/* ===========================================================================
   base.css: the shell every write-up under /blog/ shares (tokens, layout,
   sidebar nav, prose). One copy, loaded first; each article's own CSS comes
   next, then /static/blog/css/system.css last (the shared visual system).
   Was copied into each article as css/theme.css + css/page.css until Nov 2026.
   =========================================================================== */

/* ── theme ── */
/* ===========================================================================
   theme.css — monochrome token system for the attribution reference.
   Dark by default. One surface colour for header, sidebar and main (the shell
   reads as a single dark plane, like the oklch.fyi reference). No hue in the
   chrome: emphasis is carried by lightness and a hairline, never colour.

   A sanctioned accent palette (the Notion-style table, converted to OKLCH) is
   defined at the bottom for graphics/data-viz only — the prose and controls
   stay monochrome.
   =========================================================================== */

@font-face {
  font-family: "Geist Mono";
  src: url("../fonts/GeistMono-Variable.woff2?v=1") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Uncut Sans";
  src: url("../fonts/UncutSans-Variable.woff2?v=1") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Neutral ramp, 1 = darkest → 12 = lightest (kept for gradients/fills). */
  --color-1: oklch(0.145 0 0);
  --color-2: oklch(0.178 0 0);
  --color-3: oklch(0.213 0 0);
  --color-4: oklch(0.248 0 0);
  --color-5: oklch(0.285 0 0);
  --color-6: oklch(0.323 0 0);
  --color-7: oklch(0.40 0 0);
  --color-8: oklch(0.48 0 0);
  --color-9: oklch(0.58 0 0);
  --color-10: oklch(0.68 0 0);
  --color-11: oklch(0.80 0 0);
  --color-12: oklch(0.94 0 0);

  /* Non-colour tokens (radii kept tight—a couple px less than before) */
  --radius-sm: 3px;
  --radius-md: 6px;
  --radius-lg: 10px;
  --radius-pill: 999px;
  --transition: 160ms cubic-bezier(0.4, 0, 0.2, 1);
  --font: "Uncut Sans", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-sans: var(--font);
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  --text-xs: 12px;
  --text-sm: 14px;
  --text-base: 15px;
  --font-normal: 400;
  --font-medium: 500;
  --font-semibold: 600;

  /* ---- DARK (default) ---- */
  --bg: oklch(0.162 0 0);            /* single shell surface (deepened) */
  --bg-sidebar: var(--bg);          /* header = sidebar = main */
  --bg-elevated: oklch(0.196 0 0);  /* cards / modules lift by one step */
  --bg-hover: oklch(1 0 0 / 0.045);
  --bg-active: oklch(1 0 0 / 0.08);

  --border: oklch(1 0 0 / 0.10);
  --border-light: oklch(1 0 0 / 0.055);

  --text: oklch(0.95 0 0);          /* headings / high emphasis */
  --text-secondary: oklch(0.84 0 0);/* body copy */
  --text-tertiary: oklch(0.60 0 0); /* meta / muted */
  --text-disabled: oklch(0.42 0 0);

  /* "Accent" is monochrome: near-white for active text, a white wash for the
     active surface, and a neutral hairline. No colour. */
  --color-accent: oklch(0.96 0 0);
  --color-accent-hover: oklch(0.88 0 0);
  --accent: var(--color-accent);
  --accent-hover: var(--color-accent-hover);
  --accent-surface: oklch(1 0 0 / 0.07);
  --accent-surface-border: oklch(1 0 0 / 0.10);
  --accent-selected: var(--accent-surface);
  --on-accent: oklch(0.16 0 0);     /* dark text on a light (white) fill */

  /* Kept for potential destructive UI only — not used in data-viz. */
  --danger: oklch(0.72 0.17 26);
  --danger-bg: oklch(1 0 0 / 0.06);

  --tag-bg: oklch(1 0 0 / 0.06);
  --tag-text: oklch(0.72 0 0);

  /* Chip / segmented-pill fills — theme-aware so selected states read in both
     light and dark. The neutral ramp above is fixed (dark), so these override. */
  --pill-active-bg: var(--color-5);
  /* grade chips — portfolio-pill treatment: a faint hue-tinted translucent
     fill + a white hairline edge + lifted, saturated ink (like the amber
     "Auto" pill). Modelled = amber, measured = teal-green, assumed = red. */
  --grade-border: oklch(1 0 0 / 0.10);
  --grade-measured-bg: oklch(0.72 0.12 172 / 0.13); --grade-measured-text: oklch(0.82 0.13 172);
  --grade-modelled-bg: oklch(0.80 0.15 92 / 0.15);  --grade-modelled-text: oklch(0.87 0.16 92);
  --grade-assumed-bg:  oklch(0.72 0.16 25 / 0.14);  --grade-assumed-text:  oklch(0.80 0.16 25);

  /* portfolio accent blue — the "coming soon" pill */
  --accent-blue-text: oklch(0.80 0.161 259.792);
  --btn-blue: oklch(0.718 0.146 259.792 / 0.12);
  --btn-blue-border: oklch(1 0 0 / 0.10);

  /* Explorer control accents — one muted hue per control (green/blue/violet),
     same lightness+chroma family so they read as one calm set. Text is the
     saturated ink; -bg is a faint tint for the active pill (grade-chip style). */
  --ctrl-rule:   oklch(0.82 0.13 172);     --ctrl-rule-bg:   oklch(0.72 0.12 172 / 0.15);
  --ctrl-cost:   oklch(0.80 0.155 259.8);  --ctrl-cost-bg:   oklch(0.718 0.146 259.8 / 0.17);
  --ctrl-timing: oklch(0.80 0.14 305);     --ctrl-timing-bg: oklch(0.72 0.13 305 / 0.16);

  /* Self-report reconciliation bar — categorical buckets (data-viz palette):
     agree = green, conflict = red, untracked = amber, blank = blue. */
  --bucket-agree:     oklch(0.80 0.14 168);
  --bucket-conflict:  oklch(0.72 0.17 26);
  --bucket-untracked: oklch(0.84 0.15 88);
  --bucket-blank:     oklch(0.78 0.145 255);

  --switch-knob: oklch(0.95 0 0);
  --focus-ring: oklch(1 0 0 / 0.22);
  --focus-ring-neutral: oklch(1 0 0 / 0.18);
  --img-outline: oklch(1 0 0 / 0.10);

  --shadow: 0 0 0 1px oklch(1 0 0 / 0.06);
  --shadow-lg: 0 12px 40px oklch(0 0 0 / 0.5), 0 0 0 1px oklch(1 0 0 / 0.06);

  color-scheme: dark;
}

/* ---- LIGHT ---- */
:root[data-theme="light"] {
  --bg: oklch(0.988 0 0);
  --bg-sidebar: var(--bg);
  --bg-elevated: oklch(1 0 0);
  --bg-hover: oklch(0 0 0 / 0.035);
  --bg-active: oklch(0 0 0 / 0.06);

  --border: oklch(0 0 0 / 0.10);
  --border-light: oklch(0 0 0 / 0.06);

  --text: oklch(0.24 0 0);          /* one ramp step lighter than pure charcoal—softer headings */
  --text-secondary: oklch(0.34 0 0);
  --text-tertiary: oklch(0.55 0 0);
  --text-disabled: oklch(0.72 0 0);

  --color-accent: oklch(0.24 0 0);
  --color-accent-hover: oklch(0.32 0 0);
  --accent-surface: oklch(0 0 0 / 0.06);
  --accent-surface-border: oklch(0 0 0 / 0.10);
  --on-accent: oklch(0.99 0 0);

  --danger: oklch(0.55 0.20 27);
  --danger-bg: oklch(0 0 0 / 0.05);

  --tag-bg: oklch(0 0 0 / 0.05);
  --tag-text: oklch(0.40 0 0);

  --pill-active-bg: oklch(0.94 0 0);
  --grade-border: oklch(0 0 0 / 0.10);
  --grade-measured-bg: oklch(0.62 0.12 172 / 0.15); --grade-measured-text: oklch(0.42 0.11 172);
  --grade-modelled-bg: oklch(0.78 0.15 92 / 0.24);  --grade-modelled-text: oklch(0.48 0.12 85);
  --grade-assumed-bg:  oklch(0.62 0.18 25 / 0.15);  --grade-assumed-text:  oklch(0.50 0.19 25);

  --accent-blue-text: oklch(0.50 0.16 259.792);
  --btn-blue: oklch(0.718 0.146 259.792 / 0.14);
  --btn-blue-border: oklch(0 0 0 / 0.10);

  --ctrl-rule:   oklch(0.45 0.12 172);     --ctrl-rule-bg:   oklch(0.62 0.12 172 / 0.15);
  --ctrl-cost:   oklch(0.50 0.16 259.8);   --ctrl-cost-bg:   oklch(0.62 0.15 259.8 / 0.16);
  --ctrl-timing: oklch(0.47 0.16 305);     --ctrl-timing-bg: oklch(0.58 0.16 305 / 0.15);

  --bucket-agree:     oklch(0.55 0.14 168);
  --bucket-conflict:  oklch(0.55 0.20 27);
  --bucket-untracked: oklch(0.66 0.14 82);
  --bucket-blank:     oklch(0.54 0.16 255);

  --focus-ring: oklch(0 0 0 / 0.20);
  --focus-ring-neutral: oklch(0 0 0 / 0.14);
  --img-outline: oklch(0 0 0 / 0.10);

  --shadow: 0 0 0 1px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.05);
  --shadow-lg: 0 12px 32px oklch(0 0 0 / 0.12), 0 0 0 1px oklch(0 0 0 / 0.06);

  color-scheme: light;
}

/* ---------------------------------------------------------------------------
   Sanctioned accent palette (Notion dark table → OKLCH). For graphics and
   data-viz only. `-text` is the vivid ink; `-bg` is the muted fill.
   --------------------------------------------------------------------------- */
:root {
  --palette-gray:   oklch(0.694 0.004 220);  --palette-gray-bg:   oklch(0.408 0.009 229);
  --palette-brown:  oklch(0.581 0.047 44);   --palette-brown-bg:  oklch(0.375 0.004 17);
  --palette-orange: oklch(0.792 0.152 63);   --palette-orange-bg: oklch(0.420 0.032 69);
  --palette-yellow: oklch(0.899 0.162 95);   --palette-yellow-bg: oklch(0.449 0.041 103);
  --palette-green:  oklch(0.680 0.093 180);  --palette-green-bg:  oklch(0.397 0.028 193);
  --palette-blue:   oklch(0.664 0.101 238);  --palette-blue-bg:   oklch(0.394 0.030 234);
  --palette-purple: oklch(0.626 0.159 302);  --palette-purple-bg: oklch(0.383 0.041 294);
  --palette-pink:   oklch(0.657 0.191 350);  --palette-pink-bg:   oklch(0.385 0.043 338);
  --palette-red:    oklch(0.722 0.173 26);   --palette-red-bg:    oklch(0.402 0.034 19);
}

html.theme-ready,
html.theme-ready body {
  transition: background-color 0.2s ease, color 0.2s ease;
}

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


/* ── shell ── */
/* ===========================================================================
   page.css—the shared shell from the CAC write-up (cac.aidanleather.com).
   One dark plane. A hairline separates the sidebar from the body. Box spacing
   is on an 8px grid (4s and 8s). Radii come from one tight scale.
   =========================================================================== */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px; --s5: 24px;
  --s6: 32px; --s7: 40px; --s8: 48px; --s9: 56px; --s10: 64px;

  --measure: 44rem;
  --gutter: clamp(16px, 4vw, 56px);
  --sidebar-w: 232px;
  --topbar-h: 56px;
  --bar-fill: var(--color-10);
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* pretty by default (kills last-line orphans on paragraphs, list items,
     captions, table cells); headings override with balance below. Inherited,
     so it reaches child spans without per-element rules. */
  text-wrap: pretty;
}

/* ── Page-load fade-in ───────────────────────────────────────
   A gentle, staggered opacity fade so the page settles in on load
   instead of snapping/juddering as fonts and JS modules mount.
   Opacity only—no transforms—so there's no layout shift and no new
   stacking context on the tall main column.

   Only runs on the FIRST view of a page in a session: an inline head
   script adds `.aw-intro` to <html> once, so reloads and back/forward
   (assets already cached) render instantly. Off under reduced-motion.
   `both` holds each region invisible until its delay (no flash). */
@media (prefers-reduced-motion: no-preference) {
  .aw-intro .topbar,
  .aw-intro .sidebar,
  .aw-intro .main {
    animation: aw-fade-in 300ms cubic-bezier(0.4, 0, 0.2, 1) both;
  }
  .aw-intro .topbar  { animation-delay: 0ms; }
  .aw-intro .sidebar { animation-delay: 40ms; }
  .aw-intro .main    { animation-delay: 80ms; }
}

@keyframes aw-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.skip-link {
  position: fixed; left: var(--s3); top: -48px; z-index: 200;
  background: var(--bg-elevated); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: var(--s2) var(--s4); transition: top var(--transition);
}
.skip-link:focus { top: var(--s3); }

/* ── Header ─────────────────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: 50;
  height: var(--topbar-h);
  display: flex; align-items: center;
  padding: 0 var(--gutter) 0 var(--s4);
  background: var(--bg);
  border-bottom: 1px solid var(--border-light);
}
.logo {
  display: inline-flex; width: 28px; height: 28px; padding: 0; border: none;
  border-radius: var(--radius-pill); cursor: pointer;
  background:
    radial-gradient(circle at 32% 28%, oklch(0.32 0 0), transparent 55%),
    radial-gradient(circle at 70% 74%, oklch(0.08 0 0), transparent 60%),
    oklch(0.17 0 0);
  transition: filter var(--transition);
}
.logo:hover { filter: brightness(1.25); }
.logo:focus-visible { outline: 1.5px solid var(--text-tertiary); outline-offset: 2px; }

/* Light-mode orb: same top-left lit sphere, inverted to a pale neutral so it
   sits on the near-white plane instead of punching a black hole in it. The
   inset hairline keeps its edge legible against the 0.988 background. */
:root[data-theme="light"] .logo {
  background:
    radial-gradient(circle at 32% 28%, oklch(1 0 0), transparent 55%),
    radial-gradient(circle at 70% 74%, oklch(0.70 0 0), transparent 60%),
    oklch(0.86 0 0);
  box-shadow: inset 0 0 0 1px oklch(0 0 0 / 0.08);
}
:root[data-theme="light"] .logo:hover { filter: brightness(0.97); }

/* Theme toggle: transparent, sits at the sidebar foot. */
.theme-toggle {
  display: inline-flex; gap: var(--s1); padding: var(--s1);
  border-radius: var(--radius-pill); background: transparent;
}
.theme-toggle button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 28px; border: none; background: none;
  color: var(--text-tertiary); cursor: pointer; border-radius: var(--radius-md);
  transition: color var(--transition), background var(--transition);
}
.theme-toggle button:hover { color: var(--text); background: var(--bg-hover); }
.theme-toggle button.is-active { color: var(--text); background: var(--bg-active); }
.theme-toggle button:focus-visible { outline: 1.5px solid var(--text-tertiary); outline-offset: 2px; }

/* ── Layout ─────────────────────────────────────────────────── */
.layout {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  align-items: start;
}

/* ── Sidebar (app nav) with the dividing line (no ball) ─────── */
.sidebar {
  position: sticky; top: var(--topbar-h);
  height: calc(100vh - var(--topbar-h));
  background: var(--bg);
  padding: var(--s4) var(--s3);
  overflow-y: auto;
  border-right: 1px solid var(--border-light);
  display: flex; flex-direction: column;
}
.nav { display: flex; flex-direction: column; gap: 2px; }
.nav-item {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); border-radius: var(--radius-md);
  font-size: 14px; font-weight: 500; color: var(--text-tertiary);
  text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: color var(--transition), background var(--transition);
}
.nav-item:hover { color: var(--text); background: var(--bg-hover); }
.nav-item.is-active { color: var(--text); background: var(--bg-active); }
.nav-item:focus-visible { outline: 1.5px solid var(--text-tertiary); outline-offset: -2px; }
.nav-item--soon { color: var(--text-disabled); cursor: default; }
.nav-item--soon:hover { color: var(--text-disabled); background: none; }
.soon-chip {
  margin-left: auto; flex-shrink: 0;
  font-size: 10px; font-weight: 600; letter-spacing: 0;
  color: var(--accent-blue-text); background: var(--btn-blue);
  border: 1px solid var(--btn-blue-border);
  padding: 2px var(--s2); border-radius: var(--radius-sm); white-space: nowrap;
}
/* "New" — the skill is live. Green (measured) reads as available, vs the blue
   "coming soon" it replaces. */
.new-chip {
  margin-left: auto; flex-shrink: 0;
  font-size: 10px; font-weight: 600; letter-spacing: 0;
  color: var(--grade-measured-text); background: var(--grade-measured-bg);
  border: 1px solid var(--grade-border);
  padding: 2px var(--s2); border-radius: var(--radius-sm); white-space: nowrap;
}
.nav-ico {
  width: 16px; height: 16px; flex-shrink: 0;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.nav-sep { height: 1px; background: var(--border-light); margin: var(--s2) var(--s3); }
.sidebar-foot { margin-top: auto; padding-top: var(--s4); }

/* ── Main ───────────────────────────────────────────────────── */
.main { min-width: 0; padding: 0 var(--gutter); }
.column { max-width: var(--measure); margin: 0 auto; padding: var(--s4) 0 var(--s10); }
/* Sections flow on whitespace + clear headings, oklch.fyi-style—no rule between
   every one. A hairline is opt-in (.section--rule), reserved for the shifts
   between movements (self-report, brand, conclusion, the dataset appendix), so a
   rule always signals a real change of subject rather than mere spacing.
   Below the rule gets +8px over above it: the line-height under the previous
   paragraph inflates the top gap, so unequal padding reads optically even. */
.section { padding: var(--s5) 0; }
/* One rule on the whole page: under the hero, closing the title block off from
   the article. Everything below is structured by headings alone—h2 for the major
   beats, h3 for the sub-levers—so the body reads on hierarchy, not on rules. */
.intro {
  border-top: 1px solid var(--border-light);
  padding: var(--s6) 0 var(--s5);
}
/* Opt-in divider, reused only for the dataset appendix at the very bottom—it
   sits below the conclusion + sign-off, so a rule marks it as reference matter. */
.section--rule {
  border-top: 1px solid var(--border-light);
  padding-top: var(--s6);
}
/* modules sit flush to the section padding at a section's edges (no doubled gap) */
.section > .module:first-child { margin-top: 0; }
.section > .module:last-child { margin-bottom: 0; }

/* ── Prose ──────────────────────────────────────────────────── */
p { color: var(--text-secondary); line-height: 1.5; }
.section { scroll-margin-top: calc(var(--topbar-h) + var(--s4)); }
.section > p { margin-bottom: var(--s3); font-size: 15px; }
.section > p:last-child { margin-bottom: 0; }
strong { color: var(--text); font-weight: 600; }
a { color: var(--text); text-decoration: underline; text-underline-offset: 2px; text-decoration-color: var(--text-tertiary); }
a:hover { text-decoration-color: var(--text); }

h2 { font-size: 17px; line-height: 1.35; letter-spacing: -0.01em; font-weight: 700; color: var(--text); margin-bottom: var(--s3); text-wrap: balance; }
/* h3: a subordinate lever inside an h2 movement. Same weight, smaller, quieter
   colour, with clear air above it so the step down from h2 reads. */
h3 { font-size: 15px; line-height: 1.4; font-weight: 600; color: var(--text-secondary); margin: var(--s6) 0 var(--s2); text-wrap: balance; }

/* intro (first-person) — carries a top divider like the sections */
.intro p { font-size: 16px; line-height: 1.55; color: var(--text-secondary); margin-bottom: var(--s4); }
.intro p:last-child { margin-bottom: 0; }
.intro strong { color: var(--text); font-variant-numeric: tabular-nums; }

.deflist { margin: 0 0 var(--s3); }
.deflist dt { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: var(--s1); }
.deflist dd { font-size: 15px; line-height: 1.5; color: var(--text-secondary); margin-bottom: var(--s5); }
.deflist dd:last-child { margin-bottom: 0; }

.rulelist { list-style: none; margin: 0 0 var(--s3); display: flex; flex-direction: column; gap: var(--s2); }
.rulelist li { font-size: 15px; line-height: 1.45; color: var(--text-secondary); padding-left: var(--s4); position: relative; }
.rulelist li::before { content: ""; position: absolute; left: 0; top: 0.6em; width: 5px; height: 5px; border-radius: 50%; background: var(--text-tertiary); }

.grade-key { list-style: none; margin: 0 0 var(--s3); display: flex; flex-direction: column; gap: var(--s2); }
.grade-key li { font-size: 15px; line-height: 1.5; color: var(--text-secondary); }

/* inline worked figures in prose (filled by app.js) */
[data-report] { color: var(--text); font-weight: var(--font-semibold); font-variant-numeric: tabular-nums; }

/* rules table: a subtle grey card, no outer top/bottom rules—just faint row
   hairlines inside for legibility */
.rules-table {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  margin: var(--s5) 0;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.rules-table th { text-align: left; font-size: 12px; font-weight: 600; color: var(--text-tertiary); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border-light); }
.rules-table td { font-size: 14px; line-height: 1.45; padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border-light); vertical-align: top; }
.rules-table tr:last-child td { border-bottom: none; }
.rules-table td:first-child { color: var(--text); font-weight: 600; white-space: nowrap; }
.rules-table td:last-child { color: var(--text-secondary); }

/* ── Hero (centred, roomy) ──────────────────────────────────── */
.hero { text-align: center; padding: var(--s10) 0 var(--s8); }
.badge {
  display: inline-flex; align-items: center;
  font-size: 13px; font-weight: 500; color: var(--text-secondary);
  padding: var(--s1) var(--s3); border: 1px solid var(--border);
  border-radius: var(--radius-pill); margin-bottom: var(--s5);
}
.hero h1 {
  font-size: clamp(28px, 4vw, 40px);
  line-height: 1.05; letter-spacing: -0.02em; font-weight: 600;
  color: var(--text); margin-bottom: var(--s5); text-wrap: balance;
}
.lede { font-size: 18px; line-height: 1.4; color: var(--text-secondary); max-width: 34rem; margin: 0 auto; text-wrap: balance; }
.byline-avatar {
  display: block; width: 36px; height: 36px; border-radius: 50%; margin: 0 auto 40px;
  background: #fff url("../img/aidan-photo.jpg?v=2") no-repeat center / cover;
  border: 1px solid var(--border);
}

/* ── Module shell ───────────────────────────────────────────── */
.module {
  margin: var(--s7) 0;
  border-radius: var(--radius-lg);
  background: var(--bg-elevated);
  padding: var(--s5);
}
#explorer { scroll-margin-top: calc(var(--topbar-h) + var(--s4)); }
.module-fallback { font-size: 14px; color: var(--text-tertiary); }
.module-head { margin-bottom: var(--s4); }
.module-title { font-size: 15px; font-weight: 700; color: var(--text); }
.module-sub { font-size: 13px; color: var(--text-tertiary); margin-top: var(--s1); line-height: 1.45; }


.colophon { font-size: 13px; color: var(--text-tertiary); margin-top: var(--s5); }
.signoff { margin-top: var(--s5); font-size: 15px; line-height: 1.55; color: var(--text-secondary); }
.signoff a { font-weight: 600; }

/* ── Dataset viewer (multi-sheet spreadsheet) ───────────────── */
.sheet-tabs { display: flex; flex-wrap: wrap; gap: 2px; padding: 2px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-md); margin-bottom: var(--s3); width: fit-content; }
.sheet-tab { border: none; background: none; cursor: pointer; font: 500 12.5px var(--font); color: var(--text-tertiary); padding: 7px 12px; border-radius: var(--radius-sm); white-space: nowrap; transition: color var(--transition), background var(--transition); }
.sheet-tab:hover { color: var(--text); }
.sheet-tab.is-active { color: var(--text); background: var(--pill-active-bg); }
.sheet-tab:focus-visible { outline: 1.5px solid var(--text-tertiary); outline-offset: 2px; }
.sheet-meta { font-size: 12px; color: var(--text-tertiary); margin-bottom: var(--s2); }
.sheet-scroll { overflow-x: auto; overflow-y: auto; max-height: 340px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.sheet-table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
.sheet-table th, .sheet-table td { text-align: left; padding: 6px 10px; font-size: 12px; white-space: nowrap; border-bottom: 1px solid var(--border-light); }
.sheet-table th { position: sticky; top: 0; background: var(--bg-elevated); color: var(--text-tertiary); font-weight: 600; z-index: 1; }
.sheet-table td { color: var(--text-secondary); }
.sheet-table td.num { text-align: right; }
.sheet-table tr:last-child td { border-bottom: none; }
.sheet-table tbody tr:hover td { background: var(--bg-hover); }


/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 820px) {
  .layout { grid-template-columns: 1fr; }
  .sidebar {
    position: sticky; top: var(--topbar-h); height: auto;
    padding: var(--s2) var(--gutter);
    border-right: none; border-bottom: 1px solid var(--border-light);
    z-index: 40; flex-direction: row; align-items: center;
  }
  .nav { flex-direction: row; gap: var(--s1); overflow-x: auto; min-width: 0; flex: 1 1 auto; -ms-overflow-style: none; scrollbar-width: none; }
  .nav::-webkit-scrollbar { display: none; }
  .nav-sep { display: none; }
  .nav-item .nav-ico { display: none; }
  .sidebar-foot { margin-top: 0; margin-left: auto; padding-top: 0; padding-left: var(--s3); flex-shrink: 0; }
}
