/* ============================================================
   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;
}
.topnav .brand-mark {
  width: 26px; height: 26px; display: inline-block;
  background: url("../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));
}

.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; }

/* ─── 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 svg { color: var(--fg-dim); }

.stepper { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.step {
  display: grid; grid-template-columns: 32px 1fr;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  position: relative;
}
.step:not(:last-child)::before {
  content: ""; position: absolute;
  top: 38px; bottom: -6px; left: 15px; width: 2px;
  background: var(--hair);
}
.step.is-done::before { background: var(--accent); }
.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;
}
.step.is-done .step-dot { background: var(--accent); border-color: var(--accent); color: var(--paper); }
.step.is-active .step-dot { border-color: var(--accent); color: var(--accent-text); box-shadow: 0 0 0 4px var(--accent-soft); }
.step-name { font: 600 14.5px/1.3 var(--f-display); color: var(--fg); }
.step.is-done .step-name { color: var(--fg-soft); }
.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); }

.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); }
}

