/* DisplayBridge — EXPERIMENTAL scroll-story stylesheet.
   Same rules as the real one: no framework, no webfonts, system SF.
   Each .scene is a tall wrapper; its .scene__pin stays stuck for the
   whole scroll and animates from the custom property --p (0…1) that
   story.js keeps updated. With scripting off (or reduced motion) every
   scene simply shows its finished state. */

:root{
  --ink:#f5f5f7;
  --ink-2:#a1a1a6;
  --line:#2a2a2c;
  --bg:#000000;
  --bg-2:#0b0b0d;
  --blue:#0071e3;
  --blue-hi:#0077ed;
  --glass:#5ac8fa;
  --green:#30d158;
  --pad:24px;
  --sans:-apple-system,BlinkMacSystemFont,"SF Pro Display","SF Pro Text",
         "Helvetica Neue",Helvetica,Arial,sans-serif;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  font-family:var(--sans);
  font-size:17px;
  line-height:1.5;
  color:var(--ink);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
}
img,svg,canvas{display:block;max-width:100%}
a{color:var(--glass);text-decoration:none}
a:hover{text-decoration:underline}
b{font-weight:600}

.skip{position:absolute;left:-9999px;top:0;background:#fff;color:#000;
  padding:12px 18px;z-index:200}
.skip:focus{left:8px;top:8px}

/* ── type ───────────────────────────────────────────────────────── */
h1,h2{margin:0;font-weight:600;letter-spacing:-.025em;line-height:1.05}
h1{font-size:clamp(2.6rem,8.4vw,5rem);letter-spacing:-.032em}
h2{font-size:clamp(2rem,6.4vw,3.6rem)}
@media (max-width:620px){h1 br,h2 br{display:none}}
p{margin:0}

.eyebrow{
  margin:0 0 16px;
  font-size:.75rem;
  font-weight:600;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--glass);
}
.lead{
  margin:24px auto 0;
  max-width:44ch;
  font-size:clamp(1.05rem,1.4vw,1.28rem);
  color:var(--ink-2);
}
.fineprint{margin-top:22px;font-size:.85rem;color:var(--ink-2)}

/* ── nav ────────────────────────────────────────────────────────── */
.nav{position:fixed;inset:0 0 auto;z-index:100;
  background:rgba(0,0,0,.55);
  -webkit-backdrop-filter:saturate(180%) blur(18px);
  backdrop-filter:saturate(180%) blur(18px);
  border-bottom:1px solid rgba(255,255,255,.08)}
.nav__in{max-width:1080px;margin-inline:auto;padding:10px var(--pad);
  display:flex;align-items:center;justify-content:space-between}
.nav__mark{font-weight:600;color:var(--ink);letter-spacing:-.01em}
.nav__mark:hover{text-decoration:none}
.nav__tag{
  margin-left:8px;padding:2px 8px;border-radius:99px;
  font-size:.68rem;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;vertical-align:2px;
  color:var(--glass);border:1px solid rgba(90,200,250,.45)}
/* Page links, added 2026-09-06 with the SEO subpages. The nav markup is
   shared byte-for-byte with the prose pages (check-site.py enforces it),
   so the same classes have to exist in both stylesheets — this one renders
   it on black, style.css renders it on white. */
.nav__links{display:flex;gap:24px;margin-left:auto;font-size:.83rem}
.nav__links a{color:var(--ink-2)}
.nav__links a:hover{color:var(--ink);text-decoration:none}
.nav .btn{margin-left:24px}
@media (max-width:860px){
  .nav__links{display:none}
  .nav .btn{margin-left:auto}
}

/* ── buttons ────────────────────────────────────────────────────── */
.btn{display:inline-block;padding:12px 26px;border-radius:99px;
  font-weight:500;font-size:1.02rem;border:1px solid transparent}
.btn:hover{text-decoration:none}
.btn--sm{padding:6px 16px;font-size:.9rem}
.btn--blue{background:var(--blue);color:#fff}
.btn--blue:hover{background:var(--blue-hi)}
.btn--ghost{background:rgba(255,255,255,.1);color:var(--ink);
  border-color:rgba(255,255,255,.16)}
.btn--ghost:hover{background:rgba(255,255,255,.2)}
.cta{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:34px}

/* ── hero: live background video + overlaid text ────────────────────
   One 100svh section, no pin. The clip (a hand plugs the cable, the
   iMac comes alive) runs full-bleed behind the copy; the top of the
   frame is the iMac's bright alpine wallpaper, so a strong top scrim
   carries the white text, easing to nearly clear mid-frame where the
   action is, with a light foot for the scroll hint. The text block
   sits in the upper part of the viewport for the same reason. */
.vhero{
  position:relative;height:84svh;overflow:hidden;  /* 80→84svh 2026-09-05, user: a hair taller */
  display:flex;flex-direction:column;align-items:center;
  justify-content:center;text-align:center;
  padding:52px var(--pad) 40px}
/* the brightness filter is not only styling: while a video plays,
   browsers may promote it to a hardware overlay that composites ABOVE
   sibling layers — the scrim then only kicks in when the window loses
   focus and the overlay is demoted (observed 2026-09-05). Any filter
   forces the video back into the normal compositing path, so the
   scrim reliably applies AND the clip itself is pre-darkened. */
.vhero__video{
  position:absolute;inset:0;width:100%;height:100%;z-index:0;
  margin-inline:auto;
  /* bottom-anchored cover crop (user call 2026-09-05): when the
     squarish clip is taller than the hero, the excess is cut from
     the top — the cable being plugged in at the bottom edge must
     stay in frame on wide viewports. This is only the STARTING
     frame: story.js pans object-position up with playback (heroPan)
     so the clip ends framed on the iMac. */
  object-fit:cover;object-position:50% 100%;
  filter:brightness(.72);
  will-change:transform}
/* very wide screens (16:9 monitors and wider): cap the clip's width so
   the cover crop cannot over-zoom — uncapped, a wide screen showed only
   the iMac's screen and nothing of the MacBook (user report
   2026-09-05). 118svh (105 → 118 same evening, user: a bit wider)
   keeps ~3/4 of the machines band in frame at any moment; the sides
   letterbox into the page's black. */
@media (min-aspect-ratio:16/9){
  .vhero__video{width:118svh}
}
/* deliberately heavy darkening (user call 2026-09-05: with a light
   scrim the text lost against the clip) — the video reads as a moody
   backdrop, the copy carries the section */
.vhero__scrim{
  position:absolute;inset:0;z-index:1;transform:translateZ(0);
  background:linear-gradient(180deg,
    rgba(0,0,0,.72) 0%, rgba(0,0,0,.5) 22%,
    rgba(0,0,0,.36) 46%, rgba(0,0,0,.28) 72%, rgba(0,0,0,.45) 100%)}
.vhero__body{
  position:relative;z-index:2;max-width:900px;
  text-shadow:0 1px 22px rgba(0,0,0,.85)}
.vhero .hero__hint{z-index:2}

/* rotating headline — ported from the live site's style.css: all
   spans share one grid cell, so the box is always as tall as the
   LONGEST variant and the typing never shifts the layout below.
   The caret is the live span's ::after; no typing, no caret. */
.rotator{display:grid}
.rotator>span{grid-area:1/1}
.rotator__ghost{visibility:hidden;pointer-events:none}
.rotator__live::after{
  content:"";display:inline-block;width:3px;height:.78em;
  margin-left:.07em;vertical-align:-.04em;border-radius:1px;
  background:var(--glass);animation:caret 1.05s steps(1) infinite}
@keyframes caret{0%,50%{opacity:1}51%,100%{opacity:0}}
.rotator.is-static .rotator__live::after{display:none}
@media (prefers-reduced-motion:reduce){.rotator__live::after{display:none}}
/* soft local vignette so the copy stays readable where the clip is
   busy (the MacBook screen sits mid-frame on wide viewports) */
.vhero__body::before{
  content:"";position:absolute;inset:-18% -22%;z-index:-1;
  background:radial-gradient(closest-side,
    rgba(0,0,0,.55), rgba(0,0,0,.28) 55%, transparent 100%)}
.vhero__body .lead{color:rgba(245,245,247,.88)}
.hero__hint{position:absolute;left:50%;bottom:26px;translate:-50% 0;
  width:26px;height:42px;border:1.5px solid rgba(255,255,255,.35);
  border-radius:14px}
.hero__hint span{position:absolute;left:50%;top:8px;translate:-50% 0;
  width:3px;height:8px;border-radius:2px;background:rgba(255,255,255,.65);
  animation:hint 1.8s ease-in-out infinite}
@keyframes hint{
  0%,20%{transform:translateY(0);opacity:1}
  70%{transform:translateY(12px);opacity:0}
  100%{transform:translateY(0);opacity:0}}

/* ── scenes: pin + progress plumbing ────────────────────────────── */
.scene{--p:1; position:relative}
/* pixels shortened 360→240svh (user call 2026-09-05: reaching the
   ×60 punch took too much scrolling) */
.scene--pixels{height:240svh}
/* latency 300→235svh (user call 2026-09-05: scrubbing through took
   too much scroll — the runway is height minus one viewport, so
   200→135svh of scrub ≈ 50% faster) */
.scene--latency{height:235svh}
/* (scene--size is gone 2026-09-05: the footprint became a static band
   right under Setup — see index.html) */

/* pinned frame is 80svh, matching the hero (user call 2026-09-05) —
   progress still hits 1 while pinned, since the pin only releases
   once the wrapper's remaining height drops below the pin's own.
   top:10svh (user call, same day): with top:0 the frame hugged the
   viewport top and the spare 20svh sat as a black band at the
   bottom — sticking 10svh down splits the spare evenly, so the
   content rides the vertical center while you scrub the scene */
.scene__pin{
  position:sticky;top:10svh;height:80svh;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;
  justify-content:center;text-align:center;
  padding:84px var(--pad) 40px}
.scene__title{max-width:16ch}
.scene__title--tight{margin-bottom:8px}
.eyebrow--fixed{margin-bottom:6px}

.caption{
  max-width:46ch;margin:18px auto 0;
  font-size:clamp(1.02rem,1.35vw,1.22rem);
  color:var(--ink-2)}
.caption b{color:var(--ink)}
.caption--wide{max-width:52ch}

/* punchline paragraphs fade in near the end of each scene */
[data-punch]{
  opacity:clamp(0, calc((var(--p) - .72) * 6), 1);
  transform:translateY(calc((1 - clamp(0, calc((var(--p) - .72) * 6), 1)) * 18px))}

.caption .green{color:var(--green)}

/* ── setup: the four steps ──────────────────────────────────────────
   Ported from the live site's #how band (.flow), restyled for this
   page's black. A plain static band between the pinned scenes. */
/* section spacing tightened 2026-09-05 (user call: too much blank
   between sections — was clamp(88px,12vw,150px), doubled where two
   bands meet) */
.band{padding-block:clamp(56px,8vw,96px);text-align:center}
.band + .band{padding-top:clamp(20px,3vw,36px)}
.band__wrap{max-width:1000px;margin-inline:auto;padding-inline:var(--pad)}
.lead--band{max-width:52ch}

/* the real app window between the lead and the steps — widened
   640→840px 2026-09-05 (user call: the shot deserved more presence) */
.flow__shot{
  display:block;width:min(840px,96%);height:auto;
  margin:56px auto 0;border-radius:12px;
  box-shadow:0 18px 60px rgba(0,0,0,.55), 0 0 0 1px rgba(255,255,255,.08)}

.flow{
  list-style:none;margin:66px 0 0;padding:0;text-align:left;
  display:grid;gap:38px 26px;
  grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.flow li{position:relative;display:flex;flex-direction:column;gap:13px}
.flow__n{
  display:grid;place-items:center;width:36px;height:36px;border-radius:50%;
  background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.2);
  color:#fff;font-size:.92rem;font-weight:600}
.flow h3{
  margin:0;color:var(--ink);
  font-size:1.12rem;font-weight:600;letter-spacing:-.012em;line-height:1.2}
.flow p{color:var(--ink-2);font-size:.96rem;line-height:1.5}

/* between one row and one column, auto-fit lands on 3 + 1, which reads
   as a mistake — four items want 2x2 */
@media (min-width:600px) and (max-width:939px){
  .flow{grid-template-columns:repeat(2,1fr)}}

/* the connector only makes sense while all four sit on one row */
@media (min-width:940px){
  .flow li:not(:last-child)::after{
    content:"";position:absolute;left:48px;right:-26px;top:18px;height:1px;
    background:linear-gradient(90deg,rgba(90,200,250,.5),rgba(255,255,255,.07))}}

/* ── scene 2: pixels ────────────────────────────────────────────── */
.pixels__grid{position:absolute;inset:0;width:100%;height:100%;opacity:.6}
.pixels__body{position:relative}
.pixels__count{margin-top:26px}
.pixels__count b{
  display:block;
  font-size:clamp(2.6rem,9vw,6rem);
  font-weight:700;letter-spacing:-.03em;line-height:1;
  font-variant-numeric:tabular-nums;
  color:var(--ink);
  text-shadow:0 0 44px rgba(0,113,227,.55)}
.pixels__count span{
  display:block;margin-top:10px;
  font-size:1rem;color:var(--ink-2);letter-spacing:.02em}
.pixels__times{
  margin-top:18px;font-size:clamp(1.2rem,2.4vw,1.7rem);font-weight:600;
  color:var(--glass);
  opacity:clamp(0, calc((var(--p) - .48) * 7), 1);
  transform:translateY(calc((1 - clamp(0, calc((var(--p) - .48) * 7), 1)) * 14px))}

/* ── scene 3: latency ───────────────────────────────────────────── */
/* the wingbeat artwork: full-bleed behind the ruler, right-anchored.
   The canvas is drawn by story.js; the CSS background is the no-JS /
   reduced-motion fallback (one static frame, art is mostly black so
   it blends into the page). Fades in as the scene pins, and stays
   dimmed (backdrop, not subject — the text must win). */
.wing{
  position:absolute;inset:0;pointer-events:none;
  background:#000 url(assets/wing/w05.jpg) 63% center / cover no-repeat;
  opacity:calc(clamp(0, calc(var(--p) * 5), 1) * .55)}
.wing__canvas{position:absolute;inset:0;width:100%;height:100%}
.wing::after{ /* keep the left text column readable on top of the art */
  content:"";position:absolute;inset:0;
  background:linear-gradient(90deg, rgba(0,0,0,.72) 0 30%, transparent 62%)}
@media (max-width:900px){.wing{opacity:calc(clamp(0, calc(var(--p) * 5), 1) * .4)}}

.latency__body{position:relative;width:min(720px,100%)}
.latency__big{margin:18px 0 30px;line-height:1}
.latency__big b{
  font-size:clamp(4rem,13vw,8.5rem);font-weight:700;letter-spacing:-.04em;
  font-variant-numeric:tabular-nums;
  text-shadow:0 0 44px rgba(0,113,227,.5)}
.latency__big .u{
  margin-left:6px;font-size:clamp(1.4rem,3.4vw,2.2rem);
  font-weight:600;color:var(--ink-2)}

.ruler{margin-top:8px;text-align:left}
.ruler__row{margin-top:20px}
/* bar lengths + reveal indices live HERE, not in style="" attributes:
   the deployed CSP (style-src 'self', no unsafe-inline) nulls inline
   style attributes — exactly this broke the bars on the live site on
   2026-09-05. Keep this page free of style="" attributes. */
.ruler__row:nth-child(1){--w:100%}
.ruler__row:nth-child(2){--w:24.66%}
.ruler__row:nth-child(3){--w:13.33%}
.ruler__label{display:block;font-size:.92rem;color:var(--ink-2);margin-bottom:7px}
.ruler__bar{position:relative;height:30px;display:flex;align-items:center}
.ruler__bar i{
  display:block;height:100%;border-radius:7px;
  width:calc(var(--w) * clamp(0, calc((var(--p) - .3) * 3), 1));
  background:rgba(255,255,255,.16);
  transition:none}
.ruler__bar b{margin-left:12px;font-size:.95rem;color:var(--ink-2);white-space:nowrap}
.ruler__row--us .ruler__bar i{
  background:linear-gradient(90deg,var(--blue),var(--glass));
  box-shadow:0 0 22px rgba(0,113,227,.5)}
.ruler__row--us .ruler__label,
.ruler__row--us .ruler__bar b{color:var(--ink);font-weight:600}
.ruler__ticks{
  display:flex;justify-content:space-between;margin-top:16px;
  padding-top:10px;border-top:1px solid var(--line);
  font-size:.8rem;color:var(--ink-2);font-variant-numeric:tabular-nums}

/* ── requirements table + honest list ─────────────────────────────
   Ported verbatim from the live site's style.css (2026-09-05, user
   request) — only the tokens are mapped: dark-2→#161617 literal,
   dark-ink→--ink, dark-ink-2→--ink-2, dark-line→--line (identical
   values on both sheets). Keep in sync with public/style.css. */
.req{
  margin:60px auto 0;max-width:820px;text-align:left;
  border:1px solid var(--line);border-radius:20px;overflow:hidden;
  background:#161617}
.req__row{
  display:grid;grid-template-columns:1.1fr 1.3fr 1.3fr;gap:18px;
  padding:16px 24px;border-top:1px solid var(--line);
  font-size:.95rem}
.req__row:first-child{border-top:0}
.req__row span:first-child{color:var(--ink-2)}
.req__row--head{
  font-size:.76rem;text-transform:uppercase;letter-spacing:.1em;
  font-weight:600;color:var(--ink-2);background:rgba(255,255,255,.03)}
.req__row--head span{color:var(--ink-2)!important}
.req__span{grid-column:2 / -1}
@media (max-width:700px){
  .req__row{grid-template-columns:1fr;gap:4px}
  .req__row--head{display:none}
  .req__row span:first-child{
    font-size:.74rem;text-transform:uppercase;letter-spacing:.1em;
    margin-bottom:4px}
  .req__span{grid-column:auto}}

.honest{margin:56px auto 0;max-width:640px;text-align:left}
.honest h3{color:var(--ink);margin-bottom:18px;text-align:center}
.honest ul{list-style:none;margin:0;padding:0;display:grid;gap:14px}
.honest li{
  padding-left:20px;position:relative;color:var(--ink-2);font-size:.98rem}
.honest li::before{
  content:"";position:absolute;left:0;top:.62em;width:7px;height:1.5px;
  background:var(--glass)}
.honest b{color:var(--ink);font-weight:600}

/* ── faq ─────────────────────────────────────────────────────────────
   Ported verbatim from the live site's style.css (2026-09-05, user
   request) — token names match this sheet, so the rules carry over
   unchanged; only band__wrap--narrow is new (the live site uses its
   wrap--narrow, 760px). Keep in sync with public/style.css. */
.band__wrap--narrow{max-width:760px}
.faq{margin-top:50px;border-top:1px solid var(--line);text-align:left}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{
  list-style:none;cursor:pointer;padding:20px 34px 20px 0;position:relative;
  font-size:1.05rem;font-weight:500;letter-spacing:-.01em}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"";position:absolute;right:6px;top:26px;width:9px;height:9px;
  border:solid var(--ink-2);border-width:0 1.6px 1.6px 0;
  transform:rotate(45deg);transition:transform .2s ease}
.faq details[open] summary::after{transform:rotate(-135deg);top:30px}
.faq p{padding:0 40px 22px 0;color:var(--ink-2);font-size:.99rem}

/* ── the footprint (static band since 2026-09-05, was scene 4) ──── */
.size__body{width:min(680px,100%)}
/* inside the band there is no centering flex parent (the pinned
   scenes centered these blocks via .scene__pin) — center them here */
.band .size__body{margin-inline:auto}
.band .size__body .scene__title{margin-inline:auto}
.size__big{
  color:var(--glass);
  text-shadow:0 0 44px rgba(90,200,250,.4)}
/* the download facts, revealing one after another as the scene
   scrolls: each line gets a stagger index --i and derives its own
   0→1 reveal --t from the scene's --p. With --p at its no-JS /
   reduced-motion default of 1, every --t is 1 — the list is just
   there. */
.size__facts{
  list-style:none;margin:36px auto 0;padding:0;
  width:min(46ch,100%);text-align:left}
.size__facts li:nth-child(1){--i:0}
.size__facts li:nth-child(2){--i:1}
.size__facts li:nth-child(3){--i:2}
.size__facts li{
  --t:clamp(0, calc((var(--p) - .28 - var(--i) * .1) * 5), 1);
  position:relative;padding-left:30px;margin-top:16px;
  color:var(--ink-2);font-size:1rem;line-height:1.5;
  opacity:var(--t);
  transform:translateY(calc((1 - var(--t)) * 14px))}
.size__facts li::before{
  content:"";position:absolute;left:2px;top:.4em;
  width:13px;height:7px;
  border-left:2.2px solid var(--glass);
  border-bottom:2.2px solid var(--glass);
  transform:rotate(-45deg)}

/* first CTA: button + the 6 MB note side by side (stacks on narrow
   viewports); rides the shared [data-punch] end-of-scene reveal */
.size__cta{
  margin-top:44px;
  display:flex;align-items:center;justify-content:center;
  gap:12px 26px;flex-wrap:wrap}
.size__ctanote{
  font-size:.92rem;line-height:1.45;color:var(--ink-2);text-align:left}
@media (max-width:520px){.size__ctanote{text-align:center}}

/* ── impressions: card gallery slider ───────────────────────────────
   Apple-highlights-style carousel. The track is a plain scroll-snap
   scroller (works with JS off; scrollbar hidden), each card a big
   rounded image with the caption overlaid top-left on a soft scrim.
   Side padding of the track = the peek: the active card centers and
   the neighbours show at the edges. Controls (dot-pill + play/pause)
   are revealed by story.js. */
.gallery{padding:8svh 0 6svh} /* was 14/10svh — tightened 2026-09-05 */
.gallery__head{text-align:center;padding:0 var(--pad);margin-bottom:44px}
.gallery__track{
  display:flex;gap:22px;
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  /* center the snapped card: side padding = half the leftover space;
     the svh term caps a card (3:2) at ~78svh tall, so the gallery
     stays inside ~80% of the viewport like the scenes */
  --card-w:min(1060px, 88vw, 117svh);
  padding:0 calc((100vw - var(--card-w)) / 2) 8px;
  scrollbar-width:none}
.gallery__track::-webkit-scrollbar{display:none}
.gallery__track:focus-visible{outline:2px solid var(--glass);outline-offset:4px}
.gallery__card{
  position:relative;flex:0 0 var(--card-w);margin:0;
  scroll-snap-align:center;
  border-radius:28px;overflow:hidden;
  background:var(--bg-2);
  box-shadow:0 24px 70px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.06)}
.gallery__card img{width:100%;aspect-ratio:3/2;height:auto;object-fit:cover}
.gallery__cap{
  position:absolute;inset:0;padding:clamp(20px,3.4vw,44px);
  display:flex;flex-direction:column;gap:6px;align-items:flex-start;
  text-align:left;pointer-events:none;
  background:linear-gradient(160deg, rgba(0,0,0,.55) 0%, rgba(0,0,0,.18) 34%, transparent 55%)}
.gallery__cap b{
  font-size:clamp(1.25rem,2.6vw,1.9rem);font-weight:600;
  letter-spacing:-.02em;line-height:1.15;max-width:18ch;
  text-shadow:0 1px 14px rgba(0,0,0,.55)}
.gallery__cap span{
  font-size:clamp(.9rem,1.3vw,1.05rem);color:rgba(245,245,247,.85);
  max-width:34ch;text-shadow:0 1px 10px rgba(0,0,0,.6)}

/* caption choreography (JS-driven, so the no-JS page keeps every
   caption visible): --cap-o/--cap-x come from story.js and follow the
   card's real scroll offset — opacity (1-|off|)³ + a -0.45× horizontal
   lag, the same formula Apple's media-card gallery uses. The fade sits
   on the whole cap (scrim included: peeking cards show a clean image),
   the lag only on the text so the scrim never slides off the edge. */
.gallery.has-js .gallery__card{cursor:pointer}
.gallery.has-js .gallery__cap{opacity:var(--cap-o,1)}
.gallery.has-js .gallery__cap>*{
  transform:translateX(var(--cap-x,0px));
  will-change:transform}

/* controls: dot-pill + round play/pause, centered under the track */
.gallery__controls{
  display:flex;justify-content:center;align-items:center;gap:16px;
  margin-top:34px}
.gallery__dots{
  display:flex;align-items:center;gap:8px;
  padding:0 14px;height:44px;border-radius:99px;
  background:rgba(255,255,255,.1)}
.gallery__dot{
  width:8px;height:8px;border-radius:99px;border:0;padding:0;
  background:rgba(255,255,255,.4);cursor:pointer;
  transition:width .4s cubic-bezier(.4,0,.2,1), background .3s}
.gallery__dot:hover{background:rgba(255,255,255,.65)}
.gallery__dot.is-on{width:34px;background:var(--ink)}
.gallery__play{
  display:grid;place-items:center;
  width:44px;height:44px;border-radius:50%;border:0;cursor:pointer;
  background:rgba(255,255,255,.1);color:var(--ink)}
.gallery__play:hover{background:rgba(255,255,255,.2)}
.gallery__play svg{width:20px;height:20px}
.gallery__play .i-play{display:none}
.gallery__play.is-paused .i-play{display:block}
.gallery__play.is-paused .i-pause{display:none}

@media (prefers-reduced-motion:reduce){
  .gallery__dot{transition:none}}

/* ── why: advantage card grid ───────────────────────────────────────
   Apple-shop-strip-style recap (our own implementation): left-aligned
   headline, then one rounded dark card per advantage. Pure CSS grid —
   4 / 2 / 1 columns. story.js flags .why--reveal and .is-in for the
   staggered fade-up; without that class the cards are simply visible
   (no-JS and reduced-motion path). */
.why{padding:8svh var(--pad) 5svh} /* was 12/8svh — tightened 2026-09-05 */
.why__in{max-width:1180px;margin-inline:auto}
.why__head{text-align:left}
.why__head h2{max-width:20ch}
.why__grid{
  list-style:none;margin:44px 0 0;padding:0;
  display:grid;gap:18px;
  grid-template-columns:repeat(4,1fr)}
@media (max-width:1080px){.why__grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.why__grid{grid-template-columns:1fr}}
.why__card{
  display:flex;flex-direction:column;gap:10px;
  padding:26px 24px 30px;border-radius:24px;text-align:left;
  background:var(--bg-2);
  box-shadow:0 0 0 1px rgba(255,255,255,.07), 0 18px 44px rgba(0,0,0,.45)}
.why__kicker{
  font-size:.75rem;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--glass)}
.why__card h3{
  margin:0;font-size:clamp(1.25rem,1.9vw,1.5rem);font-weight:600;
  letter-spacing:-.02em;line-height:1.16}
.why__card p:last-child{
  font-size:.95rem;line-height:1.5;color:var(--ink-2)}
/* the staggered fade-up (delay per card set inline by story.js) */
.why--reveal .why__card{
  opacity:0;transform:translateY(22px);
  transition:opacity .6s ease var(--d,0s),
             transform .7s cubic-bezier(.2,.6,.2,1) var(--d,0s)}
.why--reveal .why__card.is-in{opacity:1;transform:none}

/* ── closer + foot ──────────────────────────────────────────────── */
.closer{min-height:80svh;display:grid;place-items:center;
  text-align:center;padding:80px var(--pad)}
.closer__lead{margin:18px auto 0;max-width:44ch}
.closer__lead b{color:var(--ink)}
/* requirements/license strip (2026-09-05, replaces the one-line
   fineprint): three quiet left-aligned columns under the CTA */
.closer__facts{
  margin:64px auto 0;padding-top:30px;border-top:1px solid var(--line);
  width:min(880px,100%);display:grid;gap:28px;
  grid-template-columns:repeat(3,1fr);text-align:left}
.closer__facts dt{
  font-size:.78rem;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--glass)}
.closer__facts dd{
  margin:8px 0 0;font-size:.92rem;line-height:1.55;color:var(--ink-2)}
@media (max-width:720px){.closer__facts{grid-template-columns:1fr;gap:22px}}
.foot{padding:28px var(--pad) 44px;text-align:center;
  font-size:.85rem;color:var(--ink-2);border-top:1px solid var(--line)}

/* ── reduced motion: everything just sits in its finished state ── */
@media (prefers-reduced-motion:reduce){
  .scene{height:auto !important}
  .scene__pin{position:static;height:auto;min-height:0;padding-block:96px}
  .hero__hint span{animation:none}
}

/* Link out of the homepage's three-question teaser to the full /faq. */
.faq__more{margin-top:28px;font-size:.98rem}

/* Language switcher — same markup as on the prose pages, on black. */
.langbar{
  display:flex;gap:18px;flex-wrap:wrap;justify-content:center;
  padding:20px var(--pad);border-top:1px solid var(--line);
  font-size:.82rem;
}
.langbar a{color:var(--ink-2);text-decoration:none}
.langbar a:hover{color:var(--ink);text-decoration:underline}
.langbar a[aria-current]{color:var(--ink);font-weight:600;text-decoration:none;cursor:default}

/* ── production legal footer (added at promotion, 2026-09-05) ───── */
/* .wrap only exists so the shared footer markup is identical here and on
   the prose pages; this page's .foot already has its own side padding. */
.foot .wrap{max-width:1000px;margin-inline:auto}
.foot__note{max-width:60ch;margin-inline:auto;line-height:1.6}
.foot__mark{font-weight:600;color:var(--ink)}
.foot__links{display:flex;gap:20px;justify-content:center;flex-wrap:wrap;margin:10px 0 12px}
.foot__links a{color:var(--ink-2);text-decoration:none}
.foot__links a:hover{color:var(--ink);text-decoration:underline}
