@font-face{font-family:General Sans;src:url("../fonts/general-sans-400.woff2") format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:General Sans;src:url("../fonts/general-sans-500.woff2") format("woff2");font-weight:500;font-display:swap}
@font-face{font-family:General Sans;src:url("../fonts/general-sans-600.woff2") format("woff2");font-weight:600;font-display:swap}
:root{--canvas:#f4f4f0;--white:#fff;--ink:#10110f;--muted:#666862;--stone:#e7e5df;--line:rgba(16,17,15,.22)}
/* Never dvh: the dynamic viewport unit changes as a mobile toolbar collapses,
   so anything sized in it re-lays-out on every scroll. Both vh and svh are
   static. Full-screen elements use vh (large viewport) so nothing can leave a
   gap when the toolbar hides; mid-page sections use svh, where being a little
   shorter than the viewport is harmless. */
*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:72px}body{margin:0;background:var(--canvas);color:var(--ink);font-family:"General Sans",sans-serif;-webkit-font-smoothing:antialiased;overflow-x:clip}img{display:block;width:100%;object-fit:cover}a{color:inherit;text-decoration:none}button{font:inherit}.skip{position:fixed;z-index:100;left:15px;top:-60px;background:var(--ink);color:#fff;padding:12px}.skip:focus{top:15px}
.nav{position:fixed;z-index:50;top:0;left:0;right:0;height:72px;padding:0 clamp(18px,3.2vw,52px);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;color:#fff;
  /* --navOn ramps 0 to 1 once the hero has passed, so the bar sits over the film
     with nothing behind it and only earns a background afterwards */
  background:rgba(255,255,255,calc(var(--navOn,0)*.96));
  border-bottom:1px solid rgba(255,255,255,calc(.4 - var(--navOn,0)*.4));
  transition:color .35s}
/* White type over film needs something behind it: the plate's top is bright, so
   the bar read as a blank strip until a darker frame passed under it. A gradient
   scrim costs nothing, unlike a blur — measured earlier at ~50% more dropped
   frames when the clip is playing. It fades out as the white background ramps in,
   and never applies once the site has landed on light content. */
.nav:before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,rgba(12,12,10,.42),rgba(12,12,10,.10));
  opacity:calc(1 - var(--navOn,0));transition:opacity .3s}
/* A little blur as well, but only while nothing is playing under it — the flight
   is the one moment it is expensive. */
body:not(.hero-flying) .nav{backdrop-filter:blur(2px)}.nav.solid{color:var(--ink);backdrop-filter:blur(7px);border-bottom-color:var(--line)}.wordmark{font-weight:600;letter-spacing:.17em;font-size:14px}.wordmark sup{display:inline-block;vertical-align:baseline;font-size:.571em;font-weight:500;letter-spacing:.01em;margin-left:.25em;transform:translateY(-.5em)}.desktop-links{display:flex;gap:31px;font-size:11px}.desktop-links a{position:relative}.desktop-links a:after{content:"";position:absolute;left:0;right:100%;bottom:-5px;height:1px;background:currentColor;transition:.3s}.desktop-links a:hover:after{right:0}.location{justify-self:end;font-size:11px;border-bottom:1px solid currentColor;padding-bottom:4px}.menu-toggle{display:none;border:0;background:none;color:inherit;width:44px;height:44px;padding:12px}.menu-toggle span{display:block;height:1px;background:currentColor;margin:6px}.menu{position:fixed;z-index:80;inset:0;padding:70px 25px 30px;background:var(--white);display:flex;flex-direction:column;overflow:auto;transform:translateY(-101%);transition:transform .6s cubic-bezier(.16,1,.3,1)}.menu.open{transform:none}.menu-close{position:absolute;right:20px;top:18px;width:48px;height:48px;border:1px solid var(--line);background:none;font-size:30px}.menu>a{display:flex;justify-content:space-between;align-items:end;font-size:clamp(43px,12vw,75px);letter-spacing:-.06em;border-bottom:1px solid var(--line);padding:13px 0}.menu>a span{font-size:10px;letter-spacing:.1em}
.hero{position:relative;min-height:100vh;color:#fff;overflow:hidden}.hero>img{position:absolute;inset:0;height:100%;object-position:center}.hero-shade{position:absolute;inset:0;background:linear-gradient(90deg,rgba(12,12,10,.31),transparent 70%),linear-gradient(0deg,rgba(12,12,10,.28),transparent 45%)}.hero-copy{position:relative;z-index:2;min-height:100vh;padding:clamp(105px,12vh,145px) clamp(18px,3.2vw,52px) 42px;display:flex;flex-direction:column}.hero-copy>p,.section-label{margin:0;font-size:10px;font-weight:500;letter-spacing:.12em;text-transform:uppercase}.hero h1{margin:auto 0 30px;font-size:clamp(63px,11.4vw,174px);line-height:.78;letter-spacing:-.075em;font-weight:500;text-transform:uppercase}.hero h1 span{display:block;opacity:0;transform:translateY(25px)}.round-arrow{width:54px;height:54px;border:1px solid #fff;border-radius:50%;display:grid;place-items:center;font-size:20px;margin-left:auto;transition:.3s}.round-arrow:hover{background:#fff;color:var(--ink);transform:rotate(-45deg)}
.section{padding:clamp(85px,11vw,165px) clamp(18px,5vw,75px)}.manifesto{display:grid;grid-template-columns:.48fr 1.52fr;border-bottom:1px solid var(--line)}.manifesto>div{max-width:1050px}.manifesto h2,.tailored h2,.process h2,.work h2,.contact h2{font-size:clamp(49px,7.2vw,110px);line-height:.88;letter-spacing:-.06em;font-weight:500;margin:0}.manifesto p:not(.section-label){max-width:55ch;font-size:17px;line-height:1.65;margin:42px 0}.text-link{display:flex;width:max-content;gap:50px;border-bottom:1px solid;padding-bottom:7px;font-size:12px}.text-link span{transition:.3s}.text-link:hover span{transform:translateX(7px)}
/* Accordion image slider. One slice is always open, so the row's width (and on
   mobile the column's height) never changes — which is what keeps the
   scroll-driven version below stable. */
.collections{background:#fff}
.acc-head{padding:clamp(70px,10vw,120px) clamp(18px,5vw,75px) clamp(34px,4vw,52px);max-width:1240px;margin:0 auto}
.acc-head h2{margin:0;font-size:clamp(30px,4.6vw,62px);line-height:.95;letter-spacing:-.05em;font-weight:500}
.accs{display:flex;gap:3px;height:min(84svh,840px);padding:0 3px 3px}
.acc{position:relative;flex:1;overflow:clip;cursor:pointer;background:#111;
  transition:flex .75s cubic-bezier(.32,.72,0,1)}
.acc.on{flex:3.4}
.acc>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:saturate(.75);
  transition:transform .9s cubic-bezier(.16,1,.3,1)}
.acc.on>img{transform:scale(1.035)}
.acc:after{content:"";position:absolute;inset:0;
  background:linear-gradient(0deg,rgba(8,8,7,.72),rgba(8,8,7,.15) 55%,transparent 82%)}
/* collapsed: the name runs up the slice, so a narrow column stays readable */
.acc-tab{position:absolute;z-index:2;left:0;bottom:0;padding:28px 26px;color:#fff;
  display:flex;align-items:center;gap:16px;writing-mode:vertical-rl;transform:rotate(180deg);
  transition:opacity .3s}
.acc-tab b{font-size:19px;font-weight:500;letter-spacing:.01em}
.acc-tab span{font-size:11px;letter-spacing:.1em;opacity:.72}
.acc.on .acc-tab{opacity:0;pointer-events:none}
.acc-body{position:absolute;z-index:2;inset:auto 0 0;padding:32px 30px;color:#fff;
  display:grid;grid-template-columns:40px 1fr 50px;align-items:end;
  opacity:0;transform:translateY(14px);transition:opacity .45s .18s,transform .6s .18s}
.acc.on .acc-body{opacity:1;transform:none}
.acc:not(.on) .acc-body{pointer-events:none}
.acc-body>span{font-size:11px;letter-spacing:.1em;opacity:.75}
.acc-body h3{grid-column:2;margin:0;font-size:clamp(30px,3.2vw,52px);font-weight:500;letter-spacing:-.05em}
.acc-body p{grid-column:2;margin:10px 0 0;max-width:34ch;font-size:13px;line-height:1.5}
.acc-body>a,.acc-body>.acc-next{grid-column:3;grid-row:1/4;width:48px;height:48px;border:1px solid #fff;border-radius:50%;
  display:grid;place-items:center;transition:.3s;background:none;color:inherit;font:inherit;padding:0;cursor:pointer}
.acc-body>a:hover,.acc-body>.acc-next:hover{background:#fff;color:var(--ink)}
.tailored{display:grid;grid-template-columns:.4fr 1.05fr .55fr;gap:5vw}.tailored h2{grid-column:2}.tailored-copy{grid-column:3;align-self:end}.tailored-copy p{line-height:1.65;color:var(--muted);font-size:15px;margin:0 0 24px}
.image-statement{height:min(92svh,930px);position:relative;overflow:hidden;color:#fff}.image-statement>picture,.image-statement>video{position:absolute;inset:0;z-index:0}.image-statement img,.image-statement>video{display:block;width:100%;height:100%;object-fit:cover;filter:saturate(.8)}.image-statement img{transition:opacity .5s ease}.image-statement:after{content:"";position:absolute;inset:0;background:rgba(12,12,10,.12)}.image-statement>p{position:absolute;z-index:2;left:4vw;top:7%;margin:0;font-size:clamp(65px,11vw,175px);line-height:.8;letter-spacing:-.075em;font-weight:500}.image-statement>span{position:absolute;z-index:2;right:4vw;bottom:4vw;font-size:11px;text-transform:uppercase;letter-spacing:.1em}
.process{display:grid;grid-template-columns:.38fr 1.62fr}.process header{grid-column:2}.process-list{grid-column:2;margin-top:90px;border-top:1px solid var(--line)}.process-list article{min-height:145px;display:grid;grid-template-columns:70px .45fr 1fr 50px;gap:30px;align-items:center;border-bottom:1px solid var(--line);transition:background .3s}.process-list article:hover{background:#fff}.process-list article>span{font-size:10px}.process-list h3{font-size:clamp(25px,3vw,45px);font-weight:500;letter-spacing:-.04em}.process-list p{max-width:55ch;color:var(--muted);line-height:1.55;font-size:14px}.process-list i{font-style:normal;font-size:22px;transition:.3s}.process-list article:hover i{transform:translate(6px,-6px)}
.work{padding-top:clamp(90px,12vw,175px)}.work-head{padding:0 5vw 80px;display:grid;grid-template-columns:.38fr 1.62fr}.work-head h2{grid-column:2;margin-top:20px}.work-image{position:relative;height:min(78svh,800px);overflow:hidden}.work-image img{height:100%}.work-image>.work-caption{position:absolute;left:4vw;bottom:4vw;background:#fff;min-width:300px;padding:22px;display:grid}.work-image>.work-caption b{font-size:22px}.work-image>.work-caption span{font-size:10px;margin-top:8px}
.contact{min-height:90svh;display:grid;grid-template-columns:1fr 1fr;background:#fff}.contact>img,.contact-media{height:100%;min-height:700px}.contact-media{position:relative;overflow:hidden}.contact-media>img,.contact-media>video{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:cover}.contact-media>img{transition:opacity .5s ease}.contact>div{padding:clamp(70px,7vw,120px);display:flex;flex-direction:column;justify-content:center}.contact h2{margin:40px 0 70px}.solid-link{min-height:58px;padding:0 20px;background:var(--ink);color:#fff;display:flex;align-items:center;justify-content:space-between;max-width:480px;font-size:13px}.solid-link span{transition:.3s}.solid-link:hover span{transform:translate(5px,-5px)}
/* Published call-to-action and SMS consent disclosure. These sit at the point where
   a consumer sees the number, which is what 10DLC review asks for: the number people
   call, what they get back, how consent arises, and how to stop. */
.call-link{display:inline-block;margin:0 0 4px;font-size:clamp(30px,3.6vw,46px);line-height:1.1;
  letter-spacing:-.035em;font-weight:500;border-bottom:1px solid var(--line);padding-bottom:10px}
.sms-consent{margin-top:34px;padding-top:22px;border-top:1px solid var(--line);max-width:58ch}
.sms-consent h3{margin:0 0 12px;font-size:11px;font-weight:600;letter-spacing:.12em;text-transform:uppercase}
.sms-consent p{margin:0 0 12px;font-size:13px;line-height:1.65;color:var(--muted)}
.sms-consent strong{color:var(--ink);font-weight:600}
.sms-consent a{text-decoration:underline;text-underline-offset:2px}
footer p a{text-decoration:underline;text-underline-offset:2px}
footer{padding:70px 5vw 30px;display:grid;grid-template-columns:1fr 1fr 1fr;gap:50px;border-top:1px solid var(--line)}footer>div{display:grid;gap:8px;font-size:12px}footer p{margin:0;font-size:12px;line-height:1.6}footer small{grid-column:1/4;border-top:1px solid var(--line);padding-top:20px;color:var(--muted)}
.reveal{opacity:0;transform:translateY(25px);transition:opacity .8s,transform .8s cubic-bezier(.16,1,.3,1)}.reveal.in{opacity:1;transform:none}
@media(min-width:781px) and (max-width:1180px){.accs{height:min(72svh,700px)}.acc.on{flex:4.2}.acc-body{padding:26px 22px}}
@media(max-width:780px){html{scroll-padding-top:62px}.nav{height:62px;grid-template-columns:1fr auto}.desktop-links,.location{display:none}.menu-toggle{display:block}.hero-copy{padding-top:90px}.hero h1{font-size:clamp(59px,20vw,92px)}.hero>img{object-position:60% center}.manifesto,.tailored,.process{grid-template-columns:1fr}.manifesto>div,.tailored h2,.tailored-copy,.process header,.process-list{grid-column:1}.manifesto .section-label,.tailored .section-label,.process .section-label{margin-bottom:50px}.acc-head{padding:30px 20px 22px}.tailored-copy{margin-top:55px}.image-statement{height:75svh;min-height:620px}.image-statement>p{top:9%;font-size:clamp(58px,19vw,90px)}.process-list{margin-top:55px}.process-list article{grid-template-columns:40px 1fr 35px;gap:8px;padding:25px 0}.process-list h3{margin:0}.process-list p{grid-column:2}.process-list i{grid-column:3;grid-row:1/3}.work-head{grid-template-columns:1fr;padding-inline:18px}.work-head h2{grid-column:1}.work-image{height:70svh}.work-image>.work-caption{left:18px;right:18px;min-width:0}.contact{grid-template-columns:1fr}.contact>img,.contact-media{min-height:520px}.contact>div{padding:80px 20px}footer{grid-template-columns:1fr}footer small{grid-column:1}.section{padding-inline:20px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{transition:none!important;animation:none!important}.hero h1 span,.reveal{opacity:1;transform:none}}

/* ── Scroll-flight hero: pinned video into the laptop, ending on a squared,
   blank screen that the browser below is rendered onto (inset:0 registers
   exactly because the clip's final frames are pure screen). ───────────── */
.hero{min-height:0;height:190vh;overflow:visible}
.hero-pin{position:sticky;top:0;height:100vh;overflow:hidden;background:#fff}
.hero-still,.hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;will-change:transform}
.hero-video{opacity:0}
.hero .hero-shade{background:linear-gradient(90deg,rgba(12,12,10,.34),transparent 62%),linear-gradient(0deg,rgba(12,12,10,.30),transparent 42%);z-index:2;transition:opacity .4s}
.hero .hero-copy{position:absolute;inset:0;z-index:6;will-change:transform,opacity}
/* the rendered screen — a real DOM website mapped onto the laptop's screen
   quad with matrix3d, using per-frame corner data tracked from the clip. */
.screen-stage{position:absolute;inset:0;z-index:4;pointer-events:none;overflow:hidden}
.screen{position:absolute;top:0;left:0;transform-origin:0 0;
  will-change:transform;opacity:0;background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.06)}
.screen.live{opacity:1}
/* the phone plate's screen is a rounded rect; the radius lives in the stage's own
   coordinate space, so the homography scales it along with the site */
.screen.rnd{border-radius:var(--r,0);overflow:hidden}
/* fills the whole device screen in the page's colour, so the strip the
   viewport-shaped stage doesn't cover reads as the page ending, not as a gap */
.plate{position:absolute;top:0;left:0;transform-origin:0 0;opacity:0;
  background:var(--canvas);will-change:transform;transition:opacity .55s ease}
.plate.live{opacity:1}
.plate.rnd{border-radius:var(--r,0);overflow:hidden}
/* While the clip is flying, the fixed nav's backdrop blur would re-blur the whole
   viewport on every presented frame. Its background is already 95% opaque, so
   dropping the blur for those few seconds is invisible and measurably smoother. */
body.hero-flying .nav,body.hero-flying .nav.solid{backdrop-filter:none}
/* once the site has landed the mock chrome sits directly behind the bar, so the
   bar has to be fully opaque rather than the usual 95% */
/* the mock chrome used to be hidden by an opaque bar; with a transparent one it
   has to actually leave, or the fake browser bar shows through */
body.hero-landed .browser-bar,body.hero-landed .mini-nav{opacity:0;pointer-events:none;transition:opacity .45s ease}
/* A transparent bar over the mock site's canvas just looks like a light bar —
   there is nothing behind it to see. Pull the media up through the space the
   chrome occupied so the bar sits over photography instead. The chrome keeps its
   height and fades in place; only the layers beneath shift. */
/* the closing move is one compositor-driven transition, armed only at the end so
   that per-frame updates during the flight stay instant */
.screen.entering{transition:transform .9s cubic-bezier(.25,1,.5,1),clip-path .32s ease-out,opacity .5s ease,border-radius .3s ease}
.screen.rnd.entering{border-radius:0}
/* stage B: an ordinary responsive copy of the same site, laid out once at
   viewport size and never transformed. The exit crossfades A into B so the
   landing is uncropped and correctly laid out, without running layout
   during the scrub. */
.screen-b{position:absolute;inset:0;opacity:0;background:#fff;will-change:opacity;transition:opacity .55s ease}

@media(min-width:601px) and (max-width:780px){.hero-video,.hero-still{object-fit:contain;background:var(--canvas)}}
/* screen glass: a faint sheen so the DOM reads as a lit panel, not a sticker */
.screen-stage:after{content:"";position:absolute;inset:0;pointer-events:none;z-index:5;
  background:linear-gradient(107deg,rgba(255,255,255,.16) 0%,rgba(255,255,255,0) 34%,rgba(255,255,255,0) 66%,rgba(255,255,255,.07) 100%);
  opacity:var(--glassOn,0);transition:opacity .4s}
/* the site living on the screen — laid out in px against the fixed
   1400x1000 stage, so it is identical at every viewport (the homography,
   not the viewport, decides how big it appears). */
.browser{height:100%;display:flex;flex-direction:column;background:#fff;color:var(--ink);font-family:"General Sans",sans-serif}
.browser-bar{flex:none;display:flex;align-items:center;gap:9px;padding:0 20px;height:46px;background:#fff;border-bottom:1px solid rgba(16,17,15,.07)}
.browser-bar i{width:12px;height:12px;border-radius:50%;background:#dedcd5}
.browser-bar .url{margin-left:16px;background:var(--canvas);border:1px solid rgba(16,17,15,.09);border-radius:7px;padding:6px 22px;font-size:15px;letter-spacing:.02em;color:var(--muted)}
.browser-view{position:relative;flex:1;min-height:0;display:flex;flex-direction:column;background:var(--canvas)}
.mini-nav{position:absolute;top:0;left:0;right:0;z-index:3;
  display:flex;align-items:center;gap:34px;padding:0 44px;height:84px;
  background:none;border-bottom:1px solid rgba(255,255,255,.4);
  font-size:16px;color:rgba(255,255,255,.86)}
/* the same gradient the real nav uses, so white type holds over a bright sky */
.mini-nav:before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,rgba(12,12,10,.42),rgba(12,12,10,.10))}
.mini-nav b{font-size:18px;letter-spacing:.17em;color:#fff;margin-right:auto;font-weight:600}
.mini-nav b sup{display:inline-block;vertical-align:baseline;font-size:.571em;font-weight:500;letter-spacing:.01em;margin-left:.25em;transform:translateY(-.5em)}
.mini-nav em{font-style:normal;background:var(--ink);color:#fff;padding:12px 22px;font-size:14px;letter-spacing:.06em;text-transform:uppercase}
.mini-hero{position:relative;flex:1;min-height:0;overflow:hidden}
.mini-scrim{position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,rgba(12,12,10,.26),rgba(12,12,10,0) 58%)}
/* Sticky-stack: each card arrives from below, settles, then recedes behind the
   next. Opaque throughout — a translucent stacked card shows the page through
   the pile, which reads as broken rather than as depth. */
.mini-stack{position:absolute;left:0;bottom:0;z-index:2;max-width:63%}
.mini-copy{position:absolute;left:0;right:0;bottom:0;
  background:var(--canvas);padding:30px 42px 28px;display:flex;flex-direction:column;
  border-top:1px solid var(--line);border-right:1px solid var(--line);
  border-top:1px solid rgba(16,17,15,.16);box-shadow:0 -16px 34px rgba(16,17,15,.17);
  transform-origin:0 100%;will-change:transform,filter}
/* Real stacked cards. Each rises from below the panel edge as a blank opaque
   card — its copy is held back until it seats — so a half-risen card never shows
   sliced text, and because it is opaque it covers the card beneath rather than
   letting two headlines read at once. Both faults of the earlier attempts. */
.mini-copy{position:absolute;left:0;right:0;bottom:0}
.mini-stack>.mini-copy:first-child{position:relative}
/* the deck is dealt by scroll: only the first card exists until then */
.mini-stack>.mini-copy:not(:first-child){visibility:hidden}
.mini-copy>*{opacity:var(--io,1)}
/* The cue lives inside the card beside the button, so it moves, scales and is
   occluded with its own card — no measuring a floating element against a deck
   that is mid-animation. Desktop only; the phone keeps the cue above the deck. */
.mini-act{display:flex;align-items:center;justify-content:flex-end;gap:15px;margin-top:36px}
.mini-act .mini-next{margin:0}
.mini-act .mini-cue{flex:none;width:20px;height:31px;border-radius:10px;
  border:1px solid rgba(16,17,15,.3);background:none;backdrop-filter:none}
.mini-act .mini-cue i{position:absolute;left:50%;top:6px;margin-left:-1px;width:2px;height:5px;
  border-radius:1px;background:var(--ink);opacity:.55;animation:cueDropIn 1.7s ease-in-out infinite}
@keyframes cueDropIn{0%,100%{transform:translateY(0);opacity:.55}50%{transform:translateY(9px);opacity:.12}}
@media(prefers-reduced-motion:reduce){.mini-act .mini-cue i{animation:none}}
.mini-next{margin:36px 0 0 auto;display:flex;width:max-content;align-items:center;gap:11px;
  border:0;border-bottom:1px solid var(--line);background:none;padding:0 0 7px;
  color:var(--ink);font-family:inherit;font-size:15px;letter-spacing:.08em;
  text-transform:uppercase;pointer-events:none;cursor:pointer}
body.hero-landed .mini-next{pointer-events:auto}
.mini-next span{transition:transform .3s}
.mini-next:hover span{transform:translateY(3px)}
.mini-rule{display:block;height:1px;background:var(--line);margin-bottom:18px}
.mini-label{margin:0;font-size:15px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
.mini-hero h3{margin:12px 0 0;font-size:58px;line-height:.92;letter-spacing:-.055em;font-weight:500;max-width:14ch}
.mini-cta{display:flex;align-items:center;gap:24px;margin-top:44px}
.mini-cta em{font-style:normal;background:#d6c5ac;color:var(--ink);padding:16px 26px;font-size:15px;letter-spacing:.08em;text-transform:uppercase}
.mini-cta span{font-size:17px;color:var(--muted)}
.mini-hero img,.mini-hero .mini-media{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:cover;filter:saturate(.85)}
.mini-strip{flex:none;display:flex;gap:60px;padding:0 44px;height:74px;align-items:center;border-top:1px solid rgba(16,17,15,.12);font-size:15px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}


@media(prefers-reduced-motion:reduce){.hero{height:100vh}.hero-pin{position:relative}.screen{display:none}}

/* Stage A is always 1400px wide; stage B is viewport-wide. Container queries
   let the same markup lay out correctly in both, since they respond to the
   stage's own width rather than the viewport's. */
.screen{container-type:inline-size}
@container (max-width:900px){
  .mini-nav{gap:18px;padding:0 26px;height:66px;font-size:13px}
  .mini-nav b{font-size:14px}
  .mini-nav span{display:none}
  .mini-nav em{padding:9px 15px;font-size:12px}
  .mini-stack{max-width:80%}
  .mini-copy{padding:47px 26px 30px}
  .mini-rule{margin-bottom:23px}
  .mini-hero h3{font-size:40px;margin-top:10px;max-width:15ch}
  .mini-label{font-size:12px}
  .mini-cta{margin-top:24px;gap:16px}
  .mini-cta em{padding:12px 18px;font-size:12px}
  .mini-cta span{font-size:14px}
  .mini-strip{gap:26px;padding:0 26px;height:56px;font-size:12px}
}

@container (max-width:520px){
  .mini-nav b{font-size:12px}
  .mini-nav b sup{font-weight:600}
  .mini-strip{gap:14px;font-size:10.5px;letter-spacing:.06em;padding:0 20px}
  .mini-stack{max-width:90%}
  .mini-copy{padding:45px 22px 28px}
  .mini-rule{margin-bottom:22px}
  .mini-hero h3{font-size:33px}
  .mini-next{font-size:13px;margin-top:16px}
  .mini-act{margin-top:16px}
  .mini-nav{padding:0 20px}
}

/* Phone plate: the device owns the centre of the frame, so the display line
   shrinks and tucks under the dock instead of crossing it. */
@media(max-width:600px){
  .hero h1{font-size:30px;line-height:1.1;letter-spacing:-.03em;margin-bottom:18px}
  .hero h1 span{display:inline-block;margin-right:.26em}   /* no whitespace between the spans in markup */
  .hero-copy>p{font-size:9px;letter-spacing:.1em}
  .hero .hero-copy{padding-bottom:26px}
  .round-arrow{width:42px;height:42px;font-size:16px}
}

/* ── Effect A: sticky panel copy ────────────────────────────────────────
   Below the grid breakpoint the panels stack full width and each panel's copy
   pins 200px from the top, bounded by its own panel — so the label rides down
   its image and releases at the panel's edge. Pure CSS, no JS.
   Offset is min(200px,22vh) so short viewports still leave sticky travel. */
@media(max-width:767px){
  .accs{flex-direction:column;height:auto;gap:2px;padding:2px 0 0}
  .acc{flex:none;height:auto;min-height:clamp(470px,68vh,620px);padding:2em 1.5em;cursor:default;
    display:flex;align-items:flex-start;transition:none}
  .acc.on{height:auto;min-height:clamp(470px,68vh,620px)}
  .acc-tab{display:none}
  .acc-body{position:sticky;inset:auto;top:min(200px,22vh);z-index:1;
    display:flex;flex-direction:column;align-items:flex-start;width:fit-content;max-width:100%;
    padding:0 0 3em;opacity:1;transform:none;transition:none}
  .acc .acc-body{pointer-events:auto}
  .acc-body>span{font-size:11px;letter-spacing:.1em;opacity:.8}
  .acc-body h3{margin:2px 0 0;font-size:clamp(38px,11vw,54px);line-height:.92;letter-spacing:-.055em}
  .acc-body p{margin-top:14px;max-width:28ch;font-size:13px}
  .acc-body>a,.acc-body>.acc-next{position:static;margin-top:20px;width:46px;height:46px}
  .acc-body>.acc-next{display:none}
}

/* ── Effect B: scroll translation ───────────────────────────────────────
   Not sticky. The heading and the copy translate vertically at different
   speeds, and that relative difference is what reads as anchored. */
.tailored{overflow:clip}
[data-scroll-speed]{will-change:transform}
@media(prefers-reduced-motion:reduce){[data-scroll-speed]{transform:none}}

/* ── Zoom parallax ──────────────────────────────────────────────────────
   The image scrubs from 1.35 to 1 across its own pass through the viewport.
   It is driven through the `scale` property rather than `transform`, so the
   existing hover `transform: scale()` still composes on top instead of being
   overwritten — and the hover's .8s transition cannot smear the scrub, since
   the two are separate properties. */
/* Driven through `transform`, not the `scale` property: transform is the one
   every engine reliably keeps on the compositor, so re-scaling per scroll frame
   costs no repaint. `scale` is newer and not promoted everywhere, which shows up
   as flicker on touch devices during momentum scroll. */
[data-zoom]{transform:scale(1.35);transform-origin:50% 50%;will-change:transform;backface-visibility:hidden}
/* a phone shows so little of the frame that 1.35 barely reads as movement */
@media(max-width:600px){[data-zoom]{transform:scale(1.65)}}
@media(prefers-reduced-motion:reduce){[data-zoom]{transform:none}}

/* A short viewport (a phone held sideways) is not tall enough for the menu's
   full-size items. Without overflow containment they spilled past the panel,
   and translateY(-101%) only shifts the panel — so the spill stayed on screen. */
@media(max-height:540px){
  .menu{padding:54px 25px 22px}
  .menu>a{font-size:clamp(22px,7.5vh,38px);padding:9px 0}
  .menu-close{width:40px;height:40px;font-size:24px;right:16px;top:12px}
}

/* A short, wide viewport — a phone on its side — has no room to stack the mock
   hero: the copy alone takes 236px of a 262px row and the image is squeezed to
   a sliver. Put copy and image side by side instead, as the wide layout does.
   Placed after the @container tiers so it wins at equal specificity. */
@media (max-height:560px) and (min-width:601px){
  .mini-stack{max-width:70%}
  .mini-copy{padding:26px 32px 24px}
  .mini-rule{margin-bottom:13px}
  .mini-hero h3{font-size:34px;margin-top:9px;max-width:17ch}
  .mini-label{font-size:11px}
  .mini-cta{margin-top:16px;gap:14px}
  .mini-cta em{padding:9px 14px;font-size:11px}
  .mini-cta span{font-size:12px}
  .mini-strip{height:44px;font-size:11px}
  .mini-nav{height:56px}
  .browser-bar{height:38px}
}

/* The landed site fills the screen and ends on a large image, so there is
   nothing to say the page continues — readers stop, thinking it is the end.
   A cue appears once it has landed and leaves the moment they scroll. */
.scroll-cue{position:absolute;z-index:7;left:50%;bottom:14px;transform:translateX(-50%);
  display:flex;align-items:center;gap:9px;
  opacity:0;transition:opacity .5s ease;pointer-events:none}
.scroll-cue.on{opacity:1}
/* the flanking words are a mobile-only affordance; desktop keeps the bare capsule */
.cue-word{display:none;font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink);opacity:.62;white-space:nowrap}
.cue-cap{position:relative;flex:none;
  width:26px;height:40px;border:1px solid rgba(16,17,15,.32);border-radius:13px;
  background:rgba(255,255,255,.5);backdrop-filter:blur(2px)}
.cue-cap i{position:absolute;left:50%;top:8px;margin-left:-1.5px;width:3px;height:7px;
  border-radius:2px;background:var(--ink);opacity:.55;animation:cueDrop 1.7s ease-in-out infinite}
@keyframes cueDrop{0%,100%{transform:translateY(0);opacity:.55}50%{transform:translateY(13px);opacity:.12}}
@media(max-height:460px){.cue-cap{height:32px}.scroll-cue{bottom:10px}
  @keyframes cueDrop{0%,100%{transform:translateY(0)}50%{transform:translateY(8px)}}}
/* On a phone the landed card deck occupies the lower screen, so the cue sits
   above it rather than under it. --cueLift is the measured distance from the
   pin's bottom to the top of the deck; it falls back to the desktop offset. */
@media(min-width:601px){.scroll-cue{display:none}}
@media(max-width:600px){
  .mini-act .mini-cue{display:none}
  .scroll-cue{bottom:var(--cueLift,14px);gap:8px}
  .cue-word{display:block;color:#fff;opacity:.92}
  .cue-cap{width:13px;height:20px;border-radius:6.5px;border-color:rgba(255,255,255,.72);
    background:none;backdrop-filter:none}
  .cue-cap i{top:4px;margin-left:-.75px;width:1.5px;height:3.5px;border-radius:1px;background:#fff}
  @keyframes cueDrop{0%,100%{transform:translateY(0);opacity:.55}50%{transform:translateY(6.5px);opacity:.12}}
}
@media(prefers-reduced-motion:reduce){.cue-cap i{animation:none}}

/* Scroll-linked sheen on the landed copy column. Absolutely positioned so it
   never becomes a flex item, and only once the site has landed — during the
   flight it would be per-frame work inside a transformed layer for no gain. */
body.hero-landed .mini-copy:after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,
    transparent calc(var(--sweep,-25%) - 20%),
    rgba(200,159,106,.14) var(--sweep,-25%),
    transparent calc(var(--sweep,-25%) + 20%))}
@media(prefers-reduced-motion:reduce){body.hero-landed .mini-copy:after{display:none}}

/* Line-wipe headline. Each word sits in its own overflow mask; words sharing a
   line share a stagger index, so the mask travels line by line. Only once the
   site has landed — before that the headline lives inside a transformed layer
   where masking every word would be per-frame work for nothing.
   The padding/margin pair keeps descenders from being clipped by the mask. */
body.hero-landed .mini-hero h3{position:relative}
/* Once landed the panel IS the page, so its text should behave like text.
   pointer-events stays off during the flight, where it is only a decorative
   overlay riding on the video. */
body.hero-landed .screen-stage{pointer-events:auto}
body.hero-landed .screen{user-select:text;-webkit-user-select:text}
@media(prefers-reduced-motion:reduce){
  /* no sequence without motion: show the first statement and hide the rest */
  body.hero-landed .mini-hero h3 .st[data-i="0"]{opacity:1}
}

/* the drifting media is scaled slightly, so its cell has to clip */
body.hero-landed .mini-hero{overflow:hidden}
@media(prefers-reduced-motion:reduce){body.hero-landed .mini-media{transform:none}}

@media(prefers-reduced-motion:reduce){.mini-copy{transform:none;filter:none}}
