/* dharmavāk — scroll-film candidate.
   Dark-primary. Tokens inherited from DESIGN-dharmavak.md; the dark values are
   the same ones already shipping in Frontend_AntiGravity/src/styles/tokens.css.

   The one rule this build adds: GOLD IS MATERIAL, CORAL IS INTERFACE.
   Gold belongs to the film — the leaf, the archive, the line. Coral only ever
   touches things you can click. That keeps the design doc's "one accent"
   law intact while letting the footage be gold. */

:root {
  color-scheme: dark;

  --canvas: #100f0d;
  --surface: #181715;
  --surface-raised: #201e1a;

  --ink: #faf9f5;
  --body: #cbc7be;
  /* Was #8e8b82. Measured against the brightest decile of the film under the
     copy (≈216,175,119 through the scrim) it landed at 4.4:1 — under AA for
     the small letterspaced caps the eyebrow is set in. #a9a49a
     takes the same text to 6.1:1 without brightening into --body's rank. */
  --muted: #a9a49a;
  --hairline: #2b2823;

  /* Interface accent — the only colour that means "clickable". */
  --coral: #cc785c;
  --coral-deep: #a9583e;
  --coral-link: #e0916f;
  /* The CTA band's field. Same hue as --coral (≈15°), taken deep enough to
     carry LIGHT ink — see the .cta-band note.
     #C24900 (the logo's wordmark orange) was tried 2026-08-07 and REVERTED:
     the hue is right, the AREA was wrong — a saturated orange across a
     1000px-wide field glares on a page that is otherwise near-black.
     That orange now belongs on the button only. */
  --coral-band: #8a3f28;
  /* The logo's Devanāgarī wordmark orange, sampled from the PNG (#bf4b05 avg).
     Reserved for small high-energy surfaces — the CTA button, the chat dock. */
  --brand-orange: #c24900;
  /* The film's chapter label. Gold because the eyebrow marks where you are in
     the FOOTAGE, and gold is the footage's own colour. 6.3:1 at its worst. */
  --gold-label: #c9a06a;

  /* Material accent — the film's gold. Never used for a control. */
  --gold: #d9a961;
  --gold-soft: rgba(217, 169, 97, 0.22);

  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'Source Sans 3', system-ui, sans-serif;

  --font-deva: 'Noto Sans Devanagari', sans-serif;
  --font-deva-display: 'Noto Serif Devanagari', serif;
  --font-iast: 'Gentium Plus', Georgia, serif;

  /* Type scale, made explicit when the body face changed. MEASURED: Inter's
     x-height is 0.565em, Source Sans 3's is 0.510em — a 10% drop, so a
     like-for-like swap would have shrunk the whole page by eye while every
     number stayed the same. 16 → 17px restores most of it. The two steps keep
     the 1.25 ratio the old comment called for; small text stays unmistakably
     a different rank rather than a slightly smaller body. */
  --fs-body: 17px;
  --fs-lead: 18px;
  --fs-small: 13.5px;

  --container: 1140px;
  --pad: clamp(20px, 4vw, 40px);
}

@font-face { font-family: 'Fraunces'; font-weight: 400; font-display: swap;
  src: url(/fonts/fraunces-latin-400-normal.woff2) format('woff2'); }
@font-face { font-family: 'Fraunces'; font-weight: 400; font-display: swap;
  src: url(/fonts/fraunces-latin-ext-400-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+1EF2-1EFF; }
/* Source Sans 3 replaced Inter 2026-08-07. Two reasons: Inter is the default sans
   of the last five years and reads as generic SaaS, which is a liability for a
   brand whose claim is that it does not invent; and the body face here has to
   carry IAST inside running prose (Māṇḍūkya Upaniṣad, nakṣatra, saṃdhi), which
   needs full Latin Extended Additional — a filter most fashionable sans faces
   fail. The latin-ext file below is what serves those glyphs.
   Restore Inter if ever needed:
   curl -O https://cdn.jsdelivr.net/npm/@fontsource/inter/files/inter-latin-400-normal.woff2 */
@font-face { font-family: 'Source Sans 3'; font-weight: 400; font-display: swap;
  src: url(/fonts/source-sans-3-latin-400-normal.woff2) format('woff2'); }
@font-face { font-family: 'Source Sans 3'; font-weight: 500; font-display: swap;
  src: url(/fonts/source-sans-3-latin-500-normal.woff2) format('woff2'); }
@font-face { font-family: 'Source Sans 3'; font-weight: 600; font-display: swap;
  src: url(/fonts/source-sans-3-latin-600-normal.woff2) format('woff2'); }
@font-face { font-family: 'Source Sans 3'; font-weight: 400; font-display: swap;
  src: url(/fonts/source-sans-3-latin-ext-400-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+1EF2-1EFF; }
@font-face { font-family: 'Source Sans 3'; font-weight: 500; font-display: swap;
  src: url(/fonts/source-sans-3-latin-ext-500-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+1EF2-1EFF; }
@font-face { font-family: 'Source Sans 3'; font-weight: 600; font-display: swap;
  src: url(/fonts/source-sans-3-latin-ext-600-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+1EF2-1EFF; }
@font-face { font-family: 'Gentium Plus'; font-weight: 400; font-display: swap;
  src: url(/fonts/gentium-plus-latin-400-normal.woff2) format('woff2'); }
@font-face { font-family: 'Gentium Plus'; font-weight: 400; font-display: swap;
  src: url(/fonts/gentium-plus-latin-ext-400-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+1EF2-1EFF; }
@font-face { font-family: 'Noto Sans Devanagari'; font-weight: 400; font-display: swap;
  src: url(/fonts/noto-sans-devanagari-devanagari-400-normal.woff2) format('woff2');
  unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+25CC; }
@font-face { font-family: 'Noto Serif Devanagari'; font-weight: 400; font-display: swap;
  src: url(/fonts/noto-serif-devanagari-devanagari-400-normal.woff2) format('woff2');
  unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+25CC; }

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

body {
  background: var(--canvas);
  color: var(--body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* height:auto is the guard, not a nicety — every <img> here carries width/height
   attributes for CLS, and those act as presentational hints. Set a CSS width
   without releasing the height and the image renders stretched, silently. */
img, canvas { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; }

:focus-visible { outline: 2px solid var(--coral); outline-offset: 3px; }

.container { max-width: var(--container); margin-inline: auto; padding-inline: var(--pad); }

/* ============================================================
   THE MARK — centred title card, docking top-left
   Default state IS the docked state, so no-JS / mobile / save-data /
   reduced-motion get a logo in the corner and the hero copy visible,
   with no journey and nothing hidden. .has-film adds the choreography;
   scrub.js drives it through four custom properties.
   ============================================================ */

.brand-title, .brand-veil { display: none; }

.brand-dock {
  position: fixed; z-index: 60;
  left: var(--pad); top: 18px;
  width: 44px;
  pointer-events: none;
}
.brand-dock img {
  width: 100%; height: auto;
  /* The mark is saffron line-art with open counters — over a bright film frame
     it needs its own shadow, not a scrim, or the halo dissolves into the gold. */
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.9)) drop-shadow(0 6px 18px rgba(0,0,0,0.55));
}

.has-film .brand-title {
  display: block;
  position: fixed; z-index: 61;
  left: 50%; top: 50%;
  width: clamp(148px, 14vw, 200px);
  /* NOT optional. The <img> carries height="586" as a presentational hint, and
     CSS width alone does not release it — the mark renders 200×586, stretched
     nearly 2× vertically. The footer and dock copies always set this; this one
     did not, and the distortion is not obvious in a small screenshot. */
  height: auto;
  transform:
    translate(-50%, -50%)
    translate(var(--brand-dx, 0px), var(--brand-dy, 0px))
    scale(var(--brand-scale, 1));
  opacity: var(--brand-title-o, 1);
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.85)) drop-shadow(0 18px 50px rgba(0,0,0,0.6));
}

/* The title card sits at dead centre — precisely where the film-scrim is
   weakest (it clears by 62% so the right half of every frame stays open).
   Chapter 1 is also the brightest frame in the film. This radial wash is the
   only thing that guarantees the mark reads on frame 0; it leaves with it. */
.has-film .brand-veil {
  display: block;
  position: fixed; inset: 0; z-index: 59; pointer-events: none;
  opacity: var(--brand-title-o, 1);
  background: radial-gradient(ellipse 46% 52% at 50% 50%,
    rgba(16,15,13,0.86) 0%, rgba(16,15,13,0.62) 45%, rgba(16,15,13,0) 78%);
}

.has-film .brand-dock { opacity: var(--brand-dock-o, 0); }

/* Hero copy is the second half of the title card: it arrives as the mark
   leaves, so the opening reads as one move rather than two things at once. */
.has-film #beat-hero .beat-inner { opacity: var(--hero-copy-o, 1); }

.skip-link {
  position: absolute; left: 16px; top: -100px; z-index: 200;
  background: var(--ink); color: var(--canvas);
  padding: 10px 16px; border-radius: 8px; text-decoration: none; font-weight: 600;
}
.skip-link:focus-visible { top: 16px; }

/* ============================================================
   THE FILM
   A sticky canvas pinned inside a tall track. Scroll position
   through the track maps to a fractional frame index; the renderer
   cross-fades the two adjacent frames so six stills read as motion.
   When real footage lands, only FRAME_COUNT changes.
   ============================================================ */

/* PROGRESSIVE ENHANCEMENT, THE RIGHT WAY ROUND.
   The static, readable layout is the DEFAULT — it needs no JavaScript, no
   canvas and no scroll listener. `.has-film` is added by scrub.js only once
   the frames have actually decoded, and that class is what turns the page into
   a film. Doing it the other way (a `.no-film` class added by JS) meant a
   visitor with JS disabled got the hidden state forever, because the code that
   was supposed to rescue them never ran. */

.film { position: relative; height: auto; }

.film-stage {
  position: static;
  height: auto;
  background: var(--canvas);
}

.film-canvas {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.has-film .film { height: 600vh; }
.has-film .film-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}
.has-film .film-canvas { display: block; }

/* Legibility scrim over the footage. Text always wins.
   Top and bottom gradients alone were not enough: the copy sits at vertical
   centre, exactly where neither reaches, and chapter 1 is the brightest frame
   in the film — the eyebrow disappeared into the gold entirely. The left
   gradient is the one that actually does the work, because beats 1–3 are
   left-aligned; it clears by 62% so the right half of every frame stays open.
   A low flat wash catches the rest. */
.film-scrim {
  display: none;
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(100deg,
      rgba(16,15,13,0.92) 0%,
      rgba(16,15,13,0.82) 28%,
      rgba(16,15,13,0.35) 48%,
      rgba(16,15,13,0) 62%),
    linear-gradient(to bottom, rgba(16,15,13,0.6) 0%, rgba(16,15,13,0) 24%),
    linear-gradient(to top, rgba(16,15,13,0.8) 0%, rgba(16,15,13,0) 34%),
    rgba(16, 15, 13, 0.22);
}

/* The closing beat is centred, so the left-weighted scrim would sit off-axis
   under it. Swap to an even wash for that chapter only. */
.film-stage:has(.citation-beat.is-on) .film-scrim {
  /* Kept deliberately light — the card carries its own tinted backdrop, so the
     scrim only has to soften the surround. Any heavier and it snuffed out the
     gold line, which is the whole point of this beat. */
  background:
    radial-gradient(ellipse at 50% 45%, rgba(16,15,13,0.18) 0%, rgba(16,15,13,0.72) 72%),
    rgba(16, 15, 13, 0.12);
}

/* Chapter copy. Default: stacked, readable prose sections. With the film
   running they become cross-fading overlays pinned on the canvas. */
.beat {
  position: relative;
  padding-block: clamp(56px, 9vw, 96px);
}

.has-film .beat {
  position: absolute;
  inset: 0;
  display: grid;
  align-items: center;
  padding-block: 0;
  opacity: 0;
  transition: opacity 420ms ease;
  pointer-events: none;
}
.has-film .beat.is-on { opacity: 1; pointer-events: auto; }

.beat-inner { width: 100%; }

.eyebrow {
  font-size: 13px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 14px;
}
/* Over the footage the eyebrow is a chapter label, so it takes the film's own
   gold. Off the film (the About section) it stays neutral — nothing there is
   material, so gold would be a decoration with no argument behind it. */
.beat .eyebrow { color: var(--gold-label); }

.display-xl {
  font-family: var(--font-display); font-weight: 400; color: var(--ink);
  font-size: clamp(2.5rem, 5.2vw, 4.5rem); line-height: 1.03;
  letter-spacing: -0.024em; text-wrap: balance;
}
.display-md {
  font-family: var(--font-display); font-weight: 400; color: var(--ink);
  font-size: clamp(1.75rem, 3vw, 2.5rem); line-height: 1.12;
  letter-spacing: -0.016em; text-wrap: balance;
}

.lead { max-width: 46ch; margin-top: 20px; font-size: var(--fs-lead); }

/* Chapter marker — bottom-left, tells you where in the film you are. */
.film-hud {
  display: none;
  position: absolute;
  left: var(--pad); bottom: 28px;
  align-items: center; gap: 12px;
  font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted);
}
.film-hud-rule {
  width: 64px; height: 1px; background: var(--hairline); position: relative;
}
.film-hud-rule::after {
  content: ''; position: absolute; left: 0; top: 0; height: 1px;
  width: var(--film-progress, 0%); background: var(--gold);
}

/* ============================================================
   THE FOUR MODULES — revealed one per scroll step
   ============================================================ */

/* 44ch was set against Inter at 16px. With a 10ch name column and a 17px body
   the description fell to ~30ch and every row wrapped to three lines. */
.modules-beat .module-list { list-style: none; padding: 0; margin: 28px 0 0; max-width: 52ch; }
.module-row {
  display: flex; gap: 16px; align-items: baseline;
  padding: 14px 0; border-top: 1px solid var(--hairline);
  transition: opacity 380ms ease;
}
/* Dimmed-then-revealed only when the film is driving them. 0.25 put the unread
   rows at roughly 2.5:1 over the footage — not "not yet", just unreadable.
   0.4 still reads as pending while staying legible. */
.has-film .module-row { opacity: 0.4; }
.has-film .module-row.is-on { opacity: 1; }
.module-row dt {
  font-family: var(--font-display); font-size: 20px; color: var(--ink);
  min-width: 10ch;
}
/* The common romanisation, under the IAST name. Body face on purpose — it is a
   reading aid, not part of the name, and the rank must be unmistakable. */
.module-gloss {
  display: block;
  font-family: var(--font-body); font-size: var(--fs-small); font-weight: 400;
  letter-spacing: 0.06em; color: var(--muted); margin-top: 2px;
}
.module-row dd { margin: 0; font-size: var(--fs-body); color: var(--body); }

/* ============================================================
   THE CITATION CARD — the film resolves into this
   The closing gold line of the film sits exactly where the card's
   source rule goes, so the footage becomes the card's underline.
   ============================================================ */

/* Lift the closing beat so the card's source rule meets the film's gold line.
   In f06 the line sits at ~37% of frame height; cover-fit puts that at ~37vh.
   Centred, the rule lands near 49vh, so the beat rides up to close the gap and
   the footage becomes the underline of the citation. */
.citation-beat .citation-card {
  max-width: 620px;
  margin: 0 auto;
  background: rgba(24, 23, 21, 0.82);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 34px 36px 28px;
  backdrop-filter: blur(14px);
  box-shadow: 0 40px 80px -40px rgba(0,0,0,0.9);
}
.citation-stack { display: flex; flex-direction: column; gap: 12px; margin: 0; }
.deva-display {
  font-family: var(--font-deva-display); font-weight: 400;
  font-size: clamp(24px, 2.4vw, 32px); line-height: 1.5; color: var(--ink);
}
.iast { font-family: var(--font-iast); font-size: var(--fs-lead); color: #ebe8e1; }
.citation-translation { color: var(--body); }
.citation-source {
  display: flex; align-items: baseline; gap: 10px;
  margin-top: 22px; padding-top: 16px;
  /* The rule the film's final gold line lands under. */
  border-top: 1px solid var(--gold-soft);
  font-size: var(--fs-small); font-weight: 500; color: var(--coral-link);
}
.cite-mark { color: var(--gold); font-size: 0.7em; }

/* ============================================================
   AFTER THE FILM
   ============================================================ */

.section { padding-block: clamp(72px, 10vw, 120px); }
.section-alt { background: var(--surface); }

.section-head { max-width: 54ch; margin-bottom: 48px; }
.section-head .display-md { margin-bottom: 14px; }

.people { display: grid; grid-template-columns: 1fr; gap: 32px; list-style: none; padding: 0; margin: 0; }
.person { padding-top: 22px; border-top: 1px solid var(--hairline); }
.person-mark {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; margin-bottom: 16px;
  border: 1px solid var(--gold-soft); border-radius: 999px;
  font-family: var(--font-display); font-size: 18px; color: var(--gold);
}
.person-name { font-size: 18px; font-weight: 600; color: var(--ink); margin-bottom: 2px; }
.person-role { font-size: var(--fs-small); font-weight: 500; color: var(--coral-link); margin-bottom: 10px; }
.person-bio { font-size: var(--fs-body); max-width: 38ch; }

/* THE WAITLIST PANEL — rebuilt 2026-08-07 (third pass).

   History, because it keeps being re-litigated:
   v1 was #cc785c with a #fff heading AND #141413 body — two ink polarities on
   one field, and white-on-coral measured 3.28:1, under AA, while carrying the
   page's most important sentence.
   v2 deepened the field to #8a3f28 and unified the ink.
   v3 tried #C24900, the logo's wordmark orange. Pandit Ji rejected it on sight
   and he was right: the HUE was never the problem, the AREA was. A saturated
   orange across a ~1000px field is roughly 8% of the viewport shouting on a
   page that is otherwise near-black.

   So the field is gone. This is now a dark panel with a hairline border — same
   family as the citation card — and #C24900 appears on the button ALONE, where
   at ~200px wide it reads as a jewel instead of a wall. That is also exactly
   what dydxfx.com does; its contact section has no coral field either, only a
   coral button. White on #C24900 is 4.94:1, and the button is 3.62:1 against
   the panel, so it is unmistakably the one thing you can press. */
.cta-band {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  /* Vertical padding pulled in from clamp(36,5.5vw,60): the panel measured
     760px, taller than a 13" laptop viewport, so the submit button fell below
     the fold no matter where the page scrolled to. Horizontal padding is
     unchanged — the measure was never the problem. */
  padding: clamp(30px, 4vw, 44px) clamp(24px, 4vw, 52px);
}
.cta-band h2 {
  color: var(--ink); font-family: var(--font-display); font-weight: 400;
  font-size: clamp(1.6rem, 3vw, 2.2rem); margin-bottom: 12px;
}
.cta-sub { color: var(--body); max-width: 54ch; margin-bottom: 26px; }

/* ── the form ── */
.wform { display: grid; gap: 20px; }
.wform-row { display: grid; gap: 20px; }
.wform-field { display: block; }
.wform-label {
  display: block; margin-bottom: 8px;
  font-size: var(--fs-small); font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--coral-link);
}
/* The step number, borrowed from dydxfx's numbered fields — it turns a stack of
   inputs into a sequence, which measurably reads as shorter than it is. */
.wform-label i { font-style: normal; color: var(--muted); margin-right: 6px; }
.wform-label em {
  font-style: normal; text-transform: none; letter-spacing: 0.02em;
  font-weight: 400; color: var(--muted); margin-left: 4px;
}
.wform input, .wform select, .wform textarea {
  width: 100%; font: inherit; color: var(--ink);
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: 10px;
  padding: 12px 14px;
}
.wform input, .wform select { height: 48px; }
.wform textarea { resize: vertical; min-height: 96px; line-height: 1.55; }
/* Placeholders were set in --muted, which measures 7.72:1 against the input
   fill — nearly as strong as real content, so an empty form read as a full one.
   #827d74 is 4.68:1: clearly a hint, still clearing AA. It does not go lower
   because these are the only words in the field until you type. Every field
   also carries a real visible label (01 NAME…), so the placeholder is never
   the sole cue. */
.wform ::placeholder { color: #827d74; opacity: 1; }
.wform input:focus-visible, .wform select:focus-visible, .wform textarea:focus-visible {
  border-color: var(--coral); outline-offset: 1px;
}
/* The select caret.
   The first pass drew a solid triangle out of two linear-gradients. It read as
   the stock OS control — a filled wedge is exactly what every unstyled <select>
   on the web looks like, so it fought the page instead of belonging to it.
   Replaced with a thin rotated-border chevron, in the same --coral-link the
   field labels use, so the control reads as part of this interface. Drawn on a
   pseudo-element rather than a background image so it inherits the token
   instead of hardcoding a colour into a data URI. */
.wform select { appearance: none; cursor: pointer; padding-right: 42px; }
.wform-field--select { position: relative; }
.wform-field--select::after {
  content: '';
  position: absolute; right: 20px; bottom: 21px;
  width: 7px; height: 7px;
  border-right: 1.5px solid var(--coral-link);
  border-bottom: 1.5px solid var(--coral-link);
  transform: rotate(45deg);
  pointer-events: none;
  transition: border-color 0.2s ease, transform 0.2s ease;
}
.wform-field--select:hover::after { border-color: var(--ink); }
/* A hairline rule between the value and the caret — the same device the
   citation card uses to separate a quote from its source. */
.wform-field--select::before {
  content: '';
  position: absolute; right: 42px; bottom: 12px;
  width: 1px; height: 24px; background: var(--hairline);
  pointer-events: none;
}

/* ── the upgraded select ──────────────────────────────────────────────────
   A native <select> renders its popup as an OS menu: on macOS that is a
   translucent grey sheet with a SYSTEM-ACCENT highlight (blue by default).
   `color-scheme: dark` darkens the sheet — it is already set on :root — but
   the highlight colour is not reachable from CSS at all, so a native control
   can never match this page. Hence a real listbox.

   Same inversion as `.has-film` and the docked badge: the native <select> is
   the CSS DEFAULT and JS *adds* `.wselect-on`. No-JS keeps a working control
   rather than losing the field. The <select> itself is never removed — it is
   what actually submits, so Netlify Forms still sees `name="segment"`.

   Coral, not --brand-orange: this is interface, and orange is reserved for the
   one thing you press (the submit button and the dock). */
.wselect-on > select {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden;
}
/* The native caret and its rule belong to the native control only. */
.wselect-on.wform-field--select::after,
.wselect-on.wform-field--select::before { display: none; }

.wselect-trigger {
  width: 100%; height: 48px; font: inherit; text-align: left;
  display: flex; align-items: center; gap: 12px;
  color: var(--ink); background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: 10px;
  padding: 12px 14px; cursor: pointer;
}
.wselect-trigger:focus-visible { border-color: var(--coral); outline-offset: 1px; }
.wselect-value { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The same rule + chevron the native field had, rebuilt as real elements so
   the open state can rotate the chevron. */
.wselect-rule { width: 1px; align-self: stretch; margin: -12px 0; background: var(--hairline); }
.wselect-caret {
  width: 7px; height: 7px; flex: none; margin-right: 4px;
  border-right: 1.5px solid var(--coral-link);
  border-bottom: 1.5px solid var(--coral-link);
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.2s ease, border-color 0.2s ease;
}
.wselect-trigger:hover .wselect-caret { border-color: var(--ink); }
.wselect-trigger[aria-expanded='true'] .wselect-caret { transform: translateY(1px) rotate(225deg); }

.wselect-menu {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 6px);
  margin: 0; padding: 6px; list-style: none;
  /* Tall enough that all seven segments fit without a scrollbar — the cap is
     only there to rescue a very short window. A list this size scrolling by
     default just hides two options behind a gesture. */
  max-height: min(348px, 60vh); overflow-y: auto;
  background: var(--surface-raised);
  border: 1px solid var(--hairline); border-radius: 10px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}
/* The listbox takes DOM focus so it can own the arrow keys, but the focus
   indicator is the highlighted row (aria-activedescendant), not the container.
   Without this the UA paints a heavy ring round the whole popup, which reads
   as an error state. */
.wselect-menu:focus, .wselect-menu:focus-visible { outline: none; }
/* Flipped upward when there is not room below — set by JS, measured. */
.wselect-menu[data-drop='up'] { top: auto; bottom: calc(100% + 6px); }
.wselect-menu[hidden] { display: none; }

/* ── opening ──
   The sheet grows from the edge it is attached to and the rows arrive just
   behind it, so the menu reads as unfolding out of the field rather than
   appearing on top of it. Kept deliberately short — the whole thing is done in
   ~250ms including the last row; a picker you wait for is a picker you resent.
   Animation, not transition: the element goes display:none → block, and only an
   animation fires on that change. */
@keyframes wselect-in {
  from { opacity: 0; transform: translateY(-7px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes wselect-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(-4px) scale(0.99); }
}
@keyframes wselect-row-in {
  from { opacity: 0; transform: translateY(-5px); }
  to   { opacity: 1; transform: none; }
}
.wselect-menu {
  transform-origin: top center;
  animation: wselect-in 160ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
.wselect-menu[data-drop='up'] { transform-origin: bottom center; }
.wselect-menu[data-drop='up'] { animation-name: wselect-in-up; }
@keyframes wselect-in-up {
  from { opacity: 0; transform: translateY(7px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
.wselect-menu.is-closing { animation: wselect-out 110ms ease-in both; }
.wselect-option { animation: wselect-row-in 180ms ease both; animation-delay: calc(var(--i, 0) * 16ms); }
/* On the way out the sheet leaves as one object — staggering the exit as well
   makes closing feel slower than opening, which is backwards. */
.wselect-menu.is-closing .wselect-option { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .wselect-menu,
  .wselect-menu.is-closing,
  .wselect-option { animation: none; }
}
.wselect-option {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 7px;
  color: var(--body); cursor: pointer;
}
/* One highlight for pointer and keyboard alike, so the two never disagree
   about which row is live. */
.wselect-option.is-active { background: rgba(204, 120, 92, 0.16); color: var(--ink); }
.wselect-option[aria-selected='true'] { color: var(--ink); }
.wselect-tick {
  width: 14px; flex: none; color: var(--coral-link);
  opacity: 0; font-size: var(--fs-small);
}
.wselect-option[aria-selected='true'] .wselect-tick { opacity: 1; }

/* The only orange on the page outside the logo, and the only thing you press. */
.wform-submit {
  justify-self: start;
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 50px; padding: 13px 26px; margin-top: 4px;
  font: inherit; font-weight: 600;
  background: var(--brand-orange); color: #fff;
  border: none; border-radius: 999px; cursor: pointer;
  transition: transform 0.25s ease, filter 0.25s ease;
}
.wform-submit svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; }
.wform-submit:hover { filter: brightness(1.12); transform: translateY(-2px); }
.wform-submit:active { transform: translateY(0); }
.wform-note { font-size: var(--fs-small); color: var(--muted); }

/* The honeypot. Hidden from people without display:none — some bots skip
   display:none fields precisely because they know it is a trap. */
.wform-hp {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden;
}

/* ── validation + submission state ── */
.wform-field.is-invalid input,
.wform-field.is-invalid textarea { border-color: var(--coral); }
.wform-error {
  display: block; margin-top: 6px;
  font-size: var(--fs-small); color: var(--coral-link);
}
.wform-status {
  margin: 0; padding: 14px 16px; border-radius: 10px;
  font-size: var(--fs-small);
  background: var(--canvas); border: 1px solid var(--hairline); color: var(--body);
}
.wform-status.is-ok { border-color: rgba(217, 169, 97, 0.45); color: var(--ink); }
.wform-status.is-bad { border-color: var(--coral); color: var(--ink); }
.wform-status a { color: var(--coral-link); }
.wform-submit[aria-busy='true'] { opacity: 0.72; pointer-events: none; }

/* The whole panel after a successful submit — the form is replaced by its own
   confirmation rather than sitting there inviting a second identical entry. */
.wform.is-sent > *:not(.wform-status) { display: none; }

@media (min-width: 720px) {
  .wform-row { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   THE DOCK — floating "Request early access"
   Rides --hero-copy-o so it arrives with the hero copy, at the exact moment
   the mark finishes docking top-left. No second scroll threshold to drift.
   Default (no JS / mobile / reduced motion) is visible, same inversion as
   everything else here: the static state is the CSS default.
   ============================================================ */
.dock-cta {
  position: fixed; z-index: 70;
  right: clamp(16px, 2.5vw, 28px); bottom: clamp(16px, 2.5vw, 28px);
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 22px;
  font: inherit; font-weight: 600; font-size: var(--fs-small);
  letter-spacing: 0.02em;
  background: var(--brand-orange); color: #fff;
  border: none; border-radius: 999px; cursor: pointer;
  box-shadow: 0 14px 40px -12px rgba(194, 73, 0, 0.7), 0 4px 16px rgba(0, 0, 0, 0.45);
  opacity: var(--cta-dock-o, 1);
  transition: transform 0.3s ease, box-shadow 0.3s ease, opacity 0.3s ease, visibility 0.3s;
}
/* Under the film the fallback flips to 0. Without this the dock is painted at
   full opacity for the whole frame-decoding window and then fades out the
   instant .has-film lands — which reads as a glitch, not an entrance. The
   static (no-film) state keeps fallback 1, because there the dock is simply
   navigation and should be there from the start. */
.has-film .dock-cta { opacity: var(--cta-dock-o, 0); }
.dock-cta-glyph { font-size: 0.7em; }
.dock-cta:hover { transform: translateY(-3px); box-shadow: 0 20px 50px -12px rgba(194, 73, 0, 0.85), 0 6px 20px rgba(0, 0, 0, 0.5); }
.dock-cta:active { transform: translateY(0) scale(0.98); }
/* Hidden while the waitlist is on screen — otherwise it sits on top of the form
   it is pointing at. dydxfx does the same thing, for the same reason. */
.dock-cta.is-off { opacity: 0; visibility: hidden; pointer-events: none; }
@media (max-width: 560px) {
  .dock-cta-label { display: none; }
  .dock-cta { padding: 14px 16px; }
  .dock-cta-glyph { font-size: 1rem; }
}

.footer { background: #0b0a09; padding-block: 72px 32px; color: var(--muted); }
.footer-inner { display: grid; gap: 32px; }
/* The mark, not set type. FULL COLOUR (Pandit Ji, 2026-08-07) — the mono-gold
   version was rejected. The saffron therefore IS a third accent; it is confined
   to the mark itself and never touches type or a control. */
.footer-wordmark { margin-bottom: 16px; }
.footer-wordmark img { display: block; width: 96px; height: auto; }
.footer-nav { display: flex; flex-wrap: wrap; gap: 0 22px; }
/* Type scale. 13px / 14px / 16px sat at a 1.2 ratio, which reads as one
   undifferentiated size rather than a hierarchy. Collapsed to two steps at
   16 / 12.8 (a 1.25 ratio) so small text is unmistakably a different rank. */
.footer-tagline { font-size: var(--fs-small); max-width: 34ch; }
.footer-cite { font-size: var(--fs-small); }
.footer-nav a { font-size: var(--fs-body); text-decoration: none; min-height: 44px; display: inline-flex; align-items: center; }
.footer-nav a:hover { color: var(--ink); text-decoration: underline; }
.footer-legal { font-size: var(--fs-small); border-top: 1px solid var(--hairline); padding-top: 22px; }

.deva { font-family: var(--font-deva); }

@media (min-width: 720px) {
  .people { grid-template-columns: repeat(3, 1fr); }
  .footer-inner { grid-template-columns: 1.3fr 1fr 1fr; align-items: start; }
  .footer-legal { grid-column: 1 / -1; }
}

/* ============================================================
   NO-JS / REDUCED MOTION / SAVE-DATA / SMALL SCREENS
   All handled by the absence of .has-film — see the note at the top of
   THE FILM. The only extra rule needed is hiding the still once the
   canvas takes over.
   ============================================================ */

.film-poster { display: block; width: 100%; }
.has-film .film-poster { display: none; }
/* The HUD is part of the hero copy's arrival, not of the title card. */
.has-film .film-hud { display: flex; opacity: var(--hero-copy-o, 1); }
.has-film .film-scrim { display: block; }
.has-film .citation-beat .beat-inner { transform: translateY(-10vh); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
