/* book.css — the presentation layer's single stylesheet.
   Descended from the ratified mocks (design/mockups/); tokens lifted from
   sjtSite. Light values live on :root so the page renders without JS; an
   explicit data-theme (set pre-paint by the shell's boot script, toggled by
   page.js) picks the mode thereafter. */

/* Token blocks match any [data-theme] element (not just :root) so a subtree
   can pin its theme — the capture harness pins figures light/dark this way. */
:root,
[data-theme="light"] {
  --bg: #F7F5F0; --bg-subtle: #EDEBE6;
  --text: #2C2C2C; --text-heading: #1A1A1A;
  --text-secondary: #6B6B6B; --text-tertiary: #999999;
  --accent: #3D5A80; --accent-hover: #2C4560;
  --border: #DDD9D2; --border-subtle: #E6E3DC;
  --shadow: rgba(0,0,0,0.06);
  --bar-result: #317EAB;      /* the figure-solution blue, ratified for result bars */
  --bar-definition: #B3922D;  /* gold — decided over green */
  --fig-faint: #A4B3BE; --fig-blue: #317EAB; --fig-red: #B24A4A; --fig-gold: #B3922D; --fig-violet: #8E5AA7; --fig-ink: #2E2E2E;
  --fig-axis: #C9C5BD;
  --scrim: rgba(0,0,0,0.35);
}
[data-theme="dark"] {
  --bg: #1e1d1b; --bg-subtle: #272623;
  --text: #d5d3cf; --text-heading: #eeece8;
  --text-secondary: #9a9894; --text-tertiary: #6d6b67;
  --accent: #7a9abb; --accent-hover: #9ab4d0;
  --border: #383735; --border-subtle: #302f2d;
  --shadow: rgba(0,0,0,0.35);
  --bar-result: #65A4D1;
  --bar-definition: #AC9E68;
  --fig-faint: #464C51; --fig-blue: #65A4D1; --fig-red: #E07373; --fig-gold: #AC9E68; --fig-violet: #C18AD7; --fig-ink: #D2D8DC;
  --fig-axis: #45443F;
  --scrim: rgba(0,0,0,0.55);
}
:root {
  --content-width: 44rem;
  --body-size: 1.175rem; --body-lh: 1.68;
  --rhythm: 1.974rem;
  --font-heading: 'IBM Plex Sans', 'Helvetica Neue', sans-serif;
  --font-body: 'EB Garamond', 'Georgia', serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
  --mobile-bar-h: 2.9rem;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: var(--bg); color: var(--text);
  font-family: var(--font-body);
  font-size: var(--body-size); line-height: var(--body-lh);
  transition: background 0.25s ease, color 0.25s ease;
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }

/* ===== Three-zone layout ===== */
.layout {
  display: grid;
  grid-template-columns: 15rem minmax(0, var(--content-width)) 15rem;
  justify-content: center;
  gap: 4rem;
  padding: 1.5rem 2rem 6rem;
}
@media (max-width: 1279.98px) {
  .layout { grid-template-columns: minmax(0, var(--content-width)); padding: 1.5rem 1.2rem 5rem; }
  .book-rail, .toc-rail { display: none; }
  html { scroll-padding-top: calc(var(--mobile-bar-h) + 0.5rem); }
}

/* ===== Left rail: book nav (shared vocabulary with the mobile drawer) ===== */
.book-rail, .drawer { font-family: var(--font-heading); font-size: 0.85rem; }
.book-rail .sticky, .toc-rail .sticky { position: sticky; top: 3rem; }
.book-title {
  font-weight: 600; font-size: 0.95rem; color: var(--text-heading);
  margin-bottom: 1.5rem; line-height: 1.3;
}
.book-title a { color: inherit; }
.book-title a:hover { color: var(--accent); }
.book-rail .part, .drawer .part {
  color: var(--text-tertiary); text-transform: uppercase;
  letter-spacing: 0.08em; font-size: 0.72rem;
  margin: 1.2rem 0 0.4rem;
}
.book-rail ol, .drawer ol { list-style: none; }
.book-rail li, .drawer li { margin: 0.35rem 0; }
.book-rail a, .drawer a { color: var(--text-secondary); display: block; line-height: 1.4; }
.book-rail a:hover, .drawer a:hover { color: var(--accent); }
.book-rail li.current > a, .drawer li.current > a { color: var(--text-heading); font-weight: 600; }
.book-rail li.current { border-left: 2px solid var(--accent); padding-left: 0.6rem; margin-left: -0.72rem; }

/* ===== Right rail: chapter ToC ===== */
.toc-rail { font-family: var(--font-heading); font-size: 0.82rem; }
.toc-label {
  color: var(--text-tertiary); text-transform: uppercase;
  letter-spacing: 0.08em; font-size: 0.72rem; margin-bottom: 0.6rem;
}
.toc-rail ol { list-style: none; border-left: 1px solid var(--border-subtle); }
.toc-rail li a {
  display: block; color: var(--text-secondary);
  padding: 0.3rem 0 0.3rem 0.9rem; line-height: 1.4;
  border-left: 2px solid transparent; margin-left: -1.5px;
}
.toc-rail li a:hover { color: var(--accent); }
.toc-rail li.active a { color: var(--text-heading); border-left-color: var(--accent); }

/* ===== Mobile bar: auto-hiding sticky nav (Quarto-style headroom) ===== */
.mobile-bar {
  display: none;
  position: fixed; top: 0; left: 0; right: 0; z-index: 30;
  height: var(--mobile-bar-h);
  align-items: center; gap: 0.85rem;
  padding: 0 1.1rem;
  background: var(--bg);
  border-bottom: 1px solid var(--border-subtle);
  font-family: var(--font-heading);
  transition: transform 0.25s ease, background 0.25s ease;
}
.mobile-bar.hidden { transform: translateY(-100%); }
.mobile-bar-title {
  font-size: 0.85rem; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 1279.98px) {
  .mobile-bar { display: flex; }
  .mobile-bar ~ .page-head { padding-top: calc(var(--mobile-bar-h) + 0.6rem); }
}

/* ===== Mobile drawer ===== */
.drawer {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: 50;
  width: min(19rem, 85vw);
  background: var(--bg);
  border-right: 1px solid var(--border);
  padding: 1.6rem 1.4rem;
  overflow-y: auto;
  transform: translateX(-103%);
  transition: transform 0.25s ease;
}
body.drawer-open .drawer { transform: none; }
.drawer-scrim {
  position: fixed; inset: 0; z-index: 40;
  background: var(--scrim);
  opacity: 0; pointer-events: none;
  transition: opacity 0.25s ease;
}
body.drawer-open .drawer-scrim { opacity: 1; pointer-events: auto; }
body.drawer-open { overflow: hidden; }
.drawer-sections { margin: 0.3rem 0 0.5rem; padding-left: 0.9rem; border-left: 1px solid var(--border-subtle); }
.drawer-sections a { font-size: 0.82rem; }

/* ===== Prose ===== */
.prose p { margin-bottom: var(--rhythm); }
.prose > section > p:last-child { margin-bottom: 0; }
.chapter-number {
  font-family: var(--font-heading); color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem;
  margin-bottom: 0.5rem;
}
h1 {
  font-family: var(--font-heading); color: var(--text-heading);
  font-size: 2.3rem; font-weight: 600; line-height: 1.2;
  margin-bottom: calc(var(--rhythm) * 1.5);
}
h2 {
  font-family: var(--font-heading); color: var(--text-heading);
  font-size: 1.4rem; font-weight: 600; line-height: 1.25;
  margin: calc(var(--rhythm) * 2) 0 calc(var(--rhythm) * 0.75);
}
h3 {
  font-family: var(--font-heading); color: var(--text-heading);
  font-size: 1.12rem; font-weight: 600; line-height: 1.3;
  margin: calc(var(--rhythm) * 1.4) 0 calc(var(--rhythm) * 0.6);
}
h2 .secno, h3 .secno { color: var(--text-tertiary); font-weight: 500; margin-right: 0.6rem; }
.prose ul, .prose ol { margin: 0 0 var(--rhythm) 1.4rem; }
blockquote { border-left: 3px solid var(--border); padding-left: 1.1rem; color: var(--text-secondary); margin-bottom: var(--rhythm); }
hr { border: none; border-top: 1px solid var(--border-subtle); margin: calc(var(--rhythm) * 1.5) 0; }
code { font-family: var(--font-mono); font-size: 0.82em; }
pre {
  background: var(--bg-subtle); border: 1px solid var(--border-subtle); border-radius: 6px;
  padding: 0.9rem 1.1rem; overflow-x: auto; margin-bottom: var(--rhythm);
  line-height: 1.55;
}
.broken-ref { color: #c33; font-family: var(--font-mono); font-size: 0.85em; }

/* ===== Tables ===== */
.table-wrap { overflow-x: auto; margin-bottom: var(--rhythm); }
.prose table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.prose th, .prose td {
  padding: 0.45rem 0.65rem;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: top;
}
.prose th {
  color: var(--text-heading);
  font-family: var(--font-heading);
  font-size: 0.88rem;
  font-weight: 600;
}
.prose tbody tr:last-child td { border-bottom-color: var(--border); }

/* ===== Display equations with margin-hung numbers ===== */
.disp { position: relative; margin: calc(var(--rhythm) * 0.75) 0; }
.disp .eqno {
  position: absolute; right: -3.5rem; top: 50%; transform: translateY(-50%);
  font-size: 1rem; color: var(--text-secondary);
}
@media (max-width: 1279.98px) { .disp .eqno { right: 0; } }
.disp mjx-container[display] {
  margin: 0 !important;
  overflow-x: auto; overflow-y: hidden;
  padding: 3px 0;
}
@media (max-width: 1279.98px) {
  /* keep long equations clear of the in-flow number on narrow screens */
  .disp:has(.eqno) mjx-container[display] { padding-right: 3.2rem; }
}

/* ===== Theorem-family environments =====
   Ratified: run-in Plex header, upright bodies, colored left bar by semantic
   family (results blue, definitions gold, notes faint), proofs bare with a
   tombstone. No background tints, ever. */
.env { margin-bottom: var(--rhythm); padding-left: 1.1rem; border-left: 3px solid transparent; }
.env > p:last-child { margin-bottom: 0; }
.env-result { border-left-color: var(--bar-result); }
.env-definition { border-left-color: var(--bar-definition); }
.env-note { border-left-color: var(--border); }
.env-proof { border-left-color: transparent; padding-left: 0; }
.env-head {
  font-family: var(--font-heading); font-weight: 600;
  font-size: 0.98rem; color: var(--text-heading);
  margin-right: 0.4rem;
}
.env-head .env-title { font-weight: 500; color: var(--text-secondary); }
.env-proof .env-head { font-family: var(--font-body); font-style: italic; font-weight: 400; font-size: inherit; }
.tombstone { float: right; color: var(--text-secondary); }

/* ===== Figures ===== */
figure { margin: calc(var(--rhythm) * 1.25) 0; }
figure svg { width: 100%; height: auto; display: block; }
.fig-embed { position: relative; }
.fig-embed .fig-poster { width: 100%; height: auto; display: block; }
.fig-embed.live .fig-poster { display: none; }
figcaption {
  font-size: 0.98rem; color: var(--text-secondary);
  margin-top: 0.8rem; line-height: 1.5;
}
figcaption .figno { font-family: var(--font-heading); font-weight: 600; font-size: 0.88rem; color: var(--text-heading); margin-right: 0.4rem; }

/* Live-figure control chrome: HTML below the panel, never inside the
   captured SVG (drawing-surface rule). First control kit — proposed look. */
.fig-controls {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.9rem;
  margin-top: 0.6rem;
  font-family: var(--font-heading); font-size: 0.78rem; color: var(--text-secondary);
}
.fig-controls .fc-group { display: inline-flex; align-items: center; gap: 0.25rem; }
.fig-controls [hidden] { display: none; }
.fig-controls .fc-label { font-style: italic; margin-right: 0.15rem; }
.fig-controls .fc-readout { min-width: 4.2em; text-align: center; font-variant-numeric: tabular-nums; }
.fig-controls button {
  background: none; border: 1px solid var(--border); border-radius: 5px;
  color: var(--text-secondary); font: inherit; padding: 0.15rem 0.55rem;
  cursor: pointer; line-height: 1.4;
}
.fig-controls button:hover { border-color: var(--text-tertiary); color: var(--text); }
.fig-controls button.active {
  border-color: var(--fig-gold); color: var(--text-heading);
  box-shadow: inset 0 0 0 1px var(--fig-gold);
}
.fig-controls label { display: inline-flex; align-items: center; gap: 0.35rem; cursor: pointer; }
.fig-controls input[type="checkbox"] { accent-color: var(--fig-blue); }
.fig-controls select {
  background: none; border: 1px solid var(--border); border-radius: 5px;
  color: var(--text-secondary); font: inherit; padding: 0.15rem 0.35rem;
  cursor: pointer; line-height: 1.4;
}
.fig-controls select:hover { border-color: var(--text-tertiary); color: var(--text); }
/* Sliders: a continuous parameter the reader turns. Deliberately quiet —
   a hairline track and a pale ball, so the control never competes with
   the figure it drives. */
.fig-controls input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 7rem; height: 0.9rem; background: none;
  cursor: pointer; vertical-align: middle;
}
.fig-controls input[type="range"]::-webkit-slider-runnable-track {
  height: 2px; border-radius: 1px; background: var(--border);
}
.fig-controls input[type="range"]::-moz-range-track,
.fig-controls input[type="range"]::-moz-range-progress {
  height: 2px; border-radius: 1px; background: var(--border);
}
.fig-controls input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 11px; height: 11px; margin-top: -4.5px; border-radius: 50%;
  background: var(--bg); border: 1px solid var(--text-tertiary);
}
.fig-controls input[type="range"]::-moz-range-thumb {
  width: 11px; height: 11px; border-radius: 50%; border: 1px solid var(--text-tertiary);
  background: var(--bg);
}
.fig-controls input[type="range"]:hover::-webkit-slider-thumb { border-color: var(--text-secondary); }
.fig-controls input[type="range"]:hover::-moz-range-thumb { border-color: var(--text-secondary); }

/* Python-emulation figures: the notebook cell's code above its emulated
   matplotlib output. The marked span is the code students write. */
.pyfig-code-wrap {
  position: relative;
  margin-bottom: 0.8rem;
}
.pyfig-code {
  background: var(--bg-subtle);
  border: 1px solid var(--border-subtle); border-radius: 8px;
  padding: 0.8rem 4.5rem 0.8rem 1rem; margin: 0;
  font-family: var(--font-mono); font-size: 0.74rem; line-height: 1.55;
  overflow-x: auto;
}
.pyfig-code .py-student {
  display: block; margin: 0 -1rem; padding: 0 1rem;
  background: color-mix(in srgb, var(--fig-gold) 12%, transparent);
}
.pyfig-copy {
  position: absolute; top: 0.35rem; right: 0.4rem;
  display: flex; align-items: center; justify-content: center;
  width: 1.7rem; height: 1.7rem; padding: 0;
  border: none; background: none; color: var(--text-tertiary);
  cursor: pointer; opacity: 0.72; transition: color 0.2s ease, opacity 0.2s ease;
}
.pyfig-copy:hover, .pyfig-copy:focus-visible {
  color: var(--accent); opacity: 1;
}
.pyfig-copy.copied { color: var(--accent); opacity: 1; }
.pyfig-copy svg { width: 14px; height: 14px; }
@media print { .pyfig-copy { display: none; } }

/* ===== Crossref hover previews ===== */
.xref-preview {
  position: absolute; z-index: 60;
  max-width: 26rem;
  background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 6px 24px var(--shadow);
  padding: 0.9rem 1.1rem;
  font-size: 0.92em; line-height: 1.55;
}
.xref-preview .env, .xref-preview .disp, .xref-preview figure { margin: 0; }
.xref-preview .disp .eqno { position: static; float: right; transform: none; margin-left: 0.8rem; }
.xref-preview .fig-placeholder { aspect-ratio: 3 / 1; }

/* ===== Prev/next footer ===== */
.chapter-footer {
  display: flex; justify-content: space-between; gap: 2rem;
  margin-top: calc(var(--rhythm) * 2.5);
  padding-top: var(--rhythm);
  border-top: 1px solid var(--border-subtle);
  font-family: var(--font-heading); font-size: 0.9rem;
}
.chapter-footer .dir { display: block; color: var(--text-tertiary); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 0.3rem; }
.chapter-footer a { color: var(--text-secondary); }
.chapter-footer a:hover { color: var(--accent); }
.chapter-footer .next { text-align: right; }

/* ===== Page tools: three raw icons, in flow, scroll away ===== */
.page-head {
  display: flex; justify-content: flex-end; gap: 1.1rem;
  padding: 1.1rem 1.5rem 0;
}
.tool-btn {
  display: flex; align-items: center; justify-content: center;
  padding: 0; background: none; border: none; cursor: pointer;
  color: var(--text-tertiary); text-decoration: none;
  transition: color 0.2s ease;
}
.tool-btn:hover { color: var(--accent); }
.tool-btn svg { width: 14px; height: 14px; }
.mobile-bar .tool-btn svg { width: 17px; height: 17px; }
[data-theme="light"] .icon-sun { display: none; }
[data-theme="light"] .icon-moon { display: block; }
[data-theme="dark"] .icon-sun { display: block; }
[data-theme="dark"] .icon-moon { display: none; }

/* ===== Assignment sheet =====
   A one-off page: no rails, no prev/next, no part context — just the sheet,
   centered. Problems and parts wear the numbers the resolver gave them; when
   a heading has no title the number IS the heading, so it stops being a
   quiet marker and takes the heading's own weight. */
.sheet { max-width: var(--content-width); margin: 0 auto; padding: 0 1.2rem 5rem; }
.sheet-course {
  font-family: var(--font-heading); font-size: 0.78rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--text-tertiary); margin-bottom: 2.2rem;
}
.sheet-course a { color: inherit; }
.sheet-course a:hover { color: var(--accent); }

.assignment-head { margin-bottom: calc(var(--rhythm) * 1.5); }
.assignment-number {
  font-family: var(--font-heading); color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem;
  margin-bottom: 0.5rem;
}
.sheet .assignment-head h1 { margin-bottom: 0.9rem; }
.assignment-dates {
  display: flex; flex-wrap: wrap; gap: 1.6rem;
  padding-top: 0.85rem; border-top: 1px solid var(--border-subtle);
  font-family: var(--font-heading); font-size: 0.84rem;
  color: var(--text-secondary);
}
.assignment-head:not(:has(.assignment-dates)) .sheet-actions {
  padding-top: 0.95rem; border-top: 1px solid var(--border-subtle);
}
/* A sheet is meant to be printed, so the way to print it is a worded button,
   not only the corner icon the chapters use. */
.sheet-actions {
  display: flex; flex-wrap: wrap; gap: 0.7rem;
  margin-top: 1.1rem; font-family: var(--font-heading); font-size: 0.9rem;
}

/* Solutions: published, but the reader meets the problem first. <details> is
   the whole mechanism — no script, and it survives with JS off. */
.solution { margin: calc(var(--rhythm) * 0.6) 0 var(--rhythm); }
.solution > summary {
  font-family: var(--font-heading); font-size: 0.86rem; font-weight: 600;
  color: var(--text-secondary); cursor: pointer; width: fit-content;
  padding: 0.15rem 0; list-style-position: inside;
}
.solution > summary:hover { color: var(--accent); }
.solution[open] > summary { margin-bottom: calc(var(--rhythm) * 0.5); }
.solution > :not(summary) { border-left: 2px solid var(--border); padding-left: 1.1rem; }

h2 .probno, h3 .partno { color: var(--text-tertiary); font-weight: 500; margin-right: 0.55rem; }
h2 .probno::after { content: "."; }
/* an untitled heading is nothing but its number, so the number takes the
   heading's own weight instead of standing as a quiet label on one */
h2.bare .probno, h3.bare .partno { color: var(--text-heading); margin-right: 0; }

/* A problem set is a denser document than a chapter: the book's rhythm puts
   more air around a part heading than the part deserves. */
.sheet h2 { margin: calc(var(--rhythm) * 1.5) 0 calc(var(--rhythm) * 0.5); }
.sheet h3 { margin: calc(var(--rhythm) * 0.85) 0 calc(var(--rhythm) * 0.35); }
.sheet .problem p { margin-bottom: calc(var(--rhythm) * 0.7); }
.sheet .problem-part {
  display: grid;
  grid-template-columns: 2.1rem minmax(0, 1fr);
  align-items: baseline;
  margin-top: calc(var(--rhythm) * 0.75);
}
.sheet .problem-part .partno {
  color: var(--text-heading);
  font-family: var(--font-heading);
  font-weight: 600;
}
.sheet .problem-part > p { margin: 0; }

/* End-of-chapter problems are a change of mode: denser than the narrative,
   ruled rather than boxed, and organized by purpose rather than sections. */
.chapter-problems {
  margin-top: calc(var(--rhythm) * 3.4);
  padding-top: calc(var(--rhythm) * 0.7);
  border-top: 2px solid var(--text-heading);
  font-size: 0.92em;
  line-height: 1.58;
}
.chapter-problems::before {
  content: "Practice · Exploration · Computation";
  display: block;
  margin-bottom: 0.35rem;
  color: var(--text-tertiary);
  font-family: var(--font-heading);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.chapter-problems > h2 {
  margin: 0 0 calc(var(--rhythm) * 0.65);
  font-size: 1.6rem;
}
.chapter-problems > h2 + p {
  max-width: 39rem;
  color: var(--text-secondary);
}
.chapter-problems .problem-group {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin: calc(var(--rhythm) * 1.7) 0 calc(var(--rhythm) * 0.55);
  color: var(--text-tertiary);
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.chapter-problems .problem-group::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--border);
}
.chapter-problems .problem > h3 {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr);
  column-gap: 0.35rem;
  margin: calc(var(--rhythm) * 0.75) 0 calc(var(--rhythm) * 0.08);
  font-size: 1.03rem;
  line-height: 1.32;
}
.chapter-problems .problem > :not(h3) { margin-left: 2.35rem; }
.chapter-problems .problem > h4 {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr);
  column-gap: 0.3rem;
  margin-top: calc(var(--rhythm) * 0.12);
  font-size: 0.9rem;
  line-height: 1.35;
}
.chapter-problems .problem-part {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr);
  column-gap: 0.3rem;
  align-items: baseline;
  margin-top: calc(var(--rhythm) * 0.1);
}
.chapter-problems .problem-part > p { margin: 0; }
.chapter-problems h3 .probno,
.chapter-problems h4 .partno,
.chapter-problems .problem-part .partno {
  color: var(--text-tertiary);
  font-weight: 500;
  margin-right: 0;
}
.chapter-problems h3 .probno::after { content: "."; }
.chapter-problems h3.bare .probno,
.chapter-problems h4.bare .partno { color: var(--text-heading); margin-right: 0; }
.chapter-problems .problem p { margin-bottom: calc(var(--rhythm) * 0.14); }
.chapter-problems .problem .disp { margin: calc(var(--rhythm) * 0.25) 0; }
.chapter-problems .problem pre { font-size: 0.9em; }
@media (max-width: 639.98px) {
  .chapter-problems { font-size: 0.95em; }
  .chapter-problems .problem > h3 { grid-template-columns: 1.6rem minmax(0, 1fr); }
  .chapter-problems .problem-part { grid-template-columns: 1.6rem minmax(0, 1fr); }
  .chapter-problems .problem > :not(h3) { margin-left: 1.95rem; }
}

/* ===== Site footer (chapter pages only — the cover ends at its actions) ===== */
.site-footer {
  margin-top: 3rem; padding-top: 1.2rem;
  border-top: 1px solid var(--border-subtle);
  font-family: var(--font-heading); font-size: 0.78rem;
  color: var(--text-tertiary); text-align: center;
}
.site-footer a { color: var(--text-secondary); }
.site-footer a:hover { color: var(--accent); }

/* ===== Landing cover ===== */
.cover { max-width: 58rem; margin: 0 auto; padding: 4rem 2rem 5rem; text-align: center; }
.hero-kicker {
  font-family: var(--font-heading); font-size: 0.78rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.18em; color: var(--text-tertiary);
  margin-bottom: 1.4rem;
}
.hero-title {
  font-family: var(--font-body); font-weight: 500;
  font-size: 3.6rem; line-height: 1.12; color: var(--text-heading);
  margin: 0 auto 1.2rem; max-width: 40rem;
}
.hero-author {
  font-family: var(--font-heading); font-size: 0.95rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-secondary);
}
.hero-fig { margin: 3rem auto 2.6rem; }
.hero-fig svg { width: 100%; height: auto; display: block; }
.hero-blurb {
  max-width: 34rem; margin: 0 auto 2.4rem;
  font-size: 1.25rem; line-height: 1.62; color: var(--text-secondary);
}
.hero-actions { display: flex; justify-content: center; gap: 1.4rem; font-family: var(--font-heading); font-size: 0.95rem; }
.action {
  padding: 0.55rem 1.3rem; border: 1px solid var(--border); border-radius: 6px;
  color: var(--text-secondary); transition: color 0.2s ease, border-color 0.2s ease;
}
.action.primary { color: var(--accent); border-color: var(--accent); }
.action:hover { color: var(--accent-hover); border-color: var(--accent-hover); }

/* Contents on the cover: a second movement below the cover proper — big
   air above and its own kicker, so the cover still "ends" at the actions.
   Chapters only; each chapter page's rails carry its sections. */
.cover-shelves {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2rem 3.5rem;
  align-items: start;
  max-width: 46rem; margin: 7.5rem auto 0;
}
.cover-shelves:has(> :only-child) { grid-template-columns: minmax(0, 24rem); justify-content: center; }
.cover-contents, .cover-assignments {
  text-align: left; font-family: var(--font-heading); font-size: 0.9rem;
}
.cover-assignments ol { list-style: none; }
.cover-assignments li { margin: 0.9rem 0; }
.cover-assignments a { color: var(--text-secondary); display: block; line-height: 1.4; }
.cover-assignments a:hover { color: var(--accent); }
.assign-name { display: block; }
.assign-due { display: block; color: var(--text-tertiary); font-size: 0.82rem; margin-top: 0.15rem; }
.contents-kicker {
  text-align: center;
  font-size: 0.78rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.18em;
  color: var(--text-tertiary);
  margin-bottom: 0.4rem;
}
.cover-contents .part {
  color: var(--text-tertiary); text-transform: uppercase;
  letter-spacing: 0.08em; font-size: 0.72rem;
  margin: 1.6rem 0 0.5rem;
}
.cover-contents ol { list-style: none; }
.cover-contents li { margin: 0.45rem 0; }
.cover-contents a { color: var(--text-secondary); display: block; line-height: 1.45; }
.cover-contents a:hover { color: var(--accent); }
.cover-contents .chapno { color: var(--text-tertiary); display: inline-block; min-width: 1.6rem; }
@media (max-width: 700px) {
  .cover-shelves { grid-template-columns: minmax(0, 24rem); justify-content: center; gap: 3.5rem; }
}
@media (max-width: 640px) {
  .hero-title { font-size: 2.4rem; }
  .cover { padding-top: 2.5rem; }
}
