/* chennxie.com prototype v3 · Particles of a digital universe
 * One particle pool from the first frame to the last section. Materials:
 * chrome for titles, brushed metal for buttons, etched type for labels,
 * champagne gold only for figures, live states and focus.
 */

/* ---------- tokens ---------- */
:root{
  color-scheme:dark;
  --bg:#07080A; --bg-2:#0E1013; --card:#111317; --card-2:#171A1F;
  --ink:#ECEEF1; --ink-2:#A9AEB6; --ink-3:#8A9099;
  --line:rgba(236,238,241,.14); --line-2:rgba(236,238,241,.075);
  --accent:#CDB88A; --accent-soft:rgba(205,184,138,.13); --accent-ink:#0B0B0C;
  /* chrome title: Codex's metal stops, converted to plain sRGB so a browser
     without oklch()/color-mix() can never be left with transparent text */
  --chrome-hi:#F8F9FB; --chrome-mid:#B9BDC4; --chrome-lo:#8C9099;
  --chrome-shadow:#030406;
  --shadow:0 1px 0 rgba(0,0,0,.4),0 24px 60px -30px rgba(0,0,0,.8);
  --f-display:'Archivo','Helvetica Neue',Arial,sans-serif;
  --f-body:'IBM Plex Sans','Helvetica Neue',Arial,sans-serif;
  --f-mono:'DM Mono',ui-monospace,Menlo,monospace;
  --gutter:clamp(20px,4.5vw,96px);
  /* vertical rhythm: every section heading sits in a band this tall above and below,
     and every block of content carries --pad on each side of it, the way a case does */
  --band:clamp(72px,8.4vw,132px);
  --pad:clamp(40px,5.4vw,76px);
  --ease:cubic-bezier(.2,.7,.2,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
}

/* ---------- base ---------- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{background:var(--bg);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;overflow-x:hidden;scroll-behavior:smooth}
html.lenis{scroll-behavior:auto!important}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-stopped{overflow:hidden}
body{background:var(--bg);color:var(--ink);font-family:var(--f-body);font-weight:400;line-height:1.5;width:100%;max-width:100%;overflow-x:hidden}
/* clip, not hidden: hidden turns body into a scroll container and silently breaks every position:sticky */
@supports (overflow:clip){html,body{overflow-x:clip}}
::selection{background:var(--accent);color:var(--accent-ink)}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
em,i{font-style:normal}
[hidden]{display:none!important}
.wrap{width:100%;margin:0 auto;padding-inline:var(--gutter)}
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:-999px;top:12px;z-index:200;background:var(--ink);color:var(--bg);padding:10px 14px;border-radius:8px}
.skip:focus{left:16px}
:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:6px}
section{position:relative}
main{position:relative;z-index:1}

/* ---------- universe + fallbacks ---------- */
.universe{position:fixed;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;opacity:0;transition:opacity 1.2s var(--ease)}
html.gl-on .universe{opacity:1}
/* the nearest dust drifts in front of the page, as in real depth of field */
.universe-front{position:fixed;inset:0;width:100%;height:100%;z-index:20;pointer-events:none}
/* static stars: what a visitor sees when WebGL, JS or motion is unavailable */
.stars{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.55;
  background-image:
    radial-gradient(1px 1px at 12% 18%,#fff8,transparent 60%),radial-gradient(1px 1px at 72% 12%,#fff6,transparent 60%),
    radial-gradient(1.5px 1.5px at 34% 64%,#fff7,transparent 60%),radial-gradient(1px 1px at 86% 58%,#fff5,transparent 60%),
    radial-gradient(1px 1px at 55% 36%,#fff6,transparent 60%),radial-gradient(1.5px 1.5px at 8% 82%,#fff4,transparent 60%),
    radial-gradient(1px 1px at 64% 88%,#fff5,transparent 60%),radial-gradient(1px 1px at 92% 30%,#fff4,transparent 60%),
    radial-gradient(1px 1px at 24% 42%,#cdb88a66,transparent 60%),radial-gradient(1px 1px at 46% 8%,#fff5,transparent 60%);
  background-size:420px 420px;transition:opacity 1s var(--ease)}
html.gl-on .stars{opacity:0}
/* cinematic falloff at the edges: static, so it costs nothing per frame */
.vignette{position:fixed;inset:0;z-index:0;pointer-events:none;background:radial-gradient(120% 90% at 50% 45%,transparent 55%,rgba(0,0,0,.55) 100%)}
.grain{position:fixed;inset:0;z-index:30;pointer-events:none;opacity:.04;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E")}

/* ---------- materials ---------- */
/* chrome: whole-letter metal, one left-to-right reflection (Codex's treatment) */
.metal{color:var(--ink)}
@supports ((background-clip:text) or (-webkit-background-clip:text)){
  .metal{
    color:transparent;
    background-image:
      linear-gradient(105deg,transparent 40%,rgba(248,249,251,.26) 46%,rgba(248,249,251,.5) 50%,transparent 57%),
      linear-gradient(174deg,var(--chrome-hi) 0%,var(--chrome-mid) 28%,var(--chrome-hi) 44%,var(--chrome-lo) 48%,var(--chrome-hi) 53%,var(--chrome-mid) 72%,var(--chrome-hi) 100%);
    background-size:230% 100%,100% 100%;background-position:200% 0,0 0;background-repeat:no-repeat;
    -webkit-background-clip:text;background-clip:text;
    -webkit-text-stroke:.2px rgba(248,249,251,.35);
    filter:drop-shadow(0 1.5px 0 var(--chrome-shadow))}
  .metal.shine{animation:metal-reflect 2.8s var(--ease-out) 1}
}
@keyframes metal-reflect{from{background-position:200% 0,0 0}to{background-position:-100% 0,0 0}}
.metal::selection{color:var(--accent-ink);-webkit-text-fill-color:var(--accent-ink)}

/* brushed metal buttons. Nothing about the button moves under the pointer: a hover
   that lifts the box slides it out from under a pointer resting near its lower edge,
   hover drops, the box settles back, hover returns, and the button flickers. The
   hover is light instead: a lit layer between the metal and the label fades in and
   follows the pointer through --hx/--hy, and the rim and glow come up with it. */
.btn{--hx:50%;--hy:0%;position:relative;isolation:isolate;display:inline-flex;align-items:center;justify-content:center;gap:.7rem;min-height:50px;padding:.95rem 1.55rem;border-radius:999px;font-family:var(--f-mono);font-size:.74rem;letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;border:1px solid transparent;transition:box-shadow .45s var(--ease-out),filter .2s;-webkit-tap-highlight-color:transparent}
.btn::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:0;transition:opacity .45s var(--ease-out)}
.btn.solid{color:#101114;
  background:
    radial-gradient(120% 140% at 50% 0%,rgba(255,255,255,.8),transparent 46%) padding-box,
    linear-gradient(178deg,#FBFCFD 0%,#DDE0E4 30%,#C3C7CD 49%,#EEF0F3 55%,#A7ACB3 78%,#CBCFD5 100%) padding-box,
    linear-gradient(160deg,#fff,#7C828B 45%,#EDEFF2 70%,#5E636B) border-box;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95),inset 0 -2px 3px rgba(0,0,0,.26),0 10px 26px -12px rgba(0,0,0,.9)}
.btn.solid::before{background:radial-gradient(64% 150% at var(--hx) var(--hy),rgba(255,255,255,.98),rgba(255,255,255,.4) 36%,transparent 68%),linear-gradient(178deg,rgba(255,255,255,.18),transparent 50%,rgba(0,0,0,.08))}
/* the dark half of the same pair: identical geometry, tones flipped */
.btn.ghost{color:var(--ink);
  background:
    radial-gradient(120% 140% at 50% 0%,rgba(255,255,255,.16),transparent 46%) padding-box,
    linear-gradient(178deg,#24272C 0%,#171A1F 30%,#0E1013 49%,#282B31 55%,#101216 78%,#1B1E23 100%) padding-box,
    linear-gradient(160deg,#EEF0F3,#5C616A 40%,#C9CDD3 62%,#44484F) border-box;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14),inset 0 -2px 3px rgba(0,0,0,.5),0 10px 26px -14px rgba(0,0,0,.9)}
.btn.ghost::before{background:radial-gradient(64% 150% at var(--hx) var(--hy),rgba(255,255,255,.3),rgba(255,255,255,.09) 40%,transparent 72%)}
@media (hover:hover) and (pointer:fine){
  .btn:hover::before{opacity:1}
  .btn.solid:hover{box-shadow:inset 0 1px 0 #fff,inset 0 -2px 4px rgba(0,0,0,.32),0 0 0 1px rgba(255,255,255,.22),0 14px 34px -12px rgba(0,0,0,.95),0 0 30px -6px rgba(236,238,241,.42)}
  .btn.ghost:hover{box-shadow:inset 0 1px 0 rgba(255,255,255,.3),inset 0 -2px 3px rgba(0,0,0,.5),0 0 0 1px rgba(236,238,241,.16),0 14px 34px -14px rgba(0,0,0,.95),0 0 26px -8px rgba(236,238,241,.3)}
}
.btn:active{filter:brightness(.94)}
.btn .ar{display:inline-block;transition:transform .3s var(--ease-out)}
.btn:hover .ar{transform:translateY(3px)}

/* etched labels: flat, tracked, no border, so nothing that isn't a button looks like one */
.label,.tag,.case-sub,.tl-when,.tl-where,.nav-link,.pill,.nav-cv,.cgrid .k,footer{font-family:var(--f-mono);text-transform:uppercase}

/* ---------- entrance ---------- */
.intro{position:fixed;inset:0;z-index:60;display:none;place-items:center;pointer-events:auto;cursor:default}
html.intro-on .intro{display:grid}
.intro-quote{position:absolute;left:0;right:0;top:50%;transform:translateY(-58%);text-align:center;padding-inline:var(--gutter);transition:opacity .5s var(--ease)}
/* both lines are one sentence: same family, weight, size and colour */
.ql{display:block;font-family:var(--f-display);font-weight:400;font-size:clamp(1.05rem,2.3vw,2.1rem);line-height:1.34;letter-spacing:-.012em;color:var(--ink);text-wrap:balance}
.ql-2{margin-top:.42em}
.ql-v .c{color:transparent;transition:color .12s linear}
.ql-v .c.on{color:inherit;text-shadow:0 0 18px rgba(7,8,10,.95),0 0 4px rgba(7,8,10,.9)}
.intro-id{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);text-align:center;pointer-events:none}
.intro-name{display:inline-block;font-family:var(--f-display);font-weight:600;font-size:clamp(26px,5vw,72px);line-height:1.2;letter-spacing:.04em;white-space:nowrap;color:var(--ink);opacity:0}
.intro-name.gone{color:transparent}
.intro-role{margin-top:14px;font-family:var(--f-mono);font-size:.72rem;letter-spacing:.24em;text-transform:uppercase;color:var(--ink-2);opacity:0}
.intro-skip{position:absolute;right:var(--gutter);bottom:clamp(22px,4vh,40px);font-family:var(--f-mono);font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-2);padding:10px 4px;transition:color .25s}
.intro-skip:hover{color:var(--ink)}
.intro-prog{position:absolute;left:var(--gutter);bottom:clamp(36px,5.2vh,56px);width:min(160px,30vw);height:1px;background:var(--line)}
.intro-prog i{position:absolute;inset:0;background:var(--ink-2);transform:scaleX(0);transform-origin:left}
.intro.leaving{pointer-events:none}
.intro.leaving .intro-skip,.intro.leaving .intro-prog{opacity:0;transition:opacity .4s}

/* everything behind the entrance waits for it, then staggers in */
html.intro-on .nav,html.intro-on .hero-statement,html.intro-on .hero-cta-row,html.intro-on .hero .ticker{opacity:0;transform:translateY(18px)}
html.intro-on .nav{transform:none}
html.intro-on .totop,html.intro-on .progress{opacity:0}
.hero-statement,.hero-cta-row,.hero .ticker,.nav{transition:opacity 1s var(--ease),transform 1s var(--ease)}
/* the sub-line left the hero (Mark, 2026-09-18), so the buttons and the ticker take its slots */
html.revealing .hero-cta-row{transition-delay:.14s}
html.revealing .hero .ticker{transition-delay:.26s}
html.revealing .nav{transition-delay:.38s}

/* ---------- cursor (fine pointers only, created by JS) ---------- */
.cur-ring{position:fixed;top:0;left:0;z-index:100;width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;border:1px solid rgba(236,238,241,.35);pointer-events:none;opacity:0;transform:translate3d(-100px,-100px,0);transition:opacity .3s,width .3s var(--ease-out),height .3s var(--ease-out),margin .3s var(--ease-out),background-color .3s,border-color .3s;display:grid;place-items:center;will-change:transform}
html.cursor-on .cur-ring{opacity:1}
.cur-ring.hov{width:58px;height:58px;margin:-29px 0 0 -29px;border-color:rgba(205,184,138,.6);background:rgba(205,184,138,.06)}
.cur-ring.view{width:88px;height:88px;margin:-44px 0 0 -44px;border-color:transparent;background:var(--accent)}
.cur-label{font-family:var(--f-mono);font-size:.54rem;letter-spacing:.06em;text-transform:uppercase;color:var(--accent-ink);text-align:center;line-height:1.2;width:70px;opacity:0;transition:opacity .2s}
.cur-ring.view .cur-label{opacity:1}
@media (pointer:coarse){.cur-ring{display:none}}

.progress{position:fixed;top:0;left:0;right:0;height:1px;z-index:45;background:var(--accent);transform:scaleX(0);transform-origin:left;transition:opacity .6s}

/* ---------- nav ---------- */
.nav{position:fixed;top:0;left:0;right:0;z-index:40;display:flex;align-items:center;justify-content:space-between;gap:20px;padding:16px var(--gutter);border-bottom:1px solid transparent;transition:background-color .4s,border-color .4s,opacity 1s var(--ease)}
.nav.scrolled,html:not(.js) .nav{background:rgba(7,8,10,.9)}
/* frosted rather than 90% opaque: copy passing under the bar blurs out instead of showing through as faint text */
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){.nav.scrolled{background:rgba(7,8,10,.72);-webkit-backdrop-filter:blur(16px) saturate(140%);backdrop-filter:blur(16px) saturate(140%)}}
.brand{display:flex;align-items:center;gap:.7rem;font-family:var(--f-display);font-weight:600;font-size:.92rem;letter-spacing:.02em;white-space:nowrap}
.brand-mark{width:auto;height:22px;color:var(--ink);aspect-ratio:1000/588}
.nav-links{display:flex;gap:clamp(16px,2.2vw,34px);align-items:center}
.nav-link{position:relative;font-size:.68rem;letter-spacing:.16em;color:var(--ink-2);transition:color .25s;padding:6px 0}
.nav-link::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--accent);transform:scaleX(0);transform-origin:left;transition:transform .35s var(--ease-out)}
.nav-link:hover,.nav-link.active{color:var(--ink)}
.nav-link:hover::after,.nav-link.active::after{transform:scaleX(1)}
.nav-r{display:flex;align-items:center;gap:clamp(12px,1.6vw,22px)}
.nav-cv{font-size:.64rem;letter-spacing:.12em;border:1px solid var(--line);border-radius:30px;padding:.45rem .85rem;transition:background-color .3s,color .3s,border-color .3s;white-space:nowrap}
.nav-cv:hover{background:var(--ink);color:var(--bg);border-color:var(--ink)}
.pill{display:inline-flex;align-items:center;gap:.5rem;font-size:.62rem;letter-spacing:.12em;color:var(--ink-2)}
.dot{width:7px;height:7px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 0 rgba(205,184,138,.5);animation:pulse 2.4s infinite}
@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(205,184,138,.5)}70%{box-shadow:0 0 0 7px rgba(205,184,138,0)}100%{box-shadow:0 0 0 0 rgba(205,184,138,0)}}
.menu-btn{display:none;font-family:var(--f-mono);font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;padding:.45rem .2rem}
@media (max-width:900px){
  .pill .lbl{display:none}
  .menu-btn{display:inline-block}
  .nav-links{position:absolute;top:100%;left:0;right:0;flex-direction:column;align-items:stretch;gap:2px;padding:10px var(--gutter) 22px;background:rgba(7,8,10,.97);opacity:0;visibility:hidden;transform:translateY(-8px);transition:opacity .3s,transform .3s var(--ease-out),visibility .3s}
  .nav-links.open{opacity:1;visibility:visible;transform:none}
  .nav-link{font-size:.78rem;padding:13px 0}
  .nav-link::after{display:none}
  html:not(.js) .nav-links{position:static;opacity:1;visibility:visible;transform:none;flex-direction:row;flex-wrap:wrap;padding:0;background:none;border:0}
}
@media (max-width:480px){.brand span{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}

/* ---------- hero ---------- */
.hero{position:relative;min-height:100svh;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding-top:110px;padding-bottom:28px}
/* Mark, 2026-09-18: the whole group sits a little lower than dead centre. The free space in
   a centred column is split above and below, so a top margin of 2x moves the group down by x;
   --hero-drop is that x, and it shrinks with the viewport so the ticker stays on the first
   screen on a 1280x720 laptop. This is the one number to turn if he wants it lower again. */
.hero{--hero-drop:clamp(0px,4.5svh,64px)}
.hero h1{font-weight:inherit;margin:calc(var(--hero-drop) * 2) 0 0;line-height:1}
.hero-statement{display:block;font-family:var(--f-display);font-weight:500;line-height:1.1;letter-spacing:-.03em;font-size:clamp(2.45rem,9.8vw,6.8rem);text-wrap:balance;padding:.04em .06em .1em}
/* one line on desktop, as large as the width allows. 18.8 is the line's own width in ems
   for the WIDEST font in the stack (Helvetica Neue 17.77em at -.03em tracking with the webfont
   blocked, 17.89em with the .12em side padding), with a margin; Archivo itself is 16.96em.
   (Remeasured 2026-10-01 when the tracking opened up from -.052em.) */
@media (min-width:900px){.hero-statement{white-space:nowrap;font-size:min(6.8rem,calc((100vw - 2 * var(--gutter)) / 18.8))}}
.hero-cta-row{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;margin-top:clamp(28px,3.2vw,40px)}
/* both buttons the same width, so the gap between them sits on the centre line and one
   reads as the mirror of the other (Mark, 2026-09-18). The width is the wider label's own
   width, measured with the webfont blocked, rounded up. */
.hero-cta-row .btn{min-width:15.1rem}
@media (max-width:539.98px){.hero-cta-row .btn{min-width:min(15.1rem,100%)}}

.ticker{width:100%;align-self:stretch;margin-top:clamp(60px,7.6vw,112px);overflow:hidden;position:relative;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.ticker-track{display:flex;white-space:nowrap;width:max-content;animation:scrollx 46s linear infinite}
.ticker-track .ti{flex:0 0 auto;display:inline-flex;align-items:baseline;gap:.6rem;padding:14px clamp(20px,3vw,40px);border-right:1px solid var(--line-2)}
.ticker .num{font-family:var(--f-display);font-size:1.4rem;font-weight:600;letter-spacing:-.02em}
.ticker .lbl{font-family:var(--f-mono);font-size:.64rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2)}
@keyframes scrollx{to{transform:translateX(calc(-100% / 3))}}
.ticker:hover .ticker-track{animation-play-state:paused}
html.past-hero .ticker-track{animation-play-state:paused}

/* ---------- section heads ---------- */
.sec{padding-top:0}
/* the heading sits at the centre of its own band: the same air above it as below */
.sec-head{display:grid;grid-template-columns:minmax(0,1fr);row-gap:12px;align-items:baseline;padding-block:var(--band)}
.sec-title{font-family:var(--f-display);font-weight:600;font-stretch:118%;font-size:clamp(1.9rem,5.6vw,4.9rem);line-height:1;letter-spacing:-.03em;overflow:hidden;padding-bottom:.12em;margin-bottom:-.12em}
/* the words rise out of their own line box: a composited transform, not a repainted clip */
.sec-title>span{display:inline-block;transform:translate3d(0,108%,0);transition:transform 1.1s var(--ease)}
.sec-head.in .sec-title>span{transform:none}
.sec-note{color:var(--ink-2);font-size:.95rem;max-width:72ch}

/* ---------- reveal ---------- */
.rv{opacity:0;transform:translateY(28px)}
.rv.in{opacity:1;transform:none;transition:opacity 1s var(--ease),transform 1s var(--ease)}
.sec-head.rv{opacity:1;transform:none}

/* ---------- about ---------- */
.about-grid{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(28px,5vw,80px);align-items:stretch;padding-block:var(--pad)}
/* both columns run top to bottom of the same row, so their first and last lines align */
.about-copy{display:flex;flex-direction:column;justify-content:space-between;gap:1.15em}
.about-copy p{color:var(--ink-2);font-size:clamp(1rem,1.25vw,1.08rem);line-height:1.75;max-width:60ch}
.about-copy strong{color:var(--ink);font-weight:500}
.princ{display:grid;gap:12px;align-content:space-between;list-style:none}
.princ li{position:relative;border:1px solid var(--line-2);border-radius:16px;padding:clamp(20px,2.2vw,26px);background:linear-gradient(180deg,rgba(23,26,31,.92),rgba(12,13,16,.92));box-shadow:inset 0 1px 0 rgba(255,255,255,.05);transition:transform .45s var(--ease-out),border-color .3s}
.princ li:hover{transform:translateY(-3px);border-color:var(--line)}
.princ h3{font-family:var(--f-display);font-size:1.04rem;font-weight:600;margin-bottom:9px;display:flex;gap:12px;align-items:baseline;text-wrap:balance}
.princ h3 i{font-family:var(--f-mono);font-style:normal;font-size:.68rem;color:var(--accent);letter-spacing:.1em}
.princ p{font-size:.92rem;color:var(--ink-2);line-height:1.65}
@media (max-width:880px){.about-grid{grid-template-columns:1fr;gap:34px}.about-copy{gap:1.15em}}

/* ---------- cases ---------- */
.case{padding-block:var(--pad)}
.case-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.95fr);gap:clamp(26px,5vw,80px);align-items:stretch}
.case-grid>.visual{align-self:center}
.case:nth-of-type(even) .case-info{order:2}
.case-info{display:flex;flex-direction:column;justify-content:center;gap:clamp(22px,2.6vw,34px);min-width:0}
@media (max-width:880px){.case-grid{grid-template-columns:minmax(0,1fr);gap:24px}.case:nth-of-type(even) .case-info{order:0}}
/* no "｜" in this row (Mark, 2026-09-13: none after the number or between tags; the one
   inside case 01's "London ｜ 2026" went with "London" on 09-13): the spacing does the work.
   The site-wide "｜" rule still holds everywhere else, e.g. the footer line. */
.case-meta{display:flex;gap:10px clamp(22px,2.4vw,34px);align-items:center;flex-wrap:wrap}
.case-no{font-family:var(--f-mono);font-size:.72rem;color:var(--accent);letter-spacing:.12em}
.tag{font-size:.64rem;letter-spacing:.14em;color:var(--ink-2)}
.case-title{display:flex;flex-direction:column;gap:12px}
/* 3.25vw, not 3.4: "Credit-card rewards search" was 3% too wide for its column from 1024 to
   1365 px and broke off one word; this keeps every case title on one line on desktop
   (sizes above 1378 px are unchanged). On phones a title that must wrap is balanced. */
.case h3{font-family:var(--f-display);font-weight:600;font-stretch:112%;font-size:clamp(1.7rem,3.25vw,2.8rem);letter-spacing:-.03em;line-height:1.02;text-wrap:balance}
.case-sub{font-size:.72rem;letter-spacing:.24em;color:var(--ink-3)}
.case-lead{color:var(--ink-2);font-size:1rem;line-height:1.7;max-width:56ch}
.case-notes p{font-size:1rem;line-height:1.65;max-width:54ch}
/* the figures sit at the foot of the column, clear of the paragraph above */
.metrics{display:flex;flex-direction:column;gap:clamp(14px,1.8vw,20px);margin-top:auto;padding-top:clamp(10px,1.8vw,22px)}
.metric-row{display:flex;flex-wrap:wrap;justify-content:flex-start;align-items:flex-start;max-width:100%;gap:clamp(20px,2.4vw,30px) clamp(20px,2.8vw,42px)}
.metric-row>.metric{flex:0 0 auto}
.metric{display:flex;flex-direction:column;align-items:center;text-align:center}
.metric .v{font-family:var(--f-display);font-size:clamp(1.4rem,2.2vw,2.05rem);font-weight:600;letter-spacing:-.03em;line-height:1;display:flex;align-items:baseline;justify-content:center;white-space:nowrap;font-variant-numeric:tabular-nums}
.metric .v .s{color:var(--accent)}
.metric .k{font-family:var(--f-mono);font-size:.56rem;letter-spacing:.06em;line-height:1.4;text-transform:uppercase;color:var(--ink-2);margin-top:11px;text-align:center}
.metrics-note{font-size:.8rem;color:var(--ink-3);line-height:1.6;max-width:62ch}

/* clickable visual */
.visual{position:relative;display:block;width:100%;min-width:0;text-align:left;border:1px solid var(--line);border-radius:18px;overflow:hidden;background:var(--card);box-shadow:var(--shadow),inset 0 1px 0 rgba(255,255,255,.05);transform:translate3d(0,var(--py,0px),0);transition:border-color .3s,box-shadow .6s;-webkit-tap-highlight-color:transparent}
.visual.clickable:hover{border-color:rgba(205,184,138,.55);box-shadow:0 1px 0 rgba(0,0,0,.4),0 40px 80px -36px rgba(0,0,0,.95)}
.visual .frame{display:flex;align-items:center;gap:6px;padding:10px 14px;border-bottom:1px solid var(--line);background:var(--bg-2);position:relative;z-index:3}
.visual .frame i{width:10px;height:10px;border-radius:50%;background:var(--ink-3);opacity:.5}
.visual .frame .cap{margin-left:8px;font-family:var(--f-mono);font-size:.62rem;color:var(--ink-2);letter-spacing:.04em}
.visual .shot{aspect-ratio:16/11;overflow:hidden;background:var(--bg-2);position:relative}
.visual .shot picture{display:contents}
.shot img{width:100%;height:100%;object-fit:cover;object-position:top center;transition:transform 1.1s var(--ease-out)}
.visual.clickable:hover .shot img{transform:scale(1.04)}
.v-badge{position:absolute;top:12px;right:12px;z-index:4;display:inline-flex;align-items:center;gap:.4rem;font-family:var(--f-mono);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-ink);background:var(--accent);border-radius:30px;padding:.4rem .7rem}
.v-cta{position:absolute;inset:0;z-index:5;display:flex;align-items:center;justify-content:center;background:linear-gradient(0deg,rgba(7,8,10,.55),rgba(7,8,10,.2));opacity:0;transition:opacity .35s}
.visual.clickable:hover .v-cta{opacity:1}
.v-cta>span{display:inline-flex;align-items:center;gap:.55rem;font-family:var(--f-mono);font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--accent-ink);background:var(--ink);border-radius:40px;padding:.8rem 1.3rem;transform:translateY(8px);transition:transform .35s var(--ease-out)}
.visual.clickable:hover .v-cta>span{transform:none}
@media (pointer:fine){html.cursor-on .v-cta{display:none}}

/* ---------- animated case covers (production scenes, gold accent) ---------- */
.cover{aspect-ratio:16/11;display:flex;flex-direction:column;justify-content:space-between;padding:26px;position:relative;overflow:hidden;contain:layout paint;background:radial-gradient(120% 120% at 85% 0%,var(--accent-soft),transparent 60%),var(--card)}
.cover::before{content:"";position:absolute;inset:0;background-image:linear-gradient(var(--line-2) 1px,transparent 1px),linear-gradient(90deg,var(--line-2) 1px,transparent 1px);background-size:34px 34px;opacity:.7;-webkit-mask-image:radial-gradient(120% 90% at 50% 40%,#000,transparent 75%);mask-image:radial-gradient(120% 90% at 50% 40%,#000,transparent 75%)}
.cover.demo{justify-content:flex-start;gap:0;padding:clamp(16px,2vw,22px)}
.demo-head{position:relative;display:flex;align-items:center;gap:clamp(10px,1.4vw,16px);font-family:var(--f-mono);font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);padding:0 clamp(96px,11vw,124px) 10px 0;border-bottom:1px solid var(--line-2);flex:0 0 auto}
.demo-head .live{display:inline-flex;align-items:center;gap:.42rem;color:var(--ink-2)}
.demo-head .live i{width:6px;height:6px;border-radius:50%;background:var(--accent);animation:pulse 2.4s infinite}
.demo-body{position:relative;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;justify-content:center;gap:clamp(7px,1vw,11px)}
.scene{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:clamp(7px,1vw,11px);opacity:0;animation:sceneCycle 12s linear infinite}
.scene:nth-child(2){animation-delay:4s}
.scene:nth-child(3){animation-delay:8s}
@keyframes sceneCycle{0%{opacity:0}3%,29%{opacity:1}33%,100%{opacity:0}}
.row{display:flex;align-items:center;gap:.6rem;font-family:var(--f-mono);font-size:clamp(.6rem,.95vw,.72rem);letter-spacing:.03em;color:var(--ink-2);border:1px solid var(--line-2);border-radius:9px;padding:clamp(6px,.85vw,9px) clamp(8px,1.1vw,12px);background:rgba(7,8,10,.45)}
.row .lead{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}
.row .val{flex:0 0 auto;font-weight:500;color:var(--ink-2)}
.row.win{border-color:var(--accent);background:var(--accent-soft);color:var(--ink)}
.row.win .val{color:var(--accent);font-weight:600}
.row .tick{flex:0 0 auto;color:var(--accent);font-weight:700}
.demo-foot{flex:0 0 auto;display:flex;justify-content:space-between;align-items:center;gap:10px;padding-top:10px;border-top:1px solid var(--line-2);font-family:var(--f-mono);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.scan{position:relative;height:2px;border-radius:2px;background:var(--line-2);overflow:hidden}
.scan::after{content:"";position:absolute;inset:0;width:38%;border-radius:2px;background:var(--accent);animation:scanx 1.6s ease-in-out infinite}
@keyframes scanx{0%{transform:translateX(-100%)}100%{transform:translateX(300%)}}

.pickers{justify-content:flex-start;gap:clamp(12px,1.8vw,18px)}
.merchants{display:flex;flex-wrap:wrap;gap:5px;flex:0 0 auto}
.merchants .mc{font-family:var(--f-mono);font-size:clamp(.55rem,.88vw,.66rem);letter-spacing:.04em;color:var(--ink-3);border:1px solid var(--line-2);border-radius:20px;padding:.28rem .62rem;animation:mcOn 10s linear infinite}
.merchants .mc:nth-child(2){animation-delay:2s}.merchants .mc:nth-child(3){animation-delay:4s}
.merchants .mc:nth-child(4){animation-delay:6s}.merchants .mc:nth-child(5){animation-delay:8s}
@keyframes mcOn{0%{color:var(--ink-3);border-color:var(--line-2);background:transparent}2%,19%{color:var(--ink);border-color:var(--accent);background:var(--accent-soft)}21%,100%{color:var(--ink-3);border-color:var(--line-2);background:transparent}}
.picks{position:relative;flex:1 1 auto;min-height:0}
.picks .sc{justify-content:center;gap:clamp(8px,1.1vw,12px);animation:cyc5 10s linear infinite}
.picks .sc:nth-child(2){animation-delay:2s}.picks .sc:nth-child(3){animation-delay:4s}
.picks .sc:nth-child(4){animation-delay:6s}.picks .sc:nth-child(5){animation-delay:8s}
.pick{display:flex;align-items:baseline;gap:clamp(10px,1.5vw,16px);flex-wrap:wrap}
.pick .pct{font-family:var(--f-display);font-size:clamp(1.9rem,4.2vw,3rem);font-weight:600;letter-spacing:-.03em;line-height:1;color:var(--accent)}
.pick .pct.neg{color:var(--ink-3)}
.pick .pk{font-family:var(--f-mono);font-size:clamp(.66rem,1.05vw,.8rem);letter-spacing:.03em;color:var(--ink)}
.next{font-family:var(--f-mono);font-size:clamp(.55rem,.88vw,.66rem);letter-spacing:.03em;color:var(--ink-3)}

.briefs{position:relative;flex:1 1 auto;min-height:0}
.clock{flex:0 0 auto;font-family:var(--f-display);font-size:clamp(1.5rem,3.2vw,2.3rem);font-weight:600;letter-spacing:-.02em;line-height:1;display:flex;align-items:baseline;gap:.5rem}
.clock .s{color:var(--accent)}
.clock .tag{font-family:var(--f-mono);font-size:.55rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);font-weight:400}
.clock .tag::before{content:none}
.brief-kicker{font-family:var(--f-mono);font-size:.55rem;letter-spacing:.14em;text-transform:uppercase;color:var(--accent)}

.pipe{justify-content:flex-start;gap:clamp(12px,1.8vw,20px)}
.rail{position:relative;display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:4px;padding-top:14px;flex:0 0 auto}
.rail::before{content:"";position:absolute;top:5px;left:0;right:0;height:2px;border-radius:2px;background:var(--line-2)}
/* scaleX, not width: the same picture without re-laying-out the cover */
.rail-fill{position:absolute;top:5px;left:0;right:0;height:2px;border-radius:2px;background:var(--accent);transform:scaleX(.2);transform-origin:left;animation:railMove 10s linear infinite}
@keyframes railMove{0%{transform:scaleX(.2)}20%{transform:scaleX(.2)}22%{transform:scaleX(.4)}40%{transform:scaleX(.4)}42%{transform:scaleX(.6)}60%{transform:scaleX(.6)}62%{transform:scaleX(.8)}80%{transform:scaleX(.8)}82%,100%{transform:scaleX(1)}}
.rail .st{position:relative;font-family:var(--f-mono);font-size:clamp(.5rem,.8vw,.6rem);letter-spacing:.06em;text-transform:uppercase;text-align:center;color:var(--ink-3);opacity:.5;animation:stOn 10s linear infinite}
.rail .st::before{content:"";position:absolute;top:-13px;left:50%;transform:translateX(-50%);width:8px;height:8px;border-radius:50%;background:var(--bg-2);border:1.5px solid var(--line)}
.rail .st:nth-child(3){animation-delay:2s}.rail .st:nth-child(4){animation-delay:4s}
.rail .st:nth-child(5){animation-delay:6s}.rail .st:nth-child(6){animation-delay:8s}
@keyframes stOn{0%{opacity:.5;color:var(--ink-3)}2%,19%{opacity:1;color:var(--ink)}21%,100%{opacity:.5;color:var(--ink-3)}}
.rail .st:nth-child(2)::before{animation:dotOn 10s linear infinite}
.rail .st:nth-child(3)::before{animation:dotOn 10s linear infinite 2s}
.rail .st:nth-child(4)::before{animation:dotOn 10s linear infinite 4s}
.rail .st:nth-child(5)::before{animation:dotOn 10s linear infinite 6s}
.rail .st:nth-child(6)::before{animation:dotOn 10s linear infinite 8s}
@keyframes dotOn{0%{background:var(--bg-2);border-color:var(--line)}2%,19%{background:var(--accent);border-color:var(--accent)}21%,100%{background:var(--bg-2);border-color:var(--line)}}

.screen{position:relative;flex:1 1 auto;min-height:0;border:1px solid var(--line-2);border-radius:10px;background:rgba(7,8,10,.5);overflow:hidden}
.screen .sc{padding:clamp(14px,2vw,22px);gap:clamp(9px,1.3vw,13px);justify-content:flex-start;animation:cyc5 10s linear infinite}
.screen .sc:nth-child(2){animation-delay:2s}.screen .sc:nth-child(3){animation-delay:4s}
.screen .sc:nth-child(4){animation-delay:6s}.screen .sc:nth-child(5){animation-delay:8s}
@keyframes cyc5{0%{opacity:0}2%,18%{opacity:1}20%,100%{opacity:0}}
.frame-note{font-family:var(--f-mono);font-size:clamp(.55rem,.88vw,.66rem);letter-spacing:.04em;color:var(--ink-3);margin-top:auto}
.sc-stat{display:flex;align-items:baseline;flex-wrap:wrap;gap:.45rem;font-family:var(--f-mono);font-size:clamp(.55rem,.88vw,.66rem);letter-spacing:.03em;color:var(--ink-3)}
.sc-stat b{font-weight:600;color:var(--ink);font-size:clamp(.7rem,1.15vw,.88rem)}
.sc-stat .ar{color:var(--accent)}
.film{position:relative;flex:0 0 auto;height:clamp(58px,9vw,86px);border:1px solid var(--line-2);border-radius:8px;background:linear-gradient(120deg,rgba(205,184,138,.12),transparent 60%),var(--bg-2);display:flex;align-items:center;justify-content:center}
.film .play{width:0;height:0;border-left:14px solid var(--accent);border-top:9px solid transparent;border-bottom:9px solid transparent;opacity:.85}
.film .rec{position:absolute;top:8px;left:10px}
.film .dur{position:absolute;bottom:8px;right:10px;font-family:var(--f-mono);font-size:clamp(.55rem,.88vw,.66rem);color:var(--ink-2)}
.rec{display:inline-flex;align-items:center;gap:.45rem;font-family:var(--f-mono);font-size:clamp(.55rem,.88vw,.66rem);letter-spacing:.08em;color:var(--ink)}
.rec i{width:8px;height:8px;border-radius:50%;background:#e5484d;animation:pulseRed 1.6s infinite}
@keyframes pulseRed{0%{box-shadow:0 0 0 0 rgba(229,72,77,.55)}70%{box-shadow:0 0 0 7px rgba(229,72,77,0)}100%{box-shadow:0 0 0 0 rgba(229,72,77,0)}}
/* the strip's clips still reflow, but only inside a contained cover */
.tlstrip{position:relative;display:flex;gap:3px;height:clamp(34px,5.4vw,48px);flex:0 0 auto}
.tlstrip i{flex:1 1 auto;border-radius:3px;background:var(--accent-soft);border:1px solid var(--line-2)}
.tlstrip i.cut{animation:clipCut 10s linear infinite 2s}
@keyframes clipCut{0%,6%{opacity:1;flex-grow:1}11%,18%{opacity:.12;flex-grow:.12}20%,100%{opacity:1;flex-grow:1}}
.tlstrip .head{position:absolute;top:-3px;bottom:-3px;left:0;right:0;animation:headSweep 10s linear infinite 2s}
.tlstrip .head::before{content:"";position:absolute;top:0;bottom:0;left:0;width:2px;border-radius:2px;background:var(--accent)}
/* the playhead is a full-width layer, so translateX(100%) is exactly one strip */
@keyframes headSweep{0%,2%{transform:translateX(0);opacity:0}3%{opacity:1}18%{transform:translateX(100%);opacity:1}19%,100%{opacity:0;transform:translateX(0)}}
.capbar{display:flex;align-items:flex-start;flex:0 0 auto}
/* clip-path, not width: the caption types on without a layout per frame */
.capbar span{display:inline-block;max-width:100%;overflow:hidden;white-space:nowrap;font-family:var(--f-mono);font-size:clamp(.58rem,.92vw,.7rem);color:var(--ink);background:rgba(236,238,241,.12);border-radius:5px;padding:.3rem .55rem;clip-path:inset(0 100% 0 0);animation:typeIn 10s linear infinite 4s}
.capbar.b span{color:var(--ink-2);animation-delay:5.1s}
@keyframes typeIn{0%,2%{clip-path:inset(0 100% 0 0)}12%,18%{clip-path:inset(0 0 0 0)}20%,100%{clip-path:inset(0 100% 0 0)}}
.lines{display:grid;gap:9px;flex:0 0 auto}
.lines i{display:block;height:10px;width:92%;border-radius:5px;background:var(--accent-soft);border:1px solid var(--line-2);clip-path:inset(0 100% 0 0 round 5px);animation:lineFill 10s linear infinite 6s}
.lines i:nth-child(2){animation-delay:6.35s}.lines i:nth-child(3){animation-delay:6.7s}
@keyframes lineFill{0%,1%{clip-path:inset(0 100% 0 0 round 5px)}9%,18%{clip-path:inset(0 0 0 0 round 5px)}20%,100%{clip-path:inset(0 100% 0 0 round 5px)}}
.chans{display:flex;flex-wrap:wrap;gap:7px;flex:0 0 auto}
.chans .ch{font-family:var(--f-mono);font-size:clamp(.55rem,.88vw,.66rem);letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);border:1px solid var(--line-2);border-radius:20px;padding:.34rem .7rem;animation:chOn 10s linear infinite 8s}
.chans .ch:nth-child(2){animation-delay:8.3s}.chans .ch:nth-child(3){animation-delay:8.6s}.chans .ch:nth-child(4){animation-delay:8.9s}
@keyframes chOn{0%,1%{color:var(--ink-3);border-color:var(--line-2);background:transparent}5%,18%{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}20%,100%{color:var(--ink-3);border-color:var(--line-2);background:transparent}}

.route-cover .demo-body{justify-content:space-between;gap:clamp(8px,1.2vw,14px)}
.fares{position:relative;flex:0 0 auto;min-height:calc(2 * (clamp(.6rem,.95vw,.72rem) * 1.5 + 2 * clamp(6px,.85vw,9px) + 2px) + clamp(7px,1vw,11px))}
.route{position:relative;width:100%;flex:0 0 auto}
.route-map{width:100%;height:auto;display:block;overflow:visible}
.route-path{fill:none;stroke:var(--accent);stroke-width:1.6;stroke-linecap:round;stroke-dasharray:5 6;opacity:.55;animation:routedash 3.2s linear infinite}
@keyframes routedash{to{stroke-dashoffset:-22}}
.route-node{fill:var(--bg);stroke:var(--ink);stroke-width:1.8}
.route-node.stop{stroke:var(--accent);stroke-width:1.6;animation:stoppulse 6s ease-in-out infinite}
@keyframes stoppulse{0%,34%{opacity:.55;r:3.2}46%,58%{opacity:1;r:5}70%,100%{opacity:.55;r:3.2}}
.route-plane{fill:var(--accent);filter:drop-shadow(0 0 6px var(--accent-soft))}
.route-legs{position:relative;height:1.7em;margin-top:6px}
.route-legs .leg{position:absolute;inset:0;display:flex;justify-content:space-between;align-items:center;font-family:var(--f-mono);font-size:clamp(.82rem,1.7vw,1.05rem);letter-spacing:.06em;color:var(--ink);opacity:0;animation:legcycle 9s linear infinite}
.route-legs .leg:nth-child(2){animation-delay:3s}
.route-legs .leg:nth-child(3){animation-delay:6s}
.route-legs .via{color:var(--accent);font-size:.82em;letter-spacing:.1em}
@keyframes legcycle{0%{opacity:0}4%,29%{opacity:1}34%,100%{opacity:0}}
@media (max-width:640px){
  .route-cover .route-map{height:52px}
  .route-cover .route-legs{height:1.4em;margin-top:2px}
  .cover.demo{padding:clamp(12px,3.2vw,18px)}
  .demo-head{padding-right:clamp(84px,24vw,110px)}
}
/* covers only animate while on screen; !important because each rule above
   sets the animation shorthand, which resets play-state to running */
.cover:not(.live),.cover:not(.live) *,.cover:not(.live) *::before,.cover:not(.live) *::after{animation-play-state:paused!important}

/* ---------- experience: sticky title, star on the axis, rows light up ---------- */
.xp-grid{display:grid;grid-template-columns:minmax(0,.9fr) 56px minmax(0,1.25fr);column-gap:clamp(16px,2.6vw,44px)}
.xp-sticky{position:sticky;top:calc(50vh - 90px)}
.sec.xp{padding-top:var(--band)}
.xp .sec-head{padding-block:0 22px}
/* the sticky column is narrow: size the title to it so the rising mask never crops a word */
.xp .sec-title{font-size:clamp(1.9rem,3.6vw,4.2rem)}
.xp-count{font-family:var(--f-mono);font-size:.74rem;letter-spacing:.16em;color:var(--ink-3)}
.xp-count b{font-weight:400;color:var(--accent)}
.xp-axis{position:relative}
.xp-line{position:absolute;left:50%;top:0;bottom:0;width:1px;transform:translateX(-50%);background:linear-gradient(180deg,transparent,var(--line) 8%,var(--line) 92%,transparent)}
.xp-star{position:sticky;top:calc(50vh - 20px);display:block;width:40px;height:40px;margin-inline:auto;filter:drop-shadow(0 0 10px rgba(255,255,255,.55)) drop-shadow(0 0 28px rgba(205,184,138,.35))}
.xp-star svg{display:block;width:100%;height:100%;fill:#F3F4F6;transform:rotate(var(--turn,0deg));transition:transform .9s var(--ease-out)}
.tl{list-style:none}
.tl-row{display:grid;gap:14px;min-height:clamp(260px,44vh,420px);align-content:center;padding:clamp(28px,4vh,48px) 0;transition:opacity .6s var(--ease)}
/* rows off the star step back but stay above 4.5:1; the title carries the change */
html.js .tl-row{opacity:.78}
html.js .tl-row.active{opacity:1}
html.js .tl-row .tl-what h3{color:var(--ink-2);transition:color .6s var(--ease)}
html.js .tl-row.active .tl-what h3{color:var(--ink)}
.tl-when{font-size:.72rem;letter-spacing:.14em;color:#9AA0A9}
.tl-row.now .tl-when{color:var(--accent)}
.tl-what h3{font-family:var(--f-display);font-weight:600;font-stretch:108%;font-size:clamp(1.35rem,2.4vw,2.2rem);letter-spacing:-.025em;line-height:1.12;text-wrap:balance}
.tl-where{font-size:.66rem;letter-spacing:.12em;color:var(--ink-2);margin-top:10px;line-height:1.7;text-wrap:balance}
.tl-promo{font-family:var(--f-mono);text-transform:uppercase;font-size:.66rem;letter-spacing:.12em;line-height:1.7;color:var(--accent);margin-top:2px;text-wrap:balance}
.tl-note{color:var(--ink-2);font-size:1rem;line-height:1.72;max-width:58ch}
.tl-note b{color:var(--ink);font-weight:500}
@media (max-width:880px){
  .xp-grid{grid-template-columns:28px minmax(0,1fr);column-gap:18px}
  .xp-side{grid-column:1 / -1}
  .xp-sticky{position:static}
  /* no longer sticky here, so the heading carries the ordinary symmetric band
     and the section stops adding a second helping of space above it */
  .sec.xp{padding-top:0}
  .xp .sec-head{padding-block:var(--band)}
  .xp-count{display:none}
  .xp-axis{grid-column:1}
  .xp-star{width:26px;height:26px;top:calc(50vh - 13px)}
  .tl{grid-column:2}
  .tl-row{min-height:0;padding:28px 0}
}

/* ---------- capabilities: six compact groups ---------- */
.caps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;padding-block:var(--pad)}
/* every item on one line: three columns where six would squeeze them, six (each as wide
   as its longest item) where they fit */
@media (min-width:881px){.cap li{white-space:nowrap}}
@media (min-width:1400px){.caps{grid-template-columns:repeat(6,auto)}}
@media (max-width:880px){.caps{grid-template-columns:repeat(2,minmax(0,1fr))}.cap li{text-wrap:balance}}
/* (a .cap padding and .cap li size used to sit in this query too, but the .cap rules below
   come later in the file and always won, so phones have only ever had the desktop values;
   dropped rather than switched on, which would change how the cards look) */
@media (max-width:640px){.caps{gap:8px}}
/* two cards side by side stop holding the longest item ("Mandarin and Taiwanese (native)",
   189 px) on one line below 520 px, with the webfont or without it (measured at 481-640):
   one card a row there, so no item breaks */
@media (max-width:519.98px){.caps{grid-template-columns:minmax(0,1fr)}}
.cap{border:1px solid var(--line-2);border-radius:14px;padding:16px 18px 12px;background:linear-gradient(180deg,rgba(23,26,31,.8),rgba(12,13,16,.8));box-shadow:inset 0 1px 0 rgba(255,255,255,.05);transition:transform .45s var(--ease-out),border-color .3s}
.cap:hover{transform:translateY(-3px);border-color:var(--line)}
.cap h3{font-family:var(--f-display);font-size:.9rem;font-weight:600;margin-bottom:8px;display:flex;align-items:center;gap:9px}
.cap h3 i{width:6px;height:6px;border-radius:50%;background:var(--accent)}
.cap ul{list-style:none}
.cap li{font-size:.8rem;color:var(--ink-2);padding:4px 0;line-height:1.45}

/* ---------- contact ---------- */
/* contact has no .sec-head, so it carries the same band padding itself */
.sec.contact{padding-top:var(--band)}
.contact{padding-bottom:clamp(44px,6vw,90px);text-align:center}
.contact-mark{width:min(300px,56vw);aspect-ratio:1000/588;margin:0 auto clamp(30px,4vw,48px);color:var(--ink);opacity:.9;transition:opacity 1.2s var(--ease)}
.contact-mark svg{width:100%;height:100%;display:block}
/* while the particles can draw the mark, the solid one never shows: they gather into it
   as the page reaches Contact. Motion paused, a lost context or a tier without shapes
   drops gl-forms and the solid mark comes back. */
html.gl-form .contact-mark,html.gl-forms .contact-mark{opacity:0}
.contact-big{font-family:var(--f-display);font-weight:500;letter-spacing:-.03em;line-height:1.04;font-size:clamp(2.2rem,6.4vw,5.6rem);max-width:21ch;margin:0 auto clamp(40px,5.6vw,84px);text-wrap:balance;padding:.04em .06em .1em}
/* 16 is the sentence's width in ems for the WIDEST font in the stack at this weight
   and tracking (Helvetica Neue Medium at -.03em, 15.61em with the webfont blocked, 15.73em
   with the .12em side padding), plus a margin. Archivo itself is 14.97em, so with the
   webfont up this leaves room to spare. (Was 15.45 at -.045em, changed 2026-10-01.) */
@media (min-width:900px){.contact-big{white-space:nowrap;max-width:none;font-size:min(5.6rem,calc((100vw - 2 * var(--gutter)) / 16))}}
.cgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;background:var(--line-2);border:1px solid var(--line-2);border-radius:16px;overflow:hidden;text-align:left}
.cgrid a{background:rgba(9,10,12,.92);padding:clamp(20px,2.5vw,30px);display:flex;flex-direction:column;gap:8px;transition:background-color .3s}
.cgrid a:hover{background:var(--card-2)}
.cgrid .k{font-size:.62rem;letter-spacing:.14em;color:var(--ink-3)}
.cgrid .v{font-size:1.02rem;font-weight:500;display:flex;justify-content:space-between;align-items:center;gap:8px;overflow-wrap:anywhere}
.cgrid .ar{color:var(--accent);transition:transform .3s var(--ease-out)}
.cgrid a:hover .ar{transform:translate(3px,-3px)}
@media (max-width:760px){.cgrid{grid-template-columns:1fr;gap:10px;background:none;border:0;border-radius:0;overflow:visible}.cgrid a{border:1px solid var(--line-2);border-radius:14px}}

/* below the single-line width the footer is a centred column: the parts stack, and the
   motion button sits under them on the centre line instead of being pulled to one side by
   space-between (which also dragged the stack 22 px off centre) */
footer{position:relative;z-index:1;border-top:1px solid var(--line-2);padding-block:26px;display:flex;flex-direction:column;justify-content:center;align-items:center;flex-wrap:wrap;gap:14px;font-size:.64rem;letter-spacing:.08em;color:var(--ink-3)}
/* availability (Mark, 2026-09-13: moved here from under the Contact heading): one line of
   small type across the top of the footer where it fits, one part a line where it doesn't.
   row-gap only: a column gap would sit beside every " ｜ " and widen it. */
.foot-avail{flex:1 1 auto;display:flex;flex-direction:column;align-items:center;row-gap:6px;text-align:center;color:var(--ink-2);margin:0}
.foot-avail>span{text-wrap:balance}
.foot-avail .keep-case{text-transform:none}
/* one line from 1375 px (Mark, 2026-09-18: the copyright joins the availability line). The
   whole string is 113.562em in the widest font of the stack, measured with the webfont
   blocked; at .64rem that is 1163 px. It CLEARS THE GUTTERS from 1320 px, but the motion
   button has to fit beside it as well, and it only does from 1375: between the two the line
   stayed on one row, the button dropped to a row of its own on the left, and the line sat
   22 px right of centre. Below 1375 the parts stack, one to a line (four lines), and a part
   never begins with "｜" because every "｜" inside a part is glued to the word before it
   with &nbsp;. */
@media (min-width:1375px){
  footer{flex-direction:row;justify-content:space-between;gap:10px}
  .foot-avail{flex-direction:row;justify-content:center;white-space:nowrap}
  .foot-avail>span+span::before{content:" ｜ ";white-space:pre;color:var(--ink-3)}
  /* a spacer the width of the motion button's margin box (44px wide, pulled 10px into the
     gutter), so the line is centred on the page and not pushed left by the button. Only
     where the button exists: without JavaScript it is hidden, and the spacer would then
     push the line 22 px the other way. */
  html.js footer::before{content:"";flex:0 0 34px}
}
/* the motion switch is an icon now: one shape for what pressing it does next */
.motion-btn{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;margin:-14px -10px -14px 0;color:var(--ink-2);border-radius:999px;transition:color .25s,background-color .25s}
.motion-btn:hover{color:var(--accent);background:rgba(255,255,255,.05)}
.motion-btn .mi-play{display:none}
html.motion-off .motion-btn .mi-play{display:block}
html.motion-off .motion-btn .mi-pause{display:none}
html:not(.js) .motion-btn{display:none}

/* ---------- back to top ---------- */
.totop{position:fixed;right:clamp(18px,3vw,34px);bottom:clamp(18px,3vw,34px);z-index:38;width:46px;height:46px;border-radius:50%;border:1px solid var(--line);background:rgba(14,16,19,.9);color:var(--ink);display:grid;place-items:center;opacity:0;visibility:hidden;transform:translateY(10px);transition:opacity .3s,visibility .3s,transform .3s var(--ease-out),background-color .3s,color .3s}
.totop.show{opacity:1;visibility:visible;transform:none}
.totop{translate:0 calc(-1 * var(--lift,0px))}
.totop:hover{background:var(--ink);color:var(--bg)}

/* ---------- lightbox ---------- */
.lb{position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;padding:clamp(12px,3vw,40px);background:rgba(4,5,6,.72);opacity:0;transition:opacity .4s}
.lb.open{opacity:1}
.lb-panel{position:relative;width:min(1120px,100%);max-height:90svh;display:grid;grid-template-columns:1.25fr 1fr;grid-template-rows:minmax(0,1fr);background:var(--bg-2);border:1px solid var(--line);border-radius:20px;overflow:hidden;transform:translateY(18px) scale(.98);transition:transform .5s var(--ease-out);box-shadow:0 40px 120px -40px #000}
.lb.open .lb-panel{transform:none}
@media (max-width:820px){.lb-panel{grid-template-columns:1fr;grid-template-rows:none;max-height:92svh;overflow:auto;overscroll-behavior:contain}}
.lb-media{background:var(--bg);display:flex;flex-direction:column;min-height:0}
.lb-main{flex:1;min-height:240px;overflow:auto;overscroll-behavior:contain;display:flex;align-items:flex-start;justify-content:center;background:var(--bg)}
.lb-main img{width:100%;height:auto;display:block}
.lb-zoom{display:block;width:100%;padding:0;margin-block:auto;cursor:zoom-in}
.lb-zoom:focus-visible{outline-offset:-4px}
.lb-main .cover{width:100%;aspect-ratio:16/11;margin-block:auto}
.lb-thumbs{display:flex;gap:8px;padding:12px 10px;overflow-x:auto}
.lb-thumbs button{flex:0 0 auto;padding:0;border-radius:6px;opacity:.6;transition:opacity .2s}
.lb-thumbs button.sel,.lb-thumbs button:hover{opacity:1}
.lb-thumbs img{width:64px;height:46px;object-fit:cover;border-radius:6px;border:1px solid var(--line)}
.lb-thumbs button.sel img{border-color:var(--accent)}
.lb-hint{flex:0 0 auto;padding:4px 12px 12px;font-family:var(--f-mono);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.lb-body{padding:clamp(34px,3.6vw,48px) clamp(28px,3vw,42px) clamp(40px,4.6vw,58px);overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column;gap:22px}
.lb-body::-webkit-scrollbar{width:8px}
.lb-body::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.lb-body .kicker{font-family:var(--f-mono);font-size:.64rem;letter-spacing:.18em;text-transform:uppercase;color:var(--accent)}
.lb-body h3{font-family:var(--f-display);font-weight:600;font-stretch:112%;font-size:clamp(1.5rem,2.6vw,2.1rem);letter-spacing:-.025em;line-height:1.05}
.lb-body .lb-sub{font-family:var(--f-mono);font-size:.66rem;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-3);margin-top:-10px}
.lb-body h4{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink);margin-bottom:11px;font-weight:600}
.lb-body p{color:var(--ink-2);font-size:.95rem;line-height:1.65}
.lb-body .dl{display:grid;gap:26px;border-left:1px solid var(--accent);padding-left:20px}
.lb-stack{display:flex;flex-wrap:wrap;gap:9px;margin-top:4px}
.lb-stack span{font-family:var(--f-mono);font-size:.6rem;line-height:1;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-2);border:1px solid var(--line);border-radius:999px;padding:.62rem .95rem}
.lb-close{position:absolute;top:12px;right:12px;z-index:6;width:40px;height:40px;border-radius:50%;border:1px solid var(--line);background:var(--bg-2);color:var(--ink);display:grid;place-items:center;font-size:1.05rem;transition:background-color .25s,color .25s,transform .35s var(--ease-out)}
.lb-close:hover{background:var(--ink);color:var(--bg);transform:rotate(90deg)}
.zoom{position:fixed;inset:0;z-index:90;display:flex;align-items:center;justify-content:center;padding:clamp(16px,3vw,48px);background:rgba(4,5,6,.94);opacity:0;transition:opacity .3s;cursor:zoom-out;overflow:auto}
.zoom.open{opacity:1}
.zoom img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;border-radius:8px}
.zoom-close{position:fixed;top:16px;right:16px;z-index:91;width:40px;height:40px;border-radius:50%;border:1px solid rgba(236,238,241,.3);background:rgba(7,8,10,.7);color:var(--ink);display:grid;place-items:center;font-size:1.05rem}

/* ---------- motion preferences ---------- */
/* still: reduced motion, or the visitor pressed Pause motion. Loops stop on a
   meaningful first frame instead of freezing half way through a fade */
html.still *,html.still *::before,html.still *::after{animation:none!important}
html.still .scene{opacity:0}
html.still .scene:first-child{opacity:1}
html.still .rail-fill{transform:none}
html.still .rail .st{opacity:1;color:var(--ink-2)}
html.still .capbar span,html.still .lines i{clip-path:none}
html.still .tlstrip .head,html.still .route-plane{display:none}
html.still .route-legs .leg:first-child{opacity:1}
html.still .universe{opacity:.6}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition-duration:.001ms!important;transition-delay:0s!important}
  /* the same first frames as html.still, repeated here so they hold without JavaScript */
  .scene{opacity:0}.scene:first-child{opacity:1}
  .rail-fill{transform:none}.rail .st{opacity:1;color:var(--ink-2)}
  .capbar span,.lines i{clip-path:none}
  .tlstrip .head,.route-plane{display:none}
  .route-legs .leg:first-child{opacity:1}
  .rv,.sec-title,.sec-title>span{opacity:1!important;transform:none!important;clip-path:none!important}
  html.js .tl-row{opacity:1}
}
html:not(.js) .rv,html:not(.js) .sec-title>span{opacity:1;transform:none}
html:not(.js) .cover *{animation-play-state:running!important}
/* without JavaScript the case details can't open in a dialog, so they sit under each case */
html:not(.js) .case-more[hidden]{display:grid!important;gap:20px;margin-top:30px}
html:not(.js) .more-media{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:10px}
html:not(.js) .more-media img{border-radius:12px;border:1px solid var(--line)}
html:not(.js) .case-more .dl{display:grid;gap:26px;border-left:1px solid var(--accent);padding-left:20px;max-width:72ch}
html:not(.js) .case-more h4{font-family:var(--f-mono);font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink);margin-bottom:11px;font-weight:600}
html:not(.js) .case-more p{color:var(--ink-2);font-size:.95rem;line-height:1.65}
@media print{.universe,.universe-front,.stars,.grain,.intro,.nav,.totop,.cur-ring{display:none!important}.rv,.sec-title>span{opacity:1!important;transform:none!important}}
