/* ============================================================
   SABAI STRIKING — homepage styles (jade temple direction)
   Portable static CSS. No build step. Edit tokens in :root.
   Direction: dark green stone + antique gold, Thai cave temple,
   lightly illuminated as you scroll. Reverent restraint.
   ============================================================ */

/* ---------- self-hosted fonts (D-001: no external runtime deps) ----------
   D-018: Cinzel + EB Garamond are OUT — "tacky… too performative", and no
   italics anywhere. Target: clear, calm, professional, clean. One family
   carries the whole page; weight, size, and case do the work a second
   typeface used to do. Swap candidates by changing --fd/--ft below. */
@font-face{
  font-family:"Marcellus";
  src:url("../assets/fonts/Marcellus-400.woff2") format("woff2");
  font-weight:400;font-display:swap;
}
@font-face{
  font-family:"Instrument Sans";
  src:url("../assets/fonts/InstrumentSans-var.woff2") format("woff2");
  font-weight:400 700;font-display:swap;
}
@font-face{
  font-family:"Archivo";
  src:url("../assets/fonts/Archivo-var.woff2") format("woff2");
  font-weight:300 800;font-display:swap;
}

/* ---------- design tokens ---------- */
:root{
  /* TYPE — the only two lines to touch when swapping the candidate (OPEN #24)
     Elliot 2026-07-17: Archivo is now the STANDARD header face site-wide ("make Archivo
     the standard header. i'm still seeing too much marcellus everywhere"). This one line
     flips every --fd header from Marcellus to the grotesque. Marcellus @font-face is left
     loaded but now UNUSED — remove it + its preload when convenient. Supersedes V5. */
  --fd:"Archivo",-apple-system,BlinkMacSystemFont,sans-serif;            /* display */
  --ft:"Instrument Sans",-apple-system,BlinkMacSystemFont,sans-serif;    /* text    */
  /* PHTHALO-TINTED DARKS — Elliot 2026-07-17: "we drifted almost entirely away from the
     phthalo green. let's start there… give the doc more hues of phthalo green if it fits
     visually" + "ease the background darkening by 10%".
     This is the D-041 resolution in practice: phthalo fails as a LIT surface (he rejected
     it in the nav — nothing fire-lit is turquoise) but is CORRECT as the cool SHADOW end
     of the palette. Warm gold/ember light over a cool phthalo base reads as firelit stone,
     which also de-wizards the embers he flagged (orange orbs on PURE black = fire-magic;
     the same orange over cool stone = firelight). Each token is shifted blue-green (green
     highest, blue above red = phthalo lean) AND lifted ~10% off the old near-black.
     These four tokens tint the entire site, so this is the "start there" dial — render,
     he points, adjust saturation/lightness from here. */
  --void:#0A0F0C;            /* page base — was #0A0D0B; phthalo hue, only ~10% lifted */
  --stone:#0E1611;
  --stone-2:#131C16;
  --plate:#0C1C15;           /* the green plate behind the logo lockup, now phthalo */
  --bone:#ECE7D8;
  --bone-dim:#C9C4B0;
  --muted:#8F8C7D;
  --muted-2:#8B8877;  /* small-caps labels — keep ≥4.5:1 on the darkest surfaces (WCAG AA) */
  --gold:#D5BD61;            /* approved brand gold (BRAND_SYSTEM.md) */
  --gold-bright:#EAD387;
  --gold-deep:#9A833C;
  --ember:#DD7A22;           /* warm light accent — glows only, not surfaces */
  --ember-soft:rgba(221,122,34,0.45);
  --line:rgba(213,189,97,0.16);
  --line-2:rgba(213,189,97,0.32);
  --easer:cubic-bezier(0.22,1,0.36,1);
  --gut:clamp(1.5rem,5vw,4rem);
  --maxw:1240px;
  --sy:0px;                  /* scroll offset (JS) */
  --p:0;                     /* scroll progress 0..1 (JS) */
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  background:var(--void);
  color:var(--bone);
  font-family:var(--ft);
  font-weight:400;
  font-size:1.03rem;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
::selection{background:var(--gold);color:var(--void)}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
:where(a,button):focus-visible{outline:2px solid var(--gold-bright);outline-offset:3px;border-radius:2px}
.hero,.band,.stats,.forwho,.sanctum{scroll-margin-top:78px}

.skip{
  position:absolute;left:1rem;top:-4rem;z-index:100;
  background:var(--gold);color:var(--void);padding:0.7em 1.2em;border-radius:2px;
  font-family:var(--fd);font-size:0.75rem;letter-spacing:0.07em;text-transform:uppercase;
  transition:top .3s var(--easer);
}
.skip:focus-visible{top:1rem}

/* ============ THE CAVE (fixed, scroll-lit background) ============ */
.cave{position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none}
.cave__bg{
  position:absolute;inset:0;
  /* Elliot's backdrop, mirror-tiled 3-up (2823x1672) so `cover` never over-zooms */
  background-image:url("../assets/backdrop-wide.jpg");
  background-size:cover;background-position:center top;background-repeat:no-repeat;
}
.cave__bg::after{
  content:"";position:absolute;inset:0;
  /* tinted phthalo, darkness kept near original (2026-07-17): the ~10% lift comes from
     the base tokens, not from lightening this overlay — this only shifts its HUE green */
  background:linear-gradient(180deg,rgba(8,17,14,0.53),rgba(7,15,12,0.68));
}
/* ⚠ THE PARALLAX WAS DEAD FROM THE DAY IT WAS WRITTEN (found 2026-07-17, Elliot: "look
   into an issue… talking about parallax rendering on scroll. I feel like I see it, but
   it's saying it's not there").
   JS sets --sy as `y + 'px'` — a LENGTH. The old value here was
   `calc(var(--sy) * -0.14px)` = length × length, which CSS math forbids (at most ONE
   operand may carry a unit). The parser rejected the whole declaration, so transform
   computed to `none` at every scroll position. Verified: --sy updated 0->1500->3000 while
   the transform never left `none`.
   He was right that he saw SOMETHING move: `--p` is unitless and does work, so
   .cave__glow's opacity really does respond to scroll. Two effects, one alive, one dead.
   Multiply the length by a plain NUMBER. Do not re-add a unit to the multiplier. */
.cave__lights{
  position:absolute;left:0;right:0;top:0;height:320vh;
  transform:translateY(calc(var(--sy) * -0.14));will-change:transform;
}
/* PERF: no filter:blur() here. A radial-gradient with a transparent falloff is
   already soft — the blur cost Safari ~27% of its frames and bought nothing
   visible. Measured: p95 62ms → see worklog 2026-07-16. Look is unchanged. */
/* Elliot 2026-07-17: "phthalo green core, warm gold outer glow" for the embers.
   Each glow now runs PHTHALO-GREEN at the centre -> antique gold at the mid -> transparent
   at the edge. Because these screen-blend (add light), the cool core reads as a green heart
   inside a gold halo — a temperature gradient like a flame's cool centre, and the thing
   that ties the embers to the new phthalo base instead of floating as orange fire.
   glow--c and glow--d are GONE (quantity halved). No orange left in these two. */
.glow{position:absolute;border-radius:50%;mix-blend-mode:screen;opacity:var(--o,0.12)}
/* toned down 2026-07-17 (Elliot: "tone down the embers") — layer opacity ~halved:
   0.13/0.12 -> 0.07/0.065. Colour/shape unchanged; they're just quieter now. */
.glow--a{width:40vmax;height:40vmax;left:-12vmax;top:28vh;background:radial-gradient(circle,rgba(20,86,60,0.42),rgba(213,189,97,0.30) 46%,transparent 68%);--o:0.07;animation:flick 8s ease-in-out infinite}
.glow--b{width:34vmax;height:34vmax;right:-10vmax;top:88vh;background:radial-gradient(circle,rgba(20,86,60,0.40),rgba(213,189,97,0.32) 46%,transparent 66%);--o:0.065;animation:flick 10s ease-in-out infinite 1s}
/* .cave--calm — book.html: fewer, dimmer embers (Elliot 2026-07-17: "reduce them to
   30% quantity 50% opacity" on this page). One ember at half opacity; the second off. */
.cave--calm .glow--b{display:none}
.cave--calm .glow--a{--o:0.035}
@keyframes flick{
  0%,100%{opacity:var(--o,0.12)}
  45%{opacity:calc(var(--o,0.12) * 0.72)}
  70%{opacity:calc(var(--o,0.12) * 1.12)}
}

.cave__motes{position:absolute;inset:0}
.mote{
  position:absolute;bottom:-4vh;width:3px;height:3px;border-radius:50%;
  background:radial-gradient(circle,var(--gold-bright),rgba(234,211,135,0));
  opacity:0;will-change:transform,opacity;
}
@keyframes rise{
  0%{transform:translateY(0) translateX(0);opacity:0}
  10%{opacity:.7}
  90%{opacity:.5}
  100%{transform:translateY(-108vh) translateX(var(--dx,10px));opacity:0}
}

.cave__vignette{
  position:absolute;inset:0;
  /* phthalo-tinted, darkness near original (2026-07-17) — hue shift only */
  background:radial-gradient(120% 90% at 50% 42%, transparent 54%, rgba(5,12,10,0.76) 100%);
  box-shadow:inset 0 0 22vh 8vh rgba(4,10,8,0.64);
}
/* Elliot 2026-07-16: "the spotlight is nice. It makes it feel like a special thing, but
   it's just a little too bright in the background." Keep the shape and the scroll
   response; take the intensity down — 0.12 → 0.075 at source, and a shallower scroll
   ramp so it never blows out at the bottom of the page. */
.cave__glow{
  position:absolute;inset:0;
  background:radial-gradient(72% 55% at 50% 28%, rgba(221,122,34,0.075), transparent 72%);
  /* PERF: no transition. JS rewrites --p on every scroll frame, so a .3s
     transition restarted itself ~60x/sec and never once finished. */
  opacity:calc(0.34 + var(--p) * 0.34);mix-blend-mode:screen;
}

/* PERF: grain now lives INSIDE .cave (see index.html), not over the whole page.
   As a fixed z-60 overlay with mix-blend-mode:overlay it forced every pixel of
   every section to be re-composited on every scroll frame — the single most
   expensive thing on the page. Inside the cave it blends against the backdrop
   only, which is where the texture was doing its work anyway. */
.grain{
  position:absolute;inset:0;z-index:5;pointer-events:none;opacity:0.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ============ layout ============ */
.page{position:relative;z-index:1}
.wrap{width:min(var(--maxw),100% - var(--gut)*2);margin-inline:auto}
.band{padding-block:clamp(5.5rem,11vw,9.5rem);position:relative}
.band--tight{padding-block:clamp(4rem,8vw,6.5rem)}
/* book.html: the routes directory joins straight into the intake — the two stacked
   band paddings left a near-empty screen between them (Elliot 2026-07-17: "excessive
   space and screen time"). Collapse the join. */
.band--flush-b{padding-block-end:clamp(1.4rem,2.5vw,2rem)}
#intake.band{padding-block-start:clamp(1rem,2vw,1.6rem)}
/* Breathing room above/below the title (Elliot 2026-07-18): the section sits right
   under the sticky nav and the title fed straight into the hub diagram with no lead-in. */
#where.band{padding-block-start:clamp(6rem,11vw,9rem)}
/* Soft dark scrim behind dense text so the cave never washes out reading.
   Elliot 2026-07-16: "the gray box behind ways to train. The edges are too strong, they
   need to be dissolved on the top and on the side." Cause: the old ellipse was 80%/100%
   of the box with its falloff ending at 78% OF THE RADIUS — so it was still ~16% opaque
   at the left/right edges and ~29% at the top, and the element boundary chopped it into
   a rectangle. Fix: a bigger element with a smaller ellipse inside it, so the scrim
   reaches ZERO before it reaches any edge. Nothing to clip = nothing to see. */
.act{position:relative}
.act::before{
  content:"";position:absolute;inset:-38% -26%;z-index:-1;
  background:radial-gradient(56% 56% at 50% 50%, rgba(5,9,5,0.85), rgba(5,9,5,0) 76%);
}

.eyebrow{
  font-family:var(--ft);font-size:0.7rem;font-weight:600;text-transform:uppercase;
  letter-spacing:0.22em;color:var(--gold);display:inline-flex;align-items:center;gap:0.9em;
}
.eyebrow::before{content:"";width:1.8rem;height:1px;background:var(--gold);opacity:0.7}

.title{font-family:var(--fd);font-weight:500;text-transform:uppercase;line-height:1.12;letter-spacing:0.02em;color:var(--bone)}
h2.title{font-size:clamp(1.9rem,4.4vw,3.4rem)}
.title .g{color:var(--gold)}
.lead{font-size:clamp(1.08rem,1.4vw,1.25rem);line-height:1.6;color:var(--bone-dim);max-width:52ch}
.muted{color:var(--muted)}
.prose{color:var(--bone-dim);max-width:54ch}

/* ornamental divider */
.divider{display:flex;align-items:center;justify-content:center;gap:1.4rem;margin-inline:auto;max-width:340px;opacity:0.9}
.divider::before,.divider::after{content:"";height:1px;flex:1;background:linear-gradient(90deg,transparent,var(--gold))}
.divider::after{background:linear-gradient(90deg,var(--gold),transparent)}
.divider svg{width:26px;height:26px;color:var(--gold);flex:none}

/* ============ buttons — gold pill, as on Elliot's header ============ */
/* Buttons — Elliot 2026-07-16 (second rework): the gilded-frame version "looks like
   an old rpg… let's try that stained glass theme in gold. less heavy feel." Modern
   gold-glass pill: translucent gold-tinted body, ONE thin border, soft glow, no
   inset chrome. Hover brightens the glass rather than filling solid. Glass reads
   without backdrop-filter (D-029); blur is enhancement. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:0.7em;
  padding:0.95em 2em;border-radius:999px;cursor:pointer;
  font-family:var(--ft);font-weight:400;font-size:0.78rem;letter-spacing:0.16em;text-transform:uppercase;
  /* Elliot 2026-07-16 round 5 — the current button, two changes only:
     "the text inside of the buttons doesn't quite look right and white" -> gold, not white
     border "a little thinner"                                          -> 0.5px hairline */
  color:var(--gold-bright);
  border:0.5px solid rgba(234,211,135,0.55);
  /* TRANSPARENT GOLDEN GLASS, "windows into something wonderful" (Elliot): a faint
     gold pane, both rims catching light, and the site's sanctum ember glowing low
     INSIDE the glass. No outer glow, light type. Reads without blur (D-029). */
  background:
    radial-gradient(85% 95% at 50% 115%, rgba(221,122,34,0.28), rgba(213,189,97,0.10) 55%, transparent 75%),
    linear-gradient(180deg, rgba(234,211,135,0.16), rgba(197,168,80,0.08));
  -webkit-backdrop-filter:blur(10px) saturate(115%);backdrop-filter:blur(10px) saturate(115%);
  text-shadow:0 1px 2px rgba(5,8,5,0.55);
  box-shadow:
    inset 0 1px 0 rgba(255,246,210,0.4),
    inset 0 -1px 0 rgba(255,220,140,0.15);
  transition:transform .4s var(--easer),box-shadow .4s ease,background .3s ease,border-color .3s ease,color .3s ease;
}
/* BREATHING — Elliot 2026-07-17: "explore making buttons breathe a little bit, in a
   sense where there's a subtle pulsing glow just to get their attention a little bit.
   Very, very subtle."
   Note this REVERSES part of D-035 ("remove the glow") — his call, made knowingly.
   Built as a separate layer whose OPACITY pulses: opacity is compositor-friendly, while
   animating box-shadow would repaint the button every frame forever (D-024 perf bar).
   8s is deliberately slow — a breath, not a blink. The ghost button does NOT breathe:
   two pulsing things side by side compete, and only the primary should ask for the eye. */
.btn::after{
  content:"";position:absolute;inset:-1px;border-radius:inherit;pointer-events:none;
  background:radial-gradient(60% 100% at 50% 50%, rgba(234,211,135,0.30), transparent 72%);
  opacity:0;animation:btn-breathe 8s ease-in-out infinite;
}
.btn{position:relative;overflow:visible}
.btn--ghost::after{animation:none;opacity:0}
/* REVERTED 2026-07-17 — he asked for a hover brightness increase, saw it, and said
   "bring it back to the way it was". Restored to the pre-change value (git 3b5bb2a).
   Do not re-add `filter:brightness()` or a lit hover glow without him asking again. */
.btn:hover::after{animation:none;opacity:0}
@keyframes btn-breathe{
  0%,100%{opacity:0.12}
  50%{opacity:0.42}
}
@media (prefers-reduced-motion:reduce){
  .btn::after{animation:none;opacity:0.15}
}
.btn .arw{transition:transform .4s var(--easer)}
/* hover: the light inside the window rises */
.btn:hover{
  transform:translateY(-2px);color:#F4E6AE;border-color:rgba(244,225,160,0.75);
  background:
    radial-gradient(90% 115% at 50% 105%, rgba(221,122,34,0.38), rgba(213,189,97,0.16) 55%, transparent 78%),
    linear-gradient(180deg, rgba(234,211,135,0.22), rgba(197,168,80,0.12));
  box-shadow:
    inset 0 1px 0 rgba(255,246,210,0.5),
    inset 0 -1px 0 rgba(255,220,140,0.22);
}
.btn:hover .arw{transform:translateX(4px)}
/* ghost: an unlit pane — the window lights up on hover */
.btn--ghost{
  font-weight:400;
  background:linear-gradient(180deg, rgba(234,211,135,0.08), rgba(197,168,80,0.04));
  color:var(--gold-bright);border-color:rgba(234,211,135,0.35);
  box-shadow:inset 0 1px 0 rgba(255,246,210,0.2);
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
.btn--ghost:hover{
  color:#FFF6DC;border-color:rgba(234,211,135,0.6);
  background:
    radial-gradient(85% 95% at 50% 115%, rgba(221,122,34,0.2), rgba(213,189,97,0.08) 55%, transparent 75%),
    linear-gradient(180deg, rgba(234,211,135,0.12), rgba(197,168,80,0.06));
  box-shadow:inset 0 1px 0 rgba(255,246,210,0.3);
}

.txtlink{
  display:inline-flex;align-items:center;gap:0.55em;font-family:var(--ft);font-weight:600;
  font-size:0.76rem;letter-spacing:0.07em;text-transform:uppercase;color:var(--gold);
  border-bottom:1px solid rgba(213,189,97,0.35);padding-bottom:3px;
  transition:gap .3s var(--easer),color .3s ease,border-color .3s ease;
}
.txtlink:hover{gap:0.85em;color:var(--gold-bright);border-color:var(--gold-bright)}

/* ============ header — Elliot's two-tier header, refined (D-013: keep & improve) ============ */
.brandmark{display:inline-flex;align-items:center}
.brandmark img{height:46px;width:auto;mix-blend-mode:lighten}
/* footer socials */
.iconrow{display:flex;align-items:center;gap:1.1rem;list-style:none}
.iconrow a{
  display:grid;place-items:center;width:34px;height:34px;color:var(--gold);
  transition:color .25s ease,transform .3s var(--easer);
}
.iconrow a:hover{color:var(--gold-bright);transform:translateY(-2px)}
.iconrow svg{width:19px;height:19px}

/* Phthalo nav: TRIED AND REVERTED (Elliot 2026-07-16). I used #0E2A1E, which is a warm
   forest green — not phthalo. Phthalo green is blue-leaning, near turquoise; his words:
   "not phthalo green… totally conflicts with the color scheme… more of a turquoise
   color… honestly, I don't like it. I think it should be reverted to before." Reverted
   to the D-028 value. Do not re-attempt without him asking. */
.mainnav{
  position:sticky;top:0;z-index:50;
  background:#08100B;   /* a step darker than --plate (Elliot 2026-07-16: "topnav a bit darker") */
  transition:background .4s ease,backdrop-filter .4s ease,box-shadow .4s ease;
}
.mainnav::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:linear-gradient(90deg,rgba(213,189,97,0.15),var(--gold) 30%,var(--gold) 70%,rgba(213,189,97,0.15));
  opacity:0.8;
}
/* Translucent on scroll (Elliot 2026-07-16). 0.74 is chosen to stay legible with
   NO backdrop blur — his Firefox doesn't render backdrop-filter (D-029), and
   @supports can't detect that (the engine claims support). Blur stays as an
   enhancement where it actually draws. */
.mainnav.is-scrolled{
  background:rgba(5,9,6,0.74);
  -webkit-backdrop-filter:blur(14px) saturate(120%);backdrop-filter:blur(14px) saturate(120%);
  box-shadow:0 12px 30px -18px rgba(0,0,0,0.8);
}
.mainnav .wrap{display:flex;align-items:center;gap:clamp(1.2rem,3vw,2.6rem);padding-block:0.55rem}
.navlinks{display:flex;align-items:center;list-style:none;margin-left:auto}
.navlinks li{display:flex;align-items:center}
.navlinks li + li::before{
  content:"";width:1px;height:0.9em;background:var(--line-2);margin-inline:1.15rem;
}
.navlinks a{
  font-family:var(--ft);font-size:0.74rem;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;
  color:var(--bone-dim);position:relative;padding:0.5em 0.2em;transition:color .25s;
}
.navlinks a::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;width:0;
  margin-inline:auto;background:var(--gold);transition:width .3s var(--easer);
}
.navlinks a:hover{color:var(--gold)}
.navlinks a:hover::after{width:100%}
.navlinks a[aria-current="page"]{
  color:var(--bone);border:1px solid var(--line-2);padding:0.45em 0.9em;border-radius:2px;
}
.navlinks a[aria-current="page"]::after{display:none}
.nav-cta{display:flex;align-items:center;gap:1rem}
/* Elliot 2026-07-17: "I don't really like the all caps up there. Let's make it normal
   capitalization." Nav CTA only — the body buttons stay uppercase. Tracking comes down
   with the caps: 0.16em is tuned for uppercase and looks gappy in sentence case. */
.nav-cta .btn{
  padding:0.75em 1.6em;font-size:0.82rem;
  text-transform:none;letter-spacing:0.04em;
}
.navtoggle{display:none;background:none;border:1px solid var(--line-2);border-radius:2px;padding:0.5rem 0.65rem;cursor:pointer}
.navtoggle span{display:block;width:20px;height:2px;background:var(--gold);margin:4px 0;transition:.3s}

/* ============ hero (temple doorway) ============ */
.hero{
  position:relative;display:grid;place-items:center;overflow:hidden;isolation:isolate;
  min-height:calc(100vh - 120px);   /* fallback for browsers without svh */
  min-height:calc(100svh - 120px);
}
.hero__inner{position:absolute;inset:0}
.hero__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
/* darken + desaturate the training footage so it reads as ambience behind the
   headline, and the temple palette holds. The sanctum glow layers over this. */
.hero__video{filter:brightness(0.55) saturate(0.85) contrast(1.03)}
.hero__inner::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    linear-gradient(180deg, rgba(6,9,6,0.55), transparent 30%, transparent 62%, rgba(5,8,5,0.9) 100%),
    radial-gradient(90% 80% at 50% 45%, transparent 40%, rgba(5,8,5,0.55) 100%);
}
/* ⚠ THIS IS THE ORIGINAL GLOW. DO NOT REWRITE IT. Elliot, 2026-07-17, after four
   rewrites: "all i asked you to do was take what we had before, change the shape, and
   lower the opacity."
   So that is exactly and only what happened here. The three radial gradients below are
   the originals, byte for byte, at their original positions and stops. Two edits:
     1. SHAPE  — the element is now a tall arch box (border-radius crown, standing on the
                 floor) instead of full-bleed `inset:0`. His: "a nice tall arch window of
                 light onto the hero" / "i'm talking about the SHAPE of the glow and what
                 it covers".
     2. OPACITY — 0.40/0.42/0.28 -> 0.16/0.17/0.11. His: "very subtle", "not too bright",
                 "not blocking the text".
   mix-blend-mode:screen is the ONLY addition, and it is load-bearing: it is what the
   site's other lights already use (`.glow`, `.cave__glow`). Screen can only ADD
   luminance, so lowering the alpha yields dimmer LIGHT instead of brown film. Without it,
   low-alpha gold normal-blended over the video turns to muddy haze — his "water stain".
   If this needs changing: adjust the three alphas, or the arch's width/height/radius.
   Do NOT restructure it. */
.hero__sanctum{
  position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  /* 2026-07-17 — "it's too small": 720px/74vw -> 940px/88vw, full height. */
  width:min(940px,88vw);height:100%;z-index:0;
  border-radius:50% 50% 0 0 / 34% 34% 0 0;
  mix-blend-mode:screen;
  /* 2026-07-17 — "you took barely visible too far": the alphas were cut to ~40% of the
     originals (0.40/0.42/0.28 -> 0.16/0.17/0.11). Back up to ~65% — 0.26/0.27/0.18 —
     still clearly below the version he called too bright, no longer invisible.
     THESE THREE NUMBERS AND THE WIDTH/HEIGHT ABOVE ARE THE DIALS. Nothing else. */
  background:
    radial-gradient(46% 52% at 50% 62%, rgba(234,211,135,0.26), transparent 66%),
    radial-gradient(40% 46% at 50% 46%, rgba(217,96,31,0.27), transparent 70%),
    radial-gradient(70% 80% at 50% 100%, rgba(217,96,31,0.18), transparent 72%);
}
.hero__motes{position:absolute;inset:0;z-index:1}
.hero__arch{display:none}
.hero__content{position:relative;z-index:3;text-align:center;padding:0 var(--gut);max-width:min(880px,92vw)}
.hero__content::before{
  content:"";position:absolute;inset:-40% -30%;z-index:-1;
  background:radial-gradient(60% 60% at 50% 55%, rgba(5,9,5,0.55), transparent 72%);
}
.hero__eyebrow{justify-content:center;display:flex}
/* V5 (Elliot 2026-07-17): the big brand wordmark goes grotesque (Archivo, heavy);
   section headers stay Marcellus. Archivo is already vendored. This is the one place the
   grotesque applies — the hero mark — everything else keeps --fd. Weight 700 + tight
   tracking is what reads as "fight poster / athletic" instead of "carved temple". */
.hero__title{
  /* Elliot 2026-07-17: V5 hero "too wide too heavy" — weight 700 -> 500 (lighter) and
     -0.01em tracking (tighter). Archivo is an intrinsically wide grotesque, so if it's
     STILL too wide after this, the real fix is a condensed face (Oswald) — needs vendoring. */
  font-family:"Archivo",sans-serif;font-weight:500;text-transform:uppercase;letter-spacing:-0.01em;line-height:1.0;
  font-size:clamp(2.7rem,7.8vw,6.4rem);margin:1.3rem 0 0;color:var(--bone);
  text-shadow:0 2px 40px rgba(217,96,31,0.35),0 0 2px rgba(0,0,0,0.4);
}
.hero__title .g{display:block;color:var(--gold);text-shadow:0 2px 50px rgba(213,189,97,0.5)}
/* Elliot 2026-07-17: "the text legibility is still not that great… make that text a
   little closer to true white. Not quite true white, but a little brighter."
   #F4F1E8 — brighter than --bone (#ECE7D8), deliberately short of #FFF so it still reads
   as warm bone in a fire-lit room rather than a UI label. The text-shadow does the other
   half of the work: colour alone can't hold contrast over a moving video, and a soft dark
   shadow buys legibility without brightening the type further. The glow itself also came
   down (see .hero__sanctum) — the legibility fix is all three, not one. */
.hero__sub{
  margin:1.5rem auto 0;font-size:clamp(1.05rem,1.35vw,1.2rem);line-height:1.6;
  color:#F4F1E8;max-width:42ch;
  text-shadow:0 1px 3px rgba(4,7,4,0.75), 0 0 18px rgba(4,7,4,0.45);
}
.hero__sub b{font-weight:600;color:var(--gold)}
.hero__cta{margin-top:2.4rem;display:flex;gap:1rem;justify-content:center;flex-wrap:wrap}
/* "If you are:" strip — kept from Elliot's current site */
.forwho{
  position:relative;z-index:2;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:rgba(5,9,5,0.45);text-align:center;padding-block:1.5rem;
}
.forwho p{font-size:clamp(1.15rem,2.4vw,1.7rem);color:var(--bone-dim)}
/* Width follows the current word (set by the rotor in main.js) so the sentence
   always reads as one line — a fixed min-width stretched short words into islands
   (Elliot's circled spacing complaint, 2026-07-16). */
.forwho .slot{
  font-family:var(--fd);font-weight:400;white-space:nowrap;
  letter-spacing:0.06em;color:var(--gold);display:inline-block;text-align:center;
  transition:width .45s var(--easer);
}
.forwho .slot span{display:inline-block;transition:opacity .4s ease,transform .4s var(--easer)}

/* photo placeholder (arched) — a labeled slot for Elliot's real photography */
.ph{
  position:relative;overflow:hidden;border:1px solid var(--line);
  background:
    radial-gradient(120% 90% at 70% 12%, rgba(221,122,34,0.20), transparent 55%),
    linear-gradient(160deg,#161A14,#0A0D0B 72%);
}
/* A real photo fills the frame edge to edge. His portrait is ~2:3 in a 3:4 frame, so
   cover crops ~13% of the height; the y-offset spends that crop on the background above
   his head instead of centring and clipping his hair. */
.ph img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 22%;display:block;
}
.ph::after{
  content:"";position:absolute;inset:0;opacity:0.08;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.ph__label{
  position:absolute;left:1.4rem;bottom:1.4rem;right:1.4rem;font-family:var(--fd);
  font-size:0.62rem;letter-spacing:0.1em;text-transform:uppercase;color:var(--muted);
  display:flex;align-items:center;gap:0.7em;
}
.ph__label::before{content:"";width:1.4rem;height:1px;background:var(--gold);flex:none}
.ph--arch{border-radius:50% 50% 4px 4px / 26% 26% 4px 4px}
/* Vertical portrait frame — sized to a 3:4 photo, capped so the face stays human-scale
   in the two-column coach split (Elliot, 2026-07-16). */
.ph--portrait{aspect-ratio:3/4;width:min(400px,100%);margin-inline:auto;border-radius:3px}

/* ============ stats ============ */
.stats{
  position:relative;z-index:2;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:rgba(5,9,5,0.42);
}
.stats .wrap{display:grid;grid-template-columns:repeat(4,1fr);padding-block:0}
/* 3-up since "15 Years Muay Thai" was cut (Elliot, 2026-07-16) */
.stats .wrap.stats--3{grid-template-columns:repeat(3,1fr)}
.stat{padding:clamp(2rem,3.5vw,3rem) 1rem;text-align:center;position:relative}
/* Elliot 2026-07-17: "I'm not seeing the divider I asked for by the 100%." Both dividers
   were in fact present and measured identical (1px, 92.35px, x=448/832 @1280) — but at
   var(--line) (16% alpha gold) against a backdrop whose brightness varies across the bar,
   they fell under the threshold where he'd notice them. Not missing: under-powered.
   0.16 -> 0.34, scoped to the stat bar so --line stays as-is everywhere else. */
.stat + .stat::before{content:"";position:absolute;left:0;top:24%;height:52%;width:1px;background:rgba(213,189,97,0.34)}
.stat__num{font-family:var(--fd);font-weight:400;letter-spacing:0.01em;font-size:clamp(2.4rem,4.6vw,3.8rem);line-height:1;color:var(--bone)}
.stat__num .u{color:var(--gold)}
.stat__lab{margin-top:0.7rem;font-family:var(--ft);font-size:0.66rem;letter-spacing:0.1em;text-transform:uppercase;color:var(--muted)}

/* ============ split (coach) ============ */
.split{display:grid;grid-template-columns:0.85fr 1.15fr;gap:clamp(2.5rem,5vw,5rem);align-items:center}
.split .ph{min-height:clamp(380px,48vw,580px)}
.split .ph--portrait{min-height:0}   /* aspect-ratio governs the portrait frame */
.sabai-note{
  margin-top:1.8rem;color:var(--bone-dim);
  border-left:2px solid var(--gold);padding:0.5rem 0 0.5rem 1.1rem;max-width:44ch;
}
.sabai-note b{font-family:var(--ft);font-weight:600;font-size:0.9em;letter-spacing:0.08em;color:var(--gold)}

/* ============ mission (carved inscription) ============ */
.inscription{text-align:center;max-width:860px;margin-inline:auto}
.inscription .title{font-size:clamp(1.9rem,4.4vw,3.5rem);line-height:1.1;max-width:22ch;margin-inline:auto;text-wrap:balance}
.inscription em{color:var(--gold);text-shadow:0 0 40px rgba(213,189,97,0.35)}

/* ============ lineage (signature: the lamp line) ============ */
.lineage-head{display:grid;grid-template-columns:1fr 1fr;gap:2rem;align-items:end;margin-bottom:clamp(3rem,6vw,5rem)}
.thread{position:relative;margin-left:clamp(0.5rem,2vw,1.5rem)}
.thread__spine{position:absolute;left:13px;top:16px;bottom:16px;width:2px;background:var(--line);overflow:hidden}
.thread__fill{
  position:absolute;left:0;top:0;width:100%;height:0;
  background:linear-gradient(var(--gold-bright),var(--ember));transition:height 1.8s var(--easer);
}
.lineage.in .thread__fill{height:100%}
.node{position:relative;padding:0 0 clamp(2.8rem,5vw,3.8rem) clamp(3rem,5vw,3.6rem)}
.node:last-child{padding-bottom:0}
.node__lamp{
  position:absolute;left:2px;top:4px;width:24px;height:24px;border-radius:50%;
  background:var(--void);border:2px solid var(--line-2);transition:all .6s ease;z-index:2;
}
.lineage.in .node__lamp{
  border-color:var(--gold);background:radial-gradient(circle,var(--ember),#3A1C0A);
  box-shadow:0 0 0 5px rgba(217,96,31,0.10),0 0 22px 2px rgba(217,96,31,0.6);
}
/* LIVING LAMPS — Elliot 2026-07-17: "I'm also not seeing the glow by the nodes in my
   lineage… I'd like those nodes to look a little more living." A static glow DID already
   exist here; what was missing is motion, which is what "alive" actually meant.
   Same mechanic as the buttons: a separate layer pulsing on OPACITY (compositor-cheap),
   never box-shadow (repaints every frame — D-024). Each lamp is offset by its own delay
   so they breathe independently, like separate flames rather than one blinking strip. */
.node__lamp::after{
  content:"";position:absolute;inset:-9px;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle, rgba(217,96,31,0.55), transparent 70%);
  opacity:0;transition:opacity .5s ease;
}
/* ⚠ A PULSE THAT TRAVELS THE TIMELINE — Elliot 2026-07-17: "The glowing pattern on the
   lineage thing doesn't really make any sense. It's kind of just random. Let's have it
   follow a kind of timeline-esque pathway showing the years going from year to year,
   glowing, glowing, glowing, going down to the bottom."
   He was right that it was random, and here's why: I'd staggered them with NEGATIVE
   delays (scattered phase, no direction) AND the nth-child indices were off by one —
   `.thread__spine` is the FIRST child of `.thread`, so the nodes are children 2..5 and
   every delay landed on the wrong lamp. Two bugs making literal noise.
   Now: POSITIVE, evenly increasing delays so one pulse walks 2005 -> 2012 -> ... -> you.
   The keyframe is mostly dark (the flare lives in the first 30%) so the eye reads a
   travelling signal rather than four things throbbing together. 5s cycle = ~1.7s for the
   pulse to walk the years, then a beat of quiet before it repeats.
   ⚠ Indices are 2..5 BECAUSE OF THE SPINE. Add a node and they all shift. */
/* `backwards` matters: without it, a lamp sits at its un-animated opacity:0 during its
   stagger delay — measured lamp 4 at 0.00 for its first 1.65s, a hole in the chain.
   backwards holds the 0% keyframe through the delay so every lamp starts at baseline. */
.lineage.in .node__lamp::after{animation:lamp-travel 5s ease-in-out infinite backwards}
.thread .node:nth-child(2) .node__lamp::after{animation-delay:0s}
.thread .node:nth-child(3) .node__lamp::after{animation-delay:0.55s}
.thread .node:nth-child(4) .node__lamp::after{animation-delay:1.1s}
.thread .node:nth-child(5) .node__lamp::after{animation-delay:1.65s}
/* hover: the lamp you're beside flares up and steadies */
.node:hover .node__lamp{
  border-color:var(--gold-bright);
  box-shadow:0 0 0 7px rgba(217,96,31,0.16),0 0 30px 4px rgba(217,96,31,0.8);
}
.node:hover .node__lamp::after{animation:none;opacity:0.9}
/* Pulse narrowed to the first 20% (1s of the 5s cycle). At 30% it spanned 1.5s against a
   0.55s stagger, so three lamps burned at once and it read as a throb, not a journey.
   ~1s against 0.55s = only the neighbour overlaps — the eye follows one light downward. */
@keyframes lamp-travel{
  0%{opacity:0.18}
  8%{opacity:0.9}
  20%{opacity:0.18}
  100%{opacity:0.18}
}
@media (prefers-reduced-motion:reduce){
  .lineage.in .node__lamp::after{animation:none;opacity:0.4}
}
.node--you .node__lamp{width:28px;height:28px;left:0}
.lineage.in .node--you .node__lamp{
  background:radial-gradient(circle,var(--gold-bright),var(--ember));
  box-shadow:0 0 0 6px rgba(213,189,97,0.14),0 0 34px 4px rgba(213,189,97,0.7);
}
.node__yr{font-family:var(--ft);font-weight:600;font-size:0.78rem;letter-spacing:0.1em;color:var(--gold);text-transform:uppercase}
.node__ttl{
  font-family:var(--fd);font-weight:400;text-transform:uppercase;letter-spacing:0.04em;
  font-size:clamp(1.15rem,2vw,1.55rem);margin:0.4rem 0 0.6rem;color:var(--bone);
}
.node__body{color:var(--muted);max-width:56ch}
.node__body b{color:var(--bone-dim);font-weight:600}
/* .mark — reserved for the single strongest credential in a paragraph, so it
   reads before the sentence does. Elliot 2026-07-16: Dominick Cruz. Using it on
   more than one phrase per section spends the emphasis and it stops working. */
.mark{
  color:var(--gold);font-weight:600;
  box-shadow:inset 0 -0.42em 0 rgba(213,189,97,0.11);
  /* without this the inset highlight paints only on the first line when the
     phrase wraps, which looks like a rendering bug rather than emphasis */
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
}
.node--you .node__ttl{color:var(--gold)}

/* ============ testimonials — all nine in one carousel (Elliot 2026-07-16:
   Boole's review consolidated into the rest, first in the track) ============ */
.tcite{
  font-family:var(--ft);font-weight:600;font-size:0.82rem;letter-spacing:0.12em;
  text-transform:uppercase;color:var(--gold);display:block;
}
.trole{display:block;margin-top:0.35rem;font-size:0.98rem;color:var(--muted)}

/* ============ testimonial carousel ============
   D-018: Elliot — "too many review tiles, a nice carousel may be candidate to
   replace." Treatment only: ALL NINE testimonials are still on the page (his
   2026-07-09 instruction). The carousel shows two at a time instead of stacking
   eight tiles into a wall.
   Built on scroll-snap, so it works with zero JS: it is a real scroll container.
   The JS only adds the arrows and dots. No JS → it stays swipeable. */
.tcar{position:relative;margin-top:clamp(3rem,6vw,4.5rem)}
.tgrid{
  display:grid;grid-auto-flow:column;grid-auto-columns:100%;
  gap:0;overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:none;-ms-overflow-style:none;
  padding-bottom:0.4rem;
}
.tgrid::-webkit-scrollbar{display:none}
.tgrid > .tcard{scroll-snap-align:start;margin-bottom:0}
.tcar__nav{display:flex;align-items:center;justify-content:center;gap:1.4rem;margin-top:1.8rem}
.tcar__btn{
  display:grid;place-items:center;width:42px;height:42px;flex:none;cursor:pointer;
  background:transparent;border:1px solid var(--line-2);border-radius:50%;color:var(--gold);
  transition:border-color .3s ease,color .3s ease,opacity .3s ease;
}
.tcar__btn:hover:not(:disabled){border-color:var(--gold);color:var(--gold-bright)}
.tcar__btn:disabled{opacity:0.3;cursor:default}
.tcar__btn svg{width:16px;height:16px}
.tcar__dots{display:flex;gap:0.5rem}
.tcar__dot{
  width:7px;height:7px;border-radius:50%;padding:0;cursor:pointer;
  background:var(--line-2);border:none;transition:background .3s ease,transform .3s ease;
}
.tcar__dot[aria-current="true"]{background:var(--gold);transform:scale(1.35)}
/* Unboxed (D-026, Elliot: "the testimonial boxes are ugly. no one is reading two
   reviews at a time. only one. navigation there is fine."): one centered voice per
   page, no card chrome. */
.tcard{
  padding:1.4rem clamp(1rem,6vw,4rem) 0.5rem;position:relative;text-align:center;
}
.tcard::before{
  content:"";position:absolute;left:50%;top:0;transform:translateX(-50%);
  width:3.2rem;height:2px;
  background:linear-gradient(90deg,transparent,var(--gold),transparent);
}
.tcard blockquote{color:var(--bone-dim);font-size:clamp(1.08rem,1.7vw,1.35rem);line-height:1.7;max-width:64ch;margin-inline:auto}
.tcard figcaption{margin-top:1.4rem}
.tcard .tcite{font-size:0.74rem}
.tcard .trole{font-size:0.9rem;margin-top:0.25rem}

/* ============ options (temple niches) — spotlights, not panels ============
   The "liquid glass" card is GONE (Elliot 2026-07-16). It faked glass with a bone fill
   and leaned on backdrop-filter to sell it; his Firefox draws no backdrop-filter (D-029,
   hardware-dependent — it will never start working), so what he actually saw was the
   bare construction: "grey boxes, ugly… I don't like the boxiness… I need them to be
   transparent." No fill, no border, no blur now — the cave shows through for real.
   What's left is one spotlight per niche, falling from above like light into a temple
   alcove: up at 34% behind the icon and title, OFF the body copy, wider and softer than
   the low blob it replaces ("I don't like the placement of the light. I don't like the
   size of the light").
   Hover DIMS instead of brightening — his model, verbatim: "the spotlight is there to
   get your attention. Once you get there, it should start to dim so I can read it."
   Every radius completes INSIDE the box (rx 60% × 78% falloff = 46.8% < the 50% edge),
   which is what keeps it edgeless — see .act::before for the same rule and why. */
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:1.3rem}
.niche{
  position:relative;
  border:none;box-shadow:none;
  padding:clamp(2.2rem,3vw,2.8rem) clamp(1.6rem,2.5vw,2rem) clamp(1.8rem,2.5vw,2.2rem);
  display:flex;flex-direction:column;text-align:center;
}
/* ⚠ NO `isolation:isolate` on .niche, and the light layer is z-index:0 (not -1).
   Both matter: isolation would confine ::before's blending to .niche's own backdrop —
   which is transparent — and screen-against-nothing silently degrades back to a normal
   blend, i.e. straight back to the brown stain. The children carry z-index:1 so the
   light sits under the text without needing a negative index. */
.niche > *{position:relative;z-index:1}
/* ⚠ THE LIGHT MUST BE ITS OWN LAYER, FADED BY OPACITY. Two traps, both measured, both
   of which made the spotlight SNAP instead of fade (Elliot: "the lights are still
   fading very suddenly"):
   1. CSS CANNOT INTERPOLATE GRADIENTS. `background-image` animates DISCRETELY — a
      `transition:background 2.5s` on a radial-gradient parses fine, runs nothing, and
      jumps straight to the target. Fading a layer's `opacity` is the only way; opacity
      interpolates.
   2. `.reveal` (line ~750) sets `transition:opacity/transform` and `.reveal.in` sets
      `transform:none`, both at equal specificity to a bare `.niche` and 200 lines later
      — so they silently won and killed both the timing AND the hover lift (same trap as
      D-024c). A pseudo-element is immune to `.reveal`; the lift needs `.cards` to
      outrank `.reveal.in`. */
/* ⚠ AN ACTUAL HALF CIRCLE — Elliot 2026-07-17, third pass: "I want the light to end at
   the bottom of the text. I want it to be shaped like a half circle."
   Rounds 1–2 were radial-gradient ellipses, which can only ever be a soft blob — they
   have no flat edge, so "half circle" was unreachable that way. This is a real SHAPE: an
   element with aspect-ratio 2/1 and a fully rounded top (999px 999px 0 0) = a dome whose
   bottom is a straight horizon. The sunrise reading is literal — the light is brightest
   at the horizon line and falls off upward through the dome, which is why the gradient is
   centred at 50% 100%.
   `bottom` parks that horizon at the foot of the body copy, above the link. */
.niche::before{
  content:"";position:absolute;left:50%;top:0;transform:translateX(-50%);
  /* Its flat bottom (the horizon) sits at the TITLE's baseline, not below the body copy.
     Elliot marked this himself: a red underline at each title with an arrow down to where
     the light actually was — "theese are too low". The dome now crowns the icon+title and
     the body text sits below it in clean dark ("the text can just read nicely").
     Height is tuned to the title's foot: padding(~40) + icon(38+18) + title(~22) ≈ 118px.
     Proportions are free — his: "half circle doesn't need to be true, i just need the
     horizon line and circular shape, obviously." */
  width:min(240px,80%);height:118px;
  /* lowered 2026-07-17 — his "lower it. it's too high". The horizon now falls just under
     the title rather than on its baseline. (It was at the foot of the body copy before
     that: "theese are too low" — this sits between the two.) */
  margin-top:34px;
  border-radius:999px 999px 0 0;
  z-index:0;pointer-events:none;
  mix-blend-mode:screen;   /* same reason as .hero__sanctum — without it, this IS the stain */
  background:radial-gradient(circle at 50% 100%,
    rgba(213,189,97,0.30) 0%, rgba(213,189,97,0.12) 48%, transparent 78%);
  /* "slightly dissolve the bottom edge" — the horizon stays a horizon (it's still a
     defined line, per "i just need the horizon line"), just no longer a razor cut. */
  -webkit-mask-image:linear-gradient(180deg,#000 84%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 84%,transparent 100%);
  /* NOT var(--easer) here: it's easeOutQuint, which is 79% done by 1s and reads as a
     snap no matter what the duration says. A light dimming should decay evenly, so this
     curve is near-linear on purpose. Measured: ~0.5 progress at ~1.25s. */
  transition:opacity 2.5s cubic-bezier(0.37,0.24,0.63,0.76);
}
/* hover: the light yields over ~2.5s so the copy reads — his "the spotlight is there to
   get your attention. Once you get there, it should start to dim so I can read it."
   The lift stays quick (.4s) so the card still answers the cursor at once. */
.niche:hover::before{opacity:0.22}
.cards .niche{transition:opacity 1s var(--easer),transform .4s var(--easer)}
.cards .niche:hover{transform:translateY(-5px)}
.niche__ic{width:38px;height:38px;color:var(--gold);margin:0 auto 1.1rem}
.niche__ttl{font-family:var(--fd);font-weight:400;text-transform:uppercase;font-size:clamp(1.1rem,1.9vw,1.35rem);letter-spacing:0.04em;margin-bottom:0.9rem;color:var(--bone)}
.niche__body{color:var(--muted);font-size:1.02rem;flex:1}
.niche__link{margin-top:1.6rem}

/* ============ benefits — "Compact Strip" ============
   Elliot 2026-07-17: the 2x2 grid "is very big"; he picked Direction B from the
   proposal — a single tight 4-up row, small icon, condensed one-line body. Roughly
   half the vertical footprint. Bodies shortened to their essence (he approved that
   copy by picking B). */
.benefits{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(1.4rem,3vw,2.2rem)}
.benefit{border-top:1px solid var(--line-2);padding-top:1.1rem}
.benefit__ic{width:22px;height:22px;color:var(--gold);margin-bottom:0.9rem}
.benefit__ttl{font-family:var(--fd);font-weight:400;text-transform:uppercase;font-size:clamp(0.95rem,1.3vw,1.1rem);letter-spacing:0.03em;margin-bottom:0.55rem;color:var(--bone)}
.benefit__body{color:var(--muted);font-size:0.84rem;line-height:1.55}
/* Elliot 2026-07-17: "lightly animate the iconography in that B." Each line-icon DRAWS
   ITSELF once, staggered left-to-right; a one-time flourish, not a loop (loops read
   wizardy). 240 exceeds every path length here, so it draws in one clean pass.
   ⚠ TRIGGER: fires off `.benefits.drawn` (a dedicated observer on the GRID, added when
   the strip is actually 25% on screen) — NOT off each card's own `.reveal.in`. The first
   version did the latter, and each card reveals when its BOTTOM enters, while the icon
   sits at the card's TOP — so every icon finished drawing before it scrolled into view
   and he never saw it ("animation not showing"). Default offset is 0 (icons always
   visible if JS/observer never runs).
   Icons also REDRAW on hover, so the effect is visible on demand, alongside the lift. */
@keyframes icon-draw{0%{stroke-dashoffset:240}100%{stroke-dashoffset:0}}
.benefit__ic path,.benefit__ic circle{stroke-dasharray:240;stroke-dashoffset:0}
.benefits.drawn .benefit__ic path,.benefits.drawn .benefit__ic circle{animation:icon-draw 1.2s var(--easer) backwards}
.benefits.drawn .benefit:nth-child(2) .benefit__ic path,.benefits.drawn .benefit:nth-child(2) .benefit__ic circle{animation-delay:.14s}
.benefits.drawn .benefit:nth-child(3) .benefit__ic path,.benefits.drawn .benefit:nth-child(3) .benefit__ic circle{animation-delay:.28s}
.benefits.drawn .benefit:nth-child(4) .benefit__ic path,.benefits.drawn .benefit:nth-child(4) .benefit__ic circle{animation-delay:.42s}
.benefit__ic{transition:color .4s ease,transform .4s var(--easer)}
.benefit:hover .benefit__ic{color:var(--gold-bright);transform:translateY(-2px)}
.benefit:hover .benefit__ic path,.benefit:hover .benefit__ic circle{animation:icon-draw .85s var(--easer)}
@media(prefers-reduced-motion:reduce){
  .benefits.drawn .benefit__ic path,.benefits.drawn .benefit__ic circle,
  .benefit:hover .benefit__ic path,.benefit:hover .benefit__ic circle{animation:none}
}

/* ============ train anywhere — "Home base + I come to you" (D2) ============
   Replaces the "Coastline" horizon-line (2026-07-17). Elliot: the line read as a
   TIMELINE (sequence with order) and couldn't stack on mobile — but these are four
   PARALLEL places, one a home base. This structure says the actual offer: the Training
   Center is the spotlit anchor (address shown); an "or I come to you" divider; then the
   three travel spots. Each place has its own icon (temple/pillars, wave, house,
   dumbbell) — an icon reads as "a place" with no implied order. Stacks anchor-over-three.
   Only the hub carries a spotlight; the spokes are calm, so the hierarchy is legible. */
.twh{max-width:720px;margin:4rem auto 0}
.twh__hub{position:relative;text-align:center;display:flex;flex-direction:column;align-items:center;gap:0.5rem;padding:1.8rem 1rem 2rem;overflow:hidden}
/* hub spotlight — a half-dome that completes INSIDE the box (D-040 rule) so it never
   slices into a rectangle; screen-blended so it reads as light, not a brown film. */
.twh__hub::before{
  content:"";position:absolute;left:50%;top:0;transform:translateX(-50%);
  width:min(300px,78%);height:150px;margin-top:6px;border-radius:999px 999px 0 0;
  z-index:0;pointer-events:none;mix-blend-mode:screen;
  background:radial-gradient(circle at 50% 100%,rgba(213,189,97,0.22),rgba(213,189,97,0.08) 50%,transparent 78%);
  -webkit-mask-image:linear-gradient(180deg,#000 82%,transparent 100%);mask-image:linear-gradient(180deg,#000 82%,transparent 100%);
}
.twh__hub>*{position:relative;z-index:1}
.twh__ic{color:var(--gold)}
.twh__ic--hub{width:46px;height:46px;margin-bottom:0.4rem}
.twh__hublab{font-family:var(--ft);font-size:0.62rem;letter-spacing:0.16em;text-transform:uppercase;color:var(--gold)}
.twh__hubname{font-family:var(--fd);font-weight:400;text-transform:uppercase;font-size:clamp(1.35rem,2.4vw,1.7rem);color:var(--bone);letter-spacing:0.02em}
.twh__hubadd{color:var(--muted);font-size:0.92rem;margin-top:0.15rem}
.twh__or{display:flex;align-items:center;gap:1rem;margin:1.2rem auto 2rem;max-width:440px;color:var(--gold);font-family:var(--ft);font-size:0.64rem;letter-spacing:0.16em;text-transform:uppercase}
.twh__or::before,.twh__or::after{content:"";height:1px;flex:1;background:linear-gradient(90deg,transparent,var(--gold-deep))}
.twh__or::after{background:linear-gradient(90deg,var(--gold-deep),transparent)}
.twh__spokes{display:grid;grid-template-columns:repeat(3,1fr);gap:1.6rem}
.twh__spoke{text-align:center;display:flex;flex-direction:column;align-items:center;gap:0.5rem;padding:0.4rem}
.twh__spoke .twh__ic{width:30px;height:30px;transition:transform .4s var(--easer),color .3s ease}
.twh__spoke:hover .twh__ic{transform:translateY(-3px);color:var(--gold-bright)}
.twh__sname{font-family:var(--fd);text-transform:uppercase;font-size:1rem;color:var(--bone-dim);letter-spacing:0.02em}
.twh__slab{font-family:var(--ft);font-size:0.6rem;letter-spacing:0.12em;text-transform:uppercase;color:var(--muted)}
@media(max-width:560px){.twh__spokes{grid-template-columns:1fr;gap:2rem}}

/* ============ sanctum (final cta) ============ */
.sanctum{position:relative;overflow:hidden;text-align:center;padding-block:clamp(5rem,9vw,7.5rem) clamp(3.5rem,6vw,5rem)}
/* Elliot 2026-07-16: "I have the same edge problem around the plan built around you
   area." Cause: the lower gradient was centred at 74% with a 50% radius, so its falloff
   ran past 100% and `overflow:hidden` on .sanctum sliced it flat — a hard horizontal
   line where light should have faded to nothing. Fix: every radius now reaches full
   transparency INSIDE the section box. Nothing to clip = no edge.
   Also his: "that spotlight should be maybe a little wider" — 46%/52% -> 62%/70%. */
.sanctum__glow{
  position:absolute;inset:0;z-index:0;
  background:
    radial-gradient(62% 44% at 50% 44%, rgba(234,211,135,0.26), transparent 68%),
    radial-gradient(70% 34% at 50% 60%, rgba(217,96,31,0.22), transparent 70%);
  opacity:0.4;
}
/* Arrive lit, then yield. Elliot: "the spotlight is there to get your attention. Once
   you get there, it should start to dim so I can read it… it should take about maybe two
   or three seconds to fade out." So: a fast rise as the section lands, a short hold at
   full, then a slow ~2s decay to a level the lead copy reads cleanly over. `forwards`
   parks it dim — it must not bounce back to full and start fighting the text again. */
.sanctum.in .sanctum__glow{animation:sanctum-yield 3s var(--easer) forwards}
@keyframes sanctum-yield{
  0%{opacity:0.4}
  12%{opacity:1}
  30%{opacity:1}
  100%{opacity:0.3}
}
@media (prefers-reduced-motion:reduce){
  .sanctum.in .sanctum__glow{animation:none;opacity:0.3}
}
.sanctum .wrap{position:relative;z-index:2;max-width:760px}
.sanctum .title{font-size:clamp(2.2rem,5.5vw,4.4rem)}
.sanctum .lead{margin:1.6rem auto 0;text-align:center}
.sanctum .btn{margin-top:2.2rem}

/* ============ contact ============ */
#contact.band{padding-block-start:clamp(2.5rem,5vw,4rem)}
.contact-grid{display:grid;grid-template-columns:0.9fr 1.1fr;gap:clamp(2rem,5vw,4rem);align-items:stretch}
.cinfo{display:flex;flex-direction:column;gap:0}
.crow{display:flex;gap:1.1rem;align-items:flex-start;padding:1.4rem 0;border-bottom:1px solid var(--line)}
.crow:first-child{padding-top:0}
.crow:last-child{border-bottom:none}
.crow .ic{width:22px;height:22px;color:var(--gold);flex:none;margin-top:4px}
.crow .clab{font-family:var(--ft);font-size:0.64rem;letter-spacing:0.1em;text-transform:uppercase;color:var(--muted-2)}
.crow .cval{font-size:1.15rem;color:var(--bone);margin-top:0.25rem}
.crow a.cval{display:block}
.crow a.cval:hover{color:var(--gold)}
.mapwrap{position:relative;border:1px solid var(--line);border-radius:3px;overflow:hidden;min-height:340px}
.mapwrap iframe{width:100%;height:100%;min-height:340px;border:0;filter:saturate(0.72) sepia(0.22) brightness(0.88);transition:filter .45s ease}
/* brightens to near-natural on hover (Elliot 2026-07-16) */
.mapwrap:hover iframe{filter:saturate(0.95) sepia(0.05) brightness(1)}
.mapwrap:hover::after{opacity:0.15}
/* Soft overlay so the bright map sits into the dark page instead of sticking out
   (Elliot, 2026-07-16). Natural color kept — the old grey filter stays dead (D-025);
   this warms the whites toward the bone palette and vignettes the edges into the page.
   pointer-events:none keeps the map usable. */
.mapwrap::after{
  content:"";position:absolute;inset:0;pointer-events:none;transition:opacity .45s ease;
  background:
    linear-gradient(rgba(24,18,8,0.24), rgba(24,18,8,0.24)),
    linear-gradient(180deg, rgba(5,9,5,0.42), rgba(5,9,5,0.1) 34%, rgba(5,9,5,0.1) 66%, rgba(5,9,5,0.48)),
    radial-gradient(130% 105% at 50% 50%, transparent 46%, rgba(5,9,5,0.55) 100%);
}

/* ============ book.html — the mode switch drives the whole page ============
   Elliot 2026-07-17: one control stands on its own. Returning students flip to
   "Already training" and go straight to the schedule — they never see the intake.
   New students stay on "New here", fill the intake, and the schedule is revealed
   only after they submit (they tell me their plan before they pick a time).
   Visibility is driven by data-mode on #main (set by main.js); default (no JS) shows
   everything, so the page still works without scripting. */
.bookswitch{display:inline-flex;gap:3px;padding:5px;border:1px solid var(--line-2);border-radius:999px;background:rgba(8,12,9,0.55)}
.bookswitch__opt{
  font-family:var(--ft);font-size:0.82rem;letter-spacing:0.08em;text-transform:uppercase;color:var(--bone-dim);
  padding:0.7em 1.8em;border-radius:999px;cursor:pointer;background:none;border:none;
  transition:color .25s ease,background .25s ease;position:relative;
}
.bookswitch__opt:hover{color:var(--bone)}
.bookswitch__opt.is-active{color:var(--gold-bright);background:rgba(213,189,97,0.16);box-shadow:inset 0 1px 0 rgba(255,246,210,0.12)}
.bookswitch__opt:focus-visible{outline:2px solid var(--gold-bright);outline-offset:3px}
.bookswitch-hint{color:var(--muted);font-size:0.98rem;margin:1.1rem auto 0;max-width:46ch;min-height:1.4em;transition:opacity .2s ease}
/* the fallback folds directly under the switch (Elliot: "just kill it" — the separate
   intake head + fallback block are gone; these two lines carry the context). Hidden in
   returning mode and once the intake is sent. */
.bookswitch-fallback{color:var(--muted);font-size:0.9rem;margin:0.45rem auto 0;max-width:46ch}
.bookswitch-fallback a{color:var(--gold);border-bottom:1px solid var(--line-2)}
.bookswitch-fallback a:hover{color:var(--gold-bright);border-color:var(--gold-bright)}
#main[data-mode="returning"] #bookFallback,
#main.intake-sent #bookFallback{display:none}

/* one control, whole-page reveal (see main.js) */
#main[data-mode="returning"] #intake{display:none}
#main[data-mode="new"]:not(.intake-sent) #schedule{display:none}
#main.intake-sent #intakeForm{display:none}
.intake-sent-msg{display:none}
#main.intake-sent .intake-sent-msg{display:block;text-align:center;max-width:52ch;margin:0 auto clamp(1.5rem,3vw,2.2rem)}
.intake-sent-msg .title{margin-top:1rem;font-size:clamp(1.6rem,3vw,2.2rem)}
.intake-sent-msg .lead{margin:1rem auto 0;text-align:center}

/* de-boxed (D-040): the old bordered panel is gone — the calendar is the anchor now */
.sched{text-align:center;max-width:820px;margin-inline:auto}
.sched__note{color:var(--bone-dim);margin:1.1rem auto 0;max-width:48ch}
.sched__where{color:var(--muted);font-size:0.92rem;margin-top:2.4rem}
.sched__fallback{color:var(--muted);font-size:0.9rem;margin-top:1rem}
.sched__fallback a{color:var(--gold);border-bottom:1px solid var(--line-2);padding-bottom:1px}
.sched__fallback a:hover{color:var(--gold-bright);border-color:var(--gold-bright)}

/* ---- booking calendar (client-facing; mock availability, wired to Sabai Scheduling later) ---- */
.booker{max-width:480px;margin:2.2rem auto 0}
.cal__head{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.1rem}
.cal__month{font-family:var(--fd);text-transform:uppercase;letter-spacing:0.04em;font-size:1.1rem;color:var(--bone)}
.cal__nav{display:grid;place-items:center;width:36px;height:36px;border:1px solid var(--line-2);border-radius:50%;background:none;color:var(--gold);font-size:1.15rem;line-height:1;cursor:pointer;transition:border-color .2s ease,color .2s ease}
.cal__nav:hover:not(:disabled){border-color:var(--gold);color:var(--gold-bright)}
.cal__nav:disabled{opacity:0.3;cursor:default}
.cal__nav:focus-visible{outline:2px solid var(--gold-bright);outline-offset:2px}
.cal__dow{display:grid;grid-template-columns:repeat(7,1fr);gap:0.4rem;margin-bottom:0.5rem}
.cal__dow span{text-align:center;font-family:var(--ft);font-size:0.6rem;letter-spacing:0.1em;text-transform:uppercase;color:var(--muted-2)}
.cal__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:0.4rem}
.cal__day{position:relative;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:1px solid transparent;border-radius:4px;background:none;color:var(--bone-dim);font-family:var(--ft);font-size:0.95rem;cursor:pointer;transition:border-color .2s ease,color .2s ease,background .2s ease}
.cal__day.is-empty{visibility:hidden;cursor:default}
.cal__day.is-off{color:var(--muted);opacity:0.32;cursor:default}
.cal__day.is-avail{border-color:var(--line-2)}
.cal__day.is-avail:hover{border-color:var(--gold);color:var(--gold-bright)}
.cal__day.is-avail::after{content:"";position:absolute;bottom:5px;left:50%;transform:translateX(-50%);width:3px;height:3px;border-radius:50%;background:var(--gold);opacity:0.65}
.cal__day.is-sel{background:rgba(213,189,97,0.18);border-color:var(--gold);color:var(--gold-bright)}
.cal__day.is-sel::after{opacity:0}
.cal__day:focus-visible{outline:2px solid var(--gold-bright);outline-offset:2px}

.slots{margin-top:2rem}
.slots__label{font-family:var(--ft);font-size:0.66rem;letter-spacing:0.12em;text-transform:uppercase;color:var(--gold);text-align:center;margin-bottom:1.1rem}
.slots__list{display:flex;flex-wrap:wrap;gap:0.6rem;justify-content:center}
.slots__list .slot{padding:0.55em 1.15em;border:1px solid var(--line-2);border-radius:999px;background:none;color:var(--bone-dim);font-family:var(--ft);font-size:0.92rem;cursor:pointer;transition:border-color .2s ease,color .2s ease,background .2s ease}
.slots__list .slot:hover:not(:disabled){border-color:var(--gold);color:var(--gold-bright)}
.slots__list .slot.is-sel{background:rgba(213,189,97,0.16);border-color:var(--gold);color:var(--gold-bright)}
.slots__list .slot:disabled{opacity:0.3;text-decoration:line-through;cursor:default}
.slots__list .slot:focus-visible{outline:2px solid var(--gold-bright);outline-offset:2px}

.bconfirm{display:flex;align-items:center;justify-content:center;gap:1.3rem;flex-wrap:wrap;margin-top:2.2rem}
.bconfirm__txt{font-family:var(--fd);text-transform:uppercase;letter-spacing:0.03em;color:var(--bone);font-size:1.05rem}
.bdone{max-width:44ch;margin:0.5rem auto 0}

@media(max-width:760px){
  .routes{grid-template-columns:1fr;gap:0}
}

/* ============ intake form (book.html — Sabai Scheduling, client half) ============ */
.intake-head{text-align:center;max-width:52ch;margin:0 auto clamp(2.2rem,4vw,3rem)}
.intake{
  max-width:760px;margin-inline:auto;display:flex;flex-direction:column;gap:1.4rem;
}
.fs{
  border:1px solid var(--line);border-radius:4px;padding:clamp(1.3rem,2.5vw,1.8rem);
  background:rgba(8,12,9,0.5);display:flex;flex-direction:column;gap:1.1rem;
}
.fs__lg{
  font-family:var(--fd);font-weight:400;text-transform:uppercase;font-size:0.98rem;letter-spacing:0.05em;color:var(--bone);
  padding:0;
}
.fs__hint{color:var(--muted);font-weight:400;font-size:0.9rem}
.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:1.1rem}
.fld{display:flex;flex-direction:column;gap:0.45rem}
.fld__l{font-size:0.9rem;color:var(--bone-dim)}
.fld__l b{color:var(--gold);font-weight:600}
.fld__note{font-size:0.85rem;color:var(--muted);line-height:1.5}
.intake .in{
  font-family:var(--ft);font-size:1rem;color:var(--bone);width:100%;
  background:rgba(4,6,4,0.6);border:1px solid var(--line-2);border-radius:3px;
  padding:0.7em 0.85em;transition:border-color .25s ease,box-shadow .25s ease;
}
.intake .in:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(213,189,97,0.14)}
.intake textarea.in{resize:vertical;min-height:2.6em}
.intake select.in{appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%23D5BD61' stroke-width='1.6'%3E%3Cpath d='m1 1 5 5 5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 0.9em center;padding-right:2.4em}

/* toggle-pill checkboxes for goals / disciplines / availability */
.chips{display:flex;flex-wrap:wrap;gap:0.6rem}
.chip{position:relative;cursor:pointer}
.chip input{position:absolute;opacity:0;width:0;height:0}
.chip span{
  display:inline-block;padding:0.5em 1em;border:1px solid var(--line-2);border-radius:999px;
  font-size:0.92rem;color:var(--bone-dim);transition:all .2s ease;
}
.chip input:checked + span{
  background:rgba(213,189,97,0.14);border-color:var(--gold);color:var(--gold-bright);
}
.chip input:focus-visible + span{outline:2px solid var(--gold-bright);outline-offset:2px}

/* radio groups */
.rgroup{border:none;padding:0;display:flex;flex-direction:column;gap:0.55rem}
.rgroup .fld__l{margin-bottom:0.2rem}
.radio{display:flex;align-items:center;gap:0.55rem;cursor:pointer;color:var(--bone-dim);font-size:0.95rem}
.radio input{accent-color:var(--gold);width:1.05em;height:1.05em;flex:none}
/* format radios sit in a row, not a column, so the fieldset stays compact */
.rgroup--row{flex-direction:row;flex-wrap:wrap;gap:0.6rem 1.4rem}

/* availability grid — Mon–Sun × Morning/Afternoon/Evening toggles. Replaces the four
   coarse chips (Elliot 2026-07-17: "needs a better input method… let users get
   specific"). Each cell is a checkbox named `availability`, so main.js aggregates them
   with no seam change; the free-text line below catches exact times. */
.avail{gap:0.7rem}
.availgrid{display:grid;grid-template-columns:auto repeat(3,minmax(0,1fr));gap:0.4rem 0.45rem;align-items:center}
.availgrid__cnr{}
.availgrid__h{font-family:var(--ft);font-size:0.6rem;font-weight:600;letter-spacing:0.09em;text-transform:uppercase;color:var(--muted-2);text-align:center;padding-bottom:0.15rem}
.availgrid__d{font-family:var(--ft);font-size:0.74rem;letter-spacing:0.08em;text-transform:uppercase;color:var(--bone-dim);padding-right:0.7rem;white-space:nowrap}
.availcell{position:relative;display:block}
.availcell input{position:absolute;opacity:0;width:0;height:0}
.availcell span{
  display:block;text-align:center;min-height:2.2em;line-height:2.2em;border:1px solid var(--line-2);border-radius:3px;
  color:var(--muted);cursor:pointer;transition:all .2s ease;
}
.availcell span::after{content:"";font-size:0.82rem;color:var(--gold-bright)}
.availcell input:checked + span{background:rgba(213,189,97,0.16);border-color:var(--gold)}
.availcell input:checked + span::after{content:"✓"}
.availcell input:focus-visible + span{outline:2px solid var(--gold-bright);outline-offset:2px}
@media(max-width:480px){
  .availgrid__d{font-size:0.68rem;padding-right:0.4rem}
  .availgrid__h{font-size:0.54rem}
}

.intake__submit{text-align:center;margin-top:0.6rem}
.intake__submit .btn{width:100%;max-width:420px}
.intake__fallback{margin-top:1rem;font-size:0.9rem;color:var(--muted)}
.intake__fallback a{color:var(--gold);border-bottom:1px solid var(--line-2)}
.intake__fallback a:hover{color:var(--gold-bright)}
.intake .in.err{border-color:var(--ember);box-shadow:0 0 0 3px rgba(221,122,34,0.16)}
@media(max-width:620px){ .fgrid{grid-template-columns:1fr} }

/* ============ footer ============ */
footer.ft{position:relative;z-index:2;background:rgba(5,9,5,0.6);border-top:1px solid var(--line);padding-block:clamp(3rem,6vw,4.5rem)}
.ft-grid{display:grid;grid-template-columns:1.5fr 1fr 1fr;gap:2.5rem}
/* logo sits on its own green plate — frame it as a deliberate plaque */
.ft .brandmark{margin-bottom:1.1rem;background:var(--plate);border:1px solid var(--line);border-radius:4px;padding:0.55rem 1.1rem}
.ft .brandmark img{height:64px;mix-blend-mode:lighten}
.ft p{color:var(--muted);max-width:36ch}
.ft .ft-h{font-family:var(--fd);font-size:0.64rem;letter-spacing:0.1em;text-transform:uppercase;color:var(--muted-2);margin-bottom:1.1rem}
.ft ul{list-style:none;display:flex;flex-direction:column;gap:0.7rem}
.ft ul a{color:var(--bone-dim);transition:color .25s}
.ft ul a:hover{color:var(--gold)}
.ft .iconrow{margin-top:1rem;flex-direction:row;flex-wrap:wrap} /* .ft ul sets column — icons stay a row */
.ft .iconrow a{border:1px solid var(--line-2);border-radius:50%;width:40px;height:40px;color:var(--bone-dim)}
.ft .iconrow a:hover{border-color:var(--gold);color:var(--gold)}
.ft-base{
  margin-top:clamp(2.5rem,5vw,3.5rem);padding-top:1.6rem;border-top:1px solid var(--line);
  display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  font-family:var(--fd);font-size:0.66rem;letter-spacing:0.06em;text-transform:uppercase;color:var(--muted-2);
}

/* ============ reveal ============ */
.reveal{opacity:0;transform:translateY(30px);transition:opacity 1s var(--easer),transform 1s var(--easer)}
.reveal.in{opacity:1;transform:none}
.reveal.d1{transition-delay:.1s}.reveal.d2{transition-delay:.2s}.reveal.d3{transition-delay:.3s}.reveal.d4{transition-delay:.4s}
/* if JS never runs, content must still be readable */
html:not(.js) .reveal{opacity:1;transform:none}

/* ============ responsive ============ */
@media(max-width:960px){
  .split,.lineage-head,.cards,.contact-grid,.ft-grid{grid-template-columns:1fr}
  .benefits{grid-template-columns:repeat(2,1fr)}   /* strip goes 4-up -> 2x2, never 1-wide-and-tall */
  .stats .wrap{grid-template-columns:repeat(2,1fr)}
  .stat:nth-child(3)::before{display:none}
  .navtoggle{display:block}
  /* collapsed bar: keep the Book pill so the band isn't an empty strip with a lone burger */
  .nav-cta{margin-left:auto;gap:0.7rem}
  .nav-cta .btn{padding:0.6em 1.2em;font-size:0.7rem}
  .mainnav .wrap{padding-block:0.45rem}
  .navtoggle{padding:0.4rem 0.55rem}
  .navlinks{
    position:absolute;top:100%;left:0;right:0;flex-direction:column;align-items:stretch;
    background:rgba(5,9,5,0.97);backdrop-filter:blur(14px);
    border-bottom:1px solid var(--line);padding-inline:var(--gut);
    max-height:0;overflow:hidden;padding-block:0;
    transition:max-height .4s var(--easer),padding-block .4s var(--easer);
  }
  .navlinks{-webkit-backdrop-filter:blur(14px)}
  .mainnav.menu-open .navlinks{max-height:70vh;padding-block:0.5rem}
  .navlinks li{display:block}
  .navlinks li + li::before{display:none}
  .navlinks a{display:block;width:100%;padding:0.95rem 0;font-size:0.85rem;border-bottom:1px solid var(--line)}
  .navlinks li:last-child a{border-bottom:none}
  .navlinks a::after{display:none}
  .navlinks a[aria-current="page"]{border:none;padding:0.95rem 0;border-bottom:1px solid var(--line);color:var(--gold);border-radius:0}
  .mainnav.menu-open .navtoggle span:nth-child(1){transform:translateY(6px) rotate(45deg)}
  .mainnav.menu-open .navtoggle span:nth-child(2){opacity:0}
  .mainnav.menu-open .navtoggle span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
  .lineage-head{gap:1rem}
  .brandmark img{height:38px}
}
@media(max-width:520px){
  .stats .wrap{grid-template-columns:1fr}
  .stat + .stat::before{display:none}
  .stat{border-top:1px solid var(--line)}
  .stat:first-child{border-top:none}
  .hero__cta{flex-direction:column;align-items:stretch}
  .hero__cta .btn{justify-content:center;min-width:0}
  .iconrow a{width:30px;height:30px}
  .iconrow svg{width:17px;height:17px}
}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{animation:none!important}
  .reveal{opacity:1;transform:none;transition:none}
  .thread__fill{transition:none;height:100%}
  .cave__lights{transform:none}
}

/* ═══════════════════════════════════════════════════════════════════════════
   LIGHT MODE (2026-07-20). Integrated site-wide across index/book/club.

   Purely ADDITIVE. Every rule below is scoped under [data-theme="light"], so the
   approved dark site above is untouched — delete this block and the file is byte-
   identical to src/css/styles.css.

   DIRECTION: cool paper + ink. The cave does not get "lightened" — it gets turned
   OFF. Light mode is the effects layer switched off: no backdrop photo, no embers,
   no motes, no vignette, no grain, no screen-blended glows. What remains is paper,
   ink, hairline rules, and the same type doing all the work.

   THE HERO IS DELIBERATELY UNTOUCHED (Elliot, 2026-07-20: "keep the hero it's
   fine"). It stays a self-contained dark video block sitting on paper. Not one
   hero rule is overridden below — check the selectors.

   ⚠ mix-blend-mode:screen CANNOT survive here. Screen over a light surface returns
   the light surface — every glow becomes invisible, not dimmer. So they are removed
   rather than recoloured. This is also where the speed comes from: ~7 compositing
   layers and an 18MB decoded backdrop texture stop being painted on every scroll frame.

   ⚠ BRAND GOLD #D5BD61 IS UNUSABLE AS INK — 1.70:1 on paper (WCAG needs 4.5).
   Light mode uses a deep gold at 5.23:1. Measured, not estimated. The bright brand
   gold survives only as a decorative hairline, never as text.
   ═══════════════════════════════════════════════════════════════════════════ */

:root[data-theme="light"]{
  --paper:#F4F5F3;           /* page base — cool off-white, not cream, not pure white */
  --paper-2:#FFFFFF;         /* raised surfaces */
  --paper-sunk:#EBEDEA;      /* recessed bands */
  --void:#F4F5F3;
  --stone:#EBEDEA;
  --stone-2:#E3E6E2;
  --plate:#10201A;           /* the one dark surface left — the logo plate */
  --bone:#151A17;            /* INK. 16.1:1 */
  --bone-dim:#3D4642;        /* body copy. 8.9:1 */
  --muted:#5C6560;           /* 5.5:1 */
  --muted-2:#5C6560;         /* 5.5:1 */
  /* PHTHALO INK (Elliot 2026-07-20 — "replace the brown gold with a visible pthalo
     green"). Measured on paper #F4F5F3; WCAG AA text floor is 4.5:1.
     This does NOT contradict D-041 (phthalo rejected in the DARK nav — "nothing fire-lit
     is turquoise"): that was phthalo as a LIT surface inside the cave. As ink on paper
     there is no fire to contradict, and it is the same hue family already tinting the
     dark base tokens, so both themes stay recognisably one brand. */
  --gold:#116152;            /* text, labels, links — 6.72:1 */
  --gold-bright:#0B3D33;     /* emphasis/hover = darker here, not brighter — 11.10:1 */
  --gold-deep:#157A66;       /* 4.79:1 — still passes */
  --gold-rule:#2E8C77;       /* 3.74:1 — DECORATIVE HAIRLINES ONLY, never text */
  --ember:#0F6B4F;
  --line:rgba(21,26,23,0.13);
  --line-2:rgba(21,26,23,0.26);
}

[data-theme="light"] body{background:var(--paper);color:var(--bone)}
[data-theme="light"] ::selection{background:var(--gold);color:var(--paper-2)}

/* ---------- THE CAVE, SWITCHED OFF (this is the whole perf story) ---------- */
[data-theme="light"] .cave__bg,
[data-theme="light"] .cave__bg::after,
[data-theme="light"] .cave__lights,
[data-theme="light"] .cave__motes,
[data-theme="light"] .cave__vignette,
[data-theme="light"] .cave__glow,
[data-theme="light"] .grain,
[data-theme="light"] .glow,
[data-theme="light"] .mote{display:none}
[data-theme="light"] .cave{background:var(--paper)}

/* dark scrims that existed only to protect text from the cave */
[data-theme="light"] .act::before{display:none}

/* ---------- nav ---------- */
[data-theme="light"] .mainnav{background:var(--paper-2);box-shadow:0 1px 0 rgba(21,26,23,0.07)}
[data-theme="light"] .mainnav::after{
  background:linear-gradient(90deg,transparent,var(--gold-rule) 30%,var(--gold-rule) 70%,transparent);
  opacity:0.9;height:1px;
}
[data-theme="light"] .mainnav.is-scrolled{
  background:rgba(255,255,255,0.88);
  box-shadow:0 8px 24px -18px rgba(21,26,23,0.5);
}
[data-theme="light"] .navlinks a{color:var(--bone-dim)}
[data-theme="light"] .navlinks a:hover{color:var(--gold)}
[data-theme="light"] .navlinks a[aria-current="page"]{color:var(--bone);border-color:var(--line-2)}
[data-theme="light"] .navtoggle span{background:var(--gold)}
@media(max-width:960px){
  [data-theme="light"] .navlinks{background:rgba(255,255,255,0.97)}
}

/* THE LOGO — logo-clear.png is a light mark using mix-blend-mode:lighten, which over
   paper renders as nothing at all. Prototype answer: keep it on its own dark plate, the
   same plaque treatment the footer already uses. This is a STOPGAP — the real fix is a
   dark-ink logo asset, which does not exist yet. [NEEDS ELLIOT] */
[data-theme="light"] .mainnav .brandmark{
  background:var(--plate);border-radius:4px;padding:0.3rem 0.7rem;
}
[data-theme="light"] .ft .brandmark{background:var(--plate);border-color:rgba(21,26,23,0.14)}

/* ---------- type ---------- */
[data-theme="light"] .title{color:var(--bone)}
[data-theme="light"] .title .g{color:var(--gold)}
[data-theme="light"] .lead,[data-theme="light"] .prose{color:var(--bone-dim)}
[data-theme="light"] .eyebrow{color:var(--gold)}
[data-theme="light"] .eyebrow::before{background:var(--gold-rule);opacity:1}
[data-theme="light"] .divider::before{background:linear-gradient(90deg,transparent,var(--gold-rule))}
[data-theme="light"] .divider::after{background:linear-gradient(90deg,var(--gold-rule),transparent)}
[data-theme="light"] .divider svg{color:var(--gold)}
[data-theme="light"] .inscription em{color:var(--gold);text-shadow:none}
[data-theme="light"] .mark{color:var(--gold);box-shadow:inset 0 -0.42em 0 rgba(17,97,82,0.14)}

/* ---------- buttons: KEEP THE GLASS PILL, in phthalo ----------
   REVISED 2026-07-20. The first light pass made a solid fill with WHITE text and dropped
   the button's shadow — Elliot: "you replaced the shadow for white and its horrible.
   shadow was fine, what needs to change is consistency in font and button style."
   Root cause: the hero's approved buttons are a translucent GLASS pill (thin border, inset
   top-highlight, tinted text), and the body buttons had become flat solid slabs — two
   button languages on one page. This restores the approved glass STRUCTURE for light,
   1:1 with the dark button, changing only the palette gold→phthalo. The inset highlight
   (the "shadow") and the tinted text are back; no white fill, no flat slab. */
/* DARK PHTHALO-GLASS buttons (Elliot 2026-07-20: "make the switch darker more like this" +
   "same change for this area" + "do phthalo glass for the topnav Book a Session too" — the
   hero-button look, applied to every light-mode .btn: body CTAs, the nav pill, the Book
   buttons on all pages). Dark green fill + white text + a light-green rim/glow. Opaque
   enough (unlike the hero's translucent-over-video version) to read dark on light paper. */
/* TRANSLUCENT phthalo glass (Elliot 2026-07-20: "more transparent like glass over the
   white, it looks very opaque"). The fill is now translucent phthalo — the white paper
   shows THROUGH it (real glass) — and a soft dark text-shadow keeps the white label legible
   even where the glass is lightest (the same trick the hero buttons use over the video). */
[data-theme="light"] .btn{
  color:#FFFFFF;
  text-shadow:0 1px 2px rgba(6,28,20,0.55);
  border:1px solid rgba(120,210,185,0.5);
  background:
    radial-gradient(90% 120% at 50% 118%, rgba(46,140,119,0.4), rgba(17,97,82,0.18) 55%, transparent 82%),
    linear-gradient(180deg, rgba(21,110,84,0.58), rgba(12,66,53,0.70));
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:
    inset 0 1px 0 rgba(210,245,232,0.45),
    0 2px 8px -3px rgba(8,30,24,0.30);
}
/* breathing pulse — light-green so it reads on the glass */
[data-theme="light"] .btn::after{
  display:block;
  background:radial-gradient(60% 100% at 50% 50%, rgba(120,210,185,0.26), transparent 72%);
}
[data-theme="light"] .btn:hover{
  color:#FFFFFF;
  border-color:rgba(143,225,200,0.72);
  background:
    radial-gradient(90% 120% at 50% 118%, rgba(46,140,119,0.5), rgba(17,97,82,0.24) 55%, transparent 84%),
    linear-gradient(180deg, rgba(24,124,94,0.68), rgba(13,74,60,0.78));
  box-shadow:
    inset 0 1px 0 rgba(210,245,232,0.55),
    0 5px 14px -4px rgba(8,30,24,0.38);
}
/* ghost: a lighter, more see-through pane of the same glass */
[data-theme="light"] .btn--ghost{
  color:#FFFFFF;
  text-shadow:0 1px 2px rgba(6,28,20,0.55);
  background:linear-gradient(180deg, rgba(21,110,84,0.44), rgba(12,66,53,0.56));
  border:1px solid rgba(120,210,185,0.42);
  box-shadow:inset 0 1px 0 rgba(210,245,232,0.34);
}
[data-theme="light"] .btn--ghost:hover{
  color:#FFFFFF;
  background:linear-gradient(180deg, rgba(24,124,94,0.56), rgba(13,74,60,0.66));
  border-color:rgba(143,225,200,0.58);
  box-shadow:inset 0 1px 0 rgba(210,245,232,0.44);
}
[data-theme="light"] .txtlink{color:var(--gold);border-bottom-color:rgba(17,97,82,0.35)}
[data-theme="light"] .txtlink:hover{color:var(--gold-bright);border-bottom-color:var(--gold-bright)}

/* ---------- bands ---------- */
/* (Glass bands REVERTED 2026-07-20 — Elliot: "I don't like it, get rid of it".) */
[data-theme="light"] .forwho{
  background:var(--paper-sunk);border-top-color:var(--line);border-bottom-color:var(--line);
}
[data-theme="light"] .forwho p{color:var(--bone-dim)}
[data-theme="light"] .forwho .slot{color:var(--gold)}
[data-theme="light"] .stats{
  background:var(--paper-2);border-top-color:var(--line);border-bottom-color:var(--line);
}
[data-theme="light"] .stat + .stat::before{background:var(--line-2)}
[data-theme="light"] .stat__num{color:var(--bone)}
[data-theme="light"] .stat__num .u{color:var(--gold)}
[data-theme="light"] .stat__lab{color:var(--muted)}
@media(max-width:520px){ [data-theme="light"] .stat{border-top-color:var(--line)} }

/* ---------- photo frames ---------- */
[data-theme="light"] .ph{
  border-color:var(--line-2);
  background:linear-gradient(160deg,var(--paper-sunk),var(--stone-2));
}
[data-theme="light"] .ph::after{display:none}
[data-theme="light"] .ph__label{color:var(--muted)}
[data-theme="light"] .ph__label::before{background:var(--gold-rule)}
[data-theme="light"] .sabai-note{color:var(--bone-dim);border-left-color:var(--gold)}
[data-theme="light"] .sabai-note b{color:var(--gold)}

/* ---------- lineage: lamps become printed marks ---------- */
[data-theme="light"] .thread__spine{background:var(--line-2)}
[data-theme="light"] .thread__fill{background:linear-gradient(var(--gold),var(--gold-deep))}
[data-theme="light"] .node__lamp{background:var(--paper);border-color:var(--line-2)}
[data-theme="light"] .lineage.in .node__lamp{
  border-color:var(--gold);background:var(--gold);box-shadow:none;
}
[data-theme="light"] .node__lamp::after{display:none}   /* the pulse is a light effect */
[data-theme="light"] .lineage.in .node--you .node__lamp{
  background:var(--gold-bright);border-color:var(--gold-bright);box-shadow:0 0 0 4px rgba(17,97,82,0.14);
}
[data-theme="light"] .node:hover .node__lamp{border-color:var(--gold-bright);box-shadow:0 0 0 5px rgba(17,97,82,0.16)}
[data-theme="light"] .node__yr{color:var(--gold)}
[data-theme="light"] .node__ttl{color:var(--bone)}
[data-theme="light"] .node__body{color:var(--muted)}
[data-theme="light"] .node__body b{color:var(--bone-dim)}
[data-theme="light"] .node--you .node__ttl{color:var(--gold)}

/* ---------- testimonials ---------- */
[data-theme="light"] .tcard blockquote{color:var(--bone-dim)}
[data-theme="light"] .tcard::before{background:linear-gradient(90deg,transparent,var(--gold-rule),transparent)}
[data-theme="light"] .tcite{color:var(--gold)}
[data-theme="light"] .trole{color:var(--muted)}
[data-theme="light"] .tcar__btn{border-color:var(--line-2);color:var(--gold)}
[data-theme="light"] .tcar__btn:hover:not(:disabled){border-color:var(--gold);color:var(--gold-bright)}
[data-theme="light"] .tcar__dot{background:var(--line-2)}
[data-theme="light"] .tcar__dot[aria-current="true"]{background:var(--gold)}

/* ---------- niches: the spotlight dome is a light effect — replaced by a card ----------
   The dome cannot be recoloured (screen blend). Rather than leave the niches as three
   unmarked columns, the structure that the light was providing — "these are three
   distinct things" — is carried by a paper card with a hairline instead. */
[data-theme="light"] .niche::before{display:none}
[data-theme="light"] .niche{
  background:var(--paper-2);border:1px solid var(--line);border-radius:4px;
}
[data-theme="light"] .cards .niche:hover{
  transform:translateY(-5px);border-color:var(--line-2);
  box-shadow:0 10px 28px -18px rgba(21,26,23,0.35);
}
[data-theme="light"] .niche__ic{color:var(--gold)}
[data-theme="light"] .niche__ttl{color:var(--bone)}
[data-theme="light"] .niche__body{color:var(--muted)}

/* ---------- benefits ---------- */
[data-theme="light"] .benefit{border-top-color:var(--line-2)}
[data-theme="light"] .benefit__ic{color:var(--gold)}
[data-theme="light"] .benefit__ttl{color:var(--bone)}
[data-theme="light"] .benefit__body{color:var(--muted)}
[data-theme="light"] .benefit:hover .benefit__ic{color:var(--gold-bright)}

/* ---------- train anywhere ---------- */
[data-theme="light"] .twh__hub::before{display:none}
[data-theme="light"] .twh__hub{
  background:var(--paper-2);border:1px solid var(--line);border-radius:4px;
}
[data-theme="light"] .twh__ic{color:var(--gold)}
[data-theme="light"] .twh__hublab{color:var(--gold)}
[data-theme="light"] .twh__hubname{color:var(--bone)}
[data-theme="light"] .twh__hubadd{color:var(--muted)}
[data-theme="light"] .twh__or{color:var(--gold)}
[data-theme="light"] .twh__or::before{background:linear-gradient(90deg,transparent,var(--gold-rule))}
[data-theme="light"] .twh__or::after{background:linear-gradient(90deg,var(--gold-rule),transparent)}
[data-theme="light"] .twh__sname{color:var(--bone-dim)}
[data-theme="light"] .twh__slab{color:var(--muted)}
[data-theme="light"] .twh__spoke:hover .twh__ic{color:var(--gold-bright)}

/* ---------- final CTA: the sanctum glow becomes a warm paper tint ----------
   Kept as a real element (it still carries the "arrive, then yield" motion) but as a
   faint warm wash rather than emitted light. */
[data-theme="light"] .sanctum{background:var(--paper-sunk)}
[data-theme="light"] .sanctum__glow{
  background:radial-gradient(70% 55% at 50% 45%, rgba(46,140,119,0.16), transparent 72%);
  opacity:0.9;
}
[data-theme="light"] .sanctum.in .sanctum__glow{animation:none;opacity:0.9}

/* ---------- contact + map ---------- */
[data-theme="light"] .crow{border-bottom-color:var(--line)}
[data-theme="light"] .crow .ic{color:var(--gold)}
[data-theme="light"] .crow .clab{color:var(--muted)}
[data-theme="light"] .crow .cval{color:var(--bone)}
[data-theme="light"] .crow a.cval:hover{color:var(--gold)}
[data-theme="light"] .mapwrap{border-color:var(--line-2)}
/* the map no longer needs to be dimmed into a dark page — show it straight */
[data-theme="light"] .mapwrap iframe{filter:saturate(0.92) brightness(1)}
[data-theme="light"] .mapwrap:hover iframe{filter:none}
[data-theme="light"] .mapwrap::after{display:none}

/* ---------- footer ---------- */
[data-theme="light"] footer.ft{background:var(--paper-2);border-top-color:var(--line)}
[data-theme="light"] .ft p{color:var(--muted)}
[data-theme="light"] .ft .ft-h{color:var(--muted)}
[data-theme="light"] .ft ul a{color:var(--bone-dim)}
[data-theme="light"] .ft ul a:hover{color:var(--gold)}
[data-theme="light"] .ft .iconrow a{border-color:var(--line-2);color:var(--bone-dim)}
[data-theme="light"] .ft .iconrow a:hover{border-color:var(--gold);color:var(--gold)}
[data-theme="light"] .ft-base{border-top-color:var(--line);color:var(--muted)}
[data-theme="light"] .iconrow a{color:var(--gold)}
[data-theme="light"] .iconrow a:hover{color:var(--gold-bright)}

/* ---------- forms + booking (book.html — carried now so site-global is one step) ---------- */
[data-theme="light"] .bookswitch{background:var(--paper-2);border-color:var(--line-2)}
[data-theme="light"] .bookswitch__opt{color:var(--bone-dim)}
[data-theme="light"] .bookswitch__opt:hover{color:var(--bone)}
/* active switch segment = the DARK phthalo-glass of the HERO buttons — white text, dark
   green fill, light rim (Elliot 2026-07-20: "make the switch darker, more like this" +
   the hero-button screenshot). Opaque fill (unlike the hero's, which is translucent over
   video) so it reads dark on the light paper. */
[data-theme="light"] .bookswitch__opt.is-active{
  color:#FFFFFF;
  text-shadow:0 1px 2px rgba(6,28,20,0.55);
  background:
    radial-gradient(90% 120% at 50% 118%, rgba(46,140,119,0.4), rgba(17,97,82,0.18) 55%, transparent 82%),
    linear-gradient(180deg, rgba(21,110,84,0.58), rgba(12,66,53,0.70));
  box-shadow:
    inset 0 0 0 1px rgba(120,210,185,0.42),
    inset 0 1px 0 rgba(210,245,232,0.4),
    0 2px 8px -2px rgba(8,30,24,0.35);
}
[data-theme="light"] .bookswitch__opt:hover{color:var(--gold)}
[data-theme="light"] .bookswitch-hint,[data-theme="light"] .bookswitch-fallback{color:var(--muted)}
[data-theme="light"] .fs{background:var(--paper-2);border-color:var(--line)}
[data-theme="light"] .fs__lg{color:var(--bone)}
[data-theme="light"] .fs__hint,[data-theme="light"] .fld__note{color:var(--muted)}
[data-theme="light"] .fld__l{color:var(--bone-dim)}
[data-theme="light"] .fld__l b{color:var(--gold)}
[data-theme="light"] .intake .in{
  /* background-COLOR, not the shorthand: the shorthand resets background-repeat to `repeat`,
     which tiled the <select> dropdown arrow across the whole control (2026-07-20). */
  background-color:var(--paper-2);border-color:var(--line-2);color:var(--bone);
}
[data-theme="light"] .intake .in:focus{border-color:var(--gold);box-shadow:0 0 0 3px rgba(17,97,82,0.16)}
[data-theme="light"] .intake select.in{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%237A6420' stroke-width='1.6'%3E%3Cpath d='m1 1 5 5 5-5'/%3E%3C/svg%3E");
}
[data-theme="light"] .chip span{border-color:var(--line-2);color:var(--bone-dim)}
[data-theme="light"] .chip input:checked + span{background:var(--gold);border-color:var(--gold);color:var(--paper-2)}
[data-theme="light"] .radio{color:var(--bone-dim)}
[data-theme="light"] .radio input{accent-color:var(--gold)}
[data-theme="light"] .availgrid__h{color:var(--muted)}
[data-theme="light"] .availgrid__d{color:var(--bone-dim)}
[data-theme="light"] .availcell span{border-color:var(--line-2);color:var(--muted)}
[data-theme="light"] .availcell input:checked + span{background:var(--gold);border-color:var(--gold)}
[data-theme="light"] .availcell span::after{color:var(--paper-2)}
[data-theme="light"] .sched__note{color:var(--bone-dim)}
[data-theme="light"] .sched__where,[data-theme="light"] .sched__fallback{color:var(--muted)}
[data-theme="light"] .cal__month{color:var(--bone)}
[data-theme="light"] .cal__nav{border-color:var(--line-2);color:var(--gold)}
[data-theme="light"] .cal__dow span{color:var(--muted)}
[data-theme="light"] .cal__day{color:var(--bone-dim)}
[data-theme="light"] .cal__day.is-off{color:var(--muted)}
[data-theme="light"] .cal__day.is-avail{border-color:var(--line-2)}
[data-theme="light"] .cal__day.is-avail::after{background:var(--gold);opacity:1}
[data-theme="light"] .cal__day.is-sel{background:var(--gold);border-color:var(--gold);color:var(--paper-2)}
[data-theme="light"] .slots__label{color:var(--gold)}
[data-theme="light"] .slots__list .slot{border-color:var(--line-2);color:var(--bone-dim)}
[data-theme="light"] .slots__list .slot.is-sel{background:var(--gold);border-color:var(--gold);color:var(--paper-2)}
[data-theme="light"] .bconfirm__txt{color:var(--bone)}
[data-theme="light"] .intake__fallback{color:var(--muted)}

/* ---------- the toggle control itself (styled for BOTH modes) ---------- */
.themetog{
  display:grid;place-items:center;width:34px;height:34px;flex:none;
  background:none;border:1px solid var(--line-2);border-radius:50%;
  color:var(--gold);cursor:pointer;padding:0;
  transition:color .25s ease,border-color .25s ease,transform .3s var(--easer);
}
.themetog:hover{color:var(--gold-bright);border-color:var(--gold);transform:translateY(-1px)}
.themetog:focus-visible{outline:2px solid var(--gold-bright);outline-offset:3px}
.themetog svg{width:17px;height:17px}
.themetog__sun{display:block}
.themetog__moon{display:none}
[data-theme="light"] .themetog__sun{display:none}
[data-theme="light"] .themetog__moon{display:block}
@media(max-width:960px){ .themetog{width:30px;height:30px} .themetog svg{width:15px;height:15px} }

/* ═══ THE HERO AS A DARK ISLAND ═══════════════════════════════════════════════
   FIX for a bug in the first pass of this block (found by rendering it, 2026-07-20):
   I overrode no .hero RULE, but I remapped the TOKENS the hero reads. Custom properties
   inherit, so --bone flipped to ink and the headline rendered dark-on-dark video —
   "SABAI" was all but invisible. "I didn't touch its selectors" is not the same as
   "I didn't change it".

   The fix is structural, not a colour patch: <section class="hero" data-theme="dark">
   re-declares the whole dark token set locally, so everything inside the hero keeps the
   values it has in dark mode. Nothing about the hero's own CSS changes.

   ⚠ SPECIFICITY: [data-theme="dark"] X and [data-theme="light"] X are EQUAL (0,2,0).
   Inside the hero BOTH match — so the restores below must stay AFTER the light rules in
   source order. Do not move this block up. */
[data-theme="dark"]{
  --void:#0A0F0C;
  --stone:#0E1611;
  --stone-2:#131C16;
  --plate:#0C1C15;
  --bone:#ECE7D8;
  --bone-dim:#C9C4B0;
  --muted:#8F8C7D;
  --muted-2:#8B8877;
  --gold:#D5BD61;
  --gold-bright:#EAD387;
  --gold-deep:#9A833C;
  --ember:#DD7A22;
  --line:rgba(213,189,97,0.16);
  --line-2:rgba(213,189,97,0.32);
}

/* the gold-glass button, restored verbatim inside the dark island */
[data-theme="dark"] .btn{
  color:var(--gold-bright);
  border:0.5px solid rgba(234,211,135,0.55);
  background:
    radial-gradient(85% 95% at 50% 115%, rgba(221,122,34,0.28), rgba(213,189,97,0.10) 55%, transparent 75%),
    linear-gradient(180deg, rgba(234,211,135,0.16), rgba(197,168,80,0.08));
  -webkit-backdrop-filter:blur(10px) saturate(115%);backdrop-filter:blur(10px) saturate(115%);
  text-shadow:0 1px 2px rgba(5,8,5,0.55);
  box-shadow:
    inset 0 1px 0 rgba(255,246,210,0.4),
    inset 0 -1px 0 rgba(255,220,140,0.15);
}
[data-theme="dark"] .btn::after{
  display:block;
  background:radial-gradient(60% 100% at 50% 50%, rgba(234,211,135,0.30), transparent 72%);
  opacity:0;animation:btn-breathe 8s ease-in-out infinite;
}
[data-theme="dark"] .btn--ghost::after{animation:none;opacity:0}
[data-theme="dark"] .btn:hover::after{animation:none;opacity:0}
[data-theme="dark"] .btn:hover{
  color:#F4E6AE;border-color:rgba(244,225,160,0.75);
  background:
    radial-gradient(90% 115% at 50% 105%, rgba(221,122,34,0.38), rgba(213,189,97,0.16) 55%, transparent 78%),
    linear-gradient(180deg, rgba(234,211,135,0.22), rgba(197,168,80,0.12));
  box-shadow:
    inset 0 1px 0 rgba(255,246,210,0.5),
    inset 0 -1px 0 rgba(255,220,140,0.22);
}
[data-theme="dark"] .btn--ghost{
  background:linear-gradient(180deg, rgba(234,211,135,0.08), rgba(197,168,80,0.04));
  color:var(--gold-bright);border:0.5px solid rgba(234,211,135,0.35);
  box-shadow:inset 0 1px 0 rgba(255,246,210,0.2);
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
[data-theme="dark"] .btn--ghost:hover{
  color:#FFF6DC;border-color:rgba(234,211,135,0.6);
  background:
    radial-gradient(85% 95% at 50% 115%, rgba(221,122,34,0.2), rgba(213,189,97,0.08) 55%, transparent 75%),
    linear-gradient(180deg, rgba(234,211,135,0.12), rgba(197,168,80,0.06));
  box-shadow:inset 0 1px 0 rgba(255,246,210,0.3);
}
[data-theme="dark"] .txtlink{color:var(--gold);border-bottom-color:rgba(213,189,97,0.35)}
[data-theme="dark"] .txtlink:hover{color:var(--gold-bright);border-bottom-color:var(--gold-bright)}

/* ═══ PHTHALO INK — replaces the deep gold in light mode (Elliot 2026-07-20) ═════════
   "test replace the brown gold with a visible pthalo green".

   Note this does NOT contradict D-041 (phthalo rejected in the dark nav: "nothing
   fire-lit is turquoise"). That verdict was about phthalo as a LIT surface inside the
   cave. As INK on paper there is no fire to contradict — a blue-leaning green reads as
   printed pigment, and it is the same hue family already tinting the dark base tokens,
   so the two themes stay recognisably one brand.

   Measured on paper #F4F5F3 (WCAG AA text floor = 4.5:1):
     #116152  6.72:1  ← body text, labels, links
     #0B3D33 11.10:1  ← hover / emphasis
     #157A66  4.79:1  ← deep accent, still passes
     #2E8C77  3.74:1  ← DECORATIVE HAIRLINES ONLY, never text
   White on a #116152 button fill = 7.35:1. */
:root[data-theme="light"]{ --plate:#0B3D33; }   /* footer plaque only */
/* the few places that hardcoded a gold rgba() rather than reading the token */
[data-theme="light"] .intake select.in{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%23116152' stroke-width='1.6'%3E%3Cpath d='m1 1 5 5 5-5'/%3E%3C/svg%3E");
}

/* ═══ THE MARK ═══════════════════════════════════════════════════════════════════
   Inline SVG in currentColor — the brandmark just sets `color`, and the mark follows the
   theme with no second asset and no blend mode. The dark plate that the old PNG needed in
   light mode is gone with it. */
.brandmark{color:var(--gold)}
.brandmark__svg{height:46px;width:auto;display:block;overflow:visible}
[data-theme="light"] .mainnav .brandmark{background:none;padding:0}
@media(max-width:960px){ .brandmark__svg{height:38px} }

/* ═══ THE ATTENTION CUE ══════════════════════════════════════════════════════════
   "add an attention grabber animation to light mode so folks know about it."
   Since the site now always opens dark, nobody discovers the toggle by accident — so it
   announces itself ONCE. A ring expands out of the button every few seconds, plus a small
   dot on the rim. Both are pure opacity/transform on a pseudo-element (compositor-only —
   D-024 bars animating box-shadow or anything that repaints).
   It is gated on [data-themenew], which JS removes permanently on first use, so a
   returning visitor never sees it again.
   ⚠ CONTINUOUS + OBVIOUS (rebuilt 2026-07-20, Elliot: "still not seeing any animation…
   despite repeated requests"). Every prior version was a ring that flashed bright for a
   fraction of a second then sat at opacity 0 for ~70% of the cycle — measured animating but
   effectively invisible. This version never goes invisible: the button breathes (scale) on a
   short 1.8s loop AND a glow ring is ALWAYS on screen, pulsing between 0.45 and 1 — so at
   every instant there is visible motion. Compositor-only (opacity + transform), D-024 safe. */
.themetog{position:relative}
/* ⚠ ATTENTION PING (Elliot 2026-07-22: "give the light/darkmode button a nice ping" →
   "should only ring once on load"). A sonar-style ping that fires ONCE, ~0.5s after load:
   two thin rings expand out of the button rim and fade, the second ~0.45s behind the first
   for a double-ripple, then gone. No loop. It plays only for a visitor who hasn't used the
   toggle before — [data-themenew] is set at load when sabai-theme-seen is absent, and the
   first click removes it — so a returning visitor never sees it.
   Compositor-only: transform(scale) + opacity ONLY, never box-shadow (D-024 — box-shadow
   repaints every frame). The button itself never moves; only the pseudo-rings animate.
   `both` fill holds each ring invisible through its start delay (no static ring before it
   fires) and after it ends. Colour follows --gold → phthalo in light, gold in dark. */
[data-themenew] .themetog::before,
[data-themenew] .themetog::after{
  content:"";position:absolute;inset:-3px;border-radius:50%;pointer-events:none;
  border:2px solid var(--gold);
  opacity:0;
  animation:tog-ping 1.5s ease-out 0.5s 1 both;
}
[data-themenew] .themetog::after{animation-delay:0.95s}   /* the trailing ripple */
@keyframes tog-ping{
  0%{opacity:0;transform:scale(0.9)}
  12%{opacity:0.7}
  100%{opacity:0;transform:scale(1.7)}
}
/* REDUCED MOTION — one gentle ring, no trailing ripple. A specific selector with
   `!important` outranks the base `*{animation:none!important}`. */
@media(prefers-reduced-motion:reduce){
  [data-themenew] .themetog::before{animation:tog-ping 1.5s ease-out 0.5s 1 both !important}
  [data-themenew] .themetog::after{animation:none !important}
}

/* HERO BOTTOM DISSOLVE — REVERTED 2026-07-20 (Elliot: "no on the hero"). The hero is left
   exactly as the dark island it was; its overlay is not themed. Do not re-attempt. */

/* ═══ COOL-PAPER TEXTURE + DEPTH (Elliot 2026-07-20) ══════════════════════════════
   "modest depth/texture like cool paper" → then "smoother not so grainy". Two static
   layers on the fixed .cave (position:fixed — composites ONCE, no per-scroll repaint):
     1. DEPTH — a broad radial: a touch brighter toward the upper centre, easing to a
        slightly cooler paper at the edges. Reads as a lit sheet, not flat.
     2. MOTTLE — soft low-frequency cloud (baseFrequency 0.012, not 0.9) run through a
        Gaussian blur, so it's a gentle undulation in the paper tone, NOT fine grain.
        Very low opacity, multiply-blended so it settles into the paper rather than sitting
        on top. This is the "smoother" pass — the first version was sandpaper. */
[data-theme="light"] .cave{
  background:
    radial-gradient(125% 100% at 50% 0%, #FCFCFB 0%, var(--paper) 52%, #E9EBE8 100%);
}
[data-theme="light"] .cave__paper{
  display:block;position:absolute;inset:0;pointer-events:none;
  opacity:0.6;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012' numOctaves='3' stitchTiles='stitch'/%3E%3CfeGaussianBlur stdDeviation='1.1'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.17  0 0 0 0 0.20  0 0 0 0 0.18  0 0 0 0.06 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)'/%3E%3C/svg%3E");
  background-size:600px 600px;
}
/* the texture layer does not exist in dark mode */
.cave__paper{display:none}

/* ═══ THEME SWITCH CROSSFADE (Elliot 2026-07-20: "the flash is terrible, it was better in
   its previous state") ════════════════════════════════════════════════════════════════
   Back to the View Transitions API (JS in index.html): a true whole-page content dissolve,
   old→new, not the solid-colour sheet flash that replaced it. These two rules only tune the
   dissolve time. Runs once per click; ungated now so it plays for everyone with the API. */
::view-transition-old(root),
::view-transition-new(root){ animation-duration:0.5s; }

/* ═══ HERO — OPTION 1 (Elliot 2026-07-20 chose it: "option one but I want the phthalo
   glass buttons with white text"). Light headline over the video's existing scrim, green
   used ONLY where it reads — the phthalo-glass buttons and the eyebrow tick. #116152 is
   dark ink and only reads on light, so it never floats on the dark footage; on the video
   the text is LIGHT (the proven dark-mode legibility), no shadow hacks, no dark-on-dark.
   Anchored on :root[data-theme="light"] to key off the PAGE theme past the hero's island. */
/* (Hero glass panel REMOVED 2026-07-20 — Elliot: "that is not what i asked for, remove it";
   the glass belongs on the strip below the hero, see the .forwho/.stats rules further down.) */
:root[data-theme="light"] .hero__eyebrow{color:#EFE9DB;text-shadow:0 1px 12px rgba(0,0,0,0.5)}
:root[data-theme="light"] .hero__eyebrow::before{background-color:#2E8C77}
:root[data-theme="light"] .hero__title{color:#F6F2E8;text-shadow:0 2px 30px rgba(0,0,0,0.45),0 0 2px rgba(0,0,0,0.4)}
:root[data-theme="light"] .hero__title .g{color:#F6F2E8;text-shadow:0 2px 40px rgba(0,0,0,0.4)}
:root[data-theme="light"] .hero__sub{color:#EDE8DB}
:root[data-theme="light"] .hero__sub b{color:#FFFFFF;font-weight:600}
:root[data-theme="light"] .hero .txtlink{color:#EFE9DB;border-bottom-color:rgba(255,255,255,0.4);text-shadow:0 1px 10px rgba(0,0,0,0.5)}
:root[data-theme="light"] .hero .txtlink:hover{color:#FFFFFF;border-bottom-color:#FFFFFF}

/* phthalo-glass buttons, white text — a brand-green pane that reads on the footage */
:root[data-theme="light"] .hero__cta .btn{
  color:#FFFFFF;
  border:1px solid rgba(120,210,185,0.5);
  background:
    radial-gradient(85% 95% at 50% 115%, rgba(23,138,110,0.5), rgba(17,97,82,0.34) 55%, transparent 80%),
    linear-gradient(180deg, rgba(17,97,82,0.6), rgba(11,61,51,0.52));
  text-shadow:0 1px 2px rgba(0,0,0,0.55);
  box-shadow:inset 0 1px 0 rgba(200,240,228,0.28), 0 3px 16px -6px rgba(0,0,0,0.55);
}
:root[data-theme="light"] .hero__cta .btn::after{background:radial-gradient(60% 100% at 50% 50%, rgba(120,210,185,0.22), transparent 72%);}
:root[data-theme="light"] .hero__cta .btn:hover{
  color:#FFFFFF;border-color:rgba(140,225,200,0.75);
  background:
    radial-gradient(90% 115% at 50% 105%, rgba(23,138,110,0.62), rgba(17,97,82,0.4) 55%, transparent 82%),
    linear-gradient(180deg, rgba(21,122,102,0.7), rgba(11,61,51,0.6));
  box-shadow:inset 0 1px 0 rgba(200,240,228,0.4), 0 6px 20px -6px rgba(0,0,0,0.6);
}
:root[data-theme="light"] .hero__cta .btn--ghost{
  color:#FFFFFF;border:1px solid rgba(255,255,255,0.42);
  background:linear-gradient(180deg, rgba(17,97,82,0.22), rgba(11,61,51,0.16));
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.18);
}
:root[data-theme="light"] .hero__cta .btn--ghost:hover{
  color:#FFFFFF;border-color:rgba(255,255,255,0.68);
  background:linear-gradient(180deg, rgba(17,97,82,0.3), rgba(11,61,51,0.22));
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.3);
}


/* ═══ MOBILE LOGO (2026-07-20) ══════════════════════════════════════════════════
   The full SABAI/STRIKING inline lockup is ~224px wide (aspect 5.9) — on a phone nav that
   overflows and pushes the hamburger menu off-screen. Below 520px, swap to the compact MARK.
   ⚠ MOBILE-ONLY: `.brandmark__mark` is display:none by default, so desktop/tablet are
   untouched — the full lockup still renders exactly as before at >520px. */
.brandmark__mark{display:none}
@media(max-width:520px){
  .brandmark__svg{display:none}
  .brandmark__mark{display:block;height:34px;width:auto}
}
