/*!
 * @magicblocksai/css — vanilla CSS distribution for the MagicBlocks brand kit.
 * https://brand.magicblocks.ai · https://github.com/MagicBlocksAI/brand-kit
 *
 * Single source of truth: components/_shared.css in the brand-kit repo.
 * To use:
 *   <link rel="stylesheet" href="https://brand.magicblocks.ai/css/v1/magicblocks.css">
 * or
 *   import "@magicblocksai/css";
 *
 * Tokens are CSS custom properties; dark mode flips via [data-theme="dark"]
 * on <body>. Reduced motion is honoured automatically.
 */

/* ============================================================
   MagicBlocks component library — shared tokens + page chrome
   Imported by every /components/*.html page.
   Change tokens here; every page reflects the change.
   ============================================================ */

:root {
  /* ------------------------------------------------- colour */
  /* ink/foundation */
  --ink:         #191E32;
  --slate:       #466099;
  --lavender:    #6E90CC;
  --paper:       #FFFFFF;

  /* warm neutrals — the default surface family.
     These are PINNED values: they stay warm in both light and dark
     modes so the brand's cream-paper identity carries through.
     Any component that sets one of these as its own background must
     also scope its type tokens (--fg, --fg-soft, --fg-dim, --hair)
     to ink values so copy stays legible when the theme's --fg flips. */
  --warm-1:      #FBF6F0;  /* lightest — hairline tint on paper */
  --warm-2:      #F9F1E8;  /* light — marketing footer, soft stages */
  --warm-3:      #F4ECE4;  /* default — page background in light mode */
  --warm-5:      #E8DBCB;  /* mid — panel sunken, demo-stage alt */
  --warm-7:      #D2BFAA;  /* deep — ambient blocks, hero shadows */

  /* block quad — pink is hero */
  --pink-300:    #FE84A9;
  --pink-500:    #FF5B8D;
  --pink-700:    #FF3F7A;

  --yellow-300:  #FFD878;
  --yellow-500:  #F9C33E;
  --yellow-700:  #F9AD03;

  --green-300:   #7DF4D0;
  --green-500:   #47DDB2;
  --green-700:   #37BC9B;

  --blue-300:    #5BD9FC;
  --blue-500:    #30C4F2;
  --blue-700:    #1FAAE8;

  /* semantic (warm/light mode — default) */
  --bg:          var(--warm-3);
  --bg-paper:    var(--paper);
  --bg-sunk:     var(--warm-5);
  --bg-sunken:   var(--warm-5);           /* alias of --bg-sunk */
  --bg-warm:     var(--warm-2);            /* light warm tint for subtle surfaces */
  --bg-deep:     var(--warm-7);
  --fg:          var(--ink);
  /* --fg-soft was var(--slate) = #466099 (a strong blue) which made every
     body-secondary paragraph read as a link. Changed to ink at 78% alpha
     for a neutral ink-tinted body color (~6 ratio on white, passes AA-body
     comfortably). The --slate token is still available for explicit
     slate-blue use where intentional. */
  --fg-soft:     rgba(25, 30, 50, 0.78);
  /* --fg-dim was 0.55 (3.77 ratio on white = fail AA-body). Bumped to 0.7
     for ~5.6 ratio on white — passes AA-body 4.5+. Used for muted-but-
     readable labels (chapter eyebrow, input hints, stat labels, etc.). */
  --fg-dim:      rgba(25, 30, 50, 0.7);
  /* --fg-faint was 0.35 (~2 ratio = fail everything). Bumped to 0.6 for
     ~3.7 ratio on white — passes AA-large 3.0+. Used for decorative
     captions, dividers, section numbers — text that's intentionally
     quiet but still readable. */
  --fg-faint:    rgba(25, 30, 50, 0.6);
  --hair:        rgba(25, 30, 50, 0.12);
  --hair-soft:   rgba(25, 30, 50, 0.06);
  /* warm-tinted hairline variants — for panels where cool ink-tinted
     borders read slightly muddy on warm-cream ground. Opt-in only. */
  --hair-warm:      rgba(139, 115, 85, 0.18);
  --hair-warm-soft: rgba(139, 115, 85, 0.10);
  /* per-industry hero wash. Set this on a page root to colour-wash
     .hero-bloom-canvas backgrounds without touching the component. */
  --industry-accent: var(--accent);
  --accent:      var(--pink-700);
  --accent-soft: rgba(255, 63, 122, 0.12);
  --success:     var(--green-700);
  --success-soft: rgba(55, 188, 155, 0.14);
  --warning:     var(--yellow-700);
  --warning-soft: rgba(249, 173, 3, 0.16);
  --info:        var(--blue-700);
  --info-soft:   rgba(31, 170, 232, 0.14);
  --error:       #D64545;
  --error-soft:  rgba(214, 69, 69, 0.12);

  /* Darker semantic TEXT variants — for body/caption text on LIGHT
     backgrounds. The bright brand colors (--success, --info, --warning)
     fail WCAG AA when used as small text on cream / paper, so we
     pre-darken them here. In dark mode these alias back to the brand
     colors (which read fine on ink).
     ── EXCEPTION: --accent-text was #B42463 (burgundy) for AA reasons,
     but that hue read off-brand (close to a wine-red). Per brand
     direction we now alias --accent-text → --accent (pink-700), so the
     brand pink is used everywhere and the burgundy is removed from the
     kit entirely. Trade-off: small (<14 px) accent text may not strictly
     hit AA-body on white — brand consistency wins. */
  --accent-text:   var(--accent);
  --success-text:  #1E6B44;
  --info-text:     #1463A1;
  --warning-text:  #8A5A00;
  --error-text:    var(--error);  /* already #D64545 — passes AA-body on white */

  /* ambient brand glow — sits behind the whole page via body::before.
     Subtle in light mode, more pronounced in dark where the dark base
     makes the pink feel lit rather than washed. Shared so every page
     gets the same through-line without heroes needing bespoke gradients. */
  --glow-pink:   rgba(255, 63, 122, 0.06);
  --glow-blue:   rgba(31, 170, 232, 0.04);
  --glow-warm:   rgba(249, 195, 62, 0.03);

  /* neutral hash pattern for demo stages — theme-aware so the texture
     stays visible on both cream and ink backgrounds without overpowering. */
  --stage-hash:  rgba(25, 30, 50, 0.035);

  /* ------------------------------------------------- space */
  --s-1:   4px;
  --s-2:   8px;
  --s-3:   12px;
  --s-4:   16px;
  --s-5:   20px;
  --s-6:   24px;
  --s-7:   32px;
  --s-8:   40px;
  --s-9:   48px;
  --s-10:  64px;
  --s-11:  80px;
  --s-12:  96px;
  --s-13:  128px;

  /* ------------------------------------------------- radii */
  --r-xs:  4px;
  --r-sm:  6px;
  --r-md:  10px;
  --r-lg:  14px;
  --r-xl:  20px;
  --r-2xl: 28px;
  --r-pill: 999px;

  /* ------------------------------------------------- shadow / elevation */
  --sh-0: none;
  --sh-1: 0 1px 2px rgba(25, 30, 50, 0.06), 0 1px 1px rgba(25, 30, 50, 0.04);
  --sh-2: 0 4px 10px rgba(25, 30, 50, 0.08), 0 1px 2px rgba(25, 30, 50, 0.06);
  --sh-3: 0 10px 28px rgba(25, 30, 50, 0.12), 0 2px 4px rgba(25, 30, 50, 0.06);
  --sh-4: 0 24px 56px rgba(25, 30, 50, 0.18), 0 4px 8px rgba(25, 30, 50, 0.08);
  --sh-pink: 0 12px 40px rgba(255, 63, 122, 0.28);
  --sh-focus: 0 0 0 3px rgba(255, 63, 122, 0.28);

  /* ------------------------------------------------- motion */
  --dur-1: 100ms;
  --dur-2: 160ms;
  --dur-3: 240ms;
  --dur-4: 400ms;
  --ease:  cubic-bezier(0.2, 0.8, 0.2, 1);

  /* ------------------------------------------------- type */
  --f-display: "Bricolage Grotesque", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif;
  --f-body:    "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif;
  --f-mono:    "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --f-serif:   "Fraunces", ui-serif, Georgia, "Times New Roman", serif;

  /* ------------------------------------------------- z-index */
  --z-base:    1;
  --z-sticky:  10;
  --z-overlay: 100;
  --z-modal:   200;
  --z-toast:   300;

  /* ============================================================
     App-pattern semantic aliases (CRM brief — DESIGN-SYSTEM-ADDITIONS.md)
     ------------------------------------------------------------
     These layer on top of existing tokens for the CRM-flavoured
     components in chapters 13–15 (and the small atoms in 07/08).
     All purely-derived from existing semantic colours — no new
     hex values introduced. Backward-compatible additions only.
     ============================================================ */

  /* hover wash for list rows (used by inbox row, kanban card hover, etc.) */
  --surface-list-row-hover: color-mix(in oklab, var(--bg-paper) 95%, var(--accent));

  /* stronger focus ring (3px, 30% accent) for primary interactive moments */
  --ring-accent-strong: 0 0 0 3px color-mix(in oklab, var(--accent) 30%, transparent);

  /* soft brand gradient — used by AI surfaces and the Sage drawer header band */
  --gradient-glow-soft: linear-gradient(135deg,
    color-mix(in oklab, var(--accent) 12%, transparent) 0%,
    color-mix(in oklab, var(--info)   10%, transparent) 100%);
  --ai-glow-bg: linear-gradient(135deg,
    color-mix(in oklab, var(--accent) 8%, transparent) 0%,
    color-mix(in oklab, var(--info)   6%, transparent) 100%);

  /* score / risk semantic aliases (drives Score ring, Health badge, SLA ring colour) */
  --score-low:     var(--success);
  --score-medium:  var(--warning);
  --score-high:    var(--error);

  /* badge tints — 12% colour over paper, used by risk badges, status pills */
  --badge-bg-success: color-mix(in oklab, var(--success) 12%, transparent);
  --badge-bg-warning: color-mix(in oklab, var(--warning) 12%, transparent);
  --badge-bg-danger:  color-mix(in oklab, var(--error)   12%, transparent);

  /* sparkline stroke — 1.2px in light, 1.5px in dark (per spec § 24) */
  --spark-stroke: 1.2px;

  /* density-mode row heights. Default = comfortable; the
     body[data-density="compact"] override below switches to compact.
     Components consume var(--row-h) so they automatically respond. */
  --row-h-comfortable: 52px;
  --row-h-compact:     36px;
  --row-h: var(--row-h-comfortable);
}

/* ink/dark mode — triggered by [data-theme="dark"] on <body> */
body[data-theme="dark"] {
  --bg:          var(--ink);
  --bg-paper:    #232842;
  --bg-sunk:     #141828;
  --bg-sunken:   #141828;
  --bg-warm:     #232842;                  /* dark-mode "warm" reads as raised paper */
  --bg-deep:     #0F1221;
  --fg:          #F4ECE4;
  --fg-soft:     #C9CFE2;
  --fg-dim:      rgba(244, 236, 228, 0.78);  /* was 0.7 — bumped for AA-body across all bgs */
  --fg-faint:    rgba(244, 236, 228, 0.62);  /* was 0.5 — bumped to clear AA-body 4.5+ on bg-paper */
  --hair:        rgba(244, 236, 228, 0.14);
  --hair-soft:   rgba(244, 236, 228, 0.07);
  --hair-warm:      rgba(210, 191, 170, 0.22);
  --hair-warm-soft: rgba(210, 191, 170, 0.12);
  --accent:      #FF4F87;  /* was #FF6E9D — pushed darker so white-on-accent
                              passes WCAG AA-large for chat bubbles, CTAs,
                              and pill chips. Pink-300 was too light. */
  --accent-soft: rgba(255, 63, 122, 0.24);
  --success:     var(--green-500);
  --success-soft: rgba(125, 244, 208, 0.16);
  --warning:     var(--yellow-500);
  --warning-soft: rgba(255, 216, 120, 0.18);
  --info:        var(--blue-500);
  --info-soft:   rgba(91, 217, 252, 0.16);
  --error:       #FF7A7A;
  --error-soft:  rgba(255, 120, 120, 0.16);

  /* In dark mode, the brand semantic colors are bright enough to read
     as text on the ink surface — alias the -text tokens back so the
     same rules work in both themes without per-mode overrides. */
  --accent-text:   var(--accent);
  --success-text:  var(--success);
  --info-text:     var(--info);
  --warning-text:  var(--warning);
  --error-text:    var(--error);

  /* dark mode glows — deeper and slightly more saturated so the brand
     warmth carries through the ink surface without feeling gauzy. */
  --glow-pink:   rgba(255, 110, 157, 0.14);
  --glow-blue:   rgba(91, 217, 252, 0.07);
  --glow-warm:   rgba(255, 216, 120, 0.05);

  /* hash pattern — lift to a light tint so the texture stays visible
     on ink without going full-contrast dots. */
  --stage-hash:  rgba(244, 236, 228, 0.04);

  /* App-pattern adjustments per spec § 24 (Dark-mode notes):
     • AI glow bg pumped ~1.5× so it reads at the same perceived brightness
       on the ink surface (light gradient on dark looks weaker than vice-versa)
     • Sparkline stroke +0.3px in dark to keep visual weight
     • Stronger ring uses the dark-mode --accent which is already shifted */
  --gradient-glow-soft: linear-gradient(135deg,
    color-mix(in oklab, var(--accent) 18%, transparent) 0%,
    color-mix(in oklab, var(--info)   15%, transparent) 100%);
  --ai-glow-bg: linear-gradient(135deg,
    color-mix(in oklab, var(--accent) 12%, transparent) 0%,
    color-mix(in oklab, var(--info)    9%, transparent) 100%);
  --spark-stroke: 1.5px;

  /* list-row hover — slightly more visible on the ink surface */
  --surface-list-row-hover: color-mix(in oklab, var(--bg-paper) 88%, var(--accent));

  /* badge tints — slightly stronger so the colour reads on dark paper */
  --badge-bg-success: color-mix(in oklab, var(--success) 18%, transparent);
  --badge-bg-warning: color-mix(in oklab, var(--warning) 18%, transparent);
  --badge-bg-danger:  color-mix(in oklab, var(--error)   18%, transparent);
}

/* ============================================================
   Density-mode override — opt-in via body[data-density="compact"].
   Components reference var(--row-h) for row/card heights so they
   automatically swap when this attribute flips. Toggle is demoed
   in 13-app-shell.html.
   ============================================================ */
body[data-density="compact"] {
  --row-h: var(--row-h-compact);
}

/* ============================================================ reset + base */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--f-body);
  font-optical-sizing: auto;
  color: var(--fg);
  background: var(--bg);
  line-height: 1.55;
  position: relative;
  transition: background var(--dur-3) var(--ease), color var(--dur-3) var(--ease);
  /* Defensive: prevent rogue 1-2px horizontal overflow at the body level.
     Components that need horizontal scroll (tables, kanban, command palette
     row) opt-in via their own overflow-x: auto. The page itself never
     scrolls horizontally on mobile. */
  overflow-x: hidden;
}
/* ambient brand atmosphere — lives behind every page, never clips.
   Pink in the top-right, cool blue in the bottom-left, and a whisper
   of warm yellow through the middle. Fixed so it doesn't move on
   scroll and lights the whole document like a soft-box. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(60vw 55vh at 88% 8%,  var(--glow-pink), transparent 65%),
    radial-gradient(50vw 50vh at 8% 92%,  var(--glow-blue), transparent 65%),
    radial-gradient(70vw 50vh at 50% 50%, var(--glow-warm), transparent 70%);
  transition: opacity var(--dur-3) var(--ease);
}
/* every page-content root needs to sit above the glow */
body > * { position: relative; z-index: 1; }
img, svg { max-width: 100%; display: block; }
a { color: var(--fg); text-decoration-color: var(--hair); text-underline-offset: 3px; }
a:hover { color: var(--accent-text); text-decoration-color: currentColor; }

/* keyboard focus ring — visible on all focusable elements */
:focus-visible {
  outline: none;
  box-shadow: var(--sh-focus);
  border-radius: var(--r-xs);
}
a:focus-visible, button:focus-visible, [role="button"]:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--sh-focus);
}

/* ============================================================ page chrome */

.page {
  max-width: 1160px;
  margin: 0 auto;
  padding: 0 var(--s-7);
}
@media (max-width: 640px) {
  .page { padding: 0 var(--s-4); }
}

/* top bar */
.topnav {
  position: sticky; top: 0; z-index: var(--z-sticky);
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--hair);
}
.topnav-inner {
  max-width: 1160px; margin: 0 auto;
  display: flex; align-items: center; gap: var(--s-6);
  padding: var(--s-4) var(--s-7);
}
@media (max-width: 640px) {
  .topnav-inner { gap: var(--s-3); padding: var(--s-3) var(--s-4); }
  .topnav .crumb { display: none; }
  .topnav .brand { font-size: 14px; }
}
.topnav .brand {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.02em;
  color: var(--fg);
  text-decoration: none;
  flex-shrink: 0;
}
/* The brand-mark slot is a 26×26 box that sits next to the wordmark in
   chapter-page top chrome. The icon is loaded from the kit's canonical
   CDN URL so it works in three contexts:
     • brand.magicblocks.ai chapter pages (same-origin)
     • Consumer apps that import @magicblocksai/css from npm
     • Local-disk previews with a network connection
   The asset is heavily edge-cached (24h max-age) so the network cost
   is one round-trip on first visit.

   Override locally if you ship your own logo:
     .topnav .brand-mark { background: url('/your/logo.svg') center/contain no-repeat; }
*/
.topnav .brand-mark {
  width: 26px; height: 26px; display: inline-block;
  background: url("https://brand.magicblocks.ai/02-icon/svg/magicblocks-icon-color.svg") center / contain no-repeat;
  flex-shrink: 0;
}
.topnav .brand-word { font-family: var(--f-display); font-weight: 700; }
/* legacy .dot fallback — invisible if not used */
.topnav .brand .dot { display: none; }

/* "Components" subsection label, sits AFTER the brand to give orientation
   context. Visible breadcrumb-style separator + label. Tells the user:
   "you're in the Components section of the MagicBlocks brand kit." */
.topnav .brand-sep {
  color: var(--fg-faint);
  font: 400 18px/1 var(--f-display);
  margin: 0 4px;
  user-select: none;
}
.topnav .brand-section {
  font: 600 13px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--fg-soft);
  text-decoration: none;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--hair);
  background: var(--bg-paper);
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  flex-shrink: 0;
}
.topnav .brand-section:hover {
  color: var(--fg);
  border-color: color-mix(in oklab, var(--accent) 40%, var(--hair));
}
/* Same atom but for the leaf in a two-level breadcrumb (e.g.
   `magicblocks · Library · Logos`). No border/background — keeps the chrome
   light. Always represents the current page so it isn't a link. */
.topnav .brand-subsection {
  font: 600 13px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--accent-text);
  padding: 6px 12px;
  flex-shrink: 0;
}

/* Cross-section pill nav — sits between the brand-section pill and the
   chapter dropdown in the chapter HTML topnav. Lets a chapter visitor jump
   directly to the kit-site companion sections (Tokens, Assets, Voice, …)
   without first going back to the brand-kit home. Mirrors the kit-site's
   own topnav links for IA unity. Hidden on tablet/mobile — those visitors
   reach the same destinations via the hamburger menu. */
.topnav .nav-sections {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  flex-shrink: 0;
}
.topnav .nav-sections a {
  font: 500 11.5px/1 var(--f-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fg-soft);
  text-decoration: none;
  padding: 6px 10px;
  border-radius: var(--r-pill);
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
  white-space: nowrap;
}
.topnav .nav-sections a:hover { color: var(--fg); background: var(--bg-warm); }
.topnav .nav-sections a[aria-current="true"] {
  color: var(--accent-text);
  background: var(--accent-soft);
}
@media (max-width: 1100px) {
  .topnav .nav-sections { display: none; }
}

.topnav .crumb {
  color: var(--fg-dim);
  font-size: 13px;
  display: flex; align-items: center; gap: var(--s-2);
}
.topnav .crumb .sep { color: var(--fg-faint); }
.topnav .spacer { flex: 1; }

/* ── Chapters mega-dropdown ────────────────────
   Mirror of the brand-kit-root pattern, but lists the 12 component
   chapters instead of brand-kit chapters. Wired by components/_shared.js
   (data-variant-tab handler is separate; this dropdown uses the
   nav-chapters-trigger handler in _shared.js). */
.site-menu {
  flex: 1;
  display: flex; align-items: center; gap: var(--s-3); justify-content: flex-end;
  font-family: var(--f-body); font-size: 13px;
  position: relative;
}
.nav-chapters { position: relative; }
.nav-chapters-trigger {
  appearance: none; -webkit-appearance: none;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  padding: 7px 14px 7px 16px;
  font: 500 13px/1 var(--f-body);
  color: var(--fg);
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}
.nav-chapters-trigger:hover { border-color: color-mix(in oklab, var(--accent) 30%, var(--hair)); }
.nav-chapters-trigger:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.nav-chapters-trigger .nav-chapters-num {
  font: 600 11px/1 var(--f-mono);
  color: var(--fg-dim);
  letter-spacing: 0.04em;
}
.nav-chapters-trigger .nav-chapters-caret {
  width: 10px; height: 10px; flex-shrink: 0;
  transition: transform var(--dur-2) var(--ease);
}
.nav-chapters.is-open .nav-chapters-trigger {
  background: var(--bg-sunk);
  border-color: var(--accent);
}
.nav-chapters.is-open .nav-chapters-caret { transform: rotate(180deg); }

.nav-chapters-panel {
  position: absolute;
  top: calc(100% + 10px); right: 0;
  /* Mega panel: 3-column grid for 12 chapters → fits all in one view */
  width: min(680px, calc(100vw - var(--s-7) * 2));
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  box-shadow: 0 24px 48px -20px color-mix(in oklab, var(--ink) 50%, transparent),
              0 8px 16px -8px color-mix(in oklab, var(--ink) 25%, transparent);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-5) var(--s-4);
  opacity: 0; transform: translateY(-6px) scale(0.98);
  transform-origin: top right;
  pointer-events: none;
  transition: opacity 200ms var(--ease), transform 200ms var(--ease);
  z-index: 10;
}
.nav-chapters.is-open .nav-chapters-panel {
  opacity: 1; transform: translateY(0) scale(1);
  pointer-events: auto;
}
.nav-chapters-group { display: flex; flex-direction: column; gap: 2px; }
.nav-chapters-group .nav-chapters-eyebrow {
  font: 600 10px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-dim);
  padding: 0 10px var(--s-2);
}
.nav-chapters-panel a {
  display: grid; grid-template-columns: 28px 1fr; align-items: baseline;
  gap: 10px; padding: 8px 10px;
  border-radius: var(--r-sm);
  text-decoration: none;
  transition: background var(--dur-1) var(--ease);
}
.nav-chapters-panel a:hover { background: var(--bg-warm); }
.nav-chapters-panel a[aria-current="page"] { background: var(--accent-soft); }
.nav-chapters-panel a .nav-chapters-num {
  font: 600 11.5px/1 var(--f-mono);
  color: var(--fg-dim);
}
.nav-chapters-panel a[aria-current="page"] .nav-chapters-num { color: var(--accent-text); }
.nav-chapters-panel a .nav-chapters-name {
  font: 600 13.5px/1.2 var(--f-display);
  color: var(--fg);
  letter-spacing: -0.005em;
}
.nav-chapters-panel a[aria-current="page"] .nav-chapters-name { color: var(--accent-text); }
.nav-chapters-panel a .nav-chapters-sub {
  display: block;
  font: 400 11px/1.3 var(--f-body);
  color: var(--fg-soft);
  margin-top: 2px;
}

/* "← Brand kit" back link, sits subtly far-right of the panel */
.nav-back {
  font: 500 12.5px/1 var(--f-body);
  color: var(--fg-dim);
  text-decoration: none;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  transition: color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
  flex-shrink: 0;
  display: inline-flex; align-items: center; gap: 6px;
}
.nav-back:hover { color: var(--fg); background: var(--bg-sunk); }

/* hamburger (mobile) — reuses the brand-kit pattern */
.nav-toggle {
  display: none;
  appearance: none; -webkit-appearance: none; background: transparent;
  border: 1px solid var(--hair); border-radius: var(--r-md);
  width: 36px; height: 36px; padding: 0;
  flex-direction: column; justify-content: center; align-items: center; gap: 4px;
  cursor: pointer; color: var(--fg);
  margin-left: auto;
}
.nav-toggle-bar {
  display: block; width: 16px; height: 1.75px; background: currentColor;
  border-radius: 1px;
  transition: transform var(--dur-2) var(--ease), opacity var(--dur-2) var(--ease);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(5.75px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-5.75px) rotate(-45deg); }

@media (max-width: 960px) {
  .topnav-inner { gap: var(--s-4); }
  .nav-toggle { display: inline-flex; }
  .topnav .brand-section, .topnav .brand-sep { display: none; }
  .site-menu {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: var(--s-3);
    background: var(--bg);
    border-bottom: 1px solid var(--hair);
    padding: var(--s-5);
    transform: translateY(-8px); opacity: 0; pointer-events: none;
    transition: transform var(--dur-2) var(--ease), opacity var(--dur-2) var(--ease);
    box-shadow: 0 20px 40px -20px rgba(20, 25, 55, 0.18);
  }
  .site-menu.is-open { transform: translateY(0); opacity: 1; pointer-events: auto; }
  .nav-chapters { width: 100%; }
  .nav-chapters-trigger { width: 100%; justify-content: center; }
  .nav-chapters-panel {
    position: static; width: 100%; grid-template-columns: 1fr;
    box-shadow: none; border-color: var(--hair-soft);
    margin-top: var(--s-3);
    opacity: 1; transform: none; pointer-events: auto;
  }
  .nav-back { width: 100%; text-align: center; justify-content: center; padding: 10px 12px; border: 1px solid var(--hair-soft); border-radius: var(--r-md); }
}

/* light / dark toggle */
.theme-toggle {
  display: inline-flex; align-items: center; gap: 0;
  background: var(--bg-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  padding: 3px;
  font-family: var(--f-body);
  font-size: 12px;
  font-weight: 500;
}
.theme-toggle button {
  appearance: none; -webkit-appearance: none;
  background: transparent; border: none;
  color: var(--fg-dim);
  padding: 5px 12px;
  border-radius: var(--r-pill);
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  transition: color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}
.theme-toggle button.is-active {
  background: var(--bg-paper);
  color: var(--fg);
  box-shadow: var(--sh-1);
}
.theme-toggle button svg { width: 13px; height: 13px; }

/* chapter header */
.chapter-head {
  padding: var(--s-11) 0 var(--s-9);
  border-bottom: 1px solid var(--hair);
}
.chapter-eyebrow {
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--fg-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 var(--s-4);
}
.chapter-title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.025em;
  margin: 0 0 var(--s-5);
  max-width: 22ch;
}
.chapter-title em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  /* Bright brand pink — display sizes (36–56px) easily clear AA-large at
     3:1, so we keep the on-brand --accent here. The darker --accent-text
     is reserved for body-sized text that needs the stricter 4.5:1 ratio. */
  color: var(--accent);
  font-variation-settings: "SOFT" 80;
}
.chapter-lede {
  font-size: 19px;
  line-height: 1.6;
  color: var(--fg-soft);
  max-width: 62ch;
  margin: 0 0 var(--s-6);
}

/* section divider (per-subsection) */
.section {
  padding: var(--s-11) 0;
  border-bottom: 1px solid var(--hair);
}
.section:last-of-type { border-bottom: 0; }
.section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-6); margin-bottom: var(--s-6);
  flex-wrap: wrap;
}
.section-title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 28px;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 0;
  display: flex; align-items: baseline; gap: var(--s-3);
}
.section-title .sn {
  font-family: var(--f-mono);
  font-size: 13px;
  color: var(--fg-faint);
  font-weight: 500;
}

/* section permalink — every .section gets a hash anchor next to its title.
   Shows on hover/focus; click copies the URL. JS adds the button; this
   styles it. */
.section-anchor {
  appearance: none;
  background: transparent;
  border: 0; padding: 0 var(--s-2);
  color: var(--fg-faint);
  font-family: var(--f-mono);
  font-size: 16px;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
  margin-left: var(--s-2);
  border-radius: var(--r-xs);
}
.section-anchor:hover,
.section:hover .section-anchor,
.section-anchor:focus-visible {
  opacity: 1;
  color: var(--accent-text);
}
.section-anchor.is-copied {
  opacity: 1;
  color: var(--success-text);
}
.section-anchor::before { content: '#'; }
.section-anchor.is-copied::before { content: '✓ copied'; font-size: 11px; }
/* keep the ID target visually off the sticky topnav when scrolled to */
.section { scroll-margin-top: 80px; }
.section-desc {
  color: var(--fg-soft);
  font-size: 16px;
  max-width: 60ch;
  line-height: 1.65;
  margin: 0 0 var(--s-7);
}

/* element block: the standard component slab */
.el {
  margin-bottom: var(--s-9);
}
.el-head {
  display: flex; align-items: baseline; gap: var(--s-4);
  flex-wrap: wrap;
  margin-bottom: var(--s-2);
}
.el-name {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 18px;
  letter-spacing: -0.005em;
  margin: 0;
}
.el-tag {
  font-family: var(--f-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--fg-dim);
  padding: 2px 7px;
  background: var(--bg-sunk);
  border-radius: var(--r-sm);
  border: 1px solid var(--hair-soft);
}
.el-desc {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--fg-soft);
  margin: 0 0 var(--s-4);
  max-width: 68ch;
}
/* empty descriptions (generated in bulk) were adding ~40px of dead space
   above every demo — collapse them so spacing stays consistent. */
.el-desc:empty, .section-desc:empty { display: none; }

/* the render + code panel */
.demo {
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-paper);
}
.demo-stage {
  padding: var(--s-7);
  display: flex; flex-wrap: wrap;
  gap: var(--s-5);
  align-items: flex-start;
  background:
    linear-gradient(var(--bg-paper), var(--bg-paper)),
    repeating-linear-gradient(
      45deg,
      transparent 0 6px,
      var(--stage-hash) 6px 7px
    );
  background-blend-mode: normal;
}
.demo-stage.center { justify-content: center; }
.demo-stage.vert { flex-direction: column; align-items: stretch; }
.demo-stage.plain { background: var(--bg-paper); }
/* .warm and .ink are deliberate surface variants — they pin to a specific
   tonal treatment regardless of theme so the component demo always reads
   the way the brand intends. In dark mode we nudge each one slightly so
   it stays visually separated from the surrounding page. */
.demo-stage.warm { background: var(--warm-3); color: var(--ink); }

/* ── warm-pinned surface scope ─────────────────────────────
   The warm cream tokens (--warm-1…7) DON'T flip in dark mode — by
   design, the brand's cream-paper identity carries through both
   themes. But that means any descendant reading var(--fg) on a
   warm-bg container gets cream-on-cream in dark mode (light text on
   sand bg = unreadable, e.g. .infra-map labels).
   Apply .mb-pin-warm — or list a known surface in the selector below —
   to scope --fg / --fg-soft / --fg-dim / --hair / --bg-paper back to
   ink-tinted values so every nested element stays legible. */
/* surfaces that genuinely OWN a warm bg — pinning ink-text inside them
   keeps copy legible in dark mode. Components without their own bg
   (e.g. .cost-compare which is just a layout) must NOT be in this list,
   or their text will pin to ink and disappear on the dark page bg. */
.mb-pin-warm,
.infra-map,
.hs-screen,
.hld-app,
.sc-screen,
.hero-bloom-canvas[data-variant="warm"],
.journey-map,
.roi-calc .roi-inputs,
.demo-stage.warm,
.cc-col.generic,
/* Scoreboard column-header cells own a pinned warm-3 bg (see 11-narrative-systems
   .scoreboard .sb-head > *). Rescoping the whole .scoreboard would break the
   .sb-row .good cells (which read var(--fg) and need cream in dark mode), so
   the rescope is tightened to just the head cells. .scoreboard.dark variant
   sets its own ink bg + paper text and is excluded. */
.scoreboard:not(.dark) .sb-head > * {
  --fg:        #191E32;
  --fg-soft:   #466099;
  --fg-dim:    rgba(25, 30, 50, 0.62);
  --fg-faint:  rgba(25, 30, 50, 0.45);
  --hair:      rgba(25, 30, 50, 0.12);
  --hair-soft: rgba(25, 30, 50, 0.06);
  --bg-paper:  #FFFFFF;
  --bg-sunk:   #E8DBCB;
  --bg-warm:   #F9F1E8;
}
.demo-stage.ink {
  background: var(--ink); color: var(--warm-3);
  --fg: var(--warm-3); --fg-soft: #C9CFE2; --hair: rgba(244,236,228,.14);
}
body[data-theme="dark"] .demo-stage.ink {
  /* lift off the page bg (also ink) with a subtle highlight ring */
  background: #1F2338;
  box-shadow: inset 0 0 0 1px rgba(244, 236, 228, 0.06);
}
body[data-theme="dark"] .demo-stage.warm {
  /* slightly richer warm so it feels intentional against the ink page */
  background: #E6D6C3;
}

/* variant tabs — for components with multiple modes/variants that
   each need to be seen at full size. Sits ABOVE the demo stage; the
   active variant's panel renders below. CSS-only swap based on
   .is-active class on tab + matching .is-active on .variant-panel.
   Wired in components/_shared.js (clicks on [data-variant-tab]). */
.variant-tabs {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 4px;
  background: var(--bg-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  margin-bottom: var(--s-4);
  font-family: var(--f-mono);
  font-size: 12px;
}
.variant-tabs button {
  appearance: none; background: transparent; border: 0;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  color: var(--fg-dim);
  cursor: pointer;
  font: 500 11.5px/1 var(--f-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: color 160ms var(--ease), background 160ms var(--ease);
  display: inline-flex; align-items: center; gap: 6px;
}
.variant-tabs button:hover { color: var(--fg); }
.variant-tabs button.is-active {
  background: var(--accent);
  color: var(--paper);
  box-shadow: 0 4px 12px -4px color-mix(in oklab, var(--accent) 50%, transparent);
}
.variant-tabs button:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.variant-tabs .vt-num {
  font: 700 10.5px/1 var(--f-mono);
  opacity: 0.7;
}
.variant-tabs button.is-active .vt-num { opacity: 0.85; }

/* the panel each tab reveals */
.variant-panel { display: none; }
.variant-panel.is-active { display: block; animation: vp-fade 320ms var(--ease); }
@keyframes vp-fade {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .variant-panel.is-active { animation: none; }
}

/* code tabs */
.demo-tabs {
  border-top: 1px solid var(--hair);
  display: flex; align-items: stretch;
  background: var(--bg-sunk);
  gap: 0;
  font-family: var(--f-mono); font-size: 12px;
}
.demo-tabs button {
  appearance: none; background: transparent; border: 0;
  padding: var(--s-3) var(--s-5);
  color: var(--fg-dim); cursor: pointer;
  display: inline-flex; align-items: center; gap: var(--s-2);
  border-right: 1px solid var(--hair);
  font-family: inherit; font-size: inherit;
}
.demo-tabs button.is-active { color: var(--fg); background: var(--bg-paper); }
.demo-tabs .spacer { flex: 1; }
.demo-tabs .copy {
  border-left: 1px solid var(--hair); border-right: 0;
  padding: 0 var(--s-5);
  color: var(--fg-dim);
}
.demo-tabs .copy:hover { color: var(--accent-text); }
.demo-tabs .copy.is-copied { color: var(--success-text); }

.demo-code {
  display: none;
  margin: 0;
  padding: var(--s-5) var(--s-6);
  background: var(--ink);
  color: #F4ECE4;
  font-family: var(--f-mono);
  font-size: 12.5px;
  line-height: 1.65;
  /* overflow-x: auto only works when width is constrained — pair with
     max-width:100% + min-width:0 so long lines scroll instead of widening
     the parent grid track. */
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  white-space: pre;
  tab-size: 2;
  -moz-tab-size: 2;
}
.demo-code.is-active { display: block; }
.demo-code code { display: block; min-width: 0; }
/* tiny syntax hints inside .demo-code */
.demo-code .t { color: #FF9AB8; }  /* tags */
.demo-code .a { color: #FFD878; }  /* attr */
.demo-code .s { color: #7DF4D0; }  /* strings */
.demo-code .c { color: rgba(244,236,228,0.4); font-style: italic; } /* comment */
.demo-code .p { color: #5BD9FC; }  /* property */

/* anatomy callouts */
.anatomy {
  position: relative;
  border: 1px dashed var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-10) var(--s-10);
  margin-top: var(--s-4);
  background:
    linear-gradient(var(--bg-paper), var(--bg-paper)) padding-box,
    linear-gradient(135deg, rgba(255,63,122,0.3), rgba(31,170,232,0.3)) border-box;
  border: 1px dashed transparent;
}
.anatomy-legend {
  list-style: none; padding: 0; margin: var(--s-6) 0 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--s-3) var(--s-5);
  font-family: var(--f-mono); font-size: 12px;
  color: var(--fg-soft);
}
.anatomy-legend li {
  display: flex; gap: var(--s-3); align-items: baseline;
}
.anatomy-legend .n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: 0 0 20px;
  border-radius: 50%;
  background: var(--accent); color: #fff;
  font-weight: 600; font-size: 10px;
}
.anatomy-chip {
  position: absolute;
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--accent); color: #fff;
  font-family: var(--f-mono); font-weight: 600; font-size: 10px;
  box-shadow: 0 0 0 3px var(--bg-paper);
  pointer-events: none;
  z-index: 2;
}
/* Inline numbered pin — sits adjacent to a feature instead of floating
   over it. Use on tables / cards where absolute positioning would drift
   when the parent reflows. Preserves the same visual language as
   .anatomy-chip and .anatomy-legend .n. */
.n-pin {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--accent); color: #fff;
  font: 600 10px/1 var(--f-mono);
  box-shadow: 0 0 0 2px var(--bg-paper);
  flex-shrink: 0;
  margin-right: 8px;
  vertical-align: middle;
}
.n-pin-tight { margin-right: 4px; }
/* Right-aligned cells get the pin to the LEFT of the value so numbers
   still right-align with their sibling rows. */
.tbl-right .n-pin { margin-right: 6px; }

/* ============================================================ utilities */

.row { display: flex; gap: var(--s-4); flex-wrap: wrap; align-items: center; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-6); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-6); }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-5); }
.grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s-5); }
@media (max-width: 720px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

.mono  { font-family: var(--f-mono); }
.small { font-size: 12px; }

/* ── avatars (shared atom) ─────────────────────────────────
   Originally defined only in 07-data-display.html, but used in
   content blocks (09), page templates (10), and anywhere a byline,
   presenter bug, or team card appears. Lifted here so every page
   inherits the base shape without having to re-declare it. */
.av {
  width: 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 12px/1 var(--f-display); letter-spacing: 0.02em;
  flex-shrink: 0;
  overflow: hidden;                           /* clip image children cleanly */
}
.av img { width: 100%; height: 100%; object-fit: cover; }
.av-xs { width: 20px; height: 20px; font-size: 9px; }
.av-sm { width: 26px; height: 26px; font-size: 10.5px; }
.av-lg { width: 40px; height: 40px; font-size: 14px; }
.av-xl { width: 56px; height: 56px; font-size: 19px; }
.av-ring { box-shadow: 0 0 0 2px var(--bg-paper), 0 0 0 4px var(--accent); }
.av-row { display: flex; align-items: center; gap: var(--s-3); }
.av-stack { display: inline-flex; }
.av-stack .av { margin-left: -8px; box-shadow: 0 0 0 2px var(--bg-paper); }
.av-stack .av:first-child { margin-left: 0; }
.av-more {
  background: var(--bg-sunken) !important; color: var(--fg-soft) !important;
  font-family: var(--f-mono); font-weight: 600;
}

/* ──────────────────────────────────────────────────────────────
   Shared primitives — forms, buttons, empty states
   ──────────────────────────────────────────────────────────────
   Previously these lived inside individual chapter files (forms in 04,
   empties in 07, buttons in 03). That fragmented approach meant when
   chapter 10 referenced `.input` or `.empty-ic`, the selectors had no
   style — the settings shell dropped to native-browser chrome, the
   empty-state SVGs rendered as unstyled rectangles. Lifting these
   primitives into _shared.css means every chapter inherits them
   consistently, the way the brand-kit is supposed to work. Chapter-
   specific variants can still live in the individual chapter <style>
   blocks and will compose cleanly on top. ────────────────────── */

/* Buttons — full family. Canonical definitions promoted from chapter 3
   so every chapter picks up the same transitions, padding, and variant
   suite. Includes primary (pink CTA), secondary (outlined paper), ghost,
   danger (filled), danger-outline, size modifiers (sm / default / lg /
   xl), and composition helpers (.btn-link, .btn-group, .btn-split). */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2);
  font: 600 14.5px/1 var(--f-display);
  letter-spacing: -0.005em;
  padding: 11px var(--s-5);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease),
              transform var(--dur-2) var(--ease),
              box-shadow var(--dur-2) var(--ease),
              color var(--dur-2) var(--ease);
  user-select: none;
  white-space: nowrap;
  appearance: none; -webkit-appearance: none;
}
.btn:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; pointer-events: none; }

.btn-primary {
  background: var(--accent); color: var(--paper);
  box-shadow: var(--sh-pink);
}
.btn-primary:hover   { transform: translateY(-1px); filter: brightness(1.04); }
.btn-primary:active  { transform: translateY(0); filter: brightness(0.96); }

.btn-secondary {
  background: var(--bg-paper);
  color: var(--fg);
  border-color: var(--hair);
}
.btn-secondary:hover {
  border-color: var(--fg);
  background: var(--bg-paper);
  transform: translateY(-1px);
}
.btn-secondary:active { transform: translateY(0); }

.btn-ghost {
  background: transparent;
  color: var(--fg);
  border-color: transparent;
}
.btn-ghost:hover {
  background: var(--bg-sunk);
  border-color: var(--hair);
}

.btn-danger { background: var(--error); color: var(--paper); }
.btn-danger:hover { filter: brightness(1.05); transform: translateY(-1px); }

.btn-danger-outline {
  background: transparent; color: var(--error-text);
  border-color: rgba(214, 69, 69, 0.3);
}
.btn-danger-outline:hover {
  background: var(--error-soft);
  border-color: var(--error);
}

/* Sizes — the bare `.btn` line is deliberately re-declared to reset
   padding/font if a preceding modifier set them (e.g. inside .btn-group). */
.btn-sm { padding: 7px var(--s-4); font-size: 13px; border-radius: var(--r-sm); }
.btn    { padding: 11px var(--s-5); font-size: 14.5px; }                          /* default */
.btn-lg { padding: 13px var(--s-6); font-size: 15.5px; }
.btn-xl {
  padding: 16px var(--s-7);
  font-size: 17px;
  border-radius: var(--r-lg);
  gap: var(--s-3);
}

/* Icon-only buttons — square, uses the neutral ghost-style body. */
.icon-btn {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  color: var(--fg);
  cursor: pointer;
  transition: background var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease),
              color var(--dur-2) var(--ease);
}
.icon-btn:hover { border-color: var(--fg); color: var(--fg); }
.icon-btn:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.icon-btn-primary {
  background: var(--accent); color: var(--paper);
  border-color: transparent;
}
.icon-btn-primary:hover { filter: brightness(1.05); color: var(--paper); }

/* Text-link variant styled like a button — underline tail + arrow shift. */
.btn-link {
  display: inline-flex; align-items: center; gap: var(--s-2);
  color: var(--fg);
  font: 600 14.5px/1 var(--f-display);
  text-decoration: none;
  padding: 2px 0;
  border-bottom: 1px solid var(--hair);
  transition: color var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease),
              transform var(--dur-2) var(--ease);
}
.btn-link svg { transition: transform var(--dur-2) var(--ease); }
/* Use the bright brand --accent (pink-700) instead of the AA-darkened
   --accent-text. The link button is 14.5px/600 weight → falls under
   WCAG AA-large (3:1) which the bright accent passes (~4:1 on paper),
   so we can keep brand pop without the wine/burgundy cast. */
.btn-link:hover { color: var(--accent); border-color: var(--accent); }
.btn-link:hover svg { transform: translateX(3px); }
.btn-link-accent { color: var(--accent); border-color: var(--accent-soft); }
.btn-link-accent:hover { border-color: var(--accent); }

/* Button groups + split buttons */
.btn-group { display: inline-flex; }
.btn-group .btn {
  border-radius: 0;
  border-right-width: 0;
}
.btn-group .btn:first-child { border-top-left-radius: var(--r-md); border-bottom-left-radius: var(--r-md); }
.btn-group .btn:last-child  { border-top-right-radius: var(--r-md); border-bottom-right-radius: var(--r-md); border-right-width: 1px; }
.btn-group .btn:hover       { z-index: 1; position: relative; }

.btn-split { display: inline-flex; }
.btn-split-main { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.btn-split-icon {
  padding: 11px var(--s-3);
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-left: 1px solid rgba(255,255,255,0.25);
}

.btn-loading { pointer-events: none; }

/* Inputs — textual + select. The select variant adds a brand-aware chevron. */
.input {
  display: block; width: 100%;
  font: 400 14.5px/1.4 var(--f-body);
  color: var(--fg);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  padding: 10px 14px;
  transition: border-color var(--dur-2) var(--ease),
              box-shadow var(--dur-2) var(--ease);
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
}
.input::placeholder { color: var(--fg-faint); }
.input:hover:not(:disabled):not(:focus) { border-color: var(--fg-dim); }
.input:focus { outline: 0; border-color: var(--accent); box-shadow: var(--sh-focus); }
/* warm-3 (lightest warm) for the disabled wash — warm-5/bg-sunk reads
   as "dirty/heavy" against white surfaces. Dark mode flips back. */
.input:disabled { background: var(--warm-3); color: var(--fg-dim); cursor: not-allowed; }
body[data-theme="dark"] .input:disabled { background: var(--bg-sunk); }
textarea.input { min-height: 88px; resize: vertical; line-height: 1.5; }
select.input,
.input[type="date"],
.input[type="time"] {
  padding-right: 40px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23466099' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='m5 8 5 5 5-5'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
  cursor: pointer;
}
body[data-theme="dark"] select.input,
body[data-theme="dark"] .input[type="date"],
body[data-theme="dark"] .input[type="time"] {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23C9CFE2' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='m5 8 5 5 5-5'/></svg>");
}

/* Input composition ecosystem — label / hint / error / success / group /
   affix / prefix / suffix / meta / counter. Lifted from chapter 4 so
   every chapter can build labelled-and-validated form rows consistently. */
.input-wrap { display: flex; flex-direction: column; gap: 6px; }
.input-label { font: 500 13px/1.3 var(--f-body); color: var(--fg); }
.input-hint  { font: 400 12.5px/1.4 var(--f-body); color: var(--fg-dim); }
.input-error   { font: 500 12.5px/1.4 var(--f-body); color: var(--error-text);   display: inline-flex; align-items: center; gap: 4px; }
.input-success { font: 500 12.5px/1.4 var(--f-body); color: var(--success-text); display: inline-flex; align-items: center; gap: 4px; }

.input-wrap.is-error .input         { border-color: var(--error); }
.input-wrap.is-error .input:focus   { box-shadow: 0 0 0 3px var(--error-soft); }
.input-wrap.is-success .input       { border-color: var(--success); }

/* Group — lets leading / trailing icons or prefixes/suffixes attach flush. */
.input-group {
  position: relative;
  display: flex;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  transition: border-color var(--dur-2) var(--ease),
              box-shadow   var(--dur-2) var(--ease);
}
.input-group:focus-within {
  border-color: var(--accent);
  box-shadow: var(--sh-focus);
}
.input-group .input { border: 0; background: transparent; }
.input-group .input:focus { box-shadow: none; }

.input-affix {
  position: absolute; top: 0; bottom: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; color: var(--fg-dim);
  pointer-events: none;
}
.input-group .input-affix:first-child { left: 0; }
.input-group .input-affix:last-child  { right: 0; }
.input-affix-btn { pointer-events: auto; background: transparent; border: 0; cursor: pointer; border-radius: var(--r-xs); }
.input-affix-btn:hover { color: var(--fg); }

.input.has-leading  { padding-left: 38px; }
.input.has-trailing { padding-right: 38px; }

.input-prefix,
.input-suffix {
  display: inline-flex; align-items: center;
  padding: 0 12px;
  font: 400 14px/1 var(--f-mono);
  color: var(--fg-dim);
  /* warm-3 (lightest warm) for the affix wash — warm-5/bg-sunk reads
     as "dirty/heavy" against the white input surface. Dark mode flips. */
  background: var(--warm-3);
  border-right: 1px solid var(--hair);
}
body[data-theme="dark"] .input-prefix,
body[data-theme="dark"] .input-suffix { background: var(--bg-sunk); }
.input-suffix { border-right: 0; border-left: 1px solid var(--hair); }
.input.has-prefix { padding-left: 12px; }

.input-meta {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--s-4);
}
.input-counter { font-size: 12px; color: var(--fg-dim); }

/* Empty states — .empty wrapper with icon + title + lede + actions.
   Originally in 07-data-display.html; lifted so chapter 10's empty-
   templates page and anywhere else can use the same primitive. */
.empty {
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  padding: var(--s-9) var(--s-5);
  background: var(--bg-paper);
  border: 1px dashed var(--hair);
  border-radius: var(--r-lg);
  width: 100%;                       /* fill the grid slot / column */
  max-width: min(640px, 100%);       /* cap on very wide single-column pages */
  margin: 0 auto;
}
.empty-ic {
  width: 72px; height: 72px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--warm-3);
  color: color-mix(in oklab, var(--ink) 55%, transparent);
  margin-bottom: var(--s-4);
  flex-shrink: 0;
}
body[data-theme="dark"] .empty-ic {
  background: var(--bg-sunk);
  color: color-mix(in oklab, var(--fg) 70%, transparent);
}
.empty-title {
  font: 600 20px/1.2 var(--f-display); letter-spacing: -0.01em;
  margin: 0 0 6px; color: var(--fg);
}
.empty-lede {
  font: 400 14.5px/1.55 var(--f-body); color: var(--fg-soft);
  margin: 0 0 var(--s-5); max-width: 36ch;
}
.empty-actions {
  display: flex; gap: var(--s-4); align-items: center;
  flex-wrap: wrap; justify-content: center;
}
.empty-btn {
  background: var(--accent); color: var(--paper);
  font: 600 13.5px/1 var(--f-display);
  padding: 10px var(--s-4); border-radius: var(--r-md);
  text-decoration: none; box-shadow: var(--sh-pink);
  transition: transform var(--dur-2) var(--ease);
  display: inline-flex; align-items: center; gap: var(--s-2);
  border: 0; cursor: pointer;
}
.empty-btn:hover { transform: translateY(-1px); color: var(--paper); }
.empty-ghost {
  background: transparent; border: 1px solid var(--hair);
  color: var(--fg); font: 600 13px/1 var(--f-display);
  padding: 10px 16px; border-radius: var(--r-md); cursor: pointer;
}
.empty-ghost:hover { background: var(--bg-warm); }
.empty-link {
  color: var(--fg-soft); font: 500 13.5px/1 var(--f-body);
  text-decoration: none; display: inline-flex; align-items: center; gap: 4px;
}
.empty-link:hover { color: var(--accent-text); }

/* chapter TOC (side nav on every page) */
.toc {
  position: sticky; top: 72px;
  font-family: var(--f-mono);
  font-size: 12px;
  line-height: 1.8;
  padding: var(--s-5) 0;
}
.toc h4 {
  font-family: var(--f-body);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--fg-faint);
  margin: 0 0 var(--s-3);
}
.toc a {
  display: block; color: var(--fg-soft);
  text-decoration: none; padding: 2px 0;
  border-left: 2px solid transparent;
  padding-left: var(--s-3);
  margin-left: calc(-1 * var(--s-3));
}
.toc a:hover { color: var(--accent-text); }
.toc a.is-active { color: var(--fg); border-left-color: var(--accent); }

/* layout: two-col with toc on left.
   NOTE: minmax(0, 1fr) (not just 1fr) on the content column is critical —
   grid tracks default to minmax(auto, 1fr), which lets intrinsic content
   (wide <pre> blocks inside .demo-code) push the column past its share
   and break the page width. min-width:0 on .content is belt-and-braces. */
.layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: var(--s-9);
  padding: var(--s-6) 0 var(--s-13);
}
.layout > .content { min-width: 0; }
@media (max-width: 960px) {
  .layout { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .toc { display: none; }
}

/* prev/next chapter footer */
.page-nav {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--s-5);
  margin: var(--s-11) 0 var(--s-13);
}
.page-nav a {
  display: block; padding: var(--s-6);
  border: 1px solid var(--hair); border-radius: var(--r-lg);
  background: var(--bg-paper);
  text-decoration: none; color: var(--fg);
  transition: border-color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.page-nav a:hover { border-color: var(--accent); transform: translateY(-1px); }
.page-nav .dir {
  font-family: var(--f-mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--fg-faint); margin-bottom: 6px;
}
.page-nav .title {
  font-family: var(--f-display); font-weight: 600; font-size: 18px;
}
.page-nav .next { text-align: right; }
@media (max-width: 720px) {
  .page-nav { grid-template-columns: 1fr; }
  .page-nav .next { text-align: left; }
}

/* footer */
.foot {
  padding: var(--s-9) 0;
  border-top: 1px solid var(--hair);
  color: var(--fg-dim);
  font-size: 13px;
  display: flex; justify-content: space-between; gap: var(--s-6);
  flex-wrap: wrap;
}
.foot .mono { font-size: 12px; }

/* ============================================================ motion primitives
   Shared reveal + svg-draw used by chapter 11 narrative systems (and anywhere
   else that wants a "when in view" transition). Honours prefers-reduced-motion
   — _shared.js short-circuits and marks every .reveal as is-visible immediately
   when the user prefers less motion. */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 480ms var(--ease), transform 480ms var(--ease);
  transition-delay: calc(var(--i, 0) * 60ms);
  will-change: opacity, transform;
}
.reveal.is-visible { opacity: 1; transform: none; }

/* SVG line draw — pair with .reveal so the draw plays on intersection */
.svg-draw path,
.svg-draw .draw {
  stroke-dasharray: var(--draw-len, 1200);
  stroke-dashoffset: var(--draw-len, 1200);
  transition: stroke-dashoffset 1200ms ease-out;
  transition-delay: calc(var(--i, 0) * 60ms);
}
.svg-draw.is-visible path,
.svg-draw.is-visible .draw { stroke-dashoffset: 0; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .svg-draw path, .svg-draw .draw { stroke-dasharray: none; stroke-dashoffset: 0; transition: none; }
}

/* ============================================================
   Floating page utilities — back-to-top + section nav
   Auto-injected by _shared.js on any chapter page with 3+ sections.
   Lives on the left edge so it never sits over reading content;
   the popover opens upward + to the right of the pill. */
.mb-float {
  position: fixed; left: 20px; bottom: 20px; z-index: 70;
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  pointer-events: none;
  font-family: var(--f-body, system-ui);
}
.mb-float button,
.mb-float a {
  pointer-events: auto;
  appearance: none; -webkit-appearance: none;
  font: 600 11.5px/1 var(--f-mono, ui-monospace, "JetBrains Mono", monospace);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--fg);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: 999px;
  padding: 10px 14px;
  display: inline-flex; align-items: center; gap: 6px;
  box-shadow: 0 12px 28px -16px rgba(25, 30, 50, 0.45),
              0 4px 10px -4px rgba(25, 30, 50, 0.25);
  cursor: pointer;
  text-decoration: none;
  transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1),
              opacity 200ms ease,
              background 160ms ease,
              border-color 160ms ease,
              color 160ms ease;
  opacity: 0; transform: translateY(8px) scale(0.96);
}
.mb-float.is-visible button,
.mb-float.is-visible a {
  opacity: 1; transform: translateY(0) scale(1);
}
.mb-float button:hover,
.mb-float a:hover {
  background: var(--accent);
  color: var(--paper);
  border-color: transparent;
  transform: translateY(-1px);
}
.mb-float .mb-float-top svg,
.mb-float .mb-float-toc svg {
  width: 14px; height: 14px;
  stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

.mb-float-pop {
  pointer-events: auto;
  position: absolute; left: 0; bottom: 100%;
  margin-bottom: 10px;
  width: min(280px, calc(100vw - 40px));
  max-height: 60vh;
  overflow-y: auto;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: 14px;
  box-shadow: 0 24px 48px -20px rgba(25, 30, 50, 0.50),
              0 8px 16px -8px rgba(25, 30, 50, 0.25);
  padding: 8px;
  opacity: 0; transform: translateY(8px) scale(0.96);
  transform-origin: bottom left;
  pointer-events: none;
  transition: opacity 180ms ease, transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
}
.mb-float.is-open .mb-float-pop {
  opacity: 1; transform: translateY(0) scale(1);
  pointer-events: auto;
}
.mb-float-pop .mb-float-pop-title {
  font: 600 10.5px/1 var(--f-mono, ui-monospace, "JetBrains Mono", monospace);
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--fg-dim);
  padding: 8px 10px 6px;
}
.mb-float-pop a {
  display: flex; align-items: baseline; gap: 8px;
  padding: 8px 10px;
  border-radius: 8px;
  font: 500 13px/1.35 var(--f-body, system-ui);
  color: var(--fg-soft);
  text-transform: none;
  letter-spacing: normal;
  border: 0;
  background: transparent;
  box-shadow: none;
  opacity: 1;
  transform: none;
}
.mb-float-pop a .num {
  font: 500 11px/1 var(--f-mono, ui-monospace, "JetBrains Mono", monospace);
  color: var(--fg-dim);
  flex-shrink: 0; min-width: 28px;
}
.mb-float-pop a:hover {
  background: var(--bg-warm);
  color: var(--fg);
  transform: none;
  border-color: transparent;
}
.mb-float-pop a.is-active {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.mb-float-pop a.is-active .num { color: var(--accent-text); }

@media print { .mb-float { display: none !important; } }
@media (prefers-reduced-motion: reduce) {
  .mb-float button, .mb-float a, .mb-float-pop {
    transition: none !important;
  }
}
@media (max-width: 480px) {
  .mb-float { left: 14px; bottom: 14px; gap: 8px; }
  .mb-float button, .mb-float a { padding: 9px 12px; font-size: 11px; }
}

/* ============================================================
   Atom components migrated from chapter inline <style> blocks so
   that consumers of @magicblocks/css (static-site distribution)
   get the full atom surface, not just the page chrome. The
   chapter HTML files keep their inline definitions for now —
   identical rules, harmless cascade. Phase 4 modularization will
   deduplicate.
   ============================================================ */

/* ─── Switch (chapter 03) ─────────────────────────────────── */
.switch {
  display: inline-flex; align-items: center; gap: var(--s-3);
  cursor: pointer;
  font: 500 14.5px/1.3 var(--f-body);
  color: var(--fg);
  user-select: none;
  position: relative;
}
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.switch-track {
  flex: 0 0 40px;
  width: 40px; height: 22px;
  background: var(--bg-deep);
  border-radius: var(--r-pill);
  position: relative;
  transition: background var(--dur-2) var(--ease);
}
.switch-track::after {
  content: ""; position: absolute;
  top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--paper);
  box-shadow: var(--sh-1);
  transition: transform var(--dur-2) var(--ease);
}
.switch input:checked + .switch-track { background: var(--accent); }
.switch input:checked + .switch-track::after { transform: translateX(18px); }
.switch input:focus-visible + .switch-track { box-shadow: var(--sh-focus); }
.switch input:disabled ~ * { opacity: .5; }
.switch input:disabled { cursor: not-allowed; }
.switch-label { /* visible label text — inherits .switch typography */ }

/* ─── Checkbox + Radio (chapter 03) ─────────────────────────── */
.cb, .rb {
  display: inline-flex; align-items: center; gap: var(--s-3);
  cursor: pointer;
  font: 500 14.5px/1.3 var(--f-body);
  color: var(--fg);
  user-select: none;
  position: relative;
}
.cb input, .rb input { position: absolute; opacity: 0; pointer-events: none; }
.cb-box, .rb-circle {
  flex: 0 0 18px;
  width: 18px; height: 18px;
  border: 1.5px solid var(--hair);
  background: var(--bg-paper);
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  position: relative;
}
.cb-box { border-radius: var(--r-xs); }
.rb-circle { border-radius: 50%; }
.cb input:hover + .cb-box, .rb input:hover + .rb-circle { border-color: var(--fg-dim); }
.cb input:checked + .cb-box {
  background: var(--accent); border-color: var(--accent);
}
.cb input:checked + .cb-box::after {
  content: ""; position: absolute;
  top: 2.5px; left: 5px;
  width: 4px; height: 8px;
  border: solid var(--paper);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.cb input:indeterminate + .cb-box {
  background: var(--accent); border-color: var(--accent);
}
.cb input:indeterminate + .cb-box::after {
  content: ""; position: absolute;
  top: 7px; left: 3px;
  width: 10px; height: 2px;
  background: var(--paper);
  border-radius: 1px;
}
.rb input:checked + .rb-circle { border-color: var(--accent); }
.rb input:checked + .rb-circle::after {
  content: ""; position: absolute;
  inset: 3px;
  background: var(--accent);
  border-radius: 50%;
}
.cb input:focus-visible + .cb-box, .rb input:focus-visible + .rb-circle {
  box-shadow: var(--sh-focus);
}
.cb input:disabled ~ *, .rb input:disabled ~ * { opacity: .5; }
.cb input:disabled, .rb input:disabled { cursor: not-allowed; }

/* ─── Badge (chapter 07) ─────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  font: 500 11.5px/1.2 var(--f-body);
  background: var(--hair-soft);
  color: var(--fg);
  border: 1px solid transparent;
}
.badge-row { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.badge-accent  { background: var(--accent-soft);  color: var(--accent-text); }
.badge-success { background: var(--success-soft); color: var(--success-text); }
.badge-warning { background: var(--warning-soft); color: var(--warning-text); }
.badge-danger  { background: var(--error-soft);   color: var(--error-text); }
.badge-info    { background: var(--info-soft);    color: var(--info-text); }
.badge-count {
  min-width: 20px; height: 20px; padding: 0 6px;
  justify-content: center;
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}

/* ─── Chip (chapter 07) ─────────────────────────────────── */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  font: 500 12.5px/1.3 var(--f-body);
  background: var(--bg-paper);
  color: var(--fg);
  border: 1px solid var(--hair);
  white-space: nowrap;
}
.chip-row { display: inline-flex; flex-wrap: wrap; gap: var(--s-2); }
.chip-pink   { background: var(--accent-soft);  color: var(--accent-text);  border-color: color-mix(in oklab, var(--accent) 25%, transparent); }
.chip-blue   { background: var(--info-soft);    color: var(--info-text);    border-color: color-mix(in oklab, var(--info) 25%, transparent); }
.chip-green  { background: var(--success-soft); color: var(--success-text); border-color: color-mix(in oklab, var(--success) 25%, transparent); }
.chip-amber  { background: var(--warning-soft); color: var(--warning-text); border-color: color-mix(in oklab, var(--warning) 25%, transparent); }
.chip-red    { background: var(--error-soft);   color: var(--error-text);   border-color: color-mix(in oklab, var(--error) 25%, transparent); }
.chip-purple { background: #EFE4FF; color: #5C2CA8; border-color: color-mix(in oklab, #5C2CA8 15%, transparent); }
body[data-theme="dark"] .chip-purple { background: rgba(180, 140, 240, 0.18); color: #D7C4FF; border-color: rgba(180, 140, 240, 0.32); }
.chip-dismiss { padding-right: 4px; }
.chip-dismiss button {
  appearance: none; background: transparent; border: 0; cursor: pointer;
  width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0; font: 500 13px/1 var(--f-body);
  color: currentColor; opacity: .65;
  border-radius: 50%;
  transition: opacity var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
.chip-dismiss button:hover { opacity: 1; background: color-mix(in oklab, currentColor 15%, transparent); }

/* ─────────────────────────── Chapter 05 — Cards & surfaces ──────────────── */
/* Verbatim migration from components/05-cards-and-surfaces.html so that the
   classes referenced by @magicblocksai/ui's card components ship through
   @magicblocksai/css too. Visual reference: chapter 05 demos. */

.card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-6) var(--s-6);
  display: flex; flex-direction: column; gap: var(--s-2);
  transition: border-color var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
  max-width: 320px;
}
.card-title { font: 600 16px/1.3 var(--f-display); color: var(--fg); margin: 0; letter-spacing: -0.005em; }
.card-body  { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }

.card-sunk  { background: var(--bg-sunk); border-color: var(--hair-soft); }
.card-warm  { background: color-mix(in oklab, var(--warm-5) 50%, var(--bg-paper)); border-color: var(--warm-7); }

.feat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--s-5); width: 100%;
}
.feat-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  text-decoration: none;
  color: var(--fg);
  display: flex; flex-direction: column; gap: var(--s-3);
  transition: border-color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.feat-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: var(--sh-3);
}
.feat-card:hover .feat-link svg { transform: translateX(3px); }

.feat-icon {
  width: 40px; height: 40px; border-radius: var(--r-md);
  display: inline-flex; align-items: center; justify-content: center;
}
.feat-icon-pink  { background: var(--accent-soft);  color: var(--accent-text); }
.feat-icon-blue  { background: var(--info-soft);    color: var(--info-text); }
.feat-icon-green { background: var(--success-soft); color: var(--success-text); }

.feat-title { font: 600 16px/1.3 var(--f-display); margin: 0; letter-spacing: -0.005em; }
.feat-body  { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }
.feat-link  { margin-top: auto; display: inline-flex; align-items: center; gap: var(--s-2); font: 600 13px/1 var(--f-mono); color: var(--accent-text); text-transform: uppercase; letter-spacing: 0.06em; }
.feat-link svg { transition: transform var(--dur-2) var(--ease); }

.price-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--s-5); width: 100%; }
.price-card {
  position: relative;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  padding: var(--s-7);
  display: flex; flex-direction: column; gap: var(--s-3);
}
.price-card-hero {
  background: linear-gradient(180deg, var(--bg-paper), var(--bg-paper));
  border: 1.5px solid var(--accent);
  box-shadow: var(--sh-3);
}
.price-ribbon {
  position: absolute; top: -12px; left: var(--s-5);
  background: var(--accent); color: var(--paper);
  font: 600 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  padding: 6px 10px; border-radius: var(--r-pill);
}
.price-badge {
  font: 500 12px/1 var(--f-mono);
  color: var(--fg-dim); text-transform: uppercase;
  letter-spacing: 0.1em;
}
.price-amt {
  font: 700 44px/1 var(--f-display);
  color: var(--fg); letter-spacing: -0.03em;
}
.price-amt-talk { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: var(--accent); font-size: 32px; font-variation-settings: "SOFT" 80; }
.price-cur { font-size: 20px; vertical-align: top; color: var(--fg-dim); margin-right: 2px; font-weight: 500; }
.price-per { font-size: 14px; color: var(--fg-dim); font-weight: 500; letter-spacing: 0; }
.price-desc { font: 400 13.5px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; min-height: 2.8em; }
.price-list { list-style: none; padding: 0; margin: var(--s-3) 0 var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); font: 400 14px/1.4 var(--f-body); color: var(--fg); }
.price-list li { position: relative; padding-left: var(--s-5); }
.price-list li::before { content: ""; position: absolute; left: 0; top: .4em; width: 10px; height: 6px; border-left: 2px solid var(--accent); border-bottom: 2px solid var(--accent); transform: rotate(-45deg); }

.btn-fill, .btn-line {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2);
  font: 600 14px/1 var(--f-display); padding: 12px var(--s-5);
  border-radius: var(--r-md); cursor: pointer; border: 1px solid transparent;
  white-space: nowrap;
  text-decoration: none;
  transition: transform var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}
.btn-fill { background: var(--accent); color: var(--paper); box-shadow: var(--sh-pink); }
.btn-fill:hover { transform: translateY(-1px); }
.btn-line { background: transparent; color: var(--fg); border-color: var(--hair); }
.btn-line:hover { border-color: var(--fg); }

.testim-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  padding: var(--s-8) var(--s-7) var(--s-6);
  display: flex; flex-direction: column; gap: var(--s-5);
  position: relative;
  max-width: 440px; width: 100%;
}
.testim-glyph {
  font-family: var(--f-serif); font-style: italic;
  font-variation-settings: "SOFT" 80;
  font-size: 64px; line-height: 1;
  color: var(--accent-text);
  position: absolute; top: var(--s-4); left: var(--s-6);
}
.testim-quote {
  margin: var(--s-7) 0 0;
  font: 400 19px/1.5 var(--f-body);
  color: var(--fg); letter-spacing: -0.005em;
}
.testim-quote em {
  font-family: var(--f-serif); font-style: italic; font-weight: 400;
  color: var(--accent-text); font-variation-settings: "SOFT" 80;
}
.testim-who { display: flex; align-items: center; gap: var(--s-4); }
.testim-avatar {
  width: 40px; height: 40px; border-radius: 50%;
  flex: 0 0 40px;
}
.testim-name { font: 600 14px/1.3 var(--f-display); }
.testim-role { font: 400 12px/1.3 var(--f-mono); color: var(--fg-dim); }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s-5); width: 100%; }
.stat-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-6) var(--s-6) var(--s-5);
  display: flex; flex-direction: column; gap: var(--s-3);
}
.stat-label { font: 500 12px/1 var(--f-mono); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.08em; }
.stat-val { display: flex; align-items: baseline; gap: var(--s-3); flex-wrap: wrap; }
.stat-num { font: 700 36px/1 var(--f-display); color: var(--fg); letter-spacing: -0.025em; font-variant-numeric: tabular-nums; }
.stat-delta {
  display: inline-flex; align-items: center; gap: 3px;
  font: 600 12px/1 var(--f-mono);
  padding: 4px 8px; border-radius: var(--r-pill);
}
.stat-delta.is-pos { color: var(--success-text); background: var(--success-soft); }
.stat-delta.is-neg { color: var(--error-text);   background: var(--error-soft); }
.stat-foot { font: 400 12px/1.4 var(--f-body); color: var(--fg-soft); }

.media-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  overflow: hidden;
  display: flex; flex-direction: column;
  max-width: 320px; width: 100%;
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.media-card:hover { transform: translateY(-2px); box-shadow: var(--sh-3); }
.media-thumb { aspect-ratio: 16 / 9; width: 100%; }
.media-body { padding: var(--s-5) var(--s-6) var(--s-6); display: flex; flex-direction: column; gap: var(--s-3); }
.media-tag { font: 500 11px/1 var(--f-mono); color: var(--accent-text); text-transform: uppercase; letter-spacing: 0.08em; }
.media-title { font: 600 18px/1.3 var(--f-display); color: var(--fg); margin: 0; letter-spacing: -0.01em; }
.media-excerpt { font: 400 13.5px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }
.media-meta { display: flex; gap: var(--s-2); font-size: 12px; color: var(--fg-dim); margin-top: var(--s-2); }
.media-who { font-weight: 500; color: var(--fg-soft); }
.media-date { }

.media-card-wide { max-width: 520px; flex-direction: row; align-items: stretch; }
.media-card-wide .media-thumb { flex: 0 0 200px; aspect-ratio: auto; }
@media (max-width: 640px) { .media-card-wide { flex-direction: column; } .media-card-wide .media-thumb { flex: initial; aspect-ratio: 16 / 9; } }

.cta-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-2xl);
  padding: var(--s-9) var(--s-8);
  display: flex; flex-direction: column; gap: var(--s-4);
  max-width: 520px; width: 100%;
  position: relative; overflow: hidden;
}
.cta-card::after {
  content: ""; position: absolute; right: -80px; top: -80px;
  width: 260px; height: 260px; border-radius: 50%;
  background: radial-gradient(circle, var(--accent-soft), transparent 70%);
  pointer-events: none;
}
.cta-eyebrow { font: 500 12px/1 var(--f-mono); color: var(--accent-text); text-transform: uppercase; letter-spacing: 0.08em; position: relative; }
.cta-title { font: 700 28px/1.15 var(--f-display); color: var(--fg); letter-spacing: -0.015em; margin: 0; position: relative; max-width: 22ch; text-wrap: balance; }
.cta-title em { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: var(--accent); font-variation-settings: "SOFT" 80; }
.cta-body { font: 400 16px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; max-width: 48ch; position: relative; }
.cta-actions { display: flex; gap: var(--s-3); flex-wrap: wrap; position: relative; margin-top: var(--s-3); }

.cta-card-ink {
  background: var(--ink); color: var(--warm-3);
  border-color: transparent;
}
.cta-card-ink .cta-title { color: var(--warm-3); }
.cta-card-ink .cta-body { color: #C9CFE2; }
.cta-card-ink::after { background: radial-gradient(circle, rgba(255,63,122,0.3), transparent 70%); }

.panel {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  max-width: 420px; width: 100%;
}
.panel-head { display: flex; align-items: center; justify-content: space-between; padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--hair); background: var(--bg-sunk); }
.panel-title { font: 600 13px/1 var(--f-display); margin: 0; text-transform: uppercase; letter-spacing: 0.05em; color: var(--fg-dim); }
.panel-action { background: transparent; border: 0; font: 500 12px/1 var(--f-mono); color: var(--accent-text); cursor: pointer; text-transform: uppercase; letter-spacing: 0.06em; }
.panel-action:hover { text-decoration: underline; text-underline-offset: 3px; }

.panel-row { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-4) var(--s-5); border-top: 1px solid var(--hair-soft); }
.panel-row:first-of-type { border-top: 0; }
.panel-row-icon { width: 22px; height: 22px; border-radius: 50%; flex: 0 0 22px; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; }
.panel-row-body { flex: 1; min-width: 0; }
.panel-row-name { font: 600 14px/1.3 var(--f-body); }
.panel-row-meta { font: 400 12px/1.3 var(--f-mono); color: var(--fg-dim); }
.panel-row-stat { font-size: 12px; color: var(--fg-soft); white-space: nowrap; }

.div-hair { border: 0; border-top: 1px solid var(--hair); margin: var(--s-5) 0; }
.div-accent {
  border: 0; height: 2px; margin: var(--s-5) 0;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
}
.div-label {
  display: flex; align-items: center;
  gap: var(--s-4); margin: var(--s-5) 0;
  color: var(--fg-dim);
  font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.1em;
}
.div-label::before, .div-label::after {
  content: ""; flex: 1;
  border-top: 1px solid var(--hair);
}

.dash-tile { display: flex; flex-direction: column; background: var(--bg-paper); border: 1px solid var(--hair); border-radius: var(--r-md); overflow: hidden; }
.dash-tile-head { display: flex; justify-content: space-between; align-items: center; padding: var(--s-4); border-bottom: 1px solid var(--hair); }
.dash-tile-title { font: 600 15px/1.2 var(--f-display); color: var(--fg); margin: 0; }
.dash-tile-more { border: 0; background: transparent; color: var(--fg-soft); font-size: 18px; cursor: pointer; padding: 0 var(--s-2); border-radius: var(--r-xs); }
.dash-tile-more:hover { background: var(--bg-sunk); color: var(--fg); }
.dash-tile-body { padding: var(--s-3) var(--s-4); flex: 1; }
.dash-tile-list { list-style: none; margin: 0; padding: 0; }
.dash-tile-list li { display: flex; justify-content: space-between; align-items: center; padding: var(--s-2) 0; border-bottom: 1px solid var(--hair); font: 400 14px/1 var(--f-body); color: var(--fg); }
.dash-tile-list li:last-child { border-bottom: 0; }
.dash-tile-foot { padding: var(--s-3) var(--s-4); border-top: 1px solid var(--hair); background: var(--bg-sunk); }
.dash-tile-foot a { font: 500 13px/1 var(--f-body); color: var(--accent-text); text-decoration: none; }

.kpi-tile { padding: var(--s-4); background: var(--bg-paper); border: 1px solid var(--hair); border-radius: var(--r-md); }
.kpi-label { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); }
.kpi-row { display: flex; align-items: baseline; gap: var(--s-3); margin: var(--s-2) 0 var(--s-3); }
.kpi-value { font: 700 28px/1 var(--f-display); font-variant-numeric: tabular-nums; color: var(--fg); }
.kpi-delta { font: 600 12px/1 var(--f-mono); }
.kpi-delta.is-up { color: var(--success-text); }
.kpi-delta.is-down { color: var(--error-text); }
.kpi-spark { width: 100%; height: 36px; color: var(--accent-text); }

/* ─────────────────────────── Chapter 06 — Navigation ────────────────────── */
/* Verbatim migration of the in-product nav primitives from
   components/06-navigation.html. The chapter-private demo CSS for the
   marketing site-nav (`.site-nav__*`, `.mega-*`, `.industry-bar`, `.cmdk`)
   stays in the chapter file because no @magicblocksai/ui component wraps
   them yet — adding them here would bloat the package without benefit. */

.tn {
  display: flex; align-items: center; gap: var(--s-5);
  padding: var(--s-4) var(--s-6);
  background: color-mix(in oklab, var(--bg-paper) 90%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  width: 100%; max-width: 960px;
  flex-wrap: wrap;
}
.tn-brand { display: inline-flex; align-items: center; gap: var(--s-2); font: 700 15px/1 var(--f-display); color: var(--fg); text-decoration: none; letter-spacing: -0.01em; }
.tn-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.tn-links { display: inline-flex; gap: var(--s-5); }
.tn-links a {
  color: var(--fg-soft); text-decoration: none;
  font: 500 13.5px/1 var(--f-body);
  padding: 6px 0; position: relative;
  transition: color var(--dur-2) var(--ease);
}
.tn-links a:hover { color: var(--fg); }
.tn-links a.is-active { color: var(--fg); }
.tn-links a.is-active::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px;
  height: 2px; background: var(--accent); border-radius: 2px;
}
.tn-spacer { flex: 1; }
.tn-link { color: var(--fg-soft); text-decoration: none; font: 500 13.5px/1 var(--f-body); padding: 6px 10px; }
.tn-link:hover { color: var(--fg); }
.tn-cta {
  background: var(--accent); color: var(--paper);
  font: 600 13.5px/1 var(--f-display);
  padding: 9px var(--s-4);
  border-radius: var(--r-pill);
  text-decoration: none;
  box-shadow: var(--sh-pink);
  transition: transform var(--dur-2) var(--ease);
}
.tn-cta:hover { transform: translateY(-1px); color: var(--paper); }

.sn {
  width: 240px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  display: flex; flex-direction: column; gap: 2px;
  font-family: var(--f-body);
}
.sn-brand { display: inline-flex; align-items: center; gap: var(--s-2); font: 700 14px/1 var(--f-display); padding: var(--s-2) var(--s-3) var(--s-4); }
.sn-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.sn-section { font: 500 10.5px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-faint); padding: var(--s-4) var(--s-3) var(--s-2); }
.sn-item {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 8px var(--s-3);
  border-radius: var(--r-sm);
  font: 500 13.5px/1 var(--f-body);
  color: var(--fg-soft);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
.sn-item:hover { background: var(--bg-sunk); color: var(--fg); }
.sn-item.is-active { background: var(--accent-soft); color: var(--accent-text); }
.sn-item.is-active svg { color: var(--accent-text); }
.sn-item > span:first-of-type { flex: 1; }
.sn-count { font-family: var(--f-mono); font-size: 11px; color: var(--fg-faint); font-weight: 500; }
.sn-item.is-active .sn-count { color: var(--accent-text); }

.tabs-wrap { width: 100%; }
.tabs {
  display: inline-flex; gap: 0;
  border-bottom: 1px solid var(--hair);
  width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  appearance: none; background: transparent; border: 0;
  padding: 12px var(--s-4) 14px;
  font: 500 13.5px/1 var(--f-body); color: var(--fg-dim);
  cursor: pointer;
  position: relative; white-space: nowrap;
  transition: color var(--dur-2) var(--ease);
  display: inline-flex; align-items: center; gap: var(--s-2);
}
.tab:hover { color: var(--fg); }
.tab.is-active { color: var(--fg); }
.tab.is-active::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px;
  height: 2px; background: var(--accent); border-radius: 2px;
}
.tab-count {
  font-family: var(--f-mono); font-size: 11px; color: var(--fg-faint);
  padding: 2px 6px; background: var(--bg-sunk); border-radius: var(--r-xs);
}
.tab.is-active .tab-count { color: var(--accent-text); background: var(--accent-soft); }
.tabs-body { padding: var(--s-5) 0 0; }
.tabs-body-title { font: 600 15px/1.3 var(--f-display); margin: 0 0 var(--s-2); }
.tabs-body-text { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }

.bc {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font: 500 12.5px/1 var(--f-mono);
  color: var(--fg-dim);
}
.bc-item { color: var(--fg-soft); text-decoration: none; }
.bc-item:hover { color: var(--accent-text); }
.bc-sep { color: var(--fg-faint); display: inline-flex; }
.bc-current { color: var(--fg); font-weight: 500; }

.pag { display: inline-flex; gap: 4px; align-items: center; }
.pag-btn {
  min-width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--fg-soft);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  font: 500 13px/1 var(--f-mono);
  cursor: pointer;
  padding: 0 8px;
  gap: 4px;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.pag-btn:hover { background: var(--bg-sunk); color: var(--fg); }
.pag-btn.is-active { background: var(--accent); color: var(--paper); }
.pag-arr { border-color: var(--hair); }
.pag-ellipsis { color: var(--fg-faint); padding: 0 4px; font-family: var(--f-mono); }
.pag-compact { display: inline-flex; align-items: center; gap: var(--s-2); font-size: 12.5px; color: var(--fg-soft); flex-wrap: wrap; }
.pag-compact strong { color: var(--fg); font-weight: 600; }
.pag-compact-divider { width: 1px; height: 16px; background: var(--hair); margin: 0 var(--s-2); }

.menu-trigger {
  display: inline-flex; align-items: center; gap: var(--s-2);
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-md); padding: 8px var(--s-4);
  font: 500 13px/1 var(--f-body); color: var(--fg); cursor: pointer;
}
.menu-trigger:hover { border-color: var(--fg); }
.menu {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-2);
  display: flex; flex-direction: column; gap: 2px;
  box-shadow: var(--sh-3);
  min-width: 260px;
}
.menu-head { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-3); }
.menu-head-avatar { width: 32px; height: 32px; border-radius: var(--r-sm); background: linear-gradient(135deg, var(--pink-300), var(--pink-700)); color: var(--paper); display: inline-flex; align-items: center; justify-content: center; font: 600 13px/1 var(--f-display); flex: 0 0 32px; }
.menu-head-name { font: 600 14px/1.3 var(--f-display); }
.menu-head-sub { font: 400 12px/1.3 var(--f-mono); color: var(--fg-dim); }
.menu-divider { height: 1px; background: var(--hair); margin: 4px 0; }
.menu-item {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 8px var(--s-3);
  background: transparent; border: 0;
  border-radius: var(--r-sm);
  font: 500 13.5px/1 var(--f-body);
  color: var(--fg); cursor: pointer;
  text-align: left;
}
.menu-item:hover { background: var(--bg-sunk); }
.menu-item.is-danger { color: var(--error-text); }
.menu-item.is-danger:hover { background: var(--error-soft); }
.menu-item.is-active { background: var(--bg-sunk); outline: none; }
.menu-item.is-active.is-danger { background: var(--error-soft); }
.menu-item.is-disabled { color: var(--fg-faint); cursor: not-allowed; opacity: 0.55; }
.menu-item.is-disabled:hover { background: transparent; }
.menu-item svg { color: var(--fg-dim); }
.menu-item-icon { display: inline-flex; align-items: center; flex: 0 0 auto; color: var(--fg-dim); }
.menu-item-label { flex: 1; min-width: 0; }
.menu-group { display: flex; flex-direction: column; gap: 2px; }
.menu-group + .menu-group { margin-top: 4px; }
.menu-group-label { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); padding: var(--s-2) var(--s-3); }
.menu-trigger-wrap { display: inline-block; }

/* All .step* rules below are scoped to .stepper .step so they don't leak
   into other components that happen to use a `.step` class — notably the
   Triptych panels (chapter 11.5) and any other narrative card with a
   "01 · Connect" style step eyebrow. The unscoped versions previously
   rendered a stray vertical hairline below the eyebrow on Triptych
   panels because `.step:not(:last-child)::before` matched any `.step`
   that had siblings after it. */
.stepper { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.stepper .step {
  display: grid; grid-template-columns: 32px 1fr;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  position: relative;
}
.stepper .step:not(:last-child)::before {
  content: ""; position: absolute;
  top: 38px; bottom: -6px; left: 15px; width: 2px;
  background: var(--hair);
}
.stepper .step.is-done::before { background: var(--accent); }
.stepper .step-dot {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--bg-paper); border: 2px solid var(--hair);
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 13px/1 var(--f-mono); color: var(--fg-dim);
  position: relative; z-index: 1;
}
.stepper .step.is-done .step-dot { background: var(--accent); border-color: var(--accent); color: var(--paper); }
.stepper .step.is-active .step-dot { border-color: var(--accent); color: var(--accent-text); box-shadow: 0 0 0 4px var(--accent-soft); }
.stepper .step-name { font: 600 14.5px/1.3 var(--f-display); color: var(--fg); }
.stepper .step.is-done .step-name { color: var(--fg-soft); }
.stepper .step-meta { font: 400 12.5px/1.4 var(--f-mono); color: var(--fg-dim); }

.skip-link {
  position: absolute; top: -100px; left: var(--s-4);
  padding: 10px 16px;
  background: var(--accent); color: var(--paper);
  border-radius: var(--r-sm);
  font: 600 14px/1 var(--f-body); text-decoration: none;
  z-index: 10;
  transition: top var(--dur-2) var(--ease);
}
.skip-link:focus-visible { top: var(--s-4); }

/* ─────────────────────────── Chapter 07 — Data display ──────────────────── */
/* Verbatim migration from components/07-data-display.html. Chip, badge,
   avatar, and empty-state primitives are already in this file (Phase 1A);
   they are not duplicated here. Some rules (.tbl-*, .list-rows, .codeblk,
   .chart-bar, .tree, .stat-tile) don't have React wrappers yet but ship
   so static-site consumers can use the markup unchanged. */

.tbl-wrap {
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: var(--sh-1);
}
.tbl { width: 100%; border-collapse: collapse; font: 14px/1.4 var(--f-body); }
.tbl thead th {
  text-align: left; padding: 12px var(--s-4);
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--fg-dim); background: var(--bg-sunken);
  border-bottom: 1px solid var(--hair);
  white-space: nowrap;
}
.tbl thead th.tbl-sort { cursor: pointer; user-select: none; }
.tbl thead th.tbl-sort:hover { color: var(--fg-soft); }
.tbl thead th.tbl-sort.is-active { color: var(--fg); }
.tbl-sort-ic { display: inline-flex; vertical-align: -2px; margin-left: 4px; color: var(--fg-faint); }
.tbl-sort.is-active .tbl-sort-ic { color: var(--accent-text); }
.tbl tbody tr { border-bottom: 1px solid var(--hair-soft); transition: background var(--dur-1) var(--ease); }
.tbl tbody tr:last-child { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--bg-warm); }
.tbl td { padding: 14px var(--s-4); color: var(--fg); vertical-align: middle; }
.tbl-right { text-align: right; }
.tbl-num { font-variant-numeric: tabular-nums; font-weight: 600; }
.tbl-mono { font-size: 12.5px; color: var(--fg-soft); }
.tbl-person { display: flex; align-items: center; gap: var(--s-3); }
.tbl-name { font-weight: 600; color: var(--fg); }
.tbl-sub { font-size: 12px; color: var(--fg-dim); margin-top: 1px; }
.tbl-icon {
  background: transparent; border: 1px solid transparent; color: var(--fg-dim);
  width: 28px; height: 28px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}
.tbl-icon:hover { background: var(--bg-sunken); color: var(--fg); border-color: var(--hair); }
.tbl-striped tbody tr:nth-child(odd) { background: color-mix(in oklab, var(--warm-3) 40%, transparent); }
.tbl-striped tbody tr:hover { background: var(--bg-warm); }
.tbl-compact thead th { padding: 8px var(--s-3); }
.tbl-compact td { padding: 8px var(--s-3); font-size: 13px; }
@media (max-width: 720px) {
  .tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tbl { min-width: 560px; }
  .tbl-wrap::-webkit-scrollbar { height: 4px; }
  .tbl-wrap::-webkit-scrollbar-thumb { background: var(--hair); border-radius: 2px; }
}

.list-rows {
  list-style: none; padding: 0; margin: 0;
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: var(--sh-1);
}
.list-rows li {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 14px var(--s-4);
  border-bottom: 1px solid var(--hair-soft);
  transition: background var(--dur-1) var(--ease);
}
.list-rows li:last-child { border-bottom: 0; }
.list-rows li:hover { background: var(--bg-warm); }
.lr-main { flex: 1; min-width: 0; }
.lr-name { font-weight: 600; color: var(--fg); font-size: 14px; }
.lr-sub { font-size: 12.5px; color: var(--fg-dim); margin-top: 2px; }

.kv {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--hair-soft); border: 1px solid var(--hair);
  border-radius: var(--r-lg); overflow: hidden;
  margin: 0;
}
.kv > div {
  display: grid; grid-template-columns: 140px 1fr; gap: var(--s-3);
  padding: 12px var(--s-4);
  background: var(--bg-paper);
  align-items: baseline;
}
.kv dt {
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--fg-dim);
}
.kv dd { margin: 0; color: var(--fg); font-size: 14px; }
@media (max-width: 640px) { .kv { grid-template-columns: 1fr; } }

.prog-demo { display: flex; flex-direction: column; gap: var(--s-4); width: 100%; max-width: 480px; }
.prog-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; }
.prog-label { font: 500 13px/1 var(--f-body); color: var(--fg-soft); }
.prog-val { font-size: 13px; color: var(--fg); font-variant-numeric: tabular-nums; }
.prog-track {
  height: 6px; background: var(--bg-sunken);
  border-radius: var(--r-pill); overflow: hidden;
  position: relative;
}
.prog-fill {
  height: 100%; background: var(--accent);
  border-radius: inherit;
  transition: width var(--dur-4) var(--ease);
}
.prog-green { background: var(--success); }
.prog-amber { background: var(--warning); }

.rings { display: flex; gap: var(--s-6); flex-wrap: wrap; }
.ring-item { display: flex; align-items: center; gap: var(--s-3); }
.ring-bg { stroke: var(--bg-sunken); }
.ring-fg { stroke: var(--accent); stroke-linecap: round; transition: stroke-dashoffset var(--dur-4) var(--ease); }
.ring-green { stroke: var(--success); }
.ring-amber { stroke: var(--warning); }
.ring-val { font: 600 22px/1 var(--f-display); color: var(--fg); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.ring-unit { font-size: 13px; color: var(--fg-dim); margin-left: 2px; }
.ring-label { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); margin-top: 4px; }

.timeline {
  list-style: none; padding: 0; margin: 0;
  position: relative;
}
.tl-item {
  display: grid; grid-template-columns: 28px 1fr; gap: var(--s-3);
  position: relative;
  padding-bottom: var(--s-5);
}
.tl-item:last-child { padding-bottom: 0; }
.tl-marker {
  position: relative;
  display: flex; justify-content: center;
  padding-top: 4px;
}
.tl-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--fg-faint);
  box-shadow: 0 0 0 3px var(--bg-paper), 0 0 0 4px var(--hair);
  position: relative; z-index: 1;
}
.tl-item::before {
  content: ""; position: absolute;
  left: 13px; top: 18px; bottom: 0;
  width: 1px; background: var(--hair);
}
.tl-item:last-child::before { display: none; }
.tl-done .tl-dot { background: var(--fg); box-shadow: 0 0 0 3px var(--bg-paper), 0 0 0 4px var(--fg); }
.tl-now .tl-dot {
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--bg-paper), 0 0 0 4px var(--accent), 0 0 0 9px var(--accent-soft);
}
.tl-next .tl-dot { background: var(--bg-paper); box-shadow: 0 0 0 3px var(--bg-paper), inset 0 0 0 2px var(--hair); }
.tl-body { padding-top: 0; }
.tl-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); }
.tl-head strong { font: 600 14px/1.3 var(--f-display); color: var(--fg); letter-spacing: -0.005em; }
.tl-time { font-size: 12px; color: var(--fg-dim); flex-shrink: 0; }
.tl-desc { font-size: 13.5px; color: var(--fg-soft); margin: 4px 0 0; }

.codeblk {
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-lg); overflow: hidden;
  margin: 0; box-shadow: var(--sh-2);
}
.codeblk figcaption {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 10px var(--s-4);
  border-bottom: 1px solid color-mix(in oklab, var(--paper) 10%, transparent);
  background: color-mix(in oklab, var(--paper) 4%, var(--ink));
}
.codeblk-lang {
  padding: 2px 7px; font-size: 10.5px;
  background: var(--accent); color: var(--paper);
  border-radius: var(--r-xs); text-transform: uppercase; letter-spacing: 0.08em;
  font-weight: 600;
}
.codeblk-file { font-size: 12px; color: color-mix(in oklab, var(--paper) 60%, transparent); flex: 1; }
.codeblk-copy {
  background: transparent; border: 1px solid color-mix(in oklab, var(--paper) 20%, transparent);
  color: color-mix(in oklab, var(--paper) 70%, transparent);
  font-size: 11px; padding: 3px 10px; border-radius: var(--r-xs); cursor: pointer;
  transition: color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.codeblk-copy:hover { color: var(--paper); border-color: color-mix(in oklab, var(--paper) 40%, transparent); }
.codeblk pre {
  margin: 0; padding: var(--s-4) var(--s-5);
  font: 13px/1.7 var(--f-mono); color: color-mix(in oklab, var(--paper) 92%, transparent);
  overflow-x: auto;
}
.c-k { color: #FF8BB0; }
.c-v { color: #FFE090; }
.c-f { color: #8CD8FF; }
.c-s { color: #B8F0A6; }

.stat-tile { padding: var(--s-4); background: var(--bg-paper); border: 1px solid var(--hair); border-radius: var(--r-md); position: relative; overflow: hidden; }
.stat-tile .stat-label { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); }
.stat-tile .stat-value { font: 700 24px/1 var(--f-display); font-variant-numeric: tabular-nums; color: var(--fg); margin: var(--s-2) 0; }
.stat-tile .stat-delta { font: 600 12px/1 var(--f-mono); }
.stat-tile .stat-delta.is-up { color: var(--success-text); }
.stat-tile .stat-delta.is-down { color: var(--error-text); }
.stat-tile--moment {
  background: var(--ink); color: var(--paper);
  border-color: rgba(244, 236, 228, 0.12);
}
.stat-tile--moment .stat-label { color: rgba(244, 236, 228, 0.65); }
.stat-tile--moment .stat-value { color: var(--accent); font-size: 36px; font-weight: 700; }
.stat-tile--moment .stat-delta.is-up { color: var(--success-text); }
.stat-tile--moment .stat-delta.is-down { color: var(--error-text); }
.stat-tile--big .stat-value { font-size: 36px; font-weight: 700; }
.stat-tile .stat-spark {
  position: absolute; right: 0; bottom: 0; left: 40%;
  height: 50%; pointer-events: none; opacity: 0.18;
}
.stat-tile--moment .stat-spark { opacity: 0.28; }

.chart-bar {
  padding: var(--s-4) var(--s-4) var(--s-3);
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-md);
  width: 100%; max-width: min(640px, 100%);
  margin: 0;
}
.chart-bar > svg { display: block; margin-bottom: var(--s-3); }
.chart-cap {
  font: 400 12px/1.3 var(--f-mono); color: var(--fg-dim);
  margin: var(--s-3) 0 0; padding-top: var(--s-2);
  border-top: 1px dashed var(--hair-soft);
  text-align: center;
}

.tree, .tree ul { list-style: none; margin: 0; padding: 0; }
.tree ul { padding-left: var(--s-5); border-left: 1px dashed var(--hair); margin-left: var(--s-2); }
.tree summary, .tree li { font: 400 14px/1.8 var(--f-body); color: var(--fg); cursor: pointer; padding: 2px 0; list-style: none; }
.tree summary::-webkit-details-marker { display: none; }
.tree-icon { display: inline-block; width: 14px; color: var(--fg-dim); transition: transform var(--dur-2) var(--ease); }
.tree details[open] > summary .tree-icon { transform: rotate(90deg); }

.score-ring {
  --sr-size: 40px;
  --sr-stroke: 4px;
  --sr-track: var(--hair);
  --sr-fill: var(--accent);
  display: inline-flex; align-items: center; justify-content: center;
  position: relative;
  width: var(--sr-size); height: var(--sr-size);
  flex-shrink: 0;
}
.score-ring--xs { --sr-size: 16px; --sr-stroke: 2px; }
.score-ring--sm { --sr-size: 24px; --sr-stroke: 3px; }
.score-ring--lg { --sr-size: 64px; --sr-stroke: 5px; }
.score-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); display: block; }
.score-ring circle.track { stroke: var(--sr-track); fill: none; stroke-width: var(--sr-stroke); }
.score-ring circle.fill {
  stroke: var(--sr-fill); fill: none; stroke-width: var(--sr-stroke); stroke-linecap: round;
  transition: stroke-dashoffset var(--dur-3) var(--ease), stroke var(--dur-2) var(--ease);
}
.score-ring .v {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font: 600 12px/1 var(--f-display); font-variant-numeric: tabular-nums;
  color: var(--fg);
}
.score-ring--lg .v { font-size: 18px; font-weight: 700; }
.score-ring--sm .v { font-size: 9px; }
.score-ring--xs .v { display: none; }
.score-ring[data-band="low"]    { --sr-fill: var(--score-low); }
.score-ring[data-band="medium"] { --sr-fill: var(--score-medium); }
.score-ring[data-band="high"]   { --sr-fill: var(--score-high); }
.score-ring--accent { --sr-fill: var(--accent); }
.score-ring--ink    { --sr-fill: var(--ink); }
.score-ring--info   { --sr-fill: var(--info); }
.score-ring-label {
  display: block;
  font: 500 10px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--fg-dim);
  margin-top: var(--s-2);
  text-align: center;
}

.sla-ring {
  --sla-size: 40px;
  --sla-stroke: 4px;
  --sla-fill: var(--success);
  display: inline-flex; align-items: center; justify-content: center;
  position: relative;
  width: var(--sla-size); height: var(--sla-size);
  flex-shrink: 0;
}
.sla-ring--sm { --sla-size: 24px; --sla-stroke: 3px; }
.sla-ring--lg { --sla-size: 96px; --sla-stroke: 7px; }
.sla-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); display: block; }
.sla-ring circle.track { stroke: var(--hair); fill: none; stroke-width: var(--sla-stroke); }
.sla-ring circle.fill {
  stroke: var(--sla-fill); fill: none; stroke-width: var(--sla-stroke); stroke-linecap: round;
  transition: stroke-dashoffset var(--dur-3) var(--ease), stroke var(--dur-2) var(--ease);
}
.sla-ring .t {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font: 600 11px/1 var(--f-mono); font-variant-numeric: tabular-nums;
  color: var(--fg);
  text-align: center;
}
.sla-ring--lg .t { font-size: 16px; font-weight: 700; }
.sla-ring--sm .t { display: none; }
.sla-ring[data-state="ok"]      { --sla-fill: var(--success); }
.sla-ring[data-state="warn"]    { --sla-fill: var(--warning); }
.sla-ring[data-state="danger"]  { --sla-fill: var(--error); }
.sla-ring[data-state="breach"]  { --sla-fill: var(--error); animation: sla-shake 0.4s var(--ease) 0s 1; }
.sla-ring[data-state="breach"] .t { color: var(--error-text); font-weight: 700; letter-spacing: -0.04em; }
.sla-ring--lg[data-state="breach"] .t { font-size: 12px; }
@keyframes sla-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-2px); }
  50% { transform: translateX(2px); }
  75% { transform: translateX(-1px); }
}
@media (prefers-reduced-motion: reduce) {
  .sla-ring[data-state="breach"] { animation: none; }
}

.spark {
  display: inline-block;
  vertical-align: middle;
  --spark-color: var(--success);
}
.spark.spark--inline { width: 64px;  height: 12px; }
.spark.spark--card   { width: 160px; height: 40px; }
.spark.spark--page   { width: 100%;  height: 120px; }
.spark svg { display: block; width: 100%; height: 100%; overflow: visible; }
.spark .line  { fill: none; stroke: var(--spark-color); stroke-width: var(--spark-stroke); stroke-linecap: round; stroke-linejoin: round; }
.spark .area  { fill: var(--spark-color); opacity: 0.10; }
.spark .end-dot { fill: var(--spark-color); }
.spark[data-risk="none"]     { --spark-color: var(--score-low); }
.spark[data-risk="low"]      { --spark-color: var(--score-low); }
.spark[data-risk="medium"]   { --spark-color: var(--score-medium); }
.spark[data-risk="high"]     { --spark-color: var(--score-high); }
.spark[data-risk="critical"] { --spark-color: var(--score-high); }

.risk-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: var(--r-pill);
  font: 600 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em;
  background: var(--bg-sunk); color: var(--fg-dim);
  border: 1px solid var(--hair);
  vertical-align: middle;
}
.risk-badge::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px color-mix(in oklab, currentColor 20%, transparent);
  flex-shrink: 0;
}
.risk-badge[data-risk="none"]     { background: var(--badge-bg-success); color: var(--success-text); border-color: color-mix(in oklab, var(--success) 25%, transparent); }
.risk-badge[data-risk="low"]      { background: var(--badge-bg-success); color: var(--success-text); border-color: color-mix(in oklab, var(--success) 25%, transparent); }
.risk-badge[data-risk="medium"]   { background: var(--badge-bg-warning); color: var(--warning-text); border-color: color-mix(in oklab, var(--warning) 25%, transparent); }
.risk-badge[data-risk="high"]     { background: var(--badge-bg-danger);  color: var(--error-text);   border-color: color-mix(in oklab, var(--error)   25%, transparent); }
.risk-badge[data-risk="critical"] { background: var(--badge-bg-danger);  color: var(--error-text);   border-color: color-mix(in oklab, var(--error)   40%, transparent); }

.av-stack-pop {
  position: absolute; left: 0; top: calc(100% + 8px);
  display: none;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  box-shadow: var(--sh-2);
  padding: var(--s-3) 0;
  min-width: 180px;
  z-index: var(--z-overlay);
}
.av-stack:hover .av-stack-pop,
.av-stack:focus-within .av-stack-pop { display: block; }
.av-stack-pop li {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) var(--s-4);
  font: 500 13px/1.3 var(--f-body); color: var(--fg);
  list-style: none;
}
.av-stack-pop li .av { width: 22px; height: 22px; font-size: 10px; flex-shrink: 0; }
.av-stack-pop ul { margin: 0; padding: 0; }

/* ─────────────────────────── Chapter 08 — Feedback & overlays ───────────── */
/* Verbatim migration from components/08-feedback-and-overlays.html. */

.toast {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: 12px var(--s-4);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  box-shadow: var(--sh-3);
  position: relative;
}
.toast::before {
  content: ""; position: absolute;
  left: 0; top: 10px; bottom: 10px; width: 3px;
  border-radius: 3px;
  background: var(--success);
}
.toast.toast-info::before  { background: var(--info); }
.toast.toast-warn::before  { background: var(--warning); }
.toast.toast-error::before { background: var(--accent); }
.toast-ic {
  width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; margin-top: 1px;
}
.toast-ic-success { background: var(--success-soft); color: var(--success-text); }
.toast-ic-info    { background: var(--info-soft);    color: var(--info-text); }
.toast-ic-warn    { background: var(--warning-soft); color: var(--warning-text); }
.toast-ic-error   { background: var(--accent-soft);  color: var(--accent-text); }
.toast-body { flex: 1; min-width: 0; }
.toast-title { font: 600 14px/1.3 var(--f-display); color: var(--fg); letter-spacing: -0.005em; }
.toast-desc { font: 400 13px/1.5 var(--f-body); color: var(--fg-soft); margin-top: 2px; }
.toast-desc a { color: var(--accent-text); text-decoration: none; font-weight: 500; }
.toast-desc a:hover { text-decoration: underline; }
.toast-msg { font: 400 13px/1.5 var(--f-body); color: var(--fg-soft); margin-top: 2px; }
.toast-close {
  background: transparent; border: 0; padding: 4px; margin: -4px;
  color: var(--fg-dim); cursor: pointer;
  border-radius: var(--r-xs);
  align-self: flex-start;
}
.toast-close:hover { color: var(--fg); background: var(--bg-sunken); }
.toast-action { display: inline-flex; align-items: center; margin-left: var(--s-2); }
.toast-action a, .toast-action button {
  font: 500 13px/1.3 var(--f-body); color: var(--accent-text);
  text-decoration: none; cursor: pointer; background: transparent; border: 0; padding: 0;
}
.toast-action a:hover, .toast-action button:hover { text-decoration: underline; }

/* Toaster — fixed-position portal wrapper that stacks live <Toast> records.
   The toaster itself doesn't paint anything; it just positions its children.
   Position-modifier classes (`.toaster-top-right`, etc.) anchor the stack
   to one of the six corners. Pointer-events are off on the wrapper so the
   stack never blocks clicks behind it; individual toasts re-enable them. */
.toaster {
  position: fixed;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-4);
  pointer-events: none;
  max-width: min(420px, calc(100% - var(--s-6)));
}
.toaster .toast { pointer-events: auto; min-width: 280px; }
.toaster-top-right     { top: 0; right: 0; align-items: flex-end; }
.toaster-top-left      { top: 0; left: 0;  align-items: flex-start; }
.toaster-bottom-right  { bottom: 0; right: 0; align-items: flex-end; flex-direction: column-reverse; }
.toaster-bottom-left   { bottom: 0; left: 0;  align-items: flex-start; flex-direction: column-reverse; }
.toaster-top-center    { top: 0; left: 50%; transform: translateX(-50%); align-items: center; }
.toaster-bottom-center { bottom: 0; left: 50%; transform: translateX(-50%); align-items: center; flex-direction: column-reverse; }

@media (prefers-reduced-motion: no-preference) {
  .toaster .toast {
    animation: toaster-in 180ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
  }
  @keyframes toaster-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
  }
}

.alert {
  display: flex; gap: var(--s-3);
  padding: var(--s-4);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--success);
  border-radius: var(--r-md);
}
.alert.alert-info  { border-left-color: var(--info); }
.alert.alert-warn  { border-left-color: var(--warning); }
.alert.alert-warning  { border-left-color: var(--warning); }
.alert.alert-error { border-left-color: var(--accent); }
.alert.alert-danger { border-left-color: var(--accent); }
.alert-icon, .alert-ic {
  width: 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.alert-success .alert-icon, .alert-success .alert-ic { background: var(--success-soft); color: var(--success-text); }
.alert-info    .alert-icon, .alert-info .alert-ic    { background: var(--info-soft);    color: var(--info-text); }
.alert-warn    .alert-icon, .alert-warning .alert-icon, .alert-warn .alert-ic, .alert-warning .alert-ic { background: var(--warning-soft); color: var(--warning-text); }
.alert-error   .alert-icon, .alert-danger .alert-icon, .alert-error .alert-ic, .alert-danger .alert-ic   { background: var(--error-soft); color: var(--error-text); }
.alert-body { flex: 1; }
.alert-title { font: 600 15px/1.3 var(--f-display); color: var(--fg); letter-spacing: -0.005em; }
.alert-msg { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 4px 0 0; }
.alert-body p { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 4px 0 0; }
.alert-actions { margin-top: var(--s-3); display: flex; gap: var(--s-4); align-items: center; }
.alert-actions a { font: 500 13px/1 var(--f-body); color: var(--accent-text); text-decoration: none; }
.alert-actions a:hover { text-decoration: underline; }

.banner {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 10px var(--s-4);
  background: var(--bg-sunken);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  font: 400 13.5px/1.5 var(--f-body); color: var(--fg);
}
.banner strong { font-weight: 600; }
.banner a { color: var(--accent-text); text-decoration: none; font-weight: 500; white-space: nowrap; }
.banner a:hover { text-decoration: underline; }
.banner-info   { background: var(--info-soft); border-color: color-mix(in oklab, var(--info) 30%, transparent); color: var(--info-text); }
.banner-info a { color: var(--info-text); }
.banner-warn   { background: #FFF0D6; border-color: color-mix(in oklab, #8A5A00 20%, transparent); color: #6B4300; }
.banner-warning { background: #FFF0D6; border-color: color-mix(in oklab, #8A5A00 20%, transparent); color: #6B4300; }
.banner-warn a, .banner-warning a { color: #8A5A00; }
.banner-success { background: var(--success-soft); border-color: color-mix(in oklab, var(--success) 30%, transparent); color: var(--success-text); }
.banner-success a { color: var(--success-text); }
.banner-danger { background: var(--error-soft); border-color: color-mix(in oklab, var(--error) 30%, transparent); color: var(--error-text); }
.banner-danger a { color: var(--error-text); }
.banner-accent {
  background: var(--accent); color: var(--paper);
  border-color: transparent;
  box-shadow: var(--sh-pink);
}
.banner-accent a { color: var(--paper); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
.banner-accent .banner-close { color: var(--paper); opacity: 0.7; }
.banner-accent .banner-close:hover { opacity: 1; }
.banner-icon, .banner-ic {
  width: 24px; height: 24px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  background: color-mix(in oklab, currentColor 12%, transparent);
  color: inherit;
}
.banner-body { flex: 1; }
.banner-msg { font: 400 13.5px/1.5 var(--f-body); color: inherit; }
.banner-title { font: 600 14px/1.3 var(--f-display); color: inherit; }
.banner-action { color: var(--accent-text); text-decoration: none; font-weight: 500; white-space: nowrap; }
.banner-close {
  background: transparent; border: 0; padding: 4px; margin: -4px;
  color: inherit; cursor: pointer; opacity: 0.55;
  border-radius: var(--r-xs);
}
.banner-close:hover { opacity: 1; }

.tooltip {
  background: var(--ink); color: var(--paper);
  padding: 7px 10px;
  font: 500 12.5px/1.4 var(--f-body);
  border-radius: var(--r-sm);
  box-shadow: var(--sh-2);
  white-space: nowrap;
  position: absolute;
  z-index: 50;
}
.tooltip-trigger {
  background: var(--bg-paper); border: 1px solid var(--hair);
  padding: 8px 14px; border-radius: var(--r-md);
  font: 500 13.5px/1 var(--f-body); color: var(--fg); cursor: help;
}
.tooltip[data-side="top"]::after {
  content: ""; position: absolute; left: 50%; top: 100%;
  transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: var(--ink);
}
.tooltip[data-side="bottom"]::after {
  content: ""; position: absolute; left: 50%; bottom: 100%;
  transform: translateX(-50%);
  border: 5px solid transparent; border-bottom-color: var(--ink);
}

.popover {
  position: relative;
  width: 320px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: var(--s-4);
  box-shadow: var(--sh-3);
}
.popover-trigger {
  background: var(--bg-paper); border: 1px solid var(--hair);
  padding: 8px 14px; border-radius: var(--r-md);
  font: 500 13.5px/1 var(--f-body); color: var(--fg); cursor: pointer;
}

.modal-backdrop {
  position: fixed; inset: 0;
  background: color-mix(in oklab, var(--ink) 40%, transparent);
  backdrop-filter: blur(4px);
  z-index: 1000;
}
.modal {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 1001;
  width: 100%; max-width: 460px;
  background: var(--bg-paper);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-4);
  overflow: hidden;
}
.modal-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: var(--s-4) var(--s-5) var(--s-3);
  gap: var(--s-3);
}
.modal-title {
  font: 600 20px/1.2 var(--f-display); letter-spacing: -0.015em;
  color: var(--fg); margin: 0;
}
.modal-close {
  background: transparent; border: 0; color: var(--fg-dim); cursor: pointer;
  padding: 6px; margin: -6px;
  border-radius: var(--r-xs);
}
.modal-close:hover { color: var(--fg); background: var(--bg-sunken); }
.modal-body { padding: 0 var(--s-5) var(--s-4); }
.modal-body p { font: 400 14.5px/1.6 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-4); }
.modal-foot {
  display: flex; justify-content: flex-end; gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  background: var(--bg-sunken);
  border-top: 1px solid var(--hair);
}

.drawer-backdrop {
  position: fixed; inset: 0;
  background: color-mix(in oklab, var(--ink) 32%, transparent);
  z-index: 1000;
}
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  z-index: 1001;
  width: min(440px, 92%);
  background: var(--bg-paper);
  border-left: 1px solid var(--hair);
  box-shadow: -20px 0 60px -20px color-mix(in oklab, var(--ink) 30%, transparent);
  display: flex; flex-direction: column;
  animation: dr-in var(--dur-3) var(--ease);
}
.drawer-left { right: auto; left: 0; border-left: 0; border-right: 1px solid var(--hair); }
@keyframes dr-in { from { transform: translateX(100%); } to { transform: translateX(0); } }
.drawer-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: var(--s-5) var(--s-5) var(--s-4);
  border-bottom: 1px solid var(--hair);
}
.drawer-title { font: 600 22px/1.2 var(--f-display); letter-spacing: -0.015em; color: var(--fg); margin: 4px 0 0; }
.drawer-close { background: transparent; border: 0; color: var(--fg-dim); cursor: pointer; padding: 6px; margin: -6px; border-radius: var(--r-xs); }
.drawer-close:hover { color: var(--fg); background: var(--bg-sunken); }
.drawer-body { flex: 1; overflow: auto; padding: var(--s-4) var(--s-5); }
.drawer-foot {
  display: flex; justify-content: flex-end; gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  background: var(--bg-sunken);
  border-top: 1px solid var(--hair);
}

.bulk-bar {
  display: flex; align-items: center; gap: var(--s-4);
  padding: 10px 16px;
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-pill);
  box-shadow: var(--sh-3);
  font: 500 13px/1 var(--f-body);
  max-width: 720px;
}
.bulk-bar-count, .bulk-bar .bb-count {
  font: 600 13px/1 var(--f-body);
  padding: 6px 12px;
  background: rgba(255,255,255,0.08);
  border-radius: var(--r-pill);
  flex-shrink: 0;
}
.bulk-bar-actions { display: inline-flex; gap: 4px; flex: 1; }
.bulk-bar-close, .bulk-bar .bb-clear {
  background: transparent; border: 0; cursor: pointer;
  color: rgba(244,236,228,0.7);
  font: 500 12px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em;
  padding: 6px 4px;
}
.bulk-bar-close:hover, .bulk-bar .bb-clear:hover { color: var(--paper); }
.bulk-bar .bb-action {
  background: transparent; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--paper); font: 500 13px/1 var(--f-body);
  padding: 8px 12px; border-radius: var(--r-pill);
  transition: background var(--dur-2) var(--ease);
}
.bulk-bar .bb-action:hover { background: rgba(255,255,255,0.08); }
.bulk-bar .bb-action[disabled] { opacity: 0.4; cursor: not-allowed; }
.bulk-bar .bb-action.is-danger { color: #FFB8B8; }
.bulk-bar .bb-action.is-danger:hover { background: rgba(255,120,120,0.16); color: #FFCFCF; }

/* ─────────────────────────── Chapter 02 — Typography ────────────────────── */
/* Canonical type-scale classes referenced by the chapter 02 demos. The
   chapter HTML's inline <style> contains only demo-private styling (.ty-*);
   these utility classes are listed in the demo's CSS snippet tab as the
   canonical definitions, so we mirror them here so @magicblocksai/css
   consumers (and the @magicblocksai/ui Heading/Lede/Caption/Quote/Eyebrow
   components) actually have something to style against. */

.display    { font: 700 clamp(36px, 5vw, 56px)/1.05 var(--f-display); letter-spacing: -0.025em; margin: 0; }
.headline   { font: 700 44px/1.08 var(--f-display); letter-spacing: -0.02em; margin: 0; }
.title      { font: 700 32px/1.15 var(--f-display); letter-spacing: -0.015em; margin: 0; }
.heading    { font: 600 24px/1.25 var(--f-display); letter-spacing: -0.01em; margin: 0; }
.subheading { font: 600 20px/1.3  var(--f-display); letter-spacing: -0.005em; margin: 0; }
.lede       { font: 400 19px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }
.body       { font: 400 16px/1.6  var(--f-body); margin: 0; }
.caption    { font: 400 13px/1.55 var(--f-body); color: var(--fg-dim); margin: 0; }
.micro      { font: 500 11px/1.5  var(--f-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--fg-dim); margin: 0; }
.eyebrow {
  font: 500 11.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-dim);
  margin: 0;
}

.quote {
  margin: 0; padding: var(--s-7) var(--s-7) var(--s-7) var(--s-9);
  background: var(--bg-paper);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
  position: relative;
  max-width: 62ch;
}
.quote::before {
  content: "\201C";
  position: absolute; top: -8px; left: var(--s-5);
  font-family: var(--f-serif); font-style: italic;
  font-size: 72px; line-height: 1; color: var(--accent);
  font-variation-settings: "SOFT" 80;
}
.quote blockquote {
  margin: 0 0 var(--s-4);
  font: 400 21px/1.4 var(--f-body); color: var(--fg);
  letter-spacing: -0.005em;
}
.quote blockquote em {
  font-family: var(--f-serif); font-style: italic; font-weight: 400;
  color: var(--accent); font-variation-settings: "SOFT" 80;
}
.quote figcaption { display: flex; flex-direction: column; gap: 2px; }
.quote-who  { font-family: var(--f-display); font-weight: 600; font-size: 14px; color: var(--fg); }
.quote-role { font-family: var(--f-mono); font-size: 12px; color: var(--fg-dim); }

/* ─────────────────────────── Chapter 10 — Patterns & specials ───────── */
/* Verbatim migration of the chapter-private component CSS so the
   PricingPage / SignInPage / NotFoundPage / ConversationPreview /
   DashboardShell / EmptyStatePage / SettingsShell / OnboardingStep
   classes ship through @magicblocksai/css too.

   Notes:
   - The chapter-07 .empty / .empty-ic / .empty-* primitives already live
     in this file; chapter 10's EmptyStatePage just adds the
     three-up grid wrapper + icon-tint variants.
   - Chapter 10's settings shell uses a button-based switch — to avoid
     colliding with chapter 03's label+input .switch atom, we expose the
     button-based variant as `.settings-switch`. */

/* ── 10.1 Pricing page ─────────────────────────────────────── */
.pg { padding: var(--s-9) 0; }
.pg-head { text-align: center; max-width: 680px; margin: 0 auto var(--s-7); }
.pg-eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent-text); font-weight: 600; margin: 0 0 var(--s-3); }
.pg-title { font: 600 clamp(32px, 4vw, 44px)/1.15 var(--f-display); letter-spacing: -0.02em; color: var(--fg); margin: 0 0 var(--s-3); }
.pg-title em { font-family: var(--f-italic); font-style: italic; font-weight: 400; color: var(--accent); font-variation-settings: "SOFT" 80; }
.pg-lede { font: 400 17px/1.55 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-5); }
.pg-toggle {
  display: inline-flex; padding: 4px;
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-pill);
}
.pg-toggle button {
  background: transparent; border: 0; cursor: pointer;
  padding: 8px 16px; border-radius: var(--r-pill);
  font: 500 13.5px/1 var(--f-body); color: var(--fg-soft);
}
.pg-toggle button.is-active { background: var(--ink); color: var(--paper); }
.pg-save { margin-left: 6px; font: 600 11px/1 var(--f-mono); color: var(--accent-text); }
.pg-toggle button.is-active .pg-save { color: var(--accent-text); }

.pg-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); align-items: stretch; }
@media (max-width: 880px) { .pg-grid { grid-template-columns: 1fr; } }

.pg-tier {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  display: flex; flex-direction: column;
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.pg-tier:hover { transform: translateY(-2px); box-shadow: var(--sh-2); }
.pg-tier-hero {
  background: var(--ink); color: var(--paper);
  border-color: var(--ink);
  transform: translateY(-6px);
  box-shadow: 0 24px 60px -20px color-mix(in oklab, var(--ink) 40%, transparent);
  position: relative;
  overflow: hidden;
}
.pg-tier-hero::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(400px 300px at 80% -20%, color-mix(in oklab, var(--accent) 35%, transparent), transparent 60%);
  pointer-events: none;
}
.pg-ribbon {
  position: absolute; top: 16px; right: -32px;
  transform: rotate(35deg);
  background: var(--accent); color: var(--paper);
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 5px 36px; z-index: 2;
}
.pg-name { font: 500 14px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); margin: 0 0 var(--s-2); position: relative; z-index: 1; }
.pg-tier-hero .pg-name { color: color-mix(in oklab, var(--paper) 70%, transparent); }
.pg-tag { font: 400 14px/1.5 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-5); position: relative; z-index: 1; }
.pg-tier-hero .pg-tag { color: color-mix(in oklab, var(--paper) 75%, transparent); }
.pg-price { display: flex; align-items: baseline; margin-bottom: var(--s-5); position: relative; z-index: 1; }
.pg-dollar { font: 500 20px/1 var(--f-display); color: var(--fg-soft); margin-right: 2px; }
.pg-tier-hero .pg-dollar { color: color-mix(in oklab, var(--paper) 70%, transparent); }
.pg-amt { font: 600 52px/1 var(--f-display); color: var(--fg); letter-spacing: -0.025em; font-variant-numeric: tabular-nums; }
.pg-tier-hero .pg-amt { color: var(--paper); }
.pg-per { font: 500 14px/1 var(--f-body); color: var(--fg-dim); margin-left: 6px; }
.pg-tier-hero .pg-per { color: color-mix(in oklab, var(--paper) 60%, transparent); }
.pg-price-custom { font: 600 36px/1 var(--f-display); color: var(--fg); letter-spacing: -0.02em; }
.pg-feats { list-style: none; padding: 0; margin: 0 0 var(--s-6); flex: 1; position: relative; z-index: 1; }
.pg-feats li {
  display: flex; align-items: flex-start; gap: 10px;
  font: 400 14px/1.55 var(--f-body); color: var(--fg);
  padding: 8px 0;
  border-bottom: 1px solid var(--hair-soft);
}
.pg-feats li:last-child { border-bottom: 0; }
.pg-feats li::before {
  content: "✓"; color: var(--accent-text); font-weight: 600;
  flex-shrink: 0; width: 16px; text-align: center;
}
.pg-tier-hero .pg-feats li { color: color-mix(in oklab, var(--paper) 92%, transparent); border-color: color-mix(in oklab, var(--paper) 12%, transparent); }
.pg-cta {
  display: block; text-align: center;
  background: var(--bg-paper); color: var(--fg);
  border: 1px solid var(--hair);
  padding: 12px 16px; border-radius: var(--r-md);
  font: 600 14px/1 var(--f-display); text-decoration: none;
  position: relative; z-index: 1;
  transition: background var(--dur-2) var(--ease);
}
.pg-cta:hover { background: var(--bg-warm); color: var(--fg); }
.pg-cta-hero { background: var(--accent); color: var(--paper); border-color: transparent; box-shadow: var(--sh-pink); }
.pg-cta-hero:hover { background: var(--accent); color: var(--paper); transform: translateY(-1px); }

/* ── 10.2 Sign-in page ─────────────────────────────────────── */
.au {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  overflow: hidden;
  min-height: 580px;
}
@media (max-width: 880px) { .au { grid-template-columns: 1fr; } .au-side { order: -1; } }
.au-card { padding: var(--s-8) var(--s-7); display: flex; flex-direction: column; }
.au-brand { display: inline-flex; align-items: center; gap: 10px; font: 700 16px/1 var(--f-display); color: var(--fg); text-decoration: none; letter-spacing: -0.01em; margin-bottom: var(--s-7); }
.au-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.au-title { font: 600 32px/1.15 var(--f-display); letter-spacing: -0.02em; color: var(--fg); margin: 0 0 8px; }
.au-lede { font: 400 15px/1.55 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-6); }
.au-google {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%;
  background: var(--bg-paper); border: 1px solid var(--hair);
  padding: 12px 16px; border-radius: var(--r-md);
  font: 600 14px/1 var(--f-display); color: var(--fg); cursor: pointer;
  transition: background var(--dur-2) var(--ease);
}
.au-google:hover { background: var(--bg-warm); }
.au-div {
  position: relative; text-align: center;
  margin: var(--s-5) 0;
  font: 500 11.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-dim);
}
.au-div::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: var(--hair); z-index: 0; }
.au-div span { position: relative; z-index: 1; background: var(--bg-paper); padding: 0 10px; }
.au-form { display: flex; flex-direction: column; gap: var(--s-4); }
.au-field { display: flex; flex-direction: column; gap: 6px; }
.au-field > span:first-child {
  display: flex; justify-content: space-between; align-items: baseline;
  font: 500 12.5px/1 var(--f-body); color: var(--fg-soft);
}
.au-forgot { font: 500 12px/1 var(--f-body); color: var(--accent-text); text-decoration: none; }
.au-forgot:hover { text-decoration: underline; }
.au-field input {
  font: 400 15px/1 var(--f-body);
  padding: 12px 14px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  color: var(--fg);
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}
.au-field input:focus { outline: 0; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.au-submit {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--accent); color: var(--paper); border: 0;
  padding: 13px 20px; border-radius: var(--r-md);
  font: 600 15px/1 var(--f-display); cursor: pointer;
  box-shadow: var(--sh-pink);
  margin-top: var(--s-3);
  transition: transform var(--dur-2) var(--ease);
}
.au-submit:hover { transform: translateY(-1px); }
.au-foot { margin-top: auto; padding-top: var(--s-5); font: 400 13.5px/1.5 var(--f-body); color: var(--fg-soft); }
.au-foot a { color: var(--accent-text); text-decoration: none; font-weight: 500; }
.au-foot a:hover { text-decoration: underline; }

.au-side {
  background: var(--warm-3);
  padding: var(--s-8) var(--s-7);
  display: flex; flex-direction: column; justify-content: center;
  position: relative; overflow: hidden;
  /* pinned warm — rescope type tokens so dark-mode copy reads */
  --fg:      var(--ink);
  --fg-soft: color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:  color-mix(in oklab, var(--ink) 48%, transparent);
  --hair:    rgba(25, 30, 50, 0.09);
  color: var(--fg);
}
.au-side::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(400px 320px at 100% 0%, color-mix(in oklab, var(--accent) 22%, transparent), transparent 60%);
  pointer-events: none;
}
.au-quote-glyph { position: relative; font: 400 86px/0.8 var(--f-italic); font-style: italic; color: var(--accent-text); font-variation-settings: "SOFT" 80; margin-bottom: var(--s-3); }
.au-quote { position: relative; font: 400 22px/1.4 var(--f-display); letter-spacing: -0.01em; color: var(--fg); margin: 0 0 var(--s-6); }
.au-quote em { font-family: var(--f-italic); font-style: italic; font-weight: 400; color: var(--accent); font-variation-settings: "SOFT" 80; }
.au-quote-cite { position: relative; display: flex; align-items: center; gap: var(--s-3); }
.au-quote-name { font: 600 14px/1.2 var(--f-display); color: var(--fg); }
.au-quote-role { font: 400 12.5px/1.3 var(--f-body); color: var(--fg-soft); margin-top: 2px; }

/* ── 10.3 404 / not found ─────────────────────────────────── */
.nf {
  position: relative;
  padding: var(--s-11) var(--s-7);
  background: var(--warm-3);
  border-radius: var(--r-xl);
  overflow: hidden;
  isolation: isolate;
  min-height: 480px;
  /* pinned warm — rescope type tokens so dark-mode copy reads */
  --fg:      var(--ink);
  --fg-soft: color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:  color-mix(in oklab, var(--ink) 48%, transparent);
  --hair:    rgba(25, 30, 50, 0.09);
  color: var(--fg);
}
.nf-bloom {
  position: absolute; inset: 0;
  background:
    radial-gradient(500px 400px at 20% 100%, color-mix(in oklab, var(--accent) 20%, transparent), transparent 60%),
    radial-gradient(400px 300px at 90% 10%, color-mix(in oklab, #FFC6A5 55%, transparent), transparent 60%);
  z-index: -1;
}
.nf-inner { max-width: min(880px, 100%); }
.nf-eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent-text); font-weight: 600; margin: 0 0 var(--s-4); }
.nf-title {
  font: 600 clamp(36px, 5vw, 56px)/1.1 var(--f-display);
  letter-spacing: -0.025em; color: var(--fg);
  margin: 0 0 var(--s-4);
}
.nf-title em { font-family: var(--f-italic); font-style: italic; font-weight: 400; color: var(--accent); font-variation-settings: "SOFT" 80; }
.nf-lede { font: 400 18px/1.55 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-6); max-width: 560px; }
.nf-actions { display: flex; gap: var(--s-4); align-items: center; flex-wrap: wrap; margin-bottom: var(--s-7); }
.nf-cta {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent); color: var(--paper);
  font: 600 14.5px/1 var(--f-display);
  padding: 13px 20px;
  border-radius: var(--r-pill);
  text-decoration: none;
  box-shadow: var(--sh-pink);
  transition: transform var(--dur-2) var(--ease);
}
.nf-cta:hover { transform: translateY(-2px); color: var(--paper); }
.nf-link { color: var(--fg); text-decoration: none; font: 500 14px/1 var(--f-body); border-bottom: 1px solid currentColor; padding: 4px 2px; }
.nf-link:hover { color: var(--accent-text); }
.nf-sug { border-top: 1px solid var(--hair); padding-top: var(--s-5); max-width: min(640px, 100%); }
.nf-sug-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-dim); font-weight: 600; margin: 0 0 var(--s-3); }
.nf-sug ul { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 10px var(--s-5); }
.nf-sug a { color: var(--fg); text-decoration: none; font: 500 14px/1.4 var(--f-body); }
.nf-sug a:hover { color: var(--accent-text); }

/* ── 10.4 Conversation preview ─────────────────────────────── */
.cv {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  overflow: hidden;
  max-width: 720px;
  margin: 0 auto;
}
.cv-head { display: flex; align-items: center; justify-content: space-between; padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--hair); background: var(--bg-warm); }
.cv-persona { display: flex; align-items: center; gap: var(--s-3); }
.cv-name { font: 600 14.5px/1.2 var(--f-display); color: var(--fg); letter-spacing: -0.005em; }
.cv-role { font: 400 12.5px/1.3 var(--f-body); color: var(--fg-soft); margin-top: 2px; }

.cv-thread { padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-3); }
.cv-meta { text-align: center; font-size: 11px; color: var(--fg-dim); padding: 4px 0; letter-spacing: 0.05em; }

.cv-msg { display: flex; gap: 10px; align-items: flex-end; max-width: 88%; }
.cv-in { align-self: flex-start; }
.cv-out { align-self: flex-end; flex-direction: row-reverse; }

.cv-bubble {
  padding: 10px 14px;
  background: var(--bg-warm);
  border: 1px solid var(--hair);
  border-radius: 16px 16px 16px 4px;
  font: 400 14.5px/1.5 var(--f-body); color: var(--fg);
}
.cv-bubble p { margin: 0; }
.cv-bubble em { font-family: var(--f-italic); font-style: italic; font-weight: 500; color: var(--accent-text); font-variation-settings: "SOFT" 80; }

.cv-bubble-pink {
  background: var(--accent);
  color: var(--paper);
  border-color: transparent;
  border-radius: 16px 16px 4px 16px;
  box-shadow: var(--sh-pink);
}
.cv-bubble-pink em { color: var(--paper); text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 3px; }

.cv-typing { display: flex; gap: 10px; align-items: center; align-self: flex-start; }
.cv-bubble-typing { display: flex; gap: 4px; padding: 14px 16px; }
.cv-bubble-typing span {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--fg-dim);
  animation: cv-blink 1.2s ease-in-out infinite;
}
.cv-bubble-typing span:nth-child(2) { animation-delay: 0.2s; }
.cv-bubble-typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes cv-blink { 0%, 60%, 100% { opacity: 0.3; } 30% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .cv-bubble-typing span { animation: none; opacity: 0.6; }
}

.cv-foot { padding: var(--s-3) var(--s-5); border-top: 1px solid var(--hair); background: var(--bg-warm); }
.cv-meta-inline { font-size: 11.5px; color: var(--fg-dim); display: flex; align-items: center; gap: 8px; letter-spacing: 0.04em; }
.cv-meta-inline a { color: var(--accent-text); text-decoration: none; margin-left: auto; }
.cv-meta-inline a:hover { text-decoration: underline; }

/* ── 10.5 Dashboard shell ──────────────────────────────────── */
/* Distinct from chapter 05's .dash-tile-* — this is the page shell. */
.dash {
  display: grid; grid-template-columns: 240px 1fr;
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-xl); overflow: hidden; min-height: 560px;
}
@media (max-width: 720px) { .dash { grid-template-columns: 1fr; } .dash-side { display: none; } }
.dash-side {
  background: var(--warm-3); padding: var(--s-4) var(--s-4); border-right: 1px solid var(--hair);
  /* pinned warm — rescope type tokens */
  --fg: var(--ink); --fg-soft: color-mix(in oklab, var(--ink) 68%, transparent); --fg-dim: color-mix(in oklab, var(--ink) 48%, transparent); --hair: rgba(25, 30, 50, 0.09); color: var(--fg);
}
.dash-brand { display: inline-flex; align-items: center; gap: 10px; font: 700 15px/1 var(--f-display); color: var(--fg); letter-spacing: -0.005em; padding: 6px 10px; margin-bottom: var(--s-5); }
.dash-nav-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-dim); font-weight: 600; margin: 0 10px var(--s-2); }
.dash-nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  font: 500 13.5px/1 var(--f-body);
  color: var(--fg-soft);
  text-decoration: none;
  border-radius: var(--r-sm);
  margin-bottom: 2px;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.dash-nav-item > span:first-child { flex: 1; }
.dash-nav-item:hover { background: var(--bg-paper); color: var(--fg); }
.dash-nav-item.is-active { background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }

.dash-main { padding: var(--s-6); }
.dash-main-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--s-5); gap: var(--s-3); flex-wrap: wrap; }
.dash-act {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent); color: var(--paper); border: 0;
  padding: 10px 16px; border-radius: var(--r-md);
  font: 600 13.5px/1 var(--f-display); cursor: pointer;
  box-shadow: var(--sh-pink);
}
.dash-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-3); margin-bottom: var(--s-6); }
@media (max-width: 560px) { .dash-stats { grid-template-columns: 1fr; } }
.dash-stat { padding: var(--s-4); background: var(--bg-paper); border: 1px solid var(--hair); border-radius: var(--r-md); }
.dash-stat-l { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); font-weight: 600; margin-bottom: 6px; }
.dash-stat-n { font: 600 28px/1 var(--f-display); color: var(--fg); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.dash-stat-d { font: 500 12px/1.3 var(--f-body); color: var(--accent-text); margin-top: 6px; }
.dash-feed > p { margin-bottom: var(--s-3); }
.dash-row { display: flex; align-items: center; gap: var(--s-3); padding: 12px var(--s-3); border-bottom: 1px solid var(--hair-soft); }
.dash-row:last-child { border-bottom: 0; }
.dash-row strong { font: 600 14px/1.2 var(--f-display); color: var(--fg); }

/* ── 10.6 Empty-state pages ───────────────────────────────── */
/* Chapter 10 reuses the chapter-07 .empty primitive (already in this file).
   These selectors only add the three-up grid + icon-tint variants. */
.emp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); }
@media (max-width: 880px) { .emp-grid { grid-template-columns: 1fr; } }
.emp-grid .empty { margin: 0; padding: var(--s-6) var(--s-4); }
.empty-ic-ghost { background: var(--bg-sunk) !important; }
.empty-ic-error { background: var(--accent-soft) !important; color: var(--accent-text) !important; }

/* ── 10.7 Settings shell ──────────────────────────────────── */
.settings { display: grid; grid-template-columns: 200px 1fr; gap: var(--s-6); max-width: min(1080px, 100%); margin: 0 auto; width: 100%; }
@media (max-width: 720px) { .settings { grid-template-columns: 1fr; } }
.settings-nav { display: flex; flex-direction: column; gap: var(--s-4); }
.settings-group { display: flex; flex-direction: column; gap: 2px; }
.settings-group-label { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); margin-bottom: var(--s-2); }
.settings-nav-link { padding: 8px 12px; border-radius: var(--r-xs); font: 500 14px/1 var(--f-body); color: var(--fg-soft); text-decoration: none; cursor: pointer; }
.settings-nav-link:hover { background: var(--bg-sunk); color: var(--fg); }
.settings-nav-link.is-active { background: var(--accent-soft); color: var(--accent-text); }
.settings-pane { min-width: 0; }
.settings-head { margin-bottom: var(--s-5); padding-bottom: var(--s-4); border-bottom: 1px solid var(--hair); }
.settings-title { font: 700 24px/1.2 var(--f-display); color: var(--fg); margin: 0; }
.settings-lede  { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: var(--s-1) 0 0; }
.settings-row { display: grid; grid-template-columns: 1fr auto; gap: var(--s-5); align-items: center; padding: var(--s-4) 0; border-bottom: 1px solid var(--hair); }
.settings-row-meta { min-width: 0; }
.settings-row-label { font: 600 14px/1.3 var(--f-body); color: var(--fg); }
.settings-row-desc  { font: 400 13px/1.5 var(--f-body); color: var(--fg-soft); margin-top: 2px; }
/* Button-style toggle for settings rows. Renamed from chapter 10's
   .switch to avoid colliding with the chapter 03 input-style atom. */
.settings-switch { width: 40px; height: 22px; border-radius: 999px; background: var(--hair); border: 0; position: relative; cursor: pointer; padding: 0; }
.settings-switch.is-on { background: var(--accent); }
.settings-switch-knob { position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--paper); box-shadow: var(--sh-1); transition: transform var(--dur-2) var(--ease); }
.settings-switch.is-on .settings-switch-knob { transform: translateX(18px); }
@media (prefers-reduced-motion: reduce) {
  .settings-switch-knob { transition: none; }
}
/* Sticky save bar — visible only when the form is dirty. */
.settings-save {
  position: sticky; bottom: 0;
  margin-top: var(--s-6);
  padding: var(--s-3) var(--s-4);
  display: flex; justify-content: flex-end; gap: var(--s-3);
  background: color-mix(in oklab, var(--bg-paper) 92%, transparent);
  border-top: 1px solid var(--hair);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  backdrop-filter: blur(8px);
}

/* ── 10.8 Onboarding step ─────────────────────────────────── */
.ob { max-width: min(720px, 100%); margin: 0 auto; width: 100%; }
.ob-steps { list-style: none; display: flex; gap: var(--s-3); padding: 0; margin: 0 0 var(--s-5); }
.ob-steps li { flex: 1; display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2) 0; font: 500 12px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg-dim); border-top: 2px solid var(--hair); }
.ob-steps .is-active { color: var(--accent-text); border-top-color: var(--accent); }
.ob-steps .is-done   { color: var(--fg-soft); border-top-color: var(--accent); }
.ob-dot { width: 20px; height: 20px; border-radius: 50%; background: var(--bg-sunk); color: var(--fg-soft); display: inline-flex; align-items: center; justify-content: center; font: 600 11px/1 var(--f-mono); }
.ob-steps .is-active .ob-dot { background: var(--accent); color: var(--paper); }
.ob-steps .is-done .ob-dot   { background: var(--accent-soft); color: var(--accent-text); }
.ob-panel { padding: var(--s-6); background: var(--bg-paper); border: 1px solid var(--hair); border-radius: var(--r-lg); }
.ob-eyebrow { font-size: 11px; color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.08em; }
.ob-title { font: 700 28px/1.15 var(--f-display); color: var(--fg); margin: var(--s-2) 0 var(--s-3); text-wrap: balance; }
.ob-title em { font-family: var(--f-serif); font-style: italic; font-variation-settings: "SOFT" 80; color: var(--accent); font-weight: 400; }
.ob-lede { font: 400 15px/1.6 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-4); }
.ob-choices { display: flex; flex-direction: column; gap: var(--s-2); }
.ob-choice { display: flex; align-items: center; gap: var(--s-3); padding: 12px 16px; background: var(--bg-paper); border: 1px solid var(--hair); border-radius: var(--r-sm); font: 500 14px/1 var(--f-body); color: var(--fg); cursor: pointer; text-align: left; }
.ob-choice:hover { border-color: var(--accent); color: var(--accent-text); }
.ob-choice-icon { width: 24px; height: 24px; border-radius: 50%; background: var(--bg-sunk); display: inline-flex; align-items: center; justify-content: center; font: 600 12px/1 var(--f-mono); color: var(--fg-soft); }
.ob-foot { display: flex; justify-content: space-between; margin-top: var(--s-4); }

/* ─────────────────────────── Chapter 16 — Platform narrative ─────────── */
/* Verbatim migration of the chapter-private component CSS so the
   FeatureCluster / ContrastPair / FeatureTable / ClusterMap / CounterRail
   classes ship through @magicblocksai/css too.

   No class collisions with prior chapters — `.fc-*`, `.cp-*`, `.cm-*`,
   `.cr-*`, `.feature-cluster`, `.contrast-pair`, `.feature-table`,
   `.cluster-map`, `.counter-rail` are all introduced here. The `.is-ours`
   modifier already exists in chapter 09 scoped to `.compare`; chapter 16
   scopes its `.is-ours` rules under `.feature-table` so the two co-exist
   without overriding each other. */

/* ── 16.1 FEATURE CLUSTER ─────────────────────────────────────
   Thematically-grouped block of feature cards. Used 6× on the
   /platform page, one per cluster (Engine, Channels, Conversation,
   Memory & Context, Trust & Compliance, Operations). Each cluster
   is a scannable taxonomy: header + sub-hed + grid of cards.
   ─────────────────────────────────────────────────────────────── */
.feature-cluster {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-6);
}
.fc-head {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s-5);
  align-items: start;
}
.fc-head-text { display: flex; flex-direction: column; gap: var(--s-3); max-width: 70ch; }
.fc-eyebrow {
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-faint);
  margin: 0;
}
.fc-h2 {
  font: 600 32px/1.15 var(--f-display);
  letter-spacing: -0.02em;
  color: var(--fg);
  margin: 0;
}
.fc-h2 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
  font-variation-settings: "SOFT" 80;
}
.fc-subhed {
  font: 400 17px/1.55 var(--f-body);
  color: var(--fg-soft);
  margin: 0;
}
.fc-anchor-visual {
  width: 120px;
  flex-shrink: 0;
  display: flex; align-items: flex-start; justify-content: center;
}
.fc-anchor-visual svg, .fc-anchor-visual img { max-width: 100%; height: auto; display: block; }

/* Card grid */
.fc-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-4);
}
.feature-cluster--2up .fc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.feature-cluster--4up .fc-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.fc-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: var(--s-5);
  display: flex; flex-direction: column; gap: var(--s-3);
  text-decoration: none;
  color: inherit;
  position: relative;
  transition: transform var(--dur-2) var(--ease),
              box-shadow var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease);
  /* accent stripe on left edge — only visible on hover (link cards only) */
  overflow: hidden;
}
.fc-card.is-linked::before {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0;
  width: 3px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform var(--dur-2) var(--ease);
}
.fc-card.is-linked:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 24px -8px rgba(25, 30, 50, 0.12);
  border-color: color-mix(in oklab, var(--accent) 25%, var(--hair));
}
.fc-card.is-linked:hover::before { transform: scaleY(1); }
.fc-card.is-linked:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.fc-card-icon {
  width: 28px; height: 28px;
  color: var(--fg-dim);
  transition: color var(--dur-2) var(--ease);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.fc-card.is-linked:hover .fc-card-icon { color: var(--accent); }
.fc-card-icon img, .fc-card-icon svg { width: 28px; height: 28px; display: block; }
.fc-card-name {
  font: 600 16px/1.3 var(--f-body);
  color: var(--fg);
  margin: 0;
}
.fc-card-claim {
  font: 400 14px/1.5 var(--f-body);
  color: var(--fg-soft);
  margin: 0;
}
.fc-card-proof {
  font: 400 13px/1.45 var(--f-body);
  color: var(--fg-dim);
  margin: 0;
  font-style: italic;
}
.fc-card-deeplink {
  font: 500 13px/1 var(--f-body);
  color: var(--accent-text);
  text-decoration: none;
  margin-top: auto;
  padding-top: var(--s-2);
  display: inline-flex; align-items: center; gap: 4px;
}
.fc-card.is-linked:hover .fc-card-deeplink { color: var(--accent); }

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .fc-card.is-linked:hover { transform: none; }
  .fc-card.is-linked::before { transition: none; }
}

/* Responsive */
@media (max-width: 1023px) {
  .fc-grid, .feature-cluster--4up .fc-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .fc-anchor-visual { width: 80px; }
}
@media (max-width: 767px) {
  .fc-grid, .feature-cluster--4up .fc-grid, .feature-cluster--2up .fc-grid {
    grid-template-columns: 1fr;
  }
  .fc-head { grid-template-columns: 1fr; }
  .fc-anchor-visual { display: none; }
  .fc-h2 { font-size: 26px; }
}

/* Dark-mode tweaks */
body[data-theme="dark"] .fc-card.is-linked:hover {
  box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.4);
}

/* ── 16.2 CONTRAST PAIR ──────────────────────────────────────
   Side-by-side narrative panel: left = "the category default",
   right = "the MagicBlocks way". Used 5× on /why-magicblocks
   to argue category-level differentiation without naming a
   competitor. The asymmetry between the two panels (muted
   left vs accent-tinted right) IS the argument.
   ─────────────────────────────────────────────────────────── */
.contrast-pair {
  display: grid;
  gap: var(--s-6);
  max-width: 920px;
}
.cp-head { display: flex; flex-direction: column; gap: var(--s-3); max-width: 70ch; }
.cp-eyebrow {
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-faint);
  margin: 0;
}
.cp-h2 {
  font: 600 32px/1.15 var(--f-display);
  letter-spacing: -0.02em;
  color: var(--fg);
  margin: 0;
}
.cp-h2 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
  font-variation-settings: "SOFT" 80;
}
.cp-body {
  display: flex; flex-direction: column; gap: var(--s-4);
}
.cp-body p {
  font: 400 17px/1.6 var(--f-body);
  color: var(--fg-soft);
  margin: 0;
  max-width: 70ch;
}
.cp-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-5);
}
.cp-panel {
  border-radius: var(--r-md);
  padding: var(--s-5);
  display: flex; flex-direction: column; gap: var(--s-3);
  min-height: 200px;
  position: relative;
  transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.cp-panel--left {
  background: var(--hair-soft);
  border: 1px solid var(--hair);
}
.cp-panel--right {
  background: color-mix(in oklab, var(--accent) 4%, var(--bg-paper));
  border: 1px solid color-mix(in oklab, var(--accent) 24%, transparent);
}
body[data-theme="dark"] .cp-panel--left {
  background: color-mix(in oklab, var(--bg-paper) 70%, var(--ink));
}
body[data-theme="dark"] .cp-panel--right {
  background: color-mix(in oklab, var(--accent) 12%, var(--bg-paper));
  border-color: color-mix(in oklab, var(--accent) 40%, transparent);
}
.cp-panel--right:hover {
  transform: translateY(-2px);
  border-color: color-mix(in oklab, var(--accent) 40%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .cp-panel--right:hover { transform: none; }
}
.cp-panel-eyebrow {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin: 0;
}
.cp-panel--left  .cp-panel-eyebrow { color: var(--fg-faint); }
.cp-panel--right .cp-panel-eyebrow { color: var(--accent-text); }
.cp-panel-title {
  font: 600 19px/1.3 var(--f-display);
  margin: 0;
}
.cp-panel--left  .cp-panel-title { color: var(--fg-soft); }
.cp-panel--right .cp-panel-title { color: var(--fg); }
.cp-panel-visual {
  width: 100%;
  height: 80px;
  display: flex; align-items: center; justify-content: center;
  margin: var(--s-2) 0;
}
.cp-panel-visual svg, .cp-panel-visual img { max-height: 100%; max-width: 100%; }
.cp-panel-stat {
  font: 500 14px/1.2 var(--f-mono);
  font-variant-numeric: tabular-nums;
  margin: 0;
  margin-top: auto;
}
.cp-panel--left  .cp-panel-stat { color: var(--fg-dim); }
.cp-panel--right .cp-panel-stat { color: var(--accent-text); font-weight: 600; }
.cp-panel-bullets {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.cp-panel-bullets li {
  font: 400 13.5px/1.45 var(--f-body);
  color: var(--fg-soft);
  padding-left: var(--s-4);
  position: relative;
}
.cp-panel-bullets li::before {
  content: "";
  position: absolute; left: 0; top: 8px;
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
  opacity: 0.5;
}
.cp-panel--right .cp-panel-bullets li { color: var(--fg); }
.cp-panel--right .cp-panel-bullets li::before { background: var(--accent); opacity: 1; }
.cp-cta {
  display: inline-flex; align-items: center; gap: 6px;
  align-self: flex-start;
  font: 500 14px/1 var(--f-body);
  color: var(--accent-text);
  text-decoration: none;
  border-bottom: 1px dashed currentColor;
  padding-bottom: 2px;
}
.cp-cta:hover { color: var(--accent); }
/* Variant: --reversed swaps which side gets the accent treatment */
.contrast-pair--reversed .cp-pair { direction: rtl; }
.contrast-pair--reversed .cp-pair > * { direction: ltr; }

@media (max-width: 767px) {
  .cp-pair { grid-template-columns: 1fr; gap: var(--s-4); }
  .cp-h2 { font-size: 26px; }
  .cp-body p { font-size: 15px; }
}

/* ── 16.3 FEATURE TABLE ───────────────────────────────────
   Mirrors the canonical .compare pattern from §9.8 so all the
   product-vs-competitor tables in the kit look the same: green-tinted
   "MagicBlocks" column (positive, not aggressive), neutral "Most
   platforms" column. .is-ours marks the MagicBlocks column.
   On mobile the table collapses to one card-per-row — the per-cell
   data-mobile-eyebrow attr provides the column label that <thead> hid.
   Used on /platform §10. ─────────────────────────────────── */
/* Visually-hidden helper used by .feature-table's <caption> (and any
   other surface that needs screen-reader-only text). Canonical pattern. */
.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;
}
.feature-table {
  width: 100%;
  border-collapse: collapse;
  font: 400 14px/1.4 var(--f-body);
  margin: 0 auto;
}
.feature-table th, .feature-table td {
  padding: var(--s-3) var(--s-4);
  text-align: center;
  border-bottom: 1px solid var(--hair);
  vertical-align: top;
}
.feature-table thead th {
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-dim);
  padding-top: var(--s-4);
  padding-bottom: var(--s-4);
}
.feature-table tbody th {
  text-align: left;
  font-weight: 500;
  color: var(--fg);
}
.feature-table .is-ours {
  background: var(--success-soft);
  color: var(--success-text);
  font-weight: 600;
}
.feature-table thead .is-ours {
  color: var(--success-text);
  border-top-left-radius: var(--r-sm);
  border-top-right-radius: var(--r-sm);
}
.feature-table tbody tr:last-child th,
.feature-table tbody tr:last-child td { border-bottom: 0; }

/* Mobile: stack to card-per-row, hide the now-redundant column headers,
   and surface each cell's column label via data-mobile-eyebrow. */
@media (max-width: 767px) {
  .feature-table, .feature-table thead, .feature-table tbody, .feature-table tr,
  .feature-table th, .feature-table td { display: block; width: auto; }
  .feature-table thead { display: none; }
  .feature-table tbody tr {
    border: 1px solid var(--hair);
    border-radius: var(--r-md);
    margin-bottom: var(--s-3);
    overflow: hidden;
  }
  .feature-table tbody th {
    background: var(--bg-sunk);
    padding: var(--s-3) var(--s-4);
    border-bottom: 1px solid var(--hair);
    text-align: left;
  }
  .feature-table tbody td {
    padding: var(--s-3) var(--s-4);
    text-align: left;
    border-bottom: 1px solid var(--hair-soft);
  }
  .feature-table tbody td::before {
    content: attr(data-mobile-eyebrow);
    display: block;
    font: 600 10px/1 var(--f-mono);
    text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--fg-faint);
    margin-bottom: 6px;
  }
  .feature-table tbody td.is-ours::before { color: var(--success-text); }
  .feature-table tbody tr td:last-child { border-bottom: 0; }
}

/* ── 16.4 CLUSTER MAP ────────────────────────────────────────
   Six labelled hexes radiating around a centre node, each
   anchor-linked to its cluster section below. Used on the
   /platform hero only.
   ─────────────────────────────────────────────────────────── */
.cluster-map {
  width: 100%;
  max-width: 520px;
  aspect-ratio: 1;
  margin: 0 auto;
  position: relative;
}
.cluster-map svg { width: 100%; height: 100%; display: block; overflow: visible; }
/* Hex tile — soft drop shadow gives depth, dashed connector contrasts
   against the solid stroke. Number sits ABOVE the label with mono caps. */
.cm-hex {
  fill: var(--bg-paper);
  stroke: color-mix(in oklab, var(--ink) 16%, transparent);
  stroke-width: 1.5;
  filter: drop-shadow(0 2px 4px color-mix(in oklab, var(--ink) 10%, transparent));
  transition: fill var(--dur-2) var(--ease),
              stroke var(--dur-2) var(--ease),
              filter var(--dur-2) var(--ease),
              transform var(--dur-2) var(--ease);
  transform-origin: center;
  transform-box: fill-box;
}
.cm-hex-num {
  font: 700 10px var(--f-mono); fill: var(--fg-faint);
  letter-spacing: 0.14em;
  text-anchor: middle; dominant-baseline: central;
  pointer-events: none;
}
.cm-hex-label {
  font: 700 14px var(--f-display); fill: var(--fg);
  letter-spacing: -0.01em;
  text-anchor: middle; dominant-baseline: central;
  pointer-events: none;
}
.cluster-map a:hover .cm-hex,
.cluster-map a:focus-visible .cm-hex {
  fill: color-mix(in oklab, var(--accent) 7%, var(--bg-paper));
  stroke: color-mix(in oklab, var(--accent) 60%, transparent);
  stroke-width: 2;
  filter: drop-shadow(0 6px 14px color-mix(in oklab, var(--accent) 25%, transparent));
  transform: translateY(-2px);
}
.cluster-map a:hover .cm-hex-num,
.cluster-map a:hover .cm-hex-label,
.cluster-map a:focus-visible .cm-hex-num,
.cluster-map a:focus-visible .cm-hex-label { fill: var(--accent-text); }
.cluster-map a { outline: none; -webkit-tap-highlight-color: transparent; }
.cluster-map a:focus-visible .cm-hex { stroke-width: 2.5; }
/* Connector — slightly accent-tinted dashed line so it reads as a
   glowing tether to the engine, not a stray hair. */
.cm-connector {
  stroke: color-mix(in oklab, var(--accent) 28%, var(--hair));
  stroke-width: 1.4;
  stroke-dasharray: 4 6;
  fill: none;
  opacity: 0.7;
}
/* Centre node — bigger, with an accent halo so the engine reads as the
   undisputed gravity centre of the constellation. */
.cm-center {
  fill: var(--ink);
  stroke: var(--accent);
  stroke-width: 3;
  filter: drop-shadow(0 8px 26px color-mix(in oklab, var(--accent) 40%, transparent));
}
.cm-center-label {
  font: 700 13px var(--f-display); fill: var(--paper);
  letter-spacing: -0.005em;
  text-anchor: middle; dominant-baseline: central;
  pointer-events: none;
}

/* Optional ambient drift on the connectors (very subtle). */
@keyframes cm-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 0.95; }
}
.cm-connector { animation: cm-pulse 4s ease-in-out infinite; }
.cm-connector:nth-child(2) { animation-delay: 0.6s; }
.cm-connector:nth-child(3) { animation-delay: 1.2s; }
.cm-connector:nth-child(4) { animation-delay: 1.8s; }
.cm-connector:nth-child(5) { animation-delay: 2.4s; }
.cm-connector:nth-child(6) { animation-delay: 3.0s; }
@media (prefers-reduced-motion: reduce) {
  .cm-connector { animation: none; opacity: 0.6; }
  .cluster-map a:hover .cm-hex,
  .cluster-map a:focus-visible .cm-hex { transform: none; }
}

/* Mobile fallback: collapse hex-constellation to a 2×3 chip grid */
.cm-fallback { display: none; }
@media (max-width: 600px) {
  .cluster-map > svg { display: none; }
  .cm-fallback {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-3);
    width: 100%;
  }
  .cm-fallback a {
    display: flex; flex-direction: column; gap: 2px;
    padding: var(--s-3) var(--s-4);
    background: var(--bg-paper);
    border: 1px solid var(--hair);
    border-radius: var(--r-md);
    text-decoration: none;
    transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
  }
  .cm-fallback a:hover {
    border-color: var(--accent);
    background: color-mix(in oklab, var(--accent) 6%, var(--bg-paper));
  }
  .cm-fallback .cm-fb-num { font: 600 10px/1 var(--f-mono); color: var(--fg-faint); }
  .cm-fallback .cm-fb-label { font: 600 13px/1.2 var(--f-display); color: var(--fg); }
  .cm-fallback a:hover .cm-fb-num,
  .cm-fallback a:hover .cm-fb-label { color: var(--accent-text); }
}

/* ── 16.5 COUNTER RAIL ───────────────────────────────────────
   Vertical 01–05 numbered circles for the /why-magicblocks hero.
   IntersectionObserver-driven active state.
   ─────────────────────────────────────────────────────────── */
.counter-rail {
  display: inline-flex;
  flex-direction: column;
  gap: 0;
  padding: var(--s-2) 0;
  position: relative;
}
.counter-rail::before {
  content: "";
  position: absolute;
  /* Line passes through the CENTRE of each .cr-num circle.
     Centre x = link padding-left (8px) + circle radius (16px) = 24px. */
  left: 24px;
  top: 20px; bottom: 20px;
  width: 1px;
  background: var(--hair);
  z-index: 0;
}
.counter-rail ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--s-3);
  position: relative; z-index: 1;
}
.counter-rail a {
  display: inline-flex; align-items: center; gap: var(--s-3);
  padding: 4px 8px;
  text-decoration: none;
  border-radius: var(--r-sm);
  transition: background var(--dur-2) var(--ease);
}
.counter-rail a:hover { background: var(--hair-soft); }
.counter-rail a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.cr-num {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  display: inline-flex; align-items: center; justify-content: center;
  font: 500 13px/1 var(--f-mono);
  color: var(--fg);
  flex-shrink: 0;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease), box-shadow var(--dur-3) var(--ease);
  position: relative;
  z-index: 1;
}
.cr-label {
  font: 500 13px/1.2 var(--f-body);
  color: var(--fg-soft);
  white-space: nowrap;
  transition: color var(--dur-2) var(--ease);
}
.counter-rail a:hover .cr-num { border-color: color-mix(in oklab, var(--accent) 40%, transparent); }
.counter-rail a:hover .cr-label { color: var(--fg); }
/* Active state — current section is in the viewport */
.counter-rail a[aria-current="location"] .cr-num {
  background: var(--accent);
  color: var(--paper);
  border-color: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in oklab, var(--accent) 18%, transparent);
  animation: cr-shimmer 2.4s ease-in-out infinite;
}
.counter-rail a[aria-current="location"] .cr-label { color: var(--fg); font-weight: 600; }
@keyframes cr-shimmer {
  0%, 100% { box-shadow: 0 0 0 4px color-mix(in oklab, var(--accent) 18%, transparent); }
  50%      { box-shadow: 0 0 0 6px color-mix(in oklab, var(--accent) 8%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .counter-rail a[aria-current="location"] .cr-num { animation: none; }
}

/* ── EXTRA-NARROW VIEWPORT POLISH (≤ 380px) for chapter 16 components ── */
@media (max-width: 380px) {
  /* Feature cluster (16.1) */
  .fc-card { padding: var(--s-4); }
  .fc-card-name { font-size: 15px; }
  .fc-card-claim { font-size: 13px; }
  .fc-card-proof { font-size: 12px; }
  .fc-h2 { font-size: 23px; }
  .fc-subhed { font-size: 14px; }

  /* Contrast pair (16.2) */
  .cp-panel { padding: var(--s-4); min-height: 0; }
  .cp-panel-title { font-size: 17px; }
  .cp-panel-bullets li { font-size: 13px; }
  .cp-h2 { font-size: 22px; }
  .cp-body p { font-size: 14.5px; }

  /* Feature table (16.3) — already collapsed to card-per-row. */
  .feature-table tbody th,
  .feature-table tbody td { padding: 10px 14px; font-size: 13px; }

  /* Cluster map (16.4) — chip grid already; just tighten padding */
  .cm-fallback a { padding: var(--s-2) var(--s-3); }
  .cm-fallback .cm-fb-label { font-size: 12px; }

  /* Counter rail (16.5) — labels can wrap on tiny widths; allow it */
  .cr-label { white-space: normal; line-height: 1.25; }
  .counter-rail a { gap: var(--s-2); }
}

/* ─────────────────────────── Chapter 09 — Content blocks ─────────────── */
/* Verbatim migration of the chapter-private component CSS so the Hero,
   MarketingFeatureGrid, LogoWall, TestimonialStrip, CtaBlock, StatsStrip,
   Faq, ComparisonTable, TeamGrid, PullQuote, SiteFooter, CustomerLogoGrid,
   PressStrip, IntegrationGrid, and FounderGrid classes ship through
   @magicblocksai/css too.

   Collision notes:
   • Chapter 05 already owns `.feat-grid` (auto-fill minmax) and `.feat-title`
     for the home-page feature-card grid. Chapter 09's marketing feature
     section uses a fixed 3-column shape — RENAMED its whole namespace to
     `.mfg-*` (marketing feature grid) so the two co-exist.
   • `.is-ours` already lives under `.compare` here AND under `.feature-table`
     in chapter 16. Both are properly scoped — no collision.
   • `.stats` is chapter 09's hero numbers band; chapter 05's `.stat-grid` /
     `.stat-card` is a distinct dashboard-tile family — no collision. */

/* ── 9.1 .hero — marketing hero ──────────────────────────────
   Pinned warm cream surface in BOTH themes (rescopes type tokens to ink so
   copy stays legible under data-theme="dark"). Pink + peach radial blooms,
   eyebrow pill, Fraunces-italic accent on the title. */
.hero {
  position: relative;
  padding: var(--s-11) var(--s-6);
  background: var(--warm-3);
  border-radius: var(--r-xl);
  overflow: hidden;
  isolation: isolate;
  /* pinned warm surface — rescope type tokens to ink so copy stays legible in dark */
  --fg:      var(--ink);
  --fg-soft: color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:  color-mix(in oklab, var(--ink) 48%, transparent);
  --hair:    rgba(25, 30, 50, 0.09);
  color: var(--fg);
}
.hero-bloom {
  position: absolute; inset: 0;
  background:
    radial-gradient(600px 400px at 80% 20%, color-mix(in oklab, var(--accent) 20%, transparent), transparent 60%),
    radial-gradient(500px 380px at 10% 90%, color-mix(in oklab, #FFC6A5 60%, transparent), transparent 65%);
  pointer-events: none;
  z-index: -1;
}
.hero-inner { max-width: min(960px, 100%); }
.hero-eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 5px 12px 5px 10px;
  /* Always-white pill so it reads on the pinned-cream hero in BOTH themes.
     --bg-paper would flip to dark navy in dark and collapse with the
     ink-rescoped text colour above (dark pill + ink text = invisible). */
  background: var(--paper);
  border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent);
  border-radius: var(--r-pill);
  font: 500 12px/1 var(--f-mono);
  color: var(--ink);
  letter-spacing: 0.02em;
  margin-bottom: var(--s-5);
}
.hero-eyebrow-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.hero-title {
  font: 600 clamp(40px, 5.4vw, 64px)/1.03 var(--f-display);
  letter-spacing: -0.025em;
  color: var(--fg);
  margin: 0 0 var(--s-5);
  text-wrap: balance;
}
.hero-title em {
  font-family: var(--f-italic); font-style: italic; font-weight: 400;
  color: var(--accent-text); font-variation-settings: "SOFT" 80;
  /* Keep the emphasised phrase together — without this, "human-feeling"
     breaks at the hyphen and lays out as "human-" / "feeling". With nowrap,
     the natural break now lands BEFORE the italic phrase instead. */
  white-space: nowrap;
}
.hero-lede {
  font: 400 19px/1.55 var(--f-body);
  color: var(--fg-soft);
  margin: 0 0 var(--s-6);
  max-width: 560px;
}
.hero-actions { display: flex; gap: var(--s-4); align-items: center; flex-wrap: wrap; margin-bottom: var(--s-6); }
.hero-cta {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent); color: var(--paper);
  font: 600 15px/1 var(--f-display);
  padding: 14px 22px;
  border-radius: var(--r-pill);
  text-decoration: none;
  box-shadow: var(--sh-pink);
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.hero-cta:hover { transform: translateY(-2px); color: var(--paper); box-shadow: 0 12px 28px color-mix(in oklab, var(--accent) 45%, transparent); }
.hero-link {
  color: var(--fg); text-decoration: none;
  font: 500 14.5px/1 var(--f-body);
  padding: 10px 4px;
  border-bottom: 1px solid currentColor;
}
.hero-link:hover { color: var(--accent-text); }
.hero-meta { display: flex; align-items: center; gap: var(--s-3); }
.hero-avs { display: inline-flex; }
.hero-avs .av { margin-left: -6px; box-shadow: 0 0 0 2px var(--warm-3); }
.hero-avs .av:first-child { margin-left: 0; }
.hero-meta-copy { font: 400 13.5px/1.5 var(--f-body); color: var(--fg-soft); }
.hero-meta-copy strong { color: var(--fg); font-weight: 600; }

/* ── 9.2 .mfg — marketing feature grid (3-up) ────────────────
   RENAMED from `.feat-*` to `.mfg-*` so it co-exists with chapter 05's
   home-page `.feat-grid` / `.feat-card` (auto-fill minmax) family. Same
   visual recipe: centred header + grid of paper cards with coloured icon
   chips that rotate through pink → blue → green → amber → purple → ink. */
.mfg { padding: var(--s-9) 0; }
.mfg-head { text-align: center; margin: 0 auto var(--s-8); max-width: 640px; }
.mfg-eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent-text); font-weight: 600; margin: 0 0 var(--s-3); }
.mfg-title { font: 600 clamp(28px, 3.6vw, 40px)/1.15 var(--f-display); letter-spacing: -0.02em; color: var(--fg); margin: 0 0 var(--s-3); }
.mfg-lede { font: 400 17px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }
.mfg-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-5); }
@media (max-width: 880px) { .mfg-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .mfg-grid { grid-template-columns: 1fr; } }
.mfg-item {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.mfg-item:hover { transform: translateY(-2px); box-shadow: var(--sh-2); }
.mfg-ic {
  width: 42px; height: 42px; border-radius: var(--r-md);
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: var(--s-4);
}
.mfg-ic-pink   { background: var(--accent-soft);  color: var(--accent-text); }
.mfg-ic-blue   { background: var(--info-soft);    color: var(--info-text); }
.mfg-ic-green  { background: var(--success-soft); color: var(--success-text); }
.mfg-ic-amber  { background: var(--warning-soft); color: var(--warning-text); }
.mfg-ic-purple { background: #EFE4FF; color: #5C2CA8; }
.mfg-ic-ink    { background: var(--ink); color: var(--paper); }
.mfg-item h3 { font: 600 17px/1.3 var(--f-display); letter-spacing: -0.01em; color: var(--fg); margin: 0 0 6px; }
.mfg-item p  { font: 400 14.5px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }

/* ── 9.3 .lw — typography logo wall ──────────────────────────
   PINNED white in both themes. The logos in this kit are greyscale
   wordmarks, so a coloured (warm cream) or dark surface dilutes them.
   Token re-scope inside keeps text readable on the pinned white. */
.lw {
  padding: var(--s-7) var(--s-5); text-align: center;
  background: var(--paper);
  border-radius: var(--r-lg);
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
  --fg:        var(--ink);
  --fg-soft:   color-mix(in oklab, var(--ink) 70%, transparent);
  --fg-dim:    color-mix(in oklab, var(--ink) 50%, transparent);
  --fg-faint:  color-mix(in oklab, var(--ink) 35%, transparent);
  --hair:      color-mix(in oklab, var(--ink) 12%, transparent);
  --hair-soft: color-mix(in oklab, var(--ink) 6%, transparent);
  color: var(--fg);
}
.lw-eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--fg-dim); font-weight: 600; margin: 0 0 var(--s-5); }
.lw-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--s-4);
  align-items: center;
}
@media (max-width: 800px) { .lw-grid { grid-template-columns: repeat(3, 1fr); row-gap: var(--s-5); } }
@media (max-width: 440px) { .lw-grid { grid-template-columns: repeat(2, 1fr); } }
.lw-item {
  color: var(--fg); opacity: 0.7;
  display: flex; align-items: center; justify-content: center;
  transition: opacity var(--dur-2) var(--ease);
  line-height: 1;
}
.lw-item:hover { opacity: 1; }

/* ── 9.4 .ts — testimonial strip ─────────────────────────────
   Single hero quote with Fraunces glyph, italicised emphasis phrases in
   pink, author block, and a stat pull-quote on the right. */
.ts {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  padding: var(--s-9) var(--s-7);
  box-shadow: var(--sh-1);
  position: relative;
  overflow: hidden;
}
.ts::before {
  content: ""; position: absolute; top: 0; right: 0;
  width: 320px; height: 320px;
  background: radial-gradient(closest-side, var(--accent-soft), transparent 70%);
  pointer-events: none;
}
.ts-inner { position: relative; max-width: min(960px, 100%); margin: 0 auto; }
.ts-glyph {
  font-family: var(--f-italic); font-style: italic;
  font-size: 88px; line-height: 0.8;
  color: var(--accent-text); font-variation-settings: "SOFT" 80;
  margin-bottom: var(--s-3);
}
.ts-quote {
  font: 400 clamp(22px, 2.6vw, 32px)/1.35 var(--f-display);
  letter-spacing: -0.015em;
  color: var(--fg);
  margin: 0 0 var(--s-6);
}
.ts-quote em {
  font-family: var(--f-italic); font-style: italic; font-weight: 400;
  color: var(--accent-text); font-variation-settings: "SOFT" 80;
}
.ts-cite { display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; }
.ts-name { font: 600 15px/1.2 var(--f-display); color: var(--fg); letter-spacing: -0.005em; }
.ts-role { font: 400 13px/1.3 var(--f-body); color: var(--fg-soft); margin-top: 2px; }
.ts-stat { margin-left: auto; text-align: right; padding-left: var(--s-5); border-left: 1px solid var(--hair); }
.ts-stat-n { font: 600 28px/1 var(--f-display); color: var(--accent); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.ts-stat-l { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-dim); margin-top: 4px; font-weight: 600; }

/* ── 9.5 .ctab — CTA block (warm + ink variants) ─────────────
   `.ctab` is the warm default; add `.ctab-ink` for the dark-mode-pinned
   ink variant. Both pin their token re-scope so dark-mode copy stays legible. */
.ctab {
  position: relative;
  padding: var(--s-9) var(--s-7);
  background: var(--warm-3);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  overflow: hidden;
  isolation: isolate;
  /* pinned warm — rescope type tokens so dark-mode copy is readable */
  --fg:      var(--ink);
  --fg-soft: color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:  color-mix(in oklab, var(--ink) 48%, transparent);
  --hair:    rgba(25, 30, 50, 0.09);
  color: var(--fg);
}
.ctab-bloom {
  position: absolute; inset: 0;
  background: radial-gradient(700px 380px at 80% 0%, color-mix(in oklab, var(--accent) 22%, transparent), transparent 65%);
  z-index: -1;
}
.ctab-inner { max-width: min(880px, 100%); }
.ctab-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font: 500 11.5px/1 var(--f-mono);
  color: var(--fg-dim);
  text-transform: uppercase; letter-spacing: 0.1em;
  margin: 0 0 var(--s-4);
}
.ctab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.ctab-title { font: 600 clamp(30px, 4vw, 46px)/1.1 var(--f-display); letter-spacing: -0.02em; color: var(--fg); margin: 0 0 var(--s-4); }
.ctab-title em { font-family: var(--f-italic); font-style: italic; font-weight: 400; color: var(--accent); font-variation-settings: "SOFT" 80; }
.ctab-lede { font: 400 17px/1.5 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-6); }
.ctab-actions { display: flex; gap: var(--s-4); align-items: center; flex-wrap: wrap; }
.ctab-cta {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent); color: var(--paper);
  font: 600 15px/1 var(--f-display);
  padding: 14px 22px;
  border-radius: var(--r-pill);
  text-decoration: none;
  box-shadow: var(--sh-pink);
  transition: transform var(--dur-2) var(--ease);
}
.ctab-cta:hover { transform: translateY(-2px); color: var(--paper); }
.ctab-link { color: var(--fg); text-decoration: none; font: 500 14.5px/1 var(--f-body); border-bottom: 1px solid currentColor; padding: 6px 2px; }
.ctab-link:hover { color: var(--accent-text); }

.ctab-ink {
  background: var(--ink); border-color: var(--ink);
  /* pinned ink — flip type tokens to paper so copy reads on the dark surface */
  --fg:      var(--paper);
  --fg-soft: color-mix(in oklab, var(--paper) 72%, transparent);
  --fg-dim:  color-mix(in oklab, var(--paper) 55%, transparent);
  --hair:    rgba(244, 236, 228, 0.14);
  color: var(--fg);
}
.ctab-ink .ctab-title { color: var(--fg); }
.ctab-ink .ctab-lede  { color: var(--fg-soft); }
.ctab-ink .ctab-link  { color: var(--fg-soft); }
.ctab-ink .ctab-link:hover { color: var(--accent-text); }

/* ── 9.6 .stats — stats strip ────────────────────────────────
   3–4 big numbers in display 600, units in pink, mono labels. Distinct
   from chapter 05's `.stat-grid` / `.stat-card` family (dashboard tiles). */
.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
}
@media (max-width: 720px) { .stats { grid-template-columns: repeat(2, 1fr); } }
.stats-item { background: var(--bg-paper); padding: var(--s-6) var(--s-5); text-align: left; }
.stats-n {
  font: 600 44px/1 var(--f-display);
  letter-spacing: -0.02em;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
  margin-bottom: 8px;
}
.stats-u { color: var(--accent-text); font-size: 28px; margin-left: 2px; }
.stats-l { font: 500 12px/1.3 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); }

/* ── 9.7 .faq — accordion FAQ ────────────────────────────────
   Uses native <details> / <summary> — no JS required. Hand-built + marker
   rotates 45° to × on open. */
.faq { padding: var(--s-9) 0; }
.faq-head { max-width: 520px; margin: 0 0 var(--s-7); }
.faq-eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent-text); font-weight: 600; margin: 0 0 var(--s-3); }
.faq-title { font: 600 clamp(28px, 3.2vw, 36px)/1.2 var(--f-display); letter-spacing: -0.02em; color: var(--fg); margin: 0; }
.faq-list {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.faq-item { border-bottom: 1px solid var(--hair-soft); }
.faq-item:last-child { border-bottom: 0; }
.faq-item summary {
  padding: var(--s-5);
  font: 600 16px/1.3 var(--f-display);
  letter-spacing: -0.005em;
  color: var(--fg);
  cursor: pointer;
  list-style: none;
  position: relative;
  padding-right: 56px;
  transition: background var(--dur-2) var(--ease);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  position: absolute; right: var(--s-5); top: 50%;
  transform: translateY(-50%);
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--hair); border-radius: 50%;
  font: 400 18px/1 var(--f-display); color: var(--fg-soft);
  transition: transform var(--dur-2) var(--ease), color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.faq-item[open] summary::after { transform: translateY(-50%) rotate(45deg); color: var(--accent-text); border-color: var(--accent); }
.faq-item summary:hover { background: var(--bg-warm); }
.faq-body { padding: 0 var(--s-5) var(--s-5); }
.faq-body p { font: 400 15px/1.6 var(--f-body); color: var(--fg-soft); margin: 0; max-width: 68ch; }

/* ── 9.8 .compare — comparison table ─────────────────────────
   3-column product comparison. `.is-ours` lifts the MagicBlocks column
   with a success-soft (green) background — positive, not aggressive.
   Co-exists with `.feature-table .is-ours` from chapter 16: both selectors
   are scoped under their respective root, no override. */
.compare { width: 100%; border-collapse: collapse; font: 400 14px/1.4 var(--f-body); margin: 0 auto; }
.compare th, .compare td { padding: var(--s-3) var(--s-4); text-align: center; border-bottom: 1px solid var(--hair); }
.compare thead th { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); padding-top: var(--s-4); padding-bottom: var(--s-4); }
.compare tbody th { text-align: left; font-weight: 500; color: var(--fg); }
.compare .is-ours { background: var(--success-soft); color: var(--success-text); font-weight: 600; }
.compare thead .is-ours { color: var(--success-text); }

/* ── 9.9 .team-grid · .team-card — team grid ─────────────────
   3-up grid of humans: photo, name, role, one-line bio. Square photos. */
.team-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-5); width: 100%; max-width: min(1080px, 100%); margin: 0 auto; }
@media (max-width: 720px) { .team-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .team-grid { grid-template-columns: 1fr; } }
.team-card { padding: var(--s-4); background: var(--bg-paper); border: 1px solid var(--hair); border-radius: var(--r-md); }
.team-photo { aspect-ratio: 1; width: 100%; border-radius: var(--r-sm); margin-bottom: var(--s-3); }
.team-name { font: 700 18px/1.2 var(--f-display); color: var(--fg); margin: 0; }
.team-role { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent-text); margin: var(--s-1) 0 var(--s-2); }
.team-bio  { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }

/* ── 9.10 .pull-quote — full-bleed editorial moment ──────────
   Reserved for the single best line of social proof on a page. */
.pull-quote { max-width: 720px; margin: 0 auto; padding: var(--s-7) var(--s-5); text-align: center; }
.pq-glyph { font: 400 80px/0.6 var(--f-serif); font-style: italic; font-variation-settings: "SOFT" 80; color: var(--accent-text); margin-bottom: var(--s-3); }
.pq-body { font: 500 24px/1.35 var(--f-display); color: var(--fg); text-wrap: balance; margin: 0; }
.pq-body em { font-family: var(--f-serif); font-style: italic; font-variation-settings: "SOFT" 80; color: var(--accent-text); font-weight: 400; }
.pq-cite { font: 500 12px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); margin-top: var(--s-4); }

/* ── 9.11 .mf — site footer (warm + paper variants) ──────────
   One component, two tonal variants. Default is the warm marketing footer
   — bigger, fuller, with social icons. `.mf.is-paper` flips to a paper
   surface for app-embedded or secondary pages — same grid and link
   columns, lighter tone, socials tucked. */
.mf {
  width: 100%;
  background: var(--warm-2);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  padding: var(--s-8) var(--s-7);
  /* pinned warm — rescope type tokens so copy stays legible in dark */
  --fg:      var(--ink);
  --fg-soft: color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:  color-mix(in oklab, var(--ink) 48%, transparent);
  --hair:    rgba(25, 30, 50, 0.09);
  color: var(--fg);
}
/* Paper/app variant — picks up the ambient theme, tucks socials. */
.mf.is-paper {
  background: var(--bg-paper);
  --fg:      initial; --fg-soft: initial; --fg-dim: initial; --hair: initial;
  color: var(--fg);
}
.mf.is-paper .mf-socials { display: none; }
.mf.is-paper .mf-tag { max-width: 34ch; }
.mf-top { display: grid; grid-template-columns: 1.2fr 2.6fr; gap: var(--s-8); margin-bottom: var(--s-7); }
@media (max-width: 780px) { .mf-top { grid-template-columns: 1fr; } }
.mf-brand { display: inline-flex; align-items: center; gap: 10px; font: 700 18px/1 var(--f-display); color: var(--fg); text-decoration: none; letter-spacing: -0.01em; }
.mf-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.mf-tag { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: var(--s-3) 0 var(--s-5); max-width: 32ch; }
.mf-socials { display: flex; gap: 10px; }
.mf-socials a {
  width: 36px; height: 36px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  /* Pinned-white pill so the SVG icon (currentColor=ink) reads in BOTH
     themes — bg-paper would flip dark and collapse with the ink-rescoped
     icon colour. Same fix as the hero eyebrow. */
  background: var(--paper);
  border: 1px solid color-mix(in oklab, var(--ink) 12%, transparent);
  color: var(--ink); text-decoration: none;
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease),
              background var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.mf-socials a svg { width: 16px; height: 16px; display: block; }
.mf-socials a:hover {
  color: var(--paper);
  background: var(--accent);
  border-color: var(--accent);
  transform: translateY(-1px);
}
.mf-cols { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-5); }
@media (max-width: 560px) { .mf-cols { grid-template-columns: repeat(2, 1fr); row-gap: var(--s-5); } }
.mf-cols h5 { font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-dim); margin: 0 0 var(--s-3); }
.mf-cols ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.mf-cols a { color: var(--fg); text-decoration: none; font: 500 14px/1.4 var(--f-body); transition: color var(--dur-1) var(--ease); }
.mf-cols a:hover { color: var(--accent-text); }
.mf-base {
  display: flex; justify-content: space-between; align-items: center;
  padding-top: var(--s-5);
  border-top: 1px solid var(--hair);
  font: 400 12.5px/1.5 var(--f-mono); color: var(--fg-dim);
  flex-wrap: wrap; gap: var(--s-3);
}
.mf-base-links { display: flex; gap: var(--s-5); }
.mf-base-links a { color: var(--fg-dim); text-decoration: none; }
.mf-base-links a:hover { color: var(--accent-text); }

/* ── 9.12 .logo-grid — real customer logo tiles ──────────────
   Companion to the typography-based .lw wordmark grid. Uses actual logo
   images with retina srcset. Grayscale at rest, full colour on hover. */
/* PINNED white container so the greyscale customer logos read identically
   in both themes — they otherwise vanish on dark navy. */
.logo-grid-section {
  padding: var(--s-6) var(--s-5); text-align: center; width: 100%;
  background: var(--paper);
  border-radius: var(--r-lg);
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
  --fg:        var(--ink);
  --fg-soft:   color-mix(in oklab, var(--ink) 70%, transparent);
  --fg-dim:    color-mix(in oklab, var(--ink) 50%, transparent);
  --hair:      color-mix(in oklab, var(--ink) 12%, transparent);
  color: var(--fg);
}
.logo-grid-eyebrow {
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-dim);
  margin: 0 0 var(--s-6);
}
.logo-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--s-6) var(--s-7);
  align-items: center; justify-items: center;
  width: 100%;
  max-width: min(1080px, 100%);
  margin: 0 auto;
}
.logo-grid a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 100%;
}
.logo-grid img {
  max-width: 140px; width: 100%; height: auto;
  opacity: 0.55;
  filter: grayscale(1);
  transition: opacity var(--dur-2) var(--ease),
              filter var(--dur-2) var(--ease);
}
.logo-grid a:hover img,
.logo-grid a:focus-visible img {
  opacity: 1; filter: grayscale(0);
}
.logo-grid a:focus-visible { outline: 0; box-shadow: var(--sh-focus); border-radius: var(--r-xs); }
@media (max-width: 820px) { .logo-grid { grid-template-columns: repeat(3, 1fr); gap: var(--s-5); } }
@media (max-width: 480px) { .logo-grid { grid-template-columns: repeat(2, 1fr); gap: var(--s-4); } }

/* ── 9.12b .customer-logo-wall — industry-grouped variant ────
   Same per-tile treatment as .logo-grid; layout changes from a flat
   5-up to a stacked column of industry-grouped rows. */
.customer-logo-wall {
  display: flex; flex-direction: column;
  gap: var(--s-6);
  width: 100%;
  max-width: min(1080px, 100%);
  margin: 0 auto;
  /* PINNED white surface (both themes) so greyscale customer logos read
     identically on warm or dark pages. Padding gives the row a card feel. */
  background: var(--paper);
  padding: var(--s-6) var(--s-5);
  border-radius: var(--r-lg);
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
  --fg:        var(--ink);
  --fg-soft:   color-mix(in oklab, var(--ink) 70%, transparent);
  --fg-dim:    color-mix(in oklab, var(--ink) 50%, transparent);
  --hair:      color-mix(in oklab, var(--ink) 12%, transparent);
  --hair-soft: color-mix(in oklab, var(--ink) 6%, transparent);
  color: var(--fg);
}
.cw-eyebrow {
  font: 600 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-dim);
  margin: 0;
}
.cw-group { display: flex; flex-direction: column; gap: var(--s-3); }
.cw-group-name {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-soft);
  margin: 0;
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--hair);
}
.cw-row {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-5) var(--s-7);
  padding: var(--s-2) 0;
}
.cw-row a { display: inline-flex; align-items: center; }
.cw-row img {
  max-width: 140px; height: auto;
  opacity: 0.6;
  filter: grayscale(1);
  transition: opacity var(--dur-2) var(--ease),
              filter var(--dur-2) var(--ease);
}
.cw-row a:hover img,
.cw-row a:focus-visible img { opacity: 1; filter: grayscale(0); }
.cw-row a:focus-visible { outline: 0; box-shadow: var(--sh-focus); border-radius: var(--r-xs); }
@media (max-width: 480px) {
  .cw-row { gap: var(--s-4); justify-content: center; }
  .cw-row img { max-width: 100px; }
}

/* ── 9.13 .press-strip — "as seen in" row ────────────────────
   Pinned-white surface in both themes; press marks here are greyscale. */
.press-strip {
  text-align: center; width: 100%;
  background: var(--paper);
  padding: var(--s-6) var(--s-5);
  border-radius: var(--r-lg);
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
  --fg:        var(--ink);
  --fg-soft:   color-mix(in oklab, var(--ink) 70%, transparent);
  --fg-dim:    color-mix(in oklab, var(--ink) 50%, transparent);
  --hair:      color-mix(in oklab, var(--ink) 12%, transparent);
  color: var(--fg);
}
.press-strip-eyebrow {
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-dim);
  margin: 0 0 var(--s-5);
}
.press-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--s-5) var(--s-6);
  max-width: min(1080px, 100%);
  margin: 0 auto;
}
.press-row img {
  max-width: 110px; height: auto;
  opacity: 0.55;
  filter: grayscale(1);
  transition: opacity var(--dur-2) var(--ease),
              filter var(--dur-2) var(--ease);
}
.press-row a { display: inline-flex; }
.press-row a:hover img,
.press-row a:focus-visible img { opacity: 1; filter: grayscale(0); }
.press-row a:focus-visible { outline: 0; box-shadow: var(--sh-focus); border-radius: var(--r-xs); }

/* ── 9.14 .integration-grid — square integration tiles ───────
   Tile layout for third-party integrations. Each tile hosts the
   integration's icon and a mono label. Hover: accent border + lift. */
.integration-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--s-3);
  width: 100%;
  max-width: min(720px, 100%);
  margin: 0 auto;
}
.integration-tile {
  aspect-ratio: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-2);
  padding: var(--s-4);
  /* PINNED white in both themes (via var(--paper)) — third-party logos
     are full-colour or greyscale and need a stable pale ground. Token
     re-scope keeps the mono label legible. */
  background: var(--paper);
  border: 1px solid color-mix(in oklab, var(--ink) 12%, transparent);
  border-radius: var(--r-md);
  text-decoration: none;
  --fg:        var(--ink);
  --fg-soft:   color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:    color-mix(in oklab, var(--ink) 50%, transparent);
  --hair:      color-mix(in oklab, var(--ink) 12%, transparent);
  color: var(--fg);
  transition: border-color var(--dur-2) var(--ease),
              transform var(--dur-2) var(--ease),
              box-shadow var(--dur-2) var(--ease);
}
.integration-tile:hover {
  border-color: color-mix(in oklab, var(--accent) 40%, var(--hair));
  transform: translateY(-2px);
  box-shadow: var(--sh-2);
}
.integration-tile:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.integration-tile img {
  width: 48px; height: 48px;
  object-fit: contain;
}
.integration-tile .label {
  font: 500 11px/1 var(--f-mono);
  color: var(--fg-soft);
  letter-spacing: 0.04em;
  text-align: center;
}
@media (max-width: 640px) { .integration-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 420px) { .integration-grid { grid-template-columns: repeat(2, 1fr); } }

/* ── 9.14b .integration-category-grid — category-grouped wrap ──
   Same tile pattern, organised under category headers. Adds a
   .is-coming-soon hatched-tile state for roadmap tiles. */
.integration-category-grid {
  display: flex; flex-direction: column;
  gap: var(--s-6);
  width: 100%;
  max-width: min(720px, 100%);
  margin: 0 auto;
}
.icg-group { display: flex; flex-direction: column; gap: var(--s-3); }
.icg-group-name {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-soft);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--hair);
  margin: 0;
}
.icg-group .integration-grid { max-width: 100%; }
.integration-tile.is-coming-soon {
  cursor: default;
  background:
    repeating-linear-gradient(45deg,
      var(--bg-paper), var(--bg-paper) 6px,
      var(--bg-sunk)  6px, var(--bg-sunk)  12px);
  color: var(--fg-dim);
  border-style: dashed;
}
.integration-tile.is-coming-soon:hover {
  transform: none;
  border-color: var(--hair);
  box-shadow: none;
}
.integration-tile.is-coming-soon .label::after {
  content: " · soon";
  opacity: 0.6;
  letter-spacing: 0.04em;
}

/* ── 9.15 .founder-grid · .founder-card — 2-up founder tiles ──
   Richer variant of .team-card for founders specifically. Square
   headshot, larger name, role in mono-accent, bio + optional social
   links. Two-up on desktop, single column on mobile. */
.founder-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-6);
  width: 100%;
  max-width: min(720px, 100%);
  margin: 0 auto;
}
@media (max-width: 640px) { .founder-grid { grid-template-columns: 1fr; gap: var(--s-5); } }
.founder-card {
  display: flex; flex-direction: column; gap: var(--s-3);
  padding: var(--s-5);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  text-align: center;
}
.founder-photo {
  width: 100%; aspect-ratio: 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg-sunk);
}
.founder-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.founder-name {
  font: 600 20px/1.2 var(--f-display);
  letter-spacing: -0.01em;
  color: var(--fg);
  margin: 0;
}
.founder-role {
  font: 500 11.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--accent-text);
}
.founder-bio {
  font: 400 14px/1.55 var(--f-body);
  color: var(--fg-soft);
  margin: 0;
}
.founder-links {
  display: inline-flex; gap: var(--s-3); justify-content: center;
  margin-top: var(--s-2);
}
.founder-links a {
  font: 500 12px/1 var(--f-mono);
  color: var(--fg-dim);
  text-decoration: none;
  letter-spacing: 0.04em;
  padding: 4px 8px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  transition: color var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease);
}
.founder-links a:hover { color: var(--accent-text); border-color: var(--accent); }

/* ─────────────────────────── Chapter 12 — Media & presentation ───────── */
/* Verbatim migration of chapter-12 component CSS. */

/* ──────────────────────────────── 12.1 .vid-player */
/* HTML5 video with branded chrome. Controls overlay the video from the bottom
   and fade in on hover/focus. Keyboard: Space = play/pause, ← → = ±10s,
   ↑↓ = volume, F = fullscreen, M = mute. Poster shows until first play. */
.vid-player {
  position: relative;
  width: 100%; max-width: min(1080px, 100%);
  aspect-ratio: 16/9;
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  box-shadow: var(--sh-3);
}
.vid-player video,
.vid-player .vid-surface {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  background: var(--ink);
}
.vid-player .vid-surface {
  /* Placeholder surface when no <video> is used — shows poster-style art. */
  background:
    radial-gradient(70% 70% at 80% 20%, color-mix(in oklab, var(--accent) 30%, transparent), transparent 70%),
    radial-gradient(60% 80% at 20% 80%, color-mix(in oklab, var(--blue-500) 25%, transparent), transparent 70%),
    var(--ink);
  display: flex; align-items: center; justify-content: center;
}
.vid-player .vid-surface .plate {
  font: 600 12px/1 var(--f-mono);
  letter-spacing: 0.2em; text-transform: uppercase;
  color: color-mix(in oklab, var(--paper) 55%, transparent);
}
.vid-player .vid-center {
  position: absolute; inset: 0; z-index: 3;
  display: grid; place-items: center;
  cursor: pointer;
}
.vid-player .vid-center .vid-play {
  width: 88px; height: 88px; border-radius: 50%;
  background: var(--accent); color: var(--paper);
  border: 0;
  display: inline-grid; place-items: center;
  cursor: pointer;
  box-shadow: 0 20px 48px -16px color-mix(in oklab, var(--accent) 60%, transparent);
  transition: transform var(--dur-2) var(--ease);
}
.vid-player .vid-center .vid-play:hover { transform: scale(1.06); }
/* Triangle is 44px (~50% of the 88px button). No left/right offset —
   the SVG path's centroid sits at viewBox x=11.67 (just left of the
   12 viewBox centre), so a naturally-centred SVG already lands the
   triangle's visual centre of mass at the button centre. */
.vid-player .vid-center .vid-play svg { width: 44px; height: 44px; }
.vid-player.is-playing .vid-center { opacity: 0; pointer-events: none; }

.vid-player .vid-ctrls {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 4;
  padding: 48px 20px 18px;
  background: linear-gradient(to top, rgba(14,17,30,0.72), rgba(14,17,30,0));
  display: grid;
  grid-template-columns: auto 1fr auto auto auto;
  align-items: center;
  gap: var(--s-3);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
  pointer-events: none;
}
.vid-player:hover .vid-ctrls,
.vid-player:focus-within .vid-ctrls,
.vid-player.is-paused .vid-ctrls { opacity: 1; pointer-events: auto; }

.vid-player .vid-ctrls button {
  appearance: none; -webkit-appearance: none;
  background: transparent; border: 0; color: var(--paper);
  width: 36px; height: 36px;
  border-radius: 50%;
  display: inline-grid; place-items: center;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease);
}
.vid-player .vid-ctrls button:hover { background: rgba(255,255,255,0.14); }
.vid-player .vid-ctrls button svg { width: 20px; height: 20px; }
.vid-player .vid-ctrls .vid-time {
  font: 500 12px/1 var(--f-mono);
  color: color-mix(in oklab, var(--paper) 85%, transparent);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

/* scrubber — reuse the range-slider pattern but inverted palette */
.vid-player .vid-bar {
  position: relative; height: 20px;
  display: flex; align-items: center;
}
.vid-player .vid-bar input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 4px; margin: 0;
  background: transparent;
  cursor: pointer;
}
.vid-player .vid-bar input[type="range"]::-webkit-slider-runnable-track {
  height: 4px; border-radius: 4px;
  background: linear-gradient(to right,
    var(--accent) 0%,
    var(--accent) calc(var(--vp, 0) * 1%),
    rgba(255,255,255,0.22) calc(var(--vp, 0) * 1%),
    rgba(255,255,255,0.22) 100%);
}
.vid-player .vid-bar input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--paper);
  margin-top: -5px;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 50%, transparent);
  transition: transform var(--dur-1) var(--ease);
}
.vid-player .vid-bar input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.2); }
.vid-player .vid-bar input[type="range"]::-moz-range-track  { height: 4px; border-radius: 4px; background: rgba(255,255,255,0.22); }
.vid-player .vid-bar input[type="range"]::-moz-range-progress { height: 4px; border-radius: 4px; background: var(--accent); }
.vid-player .vid-bar input[type="range"]::-moz-range-thumb  { width: 14px; height: 14px; border-radius: 50%; background: var(--paper); border: 0; box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 50%, transparent); }

/* Volume group (mute button + inline slider). Slider fill uses --vv (0–100). */
.vid-player .vid-vol { display: inline-flex; align-items: center; gap: 4px; }
.vid-player .vid-vol input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 72px; height: 4px; margin: 0;
  background: transparent; cursor: pointer;
}
.vid-player .vid-vol input[type="range"]::-webkit-slider-runnable-track {
  height: 4px; border-radius: 4px;
  background: linear-gradient(to right,
    var(--paper) 0%,
    var(--paper) calc(var(--vv, 100) * 1%),
    rgba(255,255,255,0.22) calc(var(--vv, 100) * 1%),
    rgba(255,255,255,0.22) 100%);
}
.vid-player .vid-vol input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--paper); margin-top: -4px;
  transition: transform var(--dur-1) var(--ease);
}
.vid-player .vid-vol input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.2); }
.vid-player .vid-vol input[type="range"]::-moz-range-track  { height: 4px; border-radius: 4px; background: rgba(255,255,255,0.22); }
.vid-player .vid-vol input[type="range"]::-moz-range-progress { height: 4px; border-radius: 4px; background: var(--paper); }
.vid-player .vid-vol input[type="range"]::-moz-range-thumb  { width: 12px; height: 12px; border-radius: 50%; background: var(--paper); border: 0; }

/* Dual-icon swap: play ⇄ pause on the toolbar toggle, speaker ⇄ mute on the vol button.
   Keeps DOM stable (no innerHTML thrash) and gives predictable aria + hover behaviour. */
.vid-player [data-vid-toggle] .ic-pause,
.vid-player [data-vid-mute]   .ic-mute { display: none; }
.vid-player.is-playing [data-vid-toggle] .ic-play  { display: none; }
.vid-player.is-playing [data-vid-toggle] .ic-pause { display: inline-block; }
.vid-player.is-muted   [data-vid-mute]   .ic-vol   { display: none; }
.vid-player.is-muted   [data-vid-mute]   .ic-mute  { display: inline-block; }

/* When a real <video> is present inside the player, the poster-style surface
   should step out of the way (JS adds .has-media once the player is wired). */
.vid-player.has-media .vid-surface { display: none; }

/* Narrow screens: hide the volume slider to save space (mute button stays). */
@media (max-width: 560px) {
  .vid-player .vid-vol input[type="range"] { display: none; }
  .vid-player .vid-ctrls { gap: var(--s-2); padding: 44px 12px 12px; }
  .vid-player .vid-ctrls .vid-time { font-size: 11px; }
}

/* ──────────────────────────────── 12.2 .carousel */
.carousel {
  position: relative;
  width: 100%; max-width: 960px;
}
.carousel-track {
  display: flex;
  gap: var(--s-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding: 4px 0 16px;
  scrollbar-width: none;  /* Firefox */
}
.carousel-track::-webkit-scrollbar { display: none; }  /* Chrome/Safari */
.carousel-slide {
  flex: 0 0 85%;
  scroll-snap-align: start;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  display: flex; flex-direction: column; gap: var(--s-3);
  min-height: 220px;
}
@media (min-width: 640px) { .carousel-slide { flex-basis: 420px; } }
.carousel-slide .eyebrow {
  font: 600 10.5px/1 var(--f-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-text);
}
.carousel-slide h4 {
  font: 600 22px/1.2 var(--f-display); margin: 0; letter-spacing: -0.01em;
}
.carousel-slide p { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }

.carousel-nav {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: var(--s-3);
}
.carousel-dots {
  display: flex; gap: 6px; align-items: center;
}
.carousel-dots button {
  appearance: none; -webkit-appearance: none;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--hair); border: 0; padding: 0;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease), width var(--dur-2) var(--ease);
}
.carousel-dots button.is-active {
  background: var(--accent);
  width: 22px; border-radius: 4px;
}
.carousel-arrows { display: inline-flex; gap: 6px; }
.carousel-arrows button {
  appearance: none; -webkit-appearance: none;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--bg-paper); border: 1px solid var(--hair);
  color: var(--fg); cursor: pointer;
  display: inline-grid; place-items: center;
  transition: border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
}
.carousel-arrows button:hover { border-color: var(--accent); color: var(--accent-text); transform: translateY(-1px); }
.carousel-arrows button:disabled { opacity: 0.35; cursor: not-allowed; transform: none; }
.carousel-arrows button svg { width: 18px; height: 18px; }

/* ──────────────────────────────── 12.3–12.5 .device frames */
.device {
  --device-bezel: #0c0f18;
  --device-screen: var(--bg-paper);
  position: relative;
  display: block;
  width: 100%;
  color: var(--fg);
}
.device-viewport {
  position: relative;
  overflow: hidden;
  background: var(--device-screen);
}

/* browser */
.device.browser {
  max-width: 960px;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-paper);
  box-shadow: var(--sh-3);
}
.device.browser .chrome {
  display: flex; align-items: center; gap: 14px;
  padding: 10px 14px;
  background: var(--warm-5);
  border-bottom: 1px solid var(--hair);
}
.device.browser .dots { display: flex; gap: 7px; flex: 0 0 auto; }
.device.browser .dots span {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--hair);
}
.device.browser .dots span:nth-child(1) { background: #F47B6D; }
.device.browser .dots span:nth-child(2) { background: #F9C33E; }
.device.browser .dots span:nth-child(3) { background: #47DDB2; }
.device.browser .url {
  flex: 1 1 auto;
  max-width: 520px;
  height: 28px; border-radius: 999px;
  background: var(--bg-paper); border: 1px solid var(--hair);
  display: inline-flex; align-items: center; gap: 8px;
  padding: 0 12px;
  font: 500 12px/1 var(--f-mono); color: var(--fg-soft);
  overflow: hidden;
}
.device.browser .url::before {
  content: ""; width: 12px; height: 12px; flex: 0 0 auto;
  background: currentColor; opacity: 0.6;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='black' d='M18 8h-1V6a5 5 0 0 0-10 0v2H6a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2zm-6 9a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM15 8H9V6a3 3 0 0 1 6 0v2z'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='black' d='M18 8h-1V6a5 5 0 0 0-10 0v2H6a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2zm-6 9a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM15 8H9V6a3 3 0 0 1 6 0v2z'/></svg>") center / contain no-repeat;
}
.device.browser .device-viewport { aspect-ratio: 16 / 10; }

/* laptop */
.device.laptop {
  max-width: 900px;
  margin: 0 auto;
  padding: 18px 18px 0;
  background: var(--device-bezel);
  border-radius: 22px 22px 6px 6px;
  box-shadow: 0 30px 60px -30px rgba(25, 30, 50, 0.45);
  position: relative;
}
.device.laptop::before {
  /* camera pinhole */
  content: "";
  position: absolute; top: 8px; left: 50%;
  width: 6px; height: 6px;
  background: rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  transform: translateX(-50%);
}
.device.laptop .device-viewport {
  aspect-ratio: 16 / 10;
  border-radius: 4px;
}
.device.laptop::after {
  /* lid base — the hinge/keyboard silhouette below the screen */
  content: "";
  display: block;
  height: 14px;
  margin: 0 -32px;
  background: linear-gradient(to bottom,
    var(--device-bezel) 0%,
    var(--device-bezel) 40%,
    color-mix(in oklab, var(--device-bezel) 80%, #888) 100%);
  border-radius: 0 0 22px 22px;
  box-shadow: 0 6px 14px -4px rgba(25, 30, 50, 0.4);
  margin-top: 18px;
}

/* phone */
.device.phone {
  max-width: 340px;
  margin: 0 auto;
  padding: 12px;
  background: var(--device-bezel);
  border-radius: 44px;
  box-shadow: 0 30px 60px -30px rgba(25, 30, 50, 0.45),
              0 0 0 1px rgba(255,255,255,0.08) inset;
  position: relative;
}
.device.phone .device-viewport {
  aspect-ratio: 9 / 19.5;
  border-radius: 34px;
  position: relative;
}
.device.phone .notch {
  position: absolute; z-index: 2;
  top: 10px; left: 50%; transform: translateX(-50%);
  width: 92px; height: 28px; border-radius: 999px;
  background: var(--device-bezel);
}

/* deck device — laptop + built-in slide nav */
.device.laptop.deck .device-viewport {
  background: #0F1221;
  color: var(--paper);
  position: relative;
}
.deck-slides {
  position: relative;
  width: 100%; height: 100%;
}
.deck-slide {
  position: absolute; inset: 0;
  padding: clamp(24px, 4%, 48px);
  display: flex; flex-direction: column; gap: 12px; justify-content: center;
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-3) var(--ease);
}
.deck-slide.is-active { opacity: 1; pointer-events: auto; }
.deck-slide .eyebrow {
  font: 600 10.5px/1 var(--f-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: color-mix(in oklab, var(--accent) 80%, var(--paper));
}
.deck-slide .title {
  font: 600 clamp(22px, 4.2vw, 38px)/1.08 var(--f-display); letter-spacing: -0.02em;
  margin: 0;
}
.deck-slide .title em {
  font-family: var(--f-serif); font-style: italic; font-weight: 400;
  color: var(--accent-text); font-variation-settings: "SOFT" 80;
}
.deck-slide .lede {
  font: 400 clamp(13px, 1.6vw, 16px)/1.55 var(--f-body);
  color: color-mix(in oklab, var(--paper) 75%, transparent);
  max-width: 52ch; margin: 0;
}
.deck-slide .pill-row { display: flex; gap: 8px; flex-wrap: wrap; }
.deck-slide .pill-row span {
  font: 500 11px/1 var(--f-mono); letter-spacing: 0.06em; text-transform: uppercase;
  padding: 7px 12px; border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  color: color-mix(in oklab, var(--paper) 88%, transparent);
}

/* Slide counter pinned to the top-right of the viewport */
.deck-slides .deck-count {
  position: absolute; top: 16px; right: 16px; z-index: 2;
  font: 500 11px/1 var(--f-mono); color: color-mix(in oklab, var(--paper) 60%, transparent);
  font-variant-numeric: tabular-nums; letter-spacing: 0.08em;
}

/* Brand mark pinned to the top-left */
.deck-slides .deck-brand {
  position: absolute; top: 14px; left: 16px; z-index: 2;
  font: 700 14px/1 var(--f-display); color: var(--paper);
  letter-spacing: -0.01em;
}
.deck-slides .deck-brand .dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); margin-right: 6px; vertical-align: middle;
}

/* Bottom controls */
.deck-controls {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 10px 16px;
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  background: linear-gradient(to top, rgba(15,18,33,0.82), rgba(15,18,33,0));
}
.deck-controls .deck-pager {
  display: flex; gap: 6px;
}
.deck-controls .deck-pager button {
  appearance: none; -webkit-appearance: none;
  background: transparent; border: 0; padding: 0;
  width: 22px; height: 4px; border-radius: 4px;
  background: rgba(255,255,255,0.22);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease), width var(--dur-2) var(--ease);
}
.deck-controls .deck-pager button.is-active { background: var(--accent); width: 34px; }

.deck-controls .deck-arrows { display: inline-flex; gap: 6px; }
.deck-controls .deck-arrows button {
  appearance: none; -webkit-appearance: none;
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(255,255,255,0.08); color: var(--paper);
  border: 1px solid rgba(255,255,255,0.14);
  cursor: pointer;
  display: inline-grid; place-items: center;
  transition: background var(--dur-1) var(--ease);
}
.deck-controls .deck-arrows button:hover { background: rgba(255,255,255,0.18); }
.deck-controls .deck-arrows button:disabled { opacity: 0.35; cursor: not-allowed; }
.deck-controls .deck-arrows button svg { width: 16px; height: 16px; }

@media (max-width: 640px) {
  .device.laptop { max-width: 100%; padding: 10px 10px 0; border-radius: 14px 14px 4px 4px; }
  .device.laptop::after { margin: 12px -16px 0; border-radius: 0 0 14px 14px; height: 10px; }
  .device.phone { max-width: 260px; }
  .deck-slide { padding: 20px; }
  .deck-slide .lede { display: none; }
}

/* ─────────────────────────────────────────────────────────────
   12.7 .stage-chat — streaming AI chat + HAPPA stage progress
   Phone-framed live chat that token-streams each message and
   advances a 5-stage track (Hook · Align · Personalise · Pitch
   · Action) as the conversation progresses through each stage.
   Brand-aligned: ink phone body, accent pink user bubbles,
   DM-Sans body + Bricolage display + mono for stage labels. */
.stage-chat {
  width: 100%; max-width: min(460px, 100%);
  margin: 0 auto;
  display: flex; flex-direction: column; gap: var(--s-4);
}
.sc-track {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px;
  padding: 4px;
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-md);
}
.sc-stage {
  font: 600 10.5px/1.2 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  text-align: center; padding: 8px 4px;
  border-radius: var(--r-sm);
  color: var(--fg-dim);
  transition: background var(--dur-2) var(--ease),
              color      var(--dur-2) var(--ease);
}
.sc-stage.is-done   { color: var(--fg); }
.sc-stage.is-active { background: var(--accent-soft); color: var(--accent-text); }

.sc-phone {
  background: var(--ink);
  border-radius: 32px; padding: 10px;
  box-shadow: var(--sh-3);
}
.sc-screen {
  background: var(--warm-3);
  border-radius: 24px; overflow: hidden;
  display: flex; flex-direction: column;
  min-height: 540px; max-height: 560px;
}
.sc-head {
  background: var(--ink); color: var(--paper);
  padding: 12px 16px;
  display: flex; align-items: center; gap: 10px;
}
.sc-head .sc-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent);
  display: grid; place-items: center;
  font: 700 13px/1 var(--f-display); color: var(--paper);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 28%, transparent);
}
.sc-head .sc-name { font: 600 14px/1 var(--f-display); letter-spacing: -0.005em; }
.sc-disc {
  background: color-mix(in oklab, var(--warm-3) 92%, var(--ink));
  color: var(--fg-dim);
  font: 400 10.5px/1.4 var(--f-body);
  padding: 8px 16px;
}

.sc-body {
  flex: 1;
  padding: 12px 14px 8px;
  overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column; gap: 8px;
  scrollbar-width: none;
}
.sc-body::-webkit-scrollbar { display: none; }

.sc-msg {
  display: flex; flex-direction: column;
  animation: sc-slide-in 320ms var(--ease);
}
@keyframes sc-slide-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
.sc-msg.user { align-items: flex-end; }
.sc-bubble {
  max-width: 84%;
  padding: 8px 12px;
  font: 400 13.5px/1.5 var(--f-body);
  border-radius: 14px;
  background: var(--bg-paper); color: var(--fg);
  border: 1px solid var(--hair);
  border-bottom-left-radius: 5px;
  letter-spacing: -0.005em;
  word-wrap: break-word; white-space: pre-wrap;
}
.sc-msg.user .sc-bubble {
  background: var(--accent); color: var(--paper);
  border-color: transparent;
  border-bottom-left-radius: 14px; border-bottom-right-radius: 5px;
  box-shadow: var(--sh-pink);
}

.sc-caret {
  display: inline-block; width: 2px; height: 1em;
  background: currentColor; vertical-align: -2px;
  margin-left: 2px; border-radius: 1px;
  animation: sc-blink 0.85s steps(1) infinite;
}
@keyframes sc-blink { 50% { opacity: 0; } }

.sc-typing {
  align-self: flex-start;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: 12px 12px 12px 5px;
  padding: 10px 12px;
  display: inline-flex; gap: 4px;
}
.sc-typing[hidden] { display: none; }
.sc-typing span {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--fg-dim);
  animation: sc-bp 1.1s infinite;
}
.sc-typing span:nth-child(2) { animation-delay: 0.15s; }
.sc-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes sc-bp {
  0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
  40%           { opacity: 1;   transform: translateY(-3px); }
}

.sc-foot {
  border-top: 1px solid var(--hair);
  padding: 10px 14px 12px;
  background: var(--bg-paper);
}
.sc-composer {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--accent);
  border-radius: var(--r-md);
  padding: 8px 10px;
}
.sc-composer .field {
  flex: 1; min-height: 20px;
  font: 400 13px/1.3 var(--f-body);
  color: var(--fg-soft);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.sc-composer .send {
  background: var(--accent); color: var(--paper);
  border: 0; border-radius: var(--r-sm);
  padding: 6px 12px;
  font: 600 10.5px/1 var(--f-mono);
  letter-spacing: 0.08em; text-transform: uppercase;
  cursor: default; opacity: 0.55;
  transition: opacity var(--dur-2) var(--ease);
}
.sc-composer .send.is-on { opacity: 1; }

.sc-foot-meta {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 8px;
  font: 500 10px/1 var(--f-mono);
  color: var(--fg-dim);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.sc-foot-meta strong { color: var(--accent-text); font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  .sc-caret { animation: none; }
  .sc-typing span { animation: none; opacity: 1; }
  .sc-msg { animation: none; }
}

/* ─────────────────────────────────────────────────────────────
   12.8 .product-dash — animated product dashboard mock
   Browser-framed "inside the product" view: sidebar nav on the
   left, hero title + 4 animated KPI tiles + line chart with
   drawing animation + sweeping points. Loops every ~4.3s with
   values escalating each cycle, giving a "the numbers are going
   up" narrative at a glance. Brand-aligned colours end-to-end. */
.product-dash {
  width: 100%; max-width: min(1080px, 100%);
  margin: 0 auto;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 30px 60px -24px color-mix(in oklab, var(--ink) 50%, transparent);
}

.pd-chrome {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  background: var(--bg-sunk);
  border-bottom: 1px solid var(--hair);
  font: 500 11.5px/1 var(--f-mono);
  color: var(--fg-dim);
}
.pd-chrome .pd-dots { display: flex; gap: 5px; }
.pd-chrome .pd-dots span {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--hair);
}
.pd-chrome .pd-url {
  flex: 1;
  text-align: center;
  padding: 4px 10px;
  background: var(--bg-paper);
  border-radius: var(--r-pill);
  border: 1px solid var(--hair);
  color: var(--fg-soft);
  max-width: 320px; margin: 0 auto;
  letter-spacing: 0.02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.pd-shell {
  display: grid;
  grid-template-columns: 80px 1fr;
  min-height: 480px;
}

.pd-side {
  background: var(--bg-warm);
  border-right: 1px solid var(--hair);
  padding: 14px 8px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.pd-brand {
  width: 32px; height: 32px;
  display: grid; grid-template: 1fr 1fr / 1fr 1fr; gap: 2px;
  margin-bottom: 14px;
}
.pd-brand span { border-radius: 4px; }
.pd-brand span:nth-child(1) { background: var(--yellow-500); }
.pd-brand span:nth-child(2) { background: var(--pink-500); }
.pd-brand span:nth-child(3) { background: var(--blue-500); }
.pd-brand span:nth-child(4) { background: var(--green-500); }
.pd-nav { display: flex; flex-direction: column; gap: 2px; width: 100%; align-items: center; }
.pd-nav-item {
  width: 60px;
  padding: 8px 4px;
  border-radius: var(--r-sm);
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  font: 500 9px/1 var(--f-mono);
  color: var(--fg-dim);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.pd-nav-item svg {
  width: 18px; height: 18px;
  stroke: currentColor; fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.pd-nav-item.is-active {
  background: var(--accent-soft);
  color: var(--accent-text);
}

.pd-main {
  padding: var(--s-5);
  display: flex; flex-direction: column; gap: var(--s-4);
}
.pd-title {
  font: 700 20px/1.1 var(--f-display);
  letter-spacing: -0.02em;
  color: var(--fg);
  margin: 0;
}

.pd-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-3);
}
.pd-kpi {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: 12px 14px;
}
.pd-kpi-label {
  font: 600 10px/1 var(--f-mono);
  color: var(--fg-dim);
  text-transform: uppercase; letter-spacing: 0.1em;
  margin-bottom: 6px;
}
.pd-kpi-value {
  font: 800 20px/1.1 var(--f-display);
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  letter-spacing: -0.02em;
}

.pd-chart-box {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: var(--s-4);
}
.pd-chart-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.pd-chart-title { font: 700 14px/1 var(--f-display); color: var(--fg); }
.pd-legend {
  display: flex; align-items: center; gap: var(--s-4);
  color: var(--fg-dim);
  font: 500 10.5px/1 var(--f-mono);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.pd-legend span { display: inline-flex; align-items: center; gap: 6px; }
.pd-legend .dot { width: 7px; height: 7px; border-radius: 50%; }

.pd-chart {
  position: relative;
  height: 160px;
}
.pd-chart svg { width: 100%; height: 100%; display: block; }
.pd-chart .grid { stroke: var(--hair-soft); stroke-width: 1; stroke-dasharray: 2 4; }
.pd-line {
  fill: none;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-width: 2;
  stroke-dasharray: var(--len);
  stroke-dashoffset: var(--len);
  transition: stroke-dashoffset 1800ms cubic-bezier(0.22, 1, 0.36, 1);
}
.pd-area { opacity: 0; transition: opacity 900ms ease; }
.pd-point { opacity: 0; transform-origin: center; transform-box: fill-box; }

.product-dash.is-drawn .pd-line  { stroke-dashoffset: 0; }
.product-dash.is-drawn .pd-area  { opacity: 0.14; }
.product-dash.is-drawn .pd-point { animation: pd-pop 380ms ease forwards; }
@keyframes pd-pop { from { opacity: 0; transform: scale(0.2); } to { opacity: 1; transform: scale(1); } }

@media (max-width: 820px) {
  .pd-kpis { grid-template-columns: repeat(2, 1fr); }
  .pd-shell { grid-template-columns: 1fr; }
  .pd-side {
    flex-direction: row; overflow-x: auto;
    padding: 10px 14px;
    border-right: 0; border-bottom: 1px solid var(--hair);
    gap: 6px;
  }
  .pd-brand { margin-bottom: 0; margin-right: 8px; flex-shrink: 0; }
  .pd-nav { flex-direction: row; width: auto; }
  .pd-nav-item { flex-shrink: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .pd-line { stroke-dashoffset: 0 !important; transition: none; }
  .pd-area { opacity: 0.14 !important; transition: none; }
  .pd-point { opacity: 1 !important; animation: none; }
}


/* ─────────────────────────── Chapter 11 — Narrative systems ──────────── */
/* Verbatim migration of chapter-11 component CSS. */
/* ============================================================ Chapter 11
   Narrative systems — branded system diagrams + wireframe abstractions
   used across the marketing site. Every component ships with HTML + CSS,
   uses shared brand tokens, and honours prefers-reduced-motion via the
   .reveal / .svg-draw primitives in _shared.css. */

/* shared wrappers */
.ns-stage { min-height: 340px; }
.ns-stage.pad { padding: var(--s-7) var(--s-6); }
.ns-stage.dark {
  background: var(--ink); color: var(--paper);
  --fg: var(--paper); --fg-soft: color-mix(in oklab, var(--paper) 70%, transparent);
  --hair: rgba(244,236,228,0.14);
}

/* ── 11.0 .hero-scene — flagship phone hero ──────────────────
   Animated SMS thread: trigger → personalised outbound → inbound
   tangent → calendar booking. Annotation column on the right reveals
   what the AI knew at each turn. CONTINUOUS LOOP (15.5s cycle: 12.5s
   action + 3s rest on Booked) — starts on load, no scroll gate.
   Reduced-motion renders full state instantly. Token-driven; dark-
   mode safe. */
.hero-scene {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(280px, 340px) minmax(220px, 280px);
  gap: var(--s-7);
  align-items: center;
  justify-content: center;
  max-width: min(780px, 100%);
  margin: 0 auto;
}
@media (max-width: 820px) {
  .hero-scene { grid-template-columns: minmax(260px, 340px); gap: var(--s-5); }
}

/* Phone shell — chapter-scoped (not the chapter-12 .device.phone).
   Purpose-built for hosting a live SMS thread with a pinned trigger
   card at the top and scrollable history below. */
.hs-phone {
  width: 100%; aspect-ratio: 9 / 18;
  background: var(--ink);
  border-radius: 44px;
  padding: 14px;
  box-shadow: var(--sh-3);
  position: relative;
}
.hs-notch {
  position: absolute; top: 18px; left: 50%;
  transform: translateX(-50%);
  width: 92px; height: 18px;
  background: #000;
  border-radius: 12px;
  z-index: 2;
}
.hs-screen {
  width: 100%; height: 100%;
  background: var(--warm-3);
  border-radius: 32px;
  overflow: hidden;
  position: relative;
  display: flex; flex-direction: column;
  padding-top: 40px;          /* clear the notch */
}

/* Pinned trigger strip — intent signal card, stays visible through
   the whole scene. Fades in at T=0. */
.hs-trigger {
  flex-shrink: 0;
  margin: 10px 10px 6px;
  padding: 8px 10px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in oklab, var(--accent) 28%, transparent);
  border-radius: var(--r-sm);
  display: flex; align-items: center; gap: 8px;
  font: 500 10.5px/1.1 var(--f-mono);
  /* Ink text reads cleanly against the soft-pink tint; the accent
     dot + border still carry the pink identity. Pink-on-pink-soft
     was ~2.0:1 contrast — failed AA-normal badly. */
  color: var(--ink);
  opacity: 0; transform: translateY(-4px);
  transition: opacity 400ms var(--ease), transform 400ms var(--ease);
}
.hs-trigger.is-visible { opacity: 1; transform: translateY(0); }
.hs-trigger-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 30%, transparent);
  flex-shrink: 0;
}
.hs-trigger-title { font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
.hs-trigger-sub { color: color-mix(in oklab, var(--ink) 80%, var(--accent)); font-weight: 500; }

/* Thread — scrollable, newest message scrolls into view. */
.hs-thread {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 8px 10px 12px;
  display: flex; flex-direction: column; gap: 6px;
  scrollbar-width: none;
}
.hs-thread::-webkit-scrollbar { display: none; }

/* Message bubbles — start REMOVED FROM FLOW (display:none) until revealed.
   Means the thread fills downward as bubbles arrive instead of pre-
   reserving space for all 9 (which made the conversation overflow the
   phone screen and forced a scroll-to-bottom that clipped m1). */
.hs-msg {
  display: none;
  max-width: 78%;
  padding: 7px 11px;
  font: 400 12.5px/1.4 var(--f-body);
  border-radius: 16px;
  word-wrap: break-word;
}
.hs-msg.is-visible {
  display: block;
  animation: hs-pop 320ms var(--ease) both;
}
@keyframes hs-pop {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.hs-msg.out {
  align-self: flex-end;
  background: var(--accent);
  color: var(--paper);
  border-bottom-right-radius: 5px;
}
.hs-msg.in {
  align-self: flex-start;
  background: var(--bg-paper);
  color: var(--fg);
  border: 1px solid var(--hair);
  border-bottom-left-radius: 5px;
}
.hs-msg-card {
  max-width: 84%;              /* room for the inline calendar chip */
}
.hs-msg-booked {
  background: color-mix(in oklab, var(--success) 85%, var(--accent));
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--success) 45%, transparent);
  font-weight: 500;
}

/* Inline calendar chip — two clickable-looking slots inside the card bubble.
   Was a washed-out pale-pink-on-pink that read as low-contrast mush; now
   each slot is a real tappable card — paper-white pill on the accent
   bubble, with a TODAY/TIME stack so the time hierarchy is obvious. */
.hs-cal-head {
  display: block;
  font-size: 11.5px;
  font-weight: 500;
  margin-bottom: 8px;
  opacity: 0.94;
}
.hs-cal {
  display: flex; gap: 6px;
  margin-top: 0;
}
.hs-cal-slot {
  flex: 1;
  padding: 8px 6px 9px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  font-family: var(--f-mono);
  background: var(--paper);
  color: var(--ink);
  border: 0;
  border-radius: 8px;
  text-align: center;
  letter-spacing: 0.04em;
  cursor: pointer;
  box-shadow: 0 1px 2px color-mix(in oklab, var(--ink) 14%, transparent),
              0 0 0 1px color-mix(in oklab, var(--paper) 60%, var(--accent));
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease);
}
.hs-cal-slot:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px color-mix(in oklab, var(--ink) 22%, transparent),
              0 0 0 1px color-mix(in oklab, var(--paper) 30%, var(--accent));
}
.hs-cal-slot .hs-cal-day {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--ink) 55%, transparent);
}
.hs-cal-slot .hs-cal-time {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Typing indicator — three bouncing dots that appear on MB's side
   (right / out) since MB is the one composing the next message.
   Putting it on the lead's side (left / in) used to read as "the
   lead is typing" which was confusing — they just sent a message. */
.hs-typing {
  align-self: flex-end;
  display: flex; gap: 4px;
  padding: 9px 12px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  /* tail on the bottom-right matches outgoing/MB bubble shape */
  border-radius: 16px 16px 5px 16px;
}
.hs-typing[hidden] { display: none; }
.hs-typing span {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--fg-dim);
  animation: hs-blink 1.2s ease-in-out infinite;
}
.hs-typing span:nth-child(2) { animation-delay: 0.2s; }
.hs-typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes hs-blink { 0%, 60%, 100% { opacity: 0.3; } 30% { opacity: 1; } }

/* Annotation column — context tags revealing what MagicBlocks knew.
   Each tag fades + slides in when its paired outbound message lands. */
.hs-annotations {
  display: flex; flex-direction: column;
  gap: 10px;
}
@media (max-width: 820px) {
  .hs-annotations { flex-direction: row; flex-wrap: wrap; gap: 8px; }
}
.hs-ann {
  padding: 10px 14px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-left: 2px solid var(--accent);
  border-radius: var(--r-sm);
  box-shadow: 0 1px 2px color-mix(in oklab, var(--ink) 5%, transparent);
  display: flex; flex-direction: column; gap: 2px;
  opacity: 0; transform: translateX(8px);
  transition: opacity 360ms var(--ease), transform 360ms var(--ease);
}
@media (max-width: 820px) {
  .hs-ann { flex: 1 1 140px; transform: translateY(6px); }
}
.hs-ann.is-visible { opacity: 1; transform: translate(0); }
.hs-ann-k {
  font: 600 9.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-dim);
}
.hs-ann-v {
  font: 500 13px/1.25 var(--f-display);
  color: var(--fg);
  letter-spacing: -0.005em;
}

@media (prefers-reduced-motion: reduce) {
  .hs-trigger, .hs-msg, .hs-ann {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .hs-typing { display: none !important; }
}

/* ── 11.17 .hero-live-demo — flagship laptop hero ─────────────
   Continuous-loop homepage hero: laptop frame, conversation UI
   inside, response-timer overlay (top-right), status badge
   (bottom-left), industry-scriptable via data-scenario. Mortgage
   is the default because the live-rate numbers make it concrete. */
.hero-live-demo {
  width: 100%;
  max-width: min(900px, 100%);
  margin: 0 auto;
  position: relative;
}
.hld-frame {
  /* mimic .device.laptop (chapter 12) but chapter-scoped for independence */
  padding: 14px 14px 0;
  background: color-mix(in oklab, var(--ink) 95%, #999);
  border-radius: 18px 18px 4px 4px;
  box-shadow: 0 24px 50px -24px color-mix(in oklab, var(--ink) 55%, transparent);
  position: relative;
}
.hld-frame::before {
  content: ""; position: absolute; top: 6px; left: 50%;
  width: 5px; height: 5px; transform: translateX(-50%);
  background: rgba(255,255,255,0.2); border-radius: 50%;
}
.hld-frame::after {
  content: ""; display: block; height: 12px; margin: 14px -26px 0;
  background: linear-gradient(to bottom,
    color-mix(in oklab, var(--ink) 95%, #999),
    color-mix(in oklab, var(--ink) 80%, #888));
  border-radius: 0 0 18px 18px;
}
.hld-screen {
  /* Slightly taller than classic 16:10 so all 8 conversation messages
     fit without scrolling the first one off the top. */
  aspect-ratio: 16 / 11;
  background: var(--bg-paper);
  border-radius: 3px;
  overflow: hidden;
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr;
}
.hld-tabs {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  background: var(--bg-sunk);
  border-bottom: 1px solid var(--hair);
  font: 500 11.5px/1 var(--f-mono);
  color: var(--fg-dim);
}
.hld-tabs .hld-dots { display: flex; gap: 5px; margin-right: 6px; }
.hld-tabs .hld-dots span {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--hair);
}
.hld-tabs .hld-url {
  flex: 1;
  padding: 3px 10px;
  background: var(--bg-paper);
  border-radius: var(--r-pill);
  border: 1px solid var(--hair);
  color: var(--fg-soft);
  letter-spacing: 0.02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hld-app {
  position: relative;
  background: var(--warm-3);
  padding: var(--s-5);
  overflow: hidden;
}
.hld-thread {
  /* gap tuned for the 8-message mortgage scenario; bubbles are
     display:none until revealed (.hld-msg rule), so the thread fills
     downward as the conversation arrives instead of pre-reserving the
     full layout. */
  display: flex; flex-direction: column; gap: 6px;
  max-width: 520px; margin: 0 auto;
  height: 100%; overflow-y: auto;
  scrollbar-width: none;
}
.hld-thread::-webkit-scrollbar { display: none; }
.hld-msg {
  /* Bubble padding trimmed 10/14 → 8/13 and font 14 → 13.5 for a
     slightly denser stack — still comfortable, but enough head-room
     for all 8 messages in the 16:11 screen area.
     CRITICAL: display:none until .is-visible. This means unrevealed
     messages don't reserve layout space — the thread fills downward
     as bubbles arrive, and only auto-scrolls when the latest one
     would otherwise sit below the visible fold. (When messages were
     pre-positioned with opacity 0, the thread always overflowed
     slightly and the reveal-then-scroll dance clipped m1.) */
  display: none;
  max-width: 80%;
  padding: 8px 13px;
  font: 400 13.5px/1.45 var(--f-body);
  border-radius: 16px;
}
.hld-msg.is-visible {
  display: block;
  animation: hld-pop 320ms var(--ease) both;
}
@keyframes hld-pop {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.hld-msg.in {
  align-self: flex-start;
  background: var(--bg-paper);
  color: var(--fg);
  border: 1px solid var(--hair);
  border-bottom-left-radius: 5px;
}
.hld-msg.out {
  align-self: flex-end;
  background: var(--accent);
  color: var(--paper);
  border-bottom-right-radius: 5px;
}
.hld-msg strong { font-weight: 700; }
.hld-msg.out strong { color: color-mix(in oklab, var(--paper) 95%, transparent); }
.hld-msg em {
  font-style: normal;
  font-family: var(--f-mono);
  font-size: 0.94em;
  background: color-mix(in oklab, var(--paper) 75%, transparent);
  color: var(--accent-text);
  padding: 1px 5px;
  border-radius: var(--r-xs);
}
.hld-msg.out em {
  /* darker, more opaque overlay so the white em text reads cleanly
     against the pink bubble (the 30% paper bg before was almost invisible
     and the white text + light overlay failed AA-large badly in dark mode). */
  background: rgba(0, 0, 0, 0.28);
  color: var(--paper);
  font-weight: 500;
}

/* Typing indicator (shared keyframe with .hs-typing) — appears on
   MB's side (right) since MB is composing the next response. */
.hld-typing {
  align-self: flex-end;
  display: flex; gap: 5px;
  padding: 12px 16px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: 16px 16px 5px 16px;
}
.hld-typing[hidden] { display: none; }
.hld-typing span {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--fg-dim);
  animation: hs-blink 1.2s ease-in-out infinite;
}
.hld-typing span:nth-child(2) { animation-delay: 0.2s; }
.hld-typing span:nth-child(3) { animation-delay: 0.4s; }

/* Response-timer overlay — top-right, ticks in 100ms increments
   until the agent responds, then freezes and highlights. */
.hld-timer {
  position: absolute; top: var(--s-4); right: var(--s-4);
  padding: 8px 12px;
  background: color-mix(in oklab, var(--ink) 82%, transparent);
  color: var(--paper);
  border-radius: var(--r-md);
  font: 600 12px/1 var(--f-mono);
  letter-spacing: 0.06em;
  display: inline-flex; align-items: center; gap: 8px;
  box-shadow: var(--sh-2);
  opacity: 0; transform: translateY(-6px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease),
              background 300ms var(--ease), box-shadow 300ms var(--ease);
  z-index: 3;
}
.hld-timer.is-visible { opacity: 1; transform: translateY(0); }
.hld-timer.is-frozen {
  background: var(--accent);
  box-shadow: 0 6px 16px -6px color-mix(in oklab, var(--accent) 60%, transparent);
}
.hld-timer-label {
  font-size: 9.5px; text-transform: uppercase;
  /* bumped from 65% to 85% paper so the small label reads cleanly
     against both the dark-ink default state and the pink frozen state */
  color: color-mix(in oklab, var(--paper) 88%, transparent);
  letter-spacing: 0.1em;
}
.hld-timer-value { font-variant-numeric: tabular-nums; font-size: 14px; }

/* Status badge overlay — bottom-left, cycles through the
   qualification states as the conversation progresses. */
.hld-status {
  position: absolute; bottom: var(--s-4); left: var(--s-4);
  padding: 8px 14px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font: 600 11.5px/1 var(--f-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg);
  display: inline-flex; align-items: center; gap: 8px;
  box-shadow: var(--sh-2);
  opacity: 0; transform: translateY(6px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
  z-index: 3;
}
.hld-status.is-visible { opacity: 1; transform: translateY(0); }
.hld-status-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--fg-dim);
  transition: background 260ms var(--ease),
              box-shadow 260ms var(--ease);
}
.hld-status[data-state="inbound"]   .hld-status-dot { background: var(--info); box-shadow: 0 0 0 3px color-mix(in oklab, var(--info) 25%, transparent); }
.hld-status[data-state="engaging"]  .hld-status-dot { background: var(--warning); box-shadow: 0 0 0 3px color-mix(in oklab, var(--warning) 25%, transparent); }
.hld-status[data-state="qualified"] .hld-status-dot { background: var(--green-500); box-shadow: 0 0 0 3px color-mix(in oklab, var(--green-500) 25%, transparent); animation: hld-pulse 1s ease-out 1; }
.hld-status[data-state="booked"]    .hld-status-dot { background: var(--accent); box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 25%, transparent); animation: hld-pulse 1.4s ease-out 1; }
@keyframes hld-pulse {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.4); }
  100% { transform: scale(1); }
}

/* ─── §11.17 mode variants ──────────────────────────────────
   Five overlay-emphasis modes for the same component. Each tunes
   which overlay dominates the visual weight, matched to the page
   it lives on. The base markup is identical; the mode chooses
   which overlay set is emphasised + which mode-specific overlay
   is summoned in. JSON data contract covers script + mode + scenario. */

/* speed-forward — timer dominates; status is supplementary.
   Used on Engage, Mortgage, Auto, Home Services, SMS Channel. */
.hero-live-demo[data-mode="speed-forward"] .hld-timer {
  padding: 12px 18px;
  font-size: 13px;
}
.hero-live-demo[data-mode="speed-forward"] .hld-timer-value {
  font-size: 22px; font-weight: 700;
}
.hero-live-demo[data-mode="speed-forward"] .hld-timer.is-frozen {
  box-shadow: 0 8px 28px -8px color-mix(in oklab, var(--accent) 70%, transparent),
              0 0 0 4px color-mix(in oklab, var(--accent) 18%, transparent);
}
.hero-live-demo[data-mode="speed-forward"] .hld-status { opacity: 0.78; transform: scale(0.92); transform-origin: bottom left; }
.hero-live-demo[data-mode="speed-forward"] .hld-status.is-visible { opacity: 0.78; transform: scale(0.92); }

/* qualification-forward — extra score overlay BOTTOM-LEFT, status hides.
   Was top-left but that covered the first inbound message. The status
   badge is `display:none` in this mode so bottom-left is free.
   Used on Prequalify, Insurance, Solar. */
.hld-qual-score {
  position: absolute; bottom: var(--s-4); left: var(--s-4);
  padding: 8px 14px;
  background: color-mix(in oklab, var(--ink) 88%, transparent);
  color: var(--paper);
  border-radius: var(--r-md);
  font: 500 11px/1.2 var(--f-mono);
  letter-spacing: 0.08em; text-transform: uppercase;
  display: inline-flex; flex-direction: column; gap: 4px;
  min-width: 130px;
  box-shadow: var(--sh-2);
  /* Rise-from-below entrance (matches .hld-status) so the visual
     vocabulary stays consistent across modes. */
  opacity: 0; transform: translateY(8px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
  z-index: 3;
}
.hld-qual-score.is-visible { opacity: 1; transform: translateY(0); }
.hld-qual-score .qs-label { font-size: 9.5px; opacity: 0.7; }
.hld-qual-score .qs-row { display: flex; align-items: center; gap: 8px; }
.hld-qual-score .qs-num {
  font: 700 18px/1 var(--f-display);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.hld-qual-score .qs-bar {
  flex: 1; height: 5px; border-radius: 3px;
  background: rgba(255,255,255,0.14);
  overflow: hidden;
}
.hld-qual-score .qs-bar > span {
  display: block; height: 100%;
  background: var(--green-500);
  width: var(--qs-pct, 0%);
  transition: width 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
.hero-live-demo[data-mode="qualification-forward"] .hld-status { display: none; }

/* cadence-forward — timeline of 7 touches across 30d at the bottom.
   Used on Follow Up, Tourism. */
.hld-cadence {
  position: absolute; bottom: var(--s-4); left: var(--s-4); right: var(--s-4);
  padding: 10px 14px;
  background: color-mix(in oklab, var(--ink) 88%, transparent);
  color: var(--paper);
  border-radius: var(--r-md);
  font: 500 10px/1 var(--f-mono);
  letter-spacing: 0.08em; text-transform: uppercase;
  display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center;
  box-shadow: var(--sh-2);
  opacity: 0; transform: translateY(8px);
  transition: opacity 280ms var(--ease), transform 280ms var(--ease);
  z-index: 3;
}
.hld-cadence.is-visible { opacity: 1; transform: translateY(0); }
.hld-cadence .cd-track {
  position: relative;
  height: 14px;
  border-radius: 7px;
  background: rgba(255,255,255,0.08);
  display: flex; align-items: center;
}
.hld-cadence .cd-track::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: var(--cd-progress, 100%); height: 2px;
  background: color-mix(in oklab, var(--accent) 80%, transparent);
  transform: translateY(-50%); border-radius: 1px;
}
.hld-cadence .cd-touch {
  position: absolute; top: 50%;
  width: 9px; height: 9px; border-radius: 50%;
  background: rgba(255,255,255,0.18);
  transform: translate(-50%, -50%);
  transition: background 200ms var(--ease), box-shadow 200ms var(--ease);
}
.hld-cadence .cd-touch.is-fired {
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 26%, transparent);
}
.hld-cadence .cd-touch.is-current {
  background: var(--accent);
  box-shadow: 0 0 0 5px color-mix(in oklab, var(--accent) 32%, transparent);
  animation: hld-pulse 1.2s ease-out infinite;
}
.hld-cadence .cd-label { font-size: 9.5px; opacity: 0.7; }
.hero-live-demo[data-mode="cadence-forward"] .hld-status { display: none; }

/* reactivation-forward — state-transition card BOTTOM-LEFT.
   Was top-left; moved so it doesn't cover the inbound conversation.
   The status badge is `display:none` in this mode so bottom-left is free.
   "Last contact: 47d ago" → "Re-engaged today". Used on Reengage. */
.hld-reactivation {
  position: absolute; bottom: var(--s-4); left: var(--s-4);
  padding: 10px 14px;
  background: color-mix(in oklab, var(--ink) 88%, transparent);
  color: var(--paper);
  border-radius: var(--r-md);
  font: 500 10.5px/1.3 var(--f-mono);
  letter-spacing: 0.06em;
  display: inline-flex; flex-direction: column; gap: 4px;
  box-shadow: var(--sh-2);
  /* Rise-from-below entrance (matches .hld-status / .hld-qual-score). */
  opacity: 0; transform: translateY(8px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
  z-index: 3;
}
.hld-reactivation.is-visible { opacity: 1; transform: translateY(0); }
.hld-reactivation .rx-row {
  display: flex; align-items: center; gap: 8px;
}
.hld-reactivation .rx-row .rx-dot {
  width: 8px; height: 8px; border-radius: 50%;
}
.hld-reactivation .rx-row.is-dormant { opacity: 0.55; text-decoration: line-through; }
.hld-reactivation .rx-row.is-dormant .rx-dot { background: var(--fg-dim); }
.hld-reactivation .rx-row.is-active .rx-dot {
  background: var(--green-500);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--green-500) 28%, transparent);
  animation: hld-pulse 1.6s ease-out infinite;
}
.hero-live-demo[data-mode="reactivation-forward"] .hld-status { display: none; }

/* Playback controls under the laptop */
.hld-controls {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  margin-top: var(--s-5);
  padding: 0 var(--s-4);
  font: 500 12px/1 var(--f-mono);
  color: var(--fg-dim);
}
.hld-controls .hld-btn {
  appearance: none; background: transparent;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  padding: 6px 14px;
  font: inherit; color: var(--fg);
  cursor: pointer;
  transition: border-color var(--dur-2) var(--ease),
              color var(--dur-2) var(--ease);
}
.hld-controls .hld-btn:hover { border-color: var(--accent); color: var(--accent-text); }
.hld-controls .hld-btn:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.hld-controls .hld-scenario { text-transform: uppercase; letter-spacing: 0.1em; font-size: 10.5px; }

/* Mobile — collapse the laptop frame into a borderless app view.
   Overlays stay but move to below the thread as a single info row. */
@media (max-width: 640px) {
  .hld-frame { padding: 8px 8px 0; border-radius: 10px 10px 3px 3px; }
  .hld-frame::after { height: 8px; margin: 10px -16px 0; border-radius: 0 0 10px 10px; }
  .hld-screen { aspect-ratio: 9 / 13; }
  .hld-app { padding: var(--s-4); }
  .hld-timer, .hld-status {
    position: static; margin-bottom: var(--s-2);
    display: inline-flex;
  }
  .hld-timer { background: var(--bg-paper); color: var(--fg); border: 1px solid var(--hair); }
  .hld-timer-label { color: var(--fg-dim); }
}

@media (prefers-reduced-motion: reduce) {
  .hld-msg, .hld-timer, .hld-status {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .hld-typing { display: none !important; }
  .hld-status-dot { animation: none !important; }
}

/* ── 11.18 .leak-card — four-leaks diagnostic grid ────────────
   One atom, four variants (data-leak="1|2|3|4"), each carrying its
   own accent colour via --lk-accent. Card is a single <a> so the
   whole tile is one click target and one focus ring. Stats populated
   from researched data (Hatch / Marketing Donut / RevenueHero) —
   see citations in the <p> body copy. */
.leak-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-5);
  width: 100%;
  max-width: min(960px, 100%);
  margin: 0 auto;
}
@media (max-width: 640px) { .leak-grid { grid-template-columns: 1fr; gap: var(--s-4); } }

.leak-card {
  --lk-accent: var(--accent);
  --lk-accent-soft: var(--accent-soft);
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto 1fr auto auto;
  grid-template-areas:
    "icon stat"
    "title title"
    "body body"
    "spark spark"
    "cta cta";
  gap: var(--s-4);
  padding: var(--s-6);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-top: 3px solid var(--lk-accent);  /* accent rail */
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  color: var(--fg);
  text-decoration: none;
  position: relative;
  transition: transform var(--dur-2) var(--ease),
              box-shadow var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease);
}
.leak-card:hover,
.leak-card:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--sh-3);
  border-color: color-mix(in oklab, var(--lk-accent) 40%, var(--hair));
  outline: 0;
}
.leak-card:focus-visible { box-shadow: var(--sh-3), var(--sh-focus); }

/* Per-leak accent (pink / yellow / green / blue) — pinned to palette */
.leak-card[data-leak="1"] { --lk-accent: var(--pink-500);   --lk-accent-soft: color-mix(in oklab, var(--pink-500)   14%, transparent); }
.leak-card[data-leak="2"] { --lk-accent: var(--yellow-500); --lk-accent-soft: color-mix(in oklab, var(--yellow-500) 16%, transparent); }
.leak-card[data-leak="3"] { --lk-accent: var(--green-500);  --lk-accent-soft: color-mix(in oklab, var(--green-500)  16%, transparent); }
.leak-card[data-leak="4"] { --lk-accent: var(--blue-500);   --lk-accent-soft: color-mix(in oklab, var(--blue-500)   16%, transparent); }

/* Icon slot — stroked glyph inherits --lk-accent */
.leak-card .lk-icon {
  grid-area: icon;
  width: 28px; height: 28px;
  color: var(--lk-accent);
  display: inline-flex; align-items: center; justify-content: center;
}
.leak-card .lk-icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Stat pill — top-right, big bold mono number */
.leak-card .lk-stat {
  grid-area: stat;
  justify-self: end; align-self: start;
  padding: 6px 12px;
  background: var(--lk-accent-soft);
  color: var(--lk-accent);
  font: 700 18px/1 var(--f-mono);
  letter-spacing: -0.02em;
  border-radius: var(--r-pill);
  font-variant-numeric: tabular-nums;
}

/* Headline — leak name */
.leak-card .lk-title {
  grid-area: title;
  font: 600 24px/1.2 var(--f-display);
  letter-spacing: -0.02em;
  color: var(--fg);
  margin: 0;
}

/* Body — concrete pain-naming copy with embedded sources */
.leak-card .lk-body {
  grid-area: body;
  font: 400 14px/1.55 var(--f-body);
  color: var(--fg-soft);
  margin: 0;
}
.leak-card .lk-body strong { color: var(--fg); font-weight: 600; }
.leak-card .lk-body cite {
  font-style: normal; font-size: 12px;
  color: var(--fg-dim);
  font-family: var(--f-mono);
  letter-spacing: 0.04em;
  display: block; margin-top: 4px;
}

/* Sparkline — decorative mini-chart. Draws in on hover. */
.leak-card .lk-spark {
  grid-area: spark;
  height: 36px; width: 100%;
  display: block;
  color: var(--lk-accent);
  opacity: 0.85;
}
.leak-card .lk-spark svg { width: 100%; height: 100%; overflow: visible; }
.leak-card .lk-spark path {
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: var(--lk-len, 200);
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--dur-2) var(--ease);
}
.leak-card .lk-spark .dot { fill: currentColor; stroke: none; }
.leak-card:hover .lk-spark path,
.leak-card:focus-visible .lk-spark path {
  animation: lk-spark-draw 1.4s var(--ease) forwards;
}
@keyframes lk-spark-draw {
  0%   { stroke-dashoffset: var(--lk-len, 200); }
  100% { stroke-dashoffset: 0; }
}

/* CTA — arrow shifts 4px on hover */
.leak-card .lk-cta {
  grid-area: cta;
  font: 600 14px/1 var(--f-display);
  color: var(--lk-accent);
  display: inline-flex; align-items: center; gap: 6px;
  letter-spacing: -0.005em;
  margin-top: var(--s-2);
}
.leak-card .lk-cta .arrow {
  display: inline-block;
  transition: transform var(--dur-2) var(--ease);
}
.leak-card:hover .lk-cta .arrow,
.leak-card:focus-visible .lk-cta .arrow { transform: translateX(4px); }

@media (prefers-reduced-motion: reduce) {
  .leak-card { transition: none; }
  .leak-card:hover, .leak-card:focus-visible { transform: none; }
  .leak-card .lk-spark path { animation: none !important; stroke-dashoffset: 0 !important; }
  .leak-card .lk-cta .arrow { transition: none; }
}

/* ── 11.19 .chat-comparison — dual-convo proof widget ─────────
   Two conversations running side-by-side: left column is a generic
   chatbot (desaturated, dead-ends), right is MagicBlocks (full
   colour, closes the loop). Same inbound lead message in both. The
   asymmetry IS the message. Industry chips above toggle scenario;
   scripts are data-driven via [data-scenario]. */
.chat-comparison {
  width: 100%;
  max-width: min(980px, 100%);
  margin: 0 auto;
  display: flex; flex-direction: column; gap: var(--s-5);
}
.cc-head {
  text-align: center;
  display: flex; flex-direction: column; gap: var(--s-3);
  align-items: center;
}
.cc-head h4 {
  font: 600 clamp(20px, 2.4vw, 26px)/1.25 var(--f-display);
  letter-spacing: -0.02em;
  color: var(--fg);
  margin: 0;
  max-width: 30ch;
}
.cc-head h4 em {
  font-family: var(--f-italic);
  font-style: italic;
  font-weight: 500;
  color: var(--accent-text);
  font-variation-settings: "SOFT" 80;
}
/* small eyebrow label used by the variant gallery */
.cc-eyebrow {
  font: 500 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-dim);
}

/* Industry toggle — horizontal chip row above the columns */
.cc-toggle {
  display: inline-flex; flex-wrap: wrap; gap: 6px;
  padding: 5px;
  background: var(--bg-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
}
.cc-toggle button {
  appearance: none; background: transparent; border: 0;
  font: 500 12px/1 var(--f-mono);
  color: var(--fg-dim);
  letter-spacing: 0.04em;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: color var(--dur-2) var(--ease),
              background var(--dur-2) var(--ease);
}
.cc-toggle button:hover { color: var(--fg); }
.cc-toggle button.is-active {
  background: var(--bg-paper);
  color: var(--accent-text);
  box-shadow: var(--sh-1);
}
.cc-toggle button:focus-visible { outline: 0; box-shadow: var(--sh-focus); }

/* Two-column convo grid */
.cc-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-5);
  width: 100%;
}
@media (max-width: 720px) { .cc-cols { grid-template-columns: 1fr; gap: var(--s-4); } }

.cc-col {
  /* PINNED white surface for both columns in BOTH themes — this is a
     comparison widget that needs to read as "two chat apps side-by-side",
     not "two dark surfaces in dark mode". Token re-scope keeps the
     conversation copy ink-toned regardless of page theme. */
  background: var(--paper);
  border: 1px solid color-mix(in oklab, var(--ink) 10%, transparent);
  border-radius: var(--r-lg);
  overflow: hidden;
  display: flex; flex-direction: column;
  min-height: 420px;
  --fg:        var(--ink);
  --fg-soft:   color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:    color-mix(in oklab, var(--ink) 50%, transparent);
  --hair:      color-mix(in oklab, var(--ink) 12%, transparent);
  --hair-soft: color-mix(in oklab, var(--ink) 6%, transparent);
  --bg-sunk:   #F4ECE4;
  color: var(--fg);
}
.cc-col.generic {
  /* Deliberately desaturated — reads as clinical / off-the-shelf */
  --cc-bubble: color-mix(in oklab, #F4ECE4 80%, var(--paper));
  --cc-fg: var(--fg-soft);
  filter: saturate(0.55);
}
.cc-col.mb {
  /* MagicBlocks-as-good-alternative reads as green, not pink. Pink in
     a head-to-head against a competitor read as red/aggressive; green
     reads as the calm, correct option. The accent (pink) stays the
     hero token everywhere else — this is a comparison-only swap. */
  --cc-bubble: var(--green-500);
  --cc-fg: var(--fg);
  --cc-glow: color-mix(in oklab, var(--green-500) 50%, transparent);
}
.cc-col-head {
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--hair);
  font: 600 11px/1 var(--f-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-dim);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3);
  background: var(--bg-sunk);
}
.cc-col.mb .cc-col-head {
  color: var(--green-700);
  background: color-mix(in oklab, var(--green-500) 8%, var(--bg-sunk));
}
.cc-col-name { display: inline-flex; align-items: center; gap: 8px; }
.cc-col-name .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--fg-dim);
}
.cc-col.mb .cc-col-name .dot {
  background: var(--green-500);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--green-500) 30%, transparent);
}
.cc-col-status {
  font: 500 10.5px/1 var(--f-mono);
  color: var(--fg-dim);
}
.cc-col.mb[data-state="booked"] .cc-col-status {
  color: var(--green-700);
  animation: cc-pulse 1.2s ease-out 1;
}
@keyframes cc-pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.08); }
  100% { transform: scale(1); }
}

/* Conversation area */
.cc-thread {
  flex: 1;
  padding: var(--s-4);
  display: flex; flex-direction: column; gap: 8px;
  overflow-y: auto;
  scrollbar-width: none;
}
.cc-thread::-webkit-scrollbar { display: none; }

.cc-msg {
  max-width: 82%;
  padding: 9px 13px;
  border-radius: 14px;
  font: 400 13.5px/1.45 var(--f-body);
  opacity: 0; transform: translateY(6px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
}
.cc-msg.is-visible { opacity: 1; transform: translateY(0); }
.cc-msg.in {
  align-self: flex-start;
  background: var(--bg-sunk);
  color: var(--fg);
  border: 1px solid var(--hair);
  border-bottom-left-radius: 5px;
}
.cc-msg.out {
  align-self: flex-end;
  background: var(--cc-bubble);
  color: var(--fg);
  border-bottom-right-radius: 5px;
}
.cc-col.mb .cc-msg.out {
  /* Ink text on the green bubble — white on green-500 was 1.7:1 contrast,
     dramatically failing AA. Ink-on-green-500 is ~12:1, well above AAA.
     The bubble still reads green/positive-alternative; the text is just
     legible body-weight ink instead of washed-out white. */
  color: var(--ink);
  box-shadow:
    0 6px 20px -8px var(--cc-glow),
    0 0 0 1px color-mix(in oklab, var(--green-500) 30%, transparent);
}
.cc-msg em {
  font-style: normal;
  font-family: var(--f-mono);
  font-size: 0.94em;
  background: color-mix(in oklab, var(--paper) 70%, transparent);
  color: var(--accent-text);
  padding: 1px 5px;
  border-radius: var(--r-xs);
}
.cc-col.mb .cc-msg.out em {
  /* now that the bubble carries ink body text, em pills also use ink
     on a darker green underlay — keeps the em distinguished from
     surrounding text without losing readability. */
  background: color-mix(in oklab, var(--green-700) 70%, transparent);
  color: var(--ink);
  font-weight: 600;
}

/* Dead-end signal on the generic side */
.cc-msg.dead-end {
  opacity: 0.55;
  font-style: italic;
  font-size: 12px;
  color: var(--fg-dim);
  background: transparent;
  border: 1px dashed var(--hair);
  align-self: center;
  text-align: center;
}

/* Typing indicator per column (reuses hs-blink keyframe). Lives on
   the AI's side (right within each column) since the AI is the one
   composing the next reply — both columns flip the dots to flex-end
   for that reason. */
.cc-typing {
  align-self: flex-end;
  display: flex; gap: 4px;
  padding: 10px 13px;
  background: var(--bg-sunk);
  border: 1px solid var(--hair);
  border-radius: 14px 14px 5px 14px;
}
.cc-typing[hidden] { display: none; }
.cc-typing span {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--fg-dim);
  animation: hs-blink 1.2s ease-in-out infinite;
}
.cc-typing span:nth-child(2) { animation-delay: 0.2s; }
.cc-typing span:nth-child(3) { animation-delay: 0.4s; }

/* Playback controls */
.cc-controls {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  padding: 0 var(--s-3);
  font: 500 12px/1 var(--f-mono);
  color: var(--fg-dim);
}
.cc-controls .cc-btn {
  appearance: none; background: transparent;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  padding: 6px 14px;
  font: inherit; color: var(--fg);
  cursor: pointer;
  transition: border-color var(--dur-2) var(--ease),
              color var(--dur-2) var(--ease);
}
.cc-controls .cc-btn:hover { border-color: var(--accent); color: var(--accent-text); }
.cc-controls .cc-btn:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.cc-controls .cc-scenario {
  text-transform: uppercase; letter-spacing: 0.1em; font-size: 10.5px;
}

@media (prefers-reduced-motion: reduce) {
  .cc-msg { opacity: 1 !important; transform: none !important; transition: none !important; }
  .cc-typing { display: none !important; }
  .cc-col.mb[data-state="booked"] .cc-col-status { animation: none; }
}

/* ── 11.1 .decay-curve ─────────────────────────────────────── */
.decay-curve { width: 100%; max-width: min(1080px, 100%); }
.decay-curve svg { width: 100%; height: auto; display: block; overflow: visible; }
.decay-curve .grid-line { stroke: var(--hair); stroke-width: 1; }
.decay-curve .axis { fill: var(--fg-soft); font: 500 11px/1 var(--f-mono); letter-spacing: 0.08em; text-transform: uppercase; }

/* Traffic-light zones — green = hot, amber = cooling, red = dead.
   Uses the brighter --green-500 / --yellow-500 / --error for the hot
   wash so the cream-warm background doesn't desaturate the green into
   grey. Opacities balanced so all three zones feel evenly saturated. */
.decay-curve .zone-hot   { fill: color-mix(in oklab, var(--green-500)  38%, transparent); }
.decay-curve .zone-warm  { fill: color-mix(in oklab, var(--yellow-500) 34%, transparent); }
.decay-curve .zone-dead  { fill: color-mix(in oklab, var(--error)      26%, transparent);
                           animation: dc-breathe 4.2s ease-in-out infinite; }
.decay-curve .zone-label {
  font: 700 11.5px/1 var(--f-mono); letter-spacing: 0.16em; text-transform: uppercase;
}
.decay-curve .zone-label.hot  { fill: var(--success); }
.decay-curve .zone-label.warm { fill: var(--warning); }
.decay-curve .zone-label.dead { fill: var(--error); }
/* Legacy dead-zone styles retained for backward-compat */
.decay-curve .dead-zone { fill: color-mix(in oklab, var(--error) 14%, transparent); animation: dc-breathe 4.2s ease-in-out infinite; transform-origin: center; }
.decay-curve .dead-zone-label {
  fill: var(--error); font: 600 11px/1 var(--f-mono); letter-spacing: 0.14em; text-transform: uppercase;
}
@keyframes dc-breathe {
  0%, 100% { fill-opacity: 0.9;  }
  50%      { fill-opacity: 1.15; }
}

.decay-curve .curve-path {
  fill: none; stroke: var(--fg);          /* dark-mode safe — flips to warm on dark */
  stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}
.decay-curve .curve-fill {
  fill: color-mix(in oklab, var(--accent) 14%, transparent);
  opacity: 0; transition: opacity 600ms ease-out 800ms;
}
.decay-curve.is-visible .curve-fill { opacity: 1; }
.decay-curve[data-state="fixed"] .curve-fill { fill: color-mix(in oklab, var(--accent) 22%, transparent); }

/* Continuous tracer — a pink dot representing "lead intent" sliding down
   the curve, looping every 7 seconds. Shows the decay happening in real time. */
.decay-curve .tracer-halo { fill: color-mix(in oklab, var(--accent) 30%, transparent); }
.decay-curve .tracer-dot  { fill: var(--accent); }

/* Markers — small pinned circles at the curve. Traffic-light coded:
   the "won" marker (MagicBlocks · 5s) reads GREEN because fast = good,
   the "lost" marker (Your team · 10min) reads RED because it sits in
   the dead zone. Pink stays reserved for the tracer (live intent). */
.decay-curve .marker-ring { fill: none; stroke-width: 2; }
.decay-curve .marker.lost .marker-ring { stroke: var(--error); animation: dc-pulse 1.8s ease-out infinite; }
.decay-curve .marker.lost .marker-dot  { fill: var(--error); }
.decay-curve .marker.won  .marker-ring { stroke: var(--success); animation: dc-pulse 2.2s ease-out infinite 0.4s; }
.decay-curve .marker.won  .marker-dot  { fill: var(--success); }
@keyframes dc-pulse {
  0%,100% { stroke-opacity: 1;   r: 9; }
  60%     { stroke-opacity: 0.2; r: 15; }
}

/* Callout cards — sit OFF the curve with leader lines. Stronger borders
   and a tinted fill so each card clearly "owns" the marker it labels. */
.decay-curve .callout-bg {
  fill: var(--bg-paper);
  stroke: var(--hair);
  stroke-width: 1.5;
  filter: drop-shadow(0 2px 6px color-mix(in oklab, var(--ink) 12%, transparent));
}
.decay-curve .callout-bg.won  {
  stroke: var(--success);
  stroke-width: 1.5;
  fill: color-mix(in oklab, var(--success) 8%, var(--bg-paper));
}
.decay-curve .callout-bg.lost {
  stroke: var(--error);
  stroke-width: 1.5;
  fill: color-mix(in oklab, var(--error) 6%, var(--bg-paper));
}
.decay-curve .callout-title {
  font: 600 13.5px/1.2 var(--f-body); fill: var(--fg);
}
.decay-curve .callout-title.won  { fill: var(--success); }
.decay-curve .callout-title.lost { fill: var(--error); }
.decay-curve .callout-sub {
  font: 500 10.5px/1 var(--f-mono); fill: var(--fg-soft); letter-spacing: 0.12em; text-transform: uppercase;
}
.decay-curve .callout-sub.won  { fill: var(--success); }
.decay-curve .callout-sub.lost { fill: var(--error); }
.decay-curve .callout-leader { stroke: var(--hair); stroke-width: 1.2; stroke-linecap: round; fill: none; }
.decay-curve .callout-leader.won  { stroke: color-mix(in oklab, var(--success) 55%, transparent); }
.decay-curve .callout-leader.lost { stroke: color-mix(in oklab, var(--error)   55%, transparent); }

@media (prefers-reduced-motion: reduce) {
  .decay-curve .curve-fill { opacity: 1; transition: none; }
  .decay-curve .marker.lost .marker-ring,
  .decay-curve .marker.won  .marker-ring,
  .decay-curve .dead-zone,
  .decay-curve .zone-dead,
  .decay-curve .tracer-motion,
  .decay-curve animateMotion { animation: none; }
}

/* ── 11.1b .dormant-mine — Database reactivator.
   The other half of the intent story: most of your CRM is DORMANT
   inquiries nobody had time to reach. This component shows a CRM
   table where each row cycles cold → scanning → drafting → sent →
   replied on a continuous 14s loop. A side panel shows the
   personalised outreach being drafted in real time. Adapted from
   the "Mining for Leads · V1" design spec.
   Pure CSS animation — no JS state. Each row has --i (stagger
   index) and the keyframes do the rest. */
.dormant-mine {
  width: 100%; max-width: min(1080px, 100%); margin: 0 auto;
  font-family: var(--f-body);
  /* PINNED white / token re-scope so the database UI reads as crisp
     CRM chrome in BOTH themes (warm or dark page). */
  --fg:        var(--ink);
  --fg-soft:   color-mix(in oklab, var(--ink) 70%, transparent);
  --fg-dim:    color-mix(in oklab, var(--ink) 50%, transparent);
  --fg-faint:  color-mix(in oklab, var(--ink) 35%, transparent);
  --hair:      color-mix(in oklab, var(--ink) 12%, transparent);
  --hair-soft: color-mix(in oklab, var(--ink) 6%, transparent);
  --bg-sunk:   #F4ECE4;
  color: var(--fg);
}

/* Top bar — title + revenue chip */
.dormant-mine .dm-bar {
  display: grid; grid-template-columns: 1fr auto;
  gap: var(--s-4); align-items: center;
  margin-bottom: var(--s-4);
}
.dormant-mine .dm-titles {
  display: flex; flex-direction: column; gap: 6px;
}
.dormant-mine .dm-title {
  font: 600 18px/1.25 var(--f-display);
  letter-spacing: -0.01em; color: var(--ink);
}
.dormant-mine .dm-meta {
  display: flex; gap: 8px; flex-wrap: wrap;
}
.dormant-mine .dm-token {
  font: 600 10px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 5px 9px;
  background: var(--bg-sunk);
  color: var(--fg-dim);
  border: 1px solid var(--hair-soft);
  border-radius: var(--r-pill);
}
.dormant-mine .dm-token-live {
  background: var(--accent-soft); color: var(--accent-text);
  border-color: color-mix(in oklab, var(--accent) 18%, transparent);
  display: inline-flex; align-items: center; gap: 6px;
}
.dormant-mine .dm-livedot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
  animation: dm-livepulse 1.4s ease-out infinite;
}
@keyframes dm-livepulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 55%, transparent); }
  70%  { box-shadow: 0 0 0 7px color-mix(in oklab, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 0%, transparent); }
}

/* Revenue recovered chip — sits top-right */
.dormant-mine .dm-revchip {
  display: flex; flex-direction: column; gap: 4px;
  padding: 12px 18px;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--green-500);
  border-radius: var(--r-md);
  text-align: right;
  min-width: 180px;
}
.dormant-mine .dm-revchip-label {
  font: 600 9.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-dim);
}
.dormant-mine .dm-revchip-value {
  font: 700 22px/1 var(--f-display); letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  color: var(--success-text);
}
.dormant-mine .dm-revchip-delta {
  font: 500 10.5px/1 var(--f-mono);
  color: var(--success-text);
  display: flex; gap: 5px; justify-content: flex-end;
}

/* Database table panel */
.dormant-mine .dm-table {
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  box-shadow: 0 4px 14px -8px color-mix(in oklab, var(--ink) 14%, transparent);
  overflow: hidden;
}
.dormant-mine .dm-cols {
  display: grid;
  grid-template-columns: 1.7fr 0.8fr 0.8fr 1fr;
  gap: var(--s-3);
  padding: 12px 20px;
  font: 600 10px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-faint);
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--bg-sunk) 50%, var(--paper)),
    var(--paper));
  border-bottom: 1px solid var(--hair-soft);
}
.dormant-mine .dm-rows { display: flex; flex-direction: column; }
.dormant-mine .dm-row {
  position: relative;
  display: grid;
  grid-template-columns: 1.7fr 0.8fr 0.8fr 1fr;
  gap: var(--s-3);
  align-items: center;
  padding: 12px 20px;
  border-bottom: 1px solid var(--hair-soft);
  background: var(--paper);
  /* 14s loop — each row staggered by 1.4s via --i. The animation
     cycles row background through cold → scanning → drafting → sent →
     replied → reset. */
  animation: dm-row-cycle 14s linear infinite;
  animation-delay: calc(var(--i, 0) * -1.4s);
}
.dormant-mine .dm-row:last-child { border-bottom: 0; }
@keyframes dm-row-cycle {
  0%, 9%   { background: var(--paper); }
  12%, 18% { background: color-mix(in oklab, var(--accent) 6%, var(--paper)); }   /* scanning */
  21%, 31% { background: color-mix(in oklab, var(--accent) 7%, var(--paper)); }   /* drafting */
  34%, 44% { background: color-mix(in oklab, var(--info) 6%, var(--paper)); }     /* sent */
  47%, 92% { background: color-mix(in oklab, var(--green-500) 9%, var(--paper)); } /* replied */
  100%     { background: var(--paper); }
}

/* Lead cell (avatar + name + stage) */
.dormant-mine .dm-name { display: flex; align-items: center; gap: 12px; min-width: 0; }
.dormant-mine .dm-avatar {
  width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font: 600 12px/1 var(--f-display); letter-spacing: -0.01em;
  flex-shrink: 0;
  background: var(--bg-sunk); color: var(--fg-dim);
  animation: dm-av-cycle 14s linear infinite;
  animation-delay: calc(var(--i, 0) * -1.4s);
}
@keyframes dm-av-cycle {
  0%, 9%   { background: var(--bg-sunk);     color: var(--fg-dim); }
  12%, 31% { background: var(--accent-soft); color: var(--accent-text); }
  34%, 44% { background: var(--info-soft);   color: var(--info-text); }
  47%, 92% { background: var(--success-soft); color: var(--success-text); }
  100%     { background: var(--bg-sunk);     color: var(--fg-dim); }
}
.dormant-mine .dm-name-text {
  font: 600 14px/1.2 var(--f-body);
  color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dormant-mine .dm-stage-text {
  font: 400 12px/1.3 var(--f-body);
  color: var(--fg-dim);
  margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dormant-mine .dm-amount,
.dormant-mine .dm-last {
  font: 500 12.5px/1 var(--f-mono);
  font-variant-numeric: tabular-nums;
  color: var(--fg-soft);
}

/* Status pill — 5 stacked labels, only one visible at a time per the row's phase */
.dormant-mine .dm-status { position: relative; }
.dormant-mine .dm-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font: 500 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  white-space: nowrap;
  background: var(--bg-sunk); color: var(--fg-dim);
  border-color: var(--hair-soft);
  animation: dm-pill-bg 14s linear infinite;
  animation-delay: calc(var(--i, 0) * -1.4s);
}
@keyframes dm-pill-bg {
  0%, 9%   { background: var(--bg-sunk);      color: var(--fg-dim);
             border-color: var(--hair-soft); }
  12%, 31% { background: var(--accent-soft);  color: var(--accent-text);
             border-color: color-mix(in oklab, var(--accent) 22%, transparent); }
  34%, 44% { background: var(--info-soft);    color: var(--info-text);
             border-color: color-mix(in oklab, var(--info) 22%, transparent); }
  47%, 92% { background: var(--success-soft); color: var(--success-text);
             border-color: color-mix(in oklab, var(--success) 28%, transparent); }
  100%     { background: var(--bg-sunk);      color: var(--fg-dim);
             border-color: var(--hair-soft); }
}
/* 5 stacked label spans — only one is visible at any moment */
.dormant-mine .dm-pill-lbl {
  display: inline-grid;
}
.dormant-mine .dm-pill-lbl > span {
  grid-area: 1 / 1;
  opacity: 0;
  animation: 14s linear infinite;
  animation-delay: calc(var(--i, 0) * -1.4s);
}
.dormant-mine .dm-pill-lbl .lbl-cold  { animation-name: dm-lbl-cold; }
.dormant-mine .dm-pill-lbl .lbl-scan  { animation-name: dm-lbl-scan; }
.dormant-mine .dm-pill-lbl .lbl-draft { animation-name: dm-lbl-draft; }
.dormant-mine .dm-pill-lbl .lbl-sent  { animation-name: dm-lbl-sent; }
.dormant-mine .dm-pill-lbl .lbl-ok    { animation-name: dm-lbl-ok; }
@keyframes dm-lbl-cold  { 0%, 9% { opacity: 1; } 10%, 100% { opacity: 0; } }
@keyframes dm-lbl-scan  { 0%, 9% { opacity: 0; } 12%, 18% { opacity: 1; } 19%, 100% { opacity: 0; } }
@keyframes dm-lbl-draft { 0%, 18% { opacity: 0; } 21%, 31% { opacity: 1; } 32%, 100% { opacity: 0; } }
@keyframes dm-lbl-sent  { 0%, 31% { opacity: 0; } 34%, 44% { opacity: 1; } 45%, 100% { opacity: 0; } }
@keyframes dm-lbl-ok    { 0%, 44% { opacity: 0; } 47%, 92% { opacity: 1; } 95%, 100% { opacity: 0; } }
/* tiny status dot inside the pill — colour shifts with the row's phase */
.dormant-mine .dm-pill-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--fg-dim);
  animation: dm-dotcolor 14s linear infinite;
  animation-delay: calc(var(--i, 0) * -1.4s);
}
@keyframes dm-dotcolor {
  0%, 9%   { background: var(--fg-dim); }
  12%, 31% { background: var(--accent); }
  34%, 44% { background: var(--info); }
  47%, 92% { background: var(--success); }
  100%     { background: var(--fg-dim); }
}

/* Pink scan-sweep that runs across the row during the scanning phase */
.dormant-mine .dm-scan-sweep {
  position: absolute; top: 0; bottom: 0; left: 0;
  width: 70px;
  background: linear-gradient(90deg,
    transparent,
    color-mix(in oklab, var(--accent) 32%, transparent) 50%,
    transparent);
  pointer-events: none;
  filter: blur(0.4px);
  opacity: 0;
  animation: dm-sweep 14s linear infinite;
  animation-delay: calc(var(--i, 0) * -1.4s);
}
@keyframes dm-sweep {
  0%, 9%   { left: 0;     opacity: 0; }
  10%      { left: 0;     opacity: 1; }
  19%      { left: 100%;  opacity: 1; }
  20%, 100%{ left: 100%;  opacity: 0; }
}

/* Caption below the table */
.dormant-mine .dm-cap {
  text-align: center; max-width: 56ch;
  margin: var(--s-5) auto 0;
  font: 400 13.5px/1.55 var(--f-body); color: var(--fg-soft);
}

/* Responsive — drop the revenue chip below the title on narrow */
@media (max-width: 720px) {
  .dormant-mine .dm-bar { grid-template-columns: 1fr; }
  .dormant-mine .dm-revchip { text-align: left; align-items: flex-start; }
  .dormant-mine .dm-revchip-delta { justify-content: flex-start; }
  .dormant-mine .dm-cols,
  .dormant-mine .dm-row { grid-template-columns: 1.6fr 0.7fr 1fr; gap: 10px; padding: 10px 14px; }
  .dormant-mine .dm-cols .dm-col-last,
  .dormant-mine .dm-row .dm-last { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  /* End-state snapshot: every row replied, every avatar green, every
     pill green, dot green, sweep gone. Same story without motion. */
  .dormant-mine .dm-row,
  .dormant-mine .dm-avatar,
  .dormant-mine .dm-pill,
  .dormant-mine .dm-pill-dot,
  .dormant-mine .dm-pill-lbl > span,
  .dormant-mine .dm-scan-sweep,
  .dormant-mine .dm-livedot { animation: none; }
  .dormant-mine .dm-row { background: color-mix(in oklab, var(--green-500) 9%, var(--paper)); }
  .dormant-mine .dm-avatar { background: var(--success-soft); color: var(--success-text); }
  .dormant-mine .dm-pill { background: var(--success-soft); color: var(--success-text);
                            border-color: color-mix(in oklab, var(--success) 28%, transparent); }
  .dormant-mine .dm-pill-dot { background: var(--success); }
  .dormant-mine .dm-pill-lbl .lbl-ok { opacity: 1; }
  .dormant-mine .dm-pill-lbl .lbl-cold,
  .dormant-mine .dm-pill-lbl .lbl-scan,
  .dormant-mine .dm-pill-lbl .lbl-draft,
  .dormant-mine .dm-pill-lbl .lbl-sent { opacity: 0; }
  .dormant-mine .dm-scan-sweep { opacity: 0; }
}

/* ── 11.2 .scoreboard ─────────────────────────────────────── */
.scoreboard {
  /* Two-sided contrast: red = losing / green = winning.
     Pink stays reserved for brand-signature beats (CTAs, hero markers). */
  --sb-bad:  #D64545;
  --sb-good: var(--green-700);
  display: grid;
  grid-template-columns: minmax(180px, 1fr) 1fr 1fr;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-paper);
  max-width: 860px;
}
.scoreboard .sb-head {
  display: contents;
}
.scoreboard .sb-head > * {
  padding: 16px 20px;
  font: 500 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  background: var(--warm-3); color: var(--fg-soft);
  border-bottom: 1px solid var(--hair);
}
.scoreboard .sb-head .bad  { background: color-mix(in oklab, var(--sb-bad)  14%, var(--warm-3)); color: #7A1515; }
.scoreboard .sb-head .good { background: color-mix(in oklab, var(--sb-good) 18%, var(--warm-3)); color: #0E6A4D; }
.scoreboard .sb-row { display: contents; }
.scoreboard .sb-row > * {
  padding: 14px 20px;
  border-bottom: 1px solid var(--hair-soft);
  font: 400 14px/1.4 var(--f-body);
}
.scoreboard .sb-row:last-child > * { border-bottom: 0; }
.scoreboard .sb-row .label { color: var(--fg-soft); font-weight: 500; }
.scoreboard .sb-row .bad {
  /* Use --error token so the red flips to the brighter dark-mode variant
     (#FF7A7A) on dark paper — hardcoded #7A1515 was nearly invisible there. */
  color: color-mix(in oklab, var(--error) 92%, var(--fg));
  background: color-mix(in oklab, var(--sb-bad) 6%, transparent);
  text-decoration: line-through;
  text-decoration-color: color-mix(in oklab, var(--sb-bad) 60%, transparent);
  text-decoration-thickness: 1.5px;
}
.scoreboard .sb-row .good {
  color: var(--fg); font-weight: 500;
  background: color-mix(in oklab, var(--sb-good) 8%, transparent);
  position: relative;
  overflow: hidden;
}
/* one-shot glow on first reveal */
.scoreboard.is-visible .sb-row .good::before {
  content: ""; position: absolute; inset: 0;
  background: color-mix(in oklab, var(--sb-good) 30%, transparent);
  opacity: 0; pointer-events: none;
  animation: sb-glow 1200ms ease-out 600ms forwards;
}
@keyframes sb-glow { 0% { opacity: 0.6; } 100% { opacity: 0; } }
/* continuous shimmer — narrow diagonal stripe sweeps across every 8s */
.scoreboard.is-visible .sb-row .good::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(
    110deg,
    transparent 0%,
    transparent 35%,
    color-mix(in oklab, var(--sb-good) 28%, transparent) 50%,
    transparent 65%,
    transparent 100%
  );
  background-size: 300% 100%;
  animation: sb-shimmer 8s linear infinite;
  animation-delay: 2s;
}
@keyframes sb-shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .scoreboard.is-visible .sb-row .good::before,
  .scoreboard.is-visible .sb-row .good::after { animation: none; opacity: 0; }
}
.scoreboard.dark {
  background: #1F2338; border-color: rgba(244,236,228,0.1);
  color: var(--paper);
}
.scoreboard.dark .sb-head > * { background: #141828; color: color-mix(in oklab, var(--paper) 70%, transparent); }
.scoreboard.dark .sb-row .label { color: color-mix(in oklab, var(--paper) 70%, transparent); }
.scoreboard.dark .sb-row .bad, .scoreboard.dark .sb-row .good { color: var(--paper); }
.scoreboard-foot {
  margin-top: 14px; padding: 10px 0;
  font: 500 11.5px/1 var(--f-mono); color: var(--fg-faint);
  letter-spacing: 0.08em;
}
.scoreboard-foot strong { color: var(--accent-text); font-weight: 600; }
@media (max-width: 640px) {
  .scoreboard { grid-template-columns: 1fr; }
  .scoreboard .sb-head > * { padding: 12px 16px; }
  .scoreboard .sb-row > * { padding: 12px 16px; }
  .scoreboard .sb-row .label { border-bottom: 0 !important; padding-bottom: 4px; font-weight: 600; }
}

/* ── 11.3 .race-timeline ─────────────────────────────────── */
.race-timeline {
  /* Red = losing, green = winning. Pink is reserved for brand beats elsewhere. */
  --rt-bad:  #D64545;
  --rt-good: var(--green-700);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0;
  max-width: 920px;
  position: relative;
  padding: 8px 0;
}
.race-timeline .rt-head {
  font: 500 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  padding: 8px 16px;
  border-radius: 999px;
  display: inline-flex; align-items: center; gap: 8px;
  justify-self: start;
  margin-bottom: 8px;
}
.race-timeline .rt-head.bad  {
  background: color-mix(in oklab, var(--rt-bad) 16%, transparent);
  color: var(--error-text);
  border: 1px solid color-mix(in oklab, var(--rt-bad) 26%, transparent);
}
.race-timeline .rt-head.good {
  background: color-mix(in oklab, var(--rt-good) 18%, transparent);
  color: var(--success-text);
  border: 1px solid color-mix(in oklab, var(--rt-good) 36%, transparent);
  justify-self: end;
}
.race-timeline .rt-midline {
  width: 2px;
  background: linear-gradient(var(--hair), var(--rt-good));
  border-radius: 2px;
  position: relative;
  grid-row: 2 / span 99;
  margin: 0 var(--s-6);
}
.race-timeline .rt-tick {
  display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: flex-start;
  padding: 10px 0;
}
.race-timeline .rt-left  { grid-column: 1; text-align: right; direction: rtl; }
.race-timeline .rt-left  > * { direction: ltr; }
.race-timeline .rt-right { grid-column: 3; }
.race-timeline .rt-stamp {
  font: 600 12px/1 var(--f-mono); font-variant-numeric: tabular-nums;
  padding: 6px 10px; border-radius: 999px; letter-spacing: 0.05em;
  display: inline-flex; align-items: center; gap: 6px;
}
.race-timeline .rt-left .rt-stamp {
  background: color-mix(in oklab, var(--rt-bad) 14%, transparent);
  color: var(--error-text);                                           /* dark-mode safe */
  border: 1px solid color-mix(in oklab, var(--rt-bad) 22%, transparent);
}
.race-timeline .rt-right .rt-stamp {
  background: color-mix(in oklab, var(--rt-good) 16%, transparent);
  color: var(--success-text);                                         /* dark-mode safe */
  border: 1px solid color-mix(in oklab, var(--rt-good) 28%, transparent);
}
.race-timeline .rt-tick .rt-body {
  font: 400 13.5px/1.45 var(--f-body); color: var(--fg);
}
.race-timeline .rt-tick .rt-body em { color: var(--fg-soft); font-style: normal; display: block; margin-top: 2px; font-size: 12.5px; }
.race-timeline .rt-tick.win .rt-body strong { color: var(--success-text); font-weight: 600; }
.race-timeline .rt-tick.win .rt-stamp {
  position: relative;
}
.race-timeline .rt-tick.win .rt-stamp::after {
  content: "✓"; font-family: var(--f-body); font-size: 13px;
}
/* Pulse ring on the FINAL winning stamp — heartbeat for "appointment booked" */
.race-timeline .rt-tick.win.final .rt-stamp::before {
  content: ""; position: absolute; inset: -2px; border-radius: 999px;
  border: 2px solid var(--rt-good);
  opacity: 0; pointer-events: none;
  animation: rt-ping 2.4s ease-out infinite;
}
@keyframes rt-ping {
  0%   { opacity: 0.7; transform: scale(1); }
  80%  { opacity: 0;   transform: scale(1.6); }
  100% { opacity: 0;   transform: scale(1.6); }
}
@media (prefers-reduced-motion: reduce) {
  .race-timeline .rt-tick.win.final .rt-stamp::before { animation: none; opacity: 0; }
}
@media (max-width: 640px) {
  .race-timeline { grid-template-columns: 1fr; }
  .race-timeline .rt-midline { display: none; }
  .race-timeline .rt-head.good { justify-self: start; margin-top: var(--s-5); }
  .race-timeline .rt-left  { grid-column: 1; text-align: left; direction: ltr; }
  .race-timeline .rt-right { grid-column: 1; }
}

/* ── 11.4 .engine-block ─────────────────────────────────── */
.engine-block {
  display: grid;
  grid-template-columns: minmax(140px, 180px) 1fr minmax(140px, 180px);
  gap: var(--s-5);
  align-items: center;
  max-width: 900px;
  position: relative;
}
/* Flow dots — small pink dots travelling left→core (3 "in" dots) and
   core→right (3 "out" dots). Animate `left` percentages so travel stays
   within the component regardless of viewport width. */
/* Flow dots — hub-and-spoke pattern. 5 pink inbound dots emerge from
   each source card and converge on the CENTRE of the engine block;
   3 green outbound dots fan back out from the centre to each output
   card. Dots sit at z-index: 0 so the dark engine-core (z-index: 1)
   visually swallows them at centre — they appear to travel INTO and
   emerge FROM the block. Per-dot --x / --y set each endpoint's card
   position; --delay staggers the stream. */
.engine-block .eb-flow {
  position: absolute;
  width: 8px; height: 8px; border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%);
  opacity: 0;
  z-index: 0;
  animation-duration: 3.8s;
  animation-timing-function: cubic-bezier(0.55, 0.05, 0.55, 1);
  animation-iteration-count: infinite;
  animation-delay: var(--delay, 0s);
}
.engine-block .eb-flow.in  {
  background: var(--accent);
  box-shadow: 0 0 12px color-mix(in oklab, var(--accent) 75%, transparent);
  animation-name: eb-flow-in;
}
.engine-block .eb-flow.out {
  background: var(--green-500);
  box-shadow: 0 0 12px color-mix(in oklab, var(--green-500) 75%, transparent);
  animation-name: eb-flow-out;
}
/* Inbound — originates at the source card's RIGHT edge (--x: 20%),
   flies diagonally to the engine centre where the core (z-index: 1)
   swallows it. Visible from frame 1; no fade needed. */
@keyframes eb-flow-in {
  0%   { left: var(--x, 20%); top: var(--y, 50%); opacity: 1; }
  100% { left: 50%;            top: 50%;           opacity: 1; }
}
/* Outbound — starts at centre (hidden by core), fans out to the output
   card's LEFT edge (--x: 80%). The card boundary tucks the dot away
   at the end so the loop-teleport back to centre stays invisible. */
@keyframes eb-flow-out {
  0%   { left: 50%;            top: 50%;           opacity: 1; }
  100% { left: var(--x, 80%); top: var(--y, 50%); opacity: 1; }
}
/* Hide flow dots on mobile — grid collapses, horizontal travel is meaningless */
@media (max-width: 720px) {
  .engine-block .eb-flow { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .engine-block .eb-flow { display: none; }
}
.engine-sources, .engine-outputs { display: flex; flex-direction: column; gap: 10px; position: relative; z-index: 2; }
.engine-source, .engine-output {
  /* z-index: 2 lives on the column wrappers above so dots that arrive
     at the card's outer edge (--x: 20% inbound, 80% outbound) tuck
     neatly behind the card boundary instead of bleeding onto it. */
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--bg-paper);
  font: 500 12.5px/1.2 var(--f-body); color: var(--fg);
}
.engine-source .ico, .engine-output .ico {
  width: 22px; height: 22px; flex: 0 0 22px;
  color: var(--accent-text);
  display: inline-flex; align-items: center; justify-content: center;
}
/* Output-side arrows read GREEN to match the outbound flow dots —
   pink = raw lead (source), green = qualified (output). */
.engine-output .ico {
  color: var(--green-500);
}
.engine-source .ico svg, .engine-output .ico svg { width: 100%; height: 100%; }
.engine-output { justify-content: flex-end; text-align: right; }
.engine-centre {
  position: relative;
  aspect-ratio: 1 / 1; min-height: 260px;
  display: grid; place-items: center;
}
.engine-orbit {
  position: absolute; inset: 0;
  pointer-events: none;
}
/* Whole orbit (ring + 4 channels) rotates around the SVG centre.
   Each channel's <text> counter-rotates at the same rate so the label
   stays readable (not flipping upside-down at the bottom of the loop).
   Browsers animate <g transform> reliably — a standalone <circle> alone
   was finicky in Safari. */
.engine-orbit .orbit-anim {
  transform-origin: 160px 160px;
  animation: eb-orbit 24s linear infinite;
}
.engine-orbit .ring {
  stroke: var(--hair); fill: none; stroke-width: 1;
  stroke-dasharray: 3 5;
}
.engine-orbit .orbit-anim .channel .lbl {
  /* transform-origin is set inline per channel to each label's own centre */
  animation: eb-orbit-rev 24s linear infinite;
}
@keyframes eb-orbit     { to { transform: rotate(360deg); } }
@keyframes eb-orbit-rev { to { transform: rotate(-360deg); } }
@media (prefers-reduced-motion: reduce) {
  .engine-orbit .orbit-anim,
  .engine-orbit .orbit-anim .channel .lbl { animation: none; }
}
.engine-orbit .channel .bg { fill: var(--bg-paper); stroke: var(--hair); stroke-width: 1; }
.engine-orbit .channel .lbl { fill: var(--fg); }                   /* dark-mode safe */
/* Channel labels — perfectly centred. `dominant-baseline: central`
   alone is inconsistent across browsers; combining it with a tiny
   optical push of y ensures SMS/MAIL/CHAT/VOICE all sit exactly on
   the horizontal midline of their circle. */
.engine-orbit .channel .lbl {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-weight: 600;
  font-size: 9.5px;
  letter-spacing: 0.04em;
  dominant-baseline: central;
  text-anchor: middle;
}
.engine-core {
  position: relative; z-index: 1;
  width: 58%; aspect-ratio: 1;
  border-radius: var(--r-lg);
  background: var(--ink); color: var(--paper);
  display: grid; place-items: center;
  padding: 14px; text-align: center;
  box-shadow: 0 24px 50px -24px color-mix(in oklab, var(--ink) 55%, transparent),
              0 0 0 1px rgba(255,63,122,0.18) inset;
  overflow: hidden;
}
.engine-core::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(120% 120% at 80% 0%, rgba(255,63,122,0.22), transparent 60%);
  pointer-events: none;
}
.engine-core::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(60% 40% at 50% 100%, rgba(255,63,122,0.16), transparent 70%);
  animation: eb-glow 3s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes eb-glow { from { opacity: 0.4; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .engine-core::after { animation: none; opacity: 0.7; } }
.engine-core .label {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: color-mix(in oklab, var(--paper) 70%, transparent);
  position: relative; z-index: 1;
  margin-bottom: 8px;
}
.engine-core .name {
  font: 700 22px/1.08 var(--f-display); letter-spacing: -0.01em;
  position: relative; z-index: 1;
}
.engine-core .name em { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: color-mix(in oklab, var(--accent) 70%, var(--paper)); font-variation-settings: "SOFT" 80; }
.engine-core .pill-row { margin-top: 10px; display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; position: relative; z-index: 1; }
.engine-core .pill-row span {
  font: 500 10px/1 var(--f-mono); padding: 4px 8px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--paper) 14%, transparent);
  color: color-mix(in oklab, var(--paper) 80%, transparent);
  letter-spacing: 0.06em; text-transform: uppercase;
}
@media (max-width: 720px) {
  .engine-block { grid-template-columns: 1fr; }
  .engine-centre { min-height: 320px; }
  .engine-orbit { display: none; }
  .engine-sources, .engine-outputs { flex-direction: row; flex-wrap: wrap; gap: 6px; }
  .engine-source, .engine-output { flex: 1 1 auto; padding: 8px 10px; font-size: 11.5px; }
}

/* ── 11.5 .triptych ─────────────────────────────────────── */
.triptych {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  gap: var(--s-5);
  align-items: stretch;
  max-width: 1080px;
}
.triptych .panel {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  display: flex; flex-direction: column; gap: var(--s-3);
  min-height: 260px;
}
.triptych .panel .step {
  font: 600 11px/1 var(--f-mono); color: var(--accent-text);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.triptych .panel h4 {
  font: 600 22px/1.2 var(--f-display); letter-spacing: -0.01em;
  margin: 0; color: var(--fg);
}
.triptych .panel p {
  font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 0;
}
.triptych .panel .art {
  margin-top: auto; padding-top: var(--s-4);
  display: grid; place-items: center;
  min-height: 96px;                              /* fits the bigger .spark + its halo */
}
.triptych .arrow {
  display: grid; place-items: center;
  color: var(--fg-faint);
  position: relative;
}
.triptych .arrow svg { width: 28px; height: 28px; }
/* Travelling pulse on each arrow — a small pink dot slides across */
.triptych .arrow::after {
  content: ""; position: absolute; top: 50%;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px color-mix(in oklab, var(--accent) 60%, transparent);
  transform: translateY(-50%);
  animation: trp-flow 3s ease-in-out infinite;
  pointer-events: none;
}
.triptych .arrow:nth-of-type(4)::after { animation-delay: 1s; }
@keyframes trp-flow {
  0%   { left: 0%;   opacity: 0; }
  20%  { opacity: 1; }
  80%  { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}
@media (max-width: 880px) {
  .triptych { grid-template-columns: 1fr; }
  .triptych .arrow { transform: rotate(90deg); justify-self: center; }
  /* Flip flow direction on mobile too (transform rotates the container so the ::after follows) */
}
@media (prefers-reduced-motion: reduce) {
  .triptych .arrow::after { animation: none; opacity: 0; }
}

/* ── 11.6 .handoff-card ─────────────────────────────────── */
.handoff-card {
  --ho-accent: var(--accent);
  width: 100%; max-width: 380px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  position: relative;
  box-shadow: 0 6px 14px -10px rgba(25,30,50,0.1);
  opacity: 0;
  transform: translateY(28px) scale(0.96);
  transition:
    opacity 600ms var(--ease),
    transform 600ms var(--ease),
    box-shadow 600ms var(--ease);
  transition-delay: calc(var(--i, 0) * 100ms);
}
/* Once in view: visible lift + full shadow */
.handoff-card.is-visible {
  opacity: 1;
  transform: none;
  box-shadow: 0 22px 48px -24px rgba(25,30,50,0.28);
  animation: ho-breathe 5.2s ease-in-out infinite;
  animation-delay: 900ms;
}
@keyframes ho-breathe {
  0%, 100% { box-shadow: 0 22px 48px -24px rgba(25,30,50,0.28); }
  50%      { box-shadow: 0 28px 58px -22px rgba(25,30,50,0.34); }
}
@media (prefers-reduced-motion: reduce) {
  .handoff-card { opacity: 1; transform: none; transition: none; }
  .handoff-card.is-visible { animation: none; box-shadow: 0 22px 48px -24px rgba(25,30,50,0.28); }
}
.handoff-card[data-role="insurance-agent"]     { --ho-accent: var(--green-700); }
.handoff-card[data-role="counsellor"]          { --ho-accent: var(--blue-700); }
.handoff-card[data-role="front-desk"]          { --ho-accent: var(--yellow-700); }
.handoff-card[data-role="booking-specialist"]  { --ho-accent: #C77A3E; }
.handoff-card .ho-band {
  padding: 14px 18px;
  background: color-mix(in oklab, var(--ho-accent) 12%, var(--bg-paper));
  display: flex; align-items: center; gap: 12px;
  border-bottom: 1px solid color-mix(in oklab, var(--ho-accent) 22%, transparent);
}
.handoff-card .ho-av {
  width: 40px; height: 40px; border-radius: 50%;
  background: linear-gradient(135deg, color-mix(in oklab, var(--ho-accent) 60%, #FFD878), var(--ho-accent));
  color: var(--paper);
  font: 600 15px/1 var(--f-display);
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.handoff-card .ho-who { min-width: 0; flex: 1; }
.handoff-card .ho-who .name {
  font: 600 15px/1.2 var(--f-body); color: var(--fg); margin: 0;
  position: relative; display: inline-block;
}
.handoff-card.is-visible .ho-who .name::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 2px;
  background: var(--ho-accent);
  transform-origin: left;
  animation: ho-underline 700ms ease-out 300ms backwards;
}
@keyframes ho-underline { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.handoff-card .ho-who .role {
  margin: 4px 0 0; font: 500 11px/1 var(--f-mono);
  color: color-mix(in oklab, var(--ho-accent) 80%, var(--fg-soft));
  text-transform: uppercase; letter-spacing: 0.08em;
}
.handoff-card .ho-stamp { font: 500 11px/1 var(--f-mono); color: var(--fg-soft); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.handoff-card .ho-tags {
  padding: 14px 18px 10px;
  display: flex; flex-wrap: wrap; gap: 6px;
  border-bottom: 1px solid var(--hair-soft);
}
.handoff-card .ho-tag {
  font: 500 11px/1 var(--f-body);
  padding: 5px 10px; border-radius: 999px;
  background: color-mix(in oklab, var(--ho-accent) 10%, var(--bg-paper));
  border: 1px solid color-mix(in oklab, var(--ho-accent) 20%, transparent);
  color: var(--fg);
}
.handoff-card .ho-tag.lead { background: var(--ho-accent); color: var(--paper); border-color: transparent; }
.handoff-card .ho-facts {
  padding: 14px 18px;
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px;
  border-bottom: 1px solid var(--hair-soft);
}
.handoff-card .ho-fact .k {
  font: 500 9.5px/1 var(--f-mono); color: var(--fg-faint);
  text-transform: uppercase; letter-spacing: 0.12em;
  margin-bottom: 4px;
}
.handoff-card .ho-fact .v {
  font: 600 15px/1.2 var(--f-display); color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.handoff-card .ho-fact .v em { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: var(--ho-accent); }
.handoff-card .ho-cta {
  padding: 12px 18px;
  display: flex; gap: 8px; flex-wrap: wrap;
}
.handoff-card .ho-cta button {
  appearance: none; -webkit-appearance: none;
  border: 1px solid var(--hair);
  background: var(--bg-paper); color: var(--fg);
  font: 500 11px/1 var(--f-mono); letter-spacing: 0.06em;
  padding: 8px 12px; border-radius: 999px;
  cursor: pointer; text-transform: uppercase;
}
.handoff-card .ho-cta button.primary {
  background: var(--ho-accent); color: var(--paper); border-color: transparent;
}
.handoff-card .ho-pulse {
  position: absolute; top: 14px; right: 14px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--ho-accent);
  box-shadow: 0 0 0 0 color-mix(in oklab, var(--ho-accent) 50%, transparent);
  animation: ho-pulse 2s ease-out infinite;
}
@keyframes ho-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in oklab, var(--ho-accent) 55%, transparent); }
  100% { box-shadow: 0 0 0 12px color-mix(in oklab, var(--ho-accent) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .handoff-card .ho-pulse { animation: none; }
  .handoff-card.is-visible .ho-who .name::after { animation: none; transform: scaleX(1); }
}

/* ── 11.7 .profile-card ─────────────────────────────────── */
.profile-card {
  width: 100%; max-width: 360px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  padding: 0;
}
.profile-card .pc-head {
  padding: 14px 18px 8px;
  display: flex; align-items: center; gap: 10px;
}
.profile-card .pc-av {
  width: 36px; height: 36px; border-radius: 50%;
  background: linear-gradient(135deg, var(--pink-300), var(--accent));
  color: var(--paper);
  font: 600 13px/1 var(--f-display);
  display: inline-flex; align-items: center; justify-content: center;
}
.profile-card .pc-name { font: 600 14px/1.2 var(--f-body); color: var(--fg); margin: 0; }
.profile-card .pc-email { margin: 2px 0 0; font: 500 11.5px/1 var(--f-mono); color: var(--fg-soft); }
.profile-card .pc-bars {
  padding: 6px 18px 10px;
  display: flex; gap: 4px;
}
.profile-card .pc-bar {
  flex: 1; height: 3px; border-radius: 2px;
  background: var(--hair);
  transition: background 400ms var(--ease);
}
.profile-card[data-step="1"] .pc-bar:nth-child(-n+1),
.profile-card[data-step="2"] .pc-bar:nth-child(-n+2),
.profile-card[data-step="3"] .pc-bar:nth-child(-n+3),
.profile-card[data-step="4"] .pc-bar:nth-child(-n+4),
.profile-card[data-step="5"] .pc-bar { background: var(--accent); }
.profile-card .pc-rows { padding: 0 0 8px; }
.profile-card .pc-row {
  padding: 10px 18px;
  display: grid; grid-template-columns: 22px 1fr auto; gap: 10px;
  align-items: center;
  border-top: 1px solid var(--hair-soft);
  font: 400 13px/1.35 var(--f-body); color: var(--fg);
  opacity: 0; transform: translateY(4px);
  transition: opacity 300ms var(--ease), transform 300ms var(--ease);
}
.profile-card .pc-row .ico { color: var(--accent-text); display: inline-flex; align-items: center; justify-content: center; }
.profile-card .pc-row .ico svg { width: 18px; height: 18px; }
.profile-card .pc-row .meta { font: 500 10.5px/1 var(--f-mono); color: var(--fg-faint); letter-spacing: 0.06em; }
.profile-card[data-step="1"] .pc-row:nth-child(-n+1),
.profile-card[data-step="2"] .pc-row:nth-child(-n+2),
.profile-card[data-step="3"] .pc-row:nth-child(-n+3),
.profile-card[data-step="4"] .pc-row:nth-child(-n+4),
.profile-card[data-step="5"] .pc-row { opacity: 1; transform: none; }
.profile-card.is-dormant { filter: grayscale(0.6); opacity: 0.7; transition: filter 600ms, opacity 600ms; }
.profile-card.is-reactivated { filter: none; opacity: 1; box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 30%, transparent); }
.profile-card .pc-status {
  padding: 10px 18px; border-top: 1px solid var(--hair-soft);
  font: 500 11px/1 var(--f-mono); color: var(--fg-faint);
  letter-spacing: 0.08em; text-transform: uppercase;
  display: flex; justify-content: space-between; align-items: center;
}
.profile-card.is-reactivated .pc-status { color: var(--accent-text); }

/* ── 11.8 .integration-hub ─────────────────────────────── */
.integration-hub {
  position: relative;
  width: 100%; max-width: 520px; aspect-ratio: 1;
  margin: 0 auto;
}
.integration-hub .hub-core {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 36%; aspect-ratio: 1;
  border-radius: var(--r-lg);
  background: var(--ink); color: var(--paper);
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  box-shadow: 0 12px 30px -15px color-mix(in oklab, var(--ink) 60%, transparent),
              0 0 0 1px rgba(255,63,122,0.18) inset;
  z-index: 2;
  overflow: hidden;
}
.integration-hub .hub-core::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: radial-gradient(100% 80% at 50% 0%, rgba(255,63,122,0.22), transparent 70%);
  pointer-events: none;
  z-index: 0;
}
.integration-hub .hub-core img {
  width: 62%; height: 62%;                /* sits in a generous inner frame, centred */
  object-fit: contain;
  position: relative; z-index: 1;
  display: block;
}
.integration-hub .spokes {
  position: absolute; inset: 0; z-index: 1;
}
.integration-hub .spokes line {
  stroke: color-mix(in oklab, var(--accent) 35%, var(--hair));
  stroke-width: 1;
  stroke-dasharray: 3 6;
  animation: ih-flow 3s linear infinite;
}
/* Each spoke gets a small stagger so they're not all in lockstep */
.integration-hub .spokes line:nth-child(1) { animation-delay: 0s; }
.integration-hub .spokes line:nth-child(2) { animation-delay: -0.3s; }
.integration-hub .spokes line:nth-child(3) { animation-delay: -0.6s; }
.integration-hub .spokes line:nth-child(4) { animation-delay: -0.9s; }
.integration-hub .spokes line:nth-child(5) { animation-delay: -1.2s; }
.integration-hub .spokes line:nth-child(6) { animation-delay: -1.5s; }
.integration-hub .spokes line:nth-child(7) { animation-delay: -1.8s; }
.integration-hub .spokes line:nth-child(8) { animation-delay: -2.1s; }
@keyframes ih-flow {
  from { stroke-dashoffset: 18; }
  to   { stroke-dashoffset: 0; }   /* dashes flow toward the centre */
}
@media (prefers-reduced-motion: reduce) {
  .integration-hub .spokes line { animation: none; }
}
.integration-hub .nodes {
  position: absolute; inset: 0; z-index: 3;
}
.integration-hub .node {
  position: absolute;
  transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px;
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: 999px;
  font: 500 11px/1 var(--f-mono); color: var(--fg);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.integration-hub .node .ico { width: 14px; height: 14px; color: var(--accent-text); display: inline-flex; }
.integration-hub .node .ico svg { width: 100%; height: 100%; }
.integration-hub.read-act-write .band {
  fill: none; stroke: var(--hair);
  stroke-dasharray: 2 6;
}

/* ── 11.9 .happa-arc ─────────────────────────────────── */
.happa-arc {
  position: relative;
  width: 100%; max-width: 1080px;
  padding: 20px 0 60px;
}
.happa-arc svg { width: 100%; height: auto; display: block; }
.happa-arc .arc-path {
  fill: none; stroke: var(--fg);           /* dark-mode safe — flips to warm cream on dark */
  stroke-width: 2;
  stroke-linecap: round; stroke-dasharray: 6 8;
}
.happa-arc .node-ring { fill: var(--bg-paper); stroke: var(--accent); stroke-width: 2; }
.happa-arc .node-letter {
  font: 700 22px/1 var(--f-display); fill: var(--accent); text-anchor: middle; dominant-baseline: central;
}
.happa-arc .node-label {
  font: 600 16px/1 var(--f-display); fill: var(--fg); text-anchor: middle; letter-spacing: -0.005em;
}
.happa-arc .node-desc {
  font: 400 14px/1.3 var(--f-body); fill: var(--fg-soft); text-anchor: middle;
}
.happa-arc .tracer-halo { fill: color-mix(in oklab, var(--accent) 30%, transparent); }
.happa-arc .tracer-dot  { fill: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .happa-arc .tracer { display: none; }
}

/* ── 11.10 .guardian-shield ─────────────────────────── */
.guardian-shield {
  position: relative;
  width: 100%; max-width: 320px;
  margin: 0 auto;
}
.guardian-shield svg { width: 100%; height: auto; display: block; }
.guardian-shield .sh-body {
  fill: color-mix(in oklab, var(--ink) 94%, transparent);
  stroke: var(--accent); stroke-width: 2.4;
}
.guardian-shield .sh-shine {
  fill: url(#shShine); pointer-events: none;
  transform-origin: center; transform-box: view-box;
  animation: gs-shine 5.5s ease-in-out infinite;
}
/* Shine sweeps subtly across the shield — suggests active protection */
@keyframes gs-shine {
  0%, 100% { transform: translateX(-8%); opacity: 0.85; }
  50%      { transform: translateX(8%);  opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .guardian-shield .sh-shine { animation: none; }
}
.guardian-shield .sh-items {
  position: absolute;
  /* Single-column stack fills the shield's tall shape naturally — the
     old 2×3 grid left dead space above and below the centred items.
     Bigger inset rings the stack with breathing room on all sides. */
  inset: 20% 22% 22% 22%;
  display: flex; flex-direction: column;
  justify-content: center;
  gap: 14px;
}
.guardian-shield .sh-item {
  display: flex; align-items: center; gap: 10px;
  min-width: 0;
  font: 600 12.5px/1.15 var(--f-mono);
  color: color-mix(in oklab, var(--paper) 94%, transparent);
  letter-spacing: 0.08em; text-transform: uppercase;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.guardian-shield .sh-item::before {
  content: ""; width: 14px; height: 14px; flex: 0 0 14px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-grid; place-items: center;
  /* a tiny white ✓ baked into the bullet disc */
  background-image:
    linear-gradient(transparent, transparent),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'><path d='M2 5l2 2 4-4' fill='none' stroke='white' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-size: cover;
}
.guardian-shield .sh-caption {
  text-align: center; margin-top: 12px;
  font: 500 11.5px/1 var(--f-mono); color: var(--fg-soft);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.guardian-shield .sh-caption strong { color: var(--accent-text); font-weight: 600; }

/* ── 11.11 .journey-map ─────────────────────────────── */
.journey-map {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: 10px;
  max-width: 1080px;
}
.journey-map .jm-node {
  position: relative;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: 10px 14px;
  min-width: 140px;
  display: flex; flex-direction: column; gap: 4px;
}
.journey-map .jm-node .jm-k { font: 500 10px/1 var(--f-mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-faint); }
.journey-map .jm-node .jm-t { font: 500 13px/1.25 var(--f-body); color: var(--fg); }
.journey-map .jm-node.start {
  background: var(--accent); color: var(--paper); border-color: transparent;
  position: relative;
  box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 50%, transparent);
  animation: jm-pulse 2.8s ease-out infinite;
}
.journey-map .jm-node.start .jm-k { color: color-mix(in oklab, var(--paper) 90%, transparent); }
.journey-map .jm-node.start .jm-t { color: var(--paper); }
/* Heartbeat on the start node — signals "live inbound" */
@keyframes jm-pulse {
  0%, 100% { box-shadow: 0 0 0 0   color-mix(in oklab, var(--accent) 55%, transparent); }
  60%      { box-shadow: 0 0 0 12px color-mix(in oklab, var(--accent) 0%,  transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .journey-map .jm-node.start { animation: none; }
}
.journey-map .jm-node.end     { background: var(--warm-3); border-color: var(--warm-5); }
.journey-map .jm-node.nurture { border-style: dashed; }

/* Stage-active ring — overlays a pink glow ring on each non-start node
   in sequence (01 → 02 → three branches fanning out) so the viewer
   watches a lead flow through the prequalification journey. 10s loop:
     0.5–2.5s  node 01 active
     2.5–4.5s  node 02 active
     4.5–6.5s  all 3 branches active (staggered fan-out)
     6.5–10s   rest, then loop. */
.journey-map .jm-node:not(.start) { position: relative; }
.journey-map .jm-node:not(.start)::after {
  content: "";
  position: absolute; inset: -2px;
  border: 2px solid var(--accent);
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 18%, transparent),
              0 8px 18px color-mix(in oklab, var(--accent) 22%, transparent);
  animation: jm-stage-active 10s ease-in-out infinite;
  animation-delay: var(--jm-delay, 0s);
}
@keyframes jm-stage-active {
  0%, 100% { opacity: 0; }
  5%       { opacity: 1; }
  25%      { opacity: 1; }
  30%      { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .journey-map .jm-node:not(.start)::after { animation: none; opacity: 0; }
}
.journey-map .jm-connector {
  display: inline-flex; align-items: center;
  min-height: 40px;
}
.journey-map .jm-connector svg { display: block; }
.journey-map .jm-label {
  font: 500 10px/1 var(--f-mono); color: var(--fg-faint);
  letter-spacing: 0.08em; text-transform: uppercase;
  align-self: center;
  padding: 0 4px;
}
.journey-map .jm-branch {
  display: grid; gap: 6px; padding: 4px 0;
}

/* ── 11.12 .edge-race ─ "Closest edge wins" radar ─────────
   Replaces the literal world-map version that suggested data has
   to travel FAR. Here YOU sit at the centre of concentric distance
   rings; edges (real cities) scatter around you. On each cycle a
   pulse races from every edge towards the centre — the fastest
   arrival wins, gets ringed in success-green with a latency badge,
   and the connecting line solidifies. Then the scene transitions
   to the next region (US-WEST → US-EAST → EUROPE → ASIA →
   OCEANIA, looping). Tells the proximity / low-latency story
   directly: the closest one always wins. CSS for visuals; JS at
   the bottom of the page sequences the race and city placements. */
.edge-race {
  position: relative;
  width: 100%;
  max-width: 540px;
  aspect-ratio: 1 / 1;
  /* Vertical breathing room — the pager dots sit at bottom: -28px and the
     region pill at top: -8px, so account for both plus a comfortable gap. */
  margin: var(--s-6) auto var(--s-7);
}

/* Concentric dashed rings — distance bands around the user */
.edge-race .er-ring {
  position: absolute; left: 50%; top: 50%;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  border: 1px dashed color-mix(in oklab, var(--accent) 22%, transparent);
}
.edge-race .er-ring.r1 { width: 50%;  height: 50%; }
.edge-race .er-ring.r2 { width: 80%;  height: 80%; }
.edge-race .er-ring.r3 {
  width: 100%; height: 100%;
  border-style: solid;
  border-color: color-mix(in oklab, var(--accent) 12%, transparent);
}

/* Region pill — top-left of the stage */
.edge-race .er-region {
  position: absolute;
  top: -8px; left: -8px;
  font: 600 10.5px/1 var(--f-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-text);
  background: var(--bg-paper);
  border: 1px solid color-mix(in oklab, var(--accent) 30%, var(--hair));
  padding: 5px 11px;
  border-radius: 4px;
  white-space: nowrap;
  z-index: 7;
  transition: opacity 0.4s;
}

/* The user node — dark dot with cream centre, sits at the centre */
.edge-race .er-you {
  position: absolute;
  left: 50%; top: 50%;
  width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  border-radius: 50%;
  background: var(--ink);
  box-shadow:
    0 0 0 4px var(--bg-paper),
    0 0 0 5.5px color-mix(in oklab, var(--ink) 18%, transparent),
    0 4px 14px color-mix(in oklab, var(--ink) 25%, transparent);
  z-index: 5;
}
.edge-race .er-you::before {
  content: '';
  position: absolute; inset: 6px;
  border-radius: 50%;
  background: var(--bg-paper);
}

/* User label below the centre dot */
.edge-race .er-you-label {
  position: absolute;
  left: 50%; top: calc(50% + 22px);
  transform: translateX(-50%);
  text-align: center;
  z-index: 5;
  transition: opacity 0.4s;
}
.edge-race .er-you-label .kicker {
  font: 600 9.5px/1 var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--fg-soft);
  text-transform: uppercase;
}
.edge-race .er-you-label .name {
  display: block; margin-top: 6px;
  font: 600 14px/1.2 var(--f-display);
  color: var(--fg);
  letter-spacing: -0.01em;
}

/* User halo — slow pulse radiating outward, two staggered instances */
.edge-race .er-halo {
  position: absolute;
  left: 50%; top: 50%;
  width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  border-radius: 50%;
  border: 1.5px solid color-mix(in oklab, var(--ink) 40%, transparent);
  animation: er-halo 3s ease-out infinite;
  z-index: 4;
  pointer-events: none;
}
@keyframes er-halo {
  0%   { transform: scale(1);   opacity: 0.7; }
  80%  { opacity: 0; }
  100% { transform: scale(4.5); opacity: 0; }
}

/* SVG layer for ping lines + travelling pulse circles */
.edge-race .er-lines {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
}

/* Server (edge city) dots — small open rings around the rim */
.edge-race .er-server {
  position: absolute;
  width: 14px; height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: var(--bg-paper);
  border: 2px solid color-mix(in oklab, var(--accent) 35%, transparent);
  z-index: 3;
  transition: border-color 0.5s, background 0.5s, transform 0.5s, box-shadow 0.5s;
}
.edge-race .er-server::before {
  content: ''; position: absolute; inset: 2px;
  border-radius: 50%;
  background: color-mix(in oklab, var(--warm-5) 70%, var(--bg-paper));
  transition: background 0.5s, inset 0.5s;
}
.edge-race .er-server.is-winner {
  border-color: var(--success-text);
  background: var(--success-text);
  transform: scale(1.3);
  box-shadow:
    0 0 0 3px var(--bg-paper),
    0 0 0 4.5px color-mix(in oklab, var(--success) 45%, transparent),
    0 0 18px color-mix(in oklab, var(--success) 55%, transparent);
}
.edge-race .er-server.is-winner::before {
  background: var(--bg-paper);
  inset: 4px;
}

/* City label next to each server dot */
.edge-race .er-city {
  position: absolute;
  transform: translate(-50%, -50%);
  font: 500 11.5px/1 var(--f-body);
  color: var(--fg-soft);
  white-space: nowrap;
  z-index: 4;
  pointer-events: none;
  background: var(--bg-paper);
  padding: 1px 5px;
  border-radius: 3px;
  transition: color 0.4s, font-weight 0.4s;
}
.edge-race .er-city.is-winner {
  color: var(--success-text);
  font-weight: 700;
}

/* Latency badge — appears next to the winning server with the ms value */
.edge-race .er-badge {
  position: absolute;
  transform: translate(-50%, calc(-100% - 14px));
  font: 600 11.5px/1 var(--f-mono);
  letter-spacing: 0.05em;
  color: var(--bg-paper);
  background: var(--ink);
  padding: 4px 9px;
  border-radius: 5px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  z-index: 6;
  transition: opacity 0.35s, left 0.35s, top 0.35s;
}
.edge-race .er-badge.is-show {
  opacity: 1;
  background: var(--success-text);
}
.edge-race .er-badge .num { color: color-mix(in oklab, var(--success) 70%, white); }
.edge-race .er-badge::after {
  content: '';
  position: absolute;
  left: 50%; bottom: -4px;
  transform: translateX(-50%) rotate(45deg);
  width: 7px; height: 7px;
  background: var(--ink);
  transition: background 0.35s;
}
.edge-race .er-badge.is-show::after { background: var(--success-text); }

/* Ping lines (SVG <line>s, one per edge) */
.edge-race .er-line {
  stroke: color-mix(in oklab, var(--accent) 32%, transparent);
  stroke-width: 1;
  fill: none;
  stroke-dasharray: 3 4;
  opacity: 0.55;
  transition: opacity 0.5s, stroke 0.5s, stroke-width 0.5s;
}
.edge-race .er-line.is-winner {
  stroke: var(--success-text);
  stroke-width: 1.6;
  stroke-dasharray: none;
  opacity: 1;
}
.edge-race .er-line.is-fading { opacity: 0.1; }

/* Travelling pulse circles (SVG <circle>s, one per edge).
   Use bright --accent (pink-700) for the decorative pulse — these are
   shapes, not text, so AA-text scoping doesn't apply and the bright
   brand pop reads better than the burgundy --accent-text variant. */
.edge-race .er-pulse { fill: var(--accent); }
.edge-race .er-pulse.is-winner { fill: var(--success); }

/* Region pager dots — bottom of the stage */
.edge-race .er-pager {
  position: absolute;
  bottom: -28px; left: 50%;
  transform: translateX(-50%);
  display: flex; gap: 8px;
}
.edge-race .er-pager .pd {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: color-mix(in oklab, var(--accent) 25%, transparent);
  transition: background 0.3s, transform 0.3s;
}
.edge-race .er-pager .pd.is-active {
  /* Bright --accent for decorative active state — same reasoning as the
     pulse circles. Inactive dots stay at low-opacity --accent. */
  background: var(--accent);
  transform: scale(1.4);
}

@media (prefers-reduced-motion: reduce) {
  .edge-race .er-halo { animation: none !important; opacity: 0; }
}

/* Dark-mode lift for the radar.
   In dark, --bg-paper flips to dark navy and --warm-5 reads near-black, so
   the original light-mode design (cream-on-paper centre dot, faint pink
   rings, cream-tinted city dots, pill-bg city labels) collapses into
   low-contrast mush. Invert the centre, brighten the dashed rings, give
   city dots a brighter pink border with a paper-tinted interior, and drop
   the city-label background pill since the stage itself is already dark. */
body[data-theme="dark"] .edge-race .er-ring {
  border-color: color-mix(in oklab, var(--accent) 38%, transparent);
}
body[data-theme="dark"] .edge-race .er-ring.r3 {
  border-color: color-mix(in oklab, var(--accent) 22%, transparent);
}
body[data-theme="dark"] .edge-race .er-you {
  background: var(--paper);
  box-shadow:
    0 0 0 4px color-mix(in oklab, var(--paper) 14%, transparent),
    0 0 0 5.5px color-mix(in oklab, var(--paper) 7%, transparent),
    0 4px 14px color-mix(in oklab, var(--paper) 18%, transparent);
}
body[data-theme="dark"] .edge-race .er-you::before {
  background: var(--ink);
}
body[data-theme="dark"] .edge-race .er-halo {
  border-color: color-mix(in oklab, var(--paper) 50%, transparent);
}
body[data-theme="dark"] .edge-race .er-server {
  border-color: color-mix(in oklab, var(--accent) 55%, transparent);
}
body[data-theme="dark"] .edge-race .er-server::before {
  background: color-mix(in oklab, var(--paper) 78%, transparent);
}
body[data-theme="dark"] .edge-race .er-city {
  background: transparent;
  color: color-mix(in oklab, var(--paper) 88%, transparent);
}

/* ── 11.13 .ecosystem-rings ───────────────────────────── */
.ecosystem-rings {
  position: relative;
  width: 100%; max-width: 560px; aspect-ratio: 1;
  margin: 0 auto;
}
.ecosystem-rings svg { width: 100%; height: 100%; display: block; }
.ecosystem-rings .er-ring {
  fill: none; stroke: var(--hair); stroke-width: 1; stroke-dasharray: 2 5;
  transform-origin: center; transform-box: fill-box;
  animation: er-spin 120s linear infinite;
}
.ecosystem-rings .er-ring.outer {
  stroke: color-mix(in oklab, var(--accent) 32%, transparent);
  animation: er-spin-rev 80s linear infinite;
}
/* Slow contra-rotation gives the ecosystem a subtle living-depth feel. */
@keyframes er-spin     { to { transform: rotate(360deg); } }
@keyframes er-spin-rev { to { transform: rotate(-360deg); } }
.ecosystem-rings .er-core { fill: var(--ink); }
@media (prefers-reduced-motion: reduce) {
  .ecosystem-rings .er-ring { animation: none; }
}
/* Labels are HTML overlays — precise placement + pill backgrounds prevent
   the two rings' labels from ever touching each other or the dashes. */
.ecosystem-rings .er-core-label {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  color: var(--paper);
  pointer-events: none;
  z-index: 3;
}
.ecosystem-rings .er-core-label .kicker {
  display: block;
  font: 500 9.5px/1 var(--f-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: color-mix(in oklab, var(--paper) 62%, transparent);
  margin-bottom: 4px;
}
.ecosystem-rings .er-core-label .name {
  display: block;
  font: 700 15px/1.15 var(--f-display); letter-spacing: -0.01em;
}
.ecosystem-rings .er-label {
  position: absolute;
  transform: translate(-50%, -50%);
  font: 600 10.5px/1 var(--f-mono); color: var(--fg);
  letter-spacing: 0.1em; text-transform: uppercase;
  white-space: nowrap;
  padding: 5px 10px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: 999px;
  z-index: 2;
}
.ecosystem-rings .er-label.outer {
  color: var(--accent-text);
  border-color: color-mix(in oklab, var(--accent) 30%, transparent);
  background: color-mix(in oklab, var(--accent) 7%, var(--bg-paper));
}
/* Dark mode: bg-paper flips to dark navy and a 7% pink tint disappears against
   it. Lift the fill (22%) and the border (52%) so the outer pills read clearly. */
body[data-theme="dark"] .ecosystem-rings .er-label.outer {
  background: color-mix(in oklab, var(--accent) 22%, var(--bg-paper));
  border-color: color-mix(in oklab, var(--accent) 52%, transparent);
}

/* ── 11.14 .roi-calc — dual-tab revenue calculator ───────
   Two modes in one widget: Activation (convert more inbound) and
   Reactivation (re-engage aged database). Uses plan-aware MagicBlocks
   pricing to compute actual cost, ROI multiple, and payback period.
   Dark-ink surface so the numbers pop; pink radial glow in the output
   column. All colours via tokens — dark-mode safe. */
.roi-calc {
  width: 100%;
  max-width: min(960px, 100%);
  margin: 0 auto;
}
/* Nuke browser default <p> / <h*> margins inside the calc so the
   intentional spacing rules (padding-bottom on .roi-result etc) are
   the only thing driving vertical rhythm. Without this reset, a 22px
   .roi-result-value <p> inherits ~22px top + 22px bottom margin from
   the UA stylesheet, compounding to ~250px of phantom gap across
   the 6 rows on the right column.
   Uses :where() so the reset has specificity (0,1,0) — same as a
   single class — letting class rules like .roi-result-label
   margin-bottom override it cleanly on source order. */
.roi-calc :where(p, h2, h3) { margin: 0; }
.roi-calc-eyebrow {
  font: 600 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.16em;
  color: var(--fg-dim);
  text-align: center;
  margin-bottom: var(--s-2);
}
.roi-calc-title {
  font: 700 clamp(22px, 3.2vw, 32px)/1.2 var(--f-display);
  letter-spacing: -0.02em;
  color: var(--fg);
  text-align: center;
  margin: 0 0 var(--s-2);
  text-wrap: balance;
}
.roi-calc-title em {
  font-family: var(--f-italic);
  font-style: italic; font-weight: 500;
  color: var(--accent-text);
  font-variation-settings: "SOFT" 80;
}
.roi-calc-subtitle {
  font: 400 15px/1.55 var(--f-body);
  color: var(--fg-soft);
  text-align: center;
  max-width: 560px;
  margin: 0 auto var(--s-6);
}

/* Tab switcher — pill-segmented control */
.roi-tabs {
  display: flex;
  background: var(--bg-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: 4px;
  margin-bottom: var(--s-5);
  gap: 4px;
  max-width: 560px; margin-left: auto; margin-right: auto;
}
.roi-tab-btn {
  flex: 1;
  padding: 10px 14px;
  font: 600 14px/1.3 var(--f-display);
  letter-spacing: -0.005em;
  color: var(--fg-soft);
  background: transparent;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: color var(--dur-2) var(--ease),
              background var(--dur-2) var(--ease),
              box-shadow var(--dur-2) var(--ease);
  text-align: center;
}
.roi-tab-btn:hover { color: var(--fg); background: color-mix(in oklab, var(--bg-paper) 60%, transparent); }
.roi-tab-btn:focus-visible { outline: 0; box-shadow: var(--sh-focus); }
.roi-tab-btn.is-active {
  background: var(--bg-paper);
  color: var(--fg);
  box-shadow: var(--sh-1);
}
.roi-tab-btn .ic { margin-right: 6px; }
.roi-tab-btn .sub {
  display: block;
  font: 400 11px/1 var(--f-mono);
  color: var(--fg-dim);
  margin-top: 4px;
  letter-spacing: 0.04em;
  text-transform: none;
}
.roi-tab-btn.is-active .sub { color: var(--fg-soft); }

/* Calc card — deep ink with pink glow */
.roi-card {
  background: var(--ink);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 30px 60px -24px color-mix(in oklab, var(--ink) 60%, transparent),
              0 0 0 1px color-mix(in oklab, var(--paper) 8%, transparent);
}
.roi-panel { display: none; }
.roi-panel.is-active { display: grid; grid-template-columns: 1fr 1fr; }

/* Inputs column */
.roi-inputs {
  padding: var(--s-6) var(--s-6) var(--s-5);
  background: var(--ink);
  display: flex; flex-direction: column;
}
.roi-inputs-label {
  font: 600 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: color-mix(in oklab, var(--paper) 58%, transparent);
  margin-bottom: var(--s-5);
}
.roi-field { margin-bottom: var(--s-4); }
.roi-field:last-child { margin-bottom: 0; }
.roi-field label {
  display: block;
  font: 500 13.5px/1.3 var(--f-body);
  color: color-mix(in oklab, var(--paper) 82%, transparent);
  margin-bottom: 8px;
}
.roi-field .input-wrap { position: relative; display: flex; align-items: center; }
.roi-field .roi-prefix,
.roi-field .roi-suffix {
  /* Vertical-centre explicitly — without this the absolute-positioned
     prefix/suffix falls to the top of the flex container. */
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font: 600 15px/1 var(--f-mono);
  color: color-mix(in oklab, var(--paper) 45%, transparent);
  pointer-events: none;
}
.roi-field .roi-prefix { left: 14px; }
.roi-field .roi-suffix { right: 14px; }
.roi-field input[type="text"] {
  width: 100%;
  padding: 11px 14px;
  font: 600 15px/1 var(--f-mono);
  font-variant-numeric: tabular-nums;
  color: var(--paper);
  background: color-mix(in oklab, var(--paper) 5%, transparent);
  border: 1px solid color-mix(in oklab, var(--paper) 12%, transparent);
  border-radius: var(--r-sm);
  outline: none;
  transition: border-color var(--dur-2) var(--ease),
              box-shadow var(--dur-2) var(--ease);
  -moz-appearance: textfield;
}
.roi-field input[type="text"]::-webkit-outer-spin-button,
.roi-field input[type="text"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.roi-field input[type="text"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
}
.roi-field input.has-prefix { padding-left: 30px; }
.roi-field input.has-suffix { padding-right: 32px; }

/* Slider row — input[type=range] + live value chip */
.roi-slider-row { display: flex; align-items: center; gap: 12px; }
.roi-field input[type="range"] {
  flex: 1;
  -webkit-appearance: none; appearance: none;
  height: 6px;
  background: color-mix(in oklab, var(--paper) 12%, transparent);
  border-radius: 3px;
  outline: none;
}
.roi-field input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--ink);
  box-shadow: 0 2px 8px color-mix(in oklab, var(--accent) 45%, transparent);
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease);
}
.roi-field input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.1); }
.roi-field input[type="range"]::-moz-range-thumb {
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--ink);
  cursor: pointer;
}
.roi-slider-val {
  min-width: 52px;
  font: 700 15px/1 var(--f-mono);
  font-variant-numeric: tabular-nums;
  color: var(--paper);
  text-align: right;
  cursor: pointer;
  user-select: none;
  border-bottom: 1px dashed transparent;
  transition: border-color var(--dur-2) var(--ease);
}
.roi-slider-val:hover { border-bottom-color: color-mix(in oklab, var(--paper) 32%, transparent); }
.roi-slider-edit {
  width: 56px !important;
  font: 700 15px/1 var(--f-mono);
  color: var(--paper);
  background: color-mix(in oklab, var(--paper) 12%, transparent);
  border: 1px solid var(--accent);
  border-radius: var(--r-xs);
  padding: 2px 6px;
  text-align: right;
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
  -moz-appearance: textfield;
}
.roi-field-hint {
  font: 400 12px/1.4 var(--f-body);
  color: color-mix(in oklab, var(--paper) 48%, transparent);
  margin-top: 6px;
}
.roi-field-hint strong { color: var(--accent-text); font-weight: 600; }

/* Plan note pinned to bottom of inputs */
.roi-plan-note {
  margin-top: var(--s-5);
  padding: var(--s-3) var(--s-4);
  background: color-mix(in oklab, var(--paper) 6%, transparent);
  border-radius: var(--r-sm);
  font: 400 13px/1.55 var(--f-body);
  color: color-mix(in oklab, var(--paper) 72%, transparent);
}
.roi-plan-note:empty { display: none; }
.roi-plan-note strong { color: var(--accent-text); font-weight: 700; }

/* Outputs column — darker still + pink radial glow. Spacing is
   tighter than the inputs column so the numbers stack densely and
   the hero figure doesn't get orphaned by excess whitespace. */
.roi-outputs {
  padding: var(--s-5) var(--s-5) var(--s-5) var(--s-6);
  background:
    radial-gradient(80% 65% at 92% -10%, color-mix(in oklab, var(--accent) 14%, transparent), transparent 70%),
    color-mix(in oklab, var(--ink) 88%, #000);
  border-left: 1px solid color-mix(in oklab, var(--paper) 8%, transparent);
  display: flex; flex-direction: column;
  position: relative;
}
.roi-outputs-label {
  font: 600 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: color-mix(in oklab, var(--paper) 58%, transparent);
  margin-bottom: var(--s-4);
}
.roi-result {
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-3);
  border-bottom: 1px solid color-mix(in oklab, var(--paper) 7%, transparent);
}
.roi-result:last-of-type { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.roi-result-label {
  font: 500 12.5px/1.4 var(--f-body);
  color: color-mix(in oklab, var(--paper) 62%, transparent);
  margin-bottom: 2px;
}
.roi-result-value {
  font: 700 22px/1.15 var(--f-display);
  font-variant-numeric: tabular-nums;
  color: color-mix(in oklab, var(--paper) 94%, transparent);
  letter-spacing: -0.02em;
}

/* Hero number — the big additional-revenue figure (green glow).
   Reduced halo radius + slightly looser row margin so the glow doesn't
   visually bleed into the next row. */
.roi-result.is-hero {
  padding-bottom: var(--s-4);
  margin-bottom: var(--s-3);
}
.roi-result.is-hero .roi-result-value {
  color: var(--green-500);
  font-size: clamp(30px, 3.8vw, 40px);
  text-shadow: 0 0 20px color-mix(in oklab, var(--green-500) 35%, transparent);
}
.roi-result.is-hero .roi-result-label {
  color: var(--green-500);
  font-weight: 600;
  margin-bottom: 4px;
}
.roi-result.is-cost .roi-result-value {
  font-size: 20px;
}
.roi-result.is-roi .roi-result-value {
  /* ROI is a positive outcome — green semantic, not pink. Pink at low
     opacity for a halo can read as red/warning, which is the wrong
     signal for "money back". */
  color: var(--success-text);
  font-size: clamp(26px, 3vw, 32px);
  text-shadow: 0 0 20px color-mix(in oklab, var(--success) 32%, transparent);
}
.roi-result.is-payback .roi-result-value {
  color: var(--yellow-500);
  font-size: 20px;
}

/* Mobile — stack panels */
@media (max-width: 720px) {
  .roi-tabs { flex-direction: column; }
  .roi-tab-btn { padding: 10px 14px; }
  .roi-tab-btn .sub { display: none; }
  .roi-panel.is-active { grid-template-columns: 1fr; }
  .roi-outputs { border-left: 0; border-top: 1px solid color-mix(in oklab, var(--paper) 8%, transparent); }
}
@media (max-width: 480px) {
  .roi-inputs, .roi-outputs { padding: var(--s-5); }
  .roi-result.is-hero .roi-result-value { font-size: 30px; }
  .roi-result.is-roi .roi-result-value { font-size: 26px; }
}

/* ── 11.15 .brand-timeline ───────────────────────────── */
.brand-timeline {
  position: relative;
  max-width: 900px;
  padding: 20px 0 20px;
}
.brand-timeline .bt-ticks {
  display: grid;
  grid-template-columns: repeat(var(--bt-n, 3), 1fr);
  gap: var(--s-3);
  position: relative;
}
/* Shared horizontal line — anchored at a fixed Y inside the ticks grid so
   it always passes through where every dot sits (regardless of tick height). */
.brand-timeline .bt-ticks::before {
  content: "";
  position: absolute;
  left: 8%; right: 8%;
  top: 42px;                       /* aligns with the centre of each dot */
  height: 2px;
  background: linear-gradient(90deg, var(--hair), var(--accent), var(--hair));
  border-radius: 2px;
  z-index: 0;
}
.brand-timeline .bt-tick {
  text-align: center;
  display: flex; flex-direction: column; align-items: center;
  position: relative;
  padding: 0 var(--s-3);
  z-index: 1;
}
.brand-timeline .bt-date {
  font: 500 11px/1 var(--f-mono); color: var(--fg-faint);
  letter-spacing: 0.12em; text-transform: uppercase;
  margin: 0 0 10px;
  height: 16px;                    /* lock date row height → dot alignment stays consistent */
  display: flex; align-items: center;
}
.brand-timeline .bt-dot {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--bg-paper);
  flex: 0 0 auto;
  margin-bottom: 18px;
  position: relative;
}
/* The LAST milestone (current year) gets a pulsing outer ring — "we are here" */
.brand-timeline .bt-tick:last-child .bt-dot::after {
  content: ""; position: absolute; inset: -3px; border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0;
  animation: bt-ping 2.4s ease-out infinite;
}
@keyframes bt-ping {
  0%   { opacity: 0.7; transform: scale(1); }
  80%  { opacity: 0;   transform: scale(2.4); }
  100% { opacity: 0;   transform: scale(2.4); }
}
@media (prefers-reduced-motion: reduce) {
  .brand-timeline .bt-tick:last-child .bt-dot::after { animation: none; opacity: 0; }
}
.brand-timeline .bt-title {
  font: 600 16px/1.25 var(--f-display); color: var(--fg); margin: 0;
  max-width: 24ch;
}
.brand-timeline .bt-title em { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: var(--accent); }
.brand-timeline .bt-sub {
  font: 400 12.5px/1.45 var(--f-body); color: var(--fg-soft);
  margin: 6px 0 0; max-width: 30ch;
}
@media (max-width: 720px) {
  .brand-timeline { padding: 0; }
  .brand-timeline .bt-ticks { grid-template-columns: 1fr; gap: var(--s-5); }
  .brand-timeline .bt-ticks::before { display: none; }
  .brand-timeline .bt-tick { align-items: flex-start; text-align: left; flex-direction: row; flex-wrap: wrap; gap: 8px; padding: 0; }
  .brand-timeline .bt-date { margin: 0; }
  .brand-timeline .bt-dot { margin: 2px 0 0; }
  .brand-timeline .bt-title, .brand-timeline .bt-sub { flex: 1 0 100%; max-width: none; }
}

/* ── 11.16 .hero-bloom-canvas ─────────────────────────── */
.hero-bloom-canvas {
  position: relative;
  width: 100%; aspect-ratio: 16 / 7;
  min-height: 320px;
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  background: var(--warm-3);
  /* The default variant uses --warm-3 (pinned cream) as its background —
     so the text inside must ALSO pin to ink, otherwise dark-mode's warm
     cream --fg would render on a warm cream surface (invisible). Scope
     a new --fg/--fg-soft/--fg-dim locally so any copy inside reads ink. */
  --fg:       var(--ink);
  --fg-soft:  color-mix(in oklab, var(--ink) 68%, transparent);
  --fg-dim:   color-mix(in oklab, var(--ink) 48%, transparent);
  --fg-faint: color-mix(in oklab, var(--ink) 32%, transparent);
  color: var(--fg);
}
.hero-bloom-canvas[data-variant="war-room"] {
  background: var(--ink);
  /* Dark variant — reset to the paper foreground for contrast */
  --fg:       var(--warm-3);
  --fg-soft:  color-mix(in oklab, var(--warm-3) 70%, transparent);
  --fg-dim:   color-mix(in oklab, var(--warm-3) 50%, transparent);
  --fg-faint: color-mix(in oklab, var(--warm-3) 32%, transparent);
  color: var(--fg);
}
.hero-bloom-canvas[data-variant="warm"] { background: var(--warm-3); }
.hero-bloom-canvas[data-variant="industry"] {
  background: color-mix(in oklab, var(--industry-accent) 6%, var(--warm-3));
}
.hero-bloom-canvas::before, .hero-bloom-canvas::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
}
.hero-bloom-canvas::before {
  background:
    radial-gradient(60% 60% at 85% 12%, color-mix(in oklab, var(--accent) 28%, transparent), transparent 70%),
    radial-gradient(40% 50% at 12% 80%, color-mix(in oklab, var(--blue-500) 18%, transparent), transparent 70%),
    radial-gradient(50% 40% at 50% 90%, color-mix(in oklab, var(--yellow-500) 14%, transparent), transparent 70%);
  animation: hb-drift 40s ease-in-out infinite alternate;
}
.hero-bloom-canvas[data-variant="war-room"]::before {
  background:
    radial-gradient(60% 60% at 85% 12%, color-mix(in oklab, var(--accent) 22%, transparent), transparent 70%),
    radial-gradient(40% 50% at 12% 80%, color-mix(in oklab, var(--blue-500) 14%, transparent), transparent 70%);
}
@keyframes hb-drift {
  0%   { transform: translate(0, 0); }
  50%  { transform: translate(-1.5%, 1%); }
  100% { transform: translate(1.5%, -1%); }
}
@media (prefers-reduced-motion: reduce) { .hero-bloom-canvas::before { animation: none; } }
.hero-bloom-canvas .hbc-content {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding: var(--s-9) var(--s-7); text-align: center;
}
.hero-bloom-canvas[data-variant="war-room"] .hbc-content { color: var(--paper); }
.hero-bloom-canvas .hbc-content .kicker {
  font: 500 11px/1 var(--f-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent-text); margin-bottom: 12px;
}
.hero-bloom-canvas .hbc-content h4 {
  font: 600 clamp(26px, 4vw, 40px)/1.1 var(--f-display);
  letter-spacing: -0.02em; margin: 0;
}
.hero-bloom-canvas .hbc-content h4 em { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: var(--accent); font-variation-settings: "SOFT" 80; }
.hero-bloom-canvas .motes {
  position: absolute; inset: 0; pointer-events: none;
}
.hero-bloom-canvas .mote {
  position: absolute; width: 3px; height: 3px; border-radius: 50%;
  background: var(--accent); opacity: 0.6;
  animation: hb-rise 18s linear infinite;
}
@keyframes hb-rise {
  0%   { transform: translateY(20px); opacity: 0; }
  20%  { opacity: 0.6; }
  80%  { opacity: 0.6; }
  100% { transform: translateY(-320px); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .hero-bloom-canvas .mote { animation: none; opacity: 0; } }

/* ── mini-atoms: compliance-row, channel-orbit, spark, stat-badge ── */

.compliance-row {
  display: flex; flex-wrap: wrap; gap: 8px;
}
.compliance-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; border-radius: 999px;
  border: 1px solid var(--hair);
  font: 500 11px/1 var(--f-mono);
  color: var(--fg);
  letter-spacing: 0.06em;
  background: color-mix(in oklab, var(--bg-paper) 70%, transparent);
  transition: border-color 0.15s, transform 0.15s;
}
.compliance-pill:hover { border-color: var(--accent); transform: translateY(-1px); }
.compliance-pill .ico { width: 14px; height: 14px; color: var(--accent-text); display: inline-flex; }
.compliance-pill .ico svg { width: 100%; height: 100%; }

.channel-orbit {
  position: relative;
  width: 220px; height: 220px;
}
.channel-orbit svg { width: 100%; height: 100%; display: block; }
/* Only the dashed ring rotates. Channel circles + labels stay upright.
   Using transform-box: fill-box lets us rotate around SVG element centre
   reliably across Chrome/Safari/Firefox without manual origin coords. */
.channel-orbit .orbit-ring {
  transform-origin: center;
  transform-box: fill-box;
  animation: co-spin 40s linear infinite;
}
@keyframes co-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .channel-orbit .orbit-ring { animation: none; } }

/* Spark — clean "live ping" indicator. Three concentric sonar rings
   expand outward on a staggered loop, with a gently pulsing core dot
   in the middle. No rotating rays — the earlier version felt busy.
   Reads immediately as "active / connected / live" at any size. */
.spark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 64px; height: 64px;
  position: relative;
  color: var(--accent-text);
}
.spark svg { width: 100%; height: 100%; overflow: visible; }
/* All rings + the core dot share cx=12, cy=12 (centre of 24×24 viewBox).
   `transform-origin: center` with `transform-box: fill-box` would resolve
   to each element's OWN bounding-box centre — which is the same point
   for every ring since they all share cx/cy. Using center keeps the
   expansion anchored to the true centre regardless of the element's
   current `r` value. */
.spark .sp-ring {
  fill: none; stroke: currentColor; stroke-width: 1.6;
  transform-box: fill-box; transform-origin: center;
  opacity: 0;
  animation: sp-ping 2.4s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
.spark .sp-ring.d2 { animation-delay: 0.8s; }
.spark .sp-ring.d3 { animation-delay: 1.6s; }
.spark .sp-core {
  fill: currentColor;
  filter: drop-shadow(0 0 6px color-mix(in oklab, var(--accent) 55%, transparent));
  transform-box: fill-box; transform-origin: center;
}
.spark.pulse .sp-core { animation: sp-core 2.4s ease-in-out infinite; }
@keyframes sp-ping {
  0%   { transform: scale(0.55); opacity: 0.9; }
  60%  { opacity: 0.4; }
  100% { transform: scale(3.2);  opacity: 0; }
}
@keyframes sp-core {
  0%, 100% { transform: scale(1);    opacity: 1;    }
  50%      { transform: scale(1.18); opacity: 0.82; }
}
@media (prefers-reduced-motion: reduce) {
  .spark .sp-ring, .spark .sp-core { animation: none; opacity: 1; }
}

.stat-badge {
  display: inline-flex; flex-direction: column; gap: 6px;
  padding: 14px 18px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  max-width: 200px;
}
.stat-badge .eyebrow {
  font: 500 10.5px/1 var(--f-mono); color: var(--accent-text);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.stat-badge .num {
  font: 700 40px/1 var(--f-display); color: var(--fg);
  letter-spacing: -0.025em; font-variant-numeric: tabular-nums;
}
.stat-badge .num em { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: var(--accent); }
.stat-badge .num sup { font-size: 0.55em; font-weight: 500; vertical-align: top; color: var(--fg-soft); margin-left: 2px; }
.stat-badge .cap {
  font: 500 11.5px/1.3 var(--f-body); color: var(--fg-soft);
}

/* .cost-compare — three-beat story: eyebrow → headline → bars → callout.
   Tells the pricing argument explicitly: "you've already paid to acquire
   the lead, working it costs a fraction more". Tall muted bar (acquisition)
   + short accent bar (MagicBlocks). The visual gap IS the proof; the
   headline + callout pin the meaning. Lives on the Pricing hero. */
.cost-compare {
  display: grid; grid-template-rows: auto auto 1fr auto;
  gap: var(--s-3);
  width: 100%; max-width: 680px; margin: 0 auto;
  font-family: var(--f-body);
}
.cost-compare .cc-eyebrow {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-dim);
}
.cost-compare .cc-headline {
  font: 600 19px/1.35 var(--f-display);
  letter-spacing: -0.015em;
  color: var(--fg);
  text-wrap: balance;
  margin: 2px 0 var(--s-3);
  max-width: 56ch;
}
.cost-compare .cc-headline em {
  font-family: var(--f-italic); font-style: italic; font-weight: 400;
  color: var(--accent-text);
}
.cost-compare .cc-bars {
  display: flex; flex-direction: column; gap: var(--s-4);
}
.cost-compare .cc-bar {
  display: grid; grid-template-columns: 160px 1fr auto; align-items: center;
  gap: var(--s-4);
  font: 500 12.5px/1.3 var(--f-body);
}
.cost-compare .cc-bar-meta {
  display: flex; flex-direction: column; gap: 2px;
  min-width: 0;
}
.cost-compare .cc-bar-label {
  font: 600 11px/1.2 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--fg);
}
.cost-compare .cc-bar.is-engine .cc-bar-label { color: var(--accent-text); }
.cost-compare .cc-bar-sub {
  font: 400 11px/1.3 var(--f-body);
  color: var(--fg-dim);
  letter-spacing: 0;
  text-transform: none;
}
.cost-compare .cc-bar-track {
  height: 26px; border-radius: var(--r-sm);
  background: color-mix(in oklab, var(--ink) 6%, var(--bg-paper));
  overflow: hidden;
  position: relative;
}
.cost-compare .cc-bar-fill {
  height: 100%; border-radius: var(--r-sm);
  background: var(--warm-7);
  width: var(--cc-pct, 100%);
  transition: width 800ms cubic-bezier(0.22, 1, 0.36, 1);
}
.cost-compare .cc-bar.is-engine .cc-bar-fill {
  background: var(--accent);
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 30%, transparent),
              0 4px 14px -6px color-mix(in oklab, var(--accent) 60%, transparent);
}
.cost-compare .cc-bar-amount {
  font: 700 16px/1 var(--f-display);
  letter-spacing: -0.015em;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.cost-compare .cc-bar.is-engine .cc-bar-amount { color: var(--accent-text); }
/* Punchline callout: pulls the percentage out as a hero stat with the
   concrete claim alongside. Replaces the easily-missed mono caption. */
.cost-compare .cc-callout {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  margin-top: var(--s-3);
  background: color-mix(in oklab, var(--accent) 7%, var(--bg-paper));
  border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent);
  border-radius: var(--r-md);
}
.cost-compare .cc-callout-pct {
  font: 700 36px/1 var(--f-display);
  color: var(--accent-text);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.cost-compare .cc-callout-cap {
  font: 500 13px/1.4 var(--f-body);
  color: var(--fg);
  letter-spacing: 0;
  text-wrap: balance;
}
.cost-compare .cc-callout-cap strong { color: var(--accent-text); font-weight: 700; }
@media (max-width: 560px) {
  .cost-compare .cc-bar { grid-template-columns: 1fr; gap: 4px; }
  .cost-compare .cc-bar-meta { order: 1; }
  .cost-compare .cc-bar-track { order: 2; }
  .cost-compare .cc-bar-amount { order: 3; text-align: right; }
  .cost-compare .cc-callout { grid-template-columns: 1fr; text-align: center; gap: var(--s-2); }
}

/* .stress-scoreboard — oversized stat-pair (98% / 59%) + 1000-dot
   illustration showing failure-rate at scale. Built to live on
   "Built for Production" §4. Extends .scoreboard.dark visual treatment. */
.stress-scoreboard {
  display: grid; gap: var(--s-7);
  width: 100%; max-width: min(960px, 100%); margin: 0 auto;
  padding: var(--s-7);
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-lg);
  --fg: var(--paper); --fg-soft: #C9CFE2; --hair: rgba(244,236,228,.14);
  position: relative; overflow: hidden;
}
.stress-scoreboard::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(60% 60% at 80% 20%, color-mix(in oklab, var(--accent) 18%, transparent), transparent 70%);
  pointer-events: none;
}
.stress-scoreboard > * { position: relative; z-index: 1; }
.stress-scoreboard .ss-pair {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--s-6); align-items: end;
}
.stress-scoreboard .ss-stat {
  display: flex; flex-direction: column; gap: var(--s-2);
}
.stress-scoreboard .ss-stat.is-pass { color: var(--paper); }
.stress-scoreboard .ss-stat.is-fail { color: color-mix(in oklab, var(--paper) 70%, transparent); }
.stress-scoreboard .ss-stat-eyebrow {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.14em;
  opacity: 0.75;
}
.stress-scoreboard .ss-stat-num {
  font: 700 clamp(72px, 12vw, 128px)/1 var(--f-display);
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}
.stress-scoreboard .ss-stat.is-pass .ss-stat-num { color: var(--green-300); }
.stress-scoreboard .ss-stat.is-fail .ss-stat-num { color: color-mix(in oklab, var(--paper) 60%, transparent); }
.stress-scoreboard .ss-stat-cap {
  font: 500 13px/1.4 var(--f-body); opacity: 0.8;
  max-width: 26ch;
}
.stress-scoreboard .ss-vs {
  font: 700 14px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.18em;
  opacity: 0.5;
  align-self: center;
  padding-bottom: var(--s-5);
}
.stress-scoreboard .ss-cap {
  font: 500 11.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: color-mix(in oklab, var(--paper) 65%, transparent);
}
/* Two-row dot lattice (25 dots per row): one row per system, dots tick
   on left-to-right in a continuous loop. Each dot has its own
   animation-delay so the rows feel alive (leads streaming in). The
   per-dot --final-op variable controls the held opacity, so the
   "failure tail" naturally fades out without needing extra classes.
   Was a 1000-dot grid that read as decorative noise; this design
   shows the comparison directly. */
.stress-scoreboard .ss-rows {
  display: flex; flex-direction: column; gap: var(--s-4);
}
.stress-scoreboard .ss-row {
  display: grid; grid-template-columns: repeat(25, 1fr); gap: 8px;
  padding: var(--s-4) var(--s-4);
  border: 1px solid rgba(244,236,228,.10);
  border-radius: var(--r-md);
  background: rgba(244,236,228,.03);
  position: relative;
}
.stress-scoreboard .ss-row::before {
  /* Per-row caption pinned to the top-right corner of the lattice. */
  content: attr(data-row-label);
  position: absolute; top: -10px; right: var(--s-4);
  padding: 2px 8px;
  background: var(--ink);
  font: 600 10px/1 var(--f-mono);
  letter-spacing: 0.12em; text-transform: uppercase;
  color: color-mix(in oklab, var(--paper) 65%, transparent);
}
.stress-scoreboard .ss-row.is-pass::before { color: var(--green-300); }
.stress-scoreboard .ss-row.is-fail::before { color: color-mix(in oklab, var(--error) 70%, var(--paper)); }
.stress-scoreboard .ss-row span {
  width: 100%; aspect-ratio: 1; border-radius: 50%;
  background: var(--green-500);
  opacity: 0; transform: scale(0.3);
  /* 8s loop: every dot ticks on, holds, fades, pauses, restarts.
     Stagger of 50ms × index gives the wave-of-leads feel. */
  animation: ss-pop 8s linear infinite;
  animation-delay: calc(var(--i, 0) * 0.05s);
  will-change: opacity, transform;
}
.stress-scoreboard .ss-row.is-fail span { background: var(--error); }
@keyframes ss-pop {
  0%   { opacity: 0;                         transform: scale(0.3); }
  3%   { opacity: var(--final-op, 0.95);     transform: scale(1); }
  72%  { opacity: var(--final-op, 0.95);     transform: scale(1); }
  90%  { opacity: 0;                         transform: scale(0.85); }
  100% { opacity: 0;                         transform: scale(0.3); }
}
@media (prefers-reduced-motion: reduce) {
  .stress-scoreboard .ss-row span {
    animation: none;
    opacity: var(--final-op, 0.95);
    transform: none;
  }
}
.stress-scoreboard .ss-dot-legend {
  display: flex; gap: var(--s-5); flex-wrap: wrap;
  font: 500 11.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: color-mix(in oklab, var(--paper) 75%, transparent);
}
.stress-scoreboard .ss-dot-legend span {
  display: inline-flex; align-items: center; gap: 8px;
}
.stress-scoreboard .ss-dot-legend i {
  width: 10px; height: 10px; border-radius: 50%; display: inline-block;
}
.stress-scoreboard .ss-dot-legend i.is-pass { background: var(--green-500); }
.stress-scoreboard .ss-dot-legend i.is-fail { background: var(--error); }
@media (max-width: 720px) {
  .stress-scoreboard .ss-pair { grid-template-columns: 1fr; gap: var(--s-5); }
  .stress-scoreboard .ss-vs { display: none; }
}

/* ─── §11.22 inline illustrations — five page-specific composites ───
   These don't share a JS API or canonical contract. They're inline
   illustrations the website composes once per destination page from
   brand-kit primitives. Lift the markup, customise the copy. */

/* .architecture-compare — monolithic vs modular block stack */
.architecture-compare {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-7);
  width: 100%; max-width: min(720px, 100%); margin: 0 auto;
  align-items: stretch;
}
.architecture-compare .ac-side { display: flex; flex-direction: column; gap: var(--s-3); }
.architecture-compare .ac-label {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-soft);
}
.architecture-compare .ac-stack { display: flex; flex-direction: column; gap: 6px; flex: 1; }
.architecture-compare .ac-block {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  padding: 10px 14px;
  font: 500 12.5px/1.3 var(--f-body);
  color: var(--fg);
}
.architecture-compare .ac-block-mega {
  flex: 1; align-items: center; justify-content: center;
  display: flex; flex-direction: column; gap: 4px;
  background: color-mix(in oklab, var(--warm-7) 25%, var(--bg-paper));
  font: 600 14px/1.3 var(--f-display);
  text-align: center;
  border-style: dashed;
}
.architecture-compare .ac-block-mega .ac-block-sub {
  font: 400 11px/1.3 var(--f-body); color: var(--fg-dim);
}
.architecture-compare .ac-modular .ac-block { border-color: color-mix(in oklab, var(--accent) 30%, var(--hair)); }
.architecture-compare .ac-modular .ac-block-out {
  background: var(--accent); color: var(--paper); border-color: transparent;
  box-shadow: 0 6px 18px -8px color-mix(in oklab, var(--accent) 60%, transparent);
}
@media (max-width: 640px) { .architecture-compare { grid-template-columns: 1fr; gap: var(--s-5); } }

/* .knowledge-flow — converging-flow diagram */
.knowledge-flow {
  display: grid;
  grid-template-columns: minmax(120px, 160px) 1fr minmax(140px, 180px) 1fr minmax(120px, 160px);
  align-items: center;
  gap: var(--s-2);
  width: 100%; max-width: min(720px, 100%); margin: 0 auto;
  font-family: var(--f-body);
}
.knowledge-flow .kf-sources,
.knowledge-flow .kf-outputs {
  display: flex; flex-direction: column; gap: 6px;
}
.knowledge-flow .kf-src,
.knowledge-flow .kf-out-msg {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  padding: 7px 10px;
  font: 500 12px/1.2 var(--f-body);
  color: var(--fg);
  text-align: center;
}
.knowledge-flow .kf-out-msg { background: var(--accent); color: var(--paper); border-color: transparent; }
.knowledge-flow .kf-arrows {
  /* Stretch to the column height so SVG path endpoints (expressed as
     proportions of the viewBox) line up with the actual box centres
     rendered in the source/output columns. Hardcoded 160px got out of
     sync as soon as the columns reflowed. */
  align-self: stretch;
  min-height: 140px;
}
.knowledge-flow .kf-arrows svg { width: 100%; height: 100%; display: block; }
.knowledge-flow .kf-arrows path {
  fill: none; stroke: var(--hair); stroke-width: 1.4;
  stroke-linecap: round;
}
.knowledge-flow .kf-arrows.kf-out path { stroke: color-mix(in oklab, var(--accent) 45%, var(--hair)); }
.knowledge-flow .kf-core {
  display: grid; place-items: center;
}
.knowledge-flow .kf-core-pill {
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-pill);
  padding: 12px 22px;
  font: 700 13px/1 var(--f-display);
  letter-spacing: -0.005em;
  box-shadow: 0 12px 28px -12px color-mix(in oklab, var(--ink) 60%, transparent),
              0 0 0 4px color-mix(in oklab, var(--accent) 14%, transparent);
}
@media (max-width: 720px) {
  .knowledge-flow {
    grid-template-columns: 1fr;
    gap: var(--s-4);
  }
  .knowledge-flow .kf-arrows { display: none; }
}

/* .demo-vs-prod-split — paired conversation columns */
.demo-vs-prod-split {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-5);
  width: 100%; max-width: min(880px, 100%); margin: 0 auto;
}
.dvp-side {
  display: flex; flex-direction: column; gap: var(--s-3);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: var(--s-4);
}
.dvp-side.dvp-prod { border-color: color-mix(in oklab, var(--accent) 25%, var(--hair)); }
.dvp-label {
  font: 600 10.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-soft);
}
.dvp-prod .dvp-label { color: var(--accent-text); }
.dvp-stack { display: flex; flex-direction: column; gap: 6px; }
.dvp-msg {
  font: 400 12.5px/1.45 var(--f-body);
  padding: 8px 12px;
  border-radius: 12px;
  max-width: 88%;
}
.dvp-msg-in  { background: var(--bg-sunk); color: var(--fg); align-self: flex-start; border-bottom-left-radius: 4px; }
.dvp-msg-out { background: var(--accent); color: var(--paper); align-self: flex-end; border-bottom-right-radius: 4px; }
@media (max-width: 720px) { .demo-vs-prod-split { grid-template-columns: 1fr; } }

/* .guardrails-admin — form-toggle list inside admin chrome */
.guardrails-admin {
  width: 100%; max-width: min(640px, 100%); margin: 0 auto;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  overflow: hidden;
}
.guardrails-admin .ga-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  background: var(--bg-sunk);
  border-bottom: 1px solid var(--hair);
  font-family: var(--f-body);
}
.guardrails-admin .ga-title {
  font: 600 13px/1 var(--f-display);
  color: var(--fg);
  letter-spacing: -0.005em;
}
.guardrails-admin .ga-status {
  font: 500 11px/1 var(--f-mono);
  color: var(--fg-dim);
  display: inline-flex; align-items: center; gap: 6px;
}
.guardrails-admin .ga-status-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--green-500);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--green-500) 22%, transparent);
}
.guardrails-admin .ga-rows { display: flex; flex-direction: column; }
.guardrails-admin .ga-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--hair);
  cursor: pointer;
}
.guardrails-admin .ga-row:last-child { border-bottom: 0; }
/* Theme-aware hover tint — was --warm-1 (a fixed cream) which read as
   light-mode colour leaking into the dark theme. The fg-tinted mix
   gives a subtle hover lift in BOTH themes. */
.guardrails-admin .ga-row:hover { background: color-mix(in oklab, var(--fg) 6%, transparent); }
.guardrails-admin .ga-row-name {
  font: 600 13px/1.3 var(--f-body);
  color: var(--fg);
}
.guardrails-admin .ga-row-hint {
  font: 400 12px/1.4 var(--f-body);
  color: var(--fg-soft);
  margin-top: 4px;
}
.guardrails-admin .ga-toggle {
  flex-shrink: 0;
  width: 40px; height: 22px; border-radius: 11px;
  background: var(--hair);
  position: relative;
  transition: background var(--dur-2) var(--ease);
}
.guardrails-admin .ga-toggle i {
  position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--paper);
  transition: transform var(--dur-2) var(--ease);
}
.guardrails-admin .ga-toggle.is-on { background: var(--accent); }
.guardrails-admin .ga-toggle.is-on i { transform: translateX(18px); }

/* .voice-waveform-demo — live-call card with animated waveform + transcript */
.voice-waveform-demo {
  display: flex; flex-direction: column; gap: var(--s-4);
  width: 100%; max-width: min(560px, 100%); margin: 0 auto;
  font-family: var(--f-body);
}
.voice-waveform-demo .vwd-call {
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-md);
  padding: var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-3);
}
.voice-waveform-demo .vwd-call-head {
  display: flex; align-items: center; justify-content: space-between;
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
}
.voice-waveform-demo .vwd-call-state {
  display: inline-flex; align-items: center; gap: 6px;
  color: color-mix(in oklab, var(--paper) 90%, transparent);
}
.voice-waveform-demo .vwd-pulse {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 25%, transparent);
  animation: vwd-pulse 1.4s ease-out infinite;
}
@keyframes vwd-pulse {
  0%   { transform: scale(1);   opacity: 1; }
  50%  { transform: scale(1.4); opacity: 0.55; }
  100% { transform: scale(1);   opacity: 1; }
}
.voice-waveform-demo .vwd-call-num {
  color: color-mix(in oklab, var(--paper) 60%, transparent);
}
.voice-waveform-demo .vwd-wave {
  display: flex; align-items: center; gap: 3px;
  height: 60px;
}
.voice-waveform-demo .vwd-wave span {
  flex: 1;
  background: var(--accent);
  border-radius: 2px;
  height: var(--h, 50%);
  animation: vwd-wave 1.6s ease-in-out infinite;
}
.voice-waveform-demo .vwd-wave span:nth-child(odd)  { animation-delay: 0.2s; }
.voice-waveform-demo .vwd-wave span:nth-child(3n)   { animation-delay: 0.4s; }
.voice-waveform-demo .vwd-wave span:nth-child(5n+1) { animation-delay: 0.7s; }
@keyframes vwd-wave {
  0%, 100% { transform: scaleY(0.7); opacity: 0.6; }
  50%      { transform: scaleY(1.1); opacity: 1; }
}
.voice-waveform-demo .vwd-transcript {
  display: flex; flex-direction: column; gap: 6px;
}
.voice-waveform-demo .vwd-bubble {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: 12px;
  padding: 8px 12px;
  font: 400 13px/1.45 var(--f-body);
  color: var(--fg);
  max-width: 86%;
}
.voice-waveform-demo .vwd-bubble.vwd-in { align-self: flex-start; border-bottom-left-radius: 4px; }
.voice-waveform-demo .vwd-bubble.vwd-out {
  align-self: flex-end;
  background: color-mix(in oklab, var(--accent) 92%, transparent);
  color: var(--paper);
  border-color: transparent;
  border-bottom-right-radius: 4px;
}
.voice-waveform-demo .vwd-bubble .vwd-who {
  display: block;
  font: 600 9.5px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.12em;
  margin-bottom: 4px;
  color: var(--fg-dim);
}
.voice-waveform-demo .vwd-bubble.vwd-out .vwd-who { color: color-mix(in oklab, var(--paper) 90%, transparent); font-weight: 700; }
@media (prefers-reduced-motion: reduce) {
  .voice-waveform-demo .vwd-wave span { animation: none; }
  .voice-waveform-demo .vwd-pulse { animation: none; }
}

/* section-level wrappers used by multiple components */
.ns-twin {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-5);
  max-width: 900px;
}
@media (max-width: 720px) { .ns-twin { grid-template-columns: 1fr; } }

/* anatomy override for chapter 11 — diagram overlays */
.ns-anatomy-stage {
  position: relative;
  min-height: 360px;
  padding: var(--s-6);
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
}

/* ============================================================ mobile polish
   Final breakpoints — tighten elements that risk overflow / squish on narrow
   screens. Each rule is targeted; nothing shotgun-disables motion on mobile
   except the handful of loops that actually don't carry meaning at small size. */

@media (max-width: 720px) {
  /* Demo stage margins contract so every component has more horizontal room */
  .ns-stage.pad { padding: var(--s-5) var(--s-4); }
  /* Decay curve: shrink callout text & leader reach so they still fit at narrower widths */
  .decay-curve .callout-title,
  .decay-curve .callout-title.won { font-size: 12px; }
  .decay-curve .callout-sub,
  .decay-curve .callout-sub.lost  { font-size: 9.5px; letter-spacing: 0.08em; }
  /* Happa arc gets cramped — shrink node descriptions */
  .happa-arc .node-desc { font-size: 10px; }
  /* Integration hub: chips can overlap at small scale — shrink text */
  .integration-hub .node { font-size: 9.5px; padding: 4px 7px; }
  /* Race timeline body copy compacts */
  .race-timeline .rt-body { font-size: 12.5px; }
  .race-timeline .rt-tick .rt-body em { font-size: 11px; }
}

@media (max-width: 480px) {
  .ns-stage { min-height: 280px; }
  .ns-stage.pad { padding: var(--s-4) var(--s-3); }
  /* ROI calc — inputs stack more compactly */
  .roi-calculator { padding: var(--s-4); gap: var(--s-4); }
  .roi-calculator .roi-out.gap .v { font-size: 36px; }
  /* Handoff card flows full width (max-width 380 stays, just hugs the stage) */
  .handoff-card { max-width: 100%; }
  /* Triptych panel padding contracts */
  .triptych .panel { padding: var(--s-4); min-height: 200px; }
  .triptych .panel h4 { font-size: 19px; }
  /* Guardian shield: tighten grid further */
  .guardian-shield { max-width: 260px; }
  .guardian-shield .sh-item { font-size: 8.5px; }
  /* Edge race (11.12): the radar shrinks gracefully but city labels can
     overlap at very narrow widths — hide non-winner labels and pager
     dots so the visual stays clean. The winner label + badge stay. */
  .edge-race .er-city:not(.is-winner) { display: none; }
  .edge-race .er-pager { display: none; }
  .edge-race .er-region { font-size: 9px; padding: 4px 8px; }
  /* Scoreboard shimmer is distracting at narrow widths */
  .scoreboard.is-visible .sb-row .good::after { animation: none; opacity: 0; }
  /* Brand timeline ticks stack, last-dot pulse stays */
  .brand-timeline .bt-sub { font-size: 12px; }
}

/* Global motion kill-switch for users who opted out */
@media (prefers-reduced-motion: reduce) {
  .decay-curve .tracer, .happa-arc .tracer,
  .engine-block .eb-flow, .triptych .arrow::after,
  .integration-hub .spokes line, .edge-race .er-halo,
  .ecosystem-rings .er-ring, .scoreboard.is-visible .sb-row .good::after,
  .journey-map .jm-node.start, .brand-timeline .bt-tick:last-child .bt-dot::after,
  .race-timeline .rt-tick.win.final .rt-stamp::before,
  .guardian-shield .sh-shine, .handoff-card.is-visible {
    animation: none !important;
  }
}

/* ── mobile tune-ups for the hero + diagnostic widgets ──────
   Each flagship component (.hero-scene, .hero-live-demo,
   .leak-card, .chat-comparison) already adapts at a primary
   breakpoint. These rules tighten the very-narrow (≤480) view so
   content stays readable without runaway heights or overflow. */
@media (max-width: 640px) {
  /* §11.0 — cap phone width so a 9:18 aspect doesn't bloat height */
  .hs-phone { max-width: 280px; margin: 0 auto; }
  .hero-scene { max-width: 100%; }
  .hs-annotations { gap: 6px; }
  .hs-ann { padding: 8px 10px; flex: 1 1 130px; }
  .hs-ann-v { font-size: 12px; }

  /* §11.19 — chat-comparison controls wrap cleanly; scenario label drops below */
  .cc-controls { flex-direction: column; align-items: stretch; gap: var(--s-3); }
  .cc-controls .cc-scenario { text-align: center; }
  .cc-toggle { flex-wrap: wrap; justify-content: center; }
  .cc-toggle button { padding: 7px 10px; font-size: 11px; letter-spacing: 0.02em; }
  .cc-col { min-height: 360px; }
  .cc-msg { font-size: 13px; max-width: 88%; }
}
@media (max-width: 480px) {
  /* §11.0 — even tighter phone + annotation tags shrink to chips */
  .hs-phone { max-width: 240px; }
  .hs-trigger { font-size: 9.5px; padding: 6px 8px; }
  .hs-msg { font-size: 12px; padding: 6px 10px; }
  .hs-annotations { flex-wrap: wrap; }

  /* §11.17 — hero-live-demo: tighter chrome, smaller thread font */
  .hld-app { padding: var(--s-3); }
  .hld-msg { font-size: 13px; padding: 8px 12px; }
  .hld-thread { gap: 5px; }
  .hld-tabs { padding: 8px 10px; font-size: 10px; }
  .hld-tabs .hld-url { padding: 2px 8px; }

  /* §11.18 — leak-card tighter on very-narrow screens */
  .leak-card { padding: var(--s-5); gap: var(--s-3); }
  .leak-card .lk-title { font-size: 20px; }
  .leak-card .lk-body { font-size: 13.5px; }
  .leak-card .lk-stat { font-size: 16px; padding: 5px 10px; }
}

/* Component-class additions for chapter 11 React wrappers — these are
   selectors used by the @magicblocksai/ui components but not present in
   the chapter HTML demos (which use slightly different markup). They are
   intentionally minimal because the visual heavy-lifting still happens
   inside the chapter-11 namespaced selectors above. */

/* `.callout` — used as a parent group className in <DecayCurve>; the
   actual `.callout-bg` / `.callout-title` / `.callout-leader` selectors
   are already declared above with `.decay-curve` scoping. */
.decay-curve .callout { /* group anchor — children carry the visual work */ }

/* `<EdgeRace>` adds three component-only classes for the server pins and
   pager dots. Visuals are defined here so the React component renders
   correctly without needing a chapter HTML demo using the same markup. */
.edge-race-server {
  display: inline-flex; align-items: center; gap: 4px;
  font: 600 10px/1 var(--f-mono);
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--fg-soft);
  white-space: nowrap;
}
.edge-race-server-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--fg-dim);
  flex-shrink: 0;
}
.edge-race-server.is-winner .edge-race-server-dot {
  background: var(--green-500);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--green-500) 28%, transparent);
}
.edge-race-server.is-winner .edge-race-server-label { color: var(--green-700); }
.edge-race-server-label {
  font: inherit;
  color: inherit;
}
.edge-race-pager-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--hair);
  transition: background 200ms var(--ease);
}
.edge-race-pager-dot.is-active { background: var(--accent); }

/* ─────────────────────────── Chapter 13 — App shell ─────────────────── */
/* Verbatim migration of chapter-13 component CSS. The ch-13 demo also
   relies on the `--row-h-*` density tokens and the `body[data-density]`
   override declared near the top of this file (lines 205-211 / 289-291).
   `.cmdk*` is shipped here for the first time — chapter 06's marketing
   site-nav references the same class name in its inline <style> block,
   but those rules were intentionally left chapter-private (see the note
   at the top of the chapter-06 block above). */

/* ── 13.1 DETAIL PAGE 3-COLUMN SHELL ──────────────────────────── */
.detail-shell {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr) 320px;
  gap: var(--s-5);
  background: var(--bg);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  min-height: 520px;
}
.detail-shell .ds-rail {
  background: var(--bg-paper);
  padding: var(--s-5);
  border-right: 1px solid var(--hair);
  display: flex; flex-direction: column; gap: var(--s-4);
}
.detail-shell .ds-rail--right {
  border-right: 0;
  border-left: 1px solid var(--hair);
}
.detail-shell .ds-summary-card {
  display: flex; flex-direction: column; gap: var(--s-2);
}
.detail-shell .ds-summary-card .av { width: 48px; height: 48px; font-size: 16px; }
.detail-shell .ds-summary-card .ds-name { font: 600 17px/1.15 var(--f-display); color: var(--fg); }
.detail-shell .ds-summary-card .ds-sub { font: 500 12px/1.4 var(--f-mono); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.06em; }
.detail-shell .ds-kv { display: grid; gap: var(--s-3); margin-top: var(--s-4); }
.detail-shell .ds-kv-row { display: flex; flex-direction: column; gap: 2px; }
.detail-shell .ds-kv-key { font: 500 10px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-faint); }
.detail-shell .ds-kv-val { font: 500 13px/1.3 var(--f-body); color: var(--fg); }
.detail-shell .ds-main {
  padding: var(--s-5) var(--s-6);
  display: flex; flex-direction: column;
}
.detail-shell .ds-header {
  display: flex; flex-direction: column; gap: var(--s-3);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--hair);
  position: sticky; top: 0; background: var(--bg);
  margin: calc(var(--s-5) * -1) calc(var(--s-6) * -1) 0;
  padding: var(--s-5) var(--s-6) var(--s-4);
  z-index: 2;
}
.detail-shell .ds-h-eyebrow { font: 500 11px/1 var(--f-mono); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.08em; }
.detail-shell .ds-h-title { font: 700 28px/1.1 var(--f-display); letter-spacing: -0.02em; margin: 0; color: var(--fg); }
.detail-shell .ds-h-meta { display: flex; gap: var(--s-4); align-items: center; flex-wrap: wrap; font: 400 13px var(--f-body); color: var(--fg-soft); }
.detail-shell .ds-tabs {
  display: flex; gap: var(--s-5);
  padding-top: var(--s-5);
  border-bottom: 1px solid var(--hair);
  margin: 0 calc(var(--s-6) * -1);
  padding-left: var(--s-6); padding-right: var(--s-6);
}
.detail-shell .ds-tab {
  font: 500 13px/1 var(--f-body); color: var(--fg-soft);
  padding: var(--s-3) 0;
  border-bottom: 2px solid transparent;
  cursor: pointer; background: transparent; border-left: 0; border-right: 0; border-top: 0;
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.detail-shell .ds-tab:hover { color: var(--fg); }
.detail-shell .ds-tab.is-active { color: var(--fg); border-bottom-color: var(--accent); }
.detail-shell .ds-body {
  padding: var(--s-5) 0;
  flex: 1;
  display: flex; flex-direction: column; gap: var(--s-5);
  overflow-y: auto;
}
.detail-shell .ds-context-card {
  background: var(--bg);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: var(--s-4);
}
.detail-shell .ds-context-card h4 {
  font: 600 13px/1.2 var(--f-display); margin: 0 0 var(--s-2); color: var(--fg);
}
.detail-shell .ds-context-card p {
  font: 400 13px/1.5 var(--f-body); margin: 0; color: var(--fg-soft);
}
.detail-shell .ds-context-card .ds-cc-eyebrow {
  font: 500 10px/1 var(--f-mono); color: var(--accent-text);
  text-transform: uppercase; letter-spacing: 0.08em;
  margin: 0 0 var(--s-2);
}
/* Right-rail collapse — icon strip when collapsed */
.detail-shell.is-rail-collapsed { grid-template-columns: 260px minmax(0, 1fr) 56px; }
.detail-shell.is-rail-collapsed .ds-rail--right > *:not(.ds-rail-toggle) { display: none; }
.ds-rail-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border: 1px solid var(--hair); border-radius: var(--r-sm);
  background: var(--bg); color: var(--fg-dim); cursor: pointer;
  align-self: flex-start;
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.ds-rail-toggle:hover { color: var(--fg); border-color: var(--accent); }
@media (max-width: 1100px) {
  .detail-shell { grid-template-columns: 1fr; min-height: auto; }
  .detail-shell .ds-rail, .detail-shell .ds-rail--right {
    border-right: 0; border-left: 0; border-bottom: 1px solid var(--hair);
  }
  .detail-shell .ds-header { position: static; }
}

/* ── 13.2 COMMAND PALETTE ─────────────────────────────────────── */
.cmdk {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-3);
  width: 100%;
  max-width: 560px;
  overflow: hidden;
}
.cmdk-input-wrap {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--hair);
}
.cmdk-input-wrap svg { width: 18px; height: 18px; color: var(--fg-dim); flex-shrink: 0; }
.cmdk-input {
  flex: 1; border: 0; background: transparent;
  font: 400 16px/1.4 var(--f-body); color: var(--fg);
  outline: none;
}
.cmdk-input::placeholder { color: var(--fg-faint); }
.cmdk-kbd {
  font: 500 11px/1 var(--f-mono);
  padding: 4px 7px; border-radius: var(--r-xs);
  background: var(--bg-sunk); color: var(--fg-dim);
  border: 1px solid var(--hair);
}
.cmdk-results { max-height: 380px; overflow-y: auto; padding: var(--s-2) 0; }
.cmdk-group {
  display: flex; flex-direction: column;
  padding: var(--s-2) 0;
}
.cmdk-group-label {
  font: 500 10px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--fg-faint);
  padding: var(--s-2) var(--s-5) var(--s-2);
}
.cmdk-row {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  gap: var(--s-3); align-items: center;
  padding: 8px var(--s-5);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease);
  border: 0; background: transparent; width: 100%; text-align: left;
}
.cmdk-row:hover, .cmdk-row.is-focused {
  background: var(--accent-soft);
}
.cmdk-row.is-focused {
  box-shadow: inset 3px 0 0 var(--accent);
}
.cmdk-row-icon {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-sunk); border-radius: var(--r-sm);
  color: var(--fg-dim);
}
.cmdk-row-icon svg { width: 14px; height: 14px; }
.cmdk-row-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cmdk-row-title { font: 500 14px/1.2 var(--f-body); color: var(--fg); }
.cmdk-row-sub { font: 400 12px/1.2 var(--f-mono); color: var(--fg-dim); }
.cmdk-row-meta { font: 500 11px/1 var(--f-mono); color: var(--fg-faint); }
.cmdk-empty {
  padding: var(--s-7) var(--s-5);
  text-align: center;
  font: 400 13px/1.5 var(--f-body);
  color: var(--fg-dim);
}
.cmdk-foot {
  display: flex; gap: var(--s-4); align-items: center;
  padding: var(--s-3) var(--s-5);
  background: var(--bg-sunk);
  border-top: 1px solid var(--hair);
  font: 400 11px/1 var(--f-mono); color: var(--fg-dim);
}
.cmdk-foot kbd {
  font: 500 11px/1 var(--f-mono);
  padding: 3px 6px; border-radius: var(--r-xs);
  background: var(--bg-paper); color: var(--fg);
  border: 1px solid var(--hair);
  margin-right: 4px;
}

/* ── 13.3 DENSITY MODE — DEMO ─────────────────────────────────── */
.density-demo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-5);
}
.density-demo[data-density="compact"] .density-card { --row-h: var(--row-h-compact); }
.density-demo .density-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.density-demo .density-card-head {
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--hair);
  display: flex; justify-content: space-between; align-items: center;
}
.density-demo .density-card-label {
  font: 500 11px/1 var(--f-mono); color: var(--fg-dim);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.density-demo .density-card-tag {
  font: 500 11px/1 var(--f-mono); color: var(--accent-text);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.density-demo .density-row {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: var(--s-3); align-items: center;
  padding: 0 var(--s-4);
  height: var(--row-h, var(--row-h-comfortable));
  border-bottom: 1px solid var(--hair-soft);
  font: 400 14px/1.3 var(--f-body); color: var(--fg);
  transition: background var(--dur-1) var(--ease);
}
.density-demo .density-row:last-child { border-bottom: 0; }
.density-demo .density-row:hover { background: var(--surface-list-row-hover); }
.density-demo .density-row .av {
  width: 26px; height: 26px; font-size: 10.5px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--f-display); font-weight: 600;
}
.density-demo .density-row-meta { font: 500 11px var(--f-mono); color: var(--fg-dim); }
@media (max-width: 720px) { .density-demo { grid-template-columns: 1fr; } }

.density-toggle {
  display: inline-flex;
  border: 1px solid var(--hair); border-radius: var(--r-pill);
  background: var(--bg-paper);
  padding: 3px;
}
.density-toggle button {
  border: 0; background: transparent;
  padding: 6px 14px; border-radius: var(--r-pill);
  font: 500 12px/1 var(--f-body); color: var(--fg-dim);
  cursor: pointer;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
.density-toggle button.is-active {
  background: var(--ink); color: var(--paper);
}

/* ── 13.4 EMPTY STATES ────────────────────────────────────────── */
.empty-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--s-5);
}
.empty-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-7) var(--s-5);
  display: flex; flex-direction: column; align-items: center; gap: var(--s-3);
  text-align: center;
}
.empty-card .empty-illo {
  width: 96px; height: 96px;
  margin-bottom: var(--s-2);
  display: grid; place-items: center;
}
.empty-card .empty-illo svg { width: 100%; height: 100%; }
.empty-card h3 {
  font: 700 18px/1.2 var(--f-display); letter-spacing: -0.01em;
  margin: 0; color: var(--fg);
}
.empty-card h3 em { font-family: var(--f-serif); font-style: italic; font-weight: 400; color: var(--accent-text); font-variation-settings: "SOFT" 80; }
.empty-card p {
  font: 400 14px/1.5 var(--f-body); color: var(--fg-soft);
  margin: 0; max-width: 28ch;
}
.empty-card .empty-actions {
  display: flex; gap: var(--s-3); align-items: center;
  margin-top: var(--s-3);
}
.empty-card .empty-cta {
  background: var(--accent); color: var(--paper);
  padding: 10px 18px; border-radius: var(--r-pill);
  font: 600 13px/1 var(--f-body);
  border: 0; cursor: pointer; text-decoration: none;
  display: inline-flex; align-items: center; gap: 6px;
  transition: background var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
  box-shadow: var(--sh-pink);
}
.empty-card .empty-cta:hover { transform: translateY(-1px); }
.empty-card .empty-link {
  font: 500 13px/1 var(--f-body); color: var(--fg-soft); text-decoration: none;
  border-bottom: 1px dashed var(--fg-faint);
}
.empty-card .empty-link:hover { color: var(--fg); border-bottom-color: var(--fg); }

/* ── Chapter 13 mobile fixes ─────────────────────────────────── */
@media (max-width: 720px) {
  /* Detail-shell tabs (13.1) — 5 tabs cram and the parent
     .detail-shell { overflow: hidden } would clip tabs 4 & 5
     entirely. Switch to horizontal scroll so all tabs are reachable
     via swipe, scrollbar hidden for cleanliness. */
  .detail-shell .ds-tabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap;
  }
  .detail-shell .ds-tab { flex: 0 0 auto; }
  .detail-shell .ds-tabs::-webkit-scrollbar { display: none; }
  .detail-shell .ds-tabs { scrollbar-width: none; }  /* firefox */
}

@media (max-width: 480px) {
  /* Command palette (13.2) — content overflows the 277px wrapper
     because of generous padding + footer kbd-hint row. Tighten the
     side padding, let the footer wrap, and hide the per-row shortcut
     hints (they're keyboard-only signals — irrelevant on touch). */
  .cmdk-input-wrap, .cmdk-row, .cmdk-foot, .cmdk-group-label {
    padding-left: var(--s-3);
    padding-right: var(--s-3);
  }
  .cmdk-input { font-size: 15px; }  /* slightly smaller on tiny screens */
  .cmdk-foot { flex-wrap: wrap; gap: var(--s-2); }
  .cmdk-row-meta { display: none; }

  /* Detail-shell rail toggle (13.1) — when the right rail collapses
     to icon-strip, the toggle button is too small to tap (28px).
     Bump to 36px so it clears Apple's 44px touch-target leniency. */
  .ds-rail-toggle { width: 36px; height: 36px; }

  /* Empty-card actions (13.4) — wrap CTA + import link if they overflow */
  .empty-card .empty-actions { flex-wrap: wrap; justify-content: center; }

  /* Detail-shell tab labels (13.1) — at 480px down, 5 tabs fit but the
     padding is the bottleneck. Tighten side padding so labels keep
     breathing room without scrollbar appearing. */
  .detail-shell .ds-tab { padding-left: var(--s-3); padding-right: var(--s-3); font-size: 12px; }

  /* Detail-shell header (13.1) — meta row + actions stack at narrow widths */
  .detail-shell .ds-header { flex-wrap: wrap; gap: var(--s-2); }
  .detail-shell .ds-header-actions { flex-wrap: wrap; }
}

@media (max-width: 380px) {
  /* Very narrow phones (iPhone SE / mini): give the heaviest layouts
     extra breathing room. */

  /* Detail-shell main column (13.1) — already collapsed to 1fr at
     1100px. At 380px, tighten side padding so content doesn't jam
     into the screen edges. */
  .detail-shell .ds-main { padding: var(--s-4); }
  .detail-shell .ds-rail, .detail-shell .ds-rail--right { padding: var(--s-4); }

  /* Command palette (13.2) — keep within viewport edges with a small
     gutter. The wrapper itself is already `width: 100%` so this just
     adds the breathing room. */
  .cmdk { max-width: calc(100vw - 24px); }
  .cmdk-row { grid-template-columns: 24px 1fr; }
  .cmdk-row-icon { width: 24px; height: 24px; }

  /* Density demo (13.3) — already stacks 1-col at 720px; tighten
     row padding so 36px compact row stays scannable. */
  .density-demo .density-row { padding-left: var(--s-3); padding-right: var(--s-3); }

  /* Empty-card (13.4) — illustration is decorative; on tiny screens
     hide to give the headline + CTA more vertical room. */
  .empty-card .empty-illo { display: none; }
  .empty-card { padding: var(--s-5); }
}

/* ─────────────────────────── Chapter 15 — App AI ─────────────────────── */
/* Verbatim migration of chapter-15 component CSS. The `--ai-glow-bg` and
   `--gradient-glow-soft` tokens this chapter relies on are already defined
   in `:root` + the dark-mode override at the top of this file (lines 184-190
   / 266-271), so no token migration is needed. */

/* ── 15.1 SAGE AI DRAWER ──────────────────────────────────────── */
.sage-drawer {
  width: 100%;
  max-width: 420px;
  height: 600px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  display: grid;
  grid-template-rows: auto 1fr auto;
  overflow: hidden;
  box-shadow: var(--sh-3);
  /* In real use: position: fixed; right: 0; top: 0; height: 100vh;
     width: 360px (resizable 320–520); border-radius: 0; */
}
.sage-head {
  padding: var(--s-4) var(--s-5);
  background: var(--gradient-glow-soft);
  border-bottom: 1px solid var(--hair);
  display: flex; flex-direction: column; gap: var(--s-2);
}
.sage-head .sage-row1 { display: flex; align-items: center; justify-content: space-between; }
.sage-wordmark {
  font-family: var(--f-serif); font-style: italic; font-weight: 500;
  font-size: 22px; line-height: 1; letter-spacing: -0.01em;
  color: var(--fg);
  font-variation-settings: "SOFT" 80;
  display: inline-flex; align-items: center; gap: 8px;
}
.sage-spark {
  width: 16px; height: 16px;
  color: var(--accent-text);
}
.sage-close {
  background: transparent; border: 1px solid transparent;
  color: var(--fg-dim); cursor: pointer;
  width: 28px; height: 28px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
}
.sage-close:hover { background: rgba(255,255,255,0.4); color: var(--fg); }
.sage-context {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: var(--r-pill);
  background: rgba(255,255,255,0.5);
  border: 1px solid var(--hair);
  font: 500 11px/1 var(--f-mono); color: var(--fg-soft);
  text-transform: uppercase; letter-spacing: 0.06em;
  align-self: flex-start;
}
.sage-stream {
  overflow-y: auto;
  padding: var(--s-4) var(--s-5);
  display: flex; flex-direction: column; gap: var(--s-4);
}
.sage-msg {
  display: flex; flex-direction: column; gap: 4px;
}
.sage-msg-author {
  font: 500 10px/1 var(--f-mono); color: var(--fg-faint);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.sage-msg-body {
  font: 400 14px/1.5 var(--f-body); color: var(--fg);
}
.sage-msg.is-user {
  align-self: flex-end; max-width: 80%;
}
.sage-msg.is-user .sage-msg-body {
  background: var(--accent);
  color: var(--paper);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  border-bottom-right-radius: var(--r-xs);
}
.sage-msg.is-user .sage-msg-author { text-align: right; color: var(--fg-faint); }
.sage-msg.is-assistant .sage-msg-body {
  padding-right: var(--s-2);
}

/* Tool-call card (collapsed by default) */
.sage-tool-call {
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--bg);
  font: 500 12px/1.4 var(--f-mono);
}
.sage-tool-call summary {
  padding: 8px var(--s-3);
  cursor: pointer;
  display: flex; align-items: center; gap: 8px;
  list-style: none;
  color: var(--fg-soft);
}
.sage-tool-call summary::-webkit-details-marker { display: none; }
.sage-tool-call summary::before {
  content: "›"; transition: transform var(--dur-2) var(--ease);
  display: inline-block; color: var(--fg-faint);
}
.sage-tool-call[open] summary::before { transform: rotate(90deg); }
.sage-tool-call .sage-tc-name { color: var(--accent-text); }
.sage-tool-call .sage-tc-body {
  padding: var(--s-3); font-size: 11.5px;
  border-top: 1px solid var(--hair-soft);
  color: var(--fg-soft);
  background: var(--bg-paper);
}

/* Proposal card (highlighted with --accent-soft) */
.sage-proposal {
  background: var(--accent-soft);
  border: 1px solid color-mix(in oklab, var(--accent) 30%, transparent);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-3);
}
.sage-proposal-head {
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 10px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--accent-text);
}
.sage-proposal-body {
  font: 400 13px/1.45 var(--f-body); color: var(--fg);
}
.sage-proposal-actions {
  display: flex; gap: var(--s-2); flex-wrap: wrap;
}
.sage-proposal-actions button {
  padding: 6px 12px; border-radius: var(--r-pill);
  font: 600 12px/1 var(--f-body);
  cursor: pointer;
  border: 1px solid transparent;
}
.sage-proposal-actions .sage-prop-accept { background: var(--accent); color: var(--paper); }
.sage-proposal-actions .sage-prop-edit { background: var(--bg-paper); color: var(--fg); border-color: var(--hair); }
.sage-proposal-actions .sage-prop-dismiss { background: transparent; color: var(--fg-soft); }
.sage-proposal-actions .sage-prop-dismiss:hover { color: var(--fg); }

/* Streaming dots */
.sage-typing {
  display: inline-flex; gap: 4px;
  padding: var(--s-3) var(--s-4);
  background: var(--bg-sunk);
  border-radius: var(--r-md);
  align-self: flex-start;
}
.sage-typing-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--fg-dim);
  animation: sage-pulse 1.2s var(--ease) infinite;
}
.sage-typing-dot:nth-child(2) { animation-delay: 0.2s; }
.sage-typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes sage-pulse {
  0%, 100% { opacity: 0.3; transform: translateY(0); }
  50%      { opacity: 1;   transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .sage-typing-dot { animation: none; opacity: 0.6; transform: none; }
  .sage-typing::after {
    content: "thinking…"; font: 400 12px var(--f-mono);
    color: var(--fg-dim); margin-left: 4px;
  }
  .sage-typing-dot { display: none; }
}

.sage-composer {
  border-top: 1px solid var(--hair);
  background: var(--bg);
  padding: var(--s-3) var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-2);
}
.sage-prompts {
  display: flex; gap: 6px; flex-wrap: wrap;
}
.sage-prompt-chip {
  padding: 5px 10px;
  background: var(--bg-paper); border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font: 500 11px/1 var(--f-body); color: var(--fg-soft);
  cursor: pointer;
  transition: all var(--dur-2) var(--ease);
}
.sage-prompt-chip:hover { border-color: var(--accent); color: var(--accent-text); }
.sage-input-row {
  display: flex; gap: var(--s-2); align-items: flex-end;
}
.sage-input {
  flex: 1; min-height: 38px; max-height: 180px;
  padding: 10px 12px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  font: 400 13px/1.45 var(--f-body); color: var(--fg);
  resize: none; outline: none;
}
.sage-input:focus { border-color: var(--accent); box-shadow: var(--ring-accent-strong); }
.sage-send {
  background: var(--accent); color: var(--paper);
  border: 0; cursor: pointer;
  padding: 8px 14px; border-radius: var(--r-md);
  font: 600 12px/1 var(--f-body);
  display: inline-flex; align-items: center; gap: 6px;
  flex-shrink: 0;
  height: 38px;
}
.sage-send svg { width: 14px; height: 14px; }

/* When the SageDrawer is rendered as a fixed right-edge overlay (TSX
   `<SageDrawer>` with `floating` mode), this modifier flips border-radius
   off, anchors to the viewport, and exposes a left-edge resize handle
   between 320px and 520px wide. */
.sage-drawer.is-floating {
  position: fixed; top: 0; right: 0; bottom: 0;
  height: 100vh; max-width: 520px; min-width: 320px;
  border-radius: 0;
  border-top: 0; border-right: 0; border-bottom: 0;
  z-index: 60;
}
.sage-drawer-resize {
  position: absolute; top: 0; left: -3px; bottom: 0; width: 6px;
  cursor: ew-resize;
  background: transparent;
  z-index: 1;
}
.sage-drawer-resize:hover,
.sage-drawer.is-resizing .sage-drawer-resize {
  background: color-mix(in oklab, var(--accent) 20%, transparent);
}

/* ── 15.2 COMPOSE DRAWER ──────────────────────────────────────── */
.compose {
  width: 100%;
  max-width: 600px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--sh-3);
  display: grid;
  grid-template-rows: auto auto auto 1fr auto;
}
.compose-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--hair);
  background: var(--bg);
}
.compose-head h4 {
  font: 600 14px/1 var(--f-display); color: var(--fg); margin: 0;
  display: inline-flex; align-items: center; gap: 8px;
}
.compose-head-actions { display: inline-flex; gap: var(--s-2); }
.compose-icon-btn {
  background: transparent; border: 1px solid transparent;
  color: var(--fg-dim); cursor: pointer;
  width: 28px; height: 28px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
}
.compose-icon-btn:hover { background: var(--bg-sunk); color: var(--fg); border-color: var(--hair); }
.compose-icon-btn svg { width: 14px; height: 14px; }
.compose-headers {
  padding: var(--s-3) var(--s-4);
  display: grid; gap: var(--s-2);
  border-bottom: 1px solid var(--hair-soft);
  font: 400 13px/1.4 var(--f-body);
}
.compose-header-row { display: grid; grid-template-columns: 60px 1fr; gap: var(--s-3); align-items: baseline; }
.compose-header-label { font: 500 11px/1 var(--f-mono); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.08em; padding-top: 4px; }
.compose-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px 3px 10px;
  background: var(--accent-soft); color: var(--accent-text);
  border: 1px solid color-mix(in oklab, var(--accent) 25%, transparent);
  border-radius: var(--r-pill);
  font: 500 12px/1 var(--f-body);
  margin-right: 4px;
}
.compose-chip-x { background: transparent; border: 0; color: inherit; cursor: pointer; padding: 0 2px; opacity: 0.7; }
.compose-chip-x:hover { opacity: 1; }
.compose-meta-row {
  display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap;
  padding: var(--s-2) var(--s-4);
  background: var(--bg);
  border-bottom: 1px solid var(--hair-soft);
  font: 500 11px/1 var(--f-mono); color: var(--fg-dim);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.compose-meta-pill {
  padding: 4px 10px; border-radius: var(--r-pill);
  background: var(--bg-paper); border: 1px solid var(--hair);
  cursor: pointer;
}
.compose-meta-pill.is-on { background: var(--success); color: var(--paper); border-color: var(--success); }
.compose-subject {
  padding: var(--s-3) var(--s-4);
  font: 600 16px/1.3 var(--f-display); color: var(--fg);
  border: 0; outline: none;
  border-bottom: 1px solid var(--hair-soft);
  background: transparent;
}
.compose-subject::placeholder { color: var(--fg-faint); font-weight: 500; }
.compose-ai-bar {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: var(--s-3) var(--s-4);
  background: var(--ai-glow-bg);
  border-bottom: 1px solid var(--hair-soft);
  align-items: center;
}
.compose-ai-eyebrow {
  font: 500 10px/1 var(--f-mono); color: var(--accent-text);
  text-transform: uppercase; letter-spacing: 0.08em;
  display: inline-flex; align-items: center; gap: 4px;
  margin-right: var(--s-2);
}
.compose-ai-chip {
  padding: 5px 10px;
  background: var(--bg-paper);
  border: 1px solid color-mix(in oklab, var(--accent) 20%, transparent);
  border-radius: var(--r-pill);
  font: 500 11px/1 var(--f-body); color: var(--fg);
  cursor: pointer;
  transition: all var(--dur-2) var(--ease);
}
.compose-ai-chip:hover { border-color: var(--accent); color: var(--accent-text); }
.compose-body {
  padding: var(--s-4);
  min-height: 240px;
  max-height: 360px;
  overflow-y: auto;
  font: 400 14px/1.55 var(--f-body); color: var(--fg);
  border: 0; outline: none;
}
.compose-body p { margin: 0 0 var(--s-3); }
.compose-body code.var-tag {
  display: inline-block;
  padding: 1px 6px;
  background: var(--accent-soft); color: var(--accent-text);
  border-radius: var(--r-xs);
  font: 500 12.5px/1.2 var(--f-mono);
}
.compose-foot {
  display: flex; justify-content: space-between; align-items: center;
  padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--hair);
  background: var(--bg);
  font: 500 11px var(--f-mono); color: var(--fg-dim);
}
.compose-foot-actions { display: flex; gap: var(--s-2); }
.compose-foot button {
  border: 1px solid var(--hair);
  background: var(--bg-paper);
  color: var(--fg);
  padding: 8px 14px; border-radius: var(--r-md);
  font: 600 12px/1 var(--f-body);
  cursor: pointer;
}
.compose-send-btn {
  background: var(--accent) !important; color: var(--paper) !important;
  border-color: var(--accent) !important;
}
.compose-autosave {
  display: inline-flex; align-items: center; gap: 4px;
  font: 500 11px var(--f-mono); color: var(--fg-dim);
}
.compose-autosave-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--success);
}

/* When the ComposeDrawer is rendered as a fixed right-edge overlay (TSX
   `<ComposeDrawer>` with `floating` mode), this modifier flips border-radius
   off and anchors the composer to the viewport at 540px wide. */
.compose.is-floating {
  position: fixed; top: 0; right: 0; bottom: 0;
  height: 100vh; width: 540px; max-width: 100vw;
  border-radius: 0;
  border-top: 0; border-right: 0; border-bottom: 0;
  z-index: 60;
  grid-template-rows: auto auto auto auto auto 1fr auto;
}

/* ── 15.3 AI SUGGESTION CARD ──────────────────────────────────── */
.ai-card {
  background: var(--bg-paper);
  border: 1px solid color-mix(in oklab, var(--accent) 25%, var(--hair));
  border-radius: var(--r-lg);
  padding: var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-3);
  position: relative;
  overflow: hidden;
}
.ai-card::before {
  content: ""; position: absolute; inset: 0;
  background: var(--ai-glow-bg);
  pointer-events: none;
  z-index: 0;
}
.ai-card > * { position: relative; z-index: 1; }
.ai-card-head {
  display: flex; align-items: center; justify-content: space-between;
}
.ai-card-eyebrow {
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 11px/1 var(--f-mono); color: var(--accent-text);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.ai-card-eyebrow svg { width: 13px; height: 13px; }
.ai-card-dismiss {
  background: transparent; border: 0; cursor: pointer;
  color: var(--fg-faint);
  width: 22px; height: 22px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
}
.ai-card-dismiss:hover { color: var(--fg); background: rgba(255,255,255,0.6); }
.ai-card-body {
  font: 400 14px/1.55 var(--f-body); color: var(--fg);
  margin: 0;
}
.ai-card-body em { font-family: var(--f-serif); font-style: italic; color: var(--accent-text); font-variation-settings: "SOFT" 80; font-weight: 400; }
.ai-card-actions {
  display: flex; gap: var(--s-2); align-items: center; margin-top: 4px;
}
.ai-card-cta {
  background: var(--accent); color: var(--paper);
  padding: 8px 14px; border-radius: var(--r-pill);
  font: 600 12px/1 var(--f-body);
  border: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.ai-card-edit {
  background: var(--bg-paper); color: var(--fg);
  padding: 8px 12px; border-radius: var(--r-pill);
  font: 500 12px/1 var(--f-body);
  border: 1px solid var(--hair); cursor: pointer;
}
.ai-card-link {
  color: var(--fg-soft); font: 500 12px/1 var(--f-body);
  text-decoration: none; border-bottom: 1px dashed var(--fg-faint);
}
.ai-card-link:hover { color: var(--fg); border-bottom-color: var(--fg); }

/* Generating state — skeleton shimmer */
.ai-card.is-generating .ai-card-body { color: transparent; }
.ai-card.is-generating .ai-card-body::after {
  content: "Sage is thinking…";
  display: block;
  font: 400 13px var(--f-mono); color: var(--fg-dim);
  font-style: italic;
}
.ai-card.is-generating .ai-card-actions { display: none; }

/* Dismissed-collapsed state */
.ai-card-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--r-pill);
  background: var(--bg-paper);
  border: 1px solid color-mix(in oklab, var(--accent) 25%, var(--hair));
  font: 500 12px/1 var(--f-body); color: var(--accent-text);
  cursor: pointer;
}
.ai-card-chip svg { width: 12px; height: 12px; }
.ai-card-chip:hover { background: var(--accent-soft); }

/* ── 15.4 KB SUGGESTION CARD ──────────────────────────────────── */
.kb-card-suggest {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-3);
}
.kb-card-suggest-head {
  display: flex; gap: var(--s-3); align-items: flex-start;
}
.kb-card-suggest-icon {
  width: 32px; height: 32px; border-radius: var(--r-sm);
  background: var(--bg-sunk);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--fg-dim);
  flex-shrink: 0;
}
.kb-card-suggest-icon svg { width: 18px; height: 18px; }
.kb-card-suggest-title {
  font: 600 14px/1.3 var(--f-display); color: var(--fg);
  margin: 0;
}
.kb-card-suggest-meta {
  font: 500 11px var(--f-mono); color: var(--fg-dim);
  text-transform: uppercase; letter-spacing: 0.06em;
  margin-top: 2px;
}
.kb-card-suggest-snippet {
  font: 400 13px/1.5 var(--f-body); color: var(--fg-soft);
  margin: 0;
}
.kb-card-suggest-snippet mark {
  background: var(--accent-soft); color: var(--fg);
  padding: 1px 3px; border-radius: 2px;
}
.kb-card-suggest-foot {
  display: flex; justify-content: space-between; align-items: center;
  padding-top: var(--s-2);
  border-top: 1px solid var(--hair-soft);
}
.kb-card-suggest-helpful {
  font: 500 11px/1 var(--f-mono); color: var(--fg-dim);
  display: inline-flex; align-items: center; gap: 8px;
}
.kb-card-suggest-helpful strong { color: var(--success-text); font-weight: 600; }
.kb-card-suggest-actions { display: inline-flex; gap: var(--s-2); }
.kb-card-suggest-actions button {
  border: 1px solid var(--hair); background: var(--bg-paper);
  padding: 6px 10px; border-radius: var(--r-sm);
  font: 500 12px/1 var(--f-body); color: var(--fg);
  cursor: pointer;
}
.kb-card-suggest-actions .kb-action-primary {
  background: var(--accent); color: var(--paper); border-color: var(--accent);
}
.kb-card-suggest-actions button:hover { border-color: var(--accent); }

/* ── 15.5 CONFETTI WIN MOMENT ─────────────────────────────────── */
.confetti-stage {
  position: relative;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-7);
  min-height: 240px;
  overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
}
.confetti-particle {
  position: absolute;
  top: 50%; left: 50%;
  width: 8px; height: 12px;
  background: var(--accent);
  opacity: 0;
  pointer-events: none;
}
.confetti-stage.is-firing .confetti-particle {
  animation: confetti-drift 1.4s var(--ease) forwards;
}
@keyframes confetti-drift {
  0%   { opacity: 0; transform: translate(-50%, -50%) rotate(0deg); }
  10%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--cx, -50%), 250px) rotate(var(--cr, 360deg)); }
}
@media (prefers-reduced-motion: reduce) {
  .confetti-stage.is-firing .confetti-particle { animation: none; opacity: 0; }
}
.confetti-toast {
  display: inline-flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-5);
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-pill);
  font: 600 14px/1 var(--f-body);
  box-shadow: var(--sh-3);
  position: relative; z-index: 2;
}
.confetti-toast .em { font-family: var(--f-serif); font-style: italic; color: var(--accent-text); font-variation-settings: "SOFT" 80; font-weight: 400; padding: 0 4px; }
.confetti-toast .ct-body { display: inline-flex; align-items: center; gap: 4px; }
.confetti-fire-btn {
  margin-top: var(--s-4);
  background: var(--accent); color: var(--paper);
  border: 0; cursor: pointer;
  padding: 10px 18px; border-radius: var(--r-pill);
  font: 600 13px var(--f-body);
  box-shadow: var(--sh-pink);
}

/* When `<ConfettiTrigger>` / `useConfetti()` fire programmatically into
   `document.body`, the particles are appended directly under <body> and
   need to be position: fixed (not absolute, since there's no positioned
   ancestor stage). */
.confetti-particle.is-global {
  position: fixed;
  top: 50%; left: 50%;
  z-index: 9999;
  animation: confetti-drift 1.4s var(--ease) forwards;
}
@media (prefers-reduced-motion: reduce) {
  .confetti-particle.is-global { animation: none; opacity: 0; display: none; }
}

/* Floating one-shot toast surfaced by useConfetti() when reduced-motion
   suppresses particles. Pinned to the bottom-centre, fades out. */
.confetti-floating-toast {
  position: fixed; left: 50%; bottom: var(--s-7);
  transform: translateX(-50%);
  z-index: 9998;
  display: inline-flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-5);
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-pill);
  font: 600 14px/1 var(--f-body);
  box-shadow: var(--sh-3);
  animation: confetti-floating-toast 1.6s var(--ease) forwards;
}
.confetti-floating-toast .em { font-family: var(--f-serif); font-style: italic; color: var(--accent-text); font-variation-settings: "SOFT" 80; font-weight: 400; padding: 0 4px; }
@keyframes confetti-floating-toast {
  0%   { opacity: 0; transform: translate(-50%, 16px); }
  10%  { opacity: 1; transform: translate(-50%, 0); }
  85%  { opacity: 1; transform: translate(-50%, 0); }
  100% { opacity: 0; transform: translate(-50%, -8px); }
}
@media (prefers-reduced-motion: reduce) {
  .confetti-floating-toast { animation: none; }
}

/* ── Chapter 15 mobile fixes ─────────────────────────────────── */
@media (max-width: 480px) {
  /* Compose drawer (15.2) — internal padding halved at narrow widths so
     content doesn't clip past the wrapper's max-width. */
  .compose-head,
  .compose-headers,
  .compose-meta-row,
  .compose-subject,
  .compose-ai-bar,
  .compose-body,
  .compose-foot {
    padding-left: var(--s-3);
    padding-right: var(--s-3);
  }
  .compose-meta-row { font-size: 10px; gap: var(--s-2); }
  .compose-meta-row span:not(.compose-meta-pill) { display: none; }
  .compose-foot-actions { flex-wrap: wrap; gap: var(--s-2); }
  .compose-foot-actions button { padding: 8px 12px; }
  .compose-ai-bar { gap: 4px; }
  .compose-ai-chip { padding: 4px 8px; font-size: 10.5px; }
  .compose-headers { gap: var(--s-2); font-size: 12.5px; }

  /* Sage drawer (15.1) — wrapper uses width: 100% with max-width: 420px
     so it shrinks. Tighten the inner padding so content has room. */
  .sage-head,
  .sage-stream,
  .sage-composer {
    padding-left: var(--s-3);
    padding-right: var(--s-3);
  }
  .sage-msg.is-user { max-width: 90%; }
  .sage-prompts { gap: 4px; }
  .sage-prompt-chip { padding: 4px 8px; font-size: 10.5px; }

  /* AI suggestion card (15.3) */
  .ai-card-actions { flex-wrap: wrap; gap: 6px; }

  /* KB suggestion card (15.4) — foot stacks count + actions */
  .kb-card-suggest-foot { flex-direction: column; align-items: flex-start; gap: var(--s-3); }
  .kb-card-suggest-actions { flex-wrap: wrap; gap: 6px; width: 100%; }
}

@media (max-width: 380px) {
  /* iPhone-SE-class viewports — pull padding tighter still. */
  .sage-msg .sage-avatar { width: 26px; height: 26px; flex-shrink: 0; }
  .sage-msg-body { font-size: 13px; }
  .sage-prompt-chip { font-size: 10px; padding: 3px 7px; }
  .sage-head-title { font-size: 13px; }
  .sage-citation { font-size: 10.5px; }

  .compose-meta-row .compose-meta-pill ~ span { display: none; }
  .compose-foot { padding-top: var(--s-2); padding-bottom: var(--s-2); }
  .compose-ai-bar { flex-wrap: wrap; }

  .ai-card { padding: var(--s-4); }
  .ai-card-body { font-size: 13px; }
  .ai-card-meta { font-size: 10.5px; gap: 4px; flex-wrap: wrap; }

  .kb-card-suggest { padding: var(--s-4); }
  .kb-card-suggest-title { font-size: 14px; }
  .kb-card-suggest-snippet { font-size: 12.5px; -webkit-line-clamp: 2; }

  .confetti-toast { left: 12px; right: 12px; bottom: 12px; max-width: none; }
  .confetti-toast .ct-body { font-size: 12.5px; }
}

/* ─────────────────────────── Chapter 14 — App pipeline ──────────────── */
/* Verbatim migration of chapter-14 component CSS. */

/* ── 14.1 KANBAN ──────────────────────────────────────────────── */
.kanban {
  display: grid;
  grid-template-columns: repeat(4, minmax(220px, 1fr));
  gap: var(--s-4);
  align-items: flex-start;
}
.kb-col {
  /* Use --warm-3 (lightest warm) over --bg-sunk (warm-5) so columns
     sit lightly on a paper page bg without the heavy contrast jump
     that warm-5 creates on white. Per user design preference. */
  background: var(--warm-3);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-3);
  display: flex; flex-direction: column;
  min-height: 360px;
  max-height: 520px;
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
/* In dark mode, --warm-3 stays pinned cream which would be heavy on
   the dark page bg — flip to --bg-sunk (dark) so columns remain
   distinct from the page paper. */
body[data-theme="dark"] .kb-col {
  background: var(--bg-sunk);
}
.kb-col.is-drop-target {
  background: var(--accent-soft);
  border-color: var(--accent);
  border-style: dashed;
}
.kb-col-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 4px 8px var(--s-3);
}
.kb-col-stage { font: 600 12px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg); }
.kb-col-count { font: 500 11px/1 var(--f-mono); color: var(--fg-dim);
  padding: 4px 8px; background: var(--bg-paper); border-radius: var(--r-pill); border: 1px solid var(--hair); }
.kb-col-sum { font: 600 11px/1 var(--f-mono); color: var(--fg-soft); margin-top: 2px; padding: 0 8px var(--s-3); }
.kb-cards {
  display: flex; flex-direction: column; gap: var(--s-2);
  overflow-y: auto;
  padding: 2px;
}
.kb-card {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-2);
  cursor: grab;
  transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
  position: relative;
}
.kb-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--sh-2); }
.kb-card.is-selected {
  box-shadow: var(--ring-accent-strong);
  border-color: var(--accent);
}
.kb-card.is-dragging {
  cursor: grabbing;
  box-shadow: var(--sh-3);
  transform: rotate(-2deg) translateY(-2px);
  opacity: 0.95;
}
.kb-card-row1 { display: flex; justify-content: space-between; align-items: center; gap: var(--s-2); }
.kb-card-industry {
  font: 500 10px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em;
  padding: 3px 7px; border-radius: var(--r-xs);
  /* Default chip = healthcare/info family. Use a darker info text color
     (vs the brand --info which is too bright on info-soft → fails AA).
     Inline-style chips below override both bg + color with darker pairs. */
  background: var(--info-soft); color: #1463A1;
}
body[data-theme="dark"] .kb-card-industry {
  color: var(--info-text);  /* in dark mode --info-soft is darker too, so brand info reads fine */
}
.kb-card-value { font: 700 14px/1 var(--f-display); font-variant-numeric: tabular-nums; color: var(--fg); }
.kb-card-name { font: 600 14px/1.3 var(--f-display); color: var(--fg); margin: 0; }
.kb-card-contact { font: 400 12px/1.3 var(--f-body); color: var(--fg-soft); margin: 0; }
.kb-card-meta { display: flex; align-items: center; gap: var(--s-2); margin-top: 2px; flex-wrap: wrap; }
.kb-card-glyphs {
  display: inline-flex; gap: 4px; flex: 1;
  color: var(--fg-faint);
}
.kb-card-glyphs svg { width: 12px; height: 12px; }
.kb-card-rings { display: inline-flex; gap: 6px; }
.kb-col-add {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: var(--s-2); padding: 8px;
  background: transparent; border: 1px dashed var(--hair); border-radius: var(--r-md);
  color: var(--fg-dim); cursor: pointer;
  font: 500 12px/1 var(--f-body);
  transition: border-color var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
.kb-col-add:hover { border-color: var(--accent); color: var(--accent-text); }
@media (prefers-reduced-motion: reduce) {
  .kb-card.is-dragging { transform: none; }
  .kb-card:hover { transform: none; }
}
@media (max-width: 880px) {
  .kanban { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
  .kanban { grid-template-columns: 1fr; }
}

/* ── 14.2 PIPELINE STAGE SEGMENTED BAR ──────────────────────────
   Three states (past / current / future), one consistent two-line
   layout (stage name + optional metric) so cells line up cleanly
   regardless of which carry data. Body font throughout — no more
   mono "avg 2d" debug-print look. State is communicated by fill
   colour first, text weight second; the "completed" mark moved
   from a 9px corner glyph to the cell background tint, which
   reads at a glance without the visual scratch. */
.pip-bar {
  display: flex;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  overflow: hidden;
  position: relative;
}
.pip-stage {
  flex: 1; min-width: 0;
  /* Generous horizontal padding so the label doesn't crowd the cell edges
     — especially noticeable on the active (filled) cell where text sat
     flush against the colored boundary. */
  padding: 18px 24px;
  text-align: center;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  position: relative;
  min-height: 76px;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
/* Cell separator — inset shadow instead of border so it sits
   *under* the rounded corners cleanly when the first/last cell
   is filled (past or current). */
.pip-stage:not(:last-child) { box-shadow: inset -1px 0 0 var(--hair); }

.pip-stage .pip-stage-label {
  font: 500 13.5px/1.2 var(--f-body);
  color: var(--fg);
  letter-spacing: -0.005em;
}
.pip-stage .pip-stage-days {
  font: 400 11.5px/1 var(--f-body);
  color: var(--fg-faint);
  letter-spacing: 0;
}

/* Past — completed: very light ink wash, dimmed text */
.pip-stage[data-state="past"] {
  background: color-mix(in oklab, var(--ink) 5%, transparent);
}
.pip-stage[data-state="past"] .pip-stage-label { color: var(--fg-dim); font-weight: 500; }
.pip-stage[data-state="past"] .pip-stage-days  { color: var(--fg-faint); }

/* Current — active stage: brand pink fill, paper text */
.pip-stage[data-state="current"] {
  background: var(--accent);
}
.pip-stage[data-state="current"] .pip-stage-label { color: var(--paper); font-weight: 600; }
.pip-stage[data-state="current"] .pip-stage-days  { color: color-mix(in oklab, var(--paper) 78%, var(--accent)); }

/* Future — not yet: transparent + dim */
.pip-stage[data-state="future"] .pip-stage-label { color: var(--fg-dim); font-weight: 500; }
.pip-stage[data-state="future"] .pip-stage-days  { color: var(--fg-faint); }

/* Hover (non-current cells) */
.pip-stage:hover:not([data-state="current"]) { background: var(--accent-soft); }
.pip-stage:hover:not([data-state="current"]) .pip-stage-label { color: var(--accent-text); }
.pip-stage:hover:not([data-state="current"]) .pip-stage-days  { color: color-mix(in oklab, var(--accent-text) 70%, var(--fg-faint)); }
.pip-stage[data-state="current"]:hover { background: color-mix(in oklab, var(--accent) 92%, var(--ink)); }

/* ── 14.3 ACTIVITY TIMELINE (6 sub-row variants) ──────────────── */
.act-timeline {
  display: flex; flex-direction: column;
  position: relative;
}
.act-filters {
  display: flex; gap: var(--s-2);
  margin-bottom: var(--s-5); flex-wrap: wrap;
}
.act-filter {
  padding: 6px 12px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font: 500 12px/1 var(--f-body);
  color: var(--fg-soft);
  cursor: pointer;
  transition: all var(--dur-2) var(--ease);
}
.act-filter:hover { border-color: var(--accent); color: var(--accent-text); }
.act-filter.is-active { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.act-divider {
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--fg-faint);
  padding: var(--s-4) 0 var(--s-2) 36px;
  position: relative;
}
.act-row {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  position: relative;
}
.act-row::before {
  content: "";
  position: absolute;
  left: 13px; top: 0; bottom: 0;
  width: 1px;
  background: var(--hair);
}
.act-row:last-child::before { bottom: 50%; }
.act-row .act-icon {
  width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-paper);
  border: 2px solid var(--hair);
  color: var(--fg-dim);
  position: relative; z-index: 1;
  flex-shrink: 0;
}
.act-row[data-type="email"] .act-icon { background: var(--info-soft); color: var(--info-text); border-color: color-mix(in oklab, var(--info) 30%, transparent); }
.act-row[data-type="conversation"] .act-icon { background: var(--accent-soft); color: var(--accent-text); border-color: color-mix(in oklab, var(--accent) 30%, transparent); }
.act-row[data-type="meeting"] .act-icon { background: color-mix(in oklab, var(--ink) 8%, transparent); color: var(--ink); border-color: var(--hair); }
.act-row[data-type="note"] .act-icon { background: var(--warning-soft); color: var(--warning-text); border-color: color-mix(in oklab, var(--warning) 30%, transparent); }
.act-row[data-type="stage-change"] .act-icon { background: var(--success-soft); color: var(--success-text); border-color: color-mix(in oklab, var(--success) 30%, transparent); }
.act-row[data-type="custom"] .act-icon { background: color-mix(in oklab, var(--accent) 8%, var(--bg-paper)); color: var(--accent-text); }
.act-row .act-icon svg { width: 13px; height: 13px; }
.act-row .act-body {
  display: flex; flex-direction: column; gap: 4px;
  min-width: 0;
}
.act-row .act-title { font: 600 14px/1.3 var(--f-body); color: var(--fg); }
.act-row .act-by { font-weight: 400; color: var(--fg-soft); }
.act-row .act-snippet { font: 400 13px/1.4 var(--f-body); color: var(--fg-soft); }
.act-row .act-meta-row { display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap; font: 400 12px var(--f-body); color: var(--fg-dim); margin-top: 4px; }
.act-row .act-time { font: 500 11px/1 var(--f-mono); color: var(--fg-dim); white-space: nowrap; padding-top: 6px; }
.act-row[data-expandable="true"] details > summary {
  cursor: pointer; list-style: none;
}
.act-row[data-expandable="true"] details > summary::-webkit-details-marker { display: none; }
.act-row[data-expandable="true"] details[open] .act-expand {
  margin-top: var(--s-3);
  padding: var(--s-3) var(--s-4);
  /* warm-3 (lightest warm) instead of bg-sunk — the email body reads
     calmer / less "dirty" against the white feed surface. Dark mode
     flips back to bg-sunk for proper sunken contrast. */
  background: var(--warm-3);
  border-radius: var(--r-md);
  font: 400 13px/1.55 var(--f-body); color: var(--fg-soft);
}
body[data-theme="dark"] .act-row[data-expandable="true"] details[open] .act-expand { background: var(--bg-sunk); }
.act-row .act-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: var(--r-pill);
  background: var(--warm-3); color: var(--fg-soft);
  font: 500 11px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.06em;
  border: 1px solid var(--hair);
}
body[data-theme="dark"] .act-row .act-chip { background: var(--bg-sunk); }
.act-row .act-chip-arrow {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font: 500 12px/1 var(--f-body); color: var(--fg-soft);
}
.act-row .act-attachments {
  display: inline-flex; gap: 6px; margin-top: 6px; flex-wrap: wrap;
}
.act-row .act-attachment {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 8px; background: var(--warm-3);
  border: 1px solid var(--hair); border-radius: var(--r-sm);
  font: 500 11px/1 var(--f-mono); color: var(--fg-soft);
}
body[data-theme="dark"] .act-row .act-attachment { background: var(--bg-sunk); }
.act-row .act-meters {
  display: inline-flex; gap: var(--s-3); margin-top: 6px;
  font: 500 11px/1 var(--f-mono); color: var(--fg-dim);
}
.act-row .act-meters strong { color: var(--fg); font-weight: 600; }

/* ── 14.4 INBOX ROW ───────────────────────────────────────────── */
.inbox {
  display: flex; flex-direction: column;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.inbox-row {
  display: grid;
  grid-template-columns: 36px 1fr auto auto;
  gap: var(--s-3); align-items: center;
  padding: 0 var(--s-4);
  height: var(--row-h, var(--row-h-comfortable));
  border-bottom: 1px solid var(--hair-soft);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease);
  position: relative;
}
.inbox-row:last-child { border-bottom: 0; }
.inbox-row:hover { background: var(--surface-list-row-hover); }
.inbox-row .av { width: 28px; height: 28px; font-size: 11px;
  border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--f-display); font-weight: 600; flex-shrink: 0;
}
.inbox-row .ix-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.inbox-row .ix-title { font: 500 14px/1.3 var(--f-body); color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.inbox-row .ix-sub { font: 400 12px/1.2 var(--f-mono); color: var(--fg-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.inbox-row .ix-due { font: 500 11px/1 var(--f-mono); color: var(--fg-dim); white-space: nowrap; }
.inbox-row .ix-actions { display: inline-flex; gap: 4px; }
.inbox-row .ix-action {
  background: transparent; border: 1px solid transparent; border-radius: var(--r-sm);
  width: 28px; height: 28px; cursor: pointer;
  color: var(--fg-dim);
  display: inline-flex; align-items: center; justify-content: center;
  transition: all var(--dur-2) var(--ease);
}
.inbox-row .ix-action:hover { background: var(--bg-sunk); color: var(--fg); border-color: var(--hair); }
.inbox-row .ix-action svg { width: 14px; height: 14px; }
.inbox-row[data-state="snoozed"] { opacity: 0.55; }
.inbox-row[data-state="overdue"] .ix-due { color: var(--error-text); font-weight: 600; }
.inbox-row[data-state="overdue"]::before {
  content: "";
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--error);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--error) 20%, transparent);
}
.inbox-row[data-state="completed"] .ix-title { text-decoration: line-through; color: var(--fg-faint); }
.inbox-row[data-state="completed"] .av { opacity: 0.55; }
.ix-priority {
  display: inline-flex; align-items: center;
  padding: 3px 8px; border-radius: var(--r-pill);
  font: 600 10px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em;
  background: var(--bg-sunk); color: var(--fg-dim);
  border: 1px solid var(--hair);
}
.ix-priority[data-p="high"] { background: var(--badge-bg-danger); color: var(--error-text); border-color: color-mix(in oklab, var(--error) 25%, transparent); }
.ix-priority[data-p="medium"] { background: var(--badge-bg-warning); color: var(--warning-text); border-color: color-mix(in oklab, var(--warning) 25%, transparent); }
.ix-priority[data-p="low"] { background: var(--info-soft); color: var(--info-text); border-color: color-mix(in oklab, var(--info) 25%, transparent); }

/* ── 14.5 ONBOARDING CHECKLIST ────────────────────────────────── */
.checklist {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.checklist-head {
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--hair);
  background: var(--bg);
}
.checklist-head h4 { font: 600 16px/1.2 var(--f-display); margin: 0 0 var(--s-2); color: var(--fg); }
.checklist-progress {
  display: flex; align-items: center; gap: var(--s-3);
  font: 500 11px/1 var(--f-mono); color: var(--fg-dim);
}
.checklist-progress-bar {
  flex: 1; height: 6px;
  background: var(--bg-sunk); border-radius: var(--r-pill);
  overflow: hidden;
}
.checklist-progress-fill {
  height: 100%;
  background: var(--success);
  border-radius: inherit;
  transition: width var(--dur-3) var(--ease);
}
.checklist-items { display: flex; flex-direction: column; }
.checklist-item {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  gap: var(--s-3); align-items: center;
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--hair-soft);
  transition: background var(--dur-1) var(--ease);
}
.checklist-item:last-child { border-bottom: 0; }
.checklist-item:hover { background: var(--bg); }
.checklist-tick {
  width: 22px; height: 22px;
  border: 1.8px solid var(--hair);
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-paper);
  cursor: pointer;
  transition: all var(--dur-2) var(--ease);
}
.checklist-tick:hover { border-color: var(--success); }
.checklist-item[data-state="done"] .checklist-tick {
  background: var(--success); border-color: var(--success);
  color: var(--paper);
}
.checklist-item[data-state="done"] .checklist-title { text-decoration: line-through; color: var(--fg-faint); }
.checklist-item[data-state="done"] .checklist-desc { color: var(--fg-faint); }
.checklist-item[data-state="skipped"] { opacity: 0.5; }
.checklist-item[data-state="skipped"] .checklist-title { font-style: italic; }
.checklist-tick svg { width: 12px; height: 12px; opacity: 0; transition: opacity var(--dur-1); }
.checklist-item[data-state="done"] .checklist-tick svg { opacity: 1; }
.checklist-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.checklist-title { font: 600 14px/1.3 var(--f-body); color: var(--fg); }
.checklist-desc { font: 400 12px/1.4 var(--f-body); color: var(--fg-soft); }
.checklist-item-meta { display: flex; gap: var(--s-3); align-items: center; }
.checklist-due { font: 500 11px/1 var(--f-mono); color: var(--fg-dim); white-space: nowrap; }
.checklist-due.is-overdue { color: var(--error-text); }
.checklist-item .av { width: 22px; height: 22px; font-size: 9px; flex-shrink: 0;
  border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--f-display); font-weight: 600;
}
.checklist-more {
  background: transparent; border: 0; cursor: pointer;
  padding: 4px 6px; color: var(--fg-faint);
  border-radius: var(--r-sm);
}
.checklist-more:hover { color: var(--fg); background: var(--bg-sunk); }

/* ── 14.6 MRR COMPOSITION CHART ─────────────────────────────────
   Diverging-bar layout — positive components (New + Expansion) stack
   ABOVE the zero line; negative components (Contraction + Churn) stack
   BELOW it. Was a stacked area where contraction/churn rendered as if
   they added to MRR (visually the opposite of reality). Now an operator
   can scan it and see at a glance: which months were good, which had
   spiking churn, whether expansion is keeping up with cancellations. */
.mrr-chart {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-5);
}
.mrr-chart-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  margin-bottom: var(--s-4);
  flex-wrap: wrap; gap: var(--s-4);
}
.mrr-chart-title { font: 600 16px/1.2 var(--f-display); color: var(--fg); margin: 0; }
.mrr-chart-formula {
  font: 400 12px/1.4 var(--f-mono); color: var(--fg-dim);
  margin-top: 4px; letter-spacing: 0;
}
.mrr-chart-stat { text-align: right; }
.mrr-chart-value {
  font: 700 28px/1 var(--f-display);
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}
.mrr-chart-delta {
  font: 600 13px/1 var(--f-mono);
  color: var(--success-text);
  margin-left: var(--s-2);
  vertical-align: middle;
}
.mrr-chart-stat-label {
  font: 400 11px/1 var(--f-mono); color: var(--fg-dim);
  margin-top: 4px; text-transform: uppercase; letter-spacing: 0.08em;
}

/* Breakdown row — the math under the headline number, so a viewer
   sees how the four series add up to net. */
.mrr-breakdown {
  display: flex; align-items: center; gap: var(--s-4);
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-4);
  background: var(--warm-3);
  border-radius: var(--r-md);
  margin-bottom: var(--s-4);
  font: 500 12px/1 var(--f-mono);
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}
body[data-theme="dark"] .mrr-breakdown { background: var(--bg-sunk); }
.mrr-bd { display: inline-flex; align-items: center; gap: 6px; }
.mrr-bd .sw { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.mrr-bd small {
  font: 400 11px/1 var(--f-mono);
  color: var(--fg-dim);
  text-transform: uppercase; letter-spacing: 0.06em;
  margin-left: 2px;
}
.mrr-bd-equals { color: var(--fg-dim); font-weight: 400; }
.mrr-bd.is-net { font-weight: 700; }
.mrr-bd.is-net small { color: var(--success-text); font-weight: 600; }

.mrr-chart svg { width: 100%; height: auto; display: block; }

.mrr-legend {
  display: flex; gap: var(--s-4); flex-wrap: wrap;
  margin-top: var(--s-4);
  padding-top: var(--s-3); border-top: 1px solid var(--hair-soft);
}
.mrr-legend-item {
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 12px/1.2 var(--f-body); color: var(--fg-soft);
  cursor: pointer; user-select: none;
  padding: 4px 0;
}
.mrr-legend-item small {
  font: 400 11px/1.2 var(--f-mono);
  color: var(--fg-dim); margin-left: 2px;
}
.mrr-legend-swatch {
  width: 12px; height: 12px; border-radius: 3px;
  flex-shrink: 0;
}
.mrr-legend-item.is-off { opacity: 0.4; }
.mrr-legend-item.is-off .mrr-legend-swatch { filter: grayscale(0.8); }

/* ── Chapter 14 mobile fixes ─────────────────────────────────────
   Surgical mobile fixes for chapter-14 components that don't naturally
   fit a 375px viewport. */
@media (max-width: 480px) {
  /* Pipeline bar (14.2) — 5 stages × 78px = 390px overflows. Keep
     all stages visible-and-labelled by enabling horizontal scroll;
     each stage gets a min-width so labels never crush. The horizontal
     metaphor ("this is a pipeline") is preserved this way — better
     than stacking vertically. */
  .pip-bar {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
  }
  .pip-bar::-webkit-scrollbar { height: 4px; }
  .pip-bar::-webkit-scrollbar-thumb { background: var(--hair); border-radius: 2px; }
  .pip-stage {
    flex: 0 0 auto;
    min-width: 96px;
    scroll-snap-align: start;
  }

  /* Activity row (14.3) — already fits but the action attachment row
     can wrap awkwardly. Tighten the meta-row gap so chips wrap cleanly. */
  .act-row .act-meta-row { gap: var(--s-2); font-size: 11px; }
  .act-row .act-attachments { gap: 4px; }
  .act-row .act-meters { gap: var(--s-2); font-size: 10px; }

  /* Kanban card (14.1) — already collapsed to 1-col at 520px, but
     padding still feels heavy at 375px. */
  .kb-card { padding: var(--s-3) var(--s-4); }
  .kb-card-name { font-size: 13px; }

  /* Inbox row (14.4) — collapses gracefully but the right-side meta
     gets stacked oddly. Force compact column. */
  .inbox-row { padding: var(--s-3) var(--s-4); }

  /* Onboarding checklist (14.5) — meta row collapses, hide due-date
     when there's also an avatar to keep row height sane. */
  .checklist-item { padding: var(--s-3) var(--s-4); }
  .checklist-item-meta { gap: var(--s-2); }

  /* MRR chart (14.6) — head row already wraps; numbers shrink one
     notch so $48.2k and the delta share a line. */
  .mrr-chart { padding: var(--s-4); }
  .mrr-chart-value { font-size: 22px; }
  .mrr-chart-delta { font-size: 11px; }
  .mrr-legend { gap: var(--s-3); font-size: 11px; }
}
