/* ==========================================================================
   FAITH CONSCIOUSNESS  —  Shared Design System
   Dr. Leslie Wells teaching site. Static HTML/CSS/vanilla JS.

   Concept: "Cosmic Cathedral, warmed."
   A darkened sanctuary read through an oculus into deep cosmic indigo.
   Vastness as reverence. Gold is rationed, appearing only where meaning
   gathers. Light is pooled, not painted. Hierarchy is carried by size and
   whitespace, not by stacking weights.

   This file defines ALL design tokens as CSS custom properties. Every page
   downstream must compose from these variables and never hard-code values.

   Fonts are self-hosted, loaded in each page's <head> via css/fonts.css
   (woff2 in assets/fonts/): Cormorant Garamond (display) + Hanken Grotesk (body).

   Copy rule honoured everywhere: no em dashes in visible copy.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {

  /* ---- Color: surfaces (void -> nave -> depth -> cloister) ---- */
  --color-void:            #05071A; /* deepest background: page base, footer floor */
  --color-nave:            #0C1230; /* primary section background, one step up */
  --color-depth:           #1A2148; /* raised surfaces: cards, panels, quote blocks */
  --color-cloister:        #222A55; /* hover / pressed card state */
  --color-line:            #2A3160; /* opaque hairline borders, input outlines */
  --color-control-border:  #737B9B; /* shell-control edge: 4.79:1 on void */
  --color-line-soft:       rgba(244, 239, 227, 0.08); /* translucent seam on any depth */
  /* Mask stops are alpha channels, not colours: only the opacity is read.
     Named so no page carries a raw literal (CODEX-R7: two #000 in the
     marquee mask bypassed the token system). */
  --mask-opaque:           rgba(0, 0, 0, 1);

  /* ---- Color: the candlelit gold accent (rationed) ---- */
  --color-gold:            #E0B868; /* primary sacred accent: eyebrows, links, rules */
  --color-gold-bright:     #E6BE73; /* brightest spark: focal stars, focus rings */
  --color-gold-deep:       #C98A2E; /* hover / pressed gold */
  --color-gold-on-light:   #956722; /* same gold hue at 36% HSL lightness: AA text on vellum */
  /* Gold as light, kept to two rationed sparks: the steady --color-gold (224,184,104)
     and the brighter focal --color-gold-bright (230,190,115) for stars and focus rings.
     The tint scale below steps the STEADY gold in opacity only, so every glow, wash,
     hairline and frame is that one candlelight at a measured strength, never a fresh hue. */
  --gold-tint-04:          rgba(224, 184, 104, 0.04); /* faintest fade (rule tails) */
  --gold-tint-06:          rgba(224, 184, 104, 0.06); /* faintest wash: ghost-button fill */
  --gold-tint-08:          rgba(224, 184, 104, 0.08); /* low dawn wash */
  --gold-tint-10:          rgba(224, 184, 104, 0.10); /* first horizon glow */
  --gold-tint-13:          rgba(224, 184, 104, 0.13); /* section glow pools */
  --gold-tint-16:          rgba(224, 184, 104, 0.16); /* pooled light inside frames */
  --gold-tint-22:          rgba(224, 184, 104, 0.22); /* hairlines, the scroll cue */
  --gold-tint-28:          rgba(224, 184, 104, 0.28); /* framing borders */
  --gold-bright-tint-20:   rgba(230, 190, 115, 0.20); /* the risen-light glow (climax) */
  --color-void-fade:       rgba(5, 7, 26, 0);          /* void at zero alpha: the far end of a glow gradient */
  --color-nave-veil:       rgba(12, 18, 48, 0.5);      /* nave at half: translucent chips over any ground */
  --gold-tint-70:          rgba(224, 184, 104, 0.70);  /* the live-dot's halo */
  --gold-bright-tint-40:   rgba(230, 190, 115, 0.40); /* the risen numeral aura */

  /* ---- Color: text neutrals as one warm->cool temperature ladder ----
     A single intentional axis, the same one the hero photograph is built on: text at
     the focus is warm bone (the candlelight), and as it recedes in importance it cools
     toward the indigo void. Importance therefore reads twice over, by temperature AND
     by a measured drop in contrast. Warm at the focus, cool in the depths. */
  --color-ivory:           #F4EFE3; /* warmest: headlines + lead (17.4:1 on void) */
  --color-ivory-dim:       #D7D2C4; /* warm: sustained long-form body (13.2:1 on void) */
  --color-slate:           #B9C0D8; /* cooling: muted lede / supporting voice (10.1:1 on void) */
  --color-periwinkle:      #A2A9C6; /* coolest readable: captions, metadata (AA at 13px) */
  --color-periwinkle-deep: #3A4267; /* disabled / placeholder only, never readable copy */
  --color-input-invalid:   #E0907A; /* invalid signup-field border on the void */
  --color-error:           #E6A491; /* readable signup error copy on the void */

  /* ---- Color: home-page section scrims over the fixed dawn ---- */
  --home-scrim-core:       rgba(5, 7, 26, 1);    /* invariant ground directly behind copy */
  --home-scrim-shoulder:   rgba(5, 7, 26, 0.88); /* protected feather inside the gutter */
  --home-scrim-clear:      rgba(5, 7, 26, 0);    /* open edge where the dawn reads through */

  /* ---- Color: teaching-page coda scrim over the risen dawn ---- */
  --teaching-coda-scrim-core:  rgba(5, 7, 26, 0.68); /* localized ground behind the gold coda */
  --teaching-coda-scrim-clear: rgba(5, 7, 26, 0);    /* feather back into the photograph */

  /* ---- Color: the single warm "vellum" inverted section ---- */
  --color-vellum:          #FBF6EC; /* warm paper background, used exactly once */
  --color-ink:             #1A1E33; /* text on vellum (15.3:1, AAA) */
  --color-ink-soft:        #3C3F52; /* softer ink for sustained vellum body (9.7:1, AAA) */
  --color-caption-on-vellum: #6A6A82; /* cool caption ink on the warm inverted ground */

  /* ---- Atmosphere: photographic, not decorative ----
     Depth comes from real imagery, flat fields, and grain, never a colour wash.
     The only retained "gradients" are a fine gold rule and a NEUTRAL vignette
     (edge darkening, the way a real photograph falls off for legibility). */
  --vignette:      radial-gradient(125% 95% at 50% 32%, rgba(5, 7, 26, 0) 42%, rgba(3, 4, 16, 0.58) 100%);
  --gold-hairline: linear-gradient(90deg, rgba(224, 184, 104, 0) 0%, #E0B868 50%, rgba(224, 184, 104, 0) 100%);
  --gold-cta:       #E0B868; /* flat gold, no amber sheen */
  --gold-cta-hover: #C98A2E;
  /* Film grain: an SVG noise tile that removes the synthetic smoothness. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --star-twinkle-from: 0.30;
  --star-twinkle-to:   0.85;

  /* ---- Typography: families ---- */
  --font-display: 'Cormorant Garamond', 'Cormorant Garamond Fallback', Georgia, 'Times New Roman', serif;
  --font-body:    'Hanken Grotesk', 'Hanken Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif;

  /* ---- Typography: fluid scale (sizes) ---- */
  --text-display:  clamp(2.75rem, 7vw, 5.5rem);     /* hero display, Cormorant 500 */
  --text-h1:       clamp(2.25rem, 5vw, 3.75rem);    /* page title step */
  --text-h2:       clamp(1.875rem, 1rem + 2.5vw, 3.25rem);   /* section headings, Cormorant 500 (rem term keeps the tablet step open) */
  --text-h3:       clamp(1.5rem, 2.4vw, 1.75rem);   /* sub-heads / card titles, Cormorant 600 */
  --text-lede:     clamp(1.25rem, 1.6vw, 1.3125rem);/* lede / intro, Hanken 400 */
  --text-body:     clamp(1.125rem, 1.05rem + 0.35vw, 1.1875rem);/* teaching copy, Hanken 400 (18px floor on phones) */
  --text-quote:    clamp(1.75rem, 3vw, 2rem);       /* pull-quotes, Cormorant italic 400 */
  --text-ui:       1rem;                            /* button labels, UI controls (16px floor) */
  --text-caption:  1rem;                            /* captions, metadata (16px floor) */
  --text-metadata: 0.8125rem;                       /* shared tracked-caps metadata role */
  --text-brand:    1.2rem;                          /* shell wordmark */
  --text-brand-mark: var(--text-metadata);          /* raised registered mark, on the metadata step */
  --text-home-hero: clamp(2.15rem, 1.25rem + 4vw, 5.5rem); /* home-page display */
  --text-statement: clamp(1.25rem, 0.75rem + 1.75vw, 2.5rem); /* home scripture pull quote */
  --text-era-shift: clamp(1.25rem, 1rem + 0.5vw, 1.55rem); /* era transformation motto */
  --text-monogram: clamp(3rem, 2rem + 3vw, 4.25rem); /* portrait placeholder initials */
  --text-era-number-mobile: clamp(2.25rem, 1.65rem + 4vw, 3rem); /* compact era folios */
  --text-trademark: 0.45em;                         /* registered mark beside display type */
  /* Radio's display and numeral roles preserve the page's tuned proportions,
     but live on the shared scale instead of as anonymous page literals. */
  --text-radio-hero: clamp(2.5rem, 6vw, 4.5rem);
  --text-radio-signature: clamp(1.25rem, 2.4vw, 1.75rem);
  --text-radio-featured-numeral: clamp(5rem, 12vw, 8rem);
  --text-radio-featured-title: clamp(2rem, 3.4vw, 2.75rem);
  --text-radio-lead-title: clamp(2rem, 3.4vw, 2.75rem);
  --text-radio-card-numeral: clamp(3.5rem, 9vw, 5.25rem);
  --text-radio-hero-compact: clamp(2.25rem, 9vw, 3.25rem);
  --text-radio-featured-numeral-compact: clamp(4.5rem, 22vw, 7rem);
  --size-radio-cover-motif: clamp(3.5rem, 9vw, 5.5rem);
  --shell-rule-offset: 0.35em;                      /* nav rule below the text baseline */
  --tracking-metadata: 0.22em;
  --weight-metadata: 600;
  /* Real small caps (Cormorant SC). Larger than the 13px tracked-caps role
     because small-cap forms sit at x-height and read smaller at equal size. */
  --font-smallcaps: 'Cormorant SC', 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  /* Numeral roles. The served Cormorant faces carry `lnum` and `tnum`;
     Hanken does not. Metadata uses Cormorant SC, whose shipped tables also
     carry `smcp`, so none of these declarations asks a face for a feature it
     cannot provide. */
  --font-numeral-display: var(--font-display);
  --font-numeral-metadata: var(--font-smallcaps);
  --features-numeral-display: "lnum" 1;
  --features-numeral-tabular: "lnum" 1, "tnum" 1;
  --features-numeral-metadata: "smcp" 1, "lnum" 1, "tnum" 1;
  --text-metadata-sc: 1rem;
  --weight-metadata-sc: 600;
  --tracking-metadata-sc: 0.08em;
  --color-metadata: var(--color-periwinkle);
  /* FABLE-R0-4: the metadata role rendered periwinkle on section eyebrows but
     gold on episode dates, via an anonymous page-scoped override. The split is
     wanted (a broadcast date is the episode's own mark, not a section label),
     but one role wearing two colours by container is drift. It is now a NAMED
     role, so the token layer says what renders. */
  --color-metadata-date: var(--color-gold);
  --text-eyebrow:  var(--text-metadata);            /* compatibility alias for page-scoped metadata */

  /* ---- Spacing scale (generous; carries hierarchy) ---- */
  --space-3xs: 0.25rem;  /* 4px  */
  --space-2xs: 0.5rem;   /* 8px  */
  --space-xs:  0.75rem;  /* 12px */
  --space-sm:  1rem;     /* 16px */
  --space-md:  1.5rem;   /* 24px */
  --space-lg:  2.5rem;   /* 40px */
  --space-xl:  4rem;     /* 64px */
  --space-2xl: 6rem;     /* 96px, section padding floor */
  --space-3xl: clamp(6rem, 14vh, 12.5rem);  /* section vertical padding */
  --space-4xl: clamp(8rem, 20vh, 16rem);    /* hero / closing breathing room */
  --space-5xl: 20rem;    /* 320px, maximum dramatic void */

  /* ---- Radii ----
     Softened 2026-08-26 (Felix): the 2px button and input radii read as hard
     right angles at every real size, which is what he saw on "Get the free
     introduction" and "Join the Movement". These are a gentle curve, NOT a
     pill: deliberately well short of circular so the architectural, engraved
     feeling of the site survives. Everything on the site points at these
     tokens, so the curve stays consistent by construction. */
  --radius-button: 8px;
  --radius-card:   12px;
  --radius-input:  8px;
  --radius-sm:     6px;  /* small chips, swatches, hairline rules */
  --radius-pill:   999px;/* star-dot and focus-ring only */

  /* ---- Shadows / glows ---- */
  --shadow-card:      0 1px 2px rgba(5, 7, 26, 0.4), 0 12px 32px rgba(5, 7, 26, 0.45);
  --shadow-plate:     0 32px 64px -22px rgba(5, 7, 26, 0.85), 0 12px 28px rgba(5, 7, 26, 0.55); /* the physical-book 3D shadow: hero cover + tipped-in plates */
  --shadow-gold-glow: 0 0 28px rgba(224, 184, 104, 0.22);
  /* Two neutral layers ensure that at least one ring edge reads against each
     shell ground: void against gold or ivory, ivory against the void. */
  --focus-ring:       0 0 0 2px var(--color-void), 0 0 0 4px var(--color-ivory);
  --shadow-pool:      0 0 120px 40px rgba(230, 190, 115, 0.06);

  /* ---- Transitions / motion ---- */
  --ease-entrance: cubic-bezier(0.22, 0.61, 0.36, 1); /* decelerating, calm arrival */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-fall:     cubic-bezier(0.55, 0.085, 0.68, 0.53); /* a drop gathering speed as it falls (cue) */
  --ease-drift:    cubic-bezier(0.37, 0, 0.63, 1);        /* slow sine breath (star twinkle) */
  --dur-entrance:  900ms;
  --dur-rule:      1100ms;
  --dur-hover:     240ms;
  --dur-twinkle:   9s;
  --stagger:       80ms;

  /* ---- Layout ---- */
  --container-max:     1200px;
  --container-content: 960px;
  --measure:           66ch;   /* body teaching measure */
  --measure-lede:      60ch;
  --gutter:            clamp(1.25rem, 5vw, 4rem);
  --hairline-width:    160px;
  --header-height:     76px;

  /* ---- Ethereal: starfield (generated, near-subliminal) ---- */
  --starfield-static:
    -157px 614px 0 0 rgba(244,239,227,0.52), -672px 470px 0 0.5px rgba(244,239,227,0.35),
    -702px 569px 0 0 rgba(244,239,227,0.42), 68px 136px 0 0.5px rgba(244,239,227,0.43),
    49px 11px 0 0 rgba(244,239,227,0.61), 471px 285px 0 0.5px rgba(244,239,227,0.82),
    379px 123px 0 0 rgba(244,239,227,0.84), 320px 510px 0 0 rgba(244,239,227,0.46),
    287px 19px 0 0 rgba(244,239,227,0.47), -609px 247px 0 0 rgba(244,239,227,0.65),
    -621px 222px 0 0 rgba(244,239,227,0.33), 447px 41px 0 0 rgba(244,239,227,0.67),
    771px 82px 0 0 rgba(244,239,227,0.62), -80px 76px 0 0 rgba(244,239,227,0.74),
    -653px 242px 0 0 rgba(244,239,227,0.59), 673px 154px 0 0 rgba(244,239,227,0.63),
    -579px 196px 0 0 rgba(244,239,227,0.39), -509px 597px 0 0 rgba(244,239,227,0.53),
    745px 229px 0 0 rgba(244,239,227,0.73), -124px 344px 0 0.5px rgba(244,239,227,0.63),
    812px 159px 0 0 rgba(244,239,227,0.76), 150px 346px 0 0 rgba(244,239,227,0.34),
    505px 245px 0 0 rgba(244,239,227,0.67), -238px 364px 0 0 rgba(244,239,227,0.79),
    -774px 606px 0 0.5px rgba(244,239,227,0.5), -581px 183px 0 0 rgba(244,239,227,0.42),
    -556px 385px 0 0 rgba(244,239,227,0.52), -655px 30px 0 0 rgba(244,239,227,0.52),
    -540px 468px 0 0 rgba(244,239,227,0.78), 626px 134px 0 0 rgba(244,239,227,0.5),
    -348px 26px 0 0 rgba(244,239,227,0.4), 528px 50px 0 0.5px rgba(244,239,227,0.57),
    -447px 61px 0 0 rgba(244,239,227,0.3), 274px 109px 0 0 rgba(244,239,227,0.61),
    594px 511px 0 0 rgba(244,239,227,0.82), 115px 557px 0 0.5px rgba(244,239,227,0.73),
    -17px 124px 0 0 rgba(244,239,227,0.52), 479px 126px 0 0 rgba(244,239,227,0.4),
    82px 29px 0 0 rgba(244,239,227,0.49), -611px 8px 0 0 rgba(244,239,227,0.38),
    -76px 273px 0 0 rgba(244,239,227,0.34), 437px 112px 0 0 rgba(244,239,227,0.65),
    413px 106px 0 0 rgba(244,239,227,0.37), 134px 174px 0 0 rgba(244,239,227,0.47),
    -611px 396px 0 0 rgba(244,239,227,0.71), 597px 29px 0 0.5px rgba(244,239,227,0.31),
    -80px 25px 0 0 rgba(244,239,227,0.6), 732px 207px 0 0 rgba(244,239,227,0.84),
    605px 496px 0 0 rgba(244,239,227,0.59), -92px 418px 0 0.5px rgba(244,239,227,0.59),
    -145px 292px 0 0 rgba(244,239,227,0.64), -330px 467px 0 0 rgba(244,239,227,0.71),
    -210px 150px 0 0.5px rgba(230,190,115,0.9), 330px 96px 0 0.5px rgba(230,190,115,0.9),
    70px 260px 0 0.5px rgba(230,190,115,0.9);
  --starfield-twinkle:
    -167px 328px 0 0.5px rgba(244,239,227,0.35), -132px 70px 0 0 rgba(244,239,227,0.59),
    726px 18px 0 0 rgba(244,239,227,0.54), 510px 80px 0 0 rgba(244,239,227,0.31),
    694px 96px 0 0.5px rgba(244,239,227,0.31);
}

/* --------------------------------------------------------------------------
   2. RESET + BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background-color: var(--color-void);
  color: var(--color-ivory-dim);
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 400;
  line-height: 1.85;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Typographic polish: real kerning, ligatures + contextual alternates,
     optical sizing on the variable faces, and pretty wrapping so body copy
     never leaves a lone word stranded on the last line. */
  font-kerning: normal;
  font-feature-settings: "kern", "liga", "calt";
  font-optical-sizing: auto;
  text-wrap: pretty;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

::selection { background: rgba(224, 184, 104, 0.25); color: var(--color-ivory); }

/* --------------------------------------------------------------------------
   3. TYPOGRAPHY
   Cormorant Garamond carries display sizes; Hanken Grotesk stays quiet under copy.
   -------------------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  color: var(--color-ivory);
  margin: 0;
  font-weight: 500;
  /* Balance multi-line headings so the lines are evenly weighted, not
     bottom-heavy or orphaned (hero h1 uses manual .line spans, untouched). */
  text-wrap: balance;
}

h1, .display {
  font-size: var(--text-display);
  line-height: 1.05;
  letter-spacing: -0.015em;
  font-weight: 500;
  max-width: 16ch;
}

.page-title {
  font-size: var(--text-h1);
  line-height: 1.1;
  letter-spacing: -0.012em;
}

h2, .h2 {
  font-size: var(--text-h2);
  line-height: 1.15;
  letter-spacing: -0.01em;
  font-weight: 500;
}

h3, .h3 {
  font-size: var(--text-h3);
  line-height: 1.2;
  font-weight: 600; /* heavier so Cormorant never reads thin at sub-head size */
}

/* The one warm gesture: a Cormorant italic gold phrase completing a headline */
.display-accent, .accent-italic {
  font-style: italic;
  color: var(--color-gold);
  font-weight: 500;
}

p { margin: 0; }
p + p { margin-top: var(--space-md); }

.lede {
  font-family: var(--font-body);
  font-size: var(--text-lede);
  line-height: 1.7;
  font-weight: 400;
  color: var(--color-slate);
  max-width: var(--measure-lede);
}

.body, .prose p {
  font-size: var(--text-body);
  line-height: 1.85;
  color: var(--color-ivory-dim);
}
.prose { max-width: var(--measure); }

blockquote, .quote {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--text-quote);
  line-height: 1.4;
  color: var(--color-ivory);
  margin: 0;
  max-width: var(--measure-lede);
}

/* Shared tracked-caps metadata role */
.eyebrow,
/* The metadata role: letterspaced uppercase in the body face.

   RULED BY FELIX 2026-08-26: all caps, across the whole site. This replaces the
   real-small-caps treatment added earlier the same day. Cormorant SC's `smcp`
   table only draws small caps from LOWERCASE input, so "all caps" and "small
   caps" are mutually exclusive here; Felix chose all caps, and it is the
   treatment the site carried before the small-caps change. `text-transform`
   therefore belongs here and must not be removed as a stale override again.

   Set in ONE place so every page inherits it. Two pages previously carried
   their own copy of this block and drifted apart from each other; that is the
   failure this central rule exists to prevent. */
.label-wide {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--text-metadata);
  font-weight: var(--weight-metadata);
  letter-spacing: var(--tracking-metadata);
  text-transform: uppercase;
  color: var(--color-metadata);
}
.eyebrow {
  margin: 0;
}

.caption {
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.5;
  color: var(--color-periwinkle);
}

/* Scripture citations: the SAME metadata role as .eyebrow, so one role never
   splits into two treatments. That promise predates the casing change and still
   holds: when the role went to all caps (Felix, 2026-08-26) the citations went
   with it. The homepage citation had been left behind on small caps while the
   book page's had already moved, which is exactly the split this rule exists to
   prevent (FABLE-R7-3). */
.statement__cite,
.book-intro__cite {
  font-family: var(--font-body);
  font-size: var(--text-metadata);
  font-weight: var(--weight-metadata);
  letter-spacing: var(--tracking-metadata);
  text-transform: uppercase;
  color: var(--color-metadata);
  text-align: center;
  margin-top: var(--space-md);
}

/* Section heading with a single gold star catching the light */
.star-heading::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 0.5em;
  border-radius: var(--radius-pill);
  background: var(--color-gold-bright);
  box-shadow: 0 0 9px rgba(230, 190, 115, 0.65);
  vertical-align: middle;
  transform: translateY(-0.18em);
}

/* --------------------------------------------------------------------------
   4. THE GOLD HAIRLINE  (far-candlelight signature rule)
   -------------------------------------------------------------------------- */
.gold-rule {
  display: block;
  position: relative;
  width: var(--hairline-width);
  max-width: 60vw;
  height: 1px;
  border: 0;
  background: var(--gold-hairline);
  transform-origin: center;
}
/* Signature: the brand's four-point star, threaded on the candlelight hairline at its
   center. The same star is the wordmark and the favicon, so every section opens with
   the mark itself, the one element only this site owns. Restrained, not decorative. */
.gold-rule::before {
  content: "";
  position: absolute; top: 50%; left: 50%;
  width: 11px; height: 11px;
  transform: translate(-50%, -50%);
  background: var(--color-gold-bright);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3 C12.4 8 15.6 11.1 21 11.5 C15.6 11.9 12.4 15 12 20 C11.6 15 8.4 11.9 3 11.5 C8.4 11.1 11.6 8 12 3 Z' fill='%23000'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3 C12.4 8 15.6 11.1 21 11.5 C15.6 11.9 12.4 15 12 20 C11.6 15 8.4 11.9 3 11.5 C8.4 11.1 11.6 8 12 3 Z' fill='%23000'/%3E%3C/svg%3E") center / contain no-repeat;
  filter: drop-shadow(0 0 4px rgba(230, 190, 115, 0.5));
}
/* The star settles in just after its thread has finished drawing. */
.js .gold-rule.reveal::before { opacity: 0; transition: opacity var(--dur-entrance) var(--ease-entrance); }
.gold-rule.reveal.is-visible::before { opacity: 1; transition-delay: 0.5s; }

/* --------------------------------------------------------------------------
   5. LINKS
   Gold text with an underline that grows from the left.
   -------------------------------------------------------------------------- */
a {
  color: var(--color-gold);
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--dur-hover) var(--ease-standard),
              color var(--dur-hover) var(--ease-standard);
}
a:hover { background-size: 100% 1px; }
a:focus-visible {
  outline: none;
  border-radius: var(--radius-sm);
  box-shadow: var(--focus-ring);
}

/* --------------------------------------------------------------------------
   6. BUTTONS
   One true primary (warm gold), a quiet ghost secondary, a tertiary link.
   Labels are sentence case so they read as inscriptions, not widgets.
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  font-family: var(--font-body);
  font-size: var(--text-ui);
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
  padding: 16px 34px;
  border: 1px solid transparent;
  border-radius: var(--radius-button);
  cursor: pointer;
  text-decoration: none;
  background-image: none; /* cancel the link underline mechanism */
  transition: background var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard),
              color var(--dur-hover) var(--ease-standard),
              box-shadow var(--dur-hover) var(--ease-standard),
              transform var(--dur-hover) var(--ease-standard);
}
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.btn-primary {
  background: var(--gold-cta);
  color: var(--color-void);
}
.btn-primary:hover {
  background: var(--gold-cta-hover);
  box-shadow: var(--shadow-gold-glow);
  transform: translateY(-1px);
}
.btn-primary:active { transform: translateY(0); }

.btn-secondary {
  background: transparent;
  border-color: var(--color-line);
  color: var(--color-ivory);
  font-weight: 500;
}
.btn-secondary:hover {
  border-color: var(--color-gold);
  color: var(--color-gold);
  background: var(--gold-tint-06);
}

/* Tertiary inline link: gold with a left-growing underline (inherits `a`) */
.btn-tertiary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding-block: var(--space-2xs);
  font-family: var(--font-body);
  font-size: var(--text-ui);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--color-gold);
  white-space: nowrap;
}

/* Without this the browser's default blue ring applies, which measured 2.59:1
   against the card ground and fails the 3:1 focus floor. Every sibling control
   already uses this token; this one had fallen out of the system. */
.btn-tertiary:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }

/* Visually-hidden (screen-reader only) utility */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   SIGNUP  —  reusable premium email capture with a graceful confirm state.
   Behaviour in js/main.js (initSignup). Drop a [data-signup] block anywhere.
   -------------------------------------------------------------------------- */
.signup { max-width: 34rem; margin-inline: auto; }
.signup__form { display: flex; gap: var(--space-sm); align-items: stretch; }
.signup__field { flex: 1 1 auto; min-width: 0; }
.signup__input {
  width: 100%; height: 54px; padding: 0 18px;
  font-family: var(--font-body); font-size: 1rem; line-height: 1.2;
  color: var(--color-ivory);
  background: rgba(244, 239, 227, 0.04);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-input);
  transition: border-color var(--dur-hover) var(--ease-standard),
              box-shadow var(--dur-hover) var(--ease-standard),
              background-color var(--dur-hover) var(--ease-standard);
}
.signup__input::placeholder { color: var(--color-periwinkle); }
.signup__input:focus {
  outline: none; border-color: var(--color-gold);
  box-shadow: var(--focus-ring); background: rgba(244, 239, 227, 0.06);
}
.signup__input.is-invalid { border-color: var(--color-input-invalid); }
.signup__submit { flex: none; height: 54px; }
.signup__error { margin-top: var(--space-sm); color: var(--color-error); font-size: 1rem; }
.signup__note { margin-top: var(--space-md); }
/* Kit-ready signup markup is exposed by the early `.js` class. With
   JavaScript absent, only the form's honest noscript notice is rendered. */
.signup__js-only { display: none; }
.js .signup__js-only { display: block; }
.signup__pending { margin: 0 0 var(--space-md); color: var(--color-ivory-dim); }
.signup__input:disabled,
.signup__input[readonly] { cursor: not-allowed; opacity: 1; }

/* Confirmation state (shown once the form is submitted) */
.signup__confirm {
  display: none; flex-direction: column; align-items: center;
  gap: var(--space-xs); text-align: center;
}
.signup.is-done .signup__form,
.signup.is-done .signup__error,
.signup.is-done .signup__note { display: none; }
.signup.is-done .signup__confirm {
  display: flex; outline: none;
  animation: signup-confirm-in 0.6s var(--ease-entrance) both;
}
.signup__check svg { width: 56px; height: 56px; display: block; }
.signup__check-circle { fill: none; stroke: var(--color-gold); stroke-width: 2; opacity: 0.45; }
.signup__check-mark {
  fill: none; stroke: var(--color-gold-bright); stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 48; stroke-dashoffset: 48;
}
.signup.is-done .signup__check-mark { animation: signup-check 0.6s var(--ease-entrance) 0.15s forwards; }
.signup__confirm-title { font-family: var(--font-display); font-size: clamp(1.5rem, 3vw, 2rem); color: var(--color-ivory); margin: 0; }
.signup__confirm-text { color: var(--color-slate); margin: 0; }

@keyframes signup-confirm-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes signup-check { to { stroke-dashoffset: 0; } }

@media (max-width: 560px) {
  .signup__form { flex-direction: column; }
  .signup__submit { width: 100%; }
}

/* --------------------------------------------------------------------------
   7. LAYOUT HELPERS
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--content { max-width: var(--container-content); }
.container--narrow  { max-width: var(--measure); }

.section {
  position: relative;
  padding-block: var(--space-3xl);
}

.measure       { max-width: var(--measure); }
.measure-lede  { max-width: var(--measure-lede); }

/* Page hero: the standard top section for interior pages (title + lede) */
.page-hero {
  position: relative;
  min-height: 76vh;
  display: flex;
  align-items: center;
  padding-block: var(--space-4xl);
}
.page-hero__inner { max-width: var(--measure); }
.page-hero .gold-rule { margin: var(--space-md) 0 var(--space-lg); }
.page-hero__title { margin-bottom: var(--space-lg); }

/* The single inverted warm section (use exactly once across the site) */
.section-vellum {
  background: var(--color-vellum);
  color: var(--color-ink);
}
.section-vellum h1, .section-vellum h2, .section-vellum h3,
.section-vellum .quote, .section-vellum .display { color: var(--color-ink); }
.section-vellum .eyebrow { color: var(--color-gold-on-light); }
.section-vellum a { color: var(--color-gold-on-light); }
.section-vellum .caption { color: var(--color-caption-on-vellum); }

/* --------------------------------------------------------------------------
   FILM GRAIN  (removes synthetic smoothness; reads as shot, not generated)
   A fixed, near-invisible noise layer over the whole page. A real element,
   not a body pseudo-element: a fixed body::after makes iOS Safari paint
   scrolled-past page content into the status-bar strip (bisected in the
   Simulator, 2026-08-28); the identical overlay as a real div paints clean.
   -------------------------------------------------------------------------- */
.page-grain {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  background-image: var(--grain);
  background-size: 180px 180px;
  opacity: 0.05;
  mix-blend-mode: overlay;
}

/* --------------------------------------------------------------------------
   EDITORIAL DEVICES  (sequenced numerals, wide-tracked labels)
   For pacing a journey: the three eras as 01 / 02 / 03, etc.
   -------------------------------------------------------------------------- */
.era-number {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(3.5rem, 9vw, 7rem);
  line-height: 0.9;
  color: var(--color-gold);
}
.tracked { letter-spacing: 0.3em; }

/* --------------------------------------------------------------------------
   8. THE ETHEREAL ELEMENT
   A near-subliminal box-shadow starfield over flat deep fields, with a neutral
   vignette for legibility (in production, backed by real deep-sky photography).
   No decorative colour gradients. Confined to large empty sections, never
   behind body text.
   -------------------------------------------------------------------------- */
.ethereal-stage { position: relative; overflow: hidden; isolation: isolate; }

.vignette,
.starfield,
.starfield-twinkle {
  position: absolute;
  pointer-events: none;
  z-index: -1;
}

/* Neutral edge darkening for legibility over imagery (photographic falloff). */
.vignette { inset: 0; background: var(--vignette); }

/* Starfield is a single 1px point at top-center; stars are its box-shadows. */
.starfield,
.starfield-twinkle {
  top: 0;
  left: 50%;
  width: 1px;
  height: 1px;
  border-radius: var(--radius-pill);
  background: transparent;
}
.starfield        { box-shadow: var(--starfield-static); }
.starfield-twinkle {
  box-shadow: var(--starfield-twinkle);
  animation: star-twinkle var(--dur-twinkle) var(--ease-drift) infinite;
}

@keyframes star-twinkle {
  0%, 100% { opacity: var(--star-twinkle-from); }
  50%      { opacity: var(--star-twinkle-to); }
}

/* On smaller screens, dial the field back to protect legibility. */
@media (max-width: 640px) {
  .starfield, .starfield-twinkle { opacity: 0.6; }
}

/* --------------------------------------------------------------------------
   9. MOTION  (entrance reveals + gentle parallax)
   JS toggles .is-visible on .reveal elements; parallax sets --parallax.
   -------------------------------------------------------------------------- */
/* Hidden only when JS is present (the <html class="js"> guard). Without JS,
   or if a crawler does not execute it, .reveal content shows by default. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-entrance) var(--ease-entrance),
              transform var(--dur-entrance) var(--ease-entrance);
}
.reveal.is-visible { opacity: 1; transform: none; }

/* If the deferred reveal controller never takes ownership, do not leave
   meaningful content hidden. This class is set by the 1500ms head failsafe. */
html.reveal-failsafe .reveal,
html.reveal-failsafe .gold-rule.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

/* Gold rules draw in from the centre instead of rising */
.js .gold-rule.reveal {
  opacity: 0;
  transform: scaleX(0);
  transition: transform var(--dur-rule) var(--ease-entrance),
              opacity var(--dur-entrance) var(--ease-entrance);
}
.gold-rule.reveal.is-visible { opacity: 1; transform: scaleX(1); }

/* Parallax layers drift via the --parallax variable set in main.js */
.parallax {
  transform: translateY(var(--parallax, 0));
}

/* --------------------------------------------------------------------------
   SITE SHELL  —  reusable header / navigation + footer
   Dropped into every page (canonical source in /partials). Behaviour is in
   js/nav.js. Set <body class="has-hero" data-page="..."> per page.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) { :root { --header-height: 64px; } }

/* Skip link (accessibility) */
.skip-link {
  position: fixed; top: var(--space-md); left: var(--space-md);
  z-index: 2000;
  /* Parked with a clip, NOT a translate above the screen. iOS Safari paints
     the region above the layout viewport into the status-bar strip when its
     toolbar is collapsed, so an element parked at translateY(-200%) showed
     the words "Skip to content" beside the clock in every screenshot of the
     bug (Felix, 2026-08-28; reproduced in the iOS Simulator). A clipped
     element paints nothing anywhere while staying focusable, so the link
     still appears for keyboard users exactly as before. */
  clip-path: inset(50%);
  background: var(--color-void); color: var(--color-ivory);
  border: 1px solid var(--color-line);
  font-family: var(--font-body); font-size: var(--text-ui); font-weight: 600;
  letter-spacing: 0.02em;
  padding: 14px 22px; border-radius: var(--radius-button);
}
.skip-link:focus { clip-path: none; outline: none; box-shadow: var(--focus-ring); }

/* ---- Header ---- */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 1000;
  height: var(--header-height);
  display: flex; align-items: center;
  background: var(--color-void);
  border-bottom: 1px solid var(--color-line-soft);
  box-shadow: none;
  transition: background-color var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard),
              box-shadow var(--dur-hover) var(--ease-standard);
}
.site-header__inner {
  width: 100%; max-width: var(--container-max);
  margin-inline: auto;
  /* Respect notch / rounded-corner safe areas in landscape on phones. */
  padding-inline: max(var(--gutter), env(safe-area-inset-left)) max(var(--gutter), env(safe-area-inset-right));
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-lg);
}

/* Solid is the safe default. JavaScript may opt hero pages into the original
   transparent treatment only while they are at the top of the page. */
.nav-ready body.has-hero .site-header.is-at-top {
  background: transparent;
  border-bottom-color: transparent;
  box-shadow: none;
}
.site-header.is-scrolled {
  background: var(--color-void);
  border-bottom-color: var(--color-control-border);
  box-shadow: 0 8px 24px var(--color-depth);
}
body:not(.has-hero) { padding-top: var(--header-height); }

/* ---- Brand wordmark ---- */
.brand {
  display: inline-flex; align-items: center; gap: var(--space-2xs);
  background-image: none; line-height: 1;
  min-height: 44px; /* 44px touch floor (DESIGN-FLOORS); centred content keeps
                       the wordmark's optical position in the header bar */
}
.brand__mark { color: var(--color-gold); display: inline-flex; flex: none; }
.brand__word,
.mobile-nav__proposition,
.site-footer__tagline {
  font-family: var(--font-display); font-weight: 500; font-size: var(--text-brand);
  letter-spacing: 0.015em;
}
.brand__word { color: var(--color-ivory); }
.trademark-name { white-space: nowrap; }
.brand__word .trademark-mark,
.site-footer__base .trademark-mark {
  font-family: var(--font-body);
  font-size: var(--text-brand-mark);
  line-height: 0;
  letter-spacing: 0;
  margin-inline-start: 0.04em;
  vertical-align: super;
}
.brand:hover .brand__mark { color: var(--color-gold-bright); }

/* On desktop, the name reads as a compact masthead rather than a navigation
   label. The compact measure gives the larger display step room without
   widening the brand at the narrow edge of the desktop layout. */
@media (min-width: 1050px) {
  :root { --header-height: 88px; }

  .site-header .brand__word {
    inline-size: 6.25em;
    white-space: normal;
    font-size: var(--text-h3);
    line-height: 0.9;
  }

  .site-header .brand__word .trademark-mark {
    vertical-align: 0.2em;
  }
}

/* ---- Desktop navigation ---- */
.nav-desktop { display: flex; align-items: center; gap: var(--space-xl); }
.nav-desktop__list {
  display: flex; align-items: center; gap: var(--space-lg);
  list-style: none; margin: 0; padding: 0;
}
.nav-desktop__list a {
  display: inline-block; /* makes the 44px min-width below effective (ignored on inline boxes) */
  font-family: var(--font-body); font-size: var(--text-ui); font-weight: 400;
  letter-spacing: 0.02em; color: var(--color-ivory-dim); padding-block: 14px;
  min-width: 44px; /* short labels like "Home" still get a 44px-wide hit box */
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 calc(100% - 14px - 0.5em + var(--shell-rule-offset));
  background-repeat: no-repeat;
  transition: color var(--dur-hover) var(--ease-standard),
              background-size var(--dur-hover) var(--ease-standard);
}

/* The desktop navigation begins where the established spacing curve reaches a
   full 24px between labels. It opens back to the wider established value as
   the header gains room; the link size stays constant across desktop. */
@media (min-width: 1050px) {
  .nav-desktop {
    gap: clamp(
      var(--space-xs),
      calc(16vw - 144px + var(--space-2xs)),
      var(--space-xl)
    );
  }
  .nav-desktop__list {
    gap: clamp(
      var(--space-3xs),
      calc(16vw - 144px),
      var(--space-lg)
    );
  }
  .nav-desktop__list a {
    font-size: var(--text-ui);
    white-space: nowrap;
  }
}
/* ---- Primary CTA, set apart from the text links ---- */
.btn-cta {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-body); font-size: 1rem; font-weight: 600; letter-spacing: 0.04em;
  padding: 15px 26px; border-radius: var(--radius-button);
  background: var(--color-gold); color: var(--color-void);
  border: 1px solid var(--color-gold); background-image: none; white-space: nowrap;
  transition: background-color var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard),
              box-shadow var(--dur-hover) var(--ease-standard),
              transform var(--dur-hover) var(--ease-standard);
}
.btn-cta:hover {
  background: var(--color-gold-deep); border-color: var(--color-gold-deep);
  box-shadow: var(--shadow-gold-glow); transform: translateY(-1px);
}
.btn-cta:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Shell actions are outlines. Gold fill is reserved for each page's primary
   action inside main. */
.site-header .btn-cta,
.mobile-nav .mobile-nav__cta,
.site-footer .btn-cta {
  background: transparent;
  border-color: var(--color-control-border);
  color: var(--color-ivory);
  letter-spacing: 0.02em;
}
.site-header .btn-cta:hover,
.mobile-nav .mobile-nav__cta:hover,
.site-footer .btn-cta:hover {
  background: transparent;
  border-color: var(--color-ivory);
  color: var(--color-ivory);
  box-shadow: none;
  transform: none;
}
.site-header .btn-cta[aria-current="page"],
.mobile-nav .mobile-nav__cta[aria-current="page"],
.site-footer .btn-cta[aria-current="page"] {
  background: transparent;
  border-color: var(--color-control-border);
  color: var(--color-ivory);
  box-shadow: none;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.3em;
  transform: none;
}
.site-header .btn-cta[aria-current="page"]:focus-visible,
.mobile-nav .mobile-nav__cta[aria-current="page"]:focus-visible,
.site-footer .btn-cta[aria-current="page"]:focus-visible {
  box-shadow: var(--focus-ring);
}

/* ---- Hamburger toggle (mobile only) ----
   Icon-only by ruling (SPEC round 3, fix 1): DESIGN-FLOORS.md drops the
   visible "Menu" word for this client; the aria-label carries the name. */
.nav-toggle {
  display: none; width: 48px; height: 48px; padding: 0;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  background: transparent; border: 0; cursor: pointer;
}
.nav-toggle__bar {
  display: block; width: 24px; height: 1.5px; background: var(--color-ivory);
  transition: transform var(--dur-hover) var(--ease-standard),
              opacity var(--dur-hover) var(--ease-standard),
              background-color var(--dur-hover) var(--ease-standard);
}
.nav-toggle:hover .nav-toggle__bar { background: var(--color-ivory); }
.nav-toggle.is-active .nav-toggle__bar:first-child { transform: translateY(3.25px) rotate(45deg); }
.nav-toggle.is-active .nav-toggle__bar:last-child { transform: translateY(-3.25px) rotate(-45deg); }
.nav-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-button); }

/* ---- Mobile overlay menu (full-screen, on-brand cosmic) ---- */
.mobile-nav {
  position: fixed; inset: 0; z-index: 1100;
  background: var(--color-void); overflow-y: auto;
  opacity: 0; visibility: hidden;
  pointer-events: none;
  transition: opacity 0.45s var(--ease-entrance), visibility 0.45s linear;
}
.mobile-nav.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
.mobile-nav__inner {
  position: relative; z-index: 1; min-height: 100%;
  display: flex; flex-direction: column;
  /* The overlay is full-bleed, so it must inset its content for notch + home indicator. */
  padding:
    calc(var(--header-height) + var(--space-sm) + env(safe-area-inset-top))
    max(var(--gutter), env(safe-area-inset-right))
    calc(var(--space-md) + env(safe-area-inset-bottom))
    max(var(--gutter), env(safe-area-inset-left));
}
.mobile-nav .gold-rule { margin-bottom: var(--space-md); }
.mobile-nav__proposition {
  max-width: 34ch;
  margin: 0 0 var(--space-sm);
  color: var(--color-slate);
  line-height: 1.4;
}
.mobile-nav__proposition em { font-style: italic; color: var(--color-ivory-dim); }
.mobile-nav__list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--space-xs);
}
.mobile-nav__list a {
  font-family: var(--font-display); font-weight: 500; line-height: 1.1;
  font-size: clamp(2.109375rem, 9vw, 2.75rem);
  color: var(--color-ivory-dim); display: inline-flex;
  align-items: center; min-height: 44px; padding: 0 0 6px;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 calc(100% - 2px);
  background-repeat: no-repeat;
  transition: color var(--dur-hover) var(--ease-standard),
              background-size var(--dur-hover) var(--ease-standard);
}
.mobile-nav__cta {
  min-height: 44px; margin: var(--space-lg) 0 var(--space-md);
  padding-block: 13px; align-self: flex-start;
}
.mobile-nav__listen { display: flex; flex-direction: column; gap: var(--space-2xs); }
.mobile-nav__listen .label-wide { letter-spacing: var(--tracking-metadata-sc); }
.mobile-nav__links { display: flex; flex-wrap: wrap; gap: var(--space-lg); }
.mobile-nav__links a {
  color: var(--color-ivory-dim); font-size: var(--text-ui); font-weight: 400; letter-spacing: 0.02em;
  display: inline-flex; align-items: center; min-height: 44px; padding-block: 0;
  min-width: 44px; /* 44px-wide hit box even for short labels */
}

/* staggered entrance of the menu items when opened */
.mobile-nav__list li, .mobile-nav__cta, .mobile-nav__listen {
  opacity: 0; transform: translateY(12px);
  transition: opacity 0.5s var(--ease-entrance), transform 0.5s var(--ease-entrance);
}
.mobile-nav.is-open .mobile-nav__list li,
.mobile-nav.is-open .mobile-nav__cta,
.mobile-nav.is-open .mobile-nav__listen { opacity: 1; transform: none; }
.mobile-nav.is-open .mobile-nav__list li:nth-child(1) { transition-delay: 0.10s; }
.mobile-nav.is-open .mobile-nav__list li:nth-child(2) { transition-delay: 0.16s; }
.mobile-nav.is-open .mobile-nav__list li:nth-child(3) { transition-delay: 0.22s; }
.mobile-nav.is-open .mobile-nav__list li:nth-child(4) { transition-delay: 0.28s; }
.mobile-nav.is-open .mobile-nav__list li:nth-child(5) { transition-delay: 0.34s; }
.mobile-nav.is-open .mobile-nav__cta { transition-delay: 0.40s; }
.mobile-nav.is-open .mobile-nav__listen { transition-delay: 0.46s; }

body.nav-open { overflow: hidden; }

/* While the menu is open, lift the header (and its hamburger, now an X) above
   the overlay so the close control stays visible and tappable. The bar itself
   goes transparent so only the wordmark and the X read over the cosmic overlay. */
body.nav-open .site-header {
  z-index: 1200;
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom-color: transparent;
  box-shadow: none;
}

/* The synchronous head script compacts the small-screen header before paint.
   The deferred controller alone exposes the hamburger once it is working. If
   readiness misses the failsafe window, .nav-failsafe restores real links. */
@media (max-width: 1049px) {
  .site-header {
    position: relative; inset: auto; height: auto;
    min-height: var(--header-height);
  }
  .site-header__inner {
    flex-wrap: wrap; row-gap: var(--space-2xs); padding-block: var(--space-2xs);
  }
  body:not(.has-hero) { padding-top: 0; }
  .nav-desktop { display: block; flex: 0 0 100%; width: 100%; }
  .nav-desktop__list {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 var(--space-sm);
  }
  .nav-desktop__list a {
    display: flex; align-items: center; min-height: 44px; padding-block: 0;
  }
  .nav-desktop .btn-cta {
    display: inline-flex;
    margin: var(--space-xs) 0 var(--space-2xs);
  }
  .nav-toggle { display: none; }

  html.js:not(.nav-failsafe) .site-header {
    position: fixed; inset: 0 0 auto 0; height: var(--header-height);
    min-height: 0;
  }
  html.js:not(.nav-failsafe) .site-header__inner {
    flex-wrap: nowrap; row-gap: normal; padding-block: 0;
  }
  html.js:not(.nav-failsafe) body:not(.has-hero) { padding-top: var(--header-height); }
  html.js:not(.nav-failsafe) .nav-desktop { display: none; }
  html.js:not(.nav-failsafe) .nav-desktop .btn-cta { display: none; }
  html.nav-ready:not(.nav-failsafe) .nav-toggle { display: inline-flex; }
}

/* Keep the five-link navigation in one reading column throughout the laptop
   band. The listen block uses the second column beside it, while navigation
   type scales with viewport height to preserve the complete short-window menu. */
@media (min-width: 768px) and (max-width: 1049px) {
  .mobile-nav__inner {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto auto auto auto;
    column-gap: var(--space-lg);
    align-content: start;
  }
  .mobile-nav .gold-rule,
  .mobile-nav__proposition {
    grid-column: 1 / -1;
  }
  .mobile-nav__inner > nav {
    grid-column: 1;
    grid-row: 3;
  }
  .mobile-nav__list {
    gap: var(--space-xs);
  }
  .mobile-nav__list a {
    font-size: clamp(2.109375rem, calc(0.609375rem + 4vh), 2.75rem);
    white-space: nowrap;
  }
  .mobile-nav__cta {
    grid-column: 1;
    grid-row: 4;
    margin: var(--space-md) 0 0;
  }
  .mobile-nav__listen {
    grid-column: 2;
    grid-row: 3 / 5;
    align-self: end;
  }
}

/* Keep the complete phone menu above the fold when height is scarce without
   reducing its 44px targets, shrinking its type or removing content. */
@media (max-width: 767px) and (max-height: 700px) {
  .mobile-nav__inner {
    padding-top: calc(var(--header-height) + var(--space-3xs) + env(safe-area-inset-top));
    padding-bottom: calc(var(--space-2xs) + env(safe-area-inset-bottom));
  }
  .mobile-nav .gold-rule { margin-bottom: var(--space-3xs); }
  .mobile-nav__proposition { margin-bottom: var(--space-3xs); }
  .mobile-nav__list { gap: var(--space-3xs); }
  .mobile-nav__cta { margin: var(--space-sm) 0 var(--space-3xs); }
  .mobile-nav__listen { gap: var(--space-3xs); }
}

/* ---- Footer ---- */
.site-footer { position: relative; background: var(--color-void); border-top: 1px solid var(--color-line-soft); }
.site-footer__inner {
  max-width: var(--container-max); margin-inline: auto;
  padding: var(--space-3xl) var(--gutter) var(--space-2xl);
  display: grid;
  grid-template-columns: minmax(0, 1fr) max-content max-content;
  gap: clamp(var(--space-sm), 4vw, var(--space-xl));
}
.site-footer__brand { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-md); max-width: 38ch; }
.site-footer__tagline {
  color: var(--color-slate); margin: 0;
  line-height: 1.4;
}
.site-footer__tagline em { font-style: italic; color: var(--color-ivory-dim); white-space: nowrap; }
.site-footer__col-title {
  margin-bottom: var(--space-md);
}
.site-footer__nav ul, .site-footer__listen ul {
  list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2xs);
}
.site-footer__nav a, .site-footer__listen a {
  display: inline-block; padding-block: 0.75rem; /* 48px touch target */
  min-width: 44px; /* 44px-wide hit box even for short labels */
  color: var(--color-ivory-dim); font-size: var(--text-ui); font-weight: 400; letter-spacing: 0.02em;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 calc(100% - 12px - 0.5em + var(--shell-rule-offset));
  background-repeat: no-repeat;
  transition: color var(--dur-hover) var(--ease-standard), background-size var(--dur-hover) var(--ease-standard);
}
@media (min-width: 701px) {
  .site-footer__nav a, .site-footer__listen a { white-space: nowrap; }
}
@media (min-width: 768px) {
  .site-footer__inner {
    max-width: 50rem;
    grid-template-columns: max-content max-content max-content;
    justify-content: space-between;
    padding-inline: clamp(var(--space-sm), 2.5vw, var(--space-xl));
    gap: clamp(var(--space-sm), 2vw, var(--space-lg));
  }
  .site-footer__brand {
    width: 15.25rem;
    max-width: none;
    gap: var(--space-lg);
  }
  .site-footer__brand .brand {
    min-height: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-xs);
  }
  .site-footer__brand .brand__mark {
    width: var(--space-lg);
    height: var(--space-lg);
  }
  .site-footer__brand .brand__word {
    font-size: var(--text-h3);
  }
  /* Both footer lists share one rhythm. Stretching the shorter list to match the
     taller one's height made it step 118px against the other's 62px, so the two
     columns started together and visibly drifted apart. Same gap, both lists. */
}
/* One state language in every shell navigation zone: full light rule on hover,
   full heavier rule for the page the reader is already on. */
.nav-desktop__list a:hover,
.mobile-nav__list a:hover,
.site-footer__nav a:hover,
.site-footer__listen a:hover {
  color: var(--color-ivory);
  background-size: 100% 1px;
}
.nav-desktop__list a[aria-current="page"],
.mobile-nav__list a[aria-current="page"],
.site-footer__nav a[aria-current="page"] {
  color: var(--color-ivory);
  background-size: 100% 2px;
}
.site-footer__base { border-top: 1px solid var(--color-line-soft); }
.site-footer__base-inner {
  max-width: var(--container-max); margin-inline: auto;
  padding: var(--space-lg) var(--gutter);
  display: flex; justify-content: space-between; align-items: center; gap: var(--space-md); flex-wrap: wrap;
}
.site-footer__base .caption {
  margin: 0;
  font-weight: 400;
  letter-spacing: 0.02em;
}

@media (max-width: 700px) {
  .site-footer__inner {
    grid-template-columns: 1fr; gap: var(--space-md);
    padding: var(--space-lg) var(--gutter) var(--space-md);
  }
  .site-footer__listen { width: 88%; }
  .site-footer__brand { gap: var(--space-xs); }
  .site-footer__col-title { margin-bottom: var(--space-2xs); }
  .site-footer__nav ul, .site-footer__listen ul { gap: 0; }
  .site-footer__nav a, .site-footer__listen a {
    display: inline-flex; align-items: center; min-height: 44px;
    padding-block: 0;
  }
  .site-footer__base-inner {
    padding: var(--space-xs) var(--gutter); gap: var(--space-2xs);
  }
}

/* --------------------------------------------------------------------------
   10. REDUCED MOTION
   Collapse every entrance to an instant opacity-only reveal, disable
   parallax, and freeze the star twinkle.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  /* Scroll behaviour is NOT decided here. css/motion.css loads after this
     file and sets html { scroll-behavior: initial !important }, so any rule
     written here could never take effect. The scripted engine honours
     reduced motion by tearing itself down; see js/motion-engine.js. */
  .site-header,
  .mobile-nav,
  .nav-toggle__bar { transition: none !important; }
  .reveal,
  .gold-rule.reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .parallax { transform: none !important; }
  .mobile-nav__list li,
  .mobile-nav__cta,
  .mobile-nav__listen { opacity: 1 !important; transform: none !important; transition: none !important; }
  .signup.is-done .signup__confirm { animation: none !important; }
  .signup.is-done .signup__check-mark { animation: none !important; stroke-dashoffset: 0 !important; }
  .starfield-twinkle {
    animation: none !important;
    opacity: var(--star-twinkle-to);
  }
}


/* ============================================================
   COVER ART: the book cover with all meaningful text typeset live.
   Shared by book.html (hero) and index.html (teaser). The cover
   image is deliberately text-free, so the title, byline and author
   are layered over the art: a wording change is an edit here, never
   a new image bake.
   Sizes use container-query units so the type scales with the
   cover at any layout width.
   ============================================================ */
.cover-art {
  position: relative;
  display: block;
  container-type: inline-size;
}
.cover-art img { display: block; width: 100%; height: auto; }
.cover-art__titles {
  position: absolute;
  left: 7%;
  right: 7%;
  top: 7.5%;
  /* Hidden unless container-query units are supported: on an old browser the
     overlay disappears cleanly (the page's own heading carries the title)
     instead of rendering at inherited size and flooding the cover. */
  display: none;
  text-align: center;
  pointer-events: none;
}
@supports (container-type: inline-size) {
  .cover-art__titles { display: block; }
}
.cover-art__line {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  /* 9cqw + nowrap: each authored line stays ONE line at every cover width
     (10.5cqw broke "Really Works" onto a third line from 240-420px). */
  font-size: 9cqw;
  line-height: 1.18;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-ivory);
}
.cover-art__byline {
  display: block;
  margin-top: 3.4cqw;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  /* max(13px, ...): Felix ruled the byline UP to a 13px floor (round 4, fix 6),
     not exempted; it is the book's real subtitle. 4.1cqw takes over above a
     ~317px container, so it still scales with the cover. The byline carries no
     nowrap, so at floored widths it wraps to two lines rather than overflowing;
     the one-line-box guarantee on .cover-art__line (9cqw) is untouched. */
  font-size: max(13px, 4.1cqw);
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--color-gold);
}
.cover-art__author {
  position: absolute;
  left: 7%;
  right: 7%;
  bottom: 3.8%;
  display: none;
  font-family: var(--font-display);
  font-size: max(0.8125rem, 3.8cqw);
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.36em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-gold);
  pointer-events: none;
}
@supports (container-type: inline-size) {
  .cover-art__author { display: block; }
}

/* ============================================================================
   THE PERSISTENT EPISODE PLAYER
   Docks bottom left, minimises to a tab, survives navigation. Shared across
   every page, so it lives here rather than in radio.html's page-scoped block.
   ========================================================================= */
.fc-player {
  position: fixed;
  left: var(--gutter);
  bottom: var(--gutter);
  z-index: 900; /* under the header (1000) so it never covers the navigation */
  max-width: min(24rem, calc(100vw - (var(--gutter) * 2)));
}
.fc-player[hidden] { display: none; }

/* The player is fixed, so it floats over whatever is at the bottom of the
   page. While it is open the page gets matching room at its foot, so the last
   footer line is never sitting underneath it. Set on <html> by the script. */
/* Padding on <body> puts the space BELOW the footer, which leaves the footer
   itself still sitting under the player. The room has to go inside the last
   element instead. */
html[data-fc-player-open] .site-footer { padding-bottom: 13rem; }
@media (max-width: 760px) { html[data-fc-player-open] .site-footer { padding-bottom: 15rem; } }
html[data-fc-player-open][data-fc-player-min] .site-footer { padding-bottom: 6rem; }

/* The audio element is driven entirely by the controls below it. */
.fc-player audio { display: none; }

/* `display: grid` below outranks the browser's built-in [hidden] rule, so the
   panel stayed visible when the script hid it and the minimised player showed
   BOTH faces at once. Every element here that sets `display` needs its own
   hidden rule; the tab has one further down. */
.fc-player__panel[hidden] { display: none; }
.fc-player__panel {
  background: var(--color-depth);
  border: 1px solid var(--color-line-soft);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--space-md);
  display: grid;
  gap: var(--space-sm);
}

.fc-player__head { display: flex; align-items: flex-start; gap: var(--space-sm); }
.fc-player__title {
  margin: 0; flex: 1; min-width: 0;
  color: var(--color-ivory);
  font-family: var(--font-body);
  font-size: var(--text-ui);
  line-height: 1.4;
  /* An episode title is a broadcast record, including here. Let the dock grow
     instead of clipping the title Dr. Wells gave the episode. */
  overflow-wrap: anywhere;
}

.fc-player__progress { display: grid; gap: var(--space-3xs); }
.fc-player__times { display: flex; justify-content: space-between; }
.fc-player__time {
  color: var(--color-periwinkle);
  font-family: var(--font-numeral-metadata);
  font-size: var(--text-caption);
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: var(--features-numeral-metadata);
}

/* A native range input, restyled. Keyboard seeking and screen-reader support
   come free and are not reimplemented. */
.fc-player__seek {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 18px; margin: 0;
  background: transparent; cursor: pointer;
}
.fc-player__seek::-webkit-slider-runnable-track {
  height: 3px; border-radius: 2px; background: var(--color-line);
}
.fc-player__seek::-moz-range-track {
  height: 3px; border-radius: 2px; background: var(--color-line);
}
.fc-player__seek::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 13px; height: 13px; margin-top: -5px;
  border-radius: 50%; border: 0; background: var(--color-gold);
}
.fc-player__seek::-moz-range-thumb {
  width: 13px; height: 13px; border: 0; border-radius: 50%; background: var(--color-gold);
}
.fc-player__seek:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }

.fc-player__row { display: flex; align-items: center; gap: var(--space-2xs); }

.fc-player__icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  background: transparent; border: 0; border-radius: var(--radius-pill);
  color: var(--color-periwinkle); cursor: pointer;
  transition: color var(--dur-hover) var(--ease-standard);
}
.fc-player__icon-btn:hover { color: var(--color-ivory); }
.fc-player__icon-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.fc-player__play {
  flex: none;
  min-width: 5.5rem; padding: var(--space-2xs) var(--space-md);
  background: transparent;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-pill);
  color: var(--color-gold);
  font-family: var(--font-body); font-size: var(--text-ui); font-weight: 600;
  cursor: pointer;
  transition: border-color var(--dur-hover) var(--ease-standard), color var(--dur-hover) var(--ease-standard);
}
.fc-player__play:hover { border-color: var(--color-gold); color: var(--color-gold-bright); }
/* The icon is the phone face of the toggle; the text is the desktop face. */
.fc-player__play-icon { display: none; width: 1.25rem; height: 1.25rem; fill: currentColor; }
.fc-player__play-icon .icon-pause { display: none; }
.fc-player__play[data-paused="false"] .icon-pause { display: block; }
.fc-player__play[data-paused="false"] .icon-play { display: none; }
.fc-player__play:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.fc-player__speed {
  margin-left: auto;
  padding: var(--space-3xs) var(--space-2xs);
  background: transparent; border: 1px solid var(--color-line);
  border-radius: var(--radius-pill);
  color: var(--color-periwinkle);
  font-family: var(--font-numeral-metadata);
  font-size: var(--text-caption);
  font-variant-numeric: lining-nums tabular-nums;
  cursor: pointer; min-width: 3.25rem;
  transition: border-color var(--dur-hover) var(--ease-standard), color var(--dur-hover) var(--ease-standard);
}
.fc-player__speed:hover { border-color: var(--color-gold); color: var(--color-ivory); }
.fc-player__speed:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.fc-player__min-glyph {
  display: block; width: 14px; height: 2px;
  background: currentColor; border-radius: 1px;
}

/* ---- the minimised tab --------------------------------------------------- */
.fc-player__tab {
  display: inline-flex; align-items: center; gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-md);
  background: var(--color-depth);
  border: 1px solid var(--color-line-soft);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-card);
  color: var(--color-ivory);
  font-family: var(--font-body); font-size: var(--text-ui); font-weight: 600;
  cursor: pointer;
  transition: border-color var(--dur-hover) var(--ease-standard);
}
.fc-player__tab[hidden] { display: none; }
.fc-player__tab:hover { border-color: var(--color-gold); }
.fc-player__tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* A small pulsing dot: the one signal that audio is still running while the
   panel is collapsed. It stops when the audio does, and under reduced motion. */
.fc-player__tab-icon {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--color-gold); flex: none;
}
.fc-player[data-state="playing"] .fc-player__tab-icon {
  animation: fc-player-pulse 2s var(--ease-standard) infinite;
}
@keyframes fc-player-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

/* Visually hidden, still announced. */
.fc-player__live {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (max-width: 760px) {
  /* Full width on a phone, where a floating card would crowd the content. */
  .fc-player { left: var(--gutter); right: var(--gutter); max-width: none; }
  .fc-player__play {
    min-width: 2.75rem; width: 2.75rem; height: 2.75rem; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
  }
  .fc-player__play-text { display: none; }
  .fc-player__play .fc-player__play-icon { display: block; }
  .fc-player__play-icon .icon-play { transform: translateX(1px); }
}

@media (prefers-reduced-motion: reduce) {
  .fc-player[data-state="playing"] .fc-player__tab-icon { animation: none; }
  .fc-player__icon-btn, .fc-player__play, .fc-player__speed, .fc-player__tab { transition: none; }
}

/* --------------------------------------------------------------------------
   RETURN TO TOP
   A quiet chevron in the opposite corner from the player dock (which sits
   bottom-left), so the two can never overlap. It stays out of the way until
   the reader is well down the page, and it is a real <button> rather than a
   #top anchor so it never writes a hash into the address bar or the history.
   Hidden entirely with JavaScript off, because without script it cannot work.
   -------------------------------------------------------------------------- */
.to-top {
  position: fixed;
  right: var(--gutter);
  bottom: var(--gutter);
  z-index: 890; /* below the player (900) and the header (1000) */
  width: 2.75rem;
  height: 2.75rem;
  display: none; /* .js below opts it in; see the no-script note above */
  align-items: center;
  justify-content: center;
  padding: 0;
  color: var(--color-gold);
  background: var(--color-void);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-pill);
  cursor: pointer;
  /* Out of the tab order and untouchable until it is actually offered. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  transition: opacity var(--dur-hover) var(--ease-standard),
              visibility var(--dur-hover) var(--ease-standard),
              transform var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard),
              color var(--dur-hover) var(--ease-standard);
}
html.js .to-top { display: flex; }
.to-top[data-visible] {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.to-top:hover { color: var(--color-ivory); border-color: var(--color-gold); }
.to-top:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.to-top svg { width: 1rem; height: 1rem; display: block; }

/* The reader asked for motion off; a jump is the honest equivalent. */
@media (prefers-reduced-motion: reduce) {
  .to-top { transition: none; }
}

/* On a phone the player's panel is wide, so the chevron sits a little higher
   than the dock to keep clear of it while both are on screen. */
@media (max-width: 760px) {
  html[data-fc-player-open]:not([data-fc-player-min]) .to-top { bottom: calc(var(--gutter) + 12rem); }
  html[data-fc-player-open][data-fc-player-min] .to-top { bottom: calc(var(--gutter) + 4rem); }
}
