/* 3D prototype page: a scroll-driven sticky stage holding the WebGL box and its text overlays */
.stage3d{position:relative;height:230svh}
.stage-sticky{position:sticky;top:var(--header-height);height:calc(100svh - var(--header-height));overflow:hidden}
.canvas-host{position:absolute;inset:0;opacity:0;transition:opacity .7s var(--ease)}
.canvas-host.is-ready{opacity:1}
.canvas-host canvas{display:block}

.intro3d{position:absolute;left:0;right:0;top:clamp(20px,6vh,72px);z-index:2;padding:0 20px;text-align:center;pointer-events:none}
.intro3d h1{font-family:var(--serif);font-weight:400;font-size:clamp(40px,5.4vw,78px);line-height:1.04;letter-spacing:-1.6px;margin:0 0 10px;color:var(--forest)}
.intro3d h1 em{color:#6a8562}
.intro3d p{font-size:15px;color:#4f6658;margin:0}
@media (min-width:701px){.intro3d{top:clamp(36px,12vh,132px)}} /* a little lower on desktop, nearer the box */

.tap-hint{position:absolute;left:50%;z-index:3;transform:translateX(-50%);padding:6px 12px;font-size:13px;letter-spacing:.03em;color:#4a6253;border-radius:20px;transition:background .25s,visibility 0s .35s}
.tap-hint:hover{background:#ffffff80}
.tap-hint[hidden]{display:none}
.canvas-host:not(.is-ready)~.tap-hint{visibility:hidden} /* it waits for the box it points at */

/* Text that sits on the raised lid's glass */
.lid-panel{position:absolute;z-index:3;pointer-events:none;opacity:0;transition:opacity .4s var(--ease)}
.lid-panel.is-visible{opacity:1}
.lid-welcome{position:absolute;inset:0;margin:0;display:grid;place-content:center;text-align:center;white-space:nowrap;font-family:var(--serif);font-size:clamp(24px,calc(var(--panel-w) * .046),50px);line-height:1.04;color:#1d3a2f;opacity:0;transition:opacity .35s}
.lid-welcome em{color:#5f7c57}
.lid-welcome.is-visible{opacity:1;transition-delay:.25s}
.lid-welcome:not(.is-visible){transition-duration:.12s}
.project-info{position:absolute;left:9%;right:9%;top:50%;transform:translateY(-44%);text-align:center;opacity:0;transition:opacity .35s,transform .45s var(--ease);pointer-events:none}
.project-info.is-visible{opacity:1;transform:translateY(-50%);pointer-events:auto}
.project-info h2{font-family:var(--serif);font-weight:400;font-size:clamp(22px,calc(var(--panel-w) * .044),42px);line-height:1.04;letter-spacing:-.5px;margin:0 0 10px;color:var(--forest)}
.project-info p{font-size:clamp(13px,calc(var(--panel-w) * .018),16px);line-height:1.5;margin:0 0 10px;color:#2c463a}
.info-tags{font-size:12px;color:#4b633d;margin-bottom:14px}
.info-links{display:flex;flex-wrap:wrap;gap:16px}
.info-links a{font-size:13px;color:var(--forest);border-bottom:1px solid #153c3366;padding-bottom:3px}
.info-links a:hover{border-bottom-color:var(--forest)}

.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.no-webgl-message{display:none;position:absolute;left:0;right:0;top:50%;text-align:center;font-size:15px}
html.no-webgl .no-webgl-message{display:block}
html.no-webgl .tap-hint{display:none}

@media (max-width:700px){
 .stage3d{height:210svh}
 .project-info{left:8%;right:8%} /* the phone's portrait lid is tall enough to centre the text, as on wider screens */
}
@media (prefers-reduced-motion:reduce){.canvas-host,.lid-panel,.project-info,.lid-welcome{transition:none}}

/* The light source, made legible: a faint warm glow from the top left of the page */
body{background-image:radial-gradient(ellipse 65% 55% at 6% -8%,#fffbf2,transparent 62%),radial-gradient(ellipse 80% 60% at 50% 28%,#fbf9f3,transparent 70%),linear-gradient(#f5f1e8,#ede7db)}

/* Window light: one soft beam from the top left. The page is gently shaded everywhere except the beam,
   which is what makes light visible on a pale surface. Runs behind everything, so there is no seam at the header. */
.window-light{inset:0;opacity:1;filter:blur(16px);mix-blend-mode:multiply;-webkit-mask-image:none;mask-image:none;
 background:linear-gradient(58deg,rgba(118,104,80,.19) 0%,rgba(118,104,80,.17) 20%,rgba(118,104,80,0) 27%,rgba(118,104,80,0) 41%,rgba(118,104,80,.15) 49%,rgba(118,104,80,.2) 100%)}
.window-light:after{content:'';position:absolute;inset:0;mix-blend-mode:normal;opacity:1;
 background:linear-gradient(58deg,transparent 25%,rgba(255,247,228,.6) 30%,rgba(255,248,234,.5) 37%,transparent 44%);
 -webkit-mask-image:linear-gradient(155deg,#000 8%,rgba(0,0,0,.45) 55%,transparent 82%);mask-image:linear-gradient(155deg,#000 8%,rgba(0,0,0,.45) 55%,transparent 82%)}

/* Speaker toggle in the header */
.sound-toggle{display:inline-grid;place-items:center;width:34px;height:34px;margin-left:-12px;border-radius:50%;color:var(--forest);border-bottom:0!important;transition:background .2s}
.sound-toggle:hover{background:#153c3312}
.sound-toggle .mute{display:none}
.sound-toggle[aria-pressed="false"] .wave{display:none}
.sound-toggle[aria-pressed="false"] .mute{display:inline}

/* Lid text: centred title and description, with a link down to the matching exhibit */
.project-info p{max-width:34em;margin-left:auto;margin-right:auto}
.info-exhibit{display:inline-block;margin-top:4px;font-size:13px;letter-spacing:.02em;color:var(--forest);border-bottom:1px solid #153c3366;padding-bottom:3px}
.info-exhibit:hover{border-bottom-color:var(--forest)}

/* The plinth's front face: the 3D plinth's stone carried on from the bottom of the stage to the end of the page.
   scene3d.js measures the plinth and sets --plinth-left/right/top and the stone's scale; without WebGL there is no
   plinth. So the two read as one stone where they meet, the face starts at exactly the top's white and eases to a shade
   darker further down, and it shows the stone as soft as WebGL draws it: the 2048px texture shown a few hundred pixels
   wide comes from one of its mipmaps, so scene3d.js sets --stone-image to the matching copy (stone-1024/512/256.webp) */
.plinth-face{display:none}
.has-plinth .plinth-face{display:block;position:absolute;z-index:-1;top:var(--plinth-top);bottom:0;left:var(--plinth-left);right:var(--plinth-right);
 background:var(--stone-image) var(--stone-x) 0/var(--stone-tile) auto repeat,linear-gradient(#fff 40px,#fcfbfa 120px,#f9f8f6 280px);
 background-blend-mode:multiply,normal}
.has-plinth .exhibits{margin-inline:var(--plinth-left) var(--plinth-right)}
.has-plinth .site-footer{width:min(100% - var(--plinth-left) - var(--plinth-right) - 2 * var(--gutter),var(--container))}

/* Exhibit catalogue under the box */
.exhibits{padding:110px 0 96px;color:var(--forest)}

/* Each exhibit is one textured card set on the stone: the text on one side and the piece itself on the other, swapping
   sides down the page. The piece keeps its own shape, so a phone reel stands tall and a screen recording lies wide. */
.exhibit-list{position:relative;width:min(100% - 2 * var(--gutter),var(--container));margin-inline:auto}
.exhibit-frame{display:grid;gap:clamp(28px,4vw,48px)}
/* Scroll cards (after Lightswind's Scroll Cards): the collection pins in place, and each card slides up from the bottom of
   the screen over the last, which shrinks and tilts back. exhibits.js turns this on (.is-stacked) only where every card fits
   the frame, and never for reduced motion. Cards size their piece to the frame's height (cqh). */
.is-stacked .exhibit-stage{position:sticky;top:0;height:100svh;display:grid;place-items:center;padding-top:var(--header-height)}
.is-stacked .exhibit-frame{display:block;position:relative;width:100%;aspect-ratio:16/9;max-height:calc(100svh - var(--header-height) - 116px);container-type:size}
.is-stacked .exhibit{--media-h:calc(100cqh - 2 * clamp(12px,1.4vw,18px));position:absolute;inset:0;will-change:transform;box-shadow:0 25px 50px -12px #2a221540}
/* "Back to top", in the page's outline-pill style: one pinned under the pile while the cards are stacked, so it sits under
   whichever card is showing, and one under each card when they sit in a list */
.back-to-top{display:inline-flex;align-items:center;gap:10px;min-height:44px;padding:11px 22px;border-radius:30px;border:1px solid #153c3355;background:#fbfaf7b3;font-size:14px;letter-spacing:.02em;color:var(--forest);transition:background .25s,border-color .25s}
.back-to-top span{display:inline-block;transition:transform .35s var(--ease)}
.back-to-top:hover{background:#fff;border-color:var(--forest)}
.back-to-top:hover span{transform:translateY(-3px)}
.exhibit-stage>.back-to-top,.is-stacked .exhibit-frame>.back-to-top{display:none}
.exhibit-frame>.back-to-top{justify-self:center;margin-top:calc(14px - clamp(28px,4vw,48px))}
.is-stacked .exhibit-stage{grid-template-rows:auto auto;align-content:center;row-gap:clamp(14px,2.2vh,24px)}
.is-stacked .exhibit-stage>.back-to-top{display:inline-flex}
.exhibit{--media-h:max(220px,min(calc(100svh - 230px),500px));display:grid;grid-template-columns:minmax(0,1fr) min(58%,calc(var(--media-h) * var(--ratio)));align-items:center;gap:clamp(16px,3vw,40px);padding:clamp(12px,1.4vw,18px);border-radius:16px;background:#fff;color:#24392f;box-shadow:0 0 0 1px #2a22150a,0 1px 2px #2a22150f,0 14px 30px -16px #2a221545;scroll-margin-top:calc(var(--header-height) + 24px)}
.exhibit-art{position:relative;margin:0;order:2;border-radius:8px;overflow:hidden}
.exhibit-art video,.exhibit-art img{display:block;width:100%;height:auto;aspect-ratio:var(--ratio);object-fit:cover;border-radius:8px;background:#e9e5dc}
.exhibit-art.is-object img{object-fit:contain;padding:12%;background:linear-gradient(#f6f4ef,#ebe7de)}
.art-controls{position:absolute;right:10px;bottom:10px;display:flex;gap:8px}
.art-button{width:34px;height:34px;display:grid;place-items:center;border-radius:50%;background:#fbfaf6e0;color:var(--forest);box-shadow:0 1px 3px #1a2e2229;opacity:.72;transition:opacity .2s}
.art-button svg{width:15px;height:15px}
.art-button .when-on,.art-button.is-on .when-off{display:none}
.art-button.is-on .when-on{display:block}
.exhibit-art:hover .art-button,.art-button:focus-visible{opacity:1}

.exhibit-text{max-width:34em;padding:clamp(14px,2.6vw,36px) clamp(10px,2vw,28px)}
.label-number{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:#6b7a70;margin:0 0 14px}
.exhibit-text h3{font-family:var(--serif);font-weight:400;font-size:clamp(30px,3vw,40px);line-height:1.02;letter-spacing:-.5px;margin:0 0 14px;color:var(--forest)}
.label-summary{font-size:15.5px;line-height:1.6;margin:0}
.exhibit-text h4{font-size:10.5px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;color:#6b7a70;margin:22px 0 6px}
.label-why{font-size:14px;line-height:1.6;margin:0}
.label-partner{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;margin:20px 0 0;padding-top:14px;border-top:1px solid #24392f1f}
.label-partner span{font-size:10.5px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;color:#6b7a70}
.label-partner strong{font-size:15px;font-weight:550;color:var(--forest)}
.label-links{display:flex;flex-wrap:wrap;gap:4px 18px;margin:18px 0 0}
.label-links a{font-family:"Nothing You Could Do",var(--hand);font-size:21px;line-height:1.5;color:var(--forest);border-bottom:1px solid #153c3359;transition:color .2s,border-color .2s}
.label-links a:hover{color:#5f7c57;border-bottom-color:currentColor}

@media(min-width:801px){
 .exhibit:nth-child(even){grid-template-columns:min(58%,calc(var(--media-h) * var(--ratio))) minmax(0,1fr)}
 .exhibit:nth-child(even) .exhibit-art{order:0}
}
@media(max-width:800px){.exhibit{--media-h:max(160px,min(calc(100svh - 480px),340px));grid-template-columns:1fr;gap:4px}.exhibit-art{order:0;justify-self:center;width:min(100%,calc(var(--media-h) * var(--ratio)))}}
@media(max-width:800px){.is-stacked .exhibit-frame{aspect-ratio:auto;height:calc(100svh - var(--header-height) - 104px);max-height:none}.is-stacked .exhibit{--media-h:max(140px,calc(100cqh - 360px));align-content:center}}
@media (prefers-reduced-motion:reduce){.label-links a,.art-button{transition:none}}

/* One container, as in the AI Playbook: the header, each page's content and the footer share one width, centered and
   never wider than --container, so the wordmark, the content and the footer keep one left edge however wide the screen
   is. On the homepage the box and its stone still run the full width; only what sits on them keeps to the container */
:root{--gutter:4.5%;--container:1200px}
@media (max-width:600px){:root{--gutter:5%}}
.site-header,.site-footer{width:min(100% - 2 * var(--gutter),var(--container));margin-inline:auto}

/* Current page in the header: a solid underline, where hover only shows a faint one */
.site-header nav a[aria-current="page"]{border-bottom-color:var(--forest)}

/* On phones the header links sit closer, and on the narrowest ones a little smaller, so the wordmark, After Hours,
   AI Playbook, About and the speaker share one line */
@media (max-width:600px){.site-header nav{gap:24px}.site-header nav a,.wordmark{white-space:nowrap}}
@media (max-width:440px){.site-header nav{gap:14px;font-size:13.5px}}
@media (max-width:370px){.site-header nav{gap:11px;font-size:13px}.wordmark{font-size:24px}}

/* The in-page browser (site-browser.js): a frosted browser window over the page, with traffic lights, the address in a
   pill with a padlock, "open in a new tab" and close buttons, and the project's live site below. It fills the screen
   bar a slim margin, and site-browser.js sizes and scales the site inside. Edge to edge on phones */
.site-browser{width:calc(100vw - 24px);height:calc(100dvh - 24px);max-width:none;max-height:none;padding:0;overflow:hidden;
 border:1px solid #ffffffc0;border-radius:18px;background:#eef2f7c4;-webkit-backdrop-filter:blur(26px) saturate(1.3);backdrop-filter:blur(26px) saturate(1.3);
 box-shadow:0 0 0 1px #0f1e3510,0 40px 100px -24px #0f1e3566;color:var(--forest)}
.site-browser[open]{display:grid;grid-template:auto minmax(0,1fr)/minmax(0,1fr);animation:browser-in .45s var(--ease)}
.site-browser::backdrop{background:#e8eff766;-webkit-backdrop-filter:blur(8px) saturate(1.1);backdrop-filter:blur(8px) saturate(1.1)} /* frosted, the page still light behind */
@keyframes browser-in{from{opacity:0;transform:translateY(16px) scale(.985)}}
.browser-bar{display:flex;align-items:center;gap:10px;padding:8px 8px 8px 16px}
.browser-lights{display:flex;gap:8px;margin-right:10px}
.browser-lights i{width:12px;height:12px;border-radius:50%;background:#df735b;box-shadow:inset 0 0 0 1px #0000000f}
.browser-lights i:nth-child(2){background:#e5b04f}
.browser-lights i:nth-child(3){background:#8fa78a}
.browser-address{flex:1;min-width:0;display:flex;align-items:center;gap:10px;height:34px;margin:0;padding:0 14px;border-radius:10px;background:#ffffffb8;box-shadow:inset 0 0 0 1px #0f1e350d;font-size:14px;color:#3d4c66}
.browser-address svg{flex:none;width:14px;height:14px;opacity:.65}
.browser-url{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.browser-button{flex:none;width:34px;height:34px;display:grid;place-items:center;border-radius:10px;background:#ffffffb8;box-shadow:inset 0 0 0 1px #0f1e350d;color:var(--forest);transition:background .2s}
.browser-button:hover{background:#fff}
.browser-button svg{width:18px;height:18px}
.browser-view{position:relative;margin:0 8px 8px;border-radius:11px;overflow:hidden;background:#fbfcfd;box-shadow:0 0 0 1px #0f1e3512}
.browser-view iframe{position:absolute;left:0;top:0;width:100%;height:100%;transform-origin:0 0;border:0;background:#fff;opacity:0;transition:opacity .4s}
.browser-view.is-loaded iframe{opacity:1}
.browser-loading{position:absolute;inset:0;display:grid;place-content:center;margin:0;font-family:var(--serif);font-size:22px;color:#5b6b84}
@media (max-width:700px){
 .site-browser{width:100vw;height:100dvh;border:0;border-radius:0}
 .browser-bar{gap:8px;padding:10px 8px 8px 10px}
 .browser-lights{display:none}
 .browser-address{padding:0 12px;font-size:13px}
 .browser-view{margin:0 6px 6px}
}
@media (prefers-reduced-motion:reduce){.site-browser[open]{animation:none}.browser-view iframe{transition:none}}

/* The footer: links to the privacy policy and terms */
.footer-legal{display:flex;flex-wrap:wrap;gap:2px 18px}
.footer-legal a{text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent);text-underline-offset:3px;transition:text-decoration-color .2s}
.footer-legal a:hover,.footer-legal a[aria-current="page"]{text-decoration-color:currentColor}

/* The gallery opening (opening.js). On a first visit (index.html's head sets html.is-opening) a travertine wall with the
   collection's brushed-brass nameplate stands in front of the page while the box is unpacked: the plate is engraved letter
   by letter, the count below follows the objects being built, and the wall lifts away once the box is ready. */
.opening-wall{display:none}
html.is-opening{overflow:hidden}
html.is-opening .canvas-host{transition:none} /* the box is already there when the wall lifts, not fading in behind it */
.is-opening .opening-wall{position:fixed;inset:0;z-index:40;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(22px,4vh,34px);padding:0 16px 5vh;cursor:default;
 background:radial-gradient(ellipse 34% 30% at 50% 46%,#fff8eab3,#fff8ea00),radial-gradient(ellipse 80% 70% at 18% 0,#fff,#fff0 70%),url('assets/stone.webp?v=3') 50% 0/640px auto repeat,linear-gradient(#fdfcfa,#f1eee8);
 background-blend-mode:normal,normal,multiply,normal;box-shadow:0 26px 70px #0f2c5640}
.opening-wall.is-lifting{transform:translateY(-100%);transition:transform 1.05s cubic-bezier(.7,0,.22,1)}

/* The plate, brushed side to side and darker toward its edges, held by four domed caps. Its type is sized off its own
   width (cqw), so it engraves the same at any size */
.opening-plate{position:relative;overflow:hidden;width:min(440px,80vw);aspect-ratio:5/2;container-type:inline-size;border-radius:5px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:#47330f;
 background:radial-gradient(ellipse 75% 90% at 50% 50%,#3c2a0c00 50%,#3c2a0c5e),linear-gradient(112deg,#94733a,#b08f4e 40%,#c4a463 52%,#a58444 68%,#8a6b34);
 box-shadow:inset 0 1px #f8e4ad99,inset 0 -1px #4a34107a,inset 1px 0 #f0d59a4d,inset -1px 0 #4a341040,0 1px 1px #3a2a1040,0 4px 8px -3px #3a2a1038,0 24px 44px -20px #3a2a1070}
.opening-plate::before{content:'';position:absolute;inset:0;opacity:.5;mix-blend-mode:overlay;pointer-events:none;
 background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='240'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.004 .9' numOctaves='3' seed='7'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E") 0 0/100% 100%}
.opening-plate::after{content:'';position:absolute;top:0;bottom:0;left:0;width:40%;pointer-events:none;mix-blend-mode:overlay;
 background:linear-gradient(105deg,#fff0 20%,#fff6dcd9 50%,#fff0 80%);transform:translateX(-100%);animation:plate-glint 1s cubic-bezier(.4,0,.2,1) calc(var(--glint) * 1ms) forwards paused}
.plate-caps{position:absolute;inset:2.6cqw;pointer-events:none;filter:drop-shadow(0 .3cqw .25cqw #2a1c0870);
 --cap:radial-gradient(circle at 38% 32%,#fbecc0,#c9a861 28%,#8a6a2e 60%,#5a4119 76%,#5a411900 80%);
 background:var(--cap) 0 0/3.4cqw 3.4cqw no-repeat,var(--cap) 100% 0/3.4cqw 3.4cqw no-repeat,var(--cap) 0 100%/3.4cqw 3.4cqw no-repeat,var(--cap) 100% 100%/3.4cqw 3.4cqw no-repeat}
/* Cut into the brass: a dark letter with a lit lower lip */
.opening-plate p{position:relative;margin:0;opacity:0;text-shadow:0 .16cqw 0 #ffe7ad80,0 -.1cqw 0 #2a1a0560}
.is-engraving .opening-plate p{opacity:1}
.plate-title{font-family:var(--serif);font-size:10cqw;line-height:1;letter-spacing:-.15cqw}
.opening-plate .plate-name{font-family:var(--serif);font-size:6.2cqw;line-height:1;margin-top:1.6cqw}
.plate-rule{width:7cqw;height:max(1.5px,.26cqw);margin:2.6cqw 0 2.8cqw;background:currentColor;box-shadow:0 .16cqw #ffe7ad80;transform:scaleX(0);
 animation:plate-rule .45s cubic-bezier(.3,0,.2,1) calc(var(--t) * 1ms) forwards paused}
.opening-plate .plate-meta{font-family:var(--sans);font-weight:500;font-size:3.3cqw;line-height:1;letter-spacing:.9cqw;text-transform:uppercase;margin-right:-.9cqw}
.cut{opacity:0;animation:plate-cut .32s ease-out calc(var(--t) * 1ms) forwards paused}
.is-engraving :is(.cut,.plate-rule),.is-engraving .opening-plate::after{animation-play-state:running}
@keyframes plate-cut{to{opacity:1}}
@keyframes plate-rule{to{transform:none}}
@keyframes plate-glint{to{transform:translateX(250%)}}
.opening-count{margin:0;font-size:12px;letter-spacing:.16em;text-transform:uppercase;font-variant-numeric:tabular-nums;color:var(--ink-muted,#6c7d70)}
@media (prefers-reduced-motion:reduce){
 .cut,.plate-rule{animation:none;opacity:1;transform:none}
 .opening-plate::after{display:none}
 .opening-wall.is-lifting{transform:none;opacity:0;transition:opacity .5s}
}
