/* ------------------------------------------------------------------ *\
   Just Another LLM Introspective
   One stylesheet, no build step. Order: fonts, tokens, reset, layout,
   furniture, prose, code, search, responsive, print.

   Three rules this design commits to. Breaking any of them is what makes
   a page read as generated, so they are load-bearing:

     1. No shadows. Hairline rules and surface contrast carry all
        hierarchy. There is no --shadow token to reach for.
     2. Square. border-radius is 0 everywhere, with no exceptions.
     3. The accent is rationed to links, the current chapter marker and
        the focus ring. Nothing else - headings, kickers and part titles
        are ink, not colour.
     4. No uppercase. Labels are set in sentence case; the mono face and
        a muted ink are what mark them as metadata. Uppercase micro-labels
        with wide tracking are one of the clearest generated-site tells.

   Display type is Bitter 600 against Bitter 400 body. The reference
   systems cap display weight at 400, but they all pair TWO families -
   with a single family, weight is the only contrast available, so 600 is
   the deliberate exception. It stops at 600; 700+ is where a slab starts
   to shout.
\* ------------------------------------------------------------------ */

/* ---- Fonts (self-hosted latin subsets; see fonts/LICENSE.txt) ---- */

@font-face {
  font-family: 'Bitter';
  src: url('/fonts/bitter-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  /* optional, not swap: see the note above the fallback face. */
  font-display: optional;
}
@font-face {
  font-family: 'Bitter';
  src: url('/fonts/bitter-400-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  /* optional, not swap: see the note above the fallback face. */
  font-display: optional;
}
@font-face {
  font-family: 'Bitter';
  src: url('/fonts/bitter-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  /* optional, not swap: see the note above the fallback face. */
  font-display: optional;
}
/*
 * Why the Bitter faces use `font-display: optional` rather than `swap`.
 *
 * With `swap` the browser paints in a fallback and then swaps Bitter in, and
 * because the two fonts have different metrics the whole prose column reflows.
 * Lighthouse measured CLS 0.111 on the chapter page from exactly that, blamed
 * on "Web font loaded". `optional` uses Bitter only if it is ready before first
 * paint and never swaps it in later, so that shift cannot happen - on any
 * platform, without having to guess which fallback the reader has.
 *
 * The cost is that a first-time visitor on a slow connection reads one page in
 * the fallback serif. Both Bitter weights are preloaded and only 18 KB each, so
 * that window is usually met; and the next page is served from cache, so it is
 * at worst a one-page effect that corrects itself.
 *
 * The metric-matched fallback below is what makes that acceptable: when the
 * fallback is used, it occupies very nearly the same space as Bitter would.
 *
 * Metric-matched fallback: Georgia standing in for Bitter.
 * Derived from the two fonts' own metrics, not guessed:
 *   Bitter   unitsPerEm 1000, ascent 935, descent 265, lineGap 0, xHeight 528
 *   Georgia  unitsPerEm 2048, ascent 1878, descent 449, lineGap 0, xHeight 986
 *   size-adjust      = (528/1000) / (986/2048) = 109.7%
 *   ascent-override  = (935/1000) / 1.097      =  85.3%
 *   descent-override = (265/1000) / 1.097      =  24.2%
 *
 * Tuned for Georgia because that is the fallback actually present on Windows
 * and macOS. Where Georgia is absent the @font-face simply does not resolve and
 * the stack falls through to the next family, so this can only help.
 */
@font-face {
  font-family: 'Bitter Fallback';
  src: local('Georgia');
  size-adjust: 109.7%;
  ascent-override: 85.3%;
  descent-override: 24.2%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'IBM Plex Mono';
  src: url('/fonts/ibm-plex-mono-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  /* optional for the same reason as Bitter: Lighthouse named this face as a
     cause of the remaining CLS while it was still `swap`. Every self-hosted
     face on this site uses optional, so no font load can move the layout. */
  font-display: optional;
}

/* ---- Design tokens ---- */

/*
 * Dark by default. light-dark() takes the FIRST value when the used
 * colour scheme is light and the SECOND when it is dark, so the pair
 * order below is (light, dark) even though dark is this site's default.
 *
 * `color-scheme: dark` names ONLY dark, so the page is dark for everyone
 * on arrival - including visitors whose OS asks for light. That is
 * deliberate: this is a dark-first design with a visible toggle, not a
 * system-following one. (Listing `dark light` would let a light-set OS win,
 * which is not what "dark by default" means.)
 *
 * theme.js overrides by setting `color-scheme` on the root element, which
 * is all light-dark() reads - so there is exactly one mechanism, not a data
 * attribute and a media query duplicating each other.
 *
 * Baseline note: light-dark() is newly available (Chrome 123+, Firefox
 * 120+, Safari 17.5+) and reaches widely available 2026-11-13. Older
 * browsers drop the declaration and fall back to the plain colour
 * declared immediately above each one.
 */
:root {
  color-scheme: dark;

  /* One family for display and body. Bitter is a slab drawn for screen
     reading: large x-height, rectangular serifs, and the sturdiest
     option tested on a dark ground - which is what this site defaults to. */
  --font-body: 'Bitter', 'Bitter Fallback', Georgia, 'Times New Roman', serif;
  --font-display: 'Bitter', 'Bitter Fallback', Georgia, serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Grounds and ink. The neutrals carry a slight warm bias so they sit
     with the amber rather than fighting it - a pure grey reads as
     unconsidered. */
  --paper: #16161a;
  --paper: light-dark(#fbfaf8, #16161a);
  --paper-2: #1d1d22;
  --paper-2: light-dark(#f2efe9, #1d1d22);
  --ink: #e8e5de;
  --ink: light-dark(#1a1917, #e8e5de);
  --ink-2: #96918a;
  --ink-2: light-dark(#5e5a54, #96918a);
  --rule: #2b2b32;
  --rule: light-dark(#e2ded6, #2b2b32);
  --rule-strong: #43434d;
  --rule-strong: light-dark(#c7c1b6, #43434d);

  /* The one accent. Links, current-chapter marker, focus ring. */
  --accent: #e2a468;
  --accent: light-dark(#8f4e12, #e2a468);
  --mark: #4a3a16;
  --mark: light-dark(#f8e7b4, #4a3a16);

  --measure: 34em;
  --sidebar: 16.5rem;
  --topbar-h: 3.25rem;
}

/* ---- Reset / base ---- */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
}

img,
svg {
  max-width: 100%;
  height: auto;
}

a {
  color: var(--accent);
  text-underline-offset: 0.16em;
  text-decoration-thickness: from-font;
}

a:hover {
  text-decoration-thickness: 2px;
}

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

button {
  font: inherit;
  color: inherit;
  border-radius: 0;
}

/* ---- Helpers ---- */

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

.skiplink {
  position: absolute;
  left: 0.5rem;
  top: -4rem;
  z-index: 20;
  padding: 0.6rem 1rem;
  background: var(--paper);
  border: 1px solid var(--accent);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-decoration: none;
  transition: top 0.15s ease;
}

.skiplink:focus {
  top: 0.5rem;
}

/* Uppercase mono labels: kickers, part names, meta. Ink, never accent. */
.label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--ink-2);
}

/* ---- Topbar ---- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  /* Must wrap: at 200% text zoom on a narrow viewport these controls are
     wider than the screen, and a non-wrapping row would force the whole
     page to scroll sideways (WCAG 1.4.4 / 1.4.10). */
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  min-height: var(--topbar-h);
  padding: 0.5rem 1.25rem;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}

.brand {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-decoration: none;
  flex: 0 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.brand:hover {
  color: var(--ink);
  text-decoration: underline;
}

.topbar__tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-left: auto;
  /* The controls keep their size; the brand is what gives way. */
  flex: 0 0 auto;
}

.themetoggle,
.navtoggle {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 2rem;
  padding: 0 0.6rem;
  background: transparent;
  border: 1px solid var(--rule-strong);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
  cursor: pointer;
}

.themetoggle {
  width: 2rem;
  padding: 0;
}

.themetoggle:hover,
.navtoggle:hover {
  color: var(--ink);
  border-color: var(--ink-2);
}

.themetoggle__icon {
  width: 1rem;
  height: 1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
}

/* aria-pressed=true means dark is active, so show the moon. */
.themetoggle__icon--moon,
.themetoggle[aria-pressed='true'] .themetoggle__icon--sun {
  display: none;
}

.themetoggle[aria-pressed='true'] .themetoggle__icon--moon {
  display: block;
}

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

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  max-width: 76rem;
  margin: 0 auto;
  padding: 0 1.25rem;
}

.main {
  min-width: 0;
  padding: 2.5rem 0 4rem;
}

.main:focus {
  outline: none;
}

/* ---- Sidebar / contents ---- */

.sidebar {
  padding: 1.5rem 0 0.5rem;
}

.contents__title {
  margin: 0;
  padding-bottom: 0.85rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.contents__part {
  margin-bottom: 1.5rem;
}

/* A paragraph, not a heading: the sidebar precedes <main>, so a heading
   here would land before the page h1 and break the outline. */
.contents__part-title {
  margin: 0 0 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.contents__list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-left: 1px solid var(--rule);
}

.contents__link {
  display: block;
  padding: 0.32rem 0 0.32rem 0.85rem;
  margin-left: -1px;
  border-left: 2px solid transparent;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--ink-2);
  text-decoration: none;
}

.contents__link:hover {
  color: var(--ink);
  border-left-color: var(--rule-strong);
}

/* One of the three sanctioned uses of the accent. */
.contents__link.is-current {
  color: var(--accent);
  border-left-color: var(--accent);
}

/* ---- Cover page ---- */

.cover {
  max-width: 40rem;
  padding-bottom: 2.75rem;
  border-bottom: 1px solid var(--rule);
}

.cover__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.95rem, 1.25rem + 2.8vw, 2.9rem);
  line-height: 1.04;
  letter-spacing: -0.024em;
  text-wrap: balance;
  overflow-wrap: break-word;
}

.cover__tagline {
  margin: 1rem 0 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.25rem;
  font-style: italic;
  line-height: 1.35;
  color: var(--ink-2);
  text-wrap: pretty;
}

.cover__standfirst {
  margin-top: 1.75rem;
  font-size: 1.0625rem;
}

.cover__standfirst p {
  margin: 0 0 1rem;
  text-wrap: pretty;
}

.cover__standfirst p:last-child {
  margin-bottom: 0;
}

.cover__meta {
  margin: 2rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

/* ---- Contents listing on the cover ---- */

.toc {
  max-width: 44rem;
  margin-top: 3.25rem;
}

.part + .part {
  margin-top: 3.25rem;
}

.part__title {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  margin: 0 0 0.6rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.4rem;
  line-height: 1.2;
  letter-spacing: -0.014em;
}

/* Part numbers are real information - the book is ordered - so they stay.
   Ink, not accent: the accent is rationed. */
.part__number {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.part__summary {
  margin: 0 0 1.5rem;
  max-width: var(--measure);
  color: var(--ink-2);
  text-wrap: pretty;
}

.part__chapters {
  margin: 0;
  padding: 0;
  list-style: none;
}

.part__chapter {
  padding: 1rem 0;
  border-top: 1px solid var(--rule);
}

.part__chapter:last-child {
  border-bottom: 1px solid var(--rule);
}

.part__link {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.1rem;
  line-height: 1.25;
  letter-spacing: -0.014em;
  color: var(--ink);
  text-decoration: none;
}

.part__link:hover {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.part__blurb {
  display: block;
  margin-top: 0.35rem;
  max-width: var(--measure);
  color: var(--ink-2);
  font-size: 0.9688rem;
  line-height: 1.6;
  text-wrap: pretty;
}

/* ---- Chapter ---- */

.chapter__head {
  max-width: 40rem;
  padding-bottom: 1.85rem;
  border-bottom: 1px solid var(--rule);
}

.chapter__part {
  margin: 0 0 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.chapter__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.75rem, 1.2rem + 2.1vw, 2.4rem);
  line-height: 1.08;
  letter-spacing: -0.016em;
  text-wrap: balance;
}

.chapter__summary {
  margin: 0.9rem 0 0;
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--ink-2);
  text-wrap: pretty;
}

.chapter__updated {
  margin: 1.35rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

/* ---- On this page ---- */

.onpage {
  max-width: var(--measure);
  margin: 2.25rem 0 0;
  padding: 1rem 0 1rem 1.15rem;
  border-left: 1px solid var(--rule-strong);
}

.onpage__title {
  margin: 0 0 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.onpage__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.3rem;
}

.onpage__list a {
  font-size: 0.9375rem;
  color: var(--ink-2);
  text-decoration: none;
}

.onpage__list a:hover {
  color: var(--ink);
  text-decoration: underline;
}

/* ---- Prose ---- */

.prose {
  max-width: var(--measure);
  margin-top: 2.5rem;
  /* Long tokens - URLs, identifiers - break instead of forcing a scroll. */
  overflow-wrap: break-word;
}

.prose > * + * {
  margin-top: 1.15em;
}

.prose p {
  text-wrap: pretty;
}

.prose h2,
.prose h3,
.prose h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
  scroll-margin-top: calc(var(--topbar-h) + 1rem);
}

.prose h2 {
  margin-top: 2.75em;
  padding-top: 1.35rem;
  border-top: 1px solid var(--rule);
  font-size: 1.45rem;
}

.prose h3 {
  margin-top: 2.1em;
  font-size: 1.2rem;
}

/* Below h3 the display face stops helping; a mono label reads as the
   sub-level it is without adding a fourth type size. */
.prose h4 {
  margin-top: 1.85em;
  font-family: var(--font-mono);
  font-size: 0.875rem;
  letter-spacing: 0;
  color: var(--ink-2);
}

.prose .headerlink {
  margin-left: 0.4rem;
  opacity: 0;
  font-family: var(--font-mono);
  font-size: 0.7em;
  text-decoration: none;
  color: var(--ink-2);
}

.prose h2:hover .headerlink,
.prose h3:hover .headerlink,
.prose h4:hover .headerlink,
.prose .headerlink:focus-visible {
  opacity: 1;
}

.prose ul,
.prose ol {
  padding-left: 1.4rem;
}

.prose li + li {
  margin-top: 0.45em;
}

.prose li > ul,
.prose li > ol {
  margin-top: 0.45em;
}

.prose li::marker {
  color: var(--ink-2);
}

.prose blockquote {
  margin-left: 0;
  margin-right: 0;
  padding: 0.15rem 0 0.15rem 1.25rem;
  border-left: 2px solid var(--rule-strong);
  color: var(--ink-2);
  font-style: italic;
}

.prose blockquote p {
  margin: 0.5em 0;
}

.prose hr {
  margin: 2.75em 0;
  border: 0;
  border-top: 1px solid var(--rule);
}

.prose strong {
  font-weight: 600;
}

.prose mark {
  background: var(--mark);
  color: var(--ink);
  padding: 0 0.15em;
}

/* Wide content scrolls inside its own box; the page body never scrolls.
   The wrapper carries the overflow so the table keeps `display: table` and
   its native semantics - a `display: block` table loses its table role in
   some screen readers. The build adds the wrapper and its tabindex. */
.scroller {
  overflow-x: auto;
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

.prose th,
.prose td {
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--rule);
  text-align: left;
  vertical-align: top;
}

.prose th {
  font-weight: 400;
  font-size: 0.8125rem;
  color: var(--ink-2);
  border-bottom-color: var(--rule-strong);
}

/* ---- Callouts (Markdown `!!! note` blocks) ---- */

.prose .admonition {
  padding: 1rem 0 1rem 1.25rem;
  border-left: 2px solid var(--rule-strong);
}

.prose .admonition > * + * {
  margin-top: 0.75em;
}

.prose .admonition-title {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.prose .admonition p {
  color: var(--ink-2);
}

/* A warning is semantic state, not decoration, so it is allowed its own
   colour - semantic colour is separate from the rationed accent. */
.prose .admonition.warning {
  border-left-color: light-dark(#a8442b, #e08a6e);
}

.prose .admonition.warning .admonition-title {
  color: light-dark(#a8442b, #e08a6e);
}

/* ---- Code ---- */

.prose code {
  font-family: var(--font-mono);
  font-size: 0.84em;
  background: var(--paper-2);
  padding: 0.14em 0.34em;
  word-break: break-word;
}

.prose pre {
  margin: 0;
  padding: 1rem 1.15rem;
  overflow-x: auto;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  font-size: 0.8125rem;
  line-height: 1.65;
}

.prose pre code {
  background: none;
  padding: 0;
  font-size: 1em;
}

.prose .highlight {
  position: relative;
  margin-top: 1.15em;
}

.prose .has-copybtn {
  position: relative;
}

.copybtn {
  position: absolute;
  top: 0;
  right: 0;
  padding: 0.25rem 0.55rem;
  background: var(--paper-2);
  border: 0;
  border-left: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.02em;
  color: var(--ink-2);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.has-copybtn:hover .copybtn,
.copybtn:focus-visible {
  opacity: 1;
}

.copybtn:hover {
  color: var(--ink);
}

.copybtn.is-done {
  color: var(--ink);
  opacity: 1;
}

/* Pygments, rendered at build time - no highlighter ships to the browser.
   Nesting keeps this from being 100 lines of repeated prefixes. */
.highlight {
  & .c,
  & .c1,
  & .cm,
  & .cs {
    color: light-dark(#665f52, #928d80);
    font-style: italic;
  }

  & .k,
  & .kn,
  & .kd,
  & .kc,
  & .kr,
  & .kt,
  & .nb,
  & .bp {
    color: light-dark(#8a3fa0, #cf9ada);
  }

  & .s,
  & .s1,
  & .s2,
  & .sb,
  & .sd,
  & .se,
  & .sh,
  & .si,
  & .sx,
  & .sr {
    color: light-dark(#2f7048, #8ecb9f);
  }

  & .m,
  & .mi,
  & .mf,
  & .mh,
  & .mo,
  & .il {
    color: light-dark(#96501c, #ddab78);
  }

  & .nf,
  & .nd,
  & .nc,
  & .nn,
  & .ne {
    color: light-dark(#1f5fa8, #7db2e8);
  }

  & .nv,
  & .vi,
  & .vg,
  & .err,
  & .gd {
    color: light-dark(#a8442b, #e0907a);
  }

  & .o,
  & .ow,
  & .p {
    color: light-dark(#5b564c, #a9a49a);
  }

  & .gi {
    color: light-dark(#2f7048, #8ecb9f);
  }
}

/* ---- Footnotes ---- */

.prose .footnote {
  margin-top: 3.25rem;
  padding-top: 1.35rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9375rem;
  color: var(--ink-2);
}

.prose .footnote hr {
  display: none;
}

.prose .footnote ol {
  padding-left: 1.2rem;
}

/* ---- Pager ---- */

.pager {
  display: grid;
  gap: 0;
  max-width: var(--measure);
  margin-top: 3.5rem;
  border-top: 1px solid var(--rule);
}

.pager__link {
  display: block;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
}

.pager__link:hover .pager__title {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.pager__dir {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.pager__title {
  display: block;
  margin-top: 0.25rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.1rem;
  line-height: 1.25;
  letter-spacing: -0.012em;
  color: var(--ink);
}

/* ---- Search ---- */

.search {
  position: relative;
}

.search__input {
  width: 8rem;
  min-width: 0;
  max-width: 100%;
  height: 2rem;
  padding: 0 0.6rem;
  background: transparent;
  border: 1px solid var(--rule-strong);
  border-radius: 0;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.01em;
  color: var(--ink);
  transition: width 0.16s ease;
  -webkit-appearance: none;
  appearance: none;
}

.search__input::placeholder {
  color: var(--ink-2);
  letter-spacing: 0.02em;
}

.search__input:focus {
  width: 14rem;
}

.search__results {
  position: absolute;
  top: calc(100% + 0.35rem);
  right: 0;
  z-index: 15;
  width: min(30rem, calc(100vw - 2.5rem));
  max-height: min(26rem, 70vh);
  overflow-y: auto;
  background: var(--paper);
  border: 1px solid var(--rule-strong);
}

.search__hit {
  display: block;
  padding: 0.7rem 0.85rem;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: var(--ink);
}

.search__hit:last-child {
  border-bottom: 0;
}

.search__hit:hover,
.search__hit.is-active {
  background: var(--paper-2);
}

.search__where {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.search__part {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.02em;
  color: var(--ink-2);
}

.search__snippet {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--ink-2);
}

.search__snippet mark {
  background: var(--mark);
  color: var(--ink);
}

.search__empty {
  margin: 0;
  padding: 0.9rem 0.85rem;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

/* ---- Footer ---- */

.sitefoot {
  max-width: 76rem;
  margin: 0 auto;
  padding: 2rem 1.25rem 3.5rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}

.sitefoot__line {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: -0.012em;
  color: var(--ink);
}

.sitefoot__meta {
  margin: 0.4rem 0 0;
}

/* ---- Responsive ---- */

/* Mobile sidebar visibility is owned by this media query, never by a JS class.
   It used to be a `.has-navtoggle` class that book.js added on load, which meant
   the sidebar painted and then collapsed once the deferred script ran - a large
   layout shift on any connection slow enough to paint first (Lighthouse mobile
   measured CLS 0.202 from exactly this). CSS decides; JS only toggles is-open. */
@media (max-width: 59.999rem) {
  .sidebar {
    display: none;
  }

  .sidebar.is-open {
    display: block;
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--rule);
  }
}

@media (min-width: 60rem) {
  .layout {
    grid-template-columns: var(--sidebar) minmax(0, 1fr);
    gap: 4rem;
    padding: 0 2rem;
  }

  .sidebar {
    display: block;
    position: sticky;
    top: var(--topbar-h);
    align-self: start;
    max-height: calc(100vh - var(--topbar-h));
    overflow-y: auto;
    padding: 2.75rem 0.5rem 2rem 0;
  }

  .navtoggle {
    display: none;
  }

  .topbar,
  .sitefoot {
    padding-inline: 2rem;
  }

  .pager {
    grid-template-columns: 1fr 1fr;
    column-gap: 2rem;
  }

  .main {
    padding-top: 3rem;
  }
}

/* Touch targets. WCAG 2.2 SC 2.5.8 asks for 24 CSS px minimum; the nav lists
   are the only things on the page that came in under it. Padding rather than
   min-height, so the text stays where the rule expects it. */
@media (hover: none) and (pointer: coarse) {
  .contents__link {
    padding-top: 0.55rem;
    padding-bottom: 0.55rem;
  }

  .onpage__list {
    gap: 0.15rem;
  }

  .onpage__list a {
    display: block;
    padding: 0.4rem 0;
  }

  .pager__link {
    padding: 1.35rem 0;
  }

  /* Hover reveals it on a pointer device; on touch there is no hover, so it
     would be a permanently invisible tab stop. Take it out of the flow. */
  .prose .headerlink {
    display: none;
  }

  /* No hover to reveal it, so show it and give it a real target. */
  .copybtn {
    opacity: 1;
    padding: 0.4rem 0.7rem;
  }
}

/* Below this width the topbar is deliberately two rows: the brand takes a full
   row and the controls sit under it.
   A wrappable flex container wraps before it shrinks its items - that is the
   flexbox algorithm, and it is why min-width:0 on the brand could not prevent
   this - so on a narrow screen the row wrapped only once the mono face loaded
   and widened the controls, changing the topbar's height and pushing the whole
   page down 27px (measured CLS 0.111, confirmed in the trace: .topbar__tools
   moved from x279,y10 to x184,y38, .layout from y52 to y79). Wrapping from the
   start makes the height independent of font metrics, so the shift cannot
   happen. It costs about 32px of vertical space and keeps flex-wrap available
   for the 200%-zoom reflow case. */
@media (max-width: 40rem) {
  .brand {
    flex: 1 0 100%;
  }

  .topbar__tools {
    margin-left: 0;
  }

  /* The tools row is left-aligned at this width, so anchoring the results panel
     to the input's right edge threw it off the left of the screen (measured
     left: -186px at 390px). Anchor left instead; the width already resolves to
     the content width, so it lands inside the topbar's padding on both sides.
     This breakpoint must stay equal to the one above - the anchor depends on
     which way the tools row is aligned. */
  .search__results {
    left: 0;
    right: auto;
  }
}

@media (max-width: 34rem) {
  body {
    font-size: 1rem;
  }

  .brand {
    font-size: 0.8125rem;
  }

  .search__input {
    width: 5.5rem;
  }

  .search__input:focus {
    width: 9rem;
  }
}

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---- View transitions ----
   Chapter-to-chapter navigation cross-fades. Baseline across Chrome 130+,
   Safari 18+ and Firefox 130+; browsers without it simply navigate. */
@view-transition {
  navigation: auto;
}

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 180ms;
  }
}

/* ---- Print (it is a book, after all) ---- */

@media print {
  .topbar,
  .sidebar,
  .onpage,
  .pager,
  .skiplink,
  .copybtn,
  .sitefoot__meta {
    display: none;
  }

  body {
    background: #fff;
    color: #000;
    font-size: 11pt;
  }

  .layout {
    display: block;
    padding: 0;
  }

  .prose,
  .chapter__head {
    max-width: none;
  }

  .prose pre {
    white-space: pre-wrap;
    word-break: break-word;
  }

  a::after {
    content: ' (' attr(href) ')';
    font-size: 0.85em;
    color: #444;
  }

  .prose h2,
  .prose h3 {
    break-after: avoid;
  }
}
