/* BY THE STANDARD. Shared design layer plus the landing page's own rules.
   Tokens are the single source of truth; nothing hard-codes a colour. */

/* BY THE STANDARD: shared design layer.
   Dark is the default world. Light is an explicit choice on data-bts, so a host
   theme can never override the brand. */
:root{
  /* Tied explicitly to the toggle below, not left to the OS's own
     preference — the page's <meta color-scheme> tag only says both are
     supported, not which is active. Without this, native browser chrome
     (scrollbars, form controls) follows the system setting instead of
     this page's own, and can end up fighting it. */
  color-scheme:dark;
  --bg:#000;        --fg:#fff;
  --s1:#0A0A0A;     --s2:#141414;     --s3:#1A1A1A;
  --line:#1F1F1F;   --line2:#2A2A2A;  --line-ctl:#6B6B64;
  --mute:#A8A8A8;   --faint:#858583;
  --accent:#E6FA24;                   /* fill only */
  --on-accent:#000;
  --accent-ink:#E6FA24;               /* accent as ink, hairline, focus */
  --ok:#8FE04A;     --warn:#FFC24D;     --danger:#FF4D3D;
  --grain-op:.025;  --grain-blend:normal;

  --disp:'Archivo','Arial Narrow',system-ui,sans-serif;
  --txt:'Inter',system-ui,-apple-system,sans-serif;
  --gut:22px; --max:1320px;
  --ease:cubic-bezier(.16,1,.3,1);
}
/* Volt as text on a light ground is 1.04:1, so on light the accent may only be
   a fill. As ink it becomes neutral silver: emphasis by weight, not by hue. */
:root[data-bts="light"]{
  color-scheme:light;
  --bg:#F2F2F0;     --fg:#0A0A0A;
  --s1:#E9E9E6;     --s2:#E1E1DE;     --s3:#D9D9D6;
  --line:#D6D6D2;   --line2:#C2C2BE;  --line-ctl:#787873;
  --mute:#5C5C57;   --faint:#5C5C54;
  --accent:#E6FA24;
  --on-accent:#000;
  --accent-ink:#5E6260;
  --ok:#3E7A18;     --warn:#8A5A00;     --danger:#C7311F;
  --grain-op:.035;  --grain-blend:multiply;
}
*{box-sizing:border-box}
/* a standalone file gets no host reset, and display:flex beats the hidden attribute */
[hidden]{display:none!important}
html{background:var(--bg)}
body{
  margin:0;background:var(--bg);color:var(--fg);
  font-family:var(--txt);font-size:16px;line-height:1.6;
  -webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent;
  overflow-x:hidden;
  transition:background 320ms var(--ease),color 320ms var(--ease);
}
/* Above .page (z-index:1), not below it — every section's own background
   is transparent, so sitting behind .page let the grain show through them
   naturally, but the hero paints its own opaque fill (it has to: body
   itself is a fixed black regardless of theme, so the hero needs a real
   background, not transparency, to show the right colour in light mode).
   That opaque fill blocked the grain within the hero specifically, which
   read as the hero being a visibly flatter, slightly different shade than
   the rest of the page. Pointer-events stay off and opacity stays low, so
   sitting above everything doesn't cost anything else. */
#grain{
  position:fixed;inset:0;z-index:2;pointer-events:none;
  opacity:var(--grain-op);mix-blend-mode:var(--grain-blend);
  background-repeat:repeat;background-size:128px 128px;
}
.page{position:relative;z-index:1}
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gut)}
p{margin:0}
img{max-width:100%}
h1,h2,h3,h4{font-family:var(--disp);text-transform:uppercase;margin:0;font-stretch:76%}
h1{font-weight:900;line-height:.86;letter-spacing:-.03em;font-size:clamp(38px,7vw,86px)}
h2{font-weight:800;line-height:.96;letter-spacing:-.025em;font-size:clamp(26px,4.2vw,50px)}
h3{font-weight:800;line-height:1.02;letter-spacing:-.015em;font-size:clamp(19px,2.3vw,27px)}
h4{font-weight:700;line-height:1.1;letter-spacing:.02em;font-size:14px}

.label{font-size:10.5px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);margin:0}
.label.on{color:var(--accent-ink)}
.body{color:var(--mute);max-width:64ch}
.num{font-variant-numeric:tabular-nums}

/* the wordmark's trailing dash: closes a statement, one per screen */
.us{display:inline-block;width:.38em;height:.082em;background:var(--accent-ink);margin-left:.15em;vertical-align:baseline}

button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible,[role=button]:focus-visible,[role=switch]:focus-visible,[role=tab]:focus-visible{outline:2px solid var(--accent-ink)!important;outline-offset:3px}

/* nav */
nav{position:sticky;top:env(safe-area-inset-top,0px);z-index:60;
  background:color-mix(in srgb,var(--bg) 86%,transparent);border-bottom:1px solid var(--line)}
.nav-in{display:flex;align-items:center;justify-content:space-between;gap:16px;height:60px}
.nav-l{display:flex;align-items:center;gap:14px;min-width:0}
.brand{display:block;height:22px;width:auto;flex:none}
.brand.on-light,:root[data-bts="light"] .brand.on-dark{display:none}
:root[data-bts="light"] .brand.on-light{display:block}

/* generic dark/light image swap — same mechanism as .brand above, just not
   tied to that one class, so any logo mark anywhere (member-page nav
   brands, the corner-home link, the sign-in gate's mark) can use it without
   a bespoke rule on every page. The volt mark reads as near-invisible on a
   light ground; mark-light.png is the dark ink version for that case. */
.on-dark{display:block}
.on-light{display:none}
:root[data-bts="light"] .on-dark{display:none}
:root[data-bts="light"] .on-light{display:block}
.nav-t{font-size:10.5px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nav-r{display:flex;align-items:center;gap:10px;flex:none}
#theme{width:38px;height:38px;flex:none;padding:0;cursor:pointer;background:none;
  border:1px solid var(--line2);color:var(--mute);display:inline-flex;align-items:center;justify-content:center;
  transition:border-color 160ms var(--ease),color 160ms var(--ease)}
#theme:hover{border-color:var(--accent-ink);color:var(--accent-ink)}
/* one half-filled disc, not two swapped icons — rotating it 180° reads as
   the same object turning over to its other side, day to night */
#theme svg{width:15px;height:15px;display:block;transition:transform 550ms cubic-bezier(.3,.7,.2,1)}
:root[data-bts="light"] #theme svg{transform:rotate(180deg)}

/* theme switch: a circular reveal spreading from the toggle button, via the
   View Transitions API — gated on html.theme-vt so it only ever runs for
   our own trigger (theme.js), never any other transition. Disable the
   default cross-fade so only this clip-path grow plays. */
html.theme-vt::view-transition-old(root),
html.theme-vt::view-transition-new(root){animation:none;mix-blend-mode:normal}
html.theme-vt::view-transition-new(root){animation:themeReveal .82s cubic-bezier(.7,0,.2,1)}
@keyframes themeReveal{
  from{clip-path:circle(0 at var(--tx,50%) var(--ty,50%))}
  to{clip-path:circle(150vmax at var(--tx,50%) var(--ty,50%))}
}
@media(prefers-reduced-motion:reduce){
  html.theme-vt::view-transition-new(root){animation:none}
}

/* Page-to-page navigation — the browser's own cross-document View
   Transition, not a JS-driven one: this at-rule is the opt-in itself (both
   the page being left and the page being entered need it present, which a
   shared stylesheet gives for free) — "navigation: auto" covers every
   same-origin link click and back/forward, no per-page wiring needed.
   Unsupported browsers just keep today's plain navigation; nothing here
   requires feature-detection. */
@view-transition{navigation:auto}

/* Plain (ungated) ::view-transition-*(root) here, so this is the default
   for an ordinary page load; html.theme-vt above still wins on specificity
   for the one same-document transition that needs its own animation. A
   soft dissolve, deliberately — not a slide or a zoom, which would call
   attention to the nav/content reflowing between two different pages'
   layouts; a fade reads as "the same site, new page," which is what this
   is for. Also quietly covers for the brief incorrect-width flash on nav
   paint some pages show before the shared nav settles: the crossfade
   blends across it instead of showing it as a hard cut. */
::view-transition-old(root),::view-transition-new(root){animation-duration:.22s;animation-timing-function:cubic-bezier(.4,0,.2,1)}
@media(prefers-reduced-motion:reduce){
  ::view-transition-old(root),::view-transition-new(root){animation:none}
}

/* member nav: small avatar + name, linking to /profile — shared by every
   signed-in page's top bar (learn, profile itself) */
.pme{display:inline-flex;align-items:center;gap:8px;color:var(--faint);text-decoration:none;
  font-size:12px;transition:color 140ms var(--ease)}
.pme:hover{color:var(--fg)}
.pavatar-nav{width:22px;height:22px;border-radius:50%;object-fit:cover;flex:none;
  border:1px solid var(--line2);background:var(--s2)}

/* a persistent way home while a gated page hasn't shown its real nav bar
   yet — present through the auth check and the sign-in prompt, then gone
   the moment the real app (with its own brand mark) is on screen, so there
   is never a second logo competing with the first. */
.corner-home{position:fixed;top:24px;left:24px;z-index:50;display:block;
  opacity:.9;transition:opacity 140ms var(--ease)}
.corner-home:hover{opacity:1}
.corner-home img{height:19px}
#app:not([hidden]) ~ .corner-home{display:none}

/* controls */
.btn{font-family:var(--txt);font-size:11px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  background:var(--accent);color:var(--on-accent);border:0;padding:0 28px;height:50px;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  transition:transform 120ms var(--ease);text-decoration:none;white-space:nowrap}
.btn:active{transform:scale(.98)}
.btn.ghost{background:none;color:var(--mute);border:1px solid var(--line-ctl)}
.btn.ghost:hover{border-color:var(--accent-ink);color:var(--accent-ink)}
.btn.sm{height:42px;padding:0 18px;font-size:10px}
.btn.block{width:100%}
.btn[disabled]{opacity:.45;cursor:default}

.field{display:block;width:100%;height:52px;background:var(--s2);color:var(--fg);
  border:1px solid var(--line-ctl);padding:0 16px;font:inherit;font-size:15px;border-radius:0}
.field::placeholder{color:var(--faint)}
.field:focus{border-color:var(--accent-ink);outline:none;box-shadow:0 0 0 1px var(--accent-ink)}

.pill{display:inline-block;font-size:10px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  border:1px solid var(--line2);color:var(--faint);padding:6px 11px;white-space:nowrap}
.pill.on{border-color:var(--accent-ink);color:var(--accent-ink)}
.pill.fill{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}

/* the mock frame: every screen below is a labelled specimen, not a live page */
.spec{margin-bottom:clamp(54px,9vh,104px)}
.spec-head{display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap;
  padding-bottom:12px;margin-bottom:0;border-bottom:1px solid var(--line)}
.spec-head .n{font-family:var(--disp);font-stretch:76%;font-weight:800;font-size:11px;letter-spacing:.18em;color:var(--accent-ink)}
.spec-head .t{font-family:var(--disp);font-stretch:76%;text-transform:uppercase;font-weight:800;font-size:clamp(15px,1.9vw,20px);letter-spacing:-.005em;flex:1;min-width:180px}
.spec-head .d{font-size:12.5px;color:var(--faint);max-width:52ch;line-height:1.5}
.screen{border:1px solid var(--line);border-top:0;background:var(--s1);overflow:hidden}
.screen.pad{padding:clamp(24px,4vw,56px)}

section{border-top:1px solid var(--line);padding-block:clamp(48px,7vw,86px)}
.sec-head{margin-bottom:clamp(30px,5vw,48px)}
.sec-head h2{margin-bottom:12px}

/* video */
.video{position:relative;display:block;width:100%;aspect-ratio:16/9;background:#050505;overflow:hidden;border:0;padding:0;cursor:pointer;text-align:left}
.video img{width:100%;height:100%;object-fit:cover;display:block}
.video .scrim{position:absolute;inset:0;background:linear-gradient(to top,rgba(0,0,0,.78) 0%,rgba(0,0,0,.12) 46%,rgba(0,0,0,.34) 100%)}
.play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:76px;height:76px;background:var(--accent);display:grid;place-items:center;transition:transform 160ms var(--ease)}
.video:hover .play{transform:translate(-50%,-50%) scale(1.06)}
.play svg{width:24px;height:24px;fill:#000;margin-left:3px}
.vmeta{position:absolute;left:0;right:0;bottom:0;padding:16px 18px;display:flex;justify-content:space-between;align-items:flex-end;gap:14px}
.vmeta .vt{font-family:var(--disp);font-stretch:76%;text-transform:uppercase;font-weight:800;font-size:clamp(14px,1.7vw,20px);color:#fff;line-height:1.05}
.vmeta .vd{font-size:10.5px;font-weight:600;letter-spacing:.16em;color:rgba(255,255,255,.72);white-space:nowrap}
.vbar{position:absolute;left:0;right:0;bottom:0;height:3px;background:rgba(255,255,255,.18)}
.vbar i{display:block;height:100%;background:var(--accent);width:0}
/* the watermark that makes a leak attributable */
.wm{position:absolute;right:14px;top:12px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.34);text-align:right;line-height:1.5;pointer-events:none;user-select:none}

.grid{display:grid;gap:1px;background:var(--line);border:1px solid var(--line)}
.grid > *{background:var(--bg)}
.cols2{grid-template-columns:1fr}
.cols3{grid-template-columns:1fr}
@media(min-width:720px){.cols2{grid-template-columns:1fr 1fr}}
@media(min-width:720px){.cols3{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1040px){.cols3{grid-template-columns:repeat(3,1fr)}}

@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* player transport */
.ctrls{display:flex;align-items:center;gap:14px;padding:13px 16px;background:var(--s2);border-top:1px solid var(--line);flex-wrap:wrap}
.ctrls button{background:none;border:0;color:var(--fg);cursor:pointer;display:grid;place-items:center;width:32px;height:32px;padding:0}
.ctrls svg{width:15px;height:15px;fill:currentColor}
.track{flex:1 1 160px;height:3px;background:var(--line2);position:relative;cursor:pointer;min-width:120px}
.track i{position:absolute;inset:0 auto 0 0;background:var(--accent-ink);width:0}
.track .mk{position:absolute;top:-3px;width:2px;height:9px;background:var(--faint)}
.time{font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums;white-space:nowrap}
.cc{font-size:10px;font-weight:600;letter-spacing:.14em;border:1px solid var(--line2);padding:5px 8px;color:var(--faint);background:none;cursor:pointer;width:auto!important;height:auto!important}
.cc[aria-pressed="true"]{border-color:var(--accent-ink);color:var(--accent-ink)}
.caption{position:absolute;left:50%;transform:translateX(-50%);bottom:34px;background:rgba(0,0,0,.76);
  color:#fff;font-size:14px;padding:7px 13px;max-width:82%;text-align:center;line-height:1.4}


/* ---- landing ---- */

/* Landing v2. The film is the page: it runs on arrival, muted, and the type
   sits in it rather than beside it. Same quiet register as the member app v2. */
:root{
  --fg:#E9E9E4; --mute:#9B9B95; --faint:#858583;
  --line:#191919; --line2:#232323; --line-ctl:#6B6B64; --s1:#070707; --s2:#0D0D0D;
}
:root[data-bts="light"]{
  --fg:#1A1B18; --mute:#5C5C57; --faint:#5C5C54;
  --line:#E0E0DB; --line2:#CFCFC9; --line-ctl:#787873; --s1:#EDEDE9; --s2:#E6E6E1;
}
body{font-size:16px;line-height:1.7}
.wrap{max-width:1180px}
h2{font-family:var(--disp);font-stretch:80%;text-transform:uppercase;font-weight:800;
  font-size:clamp(22px,3vw,36px);line-height:1.02;letter-spacing:-.015em}
.lb{font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--faint);margin:0}

/* nav floats over the film until you scroll past it */
nav{border-bottom:1px solid transparent;background:transparent;transition:background 300ms var(--ease),border-color 300ms var(--ease)}
nav.stuck{background:color-mix(in srgb,var(--bg) 92%,transparent);border-bottom-color:var(--line)}
.nav-in{height:66px}
.brand{height:19px;opacity:.92}
.nav-r{gap:10px}
.nav-links{display:flex;gap:28px;align-items:center}
.nav-links a{font-size:13.5px;color:var(--mute);text-decoration:none}
.nav-links a:hover{color:var(--fg)}
@media(max-width:820px){.nav-links{display:none}}
/* Deliberately NOT inside .nav-links, and so not hidden by the rule above —
   everything else in that group is a same-page scroll anchor, expendable on
   a small screen. This is the only way into the member area, so it stays
   next to the theme toggle and the enroll button, which never hide either. */
.navsignin{display:inline-flex;align-items:center;gap:8px;font-size:13.5px;color:var(--mute);
  text-decoration:none;margin-left:18px}
.navsignin:hover{color:var(--fg)}
@media(max-width:820px){.navsignin{margin-left:0}}
#theme{border-radius:50%;width:34px;height:34px;border-color:var(--line2);color:var(--faint)}
#theme:hover{border-color:var(--faint);color:var(--fg)}

/* hero */
.hero{position:relative;min-height:clamp(540px,84svh,880px);display:flex;align-items:flex-end;
  overflow:hidden;background:var(--bg);margin-top:-66px;padding-top:66px}
/* No footage yet: the hero is built from type and an oversized, cropped echo
   of the three-bar mark, not a photo standing in for motion it can't give.
   The hero follows the site's own light/dark toggle like everything else on
   the page (background:var(--bg) above, text on var(--fg)/var(--mute)
   below) — so two source images ship for it: the dark one flattened onto
   black and screen-blended (clean against black, washes out on light), the
   light one with real alpha for a light backdrop. Whichever one doesn't
   match the current backdrop is hidden. */
.hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden}
.hero-bars{position:absolute;left:-9%;top:50%;transform:translateY(-50%);
  width:min(58vw,760px);height:auto}
.hero-bars.on-dark{mix-blend-mode:screen}
.hero-bars.on-light,:root[data-bts="light"] .hero-bars.on-dark{display:none}
:root[data-bts="light"] .hero-bars.on-light{display:block}
.hero-text{margin-left:auto;max-width:min(640px,92%)}
@media(max-width:820px){.hero-bars{width:80vw;left:-20%;opacity:.5}.hero-text{margin-left:0;max-width:100%}}
.wipe{position:absolute;inset:0;z-index:5;background:var(--accent);
  transform:translateX(-100%);pointer-events:none}
.wipe.run{animation:heroWipe 900ms cubic-bezier(.76,0,.24,1) forwards}
@keyframes heroWipe{0%{transform:translateX(-100%)}45%,55%{transform:translateX(0)}100%{transform:translateX(100%)}}
.hero .inner{position:relative;z-index:2;width:100%;padding-block:clamp(38px,7vh,86px);
  transition:opacity 420ms var(--ease)}
.hero .scroll{transition:opacity 420ms var(--ease)}
/* "Watch trailer" hands the section fully to the film: the type steps out
   of the way and the scrim lifts, rather than just unmuting behind text. */
.hero.watching .inner,.hero.watching .scroll{opacity:0;pointer-events:none}
.hero.watching .veil{opacity:.2}
.veil{transition:opacity 420ms var(--ease)}
@media(prefers-reduced-motion:reduce){.hero .inner,.hero .scroll,.veil{transition:none}}
.load{opacity:0;transform:translateY(40px);transition:opacity 600ms var(--ease),transform 600ms var(--ease)}
.load.on{opacity:1;transform:translateY(0)}
.htitle{font-family:var(--disp);font-stretch:80%;text-transform:uppercase;font-weight:900;
  font-size:clamp(40px,9.6vw,132px);line-height:.88;letter-spacing:-.035em;color:var(--fg);
  margin-block:18px 20px}
.hsub{font-size:clamp(15px,1.9vw,19px);line-height:1.6;color:var(--mute);max-width:40ch}
.hacts{display:flex;gap:12px;flex-wrap:wrap;margin-top:clamp(24px,4vh,36px);align-items:center}
.hero .lb{color:var(--faint)}

.scroll{position:absolute;left:50%;bottom:clamp(16px,3vh,30px);transform:translateX(-50%);z-index:2;
  font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--faint)}
@media(max-width:760px){.scroll{display:none}}

/* sections */
section{padding-block:clamp(66px,11vw,140px)}
section + section{border-top:1px solid var(--line)}

/* Named grid areas, not flex order. The mark only ever lives in its own
   right-hand column next to the statement — there's no good place for it
   once that column can't fit, so below 900px it's hidden outright instead
   of stacking as an orphan between the statement and the facts. */
.methodrow{display:grid;grid-template-areas:"head" "facts";
  row-gap:clamp(28px,4vw,40px)}
.methodhead{grid-area:head}
@media(min-width:900px){
  .methodrow{grid-template-columns:1fr clamp(240px,26vw,380px);
    grid-template-areas:"head mark" "facts mark";
    align-items:center;column-gap:clamp(48px,6vw,110px)}
}

/* The method's own mark, used (not redrawn) as the illustration for the
   statement beside it. mark-hd(-light).png isn't a new drawing — it's the
   real mark cropped out of the 512px app-icon export (un-premultiplied
   against its own solid black backdrop), sharp at this display size in a
   way the 160×92 nav mark.png never could be. Three real copies of that
   same file sit stacked exactly on top of each other, each clipped to one
   bar's own row; .reveal animates each one's right-hand clip inward,
   left-to-right, staggered bar by bar — top, then middle, then the third,
   finishing on its real point, not a redrawn one. Only shown once there's
   an actual right column for it to live in (see .methodrow above). */
.methodmark{display:none;position:relative;aspect-ratio:201/140}
@media(min-width:900px){
  .methodmark{display:block;grid-area:mark;width:100%;justify-self:stretch}
}
.methodmark .mbar{position:absolute;inset:0;height:100%;width:100%;
  transition:clip-path 620ms cubic-bezier(.22,.8,.3,1)}
.methodmark .b1{clip-path:inset(3.571% 100% 69.286% 0)}
.methodmark .b2{clip-path:inset(37.143% 100% 37.143% 0);transition-delay:430ms}
.methodmark .b3{clip-path:inset(69.286% 100% 3.571% 0);transition-delay:860ms}
.methodmark.reveal .b1{clip-path:inset(3.571% 0% 69.286% 0)}
.methodmark.reveal .b2{clip-path:inset(37.143% 0% 37.143% 0)}
.methodmark.reveal .b3{clip-path:inset(69.286% 0% 3.571% 0)}
@media(prefers-reduced-motion:reduce){
  .methodmark .mbar{transition:none}
  .methodmark .b1{clip-path:inset(3.571% 0% 69.286% 0)}
  .methodmark .b2{clip-path:inset(37.143% 0% 37.143% 0)}
  .methodmark .b3{clip-path:inset(69.286% 0% 3.571% 0)}
}

.stmt{font-family:var(--disp);font-stretch:80%;text-transform:uppercase;font-weight:800;
  font-size:clamp(24px,4.2vw,54px);line-height:1.02;letter-spacing:-.02em;max-width:18ch}
.stmt em{font-style:normal;color:var(--accent-ink)}
.stmt-b{color:var(--mute);max-width:52ch;font-size:15.5px;margin-top:clamp(24px,4vw,38px)}

.facts{display:grid;gap:26px 44px;grid-template-columns:repeat(2,1fr)}
@media(min-width:760px){.facts{grid-template-columns:repeat(4,1fr)}}
.facts .v{font-family:var(--disp);font-stretch:80%;font-weight:800;font-size:clamp(24px,3vw,34px);line-height:1;font-variant-numeric:tabular-nums}
.facts .k{font-size:12px;color:var(--faint);margin-top:8px}

/* curriculum, locked */
.chp{margin-bottom:clamp(30px,5vw,48px)}
.chp-h{display:flex;justify-content:space-between;gap:16px;align-items:baseline;flex-wrap:wrap;
  padding-bottom:14px;border-bottom:1px solid var(--line2);
  width:100%;background:none;border-left:0;border-right:0;border-top:0;color:inherit;font:inherit;
  text-align:left;cursor:pointer;padding-inline:0}
.chp-h:hover .n,.chp-h:hover .m{color:var(--mute)}
.chp-h .n{font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:var(--faint);flex:none}
.chp-h .t{font-family:var(--disp);font-stretch:80%;text-transform:uppercase;font-weight:800;
  font-size:clamp(20px,2.8vw,32px);line-height:1;letter-spacing:-.012em;flex:1;min-width:140px}
.chp-h .m{font-size:12.5px;color:var(--faint);white-space:nowrap}
.chp-chev{width:16px;height:16px;flex:none;stroke:var(--faint);fill:none;stroke-width:2;
  transition:transform 200ms var(--ease)}
.chp-h[aria-expanded="true"] .chp-chev{transform:rotate(180deg)}
.chp-body{padding-top:14px}
.chp .sum{font-size:14.5px;color:var(--mute);line-height:1.6;max-width:56ch;margin-top:0}
.mods{display:grid;gap:20px 34px;grid-template-columns:1fr;margin-top:20px}
@media(min-width:620px){.mods{grid-template-columns:repeat(2,1fr)}}
@media(min-width:980px){.mods{grid-template-columns:repeat(3,1fr)}}
.mod .mh{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);margin-bottom:7px}
.mod ol{list-style:none;margin:0;padding:0}
.mod li{font-size:14px;color:var(--mute);padding-block:4px;line-height:1.45}

/* the lock: structure and counts legible, content is not */
.lock{filter:blur(var(--b,7px));opacity:.5;user-select:none;-webkit-user-select:none;pointer-events:none}
.chp-h .t.lock{--b:13px}
.sum.lock{--b:5px}
.mods.lock{--b:6px}
@media(max-width:700px){.chp-h .t.lock{--b:9px}}

/* enroll */
.enroll{display:grid;gap:56px;grid-template-columns:1fr}
@media(min-width:860px){.enroll{grid-template-columns:1fr 1fr;gap:0}
  .enroll > div:first-child{padding-right:64px;border-right:1px solid var(--line)}
  .enroll > div:last-child{padding-left:64px;display:flex;flex-direction:column;justify-content:center}}
.price{font-family:var(--disp);font-stretch:80%;font-weight:800;font-size:clamp(34px,5vw,52px);line-height:1;margin-block:14px 6px}
.price small{display:block;font-family:var(--txt);font-size:12.5px;color:var(--faint);margin-top:10px;font-weight:400}
.incl{list-style:none;margin:18px 0 0;padding:0}
.incl li{font-size:14.5px;color:var(--mute);padding-block:9px;border-bottom:1px solid var(--line);line-height:1.5}
.incl li:last-child{border-bottom:0}
.incl li b{color:var(--fg);font-weight:400}
.wl form{display:flex;gap:12px;margin-top:20px;flex-wrap:wrap;max-width:460px}
.wl input{flex:1 1 220px;background:none;border:0;border-bottom:1px solid var(--line-ctl);
  color:var(--fg);font:inherit;font-size:16px;height:48px;min-width:0}
.wl input::placeholder{color:var(--faint)}
.wl input:focus{border-bottom-color:var(--accent-ink)}
.wl .btn{flex:none;align-self:center;height:40px;padding:0 20px;font-size:10px;letter-spacing:.14em}
.fine{font-size:12.5px;color:var(--faint);margin-top:16px;max-width:42ch;line-height:1.6}
.done2{display:none;gap:10px;flex-direction:column;margin-top:20px}
.done2 h3{font-family:var(--disp);font-stretch:80%;text-transform:uppercase;font-weight:800;font-size:clamp(19px,2.4vw,26px)}
.done2 p{font-size:14.5px;color:var(--mute);max-width:44ch}

.btn{height:48px;padding:0 24px;font-size:12.5px;letter-spacing:.05em;text-transform:none;font-weight:500}
.btn.ghost{border-color:rgba(255,255,255,.34);color:#F0F0EC;background:none}
.btn.ghost:hover{border-color:#fff}
section .btn.ghost{border-color:var(--line2);color:var(--mute)}
section .btn.ghost:hover{border-color:var(--faint);color:var(--fg)}

footer{border-top:1px solid var(--line);padding-block:30px 46px}
.foot-in p{font-size:12.5px;color:var(--faint);text-transform:none;letter-spacing:.02em}

/* quiet secondary capture point, off by default, toggled from HQ settings */
.stayup{border-top:1px solid var(--line);padding-block:clamp(48px,7vw,80px)}
.stayup .lb{margin-bottom:22px}
.stayup-form{display:flex;gap:0;max-width:400px;border-bottom:1px solid var(--line-ctl)}
.stayup-form input{flex:1;min-width:0;background:none;border:0;color:var(--fg);
  font:inherit;font-size:15px;height:50px;padding:0}
.stayup-form input::placeholder{color:var(--faint)}
.stayup-form input:focus{border-bottom-color:var(--accent-ink)}
.stayup-form button{flex:none;height:50px}
.stayup .fine{margin-top:14px;max-width:42ch}
.stayup .err{margin-top:12px}

@media(prefers-reduced-motion:reduce){.scroll{display:none}}


/* ---- deploy additions ---- */

/* staging only: the hero is a real YouTube embed instead of the type/icon
   treatment. Full-bleed, cropped via object-fit-style overscan, our own
   controls only — the iframe never shows YouTube's own chrome (controls=0). */
.ythero{position:absolute;inset:0;z-index:0;overflow:hidden;background:#000}
.ythero iframe{position:absolute;top:50%;left:50%;width:100%;height:100%;
  min-width:177.78vh;min-height:56.25vw;transform:translate(-50%,-50%);pointer-events:none}
/* a Shorts (9:16) source needs the inverse cover-fit math: scale off width
   first, let height overscan and crop — this is what "fills full width on
   any device" actually requires for a portrait source in a landscape hero. */
.ythero.portrait iframe{min-width:56.25vh;min-height:177.78vw}
.veil{position:absolute;inset:0;z-index:1;
  background:linear-gradient(to top,rgba(0,0,0,.86) 0%,rgba(0,0,0,.3) 46%,rgba(0,0,0,.5) 100%)}
.ytctrls{position:absolute;right:clamp(16px,3vw,34px);bottom:clamp(16px,3vh,30px);z-index:3;
  display:flex;gap:8px}
.ytbtn{width:44px;height:44px;border-radius:50%;border:1px solid rgba(255,255,255,.6);
  /* these controls sit over moving video, where no contrast ratio can be
     guaranteed against the frame behind them. The scrim is opaque enough that
     the white glyph is measured against the scrim rather than the footage:
     #fff on rgba(0,0,0,.72) over any frame stays above 4.5:1. */
  background:rgba(0,0,0,.72);color:#fff;display:grid;place-items:center;cursor:pointer;padding:0;
  font-size:12px;font-weight:600;letter-spacing:.04em}
.ytbtn:hover{border-color:#fff;background:rgba(0,0,0,.85)}
.ytbtn svg{width:15px;height:15px;fill:currentColor}

.skip{position:absolute;left:12px;top:-60px;z-index:200;background:var(--accent);color:var(--on-accent);
  padding:11px 18px;font-size:13px;font-weight:500;text-decoration:none;transition:top 140ms var(--ease)}
.skip:focus{top:12px}
main:focus{outline:none}

/* honeypot: off screen rather than display:none, which bots skip */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.err{color:var(--warn);font-size:13.5px;margin-top:12px;max-width:42ch;line-height:1.6}
.wl form[hidden],.fine[hidden],.done2[hidden]{display:none}
.done2{display:flex}
.btn[disabled]{opacity:.5;cursor:default}


/* ---------- the site gate ----------
   A soft privacy curtain, not a security boundary: nothing behind it on the
   landing page is sensitive (no pricing, no real curriculum). It exists so
   the site can sit quiet before a deliberate public announcement. Toggled
   from the admin console's Settings tab, backed by config/site.public. */
.gate{min-height:100dvh;display:grid;place-items:center;padding:24px;background:var(--bg)}
.gatebox{width:100%;max-width:300px;text-align:center}
#gateicon{background:none;border:0;padding:12px;margin:-12px auto 28px;cursor:pointer;
  display:flex;align-items:center;justify-content:center;min-width:44px;min-height:44px}
#gateicon img{height:20px;width:auto;opacity:.92;display:block}
.gatebox h1{font-family:var(--disp);font-stretch:80%;text-transform:uppercase;font-weight:800;
  font-size:19px;letter-spacing:.005em;margin-bottom:0}
/* invisible until tapped (mobile has no keyboard for the silent listener to
   catch): tapping the icon reveals this and focuses it, which raises the
   on-screen keyboard. Unlocks the instant the value hashes to a match. */
.gate-pass-field{display:block;width:100%;background:none;border:0;border-bottom:1px solid var(--line-ctl);
  color:var(--fg);font:inherit;font-size:13px;text-align:center;letter-spacing:.03em;
  height:44px;padding:0;margin-top:38px}
#gatecapture{margin-top:38px}
.gate-pass-field::placeholder{color:var(--faint)}
.gate-pass{display:flex;gap:0;width:100%;border-bottom:1px solid var(--line-ctl)}
.gate-pass input{flex:1;min-width:0;background:none;border:0;color:var(--fg);font:inherit;font-size:13px;
  height:44px;padding:0;letter-spacing:.02em}
.gate-pass input::placeholder{color:var(--faint)}
.gate-pass input:focus{color:var(--fg)}
.gate-pass button{flex:none;height:44px;padding:0 16px;font-size:10px}
.gate .err{margin-top:14px;font-size:11.5px}
/* staff sign-in, same pattern as HQ — used where a page needs the real
   staff/{email} boundary rather than the soft passcode curtain above (the
   staging editorial preview, not the public landing gate). */
.gate-google{display:block;margin:22px auto 0;background:none;border:0;color:var(--faint);
  font:inherit;font-size:10px;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;padding:6px}
.gate-google:hover{color:var(--mute)}
#gatecapture .gate-label{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--faint);margin-bottom:14px}
