:root{
  --ground:#573D4D;
  --accent:#9BDB85;
  --ink:#ffffff;      /* 9.63:1 — titles, thesis lines, before-numbers  */
  --body:#DCCFD6;     /* 6.39:1 — running text                          */
  --mute:#C0ACB6;     /* 4.50:1 — micro labels, captions, secondary      */
  --dim:var(--body);  /* legacy alias                                   */
  --on-accent:#171216;
  --strip:#DAD4D8;
  --strip-ink:#171216;
  --hair:rgba(255,255,255,.17);
  --scale:1;
  --gap:150px;
  --grain:.45;
  --speed:.85s;
  --rail:64px;
  --pad:clamp(22px,4.4vw,72px);
  --mono:'JetBrains Mono',ui-monospace,Menlo,monospace;
  --sans:'Archivo',Helvetica,Arial,sans-serif;
  --micro:var(--mono);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;background:var(--ground);color:var(--ink);
  font-family:var(--sans);font-weight:400;
  -webkit-font-smoothing:antialiased;
  /* clip, not hidden — `hidden` would make body a scroll container and kill position:sticky */
  overflow-x:clip;
}
img{max-width:100%;display:block;-webkit-user-drag:none;user-drag:none}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* ── grain ── */
#grain{position:fixed;inset:0;z-index:60;pointer-events:none;
       background-image:var(--grainimg);background-size:170px 170px;
       opacity:var(--grain);mix-blend-mode:overlay}

/* ── left rail ── */
#rail{position:fixed;left:0;top:0;bottom:0;width:var(--rail);z-index:50;
      border-right:1px solid var(--hair);background:var(--ground);
      display:flex;flex-direction:column;align-items:center;justify-content:space-between;
      padding:22px 0;font-family:var(--micro);font-size:10px;letter-spacing:.16em;color:var(--mute)}
#rail .vert{writing-mode:vertical-rl;text-orientation:mixed;white-space:nowrap}
#rail .nm{writing-mode:vertical-rl;color:var(--ink);letter-spacing:.26em;font-weight:500}
body[data-rail="off"] #rail{display:none}

/* ── top-right menu ── */
/* ── the menu ───────────────────────────────────────────────────────
   One pane of glass. Closed it is a circle with a white hamburger in the
   corner; pressing it stretches the same pane into a full-height drawer.
   Width/height/top/right all animate, so the glass never cross-fades —
   it grows out of the corner and pins itself to the edge. */
#menu{position:fixed;top:16px;right:16px;z-index:56;
      width:56px;height:56px;border-radius:28px;overflow:hidden;
      background:rgba(0,0,0,.23);
      -webkit-backdrop-filter:blur(17px) saturate(90%);
      backdrop-filter:blur(17px) saturate(90%);
      transition:width .58s cubic-bezier(.22,1.28,.36,1),
                 height .58s cubic-bezier(.22,1.28,.36,1),
                 top .58s cubic-bezier(.22,1.28,.36,1),
                 right .58s cubic-bezier(.22,1.28,.36,1),
                 border-radius .5s cubic-bezier(.22,1.28,.36,1);
      will-change:width,height}
/* flush to the top-right corner when open, so 100dvh really is the screen */
#menu.open{top:0;right:0;width:min(320px,100vw);height:100vh;height:100dvh;
           border-radius:50px 0 0 50px}

#menubtn{position:absolute;top:0;right:0;z-index:2;width:56px;height:56px;padding:0;
         display:grid;place-items:center;background:none;border:0;cursor:pointer}
#menubtn .bars{position:relative;display:block;width:20px;height:11px}
#menubtn .bars i{position:absolute;left:0;width:20px;height:1.5px;border-radius:2px;
                 background:#fff;
                 transition:transform .42s cubic-bezier(.22,1.28,.36,1)}
#menubtn .bars i:nth-child(1){top:0}
#menubtn .bars i:nth-child(2){top:9.5px}
#menu.open #menubtn .bars i:nth-child(1){transform:translateY(4.75px) rotate(45deg)}
#menu.open #menubtn .bars i:nth-child(2){transform:translateY(-4.75px) rotate(-45deg)}

#menulist{position:absolute;left:0;right:0;top:54px;z-index:1;
          display:flex;flex-direction:column;padding:0 clamp(26px,3.4vw,44px) 20px;
          font-family:var(--sans);font-size:1.8rem;font-weight:600;
          letter-spacing:-.09em;line-height:1.14;
          visibility:hidden;transition:visibility 0s .45s}
#menu.open #menulist{visibility:visible;transition:visibility 0s}
#menulist a{display:block;padding:.46em 0;color:rgba(255,255,255,.74);
            border-bottom:1px solid rgba(255,255,255,.10);
            opacity:0;transform:translateY(10px);
            transition:opacity .4s, transform .5s cubic-bezier(.22,1.15,.36,1), color .2s}
#menulist a:last-child{border-bottom:0}
#menulist a:hover{color:#fff}
#menulist a.on{color:#fff}
#menulist a.on::after{content:"";display:inline-block;width:7px;height:7px;border-radius:4px;
                      background:var(--accent);margin-left:12px;vertical-align:middle}
#menu.open #menulist a{opacity:1;transform:none}
#menu.open #menulist a:nth-child(1){transition-delay:.13s}
#menu.open #menulist a:nth-child(2){transition-delay:.19s}
#menu.open #menulist a:nth-child(3){transition-delay:.25s}
#menu.open #menulist a:nth-child(4){transition-delay:.31s}

@media (max-width:760px){
  #menu{top:12px;right:12px;width:48px;height:48px;border-radius:24px}
  /* a lid that drops from the top instead of a side drawer */
  #menu.open{top:0;right:0;width:100%;height:320px;border-radius:0 0 20px 20px}
  #menubtn{width:48px;height:48px}
  #menulist{top:46px;padding:0 22px 22px;font-size:1.6rem}
}
@media (prefers-reduced-motion:reduce){
  #menu,#menulist a,#menubtn .bars i{transition:none}
}
.page{padding-left:var(--rail);transition:padding-left .3s}
body[data-rail="off"] .page{padding-left:0}
@media (max-width:760px){ #rail{display:none!important} .page{padding-left:0!important} }

.wrap{padding-left:var(--pad);padding-right:var(--pad);max-width:1240px;margin:0 auto}
section{padding-block:calc(var(--gap) * .5)}

/* ── reveal ── */
.rv{opacity:1;transform:none}
body.js .rv{opacity:0;transform:translateY(22px);
  transition:opacity var(--speed) cubic-bezier(.22,.8,.3,1), transform var(--speed) cubic-bezier(.22,.8,.3,1)}
body.js .rv.in{opacity:1;transform:none}
body.js .rv.d1{transition-delay:.07s} body.js .rv.d2{transition-delay:.14s}
body.js .rv.d3{transition-delay:.21s} body.js .rv.d4{transition-delay:.28s}
@media (prefers-reduced-motion:reduce){
  body.js .rv{opacity:1!important;transform:none!important;transition:none!important}
}

/* ── hero ── */
.hero{padding-top:clamp(70px,11vh,140px);padding-bottom:calc(var(--gap) * .42)}
.lock{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 14px}
.lock .big{font-size:calc(clamp(46px,8.6vw,104px) * var(--scale));font-weight:400;
           line-height:.98;letter-spacing:-.035em;color:var(--ink)}
.lock .sm{font-family:var(--micro);font-size:calc(13px * var(--scale));color:var(--mute);letter-spacing:.04em}
.tagline{font-size:calc(clamp(21px,2.5vw,30px) * var(--scale));font-weight:300;line-height:1.3;
         letter-spacing:-.012em;color:var(--dim);max-width:26ch;margin:34px 0 0;text-wrap:balance}
.tagline b{font-weight:500;color:var(--ink)}
/* the four disciplines are the qualifying line — out of the micro type */
.disciplines{font-size:calc(17px * var(--scale));line-height:1.55;color:var(--body);
             max-width:36ch;margin:28px 0 0}
.disciplines i{font-style:normal;color:var(--mute);padding:0 .2em}
.hero .metaline{margin-top:26px}
/* ── the hero reads like a dictionary entry: the lockup is the headword,
   everything else is the definition column beside it. Phones keep the
   plain stack. ── */
@media (min-width:880px){
  .herofix .hero{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);
                 column-gap:clamp(30px,4.2vw,68px);align-items:start}
  .herofix .hero .lock{grid-column:1;grid-row:1 / span 3;align-self:start}
  .herofix .hero .tagline,
  .herofix .hero .disciplines,
  .herofix .hero .metaline{grid-column:2;max-width:38ch}
  .herofix .hero .tagline{grid-row:1;margin-top:.35em;
                          border-left:1px solid var(--hair);padding-left:clamp(20px,2.2vw,34px)}
  .herofix .hero .disciplines{grid-row:2;padding-left:clamp(20px,2.2vw,34px)}
  .herofix .hero .metaline{grid-row:3;padding-left:clamp(20px,2.2vw,34px)}
}
.metaline{font-family:var(--micro);font-size:calc(11px * var(--scale));letter-spacing:.13em;
          text-transform:uppercase;line-height:2.1;color:var(--mute);margin:42px 0 0}

/* ── hero video ───────────────────────────────────────────────────────────
   A tall track (.herostage) with one pinned screen (.herofix) inside it.
   Scroll distance through the track = video time. Sticky, not scroll-jacking:
   the wheel is never intercepted, the screen just holds still while you pass.
   --heroscroll is how many EXTRA screens the hero holds before the page
   moves on. 0 = one screen: you scroll and the next section comes straight
   up while the word falls back and dissolves behind it. */
:root{ --heroscroll:0 }
.herostage{position:relative;margin-left:calc(var(--rail) * -1);
           width:calc(100% + var(--rail));
           /* it is a <section>, so cancel the global section padding —
              75px of it would show above the pinned screen */
           padding-block:0;
           height:calc(100vh + var(--heroscroll) * 100vh)}
@supports (height:100svh){
  .herostage{height:calc(100svh + var(--heroscroll) * 100svh)}
}
.herofix{position:sticky;top:0;height:100vh;overflow:hidden;
         padding-left:var(--rail);
         display:flex;flex-direction:column;justify-content:center}
@supports (height:100svh){ .herofix{height:100svh} }
@media (max-width:760px){
  .herostage{margin-left:0;width:100%}
  .herofix{padding-left:0}
}
.herovid{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
         z-index:0;background:var(--ground);pointer-events:none}
/* a scrim so the lockup holds up over the brightest frames */
/* the copy sits left, so the scrim darkens the left — same move as the
   case cards, where the gradient lives on the side the text crosses */
.heroveil{position:absolute;inset:0;z-index:1;pointer-events:none;
          background:linear-gradient(to right, rgba(36,23,31,.72), rgba(36,23,31,.44) 34%,
                     rgba(36,23,31,.14) 64%, rgba(36,23,31,.04))}
@media (max-width:880px){
  .heroveil{background:linear-gradient(to top, rgba(36,23,31,.70), rgba(36,23,31,.40) 55%,
            rgba(36,23,31,.16))}
}
.herofix .hero{position:relative;z-index:2;width:100%;padding-top:0;padding-bottom:0;
               animation:heroin .7s cubic-bezier(.22,.8,.3,1) both}
/* pure CSS, no JS dependency — the first screen is never blank */
@keyframes heroin{from{opacity:0;transform:translate3d(0,14px,0)} to{opacity:1;transform:none}}
.scrollcue{position:absolute;left:50%;bottom:24px;z-index:2;margin:0;
           transform:translateX(-50%);font-family:var(--micro);font-size:10px;
           letter-spacing:.3em;text-transform:uppercase;color:var(--mute);pointer-events:none}
.scrollcue::after{content:"";display:block;width:1px;height:26px;margin:10px auto 0;
                  background:linear-gradient(var(--mute),transparent)}
/* no video, or a browser that will not seek: fall back to a plain hero */
.herostage.novid{height:auto;margin-left:0;width:100%}
.herostage.novid .herofix{position:static;height:auto;padding-left:0;overflow:visible}
.herostage.novid .herovid,.herostage.novid .heroveil,.herostage.novid .scrollcue{display:none}
.herostage.novid .hero{animation:none;opacity:1!important;transform:none!important;
                       padding-top:clamp(70px,11vh,140px);padding-bottom:calc(var(--gap) * .42)}
@media (prefers-reduced-motion:reduce){
  .herostage{height:auto;margin-left:0;width:100%}
  .herofix{position:static;height:auto;padding-left:0;overflow:visible}
  .herovid{position:relative;height:auto;aspect-ratio:16/9}
  .heroveil{display:none}
  .herofix .hero{animation:none;opacity:1!important;transform:none!important;
            padding-top:clamp(40px,6vh,80px);padding-bottom:calc(var(--gap) * .42)}
  .scrollcue{display:none}
}

/* ── hero: the 3D word ──────────────────────────────────────────────
   Transparent canvas — the Grainient ground in #bg and the grain layer
   above it are what you see behind the letters, same as every other
   section. It sits under the lockup and never eats a click. */
.hero3d{position:fixed;inset:0;z-index:0;pointer-events:none;background:transparent}
body.no-hero3d .hero3d{display:none}
.hero3d canvas{display:block;width:100%;height:100%}
/* no WebGL, or reduced motion: the word is dropped and the hero collapses
   to the plain lockup — the same fallback the video used to take */
.herostage.novid .hero3d{display:none}
@media (prefers-reduced-motion:reduce){
  .herostage{height:auto}
  .herofix{position:relative;min-height:0}
  .hero3d{display:none}
}

/* ── client strip ── */
.striplab{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.24em;
          text-transform:uppercase;color:var(--accent);margin:0 0 20px}
/* inside the light client strip the sage reads as neon — match the logos */
.clients .striplab{color:var(--strip-ink);opacity:.82;text-align:center}
.clients{background:var(--strip);
         background:color-mix(in srgb, var(--strip) 40%, transparent);
         color:var(--strip-ink);padding:34px 0 36px;overflow:hidden}
.clients .wrap{padding-left:0;padding-right:0}
/* a seamless marquee: two identical runs, translated exactly one run's width.
   Each item carries its own right margin so the seam has no extra gap. */
.loop{position:relative;overflow:hidden;
      -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
      mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.loop-track{display:flex;align-items:center;width:max-content;
            animation:loopscroll 38s linear infinite}
.loop:hover .loop-track{animation-play-state:paused}
@keyframes loopscroll{from{transform:translate3d(0,0,0)} to{transform:translate3d(-50%,0,0)}}
@media (prefers-reduced-motion:reduce){
  .loop-track{animation:none;flex-wrap:wrap;justify-content:center;width:auto}
}


/* ── case cards ── */
/* the case card, as drawn in Figma: the headline block sits ON the image,
   and the note drops below it on the opposite side. */
.case{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));
      column-gap:clamp(14px,1.8vw,26px);row-gap:clamp(24px,3vw,40px);align-items:center}
.case .eyebrow{grid-column:1/-1;grid-row:1;margin:0}
.case .media{grid-column:1 / span 7;grid-row:2}
.case .lead {grid-column:6 / span 7;grid-row:2;z-index:2;position:relative}
.case.flip .eyebrow{text-align:right}
.case.flip .media{grid-column:6 / span 7}
.case.flip .lead {grid-column:1 / span 7;text-align:right}
.case.flip .note{margin-left:auto}   /* the block itself, not just the text */
/* a soft scrim so the headline reads over a light frame as well as a dark one */
/* The scrim lives on the photo, not behind the text: a gradient inside the image
   fades out within the frame, so its outer edge is the image's own edge and there
   is no floating rectangle. It darkens the side the headline actually crosses:
   the text column starts inside the frame's right edge on a standard card, and
   inside its left edge on a flipped one. */
.case .media .px{position:relative}
.case .media .px::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to left, rgba(22,14,19,.80), rgba(22,14,19,.52) 20%,
                             rgba(22,14,19,.18) 38%, rgba(22,14,19,0) 54%)}
.case.flip .media .px::after{
  background:linear-gradient(to right, rgba(22,14,19,.80), rgba(22,14,19,.52) 20%,
                             rgba(22,14,19,.18) 38%, rgba(22,14,19,0) 54%)}
@media (max-width:880px){ .case .media .px::after{display:none} }
/* portrait on desktop, landscape on a phone — the source files are one of each,
   so each one names the crop centre it needs in the frame it doesn't already fit */
.case .media img{width:100%;display:block;aspect-ratio:4/5;object-fit:cover}
.case .media img.h-milky{object-position:54% center}   /* keeps the card and the scoop */
@media (max-width:880px){
  .case .media img{aspect-ratio:4/3}
  .case .media img.h-milky{object-position:center}
  .case .media img.h-oros{object-position:center 55%}  /* keeps the hem, drops ceiling */
}
/* the client wordmark above the headline — same CSS-mask trick as the
   client bar, so it takes --ink whatever colour the source PNG is */
.caselogo{display:block;background-color:var(--ink);opacity:.92;margin:0 0 20px;
          -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
          -webkit-mask-position:left center;mask-position:left center;
          -webkit-mask-size:contain;mask-size:contain}
.case.flip .caselogo{margin-left:auto;
          -webkit-mask-position:right center;mask-position:right center}
@media (max-width:880px){ .case.flip .caselogo{margin-left:0;
          -webkit-mask-position:left center;mask-position:left center} }
@media (max-width:880px){
  .case{grid-template-columns:minmax(0,1fr);row-gap:26px}
  .case .eyebrow,.case .media,.case .lead,
  .case.flip .eyebrow,.case.flip .media,.case.flip .lead{
    grid-column:1/-1;grid-row:auto;text-align:left}
  .case.flip .note{margin-left:0}
  .case .lead::before{display:none}
}

/* parallax: JS writes --y, CSS composes it so the reveal transform never fights it */
.px{transform:translate3d(0,var(--y,0px),0);will-change:transform}
@media (prefers-reduced-motion:reduce){ .px{transform:none} }
.eyebrow{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.34em;
         text-transform:uppercase;color:var(--accent);font-weight:500;margin:0 0 20px}
.case h2{font-size:calc(clamp(28px,3.7vw,48px) * var(--scale));font-weight:300;line-height:1.1;
         letter-spacing:-.026em;color:var(--ink);margin:0 0 26px;text-wrap:balance}
.statlist{font-family:var(--micro);font-size:calc(13px * var(--scale));line-height:2.1;
          color:var(--body);font-variant-numeric:tabular-nums;margin:0 0 24px}
.statlist b{font-weight:500;color:var(--accent)}
.statlist .was{color:var(--mute)} .statlist .ar{color:var(--mute);padding:0 .4em}
.case p.note{font-size:calc(16px * var(--scale));line-height:1.62;color:var(--body);
             max-width:40ch;margin:0 0 30px}
.chip{display:inline-flex;align-items:center;gap:10px;background:var(--accent);color:var(--on-accent);
      font-weight:700;font-size:calc(15px * var(--scale));letter-spacing:.01em;padding:13px 24px;
      will-change:transform;transition:transform .18s ease}
.adgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}
.adgrid img{aspect-ratio:1;object-fit:cover;width:100%}

/* ── proof band ── */
.band{border-top:1px solid var(--hair);border-bottom:1px solid var(--hair)}
.band .kicker{font-size:calc(clamp(27px,3.6vw,44px) * var(--scale));font-weight:300;line-height:1.13;
              letter-spacing:-.026em;color:var(--ink);margin:0 0 34px;max-width:20ch;text-wrap:balance}
.nums{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:28px;margin:0 0 52px}
@media (max-width:900px){ .nums{grid-template-columns:repeat(2,minmax(0,1fr));gap:26px 22px} }
@media (max-width:560px){ .nums{grid-template-columns:minmax(0,1fr);gap:22px} }
.nums .k{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.14em;
         text-transform:uppercase;color:var(--mute);margin:0 0 10px}
.nums .v{display:flex;align-items:baseline;white-space:nowrap;
         font-size:calc(clamp(20px,2.3vw,32px) * var(--scale));font-weight:300;letter-spacing:-.03em;
         font-variant-numeric:tabular-nums;line-height:1.1}
.nums .v .was{color:var(--mute)} .nums .v .ar{color:var(--mute);padding:0 .18em}
/* a chapter that reports two results rather than four reads at the same
   size as the four-up rows; the value is the result, so it takes accent */
.nums.two{grid-template-columns:repeat(2,minmax(0,1fr));max-width:740px}
.nums.three{grid-template-columns:repeat(3,minmax(0,1fr));max-width:1020px}
@media (max-width:760px){ .nums.three{grid-template-columns:minmax(0,1fr)} }
.nums.three .v{color:var(--accent)}
@media (max-width:560px){ .nums.two{grid-template-columns:minmax(0,1fr)} }
.nums.two .v{color:var(--accent)}
.band .foot{font-size:calc(16px * var(--scale));line-height:1.62;color:var(--body);max-width:52ch;margin:44px 0 0}

/* ── before / after slider ── */
.ba{position:relative;overflow:hidden;user-select:none;touch-action:pan-y;cursor:ew-resize;
    background:#2b2126;aspect-ratio:16/9}
.ba img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:top center;
        pointer-events:none;-webkit-user-drag:none;user-drag:none}
.ba .after{clip-path:inset(0 0 0 var(--sx,50%))}
.ba .bar{position:absolute;top:0;bottom:0;left:var(--sx,50%);width:2px;background:var(--accent);
         transform:translateX(-1px);pointer-events:none}
.ba .knob{position:absolute;top:50%;left:var(--sx,50%);width:46px;height:46px;border-radius:50%;
          background:var(--accent);transform:translate(-50%,-50%);pointer-events:none;
          display:flex;align-items:center;justify-content:center;gap:3px}
.ba .knob i{width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent}
.ba .knob i:first-child{border-right:6px solid var(--on-accent)}
.ba .knob i:last-child{border-left:6px solid var(--on-accent)}
.ba .tag{position:absolute;bottom:14px;font-family:var(--micro);font-size:10px;letter-spacing:.2em;
         text-transform:uppercase;padding:6px 11px;background:rgba(0,0,0,.55);color:#fff;pointer-events:none}
.ba .tag.l{left:14px} .ba .tag.r{right:14px}
.ba:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.bacap{font-family:var(--micro);font-size:10px;letter-spacing:.18em;text-transform:uppercase;
       color:var(--mute);margin:16px 0 0}

/* ── personal ── */
/* a cluster, not a grid — the pieces overlap and come forward on hover or tap */
.personal{position:relative;aspect-ratio:13/10;margin-top:calc(var(--gap) * .3)}
.personal .ph{position:absolute;margin:0;cursor:pointer;
              transition:z-index 0s .2s, filter .45s ease}
.personal .ph .px{transition:scale .55s cubic-bezier(.2,.8,.3,1), box-shadow .55s ease;
                  scale:1;display:block}
.personal .ph img{width:100%;display:block}
.personal .ph:hover,.personal .ph.on{z-index:20;transition:z-index 0s}
.personal .ph:hover .px,.personal .ph.on .px{scale:1.075;
        box-shadow:0 26px 60px -18px rgba(12,8,11,.7)}
.personal .p1{left:1%;   top:2%;  width:29%; z-index:4}
.personal .p2{left:22%;  top:38%; width:33%; z-index:6}
.personal .p3{left:36%;  top:2%;  width:32%; z-index:3}
.personal .p4{left:65%;  top:16%; width:26%; z-index:5}
.personal .p5{left:44%;  top:40%; width:28%; z-index:7}
@media (max-width:880px){
  .personal{position:static;aspect-ratio:auto;display:grid;
            grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .personal .ph{position:static;width:auto!important}
  .personal .p5{grid-column:1/-1}
}

/* ── tools ── */
.tools{display:grid;grid-template-columns:170px minmax(0,1fr);gap:clamp(18px,3vw,44px)}
@media (max-width:820px){ .tools{grid-template-columns:minmax(0,1fr)} .tools > div:first-child{display:none} }
.tools dl{display:grid;grid-template-columns:130px minmax(0,1fr);gap:14px 26px;margin:0}
.tools dt{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.16em;
          text-transform:uppercase;color:var(--mute);padding-top:4px}
.tools dd{margin:0;font-size:calc(17px * var(--scale));line-height:1.5;color:var(--body)}
.tools dd em{font-style:normal;color:var(--mute)}

/* ── contact ── */
.contact{border-top:1px solid var(--hair);
         padding-block:clamp(56px,7vw,96px) clamp(40px,5vw,64px)}
.contact h2{font-size:calc(clamp(38px,6vw,76px) * var(--scale));font-weight:300;line-height:1;
            letter-spacing:-.035em;color:var(--accent);margin:0 0 22px}
.contact .said{font-size:calc(18px * var(--scale));line-height:1.55;color:var(--body);
               max-width:40ch;margin:0 0 40px}
.links{display:flex;flex-wrap:wrap;gap:12px 14px}
.links a{font-family:var(--micro);font-size:calc(12px * var(--scale));letter-spacing:.14em;
         text-transform:uppercase;border:1px solid var(--accent);color:var(--accent);
         padding:13px 20px;transition:.2s}
.links a:hover{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.colophon{font-family:var(--micro);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
          color:var(--mute);margin:64px 0 0;display:flex;flex-wrap:wrap;gap:8px 22px}

/* ── client logos (CSS mask = one colour, whatever the source logo is) ── */
/* width/height come from --w/--h, set per logo in js/site.js, so --logo-k
   can shrink the whole row on small screens */
.marks i{display:block;flex:0 0 auto;width:calc(var(--w) * var(--logo-k, 1));
         height:calc(var(--h) * var(--logo-k, 1));
         margin-right:calc(58px * var(--logo-k, 1));background-color:var(--strip-ink);opacity:.82;
         -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
         -webkit-mask-position:center;mask-position:center;
         -webkit-mask-size:contain;mask-size:contain;transition:opacity .2s}
.marks i:hover{opacity:1}
@media (max-width:760px){ .marks i{--logo-k:.6} }

/* ── case page ── */
.crumb{display:flex;justify-content:space-between;align-items:baseline;gap:20px;
       font-family:var(--micro);font-size:11px;letter-spacing:.16em;text-transform:uppercase;
       color:var(--mute);padding-top:30px}
.crumb a:hover{color:var(--accent)}
.ctitle{padding-top:clamp(46px,7vh,90px)}
.ctitle h1{font-size:calc(clamp(34px,5.6vw,74px) * var(--scale));font-weight:300;line-height:1.06;
           letter-spacing:-.032em;color:var(--ink);margin:22px 0 0;max-width:17ch;text-wrap:balance}
/* a title over the scope list: reads as a heading without competing with the
   chapter heads further down the page */
.rolehead{font-size:calc(clamp(20px,2.1vw,27px) * var(--scale));font-weight:300;
          letter-spacing:-.022em;line-height:1.15;color:var(--ink);margin:0 0 26px}
.role{display:grid;grid-template-columns:210px minmax(0,1fr);gap:13px 30px;margin:0;
      padding-top:34px;border-top:1px solid var(--hair)}
@media (max-width:680px){ .role{grid-template-columns:minmax(0,1fr);gap:4px 0} .role dd{margin-bottom:14px} }
.role dt{font-family:var(--micro);font-size:calc(11px * var(--scale));letter-spacing:.13em;
         text-transform:uppercase;color:var(--accent);padding-top:3px}
.role dd{margin:0;font-size:calc(16px * var(--scale));line-height:1.5;color:var(--body)}
.chap{display:grid;grid-template-columns:170px minmax(0,1fr);gap:clamp(18px,3vw,44px)}
@media (max-width:820px){ .chap{grid-template-columns:minmax(0,1fr)} }
.chap .no,.vrow .no{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.26em;
          text-transform:uppercase;color:var(--accent);padding-top:9px}
/* one vertical clip standing beside the chapter it belongs to */
.vrow{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);
      gap:clamp(22px,3.4vw,56px);align-items:center;margin-top:calc(var(--gap) * .3)}
.vrow .vplay{aspect-ratio:9/16}
.vrow .no{display:block;padding-top:0;margin:0 0 16px}
.vrow h3{font-size:calc(clamp(24px,2.7vw,36px) * var(--scale));font-weight:300;line-height:1.13;
         letter-spacing:-.026em;color:var(--ink);margin:0 0 18px;text-wrap:balance}
.vrow p.copy{font-size:calc(16.5px * var(--scale));line-height:1.6;color:var(--body);margin:0}
.vrow .figs{font-family:var(--micro);font-size:calc(13px * var(--scale));line-height:2;
            color:var(--body);font-variant-numeric:tabular-nums;margin:22px 0 0}
.vrow .figs b{font-weight:500;color:var(--accent)}
@media (max-width:900px){
  .vrow{grid-template-columns:minmax(0,1fr)}
  .vrow .vplay{max-width:300px}
  .vrow .vcopy{order:-1}
}
.chap h3{font-size:calc(clamp(27px,3.6vw,44px) * var(--scale));font-weight:300;line-height:1.13;
         letter-spacing:-.026em;color:var(--ink);margin:0 0 24px;max-width:20ch;text-wrap:balance}
.chap p{font-size:calc(17.5px * var(--scale));line-height:1.6;color:var(--body);max-width:56ch;margin:0 0 18px}
.chap p.q{color:var(--mute)}
.chap .figs{font-family:var(--micro);font-size:calc(13px * var(--scale));line-height:2;
            color:var(--body);font-variant-numeric:tabular-nums;margin:24px 0 0}
.chap .figs b{font-weight:500;color:var(--accent)}
.credit{font-family:var(--micro);font-size:calc(11px * var(--scale));line-height:1.9;color:var(--mute);
        margin:20px 0 0;padding-top:16px;border-top:1px solid var(--hair);max-width:56ch}
/* a credit that only applies to the after frame: it holds its space so the
   page does not jump, and appears with it */
.bax .credit.aft{opacity:0;visibility:hidden;transition:opacity .34s ease}
.bax[data-s="1"] .credit.aft{opacity:1;visibility:visible}
/* on a reversed block the picture sits right, so its credit follows it */
@media (min-width:901px){ .credit.right{margin-left:auto;max-width:340px} }
.big-q,.chap p.big-q{font-size:calc(clamp(27px,3.7vw,47px) * var(--scale));font-weight:300;line-height:1.16;
       letter-spacing:-.028em;color:var(--ink);margin:0 0 24px;max-width:24ch;text-wrap:balance}
.line,.chap p.line{font-size:calc(clamp(24px,3.4vw,42px) * var(--scale));font-weight:300;letter-spacing:-.028em;
      line-height:1.2;margin:30px 0 0}
.line .a{color:var(--ink)} .line .b{color:var(--accent)}
.pairwrap{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px;margin:34px 0 0}
@media (max-width:760px){ .pairwrap{grid-template-columns:minmax(0,1fr)} }
.pairwrap figure{margin:0}
.pairwrap figcaption{font-family:var(--micro);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
                     margin-top:10px;color:var(--mute)}
.pairwrap .nw figcaption{color:var(--accent)}
.metatable{font-family:var(--micro);font-size:calc(12.5px * var(--scale));line-height:2.1;
           color:var(--ink);font-variant-numeric:tabular-nums;margin:28px 0 0;overflow-x:auto}
.metatable .lbl{color:var(--mute)}
.nextcase{border-top:1px solid var(--hair);display:flex;justify-content:space-between;
          align-items:flex-end;gap:24px;flex-wrap:wrap}
.nextcase .lb{font-family:var(--micro);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
              color:var(--mute);margin:0 0 10px}
/* the next case announces itself with its own wordmark and its headline,
   the same pair the home page uses for that card */
.nextcase a.nx{display:inline-block;color:var(--ink)}
.nextcase .nxlogo{margin:0 0 13px;opacity:.9;transition:background-color .2s}
.nextcase a.nx:hover .nxlogo{background-color:var(--accent)}
.nextcase .nxt{display:block;font-size:calc(17px * var(--scale));font-weight:300;
               line-height:1.35;color:var(--body);max-width:36ch;transition:color .2s}
.nextcase a.nx:hover .nxt{color:var(--accent)}
.nextcase .nxt i{font-style:normal;color:var(--mute);padding-left:.4em}
.ba.sq{aspect-ratio:1/1} .ba.tall{aspect-ratio:3/4} .ba.wide{aspect-ratio:3/2}
.route{display:none} .route.on{display:block}

/* ── results at a glance: a KPI row, bars animate in on scroll ──
   One hue, two shades: baseline recessive, result in accent. No categorical
   palette here, so identity is carried by the row label, never by colour. */
.kpi{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
     grid-template-rows:auto auto auto;                /* shared rows, so the three */
     column-gap:clamp(30px,4.4vw,76px);row-gap:46px;   /* plots line up across tiles */
     margin:0 0 clamp(40px,5vw,64px)}
.kpi .tile{display:grid;grid-row:span 3;grid-template-rows:subgrid;row-gap:0}
@media (max-width:980px){
  .kpi{grid-template-columns:minmax(0,1fr);grid-template-rows:none}
  .kpi .tile{display:block;grid-row:auto;grid-template-rows:none}
}
.kpi .k{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.15em;
        text-transform:uppercase;color:var(--mute);margin:0 0 16px}
.kpi .kval{font-size:calc(clamp(38px,5vw,64px) * var(--scale));font-weight:300;letter-spacing:-.04em;
           line-height:1.02;color:var(--accent);margin:0 0 24px;font-variant-numeric:tabular-nums;
           align-self:start}
.kpi .kval.pair{font-size:calc(clamp(24px,2.9vw,40px) * var(--scale));white-space:nowrap}
.kpi .kval.pair i{font-style:normal;color:var(--mute);padding:0 .1em}
.kpi .plot{display:grid;gap:11px}
.kpi .row{display:grid;grid-template-columns:minmax(52px,auto) minmax(0,1fr) minmax(0,auto);
          align-items:center;gap:13px}
.kpi .rl,.kpi .rn{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.1em;
                  color:var(--mute);white-space:nowrap}
.kpi .row.on .rn{color:var(--ink)}
.kpi .track{position:relative;height:10px;background:rgba(255,255,255,.085);border-radius:0 4px 4px 0}
.kpi .bar{display:block;height:100%;width:0;border-radius:0 4px 4px 0;background:var(--mute);
          transition:width 1.05s cubic-bezier(.22,.8,.3,1) var(--d,0s)}
.kpi .bar.hi{background:var(--accent)}
.kpi.in .bar{width:var(--w)}
.kpi .mlab{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.1em;
           color:var(--mute);margin:13px 0 0}
@media (prefers-reduced-motion:reduce){ .kpi .bar{transition:none} }

/* ── the closing invitation ── */
.cta{border-top:1px solid var(--hair)}
.cta h2{font-size:calc(clamp(40px,7vw,92px) * var(--scale));font-weight:300;line-height:.98;
        letter-spacing:-.04em;color:var(--ink);margin:0 0 24px}
.cta p{font-size:calc(18px * var(--scale));line-height:1.55;color:var(--body);max-width:42ch;margin:0 0 38px}

/* ── route change: a curtain sweeps up from the bottom and exits through the top ── */
#curtain{position:fixed;inset:0;z-index:90;pointer-events:none;background:var(--accent);
         transform:scaleY(0);transform-origin:bottom;
         transition:transform .44s cubic-bezier(.68,0,.28,1)}
#curtain span{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
              font-family:var(--micro);font-size:11px;letter-spacing:.34em;text-transform:uppercase;
              color:var(--on-accent);opacity:0;transition:opacity .2s}
#curtain.up{transform:scaleY(1)}
#curtain.up span{opacity:.55}
#curtain.down{transform:scaleY(0);transform-origin:top}
@media (prefers-reduced-motion:reduce){ #curtain{display:none} }

/* ── before / after, one independent state per section ── */
.bax{position:relative}

.ba2{display:grid;grid-template-columns:minmax(0,1.12fr) minmax(0,1fr);
     gap:clamp(22px,3.4vw,56px);align-items:center}
.ba2-side{max-width:520px}
.ba2.wide{grid-template-columns:minmax(0,1fr)}
/* left-aligned like every other panel, and never upscaled far past native.
   840px read too large next to the numbers under it — 70% of that. */
.ba2.wide .ba2-stage.bleed{max-width:588px}
.ba2.wide .ba2-side{display:block;margin-top:30px}
/* at 588px the stage leaves a column free, so the chapter and its copy sit
   beside it instead of above and under it; the numbers still run full width */
@media (min-width:901px){
  .ba2.wide{grid-template-columns:minmax(0,588px) minmax(0,1fr);align-items:center}
  .ba2.wide .ba2-side{margin-top:0;align-self:center}
  .ba2.wide .nums{grid-column:1/-1}
}
/* .rev swaps the two columns so the picture side alternates down the page.
   Desktop only — stacked, every block reads image-under-text regardless. */
@media (min-width:901px){
  .ba2.rev{grid-template-columns:minmax(0,1fr) minmax(0,1.12fr)}
  .ba2.wide.rev{grid-template-columns:minmax(0,1fr) minmax(0,588px)}
  .ba2.rev .ba2-stage{order:2}
  .ba2.rev .ba2-side{order:1}
  .ba2.rev .nums{order:3}
  .ba2.card.rev .ba2-stage{margin-left:auto}   /* a capped card hugs its own edge */
  .vrow.rev{grid-template-columns:minmax(0,1fr) minmax(0,300px)}
  .vrow.rev .vplay{order:2}
  .vrow.rev .vcopy{order:1}
}
/* on a phone a column that carries the heading stacks above the image,
   so the section still opens with its title */
@media (max-width:900px){
  .ba2 .ba2-side.head{order:-1;margin-top:0;margin-bottom:30px}
}
/* the section title in the narrower side column: smaller than a full-width
   chapter head, still unmistakably the title */
.ba2-side h3{font-size:calc(clamp(24px,2.7vw,36px) * var(--scale));font-weight:300;line-height:1.13;
             letter-spacing:-.026em;color:var(--ink);margin:0 0 18px;text-wrap:balance}
.ba2-side p.intro{font-size:calc(16.5px * var(--scale));line-height:1.6;color:var(--body);margin:0 0 30px}
/* a chapter that is only its label — the content sits beside the image below */
.chap.lab{margin-bottom:6px}
@media (max-width:900px){ .ba2{grid-template-columns:minmax(0,1fr)} }
.ba2-stage{position:relative;overflow:hidden;background:#2b2126;touch-action:pan-y;cursor:pointer;outline-offset:3px}
.ba2-stage img{width:100%;display:block;pointer-events:none;-webkit-user-drag:none;user-drag:none}
/* the after frame wipes in from the right instead of cross-fading */
.ba2-stage img.aft{position:absolute;inset:0;height:100%;object-fit:cover;
                   clip-path:inset(0 0 0 100%);
                   transition:clip-path .62s cubic-bezier(.65,0,.35,1)}
.bax[data-s="1"] .ba2-stage img.aft{clip-path:inset(0 0 0 0)}
.ba2-stage .edge{position:absolute;top:0;bottom:0;left:100%;width:2px;background:var(--accent);
                 pointer-events:none;opacity:0;
                 transition:left .62s cubic-bezier(.65,0,.35,1), opacity .2s ease .5s}
/* the handle: what a drag bar would look like, so the image reads as one */
.ba2-stage .edge::after{content:'';position:absolute;top:50%;left:50%;width:38px;height:38px;
                 transform:translate(-50%,-50%);border-radius:999px;
                 background-color:var(--accent);background-repeat:no-repeat;background-position:center;
                 background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='12' viewBox='0 0 19 12' fill='none' stroke='%23171216' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.5 1.8 2.7 6l3.8 4.2M12.5 1.8 16.3 6l-3.8 4.2'/%3E%3C/svg%3E");
                 box-shadow:0 3px 18px rgba(0,0,0,.45)}
.bax[data-s="1"] .ba2-stage .edge{left:0;opacity:0}
.ba2-stage.moving .edge{opacity:1;transition:left .62s cubic-bezier(.65,0,.35,1), opacity .12s ease}
/* on scroll-in the handle slides in, lets the after frame show, and leaves again */
.ba2-stage.peek .edge{animation:edgepeek 2s cubic-bezier(.5,0,.28,1) both}
.ba2-stage.peek img.aft{animation:clippeek 2s cubic-bezier(.5,0,.28,1) both}
@keyframes edgepeek{0%{left:100%;opacity:0}13%{opacity:1}
                    40%,60%{left:63%;opacity:1}90%{opacity:0}100%{left:100%;opacity:0}}
@keyframes clippeek{0%{clip-path:inset(0 0 0 100%)}
                    40%,60%{clip-path:inset(0 0 0 63%)}100%{clip-path:inset(0 0 0 100%)}}
@media (hover:hover) and (pointer:fine){
  .bax[data-s="0"] .ba2-stage:hover .edge{left:90%;opacity:.92;
                 transition:left .38s ease, opacity .18s ease}
  .bax[data-s="0"] .ba2-stage:hover img.aft{clip-path:inset(0 0 0 90%)}
}
@media (prefers-reduced-motion:reduce){
  .ba2-stage.peek .edge,.ba2-stage.peek img.aft{animation:none}
}
.ba2-stage .stamp{position:absolute;left:0;top:0;z-index:2;font-family:var(--micro);font-size:10px;
                  letter-spacing:.2em;text-transform:uppercase;padding:6px 12px;
                  background:rgba(0,0,0,.62);color:#fff;pointer-events:none;transition:.3s}
.bax[data-s="1"] .ba2-stage .stamp{background:var(--accent);color:var(--on-accent)}
@media (prefers-reduced-motion:reduce){
  .ba2-stage img.aft,.ba2-stage .edge{transition:none}
}

/* a tall screenshot card sits in a narrow column so it doesn't tower */
/* a tall card keeps the same column as every other panel; only the image is capped */
.ba2.card .ba2-stage{max-width:340px}

/* the account grid goes edge to edge on a phone — it is unreadable inset */
@media (max-width:900px){
  .ba2.card .ba2-stage{max-width:340px}
  .ba2-stage.bleed{width:100vw;margin-left:50%;transform:translateX(-50%)}
}

.ba2-figs{display:grid;margin:0 0 24px;transition:opacity .3s}
.ba2[data-figs="after"] .ba2-figs{opacity:0;visibility:hidden}
.bax[data-s="1"] .ba2[data-figs="after"] .ba2-figs{opacity:1;visibility:visible}
.ba2-figs .fg{display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr);align-items:baseline;
              gap:14px;padding:12px 0;border-bottom:1px solid var(--hair)}
.ba2-figs .k{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.15em;
             text-transform:uppercase;color:var(--mute)}
.ba2-figs .v{display:flex;align-items:baseline;justify-content:flex-end;white-space:nowrap;
             font-size:calc(clamp(20px,2.1vw,28px) * var(--scale));font-weight:300;letter-spacing:-.03em;
             font-variant-numeric:tabular-nums;line-height:1.05}

/* "0.65" in the before state, "0.65 → 4.46" in the after, the delta in accent */
.vd{display:flex;align-items:baseline;color:var(--accent)}
.vd i{font-style:normal;opacity:.6;padding:0 .34em 0 .42em;font-size:.82em}
.nums .vd i{padding:0 .3em 0 .4em}

/* problem on the before, insight on the after — the pair is the intro */
.ba2-copy.duo{display:grid}
.ba2-copy.duo > div{grid-area:1/1;transition:opacity .34s ease, transform .34s ease}
.ba2-copy.duo p{grid-area:auto;max-width:none;transition:none}
.ba2-copy.duo .ca{opacity:0;transform:translateY(10px);pointer-events:none}
.bax[data-s="1"] .ba2-copy.duo .cb{opacity:0;transform:translateY(-10px);pointer-events:none}
.bax[data-s="1"] .ba2-copy.duo .ca{opacity:1;transform:none;pointer-events:auto}
.ba2-copy.duo .lab{font-family:var(--micro);font-size:calc(11px * var(--scale));letter-spacing:.24em;
                   text-transform:uppercase;color:var(--accent);margin:0 0 18px}
.ba2-copy.duo .big{font-size:calc(clamp(21px,2.3vw,30px) * var(--scale));font-weight:300;line-height:1.18;
                   letter-spacing:-.026em;color:var(--ink);margin:0 0 18px;max-width:23ch;text-wrap:balance}
.ba2-copy.duo .sub{font-size:calc(16.5px * var(--scale));line-height:1.6;color:var(--mute);max-width:44ch}
.ba2-copy.duo .pay{font-size:calc(clamp(19px,2.1vw,27px) * var(--scale));font-weight:300;
                   letter-spacing:-.022em;line-height:1.3;margin:24px 0 0}
.ba2-copy.duo .pay .a{color:var(--ink)} .ba2-copy.duo .pay .b{color:var(--accent)}

/* the PDP pair is shown, not explained — keep it small */
.ba2-dual.compact{max-width:840px}

.ba2-copy{display:grid}
.ba2-copy p{grid-area:1/1;margin:0;font-size:calc(16px * var(--scale));line-height:1.6;
            color:var(--body);max-width:46ch;transition:opacity .34s ease, transform .34s ease}
.ba2-copy .ca{opacity:0;transform:translateY(9px)}
.bax[data-s="1"] .ba2-copy .cb{opacity:0;transform:translateY(-9px)}
.bax[data-s="1"] .ba2-copy .ca{opacity:1;transform:none}
.ba2-tag{font-family:var(--micro);font-size:calc(10px * var(--scale));letter-spacing:.2em;
         text-transform:uppercase;color:var(--mute);margin:0 0 14px}
.bax[data-s="1"] .ba2-tag{color:var(--accent)}
/* first-run coach mark — dims the first pair until you touch it */
.coach{position:absolute;inset:0;z-index:3;display:flex;align-items:center;justify-content:center;
       background:rgba(18,12,16,.55);opacity:0;visibility:hidden;pointer-events:none;
       transition:opacity .55s ease, visibility .55s}
.ba2-stage.coached .coach{opacity:1;visibility:visible}
.coach span{font-family:var(--micro);font-size:calc(11px * var(--scale));letter-spacing:.18em;
            text-transform:uppercase;color:#fff;text-align:center;line-height:1.9;
            border:1px solid rgba(255,255,255,.42);border-radius:999px;padding:13px 22px;
            background:rgba(0,0,0,.34);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.ba2-stage.coached .coach span{animation:coachfloat 2.6s ease-in-out .3s infinite}
@keyframes coachfloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
@media (prefers-reduced-motion:reduce){ .ba2-stage.coached .coach span{animation:none} }

/* desktop + mobile shown together — equal heights, widths from their own aspect */
.ba2-dual{display:grid;grid-template-columns:16fr 5fr;gap:14px;align-items:start}
.ba2-dual .dsk{aspect-ratio:4/3}
.ba2-dual .mob{aspect-ratio:5/12}
.ba2-dual .ba2-stage img{width:100%;height:100%;object-fit:cover;object-position:top center}
@media (max-width:700px){
  .ba2-dual{grid-template-columns:minmax(0,1fr);gap:18px;justify-items:center}
  .ba2-dual .ba2-stage{width:100%}
  .ba2-dual .mob{width:56%}
}
/* == about ==================================================================
   two columns: portrait (placeholder until img/portrait.jpg exists) + copy,
   then a text-only timeline. Nothing here overlaps .chap, so no specificity
   trap — but any display class used on a <p> inside .chap still needs the
   `.cls,.chap p.cls{}` double selector. */
.route[data-route="about"]{padding-top:44px}
.abt{display:grid;grid-template-columns:minmax(0,320px) minmax(0,1fr);
     gap:clamp(26px,4vw,72px);align-items:start;margin-top:calc(var(--gap) * .3)}
@media (max-width:880px){ .abt{grid-template-columns:minmax(0,1fr)} }
.portrait{position:relative;margin:0;aspect-ratio:4/5;overflow:hidden;
          background:rgba(255,255,255,.055);border:1px solid var(--hair)}
.portrait img{width:100%;height:100%;object-fit:cover}
.portrait .ph-lab{display:none}
/* drop img/portrait.jpg in and the placeholder disappears by itself */
.portrait.ph-empty .ph-lab{display:block;position:absolute;left:0;right:0;top:50%;
          transform:translateY(-50%);text-align:center;font-family:var(--micro);
          font-size:calc(10px * var(--scale));letter-spacing:.24em;text-transform:uppercase;
          color:var(--mute)}
@media (max-width:880px){ .portrait{max-width:280px} }
.abt-copy p{font-size:calc(17.5px * var(--scale));line-height:1.62;color:var(--body);
            max-width:56ch;margin:0 0 20px}
.abt-copy p.lead-p{font-size:calc(clamp(21px,2.4vw,30px) * var(--scale));font-weight:300;
            line-height:1.26;letter-spacing:-.022em;color:var(--ink);max-width:24ch;
            margin:0 0 30px;text-wrap:balance}
.abt-copy p:last-child{margin-bottom:0}

/* ── about: the same story at two lengths ────────────────────────────
   One track, a thumb that slides between two equal halves. Without JS
   both panels show, so the page still reads. .abt-copy p is (0,0,1,1),
   so the question needs p.ask — a bare .ask would lose to it. */
.abt-copy p.ask{font-size:calc(clamp(27px,3.6vw,44px) * var(--scale));font-weight:300;
        line-height:1.13;letter-spacing:-.02em;color:var(--ink);
        max-width:18ch;margin:0 0 clamp(18px,2vw,26px);text-wrap:balance}
/* equal halves, so the thumb is exactly half the track — no measuring */
.vtog{position:relative;display:inline-grid;grid-template-columns:1fr 1fr;
      width:min(100%,430px);border:1px solid var(--hair);border-radius:999px;
      padding:4px;margin:0 0 clamp(26px,3vw,38px)}
.vthumb{position:absolute;top:4px;bottom:4px;left:4px;width:calc(50% - 4px);
        background:var(--accent);border-radius:999px;
        transition:transform .44s cubic-bezier(.22,1.2,.36,1)}
.vtog[data-ver="long"] .vthumb{transform:translateX(100%)}
.vbtn{position:relative;z-index:1;font-family:var(--micro);
      font-size:calc(13px * var(--scale));letter-spacing:.05em;
      color:var(--body);background:none;border:0;border-radius:999px;
      padding:11px 10px;cursor:pointer;white-space:nowrap;
      transition:color .25s}
.vbtn:hover{color:var(--ink)}
.vbtn.on{color:var(--on-accent);font-weight:600}
.vbtn.on:hover{color:var(--on-accent)}
/* "The Director's Cut" is a long label — give it room on small phones */
@media (max-width:420px){
  .vbtn{font-size:calc(11.5px * var(--scale));letter-spacing:.02em;padding:11px 6px}
}
@media (prefers-reduced-motion:reduce){ .vthumb{transition:none} }
.ver[hidden]{display:none}
.ver{animation:verin .42s cubic-bezier(.22,.8,.3,1) both}
@keyframes verin{from{opacity:0;transform:translateY(9px)} to{opacity:1;transform:none}}
/* the short one is the one most people read — give it a little more air */
#ver-short p{font-size:calc(19.5px * var(--scale));line-height:1.55;color:var(--ink);max-width:52ch}
@media (prefers-reduced-motion:reduce){ .ver{animation:none} }
/* timeline: year rail + role, second line recessive */
.tl{margin:0;padding-top:30px;border-top:1px solid var(--hair)}
.tl .yr{display:grid;grid-template-columns:150px minmax(0,1fr);gap:8px 30px;
        align-items:baseline;padding:16px 0;border-bottom:1px solid var(--hair)}
@media (max-width:680px){ .tl .yr{grid-template-columns:minmax(0,1fr);gap:3px;padding:14px 0} }
.tl dt{font-family:var(--micro);font-size:calc(11px * var(--scale));letter-spacing:.11em;
       color:var(--accent);font-variant-numeric:tabular-nums;white-space:nowrap}
.tl dd{margin:0;font-size:calc(16.5px * var(--scale));line-height:1.45;color:var(--ink)}
.tl dd i{display:block;font-style:normal;color:var(--mute);margin-top:4px;
         font-size:calc(14px * var(--scale));line-height:1.5}
.route[data-route="oros"]{padding-top:44px}
.wrap{max-width:1240px}
.route[data-route="milky"]{padding-top:44px}
/* ad walls — the argument tested, not one hero image */
.wall{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:34px 0 0}
.wall img{aspect-ratio:1;object-fit:cover;width:100%}
.wall.vert{margin-top:14px}
.wall.vert img,.wall.vert video{aspect-ratio:9/16}
.wall video,.shots video{width:100%;display:block;object-fit:cover;background:#2b2126}
.shots video{aspect-ratio:2/1}

/* click to load — nothing downloads until you ask for it */
.vplay{position:relative;display:block;width:100%;padding:0;border:0;cursor:pointer;
       background:#2b2126;overflow:hidden;line-height:0}
.wall.vert .vplay{aspect-ratio:9/16}
.shots .vplay{aspect-ratio:2/1}
.vplay img{width:100%;height:100%;object-fit:cover;transition:transform .5s cubic-bezier(.2,.8,.3,1),
           filter .35s ease}
.vplay:hover img{transform:scale(1.03);filter:brightness(.88)}
.vplay .pb{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
           width:58px;height:58px;border-radius:50%;background:rgba(18,12,16,.55);
           -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
           border:1px solid rgba(255,255,255,.5);
           display:flex;align-items:center;justify-content:center;
           transition:background .25s ease, transform .25s ease}
.vplay:hover .pb{background:var(--accent);border-color:var(--accent);transform:translate(-50%,-50%) scale(1.06)}
.vplay .pb::after{content:"";width:0;height:0;margin-left:4px;
                  border-top:10px solid transparent;border-bottom:10px solid transparent;
                  border-left:16px solid #fff;transition:border-left-color .25s ease}
.vplay:hover .pb::after{border-left-color:var(--on-accent)}
.vplay .dur{position:absolute;right:10px;bottom:10px;font-family:var(--micro);font-size:10px;
            letter-spacing:.12em;color:#fff;background:rgba(0,0,0,.55);padding:4px 8px}

/* ── animated ground: one fullscreen fragment shader behind everything ── */
#bg{position:fixed;inset:0;z-index:0;pointer-events:none;background:var(--ground)}
#bg canvas{width:100%;height:100%;display:block}
.page{position:relative;z-index:1}
#rail{background:rgba(87,61,77,.62);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
body[data-bg="off"] #bg canvas{display:none}
/* screenshots keep their own proportions */
.shots{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;
       max-width:840px;margin:34px 0 0}
.shots img{width:100%;height:auto}
@media (max-width:820px){ .wall{grid-template-columns:repeat(2,minmax(0,1fr))}
                          .wall.vert{grid-template-columns:repeat(2,minmax(0,1fr))} }
/* panel rhythm: after a chapter header, and between stacked panels */
.chap + .bax{margin-top:calc(var(--gap) * .3)}
.chap + .nums{margin-top:calc(var(--gap) * .3)}
.bax + .bax{margin-top:calc(var(--gap) * .62)}
.sub{margin-top:calc(var(--gap) * .58)}
