/* Course guides: book stylesheet.
   Sections: fonts, tokens, base, layout, navigation, typography,
   environments, proofs, exercises and practice, math, figures, print. */

/* ---------- Fonts ---------- */

@font-face {
  font-family: "Libertinus Sans";
  src: url("fonts/LibertinusSans-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Libertinus Sans";
  src: url("fonts/LibertinusSans-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Libertinus Sans";
  src: url("fonts/LibertinusSans-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
/* Libertinus Math is split by unicode-range (see scripts/fonts.mjs): the core
   file covers ordinary equations; the extension (fraktur, double-struck,
   sans, monospace alphabets) downloads only on pages that use it. */
@font-face {
  font-family: "Libertinus Math";
  src: url("fonts/LibertinusMath-Core.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+0000-024F, U+0300-036F, U+0370-03FF, U+2000-206F, U+2070-209F,
    U+20D0-20FF, U+2100-214F, U+2190-21FF, U+2200-22FF, U+2300-23FF, U+25A0-25FF,
    U+27C0-27FF, U+2900-2AFF, U+1D400-1D49B, U+1D6A8-1D7C9, U+1D7CE-1D7D7, U+FE00-FE0F;
}
@font-face {
  font-family: "Libertinus Math";
  src: url("fonts/LibertinusMath-Ext.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+1D49C-1D6A3, U+1D7CA-1D7CB, U+1D7D8-1D7FF;
}
/* Calligraphic letters, ℓ, and △ from New Computer Modern Math, as in the
   PDF. Its range excludes U+0020, so Libertinus Math stays the primary font
   whose MATH table drives layout. */
@font-face {
  font-family: "CG Calligraphic";
  src: url("fonts/NewCMMath-Cal.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+1D49C-1D4CF, U+210A-210B, U+2110, U+2112-2113, U+211B, U+212C,
    U+212F-2131, U+2133-2134, U+25B3, U+25B5, U+FE00-FE01;
}

/* ---------- Tokens ---------- */

:root {
  color-scheme: light dark;

  --bg: light-dark(#fcfcfa, #161616);
  --bg-raised: light-dark(#ffffff, #1e1e1d);
  --fg: light-dark(#1b1b1b, #e4e2dd);
  --fg-2: light-dark(#454545, #bcb9b3);
  --fg-3: light-dark(#6a6a6a, #8f8c86);
  --rule: light-dark(#e3e0d9, #2f2e2c);
  --rule-strong: light-dark(#c8c4bb, #4a4844);
  --link: light-dark(#1d4f91, #8fb6ec);
  --link-line: light-dark(rgb(29 79 145 / 0.35), rgb(143 182 236 / 0.4));
  --focus: light-dark(#1d4f91, #a3c6f7);
  --mark: light-dark(rgb(29 79 145 / 0.08), rgb(143 182 236 / 0.1));

  /* Environment families */
  --c-def: light-dark(#2f7d5b, #6cc39a);
  --c-thm: light-dark(#2b5c9e, #86aee6);
  --c-tech: light-dark(#9a6a14, #d9a952);
  --c-ex: light-dark(#8a8780, #6f6c66);
  --c-beyond: light-dark(#8a5a00, #d6a24a);

  /* Diagram palette (lib/config.typ maps these hex values) */
  --c-blue: light-dark(#2b5c9e, #86aee6);
  --c-green: light-dark(#2f7d5b, #6cc39a);
  --c-ochre: light-dark(#9a6a14, #d9a952);
  --c-red: light-dark(#b03a2e, #ee8b7f);
  --c-muted: light-dark(#777777, #8f8c86);
  --c-faint: light-dark(#cccccc, #444240);

  --bar-h: 3rem;
  --nav-w: 17rem;
  --toc-w: 14rem;
  --gutter: 1rem;
  --measure: 33em;
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
:root[data-width="wide"] { --measure: 46em; }
/* Text size scales the reading column only: body text, math, and the measure
   (which is in em) together. Sidebars and the top bar are sized in rem and stay
   put, so the layout breakpoints do not shift. */
:root[data-size="small"] { --text-scale: 0.9; }
:root[data-size="large"] { --text-scale: 1.125; }
:root[data-width="full"] { --measure: none; }

/* ---------- Base ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--bar-h) + 1rem);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: "Libertinus Sans", "Libertinus Math", ui-sans-serif, system-ui, sans-serif;
  font-size: calc(1.125rem * var(--text-scale, 1));
  line-height: 1.6;
  font-kerning: normal;
  font-variant-numeric: lining-nums;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}
@media (min-width: 40rem) {
  body { font-size: calc(1.1875rem * var(--text-scale, 1)); }
  :root { --gutter: 2rem; }
}

a {
  color: var(--link);
  text-decoration-line: underline;
  text-decoration-color: var(--link-line);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
a:hover { text-decoration-color: currentColor; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}

::selection { background: light-dark(rgb(29 79 145 / 0.18), rgb(143 182 236 / 0.3)); }

button { font: inherit; color: inherit; }

kbd {
  font: inherit;
  font-size: 0.85em;
  padding: 0 0.35em;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
}

.skip-link {
  position: absolute;
  left: 0.5rem;
  top: -10rem;
  z-index: 100;
  padding: 0.5rem 0.9rem;
  background: var(--bg-raised);
  color: var(--fg);
  border: 1px solid var(--rule-strong);
}
.skip-link:focus { top: 0.5rem; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Layout ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  height: var(--bar-h);
  padding: 0 0.5rem;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
  font-size: 0.9rem;
}
.topbar-title {
  flex: 1;
  min-width: 0;
  padding: 0 0.5rem;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--fg);
  font-weight: 700;
  text-decoration: none;
}
.topbar-btn {
  flex: none;
  padding: 0.3rem 0.6rem;
  border: 1px solid transparent;
  border-radius: 3px;
  background: none;
  color: var(--fg-2);
  cursor: pointer;
}
.topbar-btn:hover { border-color: var(--rule-strong); color: var(--fg); }
html:not(.js) .settings-toggle { display: none; }

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}
.main {
  min-width: 0;
  padding: 2rem var(--gutter) 4rem;
}
.main:focus { outline: none; }
.page {
  max-width: var(--measure);
  margin-inline: auto;
}

@media (min-width: 64rem) {
  .layout { grid-template-columns: var(--nav-w) minmax(0, 1fr); }
  .nav-toggle { display: none; }
  .main { padding-top: 3rem; }
}
@media (min-width: 82rem) {
  .layout { grid-template-columns: var(--nav-w) minmax(0, 1fr) var(--toc-w); }
  .layout.no-toc { grid-template-columns: var(--nav-w) minmax(0, 1fr) var(--toc-w); }
  .toc-toggle { display: none; }
}

/* ---------- Popovers ---------- */

[popover] {
  margin: 0;
  padding: 1rem 1.1rem;
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  background: var(--bg-raised);
  color: var(--fg);
  box-shadow: 0 8px 28px rgb(0 0 0 / 0.14);
}
[popover]::backdrop { background: rgb(0 0 0 / 0.2); }

.settings:popover-open {
  position: fixed;
  inset: calc(var(--bar-h) + 0.25rem) 0.5rem auto auto;
  width: 16.5rem;
  font-size: 0.9rem;
}
.settings fieldset {
  margin: 0 0 0.9rem;
  padding: 0;
  border: 0;
}
.settings legend {
  margin-bottom: 0.3rem;
  color: var(--fg-3);
  font-size: 0.85em;
}
.settings label {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-right: 0.8rem;
  cursor: pointer;
}
.settings input { margin: 0; accent-color: var(--c-thm); }
.settings-keys { margin: 0; color: var(--fg-3); font-size: 0.85em; }
@media (max-width: 63.99rem) {
  .width-setting { display: none; }
}

/* ---------- Book navigation (left) ---------- */

.book-nav {
  font-size: 0.9rem;
  line-height: 1.4;
}
.book-nav:popover-open {
  position: fixed;
  inset: 0 auto 0 0;
  width: min(21rem, 88vw);
  height: 100%;
  max-height: none;
  overflow-y: auto;
  border-radius: 0;
  border-width: 0 1px 0 0;
}
@media (min-width: 64rem) {
  .book-nav,
  .book-nav:popover-open {
    display: block;
    position: sticky;
    inset: auto;
    top: var(--bar-h);
    width: auto;
    height: calc(100vh - var(--bar-h));
    height: calc(100dvh - var(--bar-h));
    overflow-y: auto;
    padding: 1.6rem 1rem 2rem 1.25rem;
    border: 0;
    border-right: 1px solid var(--rule);
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    scrollbar-width: thin;
  }
}
.book-nav ol, .book-nav ul { list-style: none; margin: 0; padding: 0; }
.book-nav a { color: var(--fg-2); text-decoration: none; }
.book-nav a:hover { color: var(--fg); }
.book-nav a[aria-current="page"] { color: var(--fg); font-weight: 700; }
.nav-book { margin: 0 0 1.2rem; font-weight: 700; }
.nav-book a { color: var(--fg); }
.nav-chapter { margin: 0.15rem 0; }
.nav-chapter summary {
  display: flex;
  gap: 0.45rem;
  padding: 0.25rem 0;
  color: var(--fg);
  cursor: pointer;
  list-style: none;
}
.nav-chapter summary::-webkit-details-marker { display: none; }
.nav-chapter summary::before {
  content: "";
  flex: none;
  width: 0.4em;
  height: 0.4em;
  margin: 0.45em 0.1em 0 0;
  border-right: 1.5px solid var(--fg-3);
  border-bottom: 1.5px solid var(--fg-3);
  transform: rotate(-45deg);
}
.nav-chapter details[open] > summary::before { transform: rotate(45deg); margin-top: 0.35em; }
.nav-sections { margin: 0.1rem 0 0.5rem 1.05rem !important; }
.nav-sections a {
  display: flex;
  gap: 0.45rem;
  padding: 0.2rem 0 0.2rem 0.6rem;
  border-left: 1px solid var(--rule);
}
.nav-sections a[aria-current="page"] { border-left: 2px solid var(--c-thm); padding-left: calc(0.6rem - 1px); }
.book-nav .num { color: var(--fg-3); font-variant-numeric: tabular-nums; }
.nav-beyond { color: var(--c-beyond); }
.nav-extra { margin-top: 1.4rem !important; padding-top: 1rem !important; border-top: 1px solid var(--rule); }
.nav-extra li { margin: 0.3rem 0; }

/* ---------- On this page (right) ---------- */

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


.page-toc { font-size: 0.85rem; line-height: 1.35; }
.page-toc:popover-open {
  position: fixed;
  inset: calc(var(--bar-h) + 0.25rem) 0.5rem auto auto;
  width: min(20rem, calc(100vw - 1rem));
  max-height: calc(100vh - var(--bar-h) - 1rem);
  overflow-y: auto;
}
@media (min-width: 82rem) {
  .page-toc,
  .page-toc:popover-open {
    display: block;
    position: sticky;
    inset: auto;
    top: var(--bar-h);
    width: auto;
    max-height: calc(100vh - var(--bar-h));
    overflow-y: auto;
    padding: 3rem 1.25rem 2rem 0.5rem;
    border: 0;
    background: transparent;
    box-shadow: none;
    scrollbar-width: thin;
  }
}
.toc-title { margin: 0 0 0.6rem; color: var(--fg-3); }
/* One continuous rail: every link starts at the same x and carries its own
   segment of the rail, so the segments join. Nesting indents only the text.
   Typst wraps an entry that has children in a <p>; it must not add margins. */
.page-toc ol { list-style: none; margin: 0; padding: 0; }
.page-toc li > p { margin: 0; }
.page-toc a {
  display: flex;
  gap: 0.4rem;
  padding: 0.22rem 0 0.22rem 0.75rem;
  border-left: 1px solid var(--rule);
  color: var(--fg-3);
  text-decoration: none;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.page-toc ol ol a { padding-left: calc(0.75rem + 2.6em + 0.4rem); } /* align with the parent title */
.page-toc a:hover { color: var(--fg); }
/* Same rail as the book navigation: 1px, with a 2px marker on the current item
   (the padding absorbs the extra pixel so the text does not move). */
.page-toc a[aria-current="true"] { color: var(--fg); border-left: 2px solid var(--c-thm); padding-left: calc(0.75rem - 1px); }
.page-toc ol ol a[aria-current="true"] { padding-left: calc(0.75rem + 2.6em + 0.4rem - 1px); }
.page-toc .num { flex: none; min-width: 2.6em; font-variant-numeric: tabular-nums; }

/* ---------- Page furniture ---------- */

.page-header { margin-bottom: 2rem; }
.page-kicker { margin: 0 0 0.4rem; color: var(--fg-3); font-size: 0.9em; }
.page-kicker a { color: inherit; text-decoration: none; }
.page-kicker a:hover { color: var(--fg); }
.lead { color: var(--fg-2); font-size: 1.08em; }

.beyond-note {
  margin: 0.6rem 0 0;
  color: var(--fg-2);
  font-size: 0.9em;
}
.beyond-tag {
  color: var(--c-beyond);
  font-size: 0.8em;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.beyond-region {
  margin: 1.8em 0;
  padding-left: 1rem;
  border-left: 2px dashed var(--c-beyond);
}
.beyond-region > .beyond-note { margin: 0 0 0.6em; }
.beyond-region > :is(h2, h3, h4):first-child { margin-top: 0; }
.page :is(h1, h2, h3, h4) .beyond-tag { margin-left: 0.5em; font-size: 0.55em; font-weight: 400; vertical-align: 0.25em; }
.nobr { white-space: nowrap; }

.pager {
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  max-width: var(--measure);
  margin: 4rem auto 0;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
}
.pager a {
  display: flex;
  flex-direction: column;
  max-width: 48%;
  color: var(--fg);
  text-decoration: none;
}
.pager-next { margin-left: auto; text-align: right; }
.pager-dir { color: var(--fg-3); font-size: 0.85em; }
.pager-title .num { margin-right: 0.4em; color: var(--fg-3); }
.pager a:hover .pager-title { text-decoration: underline; text-decoration-color: var(--link-line); }

/* Book home */
.book-header h1 { margin-bottom: 0.3rem; }
.book-subtitle { margin: 0; color: var(--fg-2); font-size: 1.2em; }
.book-meta { margin: 0.6rem 0 0; color: var(--fg-3); }
.book-legend dl { display: grid; grid-template-columns: max-content 1fr; gap: 0.35rem 1rem; margin: 0.8rem 0 1rem; }
.book-legend dt, .book-legend dd { margin: 0; }
.contents, .contents-sections { list-style: none; padding: 0; margin: 0; }
.contents-chapter { margin: 1.4rem 0; }
.contents-chapter-link { color: var(--fg); font-weight: 700; text-decoration: none; }
.contents-chapter-link .num, .contents-sections .num { margin-right: 0.5em; color: var(--fg-3); font-weight: 400; }
.contents-desc { margin: 0.15rem 0 0.4rem; color: var(--fg-2); font-size: 0.92em; }
.contents-sections { margin-left: 1.6em; }
.contents-sections li { margin: 0.2rem 0; }
.contents-sections a { color: var(--fg); text-decoration: none; }
.contents-sections a:hover .nav-text { text-decoration: underline; text-decoration-color: var(--link-line); }

.technique-list dt { margin-top: 1rem; }
.technique-list dd { margin: 0.2rem 0 0 1.5rem; color: var(--fg-2); }

/* ---------- Typography ---------- */

.page p { margin: 0.9em 0; }
.page h1, .page h2, .page h3, .page h4 {
  position: relative;
  font-weight: 700;
  line-height: 1.2;
  text-wrap: balance;
}
.page h1 { margin: 0; font-size: 2em; letter-spacing: -0.005em; }
.page h2 { margin: 2.4em 0 0.7em; font-size: 1.4em; }
.page h3 { margin: 2em 0 0.6em; font-size: 1.15em; }
.page h4 { margin: 1.6em 0 0.5em; font-size: 1em; }
.page h1 .num, .page h2 .num, .page h3 .num { margin-right: 0.45em; color: var(--fg-3); font-weight: 400; }

/* Self-links: headings and environment labels link to themselves. A "#"
   in the margin appears on hover and focus. */
.heading-link, .env-label, .proof-label, .step-num { color: inherit; text-decoration: none; }
.heading-link::before {
  content: "#";
  position: absolute;
  right: 100%;
  padding-right: 0.35em;
  color: var(--fg-3);
  font-weight: 400;
  opacity: 0;
}
.heading-link:hover::before, .heading-link:focus-visible::before { opacity: 1; }
.env-label:hover, .proof-label:hover, .step-num:hover { text-decoration: underline; text-decoration-color: var(--rule-strong); }

.page ul, .page ol { padding-left: 1.6em; }
.page li { margin: 0.3em 0; }
msqrt { margin-inline-end: var(--msqrt-trail, 0); }
/* Accents over slanted letters (tagged in scripts/common.mjs): shift right
   like TeX's skew, since Chrome ignores the font's accent attachment. */
mo.acc-it { translate: 0.09em 0; }
mo.acc-cal { translate: 0.2em 0; }
/* Augmented matrices; see render-mat-html. */
.mat-aug .aug-v { border-left: 1px solid currentColor; padding-left: 0.6em; }
.mat-aug .aug-h { border-top: 1px solid currentColor; }
/* Lists with explicit markers ("(a)", "(i)"); see render-enum-html. */
.page ol.enum-marked { list-style: none; padding-left: 2.2em; }
/* The marker sits inline at the start of the item's first line (inside its
   <p> when the item holds block content), outdented into the gutter. Being in
   the line, it shares the line's baseline even when tall inline math (a
   matrix) makes the line taller. flex-end keeps it right-aligned, and a wide
   marker overflows into the margin rather than into the text. */
.enum-marked > li .enum-marker { display: inline-flex; justify-content: flex-end; box-sizing: border-box; width: 2.2em; margin-left: -2.2em; padding-right: 0.5em; white-space: nowrap; }
.page li > p { margin: 0.3em 0; }
.page dl dt { font-weight: 700; }

.page table { border-collapse: collapse; margin: 1.2em auto; font-variant-numeric: tabular-nums; }
/* Wide tables scroll sideways on narrow screens instead of widening the page.
   display: block keeps the table's own layout inside a scrolling box. */
.page table { display: block; width: max-content; max-width: 100%; overflow-x: auto; }
.page td, .page th { padding: 0.3em 0.8em; border-bottom: 1px solid var(--rule); text-align: left; }
.page code { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 0.85em; }

.hl-blue { color: var(--c-blue); }
.hl-red { color: var(--c-red); }
.hl-green { color: var(--c-green); }

/* ---------- Environments ---------- */

.env { margin: 1.6em 0; }
.env > p:first-child { margin-top: 0; }
.env > :last-child { margin-bottom: 0; }
.env-head { font-weight: 700; }
.env-title { font-weight: 400; }

.fam-definition, .fam-theorem, .fam-technique, .fam-exercise {
  padding-left: 1rem;
  border-left: 2px solid var(--c-thm);
}
.fam-definition { border-left-color: var(--c-def); }
.fam-technique { border-left-color: var(--c-tech); }
.fam-exercise { border-left: 1px solid var(--c-ex); }

.fam-remark .env-head, .fam-intuition .env-head { font-weight: 400; font-style: italic; }
.fam-intuition {
  padding-left: 1rem;
  border-left: 1px dotted var(--fg-3);
}
.fam-aside {
  padding: 0.7em 0;
  border-block: 1px solid var(--rule);
  color: var(--fg-2);
  font-size: 0.92em;
}
/* Only the aside's own head: environments nested in an aside keep theirs. */
.fam-aside > .env-head, .fam-aside > p:first-child > .env-head { font-weight: 400; font-style: italic; }
.fam-algorithm {
  padding: 0.7em 0;
  border-block: 1px solid var(--rule-strong);
}
.fam-algorithm .env-head { margin: 0 0 0.5em; }
.alg-io { display: grid; grid-template-columns: max-content 1fr; gap: 0.2em 0.9em; margin: 0 0 0.6em; }
.alg-io dt { font-style: italic; font-weight: 400; }
.alg-io dd { margin: 0; }
.alg-step {
  display: grid;
  grid-template-columns: 1.6em minmax(0, 1fr);
  margin: 0.5em 0;
}
.alg-step > p { margin: 0; }
.step-body > p:first-child { margin-top: 0; }
.step-body > p:last-child { margin-bottom: 0; }
.step-num { font-variant-numeric: tabular-nums; }

/* Metadata on the head line: difficulty and scope. */
.meta {
  float: right;
  margin: 0.1em 0 0 1em;
  color: var(--fg-3);
  font-size: 0.8em;
  font-style: normal;
  font-weight: 400;
}
.meta > * + * { margin-left: 0.8em; }
.diff { white-space: nowrap; }
/* A four-step meter before the word, filled to the level. */
.diff::before {
  content: "";
  display: inline-block;
  width: 1.5em;
  height: 0.42em;
  margin-right: 0.4em;
  vertical-align: 0.08em;
  background:
    linear-gradient(90deg, currentColor var(--fill, 25%), transparent 0) 0 0 / 100% 100% no-repeat;
  mask: repeating-linear-gradient(90deg, #000 0 0.3em, transparent 0.3em 0.4em);
  opacity: 0.85;
}
.diff[data-level="1"] { --fill: 25%; }
.diff[data-level="2"] { --fill: 50%; }
.diff[data-level="3"] { --fill: 75%; }
.diff[data-level="4"] { --fill: 100%; color: var(--c-beyond); }

.backlinks { margin: 0.6em 0 0; color: var(--fg-2); font-size: 0.9em; }
/* "Used in N places": closed by default; the chevron matches the book
   navigation's. */
details.backlinks > summary {
  display: flex;
  align-items: baseline;
  gap: 0.45em;
  width: fit-content;
  cursor: pointer;
  list-style: none;
}
details.backlinks > summary::-webkit-details-marker { display: none; }
details.backlinks > summary::before {
  content: "";
  flex: none;
  width: 0.38em;
  height: 0.38em;
  border-right: 1.5px solid var(--fg-3);
  border-bottom: 1.5px solid var(--fg-3);
  transform: translateY(-0.12em) rotate(-45deg);
}
details.backlinks[open] > summary::before { transform: translateY(-0.2em) rotate(45deg); }
details.backlinks > summary:hover { color: var(--fg); }
details.backlinks > p { margin: 0.3em 0 0; }

/* Collapse control on an environment's head line (added by book.js). It
   floats right, ahead of the difficulty, so the run-in head reads as before.
   Collapsed, everything after the head is hidden (hidden="until-found", so
   find-in-page still reaches it), along with the attached proofs. */
.env-toggle {
  float: right;
  display: grid;
  place-items: center;
  width: 1.5em;
  height: 1.5em;
  margin: 0.03em -0.3em 0 0.3em;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: none;
  color: var(--fg-3);
  font-style: normal;
  cursor: pointer;
}
.env-toggle::before {
  content: "";
  width: 0.4em;
  height: 0.4em;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-0.1em) rotate(45deg);
}
.env-toggle[aria-expanded="false"]::before { transform: translateX(-0.08em) rotate(-45deg); }
@media (hover: hover) {
  .env-toggle:hover { color: var(--fg); background: var(--mark); }
}
/* A hidden="until-found" run-in must be a block for the browser to hide it;
   it then takes no height, so the head stays a single line. */
.env-runin[hidden="until-found"] { display: block; }
.env-body > :last-child { margin-bottom: 0; }
.env.is-collapsed > p:first-child, .env.is-collapsed > .env-head { margin-bottom: 0; }
.proof.is-folded { display: none; }

/* ---------- Proofs ---------- */

.proof { margin: 0.9em 0 1.6em; }
.proof-head { margin: 0; }
.proof-label { font-style: italic; }
.stage { margin: 0.55em 0; }
.stage-full > p:first-child { margin-top: 0; }
.stage-uses, .stage-hint, .stage-sketch {
  padding-left: 0.9rem;
  border-left: 1px solid var(--rule-strong);
  color: var(--fg-2);
  font-size: 0.94em;
}
.stage-uses p { margin: 0.2em 0; }
.stage-label { font-style: italic; }
.qed {
  float: right;
  margin-left: 1em;
  font-family: "Libertinus Math", "Libertinus Sans", serif;
}

/* Collapsing happens only when JavaScript can reveal again. */
.js .proof .stage:not(.is-shown) { display: none; }
.reveal { display: inline; }
.reveal-controls {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-left: 0.6em;
  vertical-align: 0.05em;
}
.btn {
  padding: 0.12em 0.6em;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  background: transparent;
  color: var(--fg-2);
  font-size: 0.8em;
  line-height: 1.5;
  cursor: pointer;
}
.btn:hover { border-color: var(--fg-3); color: var(--fg); }
.btn[aria-pressed="false"] { color: var(--fg-3); border-style: dashed; }
.btn[aria-pressed="true"] { color: var(--fg); border-color: var(--fg-3); background: var(--mark); }
.btn-text { border-color: transparent; text-decoration: underline; text-decoration-color: var(--rule-strong); }

/* ---------- Exercises and practice ---------- */

.exercise-list > .env-exercise, .exercise-list > .env-problem { margin: 1.4em 0 0.4em; }
.exercise-list > .proof { margin: 0.3em 0 1.2em 1rem; }
.exercise-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 1.2em;
  color: var(--fg-3);
  font-size: 0.9em;
}
.exercise-filter .filter-label { margin-right: 0.2rem; }
.exercise-filter output { margin-left: auto; font-size: 0.9em; }

.practice {
  margin: 3em 0 0;
  padding-top: 0.2em;
}
html:not(.js) .practice-section { display: none; }
.practice-section > h2 { margin-top: 0; }
.practice-intro { color: var(--fg-2); }
.practice-form {
  display: grid;
  gap: 0.9rem 1.5rem;
  margin: 1em 0 1.4em;
  padding: 1rem 0;
  border-block: 1px solid var(--rule);
  font-size: 0.9em;
}
@media (min-width: 40rem) { .practice-form { grid-template-columns: 1fr 1fr; } }
.practice-form fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
.practice-form legend { margin-bottom: 0.3rem; color: var(--fg-3); }
.practice-form label { display: inline-flex; align-items: center; gap: 0.3rem; margin: 0.1rem 0.9rem 0.1rem 0; cursor: pointer; }
.practice-form input { margin: 0; accent-color: var(--c-thm); }
.practice-form input[type="search"] {
  width: min(16rem, 100%);
  padding: 0.2em 0.45em;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  background: var(--bg);
  color: inherit;
  font: inherit;
}
.practice-filters > summary { color: var(--fg-2); cursor: pointer; font-size: 0.9em; }
.practice-filters[open] > summary { margin-bottom: 0.2em; }
.practice-form select { font: inherit; color: inherit; background: var(--bg); border: 1px solid var(--rule-strong); border-radius: 3px; padding: 0.15em 0.3em; max-width: 100%; }
.practice-form .wide { grid-column: 1 / -1; }
.practice-topics { max-height: 16rem; overflow-y: auto; padding-right: 0.5rem; scrollbar-width: thin; }
.practice-topics .group { margin: 0.4rem 0 0.2rem; color: var(--fg-3); font-size: 0.9em; }
.practice-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 1rem 0; }
.practice-actions output { color: var(--fg-3); font-size: 0.9em; }
.practice-list { margin: 0; }
.bank-item, .practice-item { margin: 1.4em 0; padding-top: 0.2em; }
.practice-item + .practice-item { border-top: 1px solid var(--rule); padding-top: 1em; }
.practice-from { margin: 0 0 0.3em; color: var(--fg-3); font-size: 0.85em; display: flex; flex-wrap: wrap; gap: 0 0.3em; align-items: baseline; }
.practice-from a { color: inherit; }
.practice-solved { margin-left: auto; display: inline-flex; gap: 0.35em; align-items: baseline; cursor: pointer; }
.practice-item.is-solved > :not(.practice-from) { opacity: 0.6; }
.bank-standalone { max-width: calc(var(--measure) + 4rem); margin: 0 auto; }

/* ---------- Math ---------- */

math {
  font-family: "CG Calligraphic", "Libertinus Math", math;
  font-size: 1.02em;
}
.eq { margin: 1em 0; }
.eq > math[display="block"] {
  display: block math;
  overflow-x: auto;
  overflow-y: hidden;
  padding-block: 0.2em;
  scrollbar-width: thin;
}
.eq-numbered {
  display: flex;
  align-items: center;
  gap: 1em;
}
.eq-numbered > math[display="block"] { flex: 1; min-width: 0; }
.eq-num { flex: none; color: var(--fg-2); }
math[display="block"]:focus-visible { outline-offset: 0; }
mtext { font-family: "Libertinus Math", math; }
/* Transpose marks at TeX's script proportion; see fixTransposeSize in scripts/common.mjs. */
mtext.tp { font-size: 0.75em; }
/* Primes use the font's script variant; see fixPrimes in scripts/common.mjs. */
mo.prime { font-feature-settings: "ssty" 1; }
mrow.overline, mpadded.overline { border-top: 0.065em solid; padding-top: 0.08em; }
mrow.cancel {
  background: linear-gradient(to bottom right, transparent calc(50% - 0.04em), currentColor calc(50% - 0.04em), currentColor calc(50% + 0.04em), transparent calc(50% + 0.04em));
}

/* Typst's MathML support rules (it inlines these on every page; the build
   strips that copy so they are cached here instead). */
/* Child combinators throughout: these rules style the outer table of an
   aligned or multi-line equation and must not reach matrices nested in it. */
mtable.right-align > mtr > mtd,
mtable > mtr > mtd.right-align,
mtable.left-align > mtr > mtd.right-align,
mtable.aligned > mtr > mtd:nth-child(odd) { justify-items: end; text-align: right; }
mtable.cases > mtr > mtd,
mtable.left-align > mtr > mtd,
mtable > mtr > mtd.left-align,
mtable.aligned > mtr > mtd:nth-child(even),
math:is(:not([display])) > mtable.multiline-equation > mtr > mtd { justify-items: start; text-align: left; }
mtable.cases > mtr > mtd, mtable.aligned > mtr > mtd, mtable > mtr > mtd.flushed, mtable > mtr > mtd.left-flush { padding-left: 0; }
mtable.cases > mtr > mtd, mtable.aligned > mtr > mtd, mtable > mtr > mtd.flushed, mtable > mtr > mtd.right-flush { padding-right: 0; }
mtable { math-style: inherit; }
mtd { math-depth: auto-add; math-style: compact; math-shift: compact; }
mtable.multiline-equation > mtr > mtd { math-depth: inherit; math-style: inherit; math-shift: inherit; padding: 0; }
math > mtable.multiline-equation > mtr:not(:last-child) > mtd { padding-bottom: 0.5em; }
mfrac { padding-inline: 0; margin-inline: 0.1em; }
mover[accent="true" i] > :first-child { font-feature-settings: "dtls"; }
mover.dotted[accent="true" i] > :first-child { font-feature-settings: "dtls" 0; }
munder > :nth-child(2), munderover > :nth-child(2) { math-shift: compact; }
munder[accentunder="true" i] > :not(:first-child),
mover[accent="true" i] > :not(:first-child) { math-depth: inherit; math-style: inherit; math-shift: inherit; }

/* ---------- Figures, drawings, islands ---------- */

.figure, .island-figure { margin: 2em 0; }
.figure > .frame, .island-figure .island { display: flex; justify-content: center; }
.figure figcaption, .island-figure figcaption {
  max-width: 34em;
  margin: 0.7em auto 0;
  color: var(--fg-2);
  font-size: 0.9em;
}
.fig-label { font-weight: 700; }
.frame { max-width: 100%; overflow-x: auto; }
.frame svg { max-width: 100%; height: auto !important; }
/* Diagram colours follow the theme (palette in lib/config.typ). */
.frame [fill="#000000"] { fill: currentColor; }
.frame [stroke="#000000"] { stroke: currentColor; }
.frame [fill="#ffffff"] { fill: var(--bg); }
.frame [stroke="#ffffff"] { stroke: var(--bg); }
.frame [fill="#777777"] { fill: var(--c-muted); }
.frame [stroke="#777777"] { stroke: var(--c-muted); }
.frame [fill="#cccccc"] { fill: var(--c-faint); }
.frame [stroke="#cccccc"] { stroke: var(--c-faint); }
.frame [fill="#2b5c9e"] { fill: var(--c-blue); }
.frame [stroke="#2b5c9e"] { stroke: var(--c-blue); }
.frame [fill="#2f7d5b"] { fill: var(--c-green); }
.frame [stroke="#2f7d5b"] { stroke: var(--c-green); }
.frame [fill="#9a6a14"] { fill: var(--c-ochre); }
.frame [stroke="#9a6a14"] { stroke: var(--c-ochre); }
.frame [fill="#b03a2e"] { fill: var(--c-red); }
.frame [stroke="#b03a2e"] { stroke: var(--c-red); }

.island { position: relative; }
.js .island { min-height: var(--island-h, auto); }
.island.is-mounted > .island-fallback { display: none; }
.island-fallback { max-width: 100%; overflow-x: auto; }

/* ---------- Reference previews ---------- */

/* Hovering (or keyboard-focusing) a cross-reference shows the target's
   statement; see initPreviews in book.js. Sized like the text column, a
   little smaller than the text, and scrolls when the statement is long. */
.ref-preview {
  position: absolute;
  z-index: 30;
  width: max-content;
  max-width: min(32em, calc(100vw - 1rem));
  max-height: min(26em, 70vh);
  overflow: auto;
  overscroll-behavior: contain;
  padding: 0.75em 1em;
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  background: var(--bg-raised);
  color: var(--fg);
  box-shadow: 0 8px 28px rgb(0 0 0 / 0.14);
  font-size: 0.92em;
  line-height: 1.55;
  scrollbar-width: thin;
}
.ref-preview[hidden] { display: none; }
.ref-preview > .page { max-width: none; margin: 0; }
.ref-preview > .page > :first-child { margin-top: 0; }
.ref-preview > .page > :last-child { margin-bottom: 0; }
.ref-preview .env, .ref-preview .eq, .ref-preview .figure { margin: 0; }
.ref-preview-title { margin: 0 0 0.4em !important; font-weight: 700; }
.ref-preview-title .num { margin-right: 0.45em; color: var(--fg-3); font-weight: 400; }

/* ---------- Print ---------- */

@media print {
  .topbar, .book-nav, .page-toc, .pager, .reveal-controls, .exercise-filter, .practice, .skip-link, .env-toggle, .ref-preview { display: none !important; }
  .env-runin[hidden] { display: inline !important; content-visibility: visible !important; }
  .env-body[hidden] { display: block !important; content-visibility: visible !important; }
  .proof.is-folded { display: block; }
  .layout { display: block; }
  .page { max-width: none; }
  .js .proof .stage { display: block !important; }
  a { color: inherit; text-decoration: none; }
}
.technique-entry h3 a { color: inherit; text-decoration: none; }
.technique-entry h3 a:hover { text-decoration: underline; text-decoration-color: var(--rule-strong); }
.technique-meta { margin-top: -0.4em !important; color: var(--fg-3); font-size: 0.9em; }
