/* base.css — CSS shared byte-for-byte (rendering-identical) across all four
   marketing pages: index.html, couples.html, story.html, life-management.html.
   Extracted to remove duplication. Loaded AFTER fonts.css and BEFORE
   each page's inline <style>, so page-specific inline rules still override. */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
em, i { font-style: normal; }

/* ── The design system ───────────────────────────────────────────────
   Every design token is declared exactly once, here. See CLAUDE.md
   § One token namespace.

   Adopted from the Claude Design handoff (Unicorn Project Design v2).

   ONE GROUND. Night is the only ground in this system, marketing and
   product alike. The cream ramp survives below as raw palette, because
   light objects on night (a cream button, an inverted chip) still need
   it — but there is no cream ground any more.

   Elevation on night is a hard logo-colour offset, never a blur: on a
   dark field a soft shadow is invisible. The old soft-UI vocabulary is
   kept only as an alias layer (bottom of this block) and resolves to
   the offsets.

   TWO DELIBERATE DEVIATIONS from the handoff:

   1. Fonts. The handoff ships Source Serif 4 + Figtree from Google
      Fonts and flags them itself: "Fonts are substitutions. No binaries
      were supplied ... Please send the real font files or names." The
      real face is Newsreader, self-hosted in fonts/ and carrying every
      role — the handoff's two-family pairing is not what this system
      does. Its @import would also fail *silently in production only* —
      style-src 'self' blocks the stylesheet and font-src 'self' blocks
      the binaries — so it must not be adopted. Changing which face we
      set is a design decision; reaching one off a CDN at runtime is not.

   2. Radius names. The handoff's --radius-sm/md/lg/xl collide with
      Tailwind's own names in the member app's @theme block, which is
      why this repo uses semantic radius names. Both are declared; the
      semantic ones are the ones to reach for. */
:root {
  color-scheme: dark;

  /* ── Type ──────────────────────────────────────────────────────
     Family names only — every use site appends its own fallback.

     ONE FAMILY. Newsreader carries every role as of 2026-08-17 — headings and
     prose, buttons and field labels. The two tokens below therefore hold the
     same value, and that is not a mistake waiting to be tidied: they are the
     two *roles*, and keeping them distinct is what lets the voices split again
     without touching a hundred call sites. Reach for the one that describes
     what you are setting. */
  --display-font: 'Newsreader';
  --body-font: 'Newsreader';
  /* Full stacks. Renamed from --font-serif-display / --font-sans-ui on
     2026-08-17: "sans" stopped being true when Inter went, and a token whose
     name contradicts its value is worse than no token. Rename only — no call
     site reads these three, so nothing computed changed. */
  --font-display: var(--display-font), 'Charter', Georgia, serif;
  --font-ui: var(--body-font), 'Charter', Georgia, serif;
  --font-numeric: var(--font-ui);

  --size-display-1: 52px;
  --size-display-2: 38px;
  --size-display-3: 28px;
  --size-title: 22px;
  --size-subtitle: 19px;
  --size-body-lg: 18px;
  --size-body: 16px;
  --size-body-sm: 15px;
  --size-caption: 13px;
  --size-micro: 12px;

  --lh-display: 1.1;
  --lh-title: 1.2;
  --lh-body: 1.5;
  --lh-tight: 1.35;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --track-display: -0.015em;
  --track-title: -0.01em;
  --track-body: 0em;
  --track-micro: 0.02em;

  /* ── Raw palette: warm paper ───────────────────────────────────
     No longer a ground. Kept because light objects on night still
     need it. */
  --cream-50: #FDFBF7;
  --cream-100: #FBF6EE;
  --cream-200: #F7F3EA;
  --cream-300: #EFE9DE;
  --cream-400: #E2DACB;
  --cream-500: #D3C9B6;

  /* ── Raw palette: plum ink (never pure black, never neutral grey) */
  --ink-900: #201528;
  --ink-800: #2E2038;
  --ink-700: #3B2E46;
  --ink-600: #4A3D52;
  --ink-500: #574A62;
  --ink-400: #6E5F76;
  --ink-300: #8E8297;
  --ink-200: #B7AEBD;
  --ink-100: #E4E0E8;

  /* ── Raw palette: cool slate (structural chrome only) ──────────── */
  --slate-100: #EDF1F4;
  --slate-200: #DDE4EA;
  --slate-500: #808C8D;
  --slate-700: #5F6B6C;

  /* ── Night ramp: the ground, everywhere ────────────────────────── */
  --night-950: #0C0817;
  --night-900: #100B1E;
  --night-850: #181129;
  --night-800: #1B1430;
  --night-700: #241A3C;
  --night-600: #2A1D3E;
  --night-500: #43294B;
  --night-400: #5E3852;
  --night-hairline: rgba(255,255,255,.12);

  --text-on-night: #EDE7F7;
  --text-on-night-body: #DED7EE;
  --text-on-night-muted: #C6BCDD;
  --text-on-night-faint: #8B7FAA;

  /* ── Brand gradient: marketing surfaces only, never product UI ─── */
  --grad-stop-1: #F66E62;
  --grad-stop-2: #F0809B;
  --grad-stop-3: #C98FB8;
  --grad-stop-4: #8177B3;
  --grad-stop-5: #6582BA;
  --grad-unicorn: linear-gradient(90deg, #F66E62 0%, #F0809B 22%, #C98FB8 48%, #8177B3 74%, #6582BA 100%);
  --grad-night: linear-gradient(105deg, #241E35 0%, #2F1E31 55%, #221A2E 100%);
  --grad-night-sky: linear-gradient(176deg, #120C22 0%, #1B1430 32%, #2A1D3E 58%, #43294B 80%, #5E3852 100%);
  --glow-dawn: radial-gradient(62% 112% at 50% 118%, rgba(246,150,110,.5), rgba(199,124,170,.28) 40%, rgba(129,119,179,.16) 62%, rgba(27,20,48,0) 80%);
  --coral-ink: #F98D83;
  /* Coral as text ON A LIGHT OBJECT. --coral-ink is the night counterpart and
     measures 2.22:1 on --surface-invert; this is the same hue (5deg) carried
     dark enough to read there, at 5.45:1. The first component to need it is the
     race leaderboard, whose cards are light. */
  --coral-on-light: #B83C30;

  /* ── Skyline furniture (marketing hero) ────────────────────────── */
  --city-window: rgba(255,214,170,.82);
  --city-beacon: #F6766A;
  --city-haze: rgba(255,176,132,.3);
  --hill-back: #33203F;
  --hill-mid: #4A2B4E;
  --hill-front: #553055;

  /* ── Logo ramp ─────────────────────────────────────────────────── */
  --logo-coral: #F66E62;
  --logo-pink: #F0809B;
  --logo-blush: #F9C8CB;
  --logo-lilac: #D7AED0;
  --logo-violet: #AF78B2;
  --logo-indigo: #6966AD;
  --logo-blue: #6582BA;
  --logo-sky: #ADC0E0;
  --logo-deep: #59598F;
  --logo-outline: #393A4C;

  /* ── Track accents: one hue per life track ─────────────────────── */
  --track-blue: #7FA8CF;
  --track-teal: #6FC7B8;
  --track-green: #6FD69B;
  --track-slate: #A8B4B5;
  --track-plum: #C79ED8;
  --track-clay: #E0977A;
  --track-blue-tint: rgba(127,168,207,.13);
  --track-teal-tint: rgba(111,199,184,.13);
  --track-green-tint: rgba(111,214,155,.13);
  --track-slate-tint: rgba(168,180,181,.13);
  --track-plum-tint: rgba(199,158,216,.13);
  --track-clay-tint: rgba(224,151,122,.13);

  /* ── Semantic status ───────────────────────────────────────────── */
  --amber-ink: #E8C489;
  --amber-bg: rgba(232,196,137,.14);
  --amber-line: rgba(232,196,137,.28);
  --green-ink: #8FD3AC;
  --green-bg: rgba(143,211,172,.13);
  --green-line: rgba(143,211,172,.26);
  --blue-ink: #ADC0E0;
  --blue-bg: rgba(173,192,224,.14);
  --blue-line: rgba(173,192,224,.28);
  --rose-ink: #F2A9A2;
  --rose-soft: rgba(246,110,98,.30);
  --rose-bg: rgba(246,110,98,.16);

  /* ── Semantic roles: reach for THESE in components ─────────────── */
  --surface-page: var(--night-900);
  --surface-raised: var(--night-850);
  --surface-card: var(--night-800);
  --surface-sunken: var(--night-950);
  --surface-inset: var(--night-700);
  --surface-invert: var(--cream-50);

  --text-heading: #FFFFFF;
  --text-body: var(--text-on-night-body);
  --text-muted: var(--text-on-night-muted);   /* deepest legible support tone; not grey */
  --text-faint: var(--text-on-night-faint);   /* placeholders + disabled only */
  --text-invert: #180F22;                     /* ink ON a light object */
  --text-link: #C9B8E8;
  --text-link-hover: #FFFFFF;

  --border-hairline: rgba(255,255,255,.12);
  --border-field: rgba(255,255,255,.20);
  --border-strong: rgba(255,255,255,.18);
  --focus-ring: var(--logo-sky);

  --status-idle-bg: rgba(255,255,255,.07);
  --status-idle-ink: var(--text-on-night-body);
  --status-underway-bg: var(--amber-bg);
  --status-underway-ink: var(--amber-ink);
  --status-done-bg: var(--green-bg);
  --status-done-ink: var(--green-ink);
  --danger-rest: var(--rose-soft);
  --danger-hover: var(--rose-ink);

  /* Chat bubbles. App-only roles, declared here because this is the single
     token namespace — not because the marketing site draws them.

     The own-message bubble is coral at 40% over --surface-card, resolved to a
     literal so it does not depend on what it happens to sit on. It used to be
     --coral-ink (#F98D83) with a white label at 2.29:1, on the reasoning that
     coral-ink is "the text-safe coral" — but that token is coral AS TEXT ON
     NIGHT, never a ground for white. Darkening the ground keeps the white
     label and clears the floor at 8.83:1.

     The peer bubble is a step UP from the card, so it reads as raised rather
     than as a hole punched in it, and it carries a hairline because at 1.08:1
     its fill cannot define its own edge. */
  --surface-message-own: #733844;
  --surface-message-peer: var(--night-700);

  /* ── Solid action pair: coral fill, dark ink, hard indigo offset ── */
  --action-solid-bg: var(--logo-coral);
  --action-solid-bg-hover: #FF8479;
  --action-solid-ink: #180F22;
  --action-solid-edge: #180F22;

  /* ── Segmented control: the thumb must out-step the track ──────── */
  --control-track: var(--night-950);
  --control-thumb: var(--night-500);
  --control-thumb-shadow: none;

  /* ── Radius ────────────────────────────────────────────────────── */
  --radius-xs: 5px;
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 14px;
  --radius-2xl: 18px;
  --radius-pill: 999px;
  /* Semantic names — prefer these; see the deviation note above. */
  --radius-card: var(--radius-xl);
  --radius-field: var(--radius-md);
  --radius-control: var(--radius-md);
  --radius-chip: var(--radius-pill);
  --radius-micro: var(--radius-xs);
  --radius-tile: var(--radius-lg);
  --radius-hero: var(--radius-2xl);
  --radius: var(--radius-card);
  --accent-bar-h: 5px;

  /* ── Spacing ───────────────────────────────────────────────────── */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --gutter-column: 22px;
  --gutter-card: 16px;
  --pad-card: 20px;
  --pad-card-tight: 16px;
  --page-max: 1720px;
  --page-pad-x: 48px;
  --header-h: 64px;
  --column-w: 300px;

  /* ── Elevation ─────────────────────────────────────────────────── */
  /* The cream era's soft shadows are gone, not deprecated. --shadow-card,
     --shadow-card-hover, --shadow-lift and --shadow-popover were blurred plum
     ink; against #1B1430 that computes to 1.00:1 at every alpha they used, so
     they rendered nothing. They also had zero call sites left, which is the
     giveaway: a token nobody reaches for and that would do nothing if they did.

     --shadow-inset-field survives because 18 call sites use it, but its ink is
     now a light hairline. An inset highlight along the top edge is what makes a
     field read as a well on this ground; ink at 3% did not read at all. */
  --shadow-inset-field: inset 0 1px 0 rgba(255,255,255,0.05);
  --shadow-none: none;
  /* Night ground: a hard logo-colour offset, never a blur. */
  --shadow-offset-violet: 8px 8px 0 var(--logo-violet);
  --shadow-offset-indigo: 8px 8px 0 var(--logo-indigo);
  --shadow-offset-coral: 8px 8px 0 var(--logo-coral);
  --shadow-offset-deep: 8px 8px 0 var(--logo-deep);
  --shadow-offset-sm-deep: 3px 3px 0 var(--logo-deep);
  --shadow-offset-sm-violet: 3px 3px 0 var(--logo-violet);
  --shadow-offset-sm-indigo: 3px 3px 0 var(--logo-indigo);
  --night-shadow-card: var(--shadow-offset-violet);
  --night-shadow-card-alt: var(--shadow-offset-indigo);
  --night-shadow-card-hover: 10px 10px 0 var(--logo-violet);
  --night-shadow-control: var(--shadow-offset-sm-deep);
  --night-shadow-button: 4px 4px 0 var(--logo-indigo);
  /* Pressed collapses toward the page: the offset shrinks rather than
     vanishing, so the object reads as pushed down instead of switched off. */
  --night-shadow-pressed: 2px 2px 0 var(--logo-deep);
  --night-shadow-lift: 14px 14px 0 var(--logo-violet);
  --night-shadow-popover: 10px 10px 0 var(--logo-deep);
  --action-solid-shadow: var(--night-shadow-button);
  --action-quiet-shadow: var(--night-shadow-control);

  /* ── Motion ────────────────────────────────────────────────────── */
  --ease-standard: cubic-bezier(.2,.8,.3,1);
  --ease-exit: cubic-bezier(.4,0,1,1);
  --dur-instant: 80ms;
  --dur-fast: 140ms;
  --dur-base: 200ms;
  --dur-slow: 320ms;
  --transition-control: background-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
  --transition-card: box-shadow var(--dur-base) var(--ease-standard), transform var(--dur-base) var(--ease-standard);

  /* Decoration layered on top of a real outline. Focus is never shadow-only. */
  --focus-glow: 0 0 0 4px rgba(173,192,224,.25);
}

html { scroll-behavior: smooth; }

/* Keyboard focus. DESIGN.md makes Signal Violet the interaction colour, so one ring
   serves the whole site. Inputs are deliberately excluded: they carry the violet
   border plus 4px glow instead, which is the system's input-focus treatment.
   :focus-visible keeps the ring off mouse clicks. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--logo-violet);
  outline-offset: 2px;
}

/* Paper grain, painted INTO the ground instead of composited over it. The old
   version was a fixed full-viewport ::before with mix-blend-mode: multiply — a
   blended layer the compositor must re-resolve against everything beneath it
   on every scroll frame, stacked under the nav's backdrop-filter. As part of
   the body's own background it is painted once and scrolls with the page
   (static noise looks identical moving or fixed — nobody can track a grain).
   The rect bakes in the old effective alpha: 0.35 (rect) x 0.035 (layer).
   Pages set body background-color as LONGHAND for exactly this reason — the
   shorthand would reset this image layer. */
body {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.012'/></svg>");
  background-blend-mode: multiply;
}

nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 max(24px, 5vw);
  height: 72px;
  background: rgba(16,11,30,0.92);
  backdrop-filter: blur(16px) saturate(1.1);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
  border-bottom: 1px solid var(--border-hairline);
}

.nav-logo { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--text-heading); }

/* No radius: the mark is transparent and carries its own silhouette, so a
   corner radius rounds nothing. It was there for the old opaque logo tile. */
.nav-logo img { width: 40px; height: 40px; display: block; flex: none; }

.nav-logo-text {
  font-family: var(--display-font), serif;
  font-style: normal;
  /* fonts.css self-hosts Newsreader 400 and 500 only. Asking for 600 here would
     make the browser synthesise a fake bold — the face is not there to load. */
  font-weight: 500;
  font-size: 1.15rem;
  letter-spacing: -0.01em;
}

.nav-links { display: flex; gap: 2.25rem; align-items: center; }

.nav-links a {
  font-size: 0.875rem; font-weight: 400;
  color: var(--text-body); text-decoration: none;
  transition: color var(--dur-base) var(--ease-standard); position: relative;
}

/* Primary actions take the handoff's solid action pair: coral fill, dark ink
   label, hard indigo offset. On cream the ground was ink and the label white,
   because coral-under-white only reached 3.7:1 — on night that inverts, the
   ink becomes the label, and coral carries the fill at a comfortable ratio. */
/* Same overlay idiom as .btn-primary on the marketing pages: the label is
   wrapped in a <span> so it can be lifted above the gradient layer. */
.nav-cta {
  background: var(--action-solid-bg); color: var(--action-solid-ink) !important;
  padding: 10px 20px; border-radius: 999px;
  font-weight: 500 !important; font-size: 0.825rem !important;
  position: relative; overflow: hidden;
  transition: box-shadow var(--dur-base) var(--ease-standard), transform var(--dur-base) var(--ease-standard);
}

.nav-cta::before {
  content: ''; position: absolute; inset: 0;
  background: var(--grad-unicorn); opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}

.nav-cta span { position: relative; z-index: 1; }

.nav-cta:hover::before { opacity: 1; }

.nav-cta:hover { transform: translateY(-1px); box-shadow: 0 10px 24px -10px rgba(246,110,98,0.5); }

.nav-signin {
  background: var(--surface-card); border: 1px solid var(--border-strong);
  padding: 8px 16px; border-radius: 999px;
  font-size: 0.825rem !important; font-weight: 500 !important;
  color: var(--text-heading) !important;
  /* Explicit list, not `all` — `all` animates outline-width and swallows the
     focus ring, which is the exact bug globals.css had to paper over with
     !important in the member app. */
  transition: background-color var(--dur-base) var(--ease-standard), border-color var(--dur-base) var(--ease-standard), transform var(--dur-base) var(--ease-standard);
}

.nav-signin:hover { background: var(--text-body); border-color: var(--text-body); color: #fff !important; transform: translateY(-1px); }

.nav-signin::after { display: none !important; }

.nav-toggle {
  display: none;
  background: transparent; border: none;
  padding: 8px 4px; cursor: pointer;
  flex-direction: column; gap: 5px; align-items: center;
  margin-left: 0.5rem;
}

.nav-toggle span {
  display: block; width: 22px; height: 1.5px;
  background: var(--text-heading);
  transition: transform var(--dur-slow) var(--ease-standard), opacity var(--dur-base) var(--ease-standard);
  transform-origin: center;
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }

.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }

.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

footer {
  background: var(--surface-raised);
  border-top: 1px solid var(--border-hairline);
  padding: 4rem max(24px, 5vw) 2rem;
  position: relative; z-index: 1;
}

.footer-inner {
  max-width: 1240px; margin: 0 auto;
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 3rem;
  padding-bottom: 3rem;
  border-bottom: 1px solid var(--border-hairline);
}

.footer-brand { max-width: 380px; }

.footer-logo {
  font-family: var(--display-font), serif;
  font-weight: 500;
  font-size: 1.4rem; color: var(--text-heading);
  margin-bottom: 0.75rem;
  letter-spacing: -0.01em;
}

/* Gradient-filled, matching every other emphasised word on the site — see the
   headline-emphasis block below, which owns the declaration. */

.footer-brand p {
  font-size: 0.875rem; color: var(--text-muted);
  line-height: 1.6;
}

.footer-links-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
}

.footer-col h4 {
  font-family: var(--body-font), serif;
  font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--text-body); margin-bottom: 1rem;
}

.footer-col a {
  display: block;
  font-size: 0.925rem; color: var(--text-heading);
  text-decoration: none; margin-bottom: 0.5rem;
  transition: color var(--dur-base) var(--ease-standard);
}

.footer-col a:hover { color: var(--coral-ink); }

.footer-copy-wrap {
  max-width: 1240px; margin: 2rem auto 0;
  display: flex; justify-content: space-between; align-items: center;
  font-size: 0.78rem; color: var(--text-muted);
  flex-wrap: wrap; gap: 1rem;
}

.footer-copy-wrap em { font-family: var(--display-font), serif; font-style: normal; }

/* ══════════ SHARED COMPONENTS ══════════
   Hoisted out of the per-page <style> blocks, where every rule below was
   duplicated byte-for-byte across index.html, life-management.html and
   story.html — .btn-primary alone existed in six places, and one copy had
   already drifted. Page blocks still load after base.css, so a page can
   override anything here; where one does, it now says so explicitly instead
   of hiding behind an identical-looking duplicate.

   Values are unchanged from the copies they replace. */

/* ── Buttons ─────────────────────────────────────────────────── */
/* The solid action pair. Elevation is a hard indigo offset, not a blur: on the
   night ground a soft shadow is invisible, which is the same failure the old
   on-ink pair existed to fix, one ground later.
   Explicit transition list, not `all`: `all` animates outline-width and eats the
   focus ring, which globals.css already had to work around with !important. */
.btn-primary {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--action-solid-bg); color: var(--action-solid-ink);
  padding: 14px 26px; border-radius: var(--radius-pill);
  font-family: var(--body-font), serif;
  font-weight: 500; font-size: 0.925rem;
  text-decoration: none;
  box-shadow: var(--action-solid-shadow);
  transition: transform var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard), background-color var(--dur-base) var(--ease-standard);
  position: relative; overflow: hidden;
}
.btn-primary::before {
  content: ''; position: absolute; inset: 0;
  background: var(--grad-unicorn); opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.btn-primary span { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 10px; }
.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: var(--night-shadow-card-alt), 0 12px 32px rgba(246,110,98,0.25);
}
.btn-primary:hover::before { opacity: 1; }
/* Pressed collapses inward — this is the state that sells the kit. */
.btn-primary:active {
  transform: translateY(0);
  box-shadow: var(--night-shadow-pressed);
}

.btn-secondary {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--text-heading); padding: 14px 20px;
  font-family: var(--body-font), serif;
  font-weight: 500; font-size: 0.925rem;
  text-decoration: none;
  position: relative;
}
.btn-secondary::after {
  content: ''; position: absolute; left: 20px; right: 20px; bottom: 10px;
  height: 1px; background: var(--text-heading); transform: scaleX(1);
  transform-origin: left; transition: transform var(--dur-slow) var(--ease-standard);
}
.btn-secondary:hover::after { transform: scaleX(0); transform-origin: right; }

/* ── Headline emphasis ───────────────────────────────────────────
   The emphasised clause of a headline carries the four-stop brand gradient,
   on every page, matching the index.html hero. This is a deliberate brand
   decision by the owner: the rainbow is the mark.

   Declared ONCE here for every selector that takes it. It was previously
   duplicated in all four page <style> blocks, which is how the wordmark and
   the CTA card had already drifted apart from each other. Add a new
   emphasis selector to this list rather than re-declaring the gradient.

   CONTRAST, on --surface-page (#100B1E), against the 3:1 large-text floor:
     coral  #F66E62  6.73:1  ok
     pink   #F0809B  7.59:1  ok
     orchid #C98FB8  7.44:1  ok
     indigo #8177B3  4.80:1  ok
     blue   #6582BA  5.01:1  ok
   Every stop clears. This block used to carry the cream-era table, where the
   pink stop measured 2.20 and a letter landing in the pink third of a
   gradient-filled word was below AA — the worst contrast defect in the old
   system, and one with no clean fix, because darkening pink turns it into
   coral. Moving the ground resolved it; there is nothing to work around
   here any more. Nothing here is measured by an automated contrast audit
   either, since -webkit-text-fill-color: transparent hides the real colour
   from computed style — design-system/colors.html measures the stops
   directly at build time instead.

   .dropcap is story.html's drop cap. It must be a real <span>: Chromium
   silently drops -webkit-text-fill-color on ::first-letter, so the gradient
   there paints nothing and the cap falls back to flat ink. */
.hero-title .italic,
.section-title em,
.article-title .accent,
.form-title em,
.cta-title em,
.footer-logo .italic,
.step-num,
.dropcap {
  background: var(--grad-unicorn);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* ── Section eyebrow ─────────────────────────────────────────── */
.section-tag {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--body-font), serif;
  font-size: 0.72rem; font-weight: 500; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-body);
  margin-bottom: 1.5rem;
}
.section-tag::before { content: ''; width: 24px; height: 1px; background: var(--text-body); }

/* ── Feature tile ────────────────────────────────────────────────
   One rule, two historical class names: index.html called it .about-card,
   life-management.html called it .feature-card, and they were identical.
   Both selectors are kept so no markup has to change. The h3 inside them
   genuinely differs, so those stay in the page blocks. */
/* Raised at rest — the Extruded-At-Rest Rule. The hairline stays: white-ish on
   cream is ~1.06:1 and a shadow cannot carry a component boundary on its own. */
.about-card, .feature-card {
  background: var(--surface-raised);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-tile);
  padding: 1.75rem 1.5rem;
  box-shadow: var(--night-shadow-control);
  transition: transform var(--dur-slow) var(--ease-standard), box-shadow var(--dur-slow) var(--ease-standard);
  position: relative; overflow: hidden;
}
.about-card::before, .feature-card::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--grad-unicorn);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-standard);
}
.about-card:hover, .feature-card:hover { transform: translateY(-3px); box-shadow: var(--night-shadow-card-hover); }
.about-card:hover::before, .feature-card:hover::before { transform: scaleX(1); }
/* The tile held an emoji until now. Emoji are supplied by the operating
   system, so the brand rendered as three different illustration styles across
   macOS, Windows and Android, and a tinted square with an emoji in it is the
   single most recognisable stock-template shape on the web. The contents are
   now inline monoline SVG drawn on one 20px grid at one 1.5px stroke weight,
   inheriting `color` from the tile's own inline style so the icon carries the
   saturated hue of the wash behind it (--red-ink / --purple / --blue over
   --red-light / --purple-light / --blue-light, 4.61 / 4.39 / 3.04:1 — all
   clear of the 3:1 graphic floor). Reuse an existing icon before drawing a
   new one; a set that repeats reads as a system, a set that never does reads
   as clip art. */
.about-card-icon, .feature-icon {
  width: 42px; height: 42px; border-radius: var(--radius-field);
  box-shadow: var(--night-shadow-control);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 1.25rem;
}
.about-card-icon svg, .feature-icon svg { width: 20px; height: 20px; display: block; }
.about-card p, .feature-card p { font-size: 0.875rem; line-height: 1.65; color: var(--text-body); }

/* ── Step cards (on the dark band) ───────────────────────────── */
.steps-grid { margin-top: 4rem; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
/* On the ink band, so on-ink elevation plus the cream rim the Dark-Ground Rule
   asks for — the rim is what actually reads as an edge against #201528. */
.step-card {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-card);
  padding: 2.25rem 2rem 2rem;
  box-shadow: var(--night-shadow-card-alt);
  position: relative; overflow: hidden;
  transition: transform var(--dur-slow) var(--ease-standard), box-shadow var(--dur-slow) var(--ease-standard), background-color var(--dur-slow) var(--ease-standard), border-color var(--dur-slow) var(--ease-standard);
}
.step-card:hover {
  background: rgba(255,255,255,0.08);
  border-color: var(--border-field);
  transform: translateY(-4px);
  box-shadow: var(--night-shadow-card-alt), 0 18px 40px -18px rgba(0,0,0,0.55);
}
/* Gradient fill comes from the headline-emphasis block above. Every stop
   clears 3:1 against the ink band these sit on. */
.step-num {
  font-family: var(--display-font), serif;
  font-style: normal; font-weight: 400;
  font-size: 3.5rem; line-height: 1;
  margin-bottom: 1rem;
  letter-spacing: -0.02em;
}
.step-card h3 {
  font-family: var(--display-font), serif;
  font-weight: 500; font-size: 1.25rem;
  color: var(--text-heading); margin-bottom: 0.75rem;
  letter-spacing: -0.01em;
}
.step-card p { font-size: 0.925rem; line-height: 1.7; color: var(--text-muted); text-wrap: pretty; }

/* ── CTA card ────────────────────────────────────────────────────
   Shared verbatim by story.html and life-management.html except for the
   top margin, which each page still sets. */
.cta-card {
  position: relative; z-index: 1;
  max-width: 900px;
  padding: 3.5rem 2.5rem;
  background: var(--surface-card); color: var(--text-heading);
  border-radius: var(--radius-hero);
  box-shadow: var(--night-shadow-card);
  text-align: center; overflow: hidden;
}
.cta-card::before {
  content: ''; position: absolute; inset: 0;
  background: var(--grad-unicorn); opacity: 0.08;
  pointer-events: none;
}
.cta-card::after {
  content: ''; position: absolute;
  width: 420px; height: 420px;
  background: radial-gradient(circle, rgba(246,110,98,0.35) 0%, transparent 70%);
  right: -140px; bottom: -140px;
  pointer-events: none;
}
.cta-tag {
  display: inline-block;
  font-size: 0.72rem; font-weight: 500; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-muted);
  margin-bottom: 1rem;
  position: relative; z-index: 1;
}
.cta-title {
  font-family: var(--display-font), serif;
  font-weight: 400;
  font-size: clamp(1.8rem, 3.4vw, 2.4rem);
  color: var(--text-heading);
  margin-bottom: 1rem;
  line-height: 1.15; letter-spacing: -0.015em;
  position: relative; z-index: 1;
}
/* Gradient fill comes from the headline-emphasis block above. */
.cta-title em { font-style: normal; }
.cta-body {
  color: var(--text-body);
  font-size: 1rem; line-height: 1.7;
  max-width: 480px; margin: 0 auto 2rem;
  position: relative; z-index: 1;
}

/* Nav collapse. This lived in five near-identical copies across the pages and fired at
   760px, 768px or 960px depending which page you were on, so the same shared nav behaved
   differently per page. One copy, one breakpoint — 960px, the marketing breakpoint. */
@media (max-width: 960px) {
  .nav-toggle { display: flex; }

  .nav-links {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 0.75rem max(24px, 5vw) 1.5rem;
    background: rgba(16,11,30,0.98);
    backdrop-filter: blur(16px) saturate(1.1);
    -webkit-backdrop-filter: blur(16px) saturate(1.1);
    border-bottom: 1px solid var(--border-hairline);
    /* A hard edge under the panel, not a blur. The panel is full-bleed, so the
       usual corner offset would read as a slipped card; a straight-down offset
       is the same grammar applied to a full-width surface. The blurred ink it
       replaces was invisible here for the usual reason. */
    box-shadow: 0 4px 0 var(--logo-deep);
    transform: translateY(-110%); opacity: 0; pointer-events: none;
    transition: transform var(--dur-slow) var(--ease-standard), opacity var(--dur-base) var(--ease-standard);
  }

  .nav-links.is-open { transform: translateY(0); opacity: 1; pointer-events: auto; }

  .nav-links a {
    display: block; padding: 14px 4px; font-size: 1rem;
    color: var(--text-heading); border-bottom: 1px solid var(--border-hairline);
  }

  .nav-links a:last-child { border-bottom: none; }

  .nav-links a:not(.nav-cta)::after { display: none; }

  .nav-links .nav-signin { align-self: flex-start; margin-top: 0.25rem; }

  .nav-links .nav-cta {
    margin-top: 0.75rem; padding: 12px 22px !important;
    text-align: center; align-self: flex-start;
  }
}

@media (prefers-reduced-motion: reduce){ *,*::before,*::after{ animation-duration:0.01ms !important; animation-iteration-count:1 !important; transition-duration:0.01ms !important; scroll-behavior:auto !important; } }
