/* ============================================================
   EduMarkets — Base CSS: Variables, Typography, Grid
   ============================================================ */

/* Inter font loaded via <link> in index.html — no @import needed */

/* ── Colour tokens ── */
:root {
  /* Brand */
  --color-brand:        #1B3A5C;
  --color-accent:       #2E6DA4;
  --color-accent-light: #4B9FD4;
  /* Accent as INK, not as chrome. --color-accent is a fill/border colour: at
     #2E6DA4 it reads well as a background but only reaches 2.9-3.5:1 as text
     on the dark surfaces, under the 4.5:1 WCAG AA wants. This lighter accent
     is for `color:` only; fills, borders and chrome stay on --color-accent.
     Light theme keeps #2E6DA4, which passes on light surfaces. */
  --color-accent-text:  #5A9BD4;
  --color-light:        #D5E8F0;
  --sidebar-accent:     #14b8a6;
  --sidebar-accent-dim: rgba(20, 184, 166, 0.45);

  /* Dark mode (default) — GitHub-dark inspired, no halation against
     pure black; #0D1117 / #161B22 read as charcoal-blue rather than
     true black, which is sharper on Plotly canvases and carries the
     Bloomberg-feel without the brand colour. */
  --bg:          #0D1117;
  --bg-surface:  #161B22;
  --bg-header:   #1A1F26;
  --bg-elevated: #1C232C;
  --bg-input:    #20262F;
  --border:      #252830;
  --border-subtle: #1a1c22;
  --text:        #e8eaf0;
  --text-table:  #d4d8e6;
  --text-secondary: #cdd1e0;
  --text-muted:  #a8aec8;

  /* Semantic */
  --neutral:     #94a3b8;
  /* Scrollbar thumb. Separate token because the two themes need different
     weights: on dark this sits light against the background, on light it has
     to stay well above the border greys or it reads as a black bar. */
  --scrollbar-thumb: #94a3b8;
  --positive:    #22c55e;
  --negative:    #ef4444;
  --warning:     #f59e0b;
  --info:        #3b82f6;
  /* Extended palette for learn-content 8-colour card rotation */
  --lv-purple:   #a78bfa;
  --lv-pink:     #f472b6;
  --positive-bg: rgba(34, 197, 94, 0.08);
  --negative-bg: rgba(239, 68, 68, 0.08);
  --info-bg:     rgba(59, 130, 246, 0.08);
  --warning-bg:  rgba(245, 158, 11, 0.08);

  /* Typography */
  --font:        'Inter', system-ui, -apple-system, sans-serif;
  --font-mono:   'JetBrains Mono', 'Fira Code', monospace;

  /* Radius */
  --r-sm:   4px;
  --r-md:   8px;
  --r-lg:   12px;
  --r-xl:   16px;

  /* Vertical-rhythm scale — handbook + topic-surface spacing system.
     See `.scratch/ui-review/05-separation-system.md` (handbook) and
     `06-topic-surface-system.md` (topic surface) for the rulebooks.
     Tokens are multiples of 8 so they compose with the UI radius scale. */
  --space-block:           16px;  /* between paragraphs / atomic blocks */
  --space-subsection:      32px;  /* between callouts/key-facts/examples */
  --space-topic-section:   40px;  /* between major topic-surface sections */
  --space-section:         56px;  /* between handbook .ref-card-block sections */

  /* Platform typography scale — single source of truth. See
     `.scratch/ui-review/09-typography-system.md` for the rulebook.
     Applied via wrapper-scoped cascade rules in components.css.
     Module-local font-size declarations on body / title / label
     classes are overridden by those rules inside .learn-chapter-body
     and .topic-surface — pricer / dashboard / chrome surfaces keep
     their own sizes. */
  --text-body:    1.125rem;    /* 18px — body, paragraphs, list items (was 19px; reduced 2026-05-12 to sit closer to editorial-news body sizes) */
  --text-h1:      1.9rem;      /* chapter title (.learn-section-title) */
  --text-h2:      1.55rem;     /* section heading (.ref-card-title, .section-title) */
  --text-h3:      1.25rem;     /* sub-section / step title / callout title / [class*="-title"] / [class$="-subtitle"] */
  --text-h4:      1.0625rem;   /* small heading */
  --text-meta:    0.85rem;     /* eyebrow / caption / [class$="-label"] / [class$="-meta"] */
  --line-body:    1.7;
  --line-tight:   1.3;

  /* Reading measure — prose column cap inside .learn-chapter-body.
     46rem ≈ 736px ≈ ~72ch at 19px Newsreader. Per Bringhurst 60-75ch
     and Butterick 90ch absolute max. Full-width opt-out for tables,
     equations, and grid layouts in components.css. */
  --measure-prose: 46rem;

  /* Sticky-chrome heights — single source of truth. .app-header is
     64px (components.css:6+). --header-clearance adds breathing room
     for elements that float just below the header (formula panel,
     scroll-margin-top, etc.). */
  --header-height: 64px;
  --header-clearance: calc(var(--header-height) + 16px);

  /* Formula numeric — substituted-value ink in the formula panel.
     Distinct from --color-accent (chrome) and --text (regular ink).
     Light-mode override below. */
  --formula-numeric: #7ec8f0;

  /* Shadows */
  --shadow-sm:    0 1px 3px rgba(0,0,0,0.4);
  --shadow-md:    0 4px 12px rgba(0,0,0,0.5);
  --shadow-lg:    0 8px 24px rgba(0,0,0,0.6);
  --shadow-hover: 0 4px 16px rgba(0,0,0,0.25);

  /* Transitions */
  --transition: 160ms ease;

  /* Z-index layers */
  --z-dropdown:  100;
  --z-sticky:    200;
  --z-sidebar:   350;
  --z-overlay:   500;
  --z-modal:     600;
  --z-toast:     700;
  --z-max:       9999;

  /* Ecosystem tier colours */
  --tier-1: #a0aec0;
  --tier-2: #7c83f7;
  --tier-3: #22b8e0;
  --tier-4: #2dca8e;
  --tier-5: #f0a030;

  /* Backdrop blur */
  --blur-sm: 4px;
  --blur-md: 12px;
  --blur-lg: 20px;

  /* Focus ring */
  --focus-ring: 0 0 0 2px rgba(46, 109, 164, 0.2);

  /* Params sidebar width */
  --sidebar-width: 340px;
  /* Left gutter before the sidebar */
  --workspace-gutter: 28px;
}

/* ── Light mode ── */
[data-theme="light"] {
  /* Accent inks. --color-accent-text holds the value the accent has always
     had here, so light rendering is unchanged; it is dark that needed the
     lighter ink. --color-accent-light had no light override at all and was
     failing at 2.6-2.9:1 as link text on these surfaces. */
  --color-accent-text:  #2E6DA4;
  --color-accent-light: #1C6EB0;

  --bg:          #f0f2f7;
  --bg-surface:  #ffffff;
  --bg-header:   #ffffff;
  --bg-elevated: #f8f9fc;
  --bg-input:    #f4f6fa;
  --border:      #dde1ec;
  --border-subtle: #e8ebf4;
  --formula-numeric: #1a6faa;
  --text:        #1B3A5C;
  --text-table:  #2d4a6a;
  --text-secondary: #374a5e;
  --text-muted:  #5e7082;
  --shadow-sm:  0 1px 3px rgba(27,58,92,0.08);
  --shadow-md:  0 4px 12px rgba(27,58,92,0.12);
  --shadow-lg:  0 8px 24px rgba(27,58,92,0.15);
  --sidebar-accent:     #0d9488;
  --sidebar-accent-dim: rgba(13, 148, 136, 0.50);

  /* Ecosystem tier colours (light) */
  --tier-1: #5a6578;
  --tier-2: #4f52cc;
  --tier-3: #0c7da3;
  --tier-4: #0a8c60;
  --tier-5: #c47e18;

  /* Semantic – adjusted for light backgrounds. positive and warning are
     deepened to clear 4.5:1 as normal-size text (P&L figures in tables, and
     warning prose); at #059669 and #d97706 they sat at 3.4 and 2.8. */
  --positive:    #047152;
  --negative:    #dc2626;
  --warning:     #B45309;
  --neutral:     #64748b;
  --scrollbar-thumb: #c2c8d6;
  --info:        #2563eb;
  /* Extended palette (learn-content) – darkened for light bg contrast */
  --lv-purple:   #7c3aed;
  --lv-pink:     #db2777;
  --positive-bg: rgba(5, 150, 105, 0.08);
  --negative-bg: rgba(220, 38, 38, 0.08);
  --info-bg:     rgba(37, 99, 235, 0.08);
  --warning-bg:  rgba(217, 119, 6, 0.08);
  --shadow-hover: 0 4px 16px rgba(27, 58, 92, 0.1);
}
[data-theme="light"] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%234a5568'/%3E%3C/svg%3E") !important;
}

/* ── Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
button, input, textarea, select, option { font-family: inherit; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%238b8fa8'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 8px center !important;
  padding-right: 24px !important;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Suppress iOS/Android grey tap flash — we render our own :active states. */
  -webkit-tap-highlight-color: transparent;
}

/* Remove the 300ms tap delay on common interactive elements. Allows the
   browser to keep pinch-to-zoom on the page itself. */
a, button, [role="button"], input[type="button"], input[type="submit"], label {
  touch-action: manipulation;
}

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: hidden;
  /* Numeric glyphs render as tabular (fixed-advance) and lining figures
     so columns of numbers — chart hovers, data tables, metric cards,
     decimal-aligned tooltips — stop jittering as digits change.
     Non-numeric text is unaffected. Inter and JetBrains Mono both
     ship full tabular/lining numeral support. */
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: 'tnum' 1, 'lnum' 1, 'zero' 1;
}

/* Plotly hover labels and tick labels render as inline SVG text where
   `font-variant-numeric` doesn't always inherit. Force via OpenType
   feature settings so tabular figures stay tabular inside charts. */
.js-plotly-plot .plotly text,
.js-plotly-plot .hoverlayer text,
.js-plotly-plot .annotation-text {
  font-feature-settings: 'tnum' 1, 'lnum' 1, 'zero' 1;
}

/* ── Scrollbar ──
   Standard properties only. Do NOT add ::-webkit-scrollbar rules back, here or
   in any module stylesheet. Measured 2026-07-24 (Firefox 153, Edge 150):
     - Firefox 153+ reads ::-webkit-scrollbar, and any non-zero width there
       switches off its overlay scrollbar, forcing a permanent 19px bar. This
       is what made the whole platform sprout thick scrollbars overnight.
     - Chromium ignores ::-webkit-scrollbar completely once scrollbar-color is
       set, falling back to 17px, so those rules buy nothing anyway.
   scrollbar-color is safe and does NOT cost the overlay, so the thumb can be
   tinted freely. Result: 2px overlay in Firefox, 12px in Chromium. */
* { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) transparent; }

/* ── Focus ── */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
:focus:not(:focus-visible) {
  outline: none;
}

/* ── Typography ── */
h1 { font-size: 1.75rem; font-weight: 700; line-height: 1.25; letter-spacing: -0.02em; }
h2 { font-size: 1.35rem; font-weight: 600; line-height: 1.3;  }
h3 { font-size: 1.1rem;  font-weight: 600; }
/* h4 — mixed-case, weight-only differentiation. The previous rule
   (uppercase + 0.06em tracking + --text-secondary colour) is a T09
   AI-tell that survived globally; the `.eyebrow` class still owns
   that small-caps register where authors actually want it. */
h4 { font-size: 1rem; font-weight: 600; line-height: 1.35; color: var(--text); }
p  { font-size: 1rem; color: var(--text-secondary); }
a  { color: var(--color-accent-light); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Layout ── */
.app-wrapper {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* Workspace: sidebar + content, fills remaining height */
.workspace {
  display: flex;
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  padding-left: var(--workspace-gutter);
}

/* Module content divider line — single source of truth.
   Sits at the left edge of .workspace-content, so it serves as both the
   sidebar/content divider (when a sidebar is visible) and the page-edge
   line (when collapsed or absent). Edit here to change the line everywhere. */
.workspace-content {
  flex: 1;
  overflow-y: scroll;
  overflow-anchor: none;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--border);
}

.tab-content-area {
  padding: 16px 20px 48px;
  width: 100%;
  max-width: 1800px;
}
.tab-content-area:has(.ref-sub-tabs-wrap) {
  max-width: 1320px;
  margin: 0 auto;
}

/* ── Utility ── */
/* .sr-only is kept as a deliberate accessibility affordance (screen-reader-only
   text) even though no markup emits it today. */
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
.flex    { display: flex; }
.text-sm { font-size: 0.875rem; }
.text-muted { color: var(--text-muted); }
.text-secondary { color: var(--text-secondary); }
.font-mono { font-family: var(--font-mono); }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hidden { display: none !important; }

/* ── Toast Notifications ── */
.em-toast-container {
  position: fixed;
  top: 72px;
  right: 16px;
  z-index: calc(var(--z-max) + 1);
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}
.em-toast {
  pointer-events: auto;
  padding: 10px 16px;
  border-radius: 8px;
  font-size: 0.88rem;
  font-family: var(--font);
  max-width: 420px;
  cursor: pointer;
  animation: toast-in 0.3s ease;
  box-shadow: var(--shadow-md);
}
/* Toast with an action button (e.g. Undo) lays out as a row. */
.em-toast--action {
  display: flex;
  align-items: center;
  gap: 16px;
  justify-content: space-between;
}
.em-toast-action {
  flex-shrink: 0;
  background: none;
  border: 1px solid currentColor;
  color: inherit;
  font: inherit;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 6px;
  cursor: pointer;
  opacity: 0.85;
  transition: opacity 0.15s ease;
}
.em-toast-action:hover { opacity: 1; }
.em-toast-error {
  background: rgba(239, 68, 68, 0.15);
  border: 1px solid rgba(239, 68, 68, 0.4);
  color: #f87171;
}
.em-toast-success {
  background: rgba(34, 197, 94, 0.15);
  border: 1px solid rgba(34, 197, 94, 0.4);
  color: #34d399;
}
.em-toast-info {
  background: rgba(59, 130, 246, 0.15);
  border: 1px solid rgba(59, 130, 246, 0.4);
  color: #60a5fa;
}
.em-toast-exit {
  opacity: 0;
  transform: translateX(30px);
  transition: opacity 0.3s, transform 0.3s;
}
[data-theme="light"] .em-toast-error {
  background: rgba(239, 68, 68, 0.08);
  color: #dc2626;
}
[data-theme="light"] .em-toast-success {
  background: rgba(34, 197, 94, 0.08);
  color: #059669;
}
[data-theme="light"] .em-toast-info {
  background: rgba(59, 130, 246, 0.08);
  color: #2563eb;
}
@keyframes toast-in {
  from { opacity: 0; transform: translateX(30px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.15; }
}

/* ── Mobile Responsive ─────────────────────────────────────────────────── */

@media (max-width: 768px) {
  .workspace { padding-left: 0; }
  .tab-content-area img,
  .tab-content-area svg:not(.js-plotly-plot svg) { max-width: 100%; height: auto; }
  pre, code, .learn-formula-box, .learn-formula-inline,
  .learn-example-body { overflow-x: auto; }
}

@media (max-width: 480px) {
  h1 { font-size: 1.4rem; }
  h2 { font-size: 1.15rem; }
  h3 { font-size: 1rem; }
  .tab-content-area { padding: 12px 12px 24px; }
  .em-toast { max-width: 90vw; }
}

/* ── Print stylesheet ────────────────────────────────────────────────────────
   Phase 1: handbook chapters + glossary print/export. The on-screen Newsreader
   serif body carries straight into print — this block strips the chrome, forces
   light mode, sizes the type for paper, controls page breaks, and styles the
   JS-injected cover / disclaimer / running-footer artifacts (see
   js/shared/print-export.js, wired from reference-tab.js). Other surfaces
   (pricers, dashboards) get the generic chrome-strip + light mode here too;
   they just don't get the cover/disclaimer (no `.ref-sub-panel.active` →
   print-export.js no-ops). See .scratch/ui-review/48-print-spec.md. */

@page {
  margin: 16mm 14mm 20mm;   /* extra at the bottom = clearance for the fixed running footer */
}

/* The branded artifacts are display:none on screen; only print shows them. */
.em-print-cover,
.em-print-disclaimer,
.em-print-footer { display: none; }

@media print {
  html { background: #fff; color-scheme: light; }
  *, *::before, *::after { box-shadow: none !important; text-shadow: none !important; }

  /* Force readable colours — @media print does NOT honour prefers-color-scheme,
     and [data-theme="dark"] sets the dark token values, so re-declare to light. */
  :root,
  [data-theme="dark"],
  [data-theme="light"] {
    --bg: #fff;
    --bg-surface: #fff;
    --bg-header: #fff;
    --bg-elevated: #fff;
    --bg-input: #f5f5f5;
    --text: #000;
    --text-secondary: #333;
    --text-muted: #666;
    --border: #ccc;
    --border-subtle: #ddd;
    --color-accent: #1B3A5C;
    --color-accent-text: #1B3A5C;
    --positive: #1a6b34;
    --negative: #a3001f;
    --warning: #8a5800;
    --info: #1d5fa0;
  }

  /* ── Hide: app chrome, overlays, banners ───────────────────────────────── */
  .app-header,                       /* topbar incl. the Search… ⌘K box */
  .params-sidebar,
  .options-sidebar,
  .sidebar-toggle-btn,
  .sidebar-mobile-toggle,
  .sidebar-backdrop,
  .module-switcher-overlay,
  .module-transition-overlay,
  .cmd-palette-overlay,
  .em-toast-container,
  #boot-overlay,
  #em-session-bar,
  #contact-modal,
  .settings-dropdown,
  .iro-dialog-overlay,
  .pref-overlay,
  .guided-flow-card,
  .wt-overlay,
  .wt-prompt,
  .explain-popover,
  /* ── Hide: handbook / glossary / reference chrome ───────────────────────── */
  .ref-sub-tabs-wrap,                /* the sub-tab bar — and the Print control nested in it */
  .ref-print,
  .ref-print-menu,
  .learn-nav,                        /* chapter-TOC sidebar */
  .learn-nav-toggle,                 /* mobile "Chapters" disclosure button */
  .learn-nav-next,                   /* "next chapter →" pager */
  .glossary-rail,                    /* glossary category nav + A–Z bar */
  .glossary-controls,
  .glossary-search-row,
  .glossary-az-anchor,
  .glossary-card-meta,
  .pricer-link,
  .learn-pricer-link,
  /* ── Hide: interactive affordances inside content ───────────────────────── */
  .formula-btn,
  .explain-btn,
  .test-yourself-toggle,
  .challenge-btn,
  .remove-btn,
  .chart-fullscreen-btn,
  .related-topics,
  .sidebar-disclaimer {
    display: none !important;
  }

  /* ── Full-width content column — no grid, no scroll containers ──────────── */
  .app-wrapper,
  .workspace,
  #module-mount { display: block !important; }
  .workspace { padding-left: 0 !important; }
  .workspace-content,
  .tab-content-area {
    overflow: visible !important;
    margin: 0 !important;
    padding: 0 !important;
    max-width: none !important;
    width: auto !important;
  }
  .tab-panel { display: none !important; }
  .tab-panel.active { display: block !important; overflow: visible !important; }
  .ref-sub-panel { display: none !important; }
  .ref-sub-panel.active { display: block !important; }
  .learn-layout { display: block !important; }       /* was 200px 1fr — kill the dead TOC column */
  .learn-content { overflow: visible !important; padding: 0 !important; }
  .glossary-layout,
  .glossary-wrap { display: block !important; }

  /* ── "Print this chapter" mode (set by print-export.js before window.print) ── */
  body.em-print-chapter .learn-chapter:not(.em-print-target) { display: none !important; }
  body.em-print-chapter .em-print-target { break-before: avoid; page-break-before: avoid; }

  /* ── Typography for paper — inherit the Newsreader serif, shrink for print ── */
  .learn-chapter-body,
  .glossary-card-term,
  .glossary-card-def { font-size: 11pt !important; line-height: 1.55 !important; }
  .learn-section-title,
  .learn-chapter-body h2 { font-size: 16pt !important; line-height: 1.25 !important; }
  .learn-chapter-body h3 { font-size: 13pt !important; }
  .learn-chapter-body h4 { font-size: 11.5pt !important; }
  .learn-key-sym,
  .learn-key-def { font-size: 11pt !important; line-height: 1.5 !important; }
  .glossary-section-label { font-size: 12pt !important; }
  .learn-chapter-body { max-width: none !important; }   /* @page margin owns the measure now */
  .learn-chapter-body p,
  .learn-key-def { orphans: 3; widows: 3; }

  /* ── Page breaks ───────────────────────────────────────────────────────── */
  .learn-chapter { break-before: page; page-break-before: always; margin-bottom: 0 !important; }
  .learn-chapter:first-child { break-before: avoid; page-break-before: avoid; }   /* ch.1 follows the cover */
  .learn-chapter-body h2,
  .learn-chapter-body h3,
  .learn-section-title { break-after: avoid; page-break-after: avoid; }
  .learn-chapter-body figure,
  .learn-chapter-body .figure,
  .learn-chapter-body .data-table-wrap,
  .learn-chapter-body .learn-callout,
  .learn-chapter-body .callout,
  .learn-chapter-body .learn-example,
  .learn-chapter-body .learn-key-facts,
  .learn-chapter-body .learn-formula-box,
  .glossary-card { break-inside: avoid; page-break-inside: avoid; }
  .glossary-section-label { break-after: avoid; page-break-after: avoid; }

  /* ── Charts — Plotly bakes theme colours into SVG attributes (which DO print),
     so a dark-mode chart prints as a dark box. Drop the plot, keep the figure
     caption, leave a one-line trace. Crisp chart images in print = Phase 2. ── */
  .js-plotly-plot { display: none !important; }
  .chart-wrap { break-inside: avoid; page-break-inside: avoid; }
  .figure-caption { display: block !important; }
  .chart-wrap::after {
    content: "[chart — available in the online handbook]";
    display: block;
    margin-top: 4px;
    color: #666;
    font-style: italic;
    font-size: 9pt;
  }

  /* ── Search highlight — no highlighter pen / accent ring in the PDF ─────── */
  mark.search-hl,
  .glossary-match {
    background: transparent !important;
    box-shadow: none !important;
    padding: 0 !important;
    color: inherit !important;
  }

  /* ── Tables — borders + a grey header band read clearer on paper ────────── */
  .data-table-wrap { overflow-x: visible !important; border: none !important; }
  .data-table { border-collapse: collapse; }
  .learn-chapter-body .data-table,
  .learn-chapter-body .data-table th,
  .learn-chapter-body .data-table td { font-size: 9.5pt !important; }
  .data-table th,
  .data-table td {
    border: 1px solid #ccc !important;
    padding: 4px 8px !important;
    background: #fff !important;
    color: #000 !important;
  }
  .data-table th {
    background: #f0f0f0 !important;
    font-weight: 600 !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* ── Cards / callouts / formulas / badges ──────────────────────────────── */
  .card {
    border: 1px solid #ddd !important;
    background: #fff !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .card-value { color: #000 !important; }
  .callout,
  .learn-callout {
    border: 1px solid #ddd !important;
    background: #fafafa !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .learn-formula-box,
  .learn-formula-inline,
  .katex {
    color: #000 !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .badge {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    border: 1px solid currentColor;
  }
  .metrics-row { display: flex !important; flex-wrap: wrap !important; gap: 8px !important; }

  /* ── Links — in-document xrefs stay as styled-but-dead text; external links
     get their URL footnoted (the one place that earns its keep). ──────────── */
  .learn-chapter-body a[href^="#"],
  .xref-link,
  .glossary-card-term a { color: var(--color-accent-text) !important; text-decoration: none !important; }
  .learn-chapter-body a[href^="http"]::after,
  .glossary-card-def a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 8pt;
    color: #666;
    word-break: break-all;
  }

  /* ── Remove hover effects ──────────────────────────────────────────────── */
  *:hover { background: inherit !important; color: inherit !important; }

  /* ── The JS-injected branded artifacts ─────────────────────────────────── */
  .em-print-cover {
    display: block;
    margin: 0 0 12mm;
    padding-bottom: 6mm;
    border-bottom: 1px solid #ccc;
    break-after: avoid;
    page-break-after: avoid;
  }
  .em-print-cover .em-print-wordmark {
    display: block;
    font-family: 'Newsreader', 'Inter', system-ui, serif;
    font-size: 20pt;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: #1B3A5C;
  }
  .em-print-cover .em-print-doctitle {
    display: block;
    font-family: 'Newsreader', 'Inter', system-ui, serif;
    font-size: 14pt;
    color: #000;
    margin-top: 2.5mm;
  }
  .em-print-cover .em-print-meta {
    display: block;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 8.5pt;
    color: #666;
    margin-top: 2mm;
  }
  .em-print-disclaimer {
    display: block;
    margin-top: 12mm;
    padding-top: 5mm;
    border-top: 1px solid #ccc;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 8.5pt;
    line-height: 1.5;
    color: #555;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .em-print-disclaimer .em-print-copyright { display: block; margin-top: 2.5mm; }
  .em-print-footer {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 6mm;
    text-align: center;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 7.5pt;
    color: #888;
  }
}

/* ── Reduced motion ──
   Users who turn on "Reduce motion" in iOS / Android / OS settings
   expect us to strip non-essential animation. We collapse every
   animation and transition to a near-instant duration so structural
   states still update (sidebar opens, modal appears) but without the
   long ease-in-out movement that can trigger vestibular issues. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── View Transitions ──
   Tab switches inside a module use document.startViewTransition() in
   js/main.js for a smooth cross-fade between the outgoing and incoming
   panel. The browser default duration is ~250ms which feels slightly
   sluggish for tab navigation; 200ms matches the CSS-keyframe fallback
   used on browsers without view-transition support. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 200ms;
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 0.01ms !important;
  }
}
