/* menu.css — the kiosk overlay. Volume tint, big numeral + title,
   lateral nav strips with target numerals, recessed close button,
   and the small caption beneath the slipcase on the home view. */

/* Hide the original 3D viewer's toolbar/dice/caption; the live slipcase
   is the only thing we keep from the source view. */
.modes,
.dice-toggle,
.caption { display: none !important; }

body { background: var(--paper); overflow: hidden; }

/* Mobile-portrait scale-up. The bundler's __fit() math leaves the slipcase
   small on a narrow viewport; wrapping .scene and scaling the wrap makes
   the slipcase read about 50% larger on phones held in portrait. */
#webapp-scale {
  width: 100%; height: 100%;
  position: absolute; inset: 0;
}
@media (max-width: 600px) and (orientation: portrait) {
  #webapp-scale {
    transform: scale(1.55);
    transform-origin: center center;
  }
}

/* Tiny build-version pill, top-right of the splash. Subtle by design —
   a debugging affordance, not a UI element. Hidden when a menu, reader,
   or any overlay is open so it never competes with real content. */
#webapp-version {
  position: fixed;
  top: max(env(safe-area-inset-top, 0px), 10px);
  right: max(env(safe-area-inset-right, 0px), 12px);
  z-index: 4;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: .12em;
  text-transform: lowercase;
  color: rgba(43, 51, 64, .35);
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}
#webapp-version:empty { display: none; }
/* The standalone version pill is now redundant — the home-view RESET
   button shows the same VERSION (and accepts a tap for a nuclear cache
   wipe). Hide the pill on every surface to avoid double-indicators. */
#webapp-version { display: none !important; }

/* Spec line below the slipcase on the home view. Three lines of all-caps
   Mercure Transcript — the same typewriter-style face the per-volume
   colophon specs use, so "10.1\" SLIPCASE / FIVE 10\" VOLUMES / RESET"
   carries the same production-note voice across the whole app. The
   third line (RESET) is the only clickable word — styled as plain text. */
#webapp-caption {
  position: fixed;
  left: 50%;
  bottom: clamp(20px, 4vh, 56px);
  transform: translateX(-50%);
  text-align: center;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-weight: 400;
  font-size: 9.5px;
  letter-spacing: .14em;
  line-height: 1.95;
  text-transform: uppercase;
  color: rgba(43, 51, 64, .65);
  pointer-events: none;
  z-index: 5;
  user-select: none;
  -webkit-user-select: none;
}
#webapp-caption #webapp-reset {
  /* RESET matches the menus' CLOSE button — HN Medium 9px / .22em — so
     the home-view click target reads in the same voice as its sibling
     across the per-volume menus. The spec lines above stay in Mercure
     Transcript (the home-view colophon voice). */
  display: inline-block;
  margin-top: .35em;
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: .22em;
  cursor: pointer;
  pointer-events: auto;
  transition: color .15s ease;
}
#webapp-caption #webapp-reset:hover,
#webapp-caption #webapp-reset:focus {
  color: rgba(43, 51, 64, .9);
  outline: none;
}

/* Mobile: stack each spec line as label + dim across two rows so the
   colophon reads:
       1 SLIPCASE
       10.2" x 10.2" x 2.4"
       5 BOOKS
       10" x 10"
   …with a clear visual break between the two groupings, and a generous
   gap before RESET. */
@media (max-width: 700px) {
  #webapp-caption {
    line-height: 1.55;
  }
  #webapp-caption .cap-line {
    display: block;
  }
  /* Each grouping (label + dim) sits tight; the SECOND grouping gets a
     wider top margin so the eye reads "1 SLIPCASE + 10.1" as one unit
     and "5 BOOKS + 10x10" as a second. */
  #webapp-caption .cap-line + .cap-line {
    margin-top: 1.4em;
  }
  #webapp-caption .cap-label,
  #webapp-caption .cap-dim {
    display: block;
  }
  #webapp-caption .cap-dim {
    opacity: .82;
  }
  #webapp-caption #webapp-reset {
    margin-top: 2em;        /* generous breathing before the action */
  }
}

/* ===== First-visit intro / loading sequence =====
   A near-empty overlay that hosts the Skip button while the 3D slipcase
   reveals + makes one slow 360° turn. The overlay itself is transparent
   so the rotating scene shows through; its only job is to host the
   Skip affordance and capture stray taps. menu.js adds body.intro-on
   and #webapp-intro.is-on at startup on first visit, then removes both
   when the rotation finishes (or the user taps Skip), at which point
   showTintFor(0) fades up the Vol 0 menu. */
#webapp-intro {
  position: fixed;
  inset: 0;
  z-index: 55;            /* above the 3D scene, below the tint menu (60) */
  pointer-events: none;   /* no need to block scene gestures by default */
  opacity: 0;
  visibility: hidden;
  transition: opacity .6s ease, visibility 0s linear .6s;
}
#webapp-intro.is-on {
  opacity: 1;
  visibility: visible;
  pointer-events: none;   /* still passthrough — only Skip catches input */
  transition: opacity .6s ease, visibility 0s linear 0s;
}
.intro-skip {
  position: absolute;
  top: clamp(14px, 2vh, 24px);
  right: clamp(18px, 2vw, 28px);
  padding: .55em 1.2em;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-weight: 400;
  font-size: clamp(11px, 0.95vw, 13px);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #11161e;
  background: color-mix(in srgb, var(--paper) 88%, white 12%);
  border: 1px solid color-mix(in srgb, #11161e 28%, transparent);
  border-radius: 999px;
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
  transition: background .2s ease, border-color .2s ease, opacity .2s ease;
  opacity: .8;
}
.intro-skip:hover,
.intro-skip:focus {
  background: color-mix(in srgb, var(--paper) 70%, white 30%);
  border-color: color-mix(in srgb, #11161e 56%, transparent);
  opacity: 1;
  outline: none;
}
/* While the intro is playing, suppress the .scene's normal pointer
   handlers so the user's taps don't bump the rotation off course.
   The Skip button still catches its own clicks (pointer-events:auto). */
body.intro-on .scene {
  pointer-events: none;
}

/* ===== Volume menu overlay ===== */

#webapp-tint {
  position: fixed;
  inset: 0;
  z-index: 60;
  opacity: 0;
  visibility: hidden;     /* hides from pointer events even if a child has
                              pointer-events:auto — keeps the closed menu
                              from intercepting mouse drags on the slipcase. */
  background: var(--pg-3);
  transition:
    opacity .35s ease,
    background .35s ease,
    visibility 0s linear .35s;   /* delay visibility:hidden until fade out finishes */
}
#webapp-tint.is-on {
  opacity: 1;
  visibility: visible;
  transition:
    opacity .35s ease,
    background .35s ease,
    visibility 0s linear 0s;     /* show immediately on open */
}

/* While a menu overlay is open, hide the underlying 3D scene entirely and
   block any pointer events on it. Prevents weirdness on Android where a
   pinch-zoomed slipcase + a menu overlay can produce ghost gestures and
   stray scrolling beneath the overlay. */
body.menu-open .scene,
body.menu-open #webapp-scale,
body.menu-open #webapp-caption {
  visibility: hidden;
  pointer-events: none;
}

/* Static badge: numeral + title + 2D cover thumb + colophon specs, fixed in
   the top-left, no animation. Sized as a corner wayfinding mark — substantial
   but never viewport-dominating. The TOC/content panel sits cleanly below it. */
#webapp-tint .cover-stack {
  position: absolute;
  left: clamp(120px, 12vw, 200px);
  top: clamp(36px, 5vh, 72px);     /* clear of the left nav strip */
  transform-origin: top left;
  text-align: left;
  pointer-events: none;
  /* Vertical layout: numeral, cover thumb, specs stack tightly with a
     small consistent gap between each. The gap is the same on both
     sides of the cover thumb so the three pieces read as one composed
     mark rather than three loosely-floating blocks. */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
#webapp-tint .cover-badge {
  /* The badge — big LustSpine numeral + small HN UltraLight title —
     was retired across the board: Vols 1–5 now identify themselves
     via the cover-thumb's BACK face (small numeral + title + barcode)
     instead of carrying a redundant giant numeral above the thumb,
     and Vol 0 (the slipcase home) never had a numeral to display.
     Hiding it entirely lets the cover-thumb slide up to the top of
     the cover-stack and take the badge's old position. */
  display: none;
}
#webapp-tint .cover-num {
  font-family: "LustSpine", "Didot", serif;
  font-size: clamp(180px, 22vw, 320px);
  line-height: 1;
  letter-spacing: 0;
}
#webapp-tint .cover-title {
  font-family: "HN UltraLight", "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(28px, 2.6vw, 44px);
  letter-spacing: .08em;
  margin-top: -.06em;
}

/* ===== 2D cover thumb (DESKTOP) =====
   A flippable card whose front mirrors the 3D book's front cover (per-volume
   tint + cover-art tally multiplied) and whose back mirrors the printed back
   cover (LustSpine numeral + HN UltraLight title + EAN-13 barcode). Single
   tap on the card flips it. Vol 4 inverts the front art (Opposites) and
   inks its back numeral/title/barcode in white the way the printed book does.
   Hidden on mobile portrait — replaced there by the "Cover image" link. */
#webapp-tint .cover-thumb {
  position: relative;
  /* Scaled down ~25% from the original clamp(160px, 13vw, 220px) so
     the left column reads as a quieter sidebar rather than a hero
     element, freeing horizontal real estate for the body column. */
  width: clamp(120px, 9.75vw, 165px);
  aspect-ratio: 1 / 1;
  /* The negative top margin that used to pull the thumb up under the
     LustSpine numeral is gone now that the badge has been retired —
     the thumb is the first child of the cover-stack and sits directly
     at the cover-stack's top. */
  margin-top: 0;
  perspective: 900px;
  background: transparent;
  pointer-events: auto;
  flex-shrink: 0;
}
#webapp-tint .cover-thumb-card {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transform: rotateY(0deg);
  transition: transform .8s cubic-bezier(.4, .1, .2, 1);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  outline: none;
}
#webapp-tint .cover-thumb-card.is-flipped {
  transform: rotateY(180deg);
}
#webapp-tint .cover-thumb-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  background: var(--v3);   /* fallback */
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .12),
    0 1px 2px rgba(0, 0, 0, .18),
    0 6px 14px rgba(0, 0, 0, .14);
}
#webapp-tint .cover-thumb-front { transform: rotateY(0deg); }
#webapp-tint .cover-thumb-back  { transform: rotateY(180deg); }

/* Per-volume tint applied to BOTH faces. Vol 0 (the slipcase home) is
   a clean white card on the front carrying the cover-art tally
   (matching the printed slipcase front), and flips to the hand-art
   photograph on the back. Kept 2D and consistent with the per-volume
   menus rather than trying to embed the live 3D slipcase. */
#webapp-tint[data-n="0"] .cover-thumb-face { background: #ffffff; }
/* Vol 0 front: ink the tally at full opacity so the slashes read as
   solid black on the white card (the multiply blend keeps the white
   parts of the PNG transparent against the white face). */
#webapp-tint[data-n="0"] .cover-thumb .cover-thumb-ink::after {
  opacity: 1;
}
#webapp-tint[data-n="1"] .cover-thumb-face { background: var(--v1); }
#webapp-tint[data-n="2"] .cover-thumb-face { background: var(--v2); }
#webapp-tint[data-n="3"] .cover-thumb-face { background: var(--v3); }
#webapp-tint[data-n="4"] .cover-thumb-face { background: var(--v4); }
#webapp-tint[data-n="5"] .cover-thumb-face { background: var(--v5); }

/* Vol 0 BACK face — the slipcase's "reverse side" carries the hand-art
   photograph (the project's signature image) plus the small EAN-13
   barcode pinned to the bottom-center, mirroring the printed slipcase
   back. Hide the LustSpine numeral + HN UltraLight title that the
   per-volume backs carry — there's no single "volume number" for the
   slipcase as a whole, the hand image IS the identity. The salmon
   fallback shows through any transparent edges of the JPG. */
#webapp-tint[data-n="0"] .cover-thumb-back {
  background: url("../img/hand-art.jpg") center/cover no-repeat var(--paper);
}
#webapp-tint[data-n="0"] .cover-thumb-back .cover-thumb-back-stack {
  display: none;
}

/* Front: cover-art tally multiplied over the tint. */
#webapp-tint .cover-thumb .cover-thumb-ink {
  position: absolute;
  inset: 0;
  background: inherit;
}
#webapp-tint .cover-thumb .cover-thumb-ink::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../img/cover-art.png") center/cover no-repeat;
  mix-blend-mode: multiply;
  opacity: .72;
}
/* Vol 4 — Opposites — inverts the tally art to flat white over the gradient. */
#webapp-tint[data-n="4"] .cover-thumb .cover-thumb-ink::after {
  filter: invert(1);
  mix-blend-mode: screen;
  opacity: 1;
}

/* Back face content — numeral + title centered above middle, barcode bottom.
   All sized to match the cover-thumb's 75% scaled-down width: numeral
   from clamp(110, 9vw, 150) → clamp(82, 6.75vw, 112), title from
   clamp(9, 0.7vw, 11) → clamp(7, 0.52vw, 8.5), barcode width from
   clamp(28, 2.2vw, 36) → clamp(21, 1.65vw, 27). The back-stack's
   anchor moves up to top:38% so the (smaller) numeral and title clear
   the (slightly higher) barcode at the bottom — the previous values
   were sized to a 160-220px thumb and let the title overlap the
   barcode once the thumb shrank to 120-165px. */
#webapp-tint .cover-thumb-back-stack {
  position: absolute;
  /* Bumped back to top:42% — at 36% the LustSpine numeral was
     practically touching the upper rim. 42% gives it real headroom
     above while still leaving plenty of room for the barcode at
     bottom:8%. */
  left: 50%; top: 42%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
}
#webapp-tint .cover-thumb-back-num {
  font-family: "LustSpine", "Didot", serif;
  /* Down 4px from clamp(82, 6.75vw, 112) per visual review — gives the
     stack a touch more headroom in the small thumbnail. */
  font-size: clamp(78px, 6.45vw, 108px);
  line-height: 1;
}
#webapp-tint .cover-thumb-back-title {
  font-family: "HN UltraLight", "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  /* Up 2px from clamp(7, 0.52vw, 8.5) — title now reads cleanly under
     the (slightly smaller) numeral. */
  font-size: clamp(9px, 0.65vw, 10.5px);
  letter-spacing: .06em;
  line-height: 1;
  /* Pull the title closer to the numeral — first −5px, then another
     −3px on a second visual review, leaves the title nestled just
     under the numeral while still clearing the bottom-anchored
     barcode. */
  margin-top: calc(1.1em - 8px);
  white-space: nowrap;
}
#webapp-tint .cover-thumb-back-barcode {
  position: absolute;
  left: 50%;
  /* Pulled back to bottom:8% — sits closer to the lower rim, freeing
     vertical room for the title above. The barcode reads as the
     foot-of-page mark the printed slipcase carries; tighter to the
     bottom feels right. */
  bottom: 8%;
  transform: translateX(-50%);
  pointer-events: none;
}
#webapp-tint .cover-thumb-back-barcode svg {
  /* Sized to match the printed back cover's barcode-to-page ratio
     (~17%), scaled down 25% with the rest of the back face. */
  display: block;
  width: clamp(21px, 1.65vw, 27px);
  height: auto;
}
/* Per-volume back ink — vols 1, 2, 3, 5 use the slipcase --vN-d dark variant
   that the printed book carries; Vol 4 reverses to flat white. */
#webapp-tint[data-n="1"] .cover-thumb-back-num,
#webapp-tint[data-n="1"] .cover-thumb-back-title { color: var(--v1-d); }
#webapp-tint[data-n="2"] .cover-thumb-back-num,
#webapp-tint[data-n="2"] .cover-thumb-back-title { color: var(--v2-d); }
#webapp-tint[data-n="3"] .cover-thumb-back-num,
#webapp-tint[data-n="3"] .cover-thumb-back-title { color: var(--v3-d); }
#webapp-tint[data-n="4"] .cover-thumb-back-num,
#webapp-tint[data-n="4"] .cover-thumb-back-title { color: #ffffff; }
#webapp-tint[data-n="5"] .cover-thumb-back-num,
#webapp-tint[data-n="5"] .cover-thumb-back-title { color: var(--v5-d); }

/* (The full-screen cover-image overlay was removed — on every
   viewport the inline cover-thumb itself shows + flips, so a
   separate full-screen lightbox of the cover became redundant.) */
/* Volume title ("A Fable", "Some Quilts", "The Question", etc.) — a
   block-level header in HN Thin that sits inside .cover-content as its
   first child, so it always reads as "below the cover image and above
   the description" regardless of viewport. Injected by menu.js when
   each volume's content panel is rendered. */
#webapp-tint .cover-volume-title {
  display: block;
  font-family: "HN Thin", "HN UltraLight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  /* Per-volume titles ("A Fable", "Some Quilts", "The Question",
     "Opposites", "Appendix") read as the right-column heading on
     desktop — bumped ~50% from the previous clamp(22, 2.2vw, 36) to
     clamp(33, 3.3vw, 54) so they hold the column's top with the
     authority a section title deserves. The Vol 0 project title has
     its own size in .cover-volume-title-project below and is
     untouched by this bump. */
  font-size: clamp(33px, 3.3vw, 54px);
  letter-spacing: .04em;
  line-height: 1.15;
  margin: 4em 0 2em;
  color: inherit;
  opacity: .9;
}
/* Desktop: snug the volume heading to the top of its column. The
   heading sits beside the cover-stack rather than below it, so any
   top margin opens an awkward empty gap above the title — AND pushes
   the thesis + TOC down by the same amount, eating into vertical
   real estate further down. Keep the title flush to the top.
   Bottom margin trimmed too so the thesis paragraph follows close
   behind. Mobile keeps the looser 4em-above / 2em-below treatment. */
@media (min-width: 701px) {
  #webapp-tint .cover-volume-title {
    margin: 0 0 1em;
  }
}
#webapp-tint .cover-volume-title:empty { display: none; }

/* Vol 0 (slipcase home) project title — "Richard Saul Wurman 5".
   Set in HN UltraLight (the family's lightest weight) with the trailing
   "5" set in HN Black so the numeral lands as the bold typographic
   anchor of the whole project. Bumped up a notch from the per-volume
   title size so it reads as a project banner rather than a volume
   subtitle. Tightened bottom margin so the TOC starts close beneath
   it (the thesis paragraph that used to live in this gap was deleted
   so the navigation rows can rise above the fold). */
#webapp-tint .cover-volume-title-project {
  font-family: "HN UltraLight", "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(28px, 2.8vw, 44px);
  letter-spacing: .02em;
  line-height: 1.1;
  opacity: 1;
  margin: 0 0 .5em;
}
#webapp-tint .cover-volume-title-project .project-num {
  font-family: "HN Black", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 900;
  letter-spacing: 0;
  margin-left: .12em;
}
@media (min-width: 701px) {
  #webapp-tint .cover-volume-title-project {
    margin: 0 0 .35em;
  }
}

/* ===== Image overlay (lightbox) =====
   Generic full-screen viewer for artifact images — posters, plates,
   any PNG/JPG referenced from a TOC row's data-image attribute. Sits
   above the menu tint, below the cover overlay's z-index range. */
#webapp-image-overlay {
  position: fixed;
  inset: 0;
  z-index: 85;
  background: rgba(20, 24, 32, .82);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease, visibility 0s linear .3s;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(40px, 7vh, 80px) clamp(20px, 5vw, 60px);
  -webkit-tap-highlight-color: transparent;
}
#webapp-image-overlay.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity .3s ease, visibility 0s linear 0s;
}
#webapp-image-overlay .image-overlay-stage {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 0;
  pointer-events: auto;
}
#webapp-image-overlay .image-overlay-img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  background: #fff;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .25),
    0 12px 40px rgba(0, 0, 0, .55);
}
#webapp-image-overlay .image-overlay-close {
  position: absolute;
  top: max(env(safe-area-inset-top, 0px), 28px);
  right: max(env(safe-area-inset-right, 0px), 28px);
  background: transparent;
  border: 0;
  padding: 6px 4px;
  cursor: pointer;
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: #ffffff;
  opacity: .55;
  transition: opacity .15s ease;
}
#webapp-image-overlay .image-overlay-close:hover,
#webapp-image-overlay .image-overlay-close:focus {
  opacity: .92;
  outline: none;
}
#webapp-image-overlay .image-overlay-caption {
  position: absolute;
  bottom: max(env(safe-area-inset-bottom, 0px), 28px);
  left: 50%;
  transform: translateX(-50%);
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-weight: 400;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .55);
  pointer-events: none;
  text-align: center;
  max-width: 80vw;
}
#webapp-image-overlay .image-overlay-caption:empty {
  display: none;
}

/* ===== HTML overlay (iframe) =====
   Full-bleed embed for sub-pages that carry their own typography. Same
   visual register as the image overlay (dark backdrop, top-right CLOSE
   word) so the dismiss affordance is consistent. The iframe paints over
   most of the viewport with a small inset margin so the source page's
   own paper edge is visible. */
#webapp-html-overlay {
  position: fixed;
  inset: 0;
  /* z-index above the reader (90) so an in-paper cross-reference link
     can pop the overlay on top instead of disappearing behind the open
     reader. The overlay's own close button returns the user to whatever
     was underneath — reader or menu — without losing reading position. */
  z-index: 95;
  background: rgba(20, 24, 32, .82);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease, visibility 0s linear .3s;
  padding: clamp(40px, 7vh, 80px) clamp(20px, 5vw, 60px);
  -webkit-tap-highlight-color: transparent;
}
#webapp-html-overlay.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity .3s ease, visibility 0s linear 0s;
}
#webapp-html-overlay .html-overlay-frame {
  width: 100%;
  height: 100%;
  border: 0;
  background: #fafafa;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .25),
    0 12px 40px rgba(0, 0, 0, .55);
}
#webapp-html-overlay .html-overlay-close {
  position: absolute;
  top: max(env(safe-area-inset-top, 0px), 28px);
  right: max(env(safe-area-inset-right, 0px), 28px);
  background: transparent;
  border: 0;
  padding: 6px 4px;
  cursor: pointer;
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: #ffffff;
  opacity: .55;
  transition: opacity .15s ease;
  z-index: 1;
}
#webapp-html-overlay .html-overlay-close:hover,
#webapp-html-overlay .html-overlay-close:focus {
  opacity: .92;
  outline: none;
}
#webapp-html-overlay .html-overlay-caption {
  position: absolute;
  top: max(env(safe-area-inset-top, 0px), 30px);
  left: 50%;
  transform: translateX(-50%);
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-weight: 400;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .55);
  pointer-events: none;
  text-align: center;
  max-width: 80vw;
}
#webapp-html-overlay .html-overlay-caption:empty {
  display: none;
}
/* The .cover-aside wrapper is a passthrough on desktop; it becomes the third
   flex column on mobile (specs + link stacked vertically). On desktop we
   give it an extra top margin so the spec block sits noticeably further
   beneath the cover thumb than the thumb sits beneath the numeral —
   creating the asymmetric "numeral → cover (close) → specs (further)"
   rhythm the printed colophon implies. */
#webapp-tint .cover-aside {
  margin-top: clamp(22px, 2.4vh, 40px);
}

/* ===== Volume colophon specs =====
   Mercure Transcript, very small all-caps. Inherits the per-volume color
   from #webapp-tint so Vol 4 picks up the white inversion automatically.
   Width is clamped to the cover-thumb's width so the colophon block can
   never extend wider than the cover image above it — the cover is the
   visual anchor and the specs read as a caption tucked beneath it. The
   font-size is scaled to fit the longest line ("BLEED 0.125" ALL SIDES")
   inside that constraint at every viewport width. */
#webapp-tint .cover-specs {
  list-style: none;
  margin: 0;            /* gap is owned by .cover-stack flex gap */
  padding: 0;
  /* Match the cover-thumb width exactly. */
  max-width: clamp(120px, 9.75vw, 165px);
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-weight: 400;
  /* Font scaled down 25% to match the narrower column width — keeps
     the longest spec lines (BLEED 0.125″ ALL SIDES, etc.) within the
     reduced cover-thumb silhouette. */
  font-size: clamp(5.6px, 0.5vw, 7.1px);
  letter-spacing: .12em;
  line-height: 1.7;
  text-transform: uppercase;
  opacity: .82;
}
#webapp-tint .cover-specs li {
  display: block;
  /* Allow long lines to wrap rather than overflow the cover-thumb width.
     Font is sized small enough that wrapping should rarely trigger, but
     this is a safety net so a longer spec string can never punch past
     the cover image silhouette. */
  white-space: normal;
  /* Anchor for the absolutely-positioned hanging tilde. */
  position: relative;
}

/* ===== Project colophon (Vol 0 only) =====
   The flat all-caps spec list that the per-volume menus use produces
   awkward word-wraps when the strings carry whole-project information
   (the slipcase dimensions + total page count + mixed-stock note all
   exceed the narrow cover-thumb-width column). Vol 0 swaps in this
   richer "book colophon" layout: three labelled groups (SLIPCASE / THE
   SET / EACH VOLUME), each with a small Mercure Transcript section
   head above one or more value lines set in HN UltraLight. The values
   are mixed-case rather than all-caps so they stay readable at small
   sizes inside the constrained column. */
#webapp-tint .cover-specs.cover-specs-project {
  text-transform: none;       /* values are mixed-case here */
  letter-spacing: 0;
  opacity: 1;
}
#webapp-tint .cover-specs.cover-specs-project li.spec-group {
  display: block;
  margin-bottom: .9em;
  padding: 0;
  white-space: normal;
}
#webapp-tint .cover-specs.cover-specs-project .spec-value {
  /* Anchor for the absolutely-positioned hanging tilde so it sits
     to the left of the line without affecting where the digit
     starts. */
  position: relative;
}
#webapp-tint .cover-specs.cover-specs-project li.spec-group:last-child {
  margin-bottom: 0;
}
#webapp-tint .cover-specs.cover-specs-project .spec-head {
  display: block;
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: clamp(8.5px, 0.74vw, 10.5px);
  letter-spacing: .14em;
  text-transform: uppercase;
  font-variant-caps: all-small-caps;
  opacity: .55;
  margin-bottom: .15em;
}
/* Spec values match the per-volume menus' colophon specs: Mercure
   Transcript, all-caps, mildly tracked. Only the section labels above
   carry the new HN Medium small-caps treatment — the values stay in
   the project's typewriter colophon voice for continuity with Vols 1–5. */
#webapp-tint .cover-specs.cover-specs-project .spec-value {
  display: block;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-weight: 400;
  font-size: clamp(7.5px, 0.66vw, 9.5px);
  letter-spacing: .12em;
  line-height: 1.7;
  text-transform: uppercase;
  opacity: .82;
}

/* Hang the leading tilde of "~720 PAGES", "~125 PAGES", etc. into the
   left margin so the digit aligns with the other lines and the block
   reads as a justified rectangle rather than a ragged-left list. The
   span has zero advance width and is shifted left by its own (visual)
   width via translate, so the "7" starts exactly where "5" or "1"
   would. */
#webapp-tint .cover-specs .spec-tilde,
#webapp-tint .cover-specs.cover-specs-project .spec-tilde {
  /* Detach from the inline flow entirely so the digit that follows
     starts at the line origin (and therefore lines up exactly with
     "10″ × 10″ SOFTCOVER" above it). The tilde sits to the LEFT of
     the line origin, hung in the margin. */
  position: absolute;
  right: 100%;
  top: 0;
  margin-right: .35em;
}

/* Cover zoom — secret "5" key pops the active volume's back cover at
   viewport size for close inspection. Self-contained overlay; click or
   ESC or another "5" press dismisses. */
#cover-zoom-overlay {
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
  perspective: 1600px;
}
#cover-zoom-overlay > * {
  cursor: zoom-out;
}
/* The cloned thumb card sits OUTSIDE its #webapp-tint ancestor, so all
   the cover-thumb styling rules (which are scoped under #webapp-tint)
   stop applying. Re-declare just the layout & visual rules we need
   here, scaled up to viewport-fill size. */
#cover-zoom-overlay .cover-thumb-card {
  position: relative;
  width: min(90vmin, 90vh);
  height: min(90vmin, 90vh);
  transform-style: preserve-3d;
  transform: rotateY(180deg);
}
#cover-zoom-overlay .cover-thumb-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .12),
    0 4px 14px rgba(0, 0, 0, .22),
    0 24px 64px rgba(0, 0, 0, .32);
}
#cover-zoom-overlay .cover-thumb-front { transform: rotateY(0deg); }
#cover-zoom-overlay .cover-thumb-back  { transform: rotateY(180deg); }

/* Per-volume tints — mirror the #webapp-tint[data-n] rules. */
#cover-zoom-overlay[data-n="0"] .cover-thumb-face { background: #ffffff; }
#cover-zoom-overlay[data-n="1"] .cover-thumb-face { background: var(--v1); }
#cover-zoom-overlay[data-n="2"] .cover-thumb-face { background: var(--v2); }
#cover-zoom-overlay[data-n="3"] .cover-thumb-face { background: var(--v3); }
#cover-zoom-overlay[data-n="4"] .cover-thumb-face { background: var(--v4); }
#cover-zoom-overlay[data-n="5"] .cover-thumb-face { background: var(--v5); }

/* Vol 0 back uses the hand-art photograph. */
#cover-zoom-overlay[data-n="0"] .cover-thumb-back {
  background: url("../img/hand-art.jpg") center/cover no-repeat var(--paper);
}
#cover-zoom-overlay[data-n="0"] .cover-thumb-back .cover-thumb-back-stack {
  display: none;
}

/* Front tally */
#cover-zoom-overlay .cover-thumb-ink {
  position: absolute;
  inset: 0;
  background: inherit;
}
#cover-zoom-overlay .cover-thumb-ink::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../img/cover-art.png") center/cover no-repeat;
  mix-blend-mode: multiply;
  opacity: .72;
}
#cover-zoom-overlay[data-n="0"] .cover-thumb-ink::after { opacity: 1; }
#cover-zoom-overlay[data-n="4"] .cover-thumb-ink::after {
  filter: invert(1);
  mix-blend-mode: screen;
  opacity: 1;
}

/* Back face content — same proportions as the menu thumb, just scaled
   up. Use ems relative to the card size by sizing in vmin. */
#cover-zoom-overlay .cover-thumb-back-stack {
  position: absolute;
  left: 50%; top: 42%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
}
#cover-zoom-overlay .cover-thumb-back-num {
  font-family: "LustSpine", "Didot", serif;
  font-size: clamp(320px, 55vmin, 720px);
  line-height: 1;
}
#cover-zoom-overlay .cover-thumb-back-title {
  font-family: "HN UltraLight", "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(22px, 4vmin, 48px);
  letter-spacing: .06em;
  line-height: 1;
  margin-top: 1.1em;
  white-space: nowrap;
}
#cover-zoom-overlay .cover-thumb-back-barcode {
  position: absolute;
  left: 50%;
  bottom: 8%;
  transform: translateX(-50%);
  pointer-events: none;
}
#cover-zoom-overlay .cover-thumb-back-barcode svg {
  display: block;
  width: clamp(48px, 7vmin, 96px);
  height: auto;
}

/* Per-volume back ink — mirror the #webapp-tint[data-n] color rules. */
#cover-zoom-overlay[data-n="1"] .cover-thumb-back-num,
#cover-zoom-overlay[data-n="1"] .cover-thumb-back-title { color: var(--v1-d); }
#cover-zoom-overlay[data-n="2"] .cover-thumb-back-num,
#cover-zoom-overlay[data-n="2"] .cover-thumb-back-title { color: var(--v2-d); }
#cover-zoom-overlay[data-n="3"] .cover-thumb-back-num,
#cover-zoom-overlay[data-n="3"] .cover-thumb-back-title { color: var(--v3-d); }
#cover-zoom-overlay[data-n="4"] .cover-thumb-back-num,
#cover-zoom-overlay[data-n="4"] .cover-thumb-back-title { color: #ffffff; }
#cover-zoom-overlay[data-n="5"] .cover-thumb-back-num,
#cover-zoom-overlay[data-n="5"] .cover-thumb-back-title { color: var(--v5-d); }


/* Per-volume color of the numeral, title, content, and the CLOSE word —
   tone-on-tone darker for 1, 2, 3, 5; flat white for vol 4 (Opposites
   inversion). Setting the color on #webapp-tint itself lets every child
   that uses `color: inherit` (close-btn, future UI bits) follow suit. */
/* Vol 0 inks dark on the salmon paper — the same near-black ink the
   home-view typography uses on the same ground. */
#webapp-tint[data-n="0"] { color: #11161e; }

/* Vol 0 alternate color scheme — Payne's-grey ground (matching the
   actual slipcase color) with white type, used as a side-by-side
   comparison palette to evaluate against the salmon default. Toggled
   via the "b" keyboard shortcut while Vol 0 is open; the choice is
   persisted in localStorage so the same scheme greets the user on the
   next open. The background gets re-set inline by JS so we don't need
   !important here for the bg; the text colors cascade through
   currentColor + the few explicit overrides below. */
#webapp-tint[data-n="0"].vol-zero-blue {
  color: #ffffff;
}
/* Soften a couple of the text-on-blue tones so the palette reads
   silvery-white rather than flat-white — the labels on a dark
   ground need a touch less ink than the headlines or the borders
   would feel like ruled lines instead of whispers. */
#webapp-tint[data-n="0"].vol-zero-blue .v-toc li {
  border-color: color-mix(in srgb, #ffffff 28%, transparent);
}
#webapp-tint[data-n="0"].vol-zero-blue .v-toc li:last-child {
  border-bottom-color: color-mix(in srgb, #ffffff 28%, transparent);
}
/* All-caps row labels (PREAMBLE, VOLUME I…V) inked silver-gray
   instead of white — pulls the labels back so the volume titles
   ("A Fable", "Some Quilts", etc.) stay the white-on-blue figure
   and the labels read as quieter ground. Reinforces the type
   contrast between the two content layers. Applied to the frame
   labels too (.frame .v-label normally bumps to opacity 1) so
   PREAMBLE matches the per-volume row labels. */
#webapp-tint[data-n="0"].vol-zero-blue .v-toc .v-label,
#webapp-tint[data-n="0"].vol-zero-blue .v-toc li.frame .v-label {
  color: #b8c2cc;
  opacity: 1;
}
#webapp-tint[data-n="1"] { color: var(--pg-1-dark); }
#webapp-tint[data-n="2"] { color: var(--pg-2-dark); }
#webapp-tint[data-n="3"] { color: var(--pg-3-dark); }
#webapp-tint[data-n="4"] { color: var(--pg-4-dark); }
#webapp-tint[data-n="5"] { color: var(--pg-5-dark); }

/* ===== Slipcase attribution block (Vol 0 only) =====
   Sits inside .cover-aside above the .cover-specs colophon. Two-line
   block: a Mercure Transcript label ("As told to, translated and
   embellished by") above a HN UltraLight name ("Dan Klyn"). Constrained
   to the same cover-thumb width as the specs so the whole left column
   stays visually plumb to the slipcase image. The hidden attribute
   collapses it on every other volume. */
#webapp-tint .cover-attribution {
  max-width: clamp(120px, 9.75vw, 165px);
  margin-bottom: clamp(10px, 1.4vh, 16px);
}
#webapp-tint .cover-attribution[hidden] { display: none; }
/* Per-volume mobile label injected into the cover-aside above the
   specs ("Volume I" through "Volume V"). Mirrors the .spec-head
   treatment used for "THE SET" et al. on Vol 0 — HN Medium, all-caps
   with small-cap proportions, knocked back to about half ink. Hidden
   on desktop (the right-column .cover-volume-title already names the
   volume there) and revealed by the mobile-portrait media query at
   the bottom of this file. */
#webapp-tint .cover-volume-label {
  display: none;
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: clamp(8.5px, 0.74vw, 10.5px);
  letter-spacing: .14em;
  text-transform: uppercase;
  font-variant-caps: all-small-caps;
  opacity: .55;
  margin-bottom: .15em;
}

/* Vol 0 mobile-only project title — "Richard Saul Wurman 5" set into
   the cover-aside (top-right column on mobile) where the desktop's
   attribution-label/name pair is hidden. HN UltraLight for the name,
   HN Black for the numeral. Default state: hidden — only revealed by
   the mobile-portrait media query at the bottom of this file. */
#webapp-tint .cover-attribution-title {
  display: none;
  font-family: "HN UltraLight", "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(22px, 5.5vw, 30px);
  letter-spacing: .02em;
  line-height: 1.05;
  color: inherit;
}
#webapp-tint .cover-attribution-title .project-num {
  font-family: "HN Black", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 900;
  letter-spacing: 0;
  margin-left: .12em;
}

/* Attribution label — HN Medium set in all-caps with small-cap
   tracking and proportions. font-variant-caps:all-small-caps will
   pick up real SC glyphs if the font ships them; without them, the
   text-transform:uppercase + the small font-size + the wide tracking
   together produce the "small caps" look. Knocked back so it reads
   as a quiet supporting line above the byline name. */
#webapp-tint .cover-attribution-label {
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: clamp(8.5px, 0.74vw, 10.5px);
  letter-spacing: .14em;
  line-height: 1.35;
  text-transform: uppercase;
  font-variant-caps: all-small-caps;
  opacity: .72;
  margin-bottom: .5em;
}
/* Byline name — same family + weight as the project title above the
   panel ("Richard Saul Wurman" in HN UltraLight), several notches smaller
   so the left-column attribution block never outruns the body-column TOC
   in height on desktop slipcase (Vol 0) views. Both byline names
   (Wurman + Klyn) share these proportions so neither over-claims the
   other. The mobile-portrait override at the bottom of this file bumps
   them up again for the narrow viewport where the cover-aside has more
   vertical room to spend. */
#webapp-tint .cover-attribution-name {
  font-family: "HN UltraLight", "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(15px, 1.25vw, 20px);
  letter-spacing: .02em;
  line-height: 1.1;
  margin-bottom: .25em;
}
/* Second attribution pair gets vertical breathing room so the two
   labels (A NEW WORK BY / AS TOLD TO…) don't run together. */
#webapp-tint .cover-attribution-label.cover-attribution-pair-2 {
  margin-top: 1.2em;
}

/* ===== Per-volume content panel — stacks BENEATH the big numeral + title.
   Same horizontal margins as the badge so both align flush left. The top
   offset clamps so the badge always has room above on any viewport. ===== */

#webapp-tint .cover-content {
  position: absolute;
  /* DESKTOP DEFAULT: 2-column layout — badge sits on the left, content
     panel sits to its right with comfortable horizontal breathing room
     and clear of the right close-button + nav strip. Margins pull
     inboard so a 1200-px desktop window (roughly the user's typical
     working width) has a generous content column rather than a narrow
     half-width strip. Two narrower-viewport breakpoints later swap to
     a vertically-stacked layout: the narrow-desktop band (701–1100px)
     and the mobile-portrait one (≤700px portrait). */
  /* Left edge pulled in ~25% from the original clamp(320, 32vw, 600)
     to take advantage of the slimmer left column above. */
  left: clamp(240px, 24vw, 450px);
  right: clamp(80px, 10vw, 220px);
  top: clamp(80px, 10vh, 140px);
  bottom: clamp(40px, 6vh, 80px);
  max-width: 880px;
  /* Pointer events on so the user can scroll long TOCs (Vol 5 with
     all five Prior Fables expanded, etc.). overflow-y: auto reveals a
     thin scrollbar; -webkit-overflow-scrolling enables iOS momentum.
     touch-action: pan-y leaves horizontal gestures available for the
     swipe-between-volumes handler in menu.js. */
  pointer-events: auto;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  /* Razor-thin inset scrollbar — barely-there ink-ghost stripe that wakes
     up a touch on hover. WebKit uses the ::-webkit pseudo-elements below
     for a true 1px track; Firefox can only go as thin as scrollbar-width:
     thin, but the color treatment keeps it visually quiet either way. */
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, currentColor 18%, transparent) transparent;
}
/* Global scrollbar treatment — every overflow surface inside the PWA
   gets a 1px hairline track and a small dark "handle". The handle has
   min-height so it stays grabbable even when the scroll range is short.
   Per-surface rules (.cover-content, #webapp-reader, etc.) win on
   specificity where they differ; this catches everything else (search
   results, marginalia grid, any future scrollable). */
.webapp-mode * {
  scrollbar-width: thin;
  scrollbar-color: rgba(40, 36, 28, .32) transparent;
}
.webapp-mode *::-webkit-scrollbar { width: 1px; height: 1px; }
.webapp-mode *::-webkit-scrollbar-track { background: transparent; }
.webapp-mode *::-webkit-scrollbar-thumb {
  background: rgba(40, 36, 28, .32);
  min-height: 44px;
  border-radius: 0;
}
.webapp-mode *::-webkit-scrollbar-thumb:hover {
  background: rgba(40, 36, 28, .56);
}

/* Vertical scrollbar in cover-content — hidden track with a
   razor-thin (1px) thumb that shows only on hover/active scroll.
   WebKit enforces a minimum rendered scrollbar width of ~4-6px when
   the scrollbar is visible, so we instead use overlay-style: a
   transparent thumb at rest, and a hairline thumb on hover. The
   content still scrolls via wheel/trackpad/keyboard either way.
   `scrollbar-color: transparent transparent` on Firefox achieves the
   same hide-when-idle effect for that engine. */
#webapp-tint .cover-content {
  scrollbar-color: transparent transparent;
}
#webapp-tint .cover-content:hover {
  scrollbar-color: color-mix(in srgb, currentColor 38%, transparent) transparent;
}
#webapp-tint .cover-content::-webkit-scrollbar {
  width: 4px;     /* WebKit's effective minimum — thumb fits inside */
}
#webapp-tint .cover-content::-webkit-scrollbar-track {
  background: transparent;
}
#webapp-tint .cover-content::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 0;
  min-height: 44px;
  /* Hairline thumb: 1px-wide colored stripe centered inside the
     4px-wide track. The other 3px is transparent border, so the
     visible thumb reads as a single-pixel line. */
  border-left: 3px solid transparent;
  background-clip: padding-box;
}
#webapp-tint .cover-content:hover::-webkit-scrollbar-thumb {
  background-color: color-mix(in srgb, currentColor 38%, transparent);
}

/* Volume thesis line — Mercure Regular, larger. Full opacity for max
   contrast against the tinted background.
   text-wrap: pretty asks the browser's high-quality line-breaker to
   avoid leaving a single short word stranded on the last line — fixes
   orphans like "true" on Vol 4's "…is also true" without needing a
   manual <br> for every viewport. The .v-thesis-break mechanism stays
   in place as a designer-controlled override (used by Vol 3 + Vol 4
   on desktop ≥701px); pretty handles the rest, and gracefully
   degrades to default wrapping on browsers that don't support it. */
#webapp-tint .v-thesis {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-style: normal;
  font-weight: 400;
  font-size: clamp(24px, 2.8vw, 38px);
  line-height: 1.3;
  margin: 0 0 1.4em 0;
  text-wrap: pretty;
}
/* Optional, designer-controlled wide-viewport line break inside a thesis
   paragraph. Used by Vol 4 to force the break after the colon so the
   "association / juxtaposition" pair lands together on its own line.
   Hidden on mobile so the natural wrap takes over below the menu's
   700px mobile cutoff. */
#webapp-tint .v-thesis .v-thesis-break {
  display: none;
}
@media (min-width: 701px) {
  #webapp-tint .v-thesis .v-thesis-break {
    display: initial;
  }
}
/* Attribution line beneath a thesis (e.g. V4's Bohr line). Markup carries
   an explicit <br> + em-dash, so it degrades to a sensible default-italic
   line even if these style rules don't load. Block display + line-height
   here just give it some breathing room beneath the thesis. */
#webapp-tint .v-thesis .v-thesis-cite {
  display: block;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 400;
  font-size: 0.55em;
  line-height: 1.3;
  margin-top: 0.55em;
  opacity: 0.72;
}

/* TOC list — all Mercure Regular. Hierarchy via case + tracking + opacity,
   not via italic. Each row separated by a hairline. */
#webapp-tint .v-toc {
  list-style: none;
  padding: 0;
  margin: 0;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-style: normal;
  font-size: clamp(17px, 1.8vw, 22px);
  line-height: 1.45;
}
/* Chapter / section row. Stacked single-column at every viewport: the
   v-label (CH I, PRELUDE, etc.) sits on its own line above the v-title
   (Self / Other), both flush to the same left margin. The expandable
   +/− chevron is position:absolute so it stays on the right edge
   regardless of the row's flow. */
#webapp-tint .v-toc li {
  display: grid;
  grid-template-columns: 1fr;
  row-gap: .1em;
  padding: .5em .25em;
  border-top: 1px solid currentColor;
  border-color: color-mix(in srgb, currentColor 32%, transparent);
}
#webapp-tint .v-toc li:last-child {
  border-bottom: 1px solid currentColor;
  border-bottom-color: color-mix(in srgb, currentColor 32%, transparent);
}
/* Frame rows carry the same hairline above and below as every other
   menu row — the rules let PRELUDE and CODA read as clearly clickable
   options bracketed by the same dividers as the Acts they frame. */
/* Frame rows carry an empty `&nbsp;` v-title that the grid auto-flows
   into a second row beneath the spanning label, opening a phantom gap.
   Hiding it collapses the row to just the label height so PRELUDE,
   CODA, and similar frame entries sit snug to their adjacent rules. */
#webapp-tint .v-toc li.frame > .v-title { display: none; }
/* Frame labels (PRELUDE, CODA, MARGINALIA…) read at full ink so the
   click affordance is unambiguous. The default .v-label opacity (.85)
   makes them look knocked-back. */
#webapp-tint .v-toc li.frame .v-label {
  opacity: 1;
}
/* Section label — Mercure Regular, all caps, lightly tracked. Sits as
   its own block above the v-title (CH I → Self / Other). Explicit
   block display so it reliably takes its own grid row even when the
   chapter row's grid is single-column. */
#webapp-tint .v-toc .v-label {
  display: block;
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: .78em;
  opacity: .85;
}
/* Section title — Mercure Regular body. */
/* Chapter title — the visual anchor for the row. Bumped up so the
   chapter reads as the parent and the sub-rows below it read as its
   children, not as peers. */
#webapp-tint .v-toc .v-title {
  display: block;
  font-style: normal;
  font-size: 1.18em;
  line-height: 1.18;
}
/* Subline beneath a TOC title (e.g. the Wurman law under each Vol 2
   chapter). Smaller, sits inside the second column. */
#webapp-tint .v-toc .v-subline {
  display: block;
  font-size: .82em;
  letter-spacing: 0;
  text-transform: none;
  margin-top: .2em;
  opacity: .82;
}

/* Coming-attraction rows — TOC entries whose underlying content isn't
   written yet. Knocked back to about half ink, italicized, with a small
   Mercure-Transcript "WIP" tag inline next to the title. The row
   itself stays in the rhythm of the list (still bordered, still in-flow)
   but signals plainly that there's nothing to tap yet. */
#webapp-tint .v-toc li.coming {
  opacity: .48;
  cursor: default;
  font-style: italic;
}
#webapp-tint .v-toc li.coming:hover {
  background-color: transparent;
}
/* WIP badge — usable on either a fully-knocked-back .coming row
   (where the row itself is non-interactive) OR on a regular interactive
   row that happens to point at a stub manuscript (Vol 1 Acts II + III).
   The selector no longer requires the .coming parent. Heavily faded so
   the badge whispers production status without competing with the
   chapter title beside it. */
#webapp-tint .v-toc .v-coming-tag {
  display: inline-block;
  margin-left: .8em;
  padding: 0 .42em;
  font-family: "Mercure Transcript", "Courier New", monospace;
  font-style: normal;
  font-size: .5em;
  letter-spacing: .14em;
  text-transform: uppercase;
  vertical-align: .22em;
  border: 1px solid currentColor;
  border-radius: 2px;
  opacity: .32;
}

/* Expandable TOC items reveal nested sub-elements on tap. The whole row
   is clickable; a chevron in the right margin signals "tap to open". */
#webapp-tint .v-toc li {
  position: relative;   /* anchor the chevron */
}
#webapp-tint .v-toc li.expandable {
  cursor: pointer;
  pointer-events: auto;
  padding-right: 2em;   /* reserve room for the chevron */
  transition: background-color .15s ease;
}
#webapp-tint .v-toc li.expandable::after {
  content: "+";
  position: absolute;
  right: .35em;
  top: .55em;
  font-size: 1.4em;
  font-weight: 400;
  line-height: 1;
  opacity: .65;
  transition: opacity .15s ease, transform .2s ease;
  pointer-events: none;
}
#webapp-tint .v-toc li.expandable:hover::after { opacity: .92; }
#webapp-tint .v-toc li.expandable.is-open::after {
  content: "\2212";   /* minus sign */
  opacity: .92;
}
/* Open-chapter highlight. A whisper-thin lightening wash applied to the
   open expandable row so it reads as "this one is open" without forming
   a heavy block that drags down the type inside it. White-mix (rather
   than currentColor-mix) so the result lifts on every per-volume ground
   instead of darkening on the lighter-text volumes — the open row should
   always feel like a glow, never like a shadow. */
#webapp-tint .v-toc li.expandable.is-open {
  background: rgba(255, 255, 255, 0.08);
}

/* Nested sub-list — direct child of the expandable li. Spans the
   chapter row's full width so its rows can sit flush to the same left
   margin as the chapter v-label and v-title above. */
#webapp-tint .v-toc .v-subs {
  list-style: none;
  padding: 0;
  margin: .35em 0 .15em 0;
  font-size: .88em;
  display: none;
  grid-column: 1 / -1;
}
/* Direct-child selector so a nested expandable (e.g. Marginalia inside
   Gallery) keeps its own children hidden until the user opens it,
   independently of whether its grandparent is open. */
#webapp-tint .v-toc li.expandable.is-open > .v-subs { display: block; }
/* Sub-row: stacked single-column. Sub-label (ESSAY / MARGINALIA / year
   / LATCH letter) sits as its own line above the sub-title, both flush
   to the same left margin as the chapter v-label and v-title above. */
#webapp-tint .v-toc .v-subs li.sub {
  display: block;
  padding: .35em 0;
  border: 0;
  position: static;
}
#webapp-tint .v-toc .v-subs li.sub:first-child { padding-top: .35em; }
#webapp-tint .v-toc .v-subs li.sub.single {
  display: block;
}

/* ===== Marginalia group =====
   A nested expandable inside a chapter's v-subs that collects all of
   that chapter's marginalia entries under a single MARGINALIA label.
   Tap the label → group expands and shows its entries; tap again →
   collapses. Used in V2 and V4 chapters; V1 and V5 keep the older
   chapter-level Marginalia frame treatment.

   The marg-group needs position:relative so the .expandable::after
   chevron anchors to the group's own top-right corner instead of the
   parent chapter's. The label is bumped from .62em (the regular
   per-item sub-label size) to a more clickable .82em, and the chevron
   is nudged to sit on the same baseline as that label. */
#webapp-tint .v-toc .v-subs li.sub.marg-group {
  position: relative;
  padding-right: 2em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#webapp-tint .v-toc .v-subs li.sub.marg-group > .sub-label {
  /* Match the GUEST ESSAY / SPEECH / ESSAY labels above — same .62em
     Mercure Transcript treatment (inherited from the default
     .v-subs .sub-label rule), just bumped to opacity 1 so MARGINALIA
     reads as a clickable header rather than a faded marker. */
  font-size: .62em;
  opacity: 1;
  margin-bottom: 0;
}
/* Re-anchor the +/− chevron for the marg-group sub. The desktop rule
   anchors it to the chapter li at top:.8em right:.5em — at the
   smaller sub-row scale that lands too far down and too small. */
#webapp-tint .v-toc .v-subs li.sub.marg-group::after {
  content: "+";
  position: absolute;
  right: 0;
  top: .35em;
  opacity: .55;
  font-size: 1.1em;
  pointer-events: none;
}
#webapp-tint .v-toc .v-subs li.sub.marg-group.is-open::after {
  content: "\2212";   /* − */
  opacity: .85;
}
/* Nested v-subs inside a marg-group — entries are display:none until
   the group opens. Tightened top-margin so the entries snug against
   the MARGINALIA label rather than floating with the chapter's gap. */
#webapp-tint .v-toc .v-subs li.sub.marg-group > .v-subs {
  display: none;
  margin: .35em 0 0 0;
  padding: 0;
}
#webapp-tint .v-toc .v-subs li.sub.marg-group.is-open > .v-subs {
  display: block;
}
#webapp-tint .v-toc .v-subs li.sub.marg-group > .v-subs > li.sub {
  padding: .25em 0;
}
/* Group-break modifier: insert one line-height of vertical space above
   this row so the chronologically-ordered hominin clump in the V5
   Marginalia grid sits visually apart from the general (alphabetised)
   marginalia above it. */
#webapp-tint .v-toc .v-subs li.sub.is-group-break {
  margin-top: 1.4em;
}
/* Type marker (ESSAY / MARGINALIA / year / LATCH letter) — Mercure
   Transcript, all caps, lightly tracked, set smaller than the
   sub-title below it so the marker reads as a label rather than as
   content. Displays as its own line above the sub-title. */
#webapp-tint .v-toc .v-subs .sub-label {
  display: block;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: .62em;
  opacity: .6;
  margin-bottom: .15em;
}
/* Sub-title sits on its own line below the sub-label, flush to the
   same left margin as the chapter v-title. Slightly smaller and a
   shade dimmer than the chapter title so the chapter heading reads
   as the parent and the sub-rows read as its children. */
#webapp-tint .v-toc .v-subs .sub-title {
  display: block;
  font-size: .94em;
  opacity: .88;
  line-height: 1.25;
}
/* Featured type markers (Essay / Guest Essay / Speech) — the primary
   long-form pieces of each chapter — and chapter-level featured rows
   marked .is-featured (V3's Research Paper section). The salmon/pink
   tint signals "this is the lead piece" and pops against the neutral
   Marginalia rows without needing a "featured" badge.
   The exact hue is set per-volume below — every menu picks a tone
   that reads cleanly against its own ground. The base rule here just
   bumps opacity to full; color cascades from the per-volume overrides. */
#webapp-tint .v-toc .v-subs li.sub.is-featured .sub-label,
#webapp-tint .v-toc li.is-featured > .v-label {
  opacity: 1;
}

/* ----- Per-volume featured-marker tints -----
   Vols 1, 2, 3, 5 (light gray-blue grounds) carry a deeper salmon —
   the original project hue, with enough saturation to sit clearly on
   a light field without muddying. Vol 4 (Payne's-grey ground) inverts
   to a light pink, which reads as a glow against the dark field where
   the deeper salmon would lose contrast. Each tone was picked for its
   specific ground, not as a universal "highlight color". */
#webapp-tint[data-n="1"] .v-toc .v-subs li.sub.is-featured .sub-label,
#webapp-tint[data-n="1"] .v-toc li.is-featured > .v-label {
  color: #B85A3F;
}
#webapp-tint[data-n="2"] .v-toc .v-subs li.sub.is-featured .sub-label,
#webapp-tint[data-n="2"] .v-toc li.is-featured > .v-label {
  color: #A24E36;
}
#webapp-tint[data-n="3"] .v-toc .v-subs li.sub.is-featured .sub-label,
#webapp-tint[data-n="3"] .v-toc li.is-featured > .v-label {
  color: #8E4530;
}
#webapp-tint[data-n="4"] .v-toc .v-subs li.sub.is-featured .sub-label,
#webapp-tint[data-n="4"] .v-toc li.is-featured > .v-label {
  color: #F4B8AC;
}
#webapp-tint[data-n="5"] .v-toc .v-subs li.sub.is-featured .sub-label,
#webapp-tint[data-n="5"] .v-toc li.is-featured > .v-label {
  color: #C56F4E;
}
/* ===== Project-wide search (Vol 5, Part III) =====
   Lives inside an expandable li and reveals when the row opens. The
   input picks up the per-volume color (currentColor) and sits on a
   barely-there ink wash so it reads as part of the menu rather than
   a foreign control. */
#webapp-tint .v-toc .v-search {
  display: none;
  grid-column: 1 / -1;
  margin: .35em 0 .15em 0;
}
#webapp-tint .v-toc li.v-search-row.is-open > .v-search { display: block; }
#webapp-tint .v-toc .v-search-input {
  width: 100%;
  background: color-mix(in srgb, currentColor 6%, transparent);
  color: inherit;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, currentColor 28%, transparent);
  padding: .45em .25em .35em;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: .9em;
  letter-spacing: 0;
  outline: none;
  border-radius: 0;
  -webkit-appearance: none;
  appearance: none;
}
#webapp-tint .v-toc .v-search-input::placeholder {
  color: color-mix(in srgb, currentColor 50%, transparent);
  font-style: italic;
}
#webapp-tint .v-toc .v-search-input:focus {
  border-bottom-color: color-mix(in srgb, currentColor 60%, transparent);
  background: color-mix(in srgb, currentColor 9%, transparent);
}
#webapp-tint .v-toc .v-search-empty {
  margin: .8em 0 0;
  font-size: .82em;
  font-style: italic;
  opacity: .55;
}
/* "Open the full glossary →" button — sits between the search input
   and the result list as a quiet escape hatch into the long-form read. */
#webapp-tint .v-toc .v-search-open-all {
  display: inline-block;
  background: transparent;
  border: 0;
  padding: .55em 0 .25em;
  margin: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: .82em;
  font-style: italic;
  color: inherit;
  opacity: .65;
  transition: opacity .15s ease;
}
#webapp-tint .v-toc .v-search-open-all:hover,
#webapp-tint .v-toc .v-search-open-all:focus {
  opacity: 1;
  outline: none;
  text-decoration: underline;
  text-underline-offset: 2px;
}
#webapp-tint .v-toc .v-search-results {
  list-style: none;
  padding: 0;
  margin: .65em 0 .25em;
  font-size: .88em;
  max-height: 60vh;
  overflow-y: auto;
}
#webapp-tint .v-toc .v-search-results li {
  display: block;
  grid-template-columns: none;
  padding: .55em 0;
  border: 0;
  border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
  cursor: pointer;
  position: static;
  transition: background-color .12s ease;
}
#webapp-tint .v-toc .v-search-results li:first-child { border-top: 0; }
#webapp-tint .v-toc .v-search-results li:hover {
  background: color-mix(in srgb, currentColor 6%, transparent);
}
#webapp-tint .v-toc .v-search-results .sr-title {
  display: block;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 1em;
  line-height: 1.3;
}
#webapp-tint .v-toc .v-search-results .sr-where {
  display: block;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-size: .68em;
  letter-spacing: .14em;
  text-transform: uppercase;
  opacity: .55;
  margin-top: .25em;
}
#webapp-tint .v-toc .v-search-results .sr-snippet {
  display: block;
  font-style: italic;
  font-size: .9em;
  opacity: .7;
  margin-top: .2em;
  line-height: 1.4;
}
#webapp-tint .v-toc .v-search-results mark {
  background: color-mix(in srgb, currentColor 18%, transparent);
  color: inherit;
  padding: 0 .1em;
  border-radius: 1px;
}

/* Frame chapters (Prelude/Coda in Vol 1, Marginalia/Images in Vol 5)
   — same Mercure Regular as Acts. Label spans both grid columns so
   longer phrases don't overflow into the (empty) title column. Full
   ink so the row reads as clearly clickable, matching the Acts. */
#webapp-tint .v-toc li.frame .v-label {
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: .78em;
  opacity: 1;
  grid-column: 1 / -1;
}
/* When a frame row also expands (Marginalia in V5) and sits at the
   end of the list, drop the closing hairline rather than force a
   tight or asymmetric one beneath a single-line label. The TOC
   trails off after the label and reads cleaner than fighting the
   row's intrinsic short height. The rule returns naturally when
   the row expands and the marg-grid fills it out. */
#webapp-tint .v-toc li.frame.expandable:not(.is-open):last-child {
  border-bottom: 0;
}

/* (Earlier narrow-desktop cover-content override removed — the
   absolutely-positioned cover-content was being pushed too far down at
   common workspace widths, breaking the 2-column layout. The default
   desktop positioning at line 557 handles wide desktops correctly; if
   the heading overlaps the cover-thumb-card on a narrow Chrome window,
   that specific edge case can be handled via window resizing for now. */

/* ----- iPad mini portrait — tighter left margins to use the narrow
   tablet's horizontal space efficiently ----- */
/* iPad mini in portrait is 744px wide. The default desktop clamps
   leave ~120px of empty space to the left of the cover-stack — fine
   on a 1400px monitor but wasteful on a 744px tablet. This block
   pulls the cover-stack closer to the left edge and shifts the
   cover-content panel in to match, so the body column gets the room
   it needs without the columns crowding each other. Targets the
   744–1024px portrait band (covers iPad mini and iPad Air portrait). */
@media (min-width: 701px) and (max-width: 1024px) and (orientation: portrait) {
  /* Single gutter token applied to every margin in the layout — top,
     left, right, AND the gap between cover-stack and cover-content.
     Computed against vw on every side so the four margins stay equal
     as the viewport scales (vh would skew with orientation). Result:
     a balanced 4-margin frame, with the gap between columns reading
     as the same measure as the outer page margins — a typographic
     symmetry that the previous one-off clamp values approximated but
     didn't enforce. */
  #webapp-tint {
    /* Gutter bumped from 24 → 36 minimum so the corner inset feels
       like a deliberate margin rather than a pixel-tight fit on the
       744px iPad mini portrait, scaling up to a 64px upper bound at
       the iPad-air-portrait end of this band. */
    --gutter: clamp(36px, 5.5vw, 64px);
    /* Thumb slightly more generous on iPad mini so the cover reads
       as a present mark rather than disappearing — bumped from 120
       to 140 minimum, scaling proportionally. */
    --thumb-w: clamp(140px, 11vw, 180px);
    /* Additional shift applied to BOTH columns' left position — slides
       the whole content slab to the right on iPad mini so the cover
       column hangs further from the edge. Both columns shift by the
       same amount so the inter-column gap stays put. */
    --col-shift: 32px;
  }
  #webapp-tint .cover-stack {
    left: calc(var(--gutter) + var(--col-shift));
    top:  var(--gutter);
  }
  #webapp-tint .cover-content {
    /* left = outer-gutter + col-shift + thumb width + inner-gap.
       The inner gap is the outer gutter MINUS 10px — pulls the body
       column 10px closer to the cover-stack so the two columns read
       as a more cohesive pair without the small gap of "negative
       space" the fully-symmetric version opened up. */
    left:  calc(var(--gutter) * 2 + var(--col-shift) + var(--thumb-w) - 10px);
    right: var(--gutter);
    top:   var(--gutter);
  }
  /* Pull the specs block up toward the cover-thumb. The desktop
     default opens a clamp(22px, 2.4vh, 40px) margin between thumb
     and aside; on iPad mini portrait we want them to read as a
     single composed mark, so the aside hugs the thumb with only the
     cover-stack's flex gap separating them. */
  #webapp-tint .cover-aside {
    margin-top: 0;
  }
}

/* ----- Phone landscape — single-page scroll instead of nested ----- */
/* When the phone is rotated to landscape, the desktop 2-column
   layout's cover-content panel (position:absolute + overflow-y:auto)
   creates an awkward nested scrollbar within already-very-short
   vertical real estate. Easier model for short-landscape phones:
   let the WHOLE menu page scroll as one unit — drop the panel's
   bottom anchor and overflow, and turn on overflow on the parent
   tint. cover-stack stays in place (small thumb + specs, anchored
   to the corner); cover-content flows naturally below or to the
   side and the user scrolls the whole thing as a single scroll
   surface. Targets phone-class landscape viewports specifically:
   width 700–950px AND height ≤ 600px (catches iPhone landscape
   ~852×393, Z Flip ~768×370). iPad mini landscape (744 tall) and
   wider laptops both clear the height threshold and keep their
   nested-panel behavior. */
@media (orientation: landscape) and (min-width: 700px) and (max-width: 950px) and (max-height: 600px) {
  #webapp-tint {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  #webapp-tint .cover-content {
    bottom: auto;       /* drop the bottom anchor; height grows with content */
    overflow: visible;  /* no nested scrollbar — let content flow past */
    max-height: none;
    /* Push cover-content top further down to clear the (now larger
       in landscape) cover-thumb. The phone-portrait rule clamped to
       150px assumed a portrait viewport where the thumb at 28vw is
       small; on a landscape viewport, 28vw of 852px = 165px tall
       thumb, which sits below the 150px top and overlaps the thesis. */
    top: clamp(170px, 48vh, 210px);
  }
  /* Shrink the cover-thumb on phone landscape so it doesn't bloat with
     the wider viewport. Sized to vh (the LIMITED dimension in this
     orientation) instead of vw, so the thumb stays in proportion to
     the available vertical space rather than dominating it. */
  #webapp-tint .cover-thumb {
    width: clamp(80px, 28vh, 130px);
  }
  /* Cover-stack tightens its top inset too — the phone-portrait
     rule's clamp(16, 3vh, 26) at 393px height gives 26 (max),
     which is fine, but pulled to ~16 here for a snugger top. */
  #webapp-tint .cover-stack {
    top: clamp(12px, 4vh, 20px);
  }
}

/* ----- iPad mini landscape — pull the left column ~10px back toward
   the edge so it doesn't crowd the body column ----- */
/* iPad mini in landscape is 1133×744. The desktop default places
   cover-stack at 12vw=136px and cover-content at 24vw=272px, leaving
   only ~16px between the cover thumb's right edge and the body column
   — too tight at this aspect ratio. Pull cover-stack ~10px back
   toward the left edge so the gap reads as deliberate breathing room
   instead of accidental crowding. Scoped to the 1100-1200px landscape
   band to avoid affecting larger landscape windows. */
@media (min-width: 1100px) and (max-width: 1200px) and (orientation: landscape) {
  #webapp-tint .cover-stack {
    left: clamp(90px, 11vw, 130px);
  }
  /* Body column nudged ~20px to the right of the desktop default
     (24vw=272px on 1133px landscape iPad mini becomes ~292px) so the
     gap to the cover-stack reads as a deliberate column gutter rather
     than the pinched ~16px the default produced. Pairs with the
     cover-stack's leftward pull above. */
  #webapp-tint .cover-content {
    left: clamp(260px, 26vw, 470px);
  }
}

/* ----- Narrow-viewport (phone) layout ----- */
/* Phones (portrait or landscape ≤700px wide) flip the cover-stack from
   vertical to a single horizontal row: [badge | cover thumb at badge
   height | specs]. The thumb sizes itself to match the height of the
   [numeral + title] block, and the specs column flows to the right of
   the thumb and scales fluidly to the remaining viewport width.
   The 700px ceiling is deliberately set BELOW iPad mini's 744px
   portrait width so that iPad mini in portrait orientation receives
   the wide 2-column desktop layout — the tight phone treatment would
   waste the iPad's horizontal real estate. Resized desktop browser
   windows above 700px also get the wide layout; there is no
   intermediate "stacked desktop" band, since that produced too much
   horizontal air without enough payoff.
   The second clause catches NARROW landscape viewports (orientation
   landscape AND width ≤ 950px AND height ≤ 600px) — wacky foldables
   like the Galaxy Z Flip in landscape (~768×370) where the narrow
   width can't sustain the wide 2-column layout. iPhone landscape
   (~852×393) and other wider-but-still-short phones get a different
   compact 2-column treatment in the next block — they have enough
   width for a side-by-side layout, just need it tighter vertically. */
@media (max-width: 700px),
       (orientation: landscape) and (max-width: 950px) and (max-height: 600px) {
  #webapp-tint .cover-stack {
    /* Left: past the 28-px nav-prev strip + breathing room.
       Right: clears the 28-px nav-next strip + breathing room.
       Top: ducks under the notch on safe-area phones, otherwise 16-26 px. */
    left: clamp(40px, 9vw, 56px);
    right: clamp(40px, 9vw, 56px);
    top: max(env(safe-area-inset-top, 0px), clamp(16px, 3vh, 26px));
    transform: none;             /* drop the desktop scale trick */
    display: flex;
    flex-direction: row;
    align-items: flex-start;     /* anchor everything to the top of the row */
    gap: clamp(10px, 2.8vw, 18px);
  }
  /* Badge claims ~20% of the portrait viewport — sized so the numeral
     reads as a strong mark without dwarfing the thesis paragraph and TOC
     beneath it. Pulled back ~33% from the previous oversized treatment. */
  #webapp-tint .cover-badge {
    flex: 0 0 auto;
  }
  #webapp-tint .cover-num {
    font-size: clamp(120px, 40vw, 188px);
  }
  #webapp-tint .cover-title {
    font-size: clamp(19px, 4.7vw, 27px);
    margin-top: -.04em;
  }
  /* On mobile portrait the cover thumb stands in for the numeral + title
     badge: it's the prominent identity for the volume. Default-flipped
     to the back face (numeral + title + barcode) by JS at init; tap
     toggles between back and front. Sized small here — the cover-thumb
     is now defaulting to the back face on every viewport (with all of
     the volume's identity baked into it), so the mobile version no
     longer needs to read as a hero element. Pulled back to ~30% of
     viewport width so the cover-content panel underneath has clear
     vertical room and the thesis + TOC stop overlapping the thumb. */
  #webapp-tint .cover-thumb {
    display: block;
    width: clamp(105px, 28vw, 165px);
    aspect-ratio: 1 / 1;
    margin: 0 clamp(12px, 3.4vw, 20px) clamp(14px, 2.6vh, 26px) 0;
    perspective: 900px;
    flex: 0 0 auto;
  }
  /* Back-face proportions scale with the smaller card — numeral still
     dominates, title and barcode keep their relative ratios but at the
     reduced sizes appropriate to the new ~30vw thumb. */
  #webapp-tint .cover-thumb-back-num {
    font-size: clamp(46px, 12.5vw, 78px);
  }
  #webapp-tint .cover-thumb-back-title {
    font-size: clamp(9px, 2vw, 12px);
    margin-top: .35em;
  }
  #webapp-tint .cover-thumb-back-barcode svg {
    width: clamp(22px, 5.2vw, 32px);
  }
  /* Hide the inline numeral + title — same content lives on the back
     face of the cover thumb now, so showing both would be redundant. */
  #webapp-tint .cover-badge { display: none; }
  /* Volume title (e.g. "A Fable", "Richard Saul Wurman 5") is hidden
     entirely on mobile portrait — the cover-thumb's BACK face already
     carries the volume's identity (small numeral + title + barcode),
     and the Vol 0 slipcase front already carries "Richard Saul Wurman".
     Repeating the title as standalone text below the thumb was both
     redundant and the source of the overlap with the cover-stack at
     narrow widths. The desktop layout still shows the title — it has
     room, and the title there reads as the right-column heading. */
  #webapp-tint .cover-volume-title {
    display: none;
  }
  /* Cover-aside is the third flex column on mobile, holding specs + link
     stacked vertically. Replaces the cover-thumb's role in the row. */
  #webapp-tint .cover-aside {
    flex: 1 1 auto;
    min-width: 0;
    align-self: flex-start;
    margin-top: 0;               /* drop the desktop "below the cover thumb"
                                    margin — in row layout the aside sits
                                    next to the badge, not below it */
    padding-top: .15em;          /* baseline-align with the title beneath the numeral */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(10px, 1.6vh, 16px);
  }
  /* Specs sit at the top of the aside; link beneath. Shrunk 25% to
     give the back-cover thumb more visual weight on mobile. */
  #webapp-tint .cover-specs {
    margin: 0;
    font-size: clamp(5.6px, 1.46vw, 7.1px);
    letter-spacing: .12em;
    line-height: 1.65;
  }
  /* On mobile, drop nowrap and let long lines (the page-with-bleed line)
     break naturally instead of ellipsis-truncating. Reads cleaner as a
     small typewriter colophon block. */
  #webapp-tint .cover-specs li {
    white-space: normal;
  }
  /* Per-volume mobile label "Volume I" / "Volume II" / … is shown
     in the cover-aside above the specs block on Vols 1–5. Vol 0
     suppresses it (the project title takes the same slot via
     .cover-attribution-title). */
  #webapp-tint:not([data-n="0"]) .cover-volume-label {
    display: block;
  }
  /* Vol 0 mobile aside contents:
       1) The matched-pair byline (A NEW WORK BY / Richard Saul Wurman +
          AS TOLD TO… / Dan Klyn) does the project-identifying work
          itself, so the legacy .cover-attribution-title slot stays
          hidden here too — no separate "Richard Saul Wurman 5" line
          is needed above it.
       2) THE SET spec only (slipcase dimensions + each-volume specs
          are hidden on mobile to keep the aside short enough to fit) */
  #webapp-tint[data-n="0"] .cover-attribution-title {
    display: none;
  }
  #webapp-tint[data-n="0"] .cover-attribution-label,
  #webapp-tint[data-n="0"] .cover-attribution-name {
    display: block;
  }
  /* On portrait phones the dual byline (RSW + DK) is doing all the
     project-identifying work the aside needs — the colophon spec block
     just crowds the layout and pushes the volume list down. Hide it
     entirely here. (Desktop still shows the full SLIPCASE / BOXED SET /
     EACH VOLUME colophon.) */
  #webapp-tint[data-n="0"] .cover-specs.cover-specs-project {
    display: none;
  }
  /* Bring the Wurman + Klyn names down a notch in portrait so
     "Richard Saul Wurman" reads cleanly on one line instead of
     wrapping across two narrow ones. */
  #webapp-tint[data-n="0"] .cover-attribution-name {
    font-size: clamp(18px, 5.4vw, 22px);
    line-height: 1.1;
    /* Tighten the trailing margin so the next label snugs up close. */
    margin-bottom: 0;
  }
  #webapp-tint[data-n="0"] .cover-attribution-label {
    font-size: clamp(7.5px, 2.4vw, 9px);
  }
  /* Pull the second attribution pair (AS TOLD TO… / Dan Klyn) up
     tight against the end of "Wurman" — the desktop 1.2em gap reads
     too airy in portrait where the column is narrow. */
  #webapp-tint[data-n="0"] .cover-attribution-label.cover-attribution-pair-2 {
    margin-top: .35em;
  }
  /* Vol 0 attribution + specs sit stacked in the right-column aside on
     mobile. The desktop's bottom-margin on .cover-attribution opens an
     unintended gap here on top of the cover-aside's flex gap — drop it
     to zero so the spec snugs cleanly under the project title instead
     of floating with a half-line of empty space above. The flex-gap
     on cover-aside still provides the small visual separation between
     the title block and the spec block. */
  #webapp-tint[data-n="0"] .cover-attribution {
    margin-bottom: 0;
  }
  #webapp-tint[data-n="0"] .cover-aside {
    gap: clamp(4px, 0.6vh, 8px);
  }
  #webapp-tint .cover-content {
    /* Match the cover-stack's horizontal frame so the thesis + TOC align
       under the badge. Top is snugged so the thesis paragraph sits just
       beneath the badge row instead of leaving a half-screen of empty
       paper between the colophon and the thesis. The previous
       clamp(200, 26vh, 260) was sized to the larger 39vw cover-thumb;
       now that the thumb has shrunk to 28vw the content panel can
       come up a corresponding amount and close the empty band that
       was opening between the cover-stack and the thesis on iOS
       Safari. */
    left: clamp(40px, 9vw, 56px);
    right: clamp(40px, 9vw, 56px);
    top: clamp(150px, 19vh, 200px);
    bottom: clamp(28px, 5vh, 56px);
    max-width: none;
  }
  /* Slightly smaller thesis on narrow screens. */
  #webapp-tint .v-thesis {
    font-size: clamp(16px, 4.3vw, 20px);
    line-height: 1.32;
    margin-bottom: 1.1em;
  }
  /* Inherit the single-column stacked layout from the desktop default;
     just tighten padding/row-gap and clamp the body type for narrow
     viewports. The chapter v-label sits as its own line above the
     v-title, both flush to the same left margin (no 2-column grid). */
  #webapp-tint .v-toc {
    font-size: clamp(13px, 3.6vw, 17px);
  }
  #webapp-tint .v-toc li {
    row-gap: .08em;
    padding: .5em 0;
  }
  /* Subline already small; keep it crisp on phones. */
  #webapp-tint .v-toc .v-subline {
    font-size: .8em;
    line-height: 1.35;
  }
  /* Mobile close affordance: matches the desktop word treatment —
     plain "MENU" (or "CLOSE" on Vol 0) in HN Medium 9px with .22em
     tracking, all caps. Same typographic voice as the rest of the
     menu chrome on every viewport. The previous mobile-only minus-
     stroke replacement is gone; the button is once again a labeled
     text affordance. !important on the position/sizing because the
     desktop default close-btn rule sits LATER in source order at the
     same specificity. The 44×44 hit-target stays so the button is
     still tappable on a phone — only the visible glyph changes. */
  /* Mobile: match the nav-strip arrow's top to the close-btn's top so
     ←, TOC/CLOSE, → all share a baseline at the very top of the
     viewport instead of the desktop's 28px offset. */
  #webapp-tint .nav-strip::before {
    top: max(env(safe-area-inset-top, 0px), 6px);
  }
  #webapp-tint .close-btn {
    top: max(env(safe-area-inset-top, 0px), 6px) !important;
    /* Bumped from 6px → 32px so the MENU/CLOSE word clears the
       16-px-wide right nav-strip plus its own breathing room without
       getting clipped against the device edge. */
    right: max(env(safe-area-inset-right, 0px), 32px) !important;
    min-width: 44px;
    min-height: 44px;
    padding: 6px 10px !important;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif !important;
    font-weight: 500;
    font-size: 9px !important;
    letter-spacing: .22em !important;
    text-transform: uppercase;
    opacity: .55;
  }
  #webapp-tint .close-btn:hover,
  #webapp-tint .close-btn:focus {
    opacity: .92;
  }
}

/* ----- Tiny phones (≤ 380 px wide): drop the label column and stack
        each TOC entry as label-then-title on two lines. ----- */
/* Narrow-viewport tightening. The stacked left-aligned layout is the
   default at every viewport; the rules below only adjust sizes and
   spacing for a phone screen — chapter title bumped a touch larger to
   anchor the group, sub-title and labels shaved a touch smaller, row
   padding tightened so the menu doesn't sprawl on a tall narrow
   viewport. The hierarchy on a phone reads (largest → smallest):
       chapter title     1.1em    (anchors the group)
       sub title         .85em    (children of the chapter)
       chapter label    .62em    (CH I, CH II … barely a whisper)
       sub label         .55em    (ESSAY, MARGINALIA … same family) */
@media (max-width: 600px) and (orientation: portrait) {
  #webapp-tint .v-toc li {
    padding: .65em 0;
    row-gap: .12em;
  }
  #webapp-tint .v-toc .v-label {
    font-size: .62em;
    opacity: .65;
  }
  #webapp-tint .v-toc .v-title {
    font-size: 1.1em;
    line-height: 1.2;
  }
  #webapp-tint .v-toc .v-subs {
    margin: .3em 0 .1em 0;
  }
  #webapp-tint .v-toc .v-subs li.sub {
    padding: .25em 0;
  }
  #webapp-tint .v-toc .v-subs .sub-label {
    font-size: .55em;
    opacity: .55;
    margin-bottom: .08em;
  }
  #webapp-tint .v-toc .v-subs .sub-title {
    font-size: .85em;
    line-height: 1.25;
  }
}

/* ===== Lateral nav strips ===== */

#webapp-tint .nav-strip {
  position: absolute;
  top: 0; bottom: 0;
  /* Slimmed from 28px → 16px so the rails read as a quieter
     directional hint rather than a chunky chrome element. The arrow
     glyph + tiny numeral both still fit comfortably in the slimmer
     width; on hover the strip widens to 22px (was 36px) to telegraph
     the same "tap me" affordance at a more proportional scale. */
  width: 16px;
  cursor: pointer;
  z-index: 5;
  transition: width .2s ease, filter .2s ease;
}
#webapp-tint .nav-strip:hover  { width: 22px; filter: brightness(1.08); }
#webapp-tint .nav-strip:active { filter: brightness(.94); }
#webapp-tint .nav-prev { left: 0;  border-right: 1px solid color-mix(in srgb, currentColor 8%, transparent); }
#webapp-tint .nav-next { right: 0; border-left:  1px solid color-mix(in srgb, currentColor 8%, transparent); }
#webapp-tint .nav-strip.is-hidden { display: none; }

/* Tiny numeral at the bottom of each nav strip — labels its target volume.
   Uses the volume's body ink (inherited via currentColor) at low opacity
   so it reads quietly against the lighter menu backgrounds. */
#webapp-tint .nav-strip .nav-num {
  position: absolute;
  bottom: 18px; left: 0; right: 0;
  text-align: center;
  font: 100 11px/1 "HN UltraLight", "HN Thin", "Helvetica Neue", Helvetica, sans-serif;
  letter-spacing: .06em;
  color: currentColor;
  opacity: .5;
  pointer-events: none;
}

/* Lateral-navigation arrows — set in Sometimes Times Medium, which has
   a distinctive ← → pair that prompts the user to swipe / tap toward
   the adjacent volume's menu. Sized larger than the nav-num and
   centered vertically so the strip reads as a directional invitation
   rather than just a colored rail with a tiny numeral at the foot.
   Inherits currentColor at a slightly higher opacity than the num so
   the arrow becomes the dominant signal in the strip and the numeral
   reads as a quieter label beneath it.
   Hidden when the nav-strip is hidden (e.g. Vol 0 has no prev arrow,
   Vol 5 has no next arrow). */
#webapp-tint .nav-strip::before {
  position: absolute;
  /* Top offset matches the close-btn's top — arrows hang at the same
     vertical line as the TOC / CLOSE word so the three navigation
     affordances (← prev, TOC/CLOSE, → next) all sit on a shared top
     baseline across the viewport. The mobile media query overrides
     this to match the mobile close-btn position. */
  top: max(env(safe-area-inset-top, 0px), 28px);
  left: 0; right: 0;
  text-align: center;
  font-family: "Sometimes Times", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 14px;
  line-height: 1;
  color: currentColor;
  opacity: .75;
  pointer-events: none;
  /* Animate gently when the strip widens on hover so the arrow feels
     responsive to the user's intent. */
  transition: opacity .2s ease, transform .2s ease;
}
#webapp-tint .nav-prev::before { content: "\2190"; }   /* ← LEFTWARDS ARROW */
#webapp-tint .nav-next::before { content: "\2192"; }   /* → RIGHTWARDS ARROW */
#webapp-tint .nav-strip:hover::before {
  opacity: 1;
}
#webapp-tint .nav-prev:hover::before {
  transform: translateX(-3px);   /* slight nudge toward the destination */
}
#webapp-tint .nav-next:hover::before {
  transform: translateX(3px);
}

/* ===== Recessed-hemisphere close button ===== */

#webapp-tint .close-btn {
  /* Plain-text CLOSE — same type as the RESET word in the home-view
     caption: HN Medium 9px, .22em tracking, all caps. Color inherits
     from the volume's --pg-N-dark, so it matches the rest of the menu
     typography on every volume (including Vol 4's flat-white inversion). */
  position: absolute;
  top: max(env(safe-area-inset-top, 0px), 28px);
  right: max(env(safe-area-inset-right, 0px), 60px);
  background: transparent;
  border: 0;
  padding: 6px 4px;
  margin: 0;
  cursor: pointer;
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: inherit;
  opacity: .55;
  transition: opacity .15s ease;
}
#webapp-tint .close-btn:hover,
#webapp-tint .close-btn:focus {
  opacity: .92;
  outline: none;
}

/* PRINT — twin of the CLOSE button, summoning the Build-PDF dialog
   from the volume menu instead of waiting for the 555 keystroke.
   Hidden by default; only revealed at viewports ≥ 1024px wide (iPad
   landscape and up), since hard-copy review is a desktop workflow
   and the dialog isn't useful on phone or iPad-portrait screens. */
#webapp-tint .print-btn {
  display: none;
  position: absolute;
  top: max(env(safe-area-inset-top, 0px), 28px);
  right: calc(max(env(safe-area-inset-right, 0px), 60px) + 60px);
  background: transparent;
  border: 0;
  padding: 6px 4px;
  margin: 0;
  cursor: pointer;
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: inherit;
  opacity: .55;
  transition: opacity .15s ease;
}
@media (min-width: 1024px) {
  #webapp-tint .print-btn { display: inline-block; }
}
#webapp-tint .print-btn:hover,
#webapp-tint .print-btn:focus {
  opacity: .92;
  outline: none;
}

/* ===== Readable TOC items =====
   A TOC row carrying data-doc is a manuscript link. Cursor pointer +
   subtle hover affordance signal that the row is clickable into the
   reading mode. Inherits the volume's body ink via currentColor. */
#webapp-tint .v-toc [data-doc] {
  cursor: pointer;
}
#webapp-tint .v-toc [data-doc]:hover .sub-title,
#webapp-tint .v-toc [data-doc]:hover .v-title {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
  text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
}
/* "Single" sub-items have no inner span — text sits directly inside
   the <li>. Underline on hover applies to the whole row. */
#webapp-tint .v-toc li.sub.single[data-doc]:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
  text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
}

/* TOC rows carrying data-image (poster / plate references) get the
   same cursor + underline-on-hover affordance as data-doc rows. */
#webapp-tint .v-toc [data-image] {
  cursor: pointer;
}
#webapp-tint .v-toc [data-image]:hover .sub-title,
#webapp-tint .v-toc [data-image]:hover .v-title {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
  text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
}
/* Frame rows (PRELUDE, CODA, ABSTRACT, GALLERY) carry an empty v-title.
   When a frame row has data-doc, the underline-on-hover affordance
   targets the v-label instead, so the structural label itself is the
   visible link. */
#webapp-tint .v-toc li.frame[data-doc]:hover .v-label {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
  text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
}

/* The wordmark under the big numeral is hidden across every volume —
   the volume's identity is already carried by the LustSpine numeral
   above, the thesis blurb in the body column, and (for Vols 1, 2, 3, 5)
   the same title appearing on the canonical book back cover. The
   VOL_TITLES entries stay intact in JS for use elsewhere (PDF filename
   slug, accessibility, the cover-thumb back face, the 3D book back
   cover, future surfaces). */
#webapp-tint .cover-title {
  display: none;
}

/* ===== Reading mode overlay =====
   Full-screen text reader. Cream-paper ground (the slipcase outer
   color), Mercure Regular body at ~78% ink, **bold** rendered as
   faux-bold via FULL ink saturation — Mercure has no real bold so
   emphasis is encoded as a darker mark, not a thicker one. Italic stays
   real Mercure Italic. Sits above #webapp-tint and #webapp-cover-overlay. */
#webapp-reader {
  position: fixed;
  inset: 0;
  z-index: 90;
  /* Salmon paper — same warm ground as the slipcase home view, so the
     reading mode reads as a continuation of the PWA's environment
     rather than a new sheet of paper. Print mode swaps this for true
     white below. */
  background: var(--paper, #E5A597);
  opacity: 0;
  visibility: hidden;
  transition: opacity .35s ease, visibility 0s linear .35s;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Reader body type-size multiplier — driven by the A−/A+ controls
     in the chrome and persisted in localStorage. 1 = design default. */
  --reader-scale: 1;
  /* Subtle scrollbar matching the menu's whisper-quiet treatment. */
  scrollbar-width: thin;
  scrollbar-color: rgba(40, 36, 28, .14) transparent;
}
#webapp-reader.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity .35s ease, visibility 0s linear 0s;
}
#webapp-reader::-webkit-scrollbar { width: 1px; }
#webapp-reader::-webkit-scrollbar-track { background: transparent; }
#webapp-reader::-webkit-scrollbar-thumb {
  background: rgba(40, 36, 28, .32);
  border-radius: 0;
  min-height: 44px;       /* discreet handle, grabbable on a 1px track */
}
#webapp-reader::-webkit-scrollbar-thumb:hover {
  background: rgba(40, 36, 28, .56);
}

/* Sticky chrome strip — breadcrumb context on the left, CLOSE on the
   right. Fades the cream ground out below it so body text scrolling
   under the strip doesn't read as a hard-edged occlusion. */
#webapp-reader .reader-chrome {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: max(env(safe-area-inset-top, 0px), 14px) clamp(20px, 5vw, 56px) 14px;
  background: linear-gradient(
    to bottom,
    var(--paper, #E5A597) 0%,
    var(--paper, #E5A597) 70%,
    color-mix(in srgb, var(--paper, #E5A597) 80%, transparent) 100%
  );
}
#webapp-reader .reader-context {
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(40, 36, 28, .55);
  line-height: 1.4;
  padding-top: 4px;
}
/* Two-space gap between the project prefix ("Richard Saul Wurman 5")
   and the per-piece address ("Volume 5 · Part I"). em-units track the
   text size if the user later resizes. */
#webapp-reader .reader-context-project {
  margin-right: 1.6em;
}
#webapp-reader .reader-context-address:empty {
  display: none;
}
/* File-format links (the .md source and the .icml InDesign download).
   Inherit the header's quiet ink color rather than rendering as the
   browser-default blue. Subtle underline as the link affordance. */
#webapp-reader .reader-context-address {
  margin-right: 1.6em;
}
#webapp-reader .reader-context-file {
  display: inline-block;
  margin-right: 1em;
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 0.22em;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  cursor: pointer;
  transition: color .15s ease, text-decoration-color .15s ease;
}
#webapp-reader .reader-context-file:hover,
#webapp-reader .reader-context-file:focus {
  color: rgba(40, 36, 28, .92);
  text-decoration-color: rgba(40, 36, 28, .92);
  outline: none;
}
#webapp-reader .reader-context-file:empty {
  display: none;
}
#webapp-reader .reader-close,
#webapp-reader .reader-tool {
  font-family: "HN Medium", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(40, 36, 28, .55);
  background: transparent;
  border: 0;
  padding: 4px 6px;
  cursor: pointer;
  transition: color .15s ease;
  flex: 0 0 auto;
}
#webapp-reader .reader-close:hover,
#webapp-reader .reader-close:focus,
#webapp-reader .reader-tool:hover,
#webapp-reader .reader-tool:focus {
  color: rgba(40, 36, 28, .92);
  outline: none;
}
/* The A−/A+/PDF cluster sits between the breadcrumb context and the
   CLOSE word, with a slim divider between it and CLOSE so the action
   group reads as its own affordance row. */
#webapp-reader .reader-tools {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;        /* push the cluster all the way right */
  padding-right: 14px;
  border-right: 1px solid rgba(40, 36, 28, .14);
  margin-right: 14px;
}

/* ===== Mobile reader chrome — three-zone layout.
   TOP-LEFT  : tools cluster (A− A+ PDF MD ICML)
   TOP-RIGHT : CLOSE
   BOTTOM    : centered breadcrumb strip (VOLUME · CHAPTER · SECTION),
               position: fixed, with a soft paper gradient so body text
               scrolls behind it instead of bumping into a hard edge.
   The project prefix ("Richard Saul Wurman 5") drops out — the slipcase
   home view already establishes the project. ===== */
@media (max-width: 700px) {
  #webapp-reader .reader-chrome {
    align-items: center;
    gap: 8px;
    padding-top: max(env(safe-area-inset-top, 0px), 10px);
    padding-left:  clamp(14px, 4vw, 24px);
    padding-right: clamp(14px, 4vw, 24px);
    padding-bottom: 10px;
  }
  /* Breadcrumb pulled out of the top chrome and pinned to the bottom of
     the viewport so body text scrolls under it. */
  #webapp-reader .reader-context {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 6;
    margin: 0;
    padding: 14px clamp(14px, 4vw, 24px) max(env(safe-area-inset-bottom, 0px), 14px);
    text-align: center;
    font-size: 9px;
    letter-spacing: .18em;
    line-height: 1.3;
    pointer-events: none;       /* breadcrumb is not interactive */
    background: linear-gradient(
      to top,
      var(--paper, #E5A597) 0%,
      var(--paper, #E5A597) 60%,
      color-mix(in srgb, var(--paper, #E5A597) 80%, transparent) 100%
    );
  }
  #webapp-reader .reader-context-project { display: none; }
  #webapp-reader .reader-context-address { margin-right: 0; }
  /* Tools cluster lives at the TOP-LEFT — push CLOSE to the right via
     margin-right: auto. Slim divider keeps the cluster reading as a
     unit distinct from CLOSE. */
  #webapp-reader .reader-tools {
    margin-left: 0;
    margin-right: auto;
    padding-right: 10px;
    border-right: 1px solid rgba(40, 36, 28, .14);
    gap: 4px;
  }
  #webapp-reader .reader-tool,
  #webapp-reader .reader-close {
    font-size: 9.5px;
    letter-spacing: .18em;
    padding: 6px 4px;
  }
  /* Body gets bottom padding so the last lines clear the fixed
     bottom-strip breadcrumb instead of disappearing under it. */
  #webapp-reader .reader-page {
    padding-bottom: clamp(80px, 14vh, 140px);
  }
}
#webapp-reader .reader-tool {
  /* Slightly tighter tracking than CLOSE — these are quick toggles. */
  letter-spacing: .14em;
  padding: 4px 4px;
}

/* The reading page itself — a single comfortable measure column. */
#webapp-reader .reader-page {
  max-width: 680px;
  margin: 0 auto;
  padding: clamp(40px, 6vh, 80px) clamp(24px, 5vw, 56px) clamp(80px, 12vh, 140px);
}

/* Document head: title (Mercure Italic, full ink), subtitle (Mercure
   Regular, knocked back), attribution (Mercure Transcript, all caps). */
#webapp-reader .reader-meta {
  text-align: center;
  margin-bottom: clamp(40px, 7vh, 80px);
}
#webapp-reader .reader-title {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(28px, 4vw, 40px);
  line-height: 1.15;
  letter-spacing: -0.005em;
  color: #1a1612;
  margin: 0 0 .25em 0;
}
#webapp-reader .reader-subtitle {
  font-family: "Mercure", Georgia, serif;
  font-style: normal;
  font-weight: 400;
  font-size: clamp(15px, 1.7vw, 19px);
  line-height: 1.4;
  color: rgba(40, 36, 28, .76);
  margin: 0;
}
#webapp-reader .reader-subtitle:empty,
#webapp-reader .reader-attribution:empty {
  display: none;
}
#webapp-reader .reader-attribution {
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-weight: 400;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(40, 36, 28, .55);
  margin: 1.6em 0 0 0;
}
/* Two-line attribution stack: byline (author · date · location) above,
   stats (word count · last updated) below. Both spans inherit the
   parent's mono caps treatment so the header reads as one block. The
   stats line is knocked back a hair so the byline (when present)
   stays primary. */
#webapp-reader .reader-attribution .reader-byline,
#webapp-reader .reader-attribution .reader-stats {
  display: block;
}
#webapp-reader .reader-attribution .reader-byline + .reader-stats {
  margin-top: .5em;
  opacity: .72;
}

/* Body — Mercure Regular at ~78% ink. The faux-bold magic happens here:
   <strong> uses font-weight: 400 (no synthetic bolding) and bumps color
   to full pure ink. Italic uses real Mercure Italic glyphs. */
#webapp-reader .reader-body {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-style: normal;
  font-weight: 400;
  /* Scaled by --reader-scale (driven by the A−/A+ controls). */
  font-size: calc(clamp(16px, 1.45vw, 19px) * var(--reader-scale, 1));
  line-height: 1.65;
  color: rgba(40, 36, 28, .82);
}
/* Desktop: bump the reader body's base size by four A+ steps (each
   step is +0.08 in the JS-driven --reader-scale, so four steps =
   ×1.32). The A−/A+ controls still scale on top of this base, so a
   user can fine-tune from a comfortable starting point on a wider
   screen. Mobile keeps the unboosted base — phone screens already
   render the body at a comfortable size relative to the viewport. */
@media (min-width: 701px) {
  #webapp-reader .reader-body {
    font-size: calc(clamp(16px, 1.45vw, 19px) * 1.32 * var(--reader-scale, 1));
  }
}
#webapp-reader .reader-body p {
  margin: 0 0 1.2em 0;
}
#webapp-reader .reader-body strong {
  /* Faux-bold: Mercure has no real bold, so emphasis is encoded as
     color saturation. Body sits at .82 ink; bold rises to full pure
     ink (#000) — a darker mark, not a thicker one. */
  font-weight: 400;
  color: #000;
}
#webapp-reader .reader-body em,
#webapp-reader .reader-body i {
  font-style: italic;
}
#webapp-reader .reader-body h1,
#webapp-reader .reader-body h2,
#webapp-reader .reader-body h3,
#webapp-reader .reader-body h4 {
  font-family: "Mercure", Georgia, serif;
  font-style: italic;
  font-weight: 400;
  color: #1a1612;
  letter-spacing: -.005em;
  line-height: 1.2;
  margin: 1.8em 0 .55em 0;
}
#webapp-reader .reader-body h1 { font-size: 1.55em; }
#webapp-reader .reader-body h2 { font-size: 1.32em; }
#webapp-reader .reader-body h3 { font-size: 1.12em; }
#webapp-reader .reader-body h4 { font-size: 1em; text-transform: uppercase; letter-spacing: .12em; font-style: normal; opacity: .7; }
/* Brief flash on the heading the user just jumped to from the glossary
   search — quick wash of warm paper that fades within ~1.6s. */
#webapp-reader .reader-body .is-search-target {
  background: rgba(229, 165, 151, .35);
  box-shadow: 0 0 0 .25em rgba(229, 165, 151, .35);
  transition: background-color 1.4s ease, box-shadow 1.4s ease;
}
#webapp-reader .reader-body h1.is-search-target,
#webapp-reader .reader-body h2.is-search-target,
#webapp-reader .reader-body h3.is-search-target,
#webapp-reader .reader-body h4.is-search-target {
  scroll-margin-top: 1em;
}
#webapp-reader .reader-body blockquote {
  margin: 1.4em .4em 1.4em 1em;
  padding: .1em 0 .1em 1em;
  border-left: 2px solid rgba(40, 36, 28, .2);
  color: rgba(40, 36, 28, .68);
  font-style: italic;
}

/* ============================================================
   Reader: <figure.broadside>
   ============================================================
   In V2 Ch IV the 'Commish prints his "Six IOUs" on the front page
   of the *What-If Daily Wonder*. The manuscript wraps that printed
   broadside in <figure class="broadside">…</figure> and the rules
   below dress it as a small typeset newspaper inset:
     - a Mercure Transcript kicker line ("From the front page of…")
     - a centered HN UltraLight title
     - a numbered list with hung Roman numerals + bold leads
     - paired hairline rules top and bottom (a "double rule" feel)

   The treatment is opt-in (any manuscript can use it) but exists
   primarily for The Six IOUs. Lives inside .reader-body so it
   inherits the reader's text color and serif body type.
   ============================================================ */
/* ============================================================
   Reader: <figure.fable-aside>
   ============================================================
   A boxed companion story that rides alongside a marginalia
   piece — used first for the 'Commish-voice walnut episode that
   sits inside 088-brains-measured-in-walnuts. Subtle inset card
   with a small uppercase kicker; preserves the body type so the
   prose still reads like prose, just visually held apart.
   ============================================================ */
#webapp-reader .reader-body figure.fable-aside {
  margin: 2em 0;
  padding: 1.4em 1.6em 1.2em;
  border: 1px solid rgba(40, 36, 28, 0.18);
  background: rgba(40, 36, 28, 0.035);
  border-radius: 2px;
}
#webapp-reader .reader-body figure.fable-aside figcaption {
  font-family: "Mercure-Transcript", "Mercure-Regular", Georgia, serif;
  font-size: 0.78em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(40, 36, 28, 0.62);
  margin-bottom: 1em;
  padding-bottom: 0.55em;
  border-bottom: 1px solid rgba(40, 36, 28, 0.18);
}
#webapp-reader .reader-body figure.fable-aside p {
  margin: 0 0 0.9em 0;
}
#webapp-reader .reader-body figure.fable-aside p:last-child {
  margin-bottom: 0;
}

#webapp-reader .reader-body figure.broadside {
  margin: 2.4em auto;
  max-width: 32em;
  padding: 1.8em 1.6em 1.7em;
  position: relative;
  border-top: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  font-style: normal;     /* don't inherit any italic from a wrapping block */
}
#webapp-reader .reader-body figure.broadside::before,
#webapp-reader .reader-body figure.broadside::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: currentColor;
  opacity: .55;
  pointer-events: none;
}
#webapp-reader .reader-body figure.broadside::before { top: 5px; }
#webapp-reader .reader-body figure.broadside::after  { bottom: 5px; }

#webapp-reader .reader-body figure.broadside .broadside-kicker {
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: .68em;
  text-align: center;
  opacity: .68;
  margin: 0 0 1.4em;
  font-style: normal;
}
#webapp-reader .reader-body figure.broadside .broadside-kicker em {
  font-style: italic;
  letter-spacing: .12em;
}

#webapp-reader .reader-body figure.broadside .broadside-title {
  /* Mercure Italic — gives the title an editorial / period-newspaper
     slant. Stays in the Mercure family so the broadside reads as
     typeset on the same press as the body around it. Title is set as
     two stacked lines: line 1 is the possessive phrase ("Every
     Instruction-Giver's"); line 2 is a big numeral 6 followed by
     "IOUs". The numeral pulls the eye down to the list below. */
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 400;
  font-size: 1.9em;
  line-height: 1;
  text-align: center;
  margin: 0 0 1em;
  letter-spacing: .002em;
}
#webapp-reader .reader-body figure.broadside .broadside-title-line1 {
  display: block;
  font-size: .58em;
  letter-spacing: .02em;
  margin-bottom: .25em;
  opacity: .82;
}
#webapp-reader .reader-body figure.broadside .broadside-title-line2 {
  display: block;
  line-height: 1;
  /* Mercure Regular for the whole line. The numeral and the spelled-
     out "I Owe You"s sit together as one clean serif anchor under
     the italic possessive line above. Dark charcoal for presence
     against the salmon ground. */
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-style: normal;
  font-weight: 400;
  font-size: 1.55em;
  letter-spacing: 0;
  color: #2a2d33;
}
#webapp-reader .reader-body figure.broadside .broadside-numeral {
  /* The numeral keeps a small size bump as the visual anchor; font
     family / weight cascade from .broadside-title-line2 above (now
     also Mercure Regular). */
  font-size: 1.25em;
  line-height: .95;
  letter-spacing: 0;
  margin-right: .18em;
  vertical-align: -.04em;
  font-style: normal;
  font-weight: 400;
}

#webapp-reader .reader-body figure.broadside .broadside-list {
  list-style: none;
  counter-reset: broadside-counter;
  padding: 0;
  margin: 0;
}
#webapp-reader .reader-body figure.broadside .broadside-list li {
  counter-increment: broadside-counter;
  position: relative;
  padding: .35em 0 .35em 2.1em;
  margin: 0;
  line-height: 1.45;
  font-style: normal;
  border: 0;
}
#webapp-reader .reader-body figure.broadside .broadside-list li + li {
  border-top: 1px solid color-mix(in srgb, currentColor 18%, transparent);
}
#webapp-reader .reader-body figure.broadside .broadside-list li::before {
  content: counter(broadside-counter) ".";
  position: absolute;
  left: 0;
  top: .42em;
  width: 1.6em;
  text-align: right;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-size: .82em;
  letter-spacing: .04em;
  opacity: .68;
}
#webapp-reader .reader-body figure.broadside .broadside-list li strong {
  /* Display:block stacks the bold lead ("I owe you the Mission.") on
     its own line above the explication ("Why I am asking you to do
     this at all."). Reads as headline-then-deck, so each IOU lands
     as its own little entry rather than a run-on sentence. */
  display: block;
  font-weight: 600;
  letter-spacing: .005em;
  margin-bottom: .18em;
}
/* Lists — bulleted (`-` / `*`) and numbered (`1.` / `2.`). Hanging
   indent so wraps align with the first character of the item text,
   not the bullet/number. */
#webapp-reader .reader-body ul,
#webapp-reader .reader-body ol {
  margin: 0 0 1.2em 0;
  padding-left: 1.5em;
}
#webapp-reader .reader-body li {
  margin: 0 0 .35em 0;
  padding-left: .15em;
}
#webapp-reader .reader-body ul {
  list-style-type: none;
}
#webapp-reader .reader-body ul > li {
  position: relative;
}
#webapp-reader .reader-body ul > li::before {
  /* Subtle middle-dot bullet — quieter than a dash, matches the spec
     colophon's hairline aesthetic. */
  content: "·";
  position: absolute;
  left: -.95em;
  top: 0;
  color: rgba(40, 36, 28, .55);
  font-weight: 400;
}
#webapp-reader .reader-body ol {
  list-style-type: decimal;
}
#webapp-reader .reader-body hr {
  border: 0;
  height: 1px;
  background: rgba(40, 36, 28, .15);
  margin: 2.4em auto;
  width: 4em;
}

/* ===== Glyph etymology table — used in marginalia on punctuation,
   alphabet history, etc. Three columns: a centered, large glyph; the
   bold name of the mark; an etymology phrase smaller and dimmer than
   body, with foreign words italicized. Borrows the Wurman three-column
   listing logic — clean, scannable, and fast. ===== */
#webapp-reader .reader-body .glyph-gallery {
  margin: 3.4em 0 3.4em;
}
#webapp-reader .reader-body .glyph-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0;
}
#webapp-reader .reader-body .glyph-table tr {
  border-top: 1px solid rgba(40, 36, 28, .12);
}
#webapp-reader .reader-body .glyph-table tr:last-child {
  border-bottom: 1px solid rgba(40, 36, 28, .12);
}
#webapp-reader .reader-body .glyph-table td {
  vertical-align: middle;
  padding: .55em .75em;
}
#webapp-reader .reader-body .glyph-table td.glyph {
  width: 2.2em;
  font-family: "King's Caslon Display Regular", "King's Caslon Display", "Source Serif Pro", Georgia, serif;
  font-size: 1.55em;
  line-height: 1;
  text-align: center;
  color: rgba(40, 36, 28, .92);
  padding-left: .25em;
  padding-right: 1em;
}
#webapp-reader .reader-body .glyph-table td.name {
  width: 8.5em;
  font-family: inherit;
  font-size: .98em;
  white-space: nowrap;
}
#webapp-reader .reader-body .glyph-table td.name strong {
  font-weight: normal;            /* Wurman faux-bold via full ink */
  color: rgba(40, 36, 28, 1);
}
#webapp-reader .reader-body .glyph-table td.etym {
  font-size: .88em;
  color: rgba(40, 36, 28, .72);
  line-height: 1.4;
}
#webapp-reader .reader-body .glyph-table td.etym em {
  font-style: italic;
  color: rgba(40, 36, 28, .82);
}
@media (max-width: 700px) {
  #webapp-reader .reader-body .glyph-table td.glyph {
    width: 1.8em;
    font-size: 1.4em;
    padding-right: .6em;
  }
  #webapp-reader .reader-body .glyph-table td.name {
    width: auto;
  }
  #webapp-reader .reader-body .glyph-table td {
    padding: .5em .35em;
  }
}

/* Verse mode: paragraphs are stanzas; single newlines (rendered as
   <br>) are line breaks. Paragraph margin separates stanzas; the
   first-line indent that prose paragraphs sometimes use is suppressed. */
#webapp-reader .reader-body.is-verse p {
  margin: 0 0 1.4em 0;
}

/* Inline editorial accent — manuscript files mark words with <red>...</red>
   and the parser converts that to a span with this class. Used for
   word-level emphasis that needs more than italic alone (e.g. the V1
   Prelude's "where" key word). */
#webapp-reader .reader-body .reader-red {
  color: #b03028;
}

/* ===== Reader print stylesheet =====
   Triggered by the PDF button (window.print()). The browser's print
   dialog offers Save-as-PDF on macOS / Chrome / most modern setups. We
   hide everything outside the reader, swap the cream paper for true
   white print stock, drop the chrome strip, and give the body 1-inch
   margins. The faux-bold treatment is preserved (full ink, normal
   weight) so what reads bold on screen reads bold on paper. */
/* Print-only elements — hidden on screen; revealed by @media print. */
.print-footer,
.print-page-head {
  display: none;
}
/* Running-footer string source — always in the layout (so string-set
   evaluates and the @page @bottom-left content has a value to display
   in print) but never visible. Positioned off-screen with size zero. */
.print-citation-source {
  string-set: citation content();
  position: absolute;
  top: -1000px;
  left: -1000px;
  width: 0;
  height: 0;
  overflow: hidden;
  visibility: hidden;
  pointer-events: none;
}

@media print {
  /* Generous @page margins reserve space for the bottom-center page
     number. Body content lives strictly inside these margins, so it
     can't overlap the number. */
  @page {
    size: letter;
    margin: 0.9in 0.9in 1.05in 0.9in;
    /* Per-page running footer. @bottom-left carries the citation
       breadcrumb (populated by stampPrintFooter via string-set on the
       hidden .print-citation-source span); @bottom-right carries the
       page number. Chrome, Safari (17.4+), Edge, and Firefox (138+)
       honor string() in @page margin boxes — older browsers get the
       page number alone. */
    @bottom-left {
      content: string(citation);
      font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
      font-size: 7.5pt;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: #6b6359;
      vertical-align: top;
      padding-top: 10pt;
    }
    @bottom-right {
      content: counter(page);
      font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
      font-size: 8.5pt;
      letter-spacing: .15em;
      color: #6b6359;
      vertical-align: top;
      padding-top: 10pt;
    }
  }

  body > *:not(#webapp-reader) {
    display: none !important;
  }
  /* Force the html element's grounds (set in two places — an inline
     <head> style as #E5A597 salmon, AND a slipcase.css rule that paints
     a cream radial-gradient on html,body to anchor the 3D scene) to
     pure white for print. The radial-gradient is the actual culprit
     behind the cream/tan rectangle that prints on the last page below
     the colophon. The shorthand `background: #fff !important` should
     reset background-image, but we nail background-image explicitly
     below to defeat any cascade quirk. (The body rule below still wins
     for <body>, since it has the same specificity and is later in the
     cascade — that's where the DRAFT watermark gets reapplied.) */
  html {
    background: #fff !important;
    background-image: none !important;
    background-color: #fff !important;
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  /* DRAFT watermark lives on <body> so it covers EVERY printed page in
     full, including the empty area below #webapp-reader on the last
     page. (Previously the watermark sat on #webapp-reader, which only
     extends to its content; the area between the reader's end and the
     @page bottom margin printed without the watermark and showed the
     html ground through, reading as a tan rectangle.) */
  body {
    background-color: #fff !important;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="320" height="320" viewBox="0 0 320 320"><g transform="rotate(-28 160 160)"><text x="160" y="160" fill="rgb(40,36,28)" fill-opacity="0.075" font-family="Helvetica,Arial,sans-serif" font-size="46" font-weight="700" letter-spacing="8" text-anchor="middle" dominant-baseline="middle">DRAFT</text></g></svg>') !important;
    background-repeat: repeat !important;
    background-size: 320px 320px !important;
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    color-adjust: exact !important;
    overflow: visible !important;
  }
  #webapp-reader {
    position: static !important;
    inset: auto !important;
    visibility: visible !important;
    opacity: 1 !important;
    /* Reader is transparent in print — the watermark + white ground
       are now carried by <body>, which covers the full page. */
    background: transparent !important;
    overflow: visible !important;
    height: auto !important;
    z-index: auto !important;
  }
  #webapp-reader .reader-chrome { display: none !important; }
  #webapp-reader .reader-page {
    max-width: none !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  /* ===== Title page suppressed =====
     The previous build included a centered title page (project banner
     + title + subtitle + attribution) with a hard page break before
     the body. That page is gone — the PDF now opens straight into the
     body type, with the page number running in the @bottom-center
     margin from page 1 forward. The print-page-head and reader-meta
     elements stay in the DOM (the on-screen reader uses them) but are
     hidden from print. */
  #webapp-reader .print-page-head,
  #webapp-reader .reader-meta {
    display: none !important;
  }

  /* ===== Body pages =====
     Set in Mercure throughout, body type bumped to 15pt with generous
     line-height and paragraph spacing — reads as a long-form printed
     piece rather than a screen-density transcript. Body color is held
     at canonical Payne's Grey (#3D4A57, --paynes from slipcase.css)
     so the faux-bold treatment on <strong> elements — which lands at
     pure #000 — pops with both a clear darkness-jump AND a hue shift
     from cool blue-gray body into pure neutral ink. Mercure has no
     bold cut so the project encodes emphasis as ink density rather
     than weight; this pairing makes the encoding read on print
     output (the prior near-black #1a1612 body left bolds visually
     indistinguishable from body text). */
  #webapp-reader .reader-body {
    font-family: "Mercure", Georgia, "Times New Roman", serif !important;
    font-size: 15pt !important;
    line-height: 1.75 !important;
    color: #3D4A57 !important;
  }
  /* Generous gap between paragraphs (and lists, blockquotes) — 1em of
     bottom margin at the new 15pt base reads as a full line of air,
     matching the breathing room you'd find in a printed essay. */
  #webapp-reader .reader-body p,
  #webapp-reader .reader-body blockquote {
    margin: 0 0 1em 0 !important;
  }
  #webapp-reader .reader-body strong {
    /* Faux-bold survives into print: normal weight, full pure ink. */
    font-weight: 400 !important;
    color: #000 !important;
  }
  #webapp-reader .reader-body em,
  #webapp-reader .reader-body i {
    font-style: italic !important;
  }

  /* ===== Page-break behavior — prefer blank space to orphans =====
     Goal: never split a paragraph or list item across pages, never
     strand a heading at the bottom of a page, and let pages run
     short rather than tear a thought across a fold.
     1. Every paragraph, blockquote, and list item is kept whole
        (`break-inside: avoid`). When a paragraph won't fit in the
        space remaining on the current page, the browser pushes it
        to the next page and leaves blank space behind — which is
        what we want.
     2. Headings and their following content stay together
        (`break-after: avoid-page` on the heading; the paragraph
        that follows is itself unbreakable, so the heading + first
        paragraph travel together to the next page if needed).
     3. Headings are themselves unbreakable.
     4. orphans/widows raised to 4 lines — backup measure for any
        block long enough to span pages despite break-inside: avoid
        (a paragraph longer than a full page, for instance). */
  #webapp-reader .reader-body p,
  #webapp-reader .reader-body blockquote,
  #webapp-reader .reader-body li,
  #webapp-reader .reader-body pre {
    page-break-inside: avoid;
    break-inside: avoid;
    orphans: 4;
    widows: 4;
  }
  #webapp-reader .reader-body h1,
  #webapp-reader .reader-body h2,
  #webapp-reader .reader-body h3,
  #webapp-reader .reader-body h4 {
    page-break-after: avoid;
    break-after: avoid-page;
    page-break-inside: avoid;
    break-inside: avoid;
  }
  /* Group each heading with the paragraph that immediately follows
     it — the heading is `break-after: avoid` and the paragraph is
     `break-inside: avoid`, so the pair will only break before the
     heading, never between them. */
  #webapp-reader .reader-body h2 {
    margin-top: 24pt;
  }
  /* HR (the markdown `---` section divider) — a clean place for the
     break-engine to find air. We don't force a break here; we just
     leave breaks permitted, since that's already a natural seam in
     the prose. */
  #webapp-reader .reader-body hr {
    page-break-before: auto;
    break-before: auto;
    page-break-after: auto;
    break-after: auto;
  }
  /* Tables (when they appear) get the same treatment. */
  #webapp-reader .reader-body table,
  #webapp-reader .reader-body figure {
    page-break-inside: avoid;
    break-inside: avoid;
  }

  /* Hide the slipcase scene + menu + cover overlay + toast. */
  .scene, #webapp-tint, #webapp-cover-overlay, #webapp-caption,
  #webapp-scale, #webapp-toast, #webapp-print-tip {
    display: none !important;
  }

  /* ===== End-of-document colophon =====
     One-time block at the very end of the printed document — date the
     PDF was generated, plus a draft-attribution / source line. Per-
     page numbering is handled separately by @page @bottom-center
     above; this block does not repeat. Replaces the old position:
     fixed footer, which Chrome refused to repeat reliably per page
     and ended up overlapping body content on the final page. */
  .print-footer {
    display: block !important;
    margin: .75in 0 0 0;
    padding: 12pt 0 0 0;
    border-top: 0.5pt solid rgba(40, 36, 28, .22);
    font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace !important;
    font-weight: 400;
    font-size: 8.5pt;
    letter-spacing: .14em;
    line-height: 1.6;
    text-transform: uppercase;
    color: rgba(40, 36, 28, .55) !important;
    text-align: center;
    page-break-inside: avoid;
    break-inside: avoid;
    /* Solid white ground so the DRAFT watermark behind <body> doesn't
       bleed through the colophon's text. The watermark continues
       elsewhere on the page; only the colophon block masks it. */
    background: #fff !important;
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    position: relative;
    z-index: 1;
  }
  .print-footer-date,
  .print-footer-source {
    display: block;
    margin: 0;
  }
}

/* ===== Update toast ===== */

#webapp-toast {
  position: fixed;
  bottom: max(env(safe-area-inset-bottom, 0px), 22px);
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 14px 10px 18px;
  background: rgba(43, 51, 64, .94);
  color: #fff;
  border-radius: 999px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .22);
  font: 500 11px/1 "HN Medium", "Helvetica Neue", Helvetica, sans-serif;
  letter-spacing: .14em;
  text-transform: uppercase;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease, transform .35s cubic-bezier(.2, .7, .25, 1);
}
#webapp-toast.is-on {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
#webapp-toast button {
  background: transparent;
  color: var(--paper);
  border: 1px solid rgba(229, 165, 151, .55);
  padding: 6px 12px;
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
  letter-spacing: .14em;
}
#webapp-toast button:hover { background: rgba(229, 165, 151, .12); }

/* ===== Print-tip toast =====
   Briefly surfaced when the user clicks the reader's PDF button. The
   tip steers them to uncheck "Headers and footers" in the OS print
   dialog so the browser's URL/page-count footer doesn't double up
   with our own bottom-center page number. Hidden in @media print so
   it never bleeds into the actual PDF output. */
#webapp-print-tip {
  position: fixed;
  bottom: max(env(safe-area-inset-bottom, 0px), 22px);
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  z-index: 110;
  max-width: min(560px, calc(100vw - 32px));
  padding: 12px 18px;
  background: rgba(43, 51, 64, .94);
  color: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .22);
  font: 500 12px/1.45 "HN Medium", "Helvetica Neue", Helvetica, sans-serif;
  letter-spacing: .04em;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease, transform .35s cubic-bezier(.2, .7, .25, 1);
  text-align: center;
}
#webapp-print-tip.is-on {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
#webapp-print-tip strong {
  letter-spacing: .14em;
  text-transform: uppercase;
  font-size: 10px;
  margin-right: 6px;
  color: var(--paper, #E5A597);
}
#webapp-print-tip em {
  font-style: normal;
  background: rgba(229, 165, 151, .18);
  padding: 1px 6px;
  border-radius: 4px;
  letter-spacing: .02em;
}

/* ============================================================
   Glossary in-document search (V5 Part II)
   ============================================================
   The Glossary doc carries an inline search input at the top of
   its body (between the word-count line and the first entry).
   Filters visible <h3> entry blocks live as the user types; the
   hidden class hides each h3 plus its trailing paragraphs until
   the next h3.

   Lives inside .reader-body so it picks up the salmon paper
   ground and the Mercure body family. The input itself sits in
   a soft white wash so it reads as a control without competing
   with the Mercure ink around it.
   ============================================================ */
#webapp-reader .reader-body .glossary-search {
  margin: 1.6em 0 2.4em;
}
#webapp-reader .reader-body .glossary-search-input {
  width: 100%;
  box-sizing: border-box;
  padding: .58em .85em;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 1em;
  font-style: normal;
  background: rgba(255, 255, 255, .38);
  border: 1px solid rgba(40, 36, 28, .25);
  border-radius: 3px;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
  transition: background-color .12s ease, border-color .12s ease;
}
#webapp-reader .reader-body .glossary-search-input::placeholder {
  color: rgba(40, 36, 28, .55);
  font-style: italic;
}
#webapp-reader .reader-body .glossary-search-input:focus {
  outline: none;
  border-color: rgba(40, 36, 28, .55);
  background: rgba(255, 255, 255, .58);
}
#webapp-reader .reader-body .glossary-search-status {
  margin: .5em 0 0;
  font-family: "Mercure Transcript", "Courier New", ui-monospace, monospace;
  font-size: .76em;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(40, 36, 28, .55);
  min-height: 1em;
}
/* Hidden entries during search filter. */
#webapp-reader .reader-body .glossary-entry-hidden {
  display: none;
}

/* ============================================================
   Vol 2 — orange-peel quilt overlay
   ============================================================
   "Some Quilts" gets the subtlest possible quilting motif layered
   behind everything in the Vol 2 menu. A canvas is injected as the
   first child of #webapp-tint by the quiltSetup IIFE in menu.js and
   painted with two concentric layers of arcs:
     1. continuous guide circles at very low alpha
     2. running-stitch dashes at slightly higher alpha
   The motif is hidden everywhere except data-n="2".

   Layering: #webapp-tint already establishes a stacking context
   (position:fixed; z-index:60), so a child at z-index:-1 paints
   ABOVE the tint's own per-volume background but BELOW every other
   child. The cover stack, chapter rows, nav strips, and close button
   all float on top of the quilt — the menu's words land on cloth.

   The reader overlay (#webapp-reader) is a higher-z sibling of
   #webapp-tint, so when it opens its salmon ground completely covers
   the quilting — quilting is a Vol 2 *menu* treatment only, not a
   reader treatment.

   Tunable via CSS custom properties on #webapp-tint (the JS reads
   them at paint time, so live-edit in DevTools works):
     --quilt-cell    circle radius / pitch in px (default 132)
     --quilt-opacity thread alpha 0–1            (default 0.032)
     --quilt-gap     stitch gap in px            (default 3)
   ============================================================ */
#webapp-tint > canvas.quilt-canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  display: none;
}
#webapp-tint[data-n="2"] > canvas.quilt-canvas {
  display: block;
}

/* ============================================================
   Print-for-Richard dialog
   ============================================================
   Triggered by typing "555" on any TOC view. Renders a modal
   overlay listing every manuscript chunk as a checkbox; user
   picks the pieces and clicks Build PDF to launch the browser's
   print dialog with a stylesheet tuned for Richard's annotation
   pass (see the @media print block at the bottom of this file).
   ============================================================ */
.richard-print-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 14, 0.55);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.richard-print-dialog {
  background: #f6f1e6;
  color: #1a1a1a;
  border-radius: 4px;
  max-width: 720px;
  width: 100%;
  max-height: 86vh;
  overflow-y: auto;
  padding: 1.6rem 2rem 1.2rem;
  position: relative;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
  font-family: Georgia, "Times New Roman", serif;
}

.richard-print-close {
  position: absolute;
  top: 0.4rem;
  right: 0.6rem;
  background: transparent;
  border: 0;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  color: rgba(0, 0, 0, 0.45);
  padding: 0.25rem 0.5rem;
}
.richard-print-close:hover { color: #000; }

.richard-print-title {
  margin: 0 0 0.35rem;
  font-size: 1.32rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.richard-print-blurb {
  margin: 0 0 0.9rem;
  font-size: 0.88rem;
  color: rgba(0, 0, 0, 0.7);
  line-height: 1.45;
}

/* Two-column flow layout (CSS columns instead of a rigid grid) so a
   short group like Slipcase doesn't leave a gaping hole next to V1
   Fable. Groups are kept atomic (no splitting mid-list) via
   break-inside:avoid, and the content packs top-down within each
   column. */
.richard-print-groups {
  column-count: 2;
  column-gap: 1.6rem;
  column-fill: balance;
}

.richard-print-group {
  border: 0;
  margin: 0 0 0.9rem 0;
  padding: 0;
  min-width: 0;
  break-inside: avoid;
  page-break-inside: avoid;
  -webkit-column-break-inside: avoid;
  display: block;
}
.richard-print-group:last-child {
  margin-bottom: 0;
}

.richard-print-group legend {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
  margin: 0 0 0.45rem;
  padding: 0;
  font-weight: 600;
}
/* Group header row — volume label on the left, marginalia plunger on
   the right (when the volume has marginalia available). */
.richard-print-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.45rem;
}
.richard-print-group-label {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
  font-weight: 600;
}
.richard-print-marg-toggle {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 0.74rem;
  color: rgba(0, 0, 0, 0.55);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
  white-space: nowrap;
}
.richard-print-marg-toggle:hover {
  color: #000;
}
.richard-print-marg-toggle[data-state="off"] {
  color: rgba(0, 0, 0, 0.4);
  font-style: italic;
}
/* Wrapper for the right-hand plungers in the group head — keeps
   marginalia + any extras (V3 Table / V3 Chart) grouped together on
   the right side of the row even when there are two or three of them. */
.richard-print-group-plungers {
  display: inline-flex;
  align-items: baseline;
  gap: 0.9rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}
/* Per-volume extra-content plunger (V3 Table / Chart) — visually
   identical to the marginalia plunger, separate class so future
   tweaks to one don't drag the other. */
.richard-print-extra-toggle {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 0.74rem;
  color: rgba(0, 0, 0, 0.55);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
  white-space: nowrap;
}
.richard-print-extra-toggle:hover {
  color: #000;
}
.richard-print-extra-toggle[data-state="off"] {
  color: rgba(0, 0, 0, 0.4);
  font-style: italic;
}
/* Rotated-content embeds (V3 Table / Chart) — render the standalone
   artifact on a portrait page with the content rotated 90° clockwise
   so it reads when the reader turns the printout sideways. All pages
   keep the same physical (portrait) shape, which matters for binding.

   The section is a portrait page-sized container. Inside, a stage div
   sits at the landscape dimensions of the page's content area and is
   rotated 90° via CSS transform. Either an iframe (table — sub-page
   HTML) or an img (chart — PNG poster, see fitting notes below) fills
   the stage. */
#richard-print-output .richard-doc-html-rotated {
  page-break-before: always;
  break-before: page;
  page-break-after: always;
  break-after: page;
  /* Portrait page content area (default @page margins on Letter are
     0.9 / 0.9 / 1.05 / 0.9): 6.7in × 9.05in. */
  width: 6.7in;
  height: 9.05in;
  margin: 0 auto;
  padding: 0;
  position: relative;
  overflow: hidden;
  background: #fff;
}
#richard-print-output .richard-doc-html-rotated-stage {
  /* The stage lives at the landscape rotation of the page content
     area (9.05in × 6.7in). After the 90° rotation, the visual
     bounding box matches the portrait page content area exactly.
     transform-origin: center keeps the rotated content centered. */
  position: absolute;
  top: 50%;
  left: 50%;
  width: 9.05in;
  height: 6.7in;
  transform: translate(-50%, -50%) rotate(90deg);
  transform-origin: center center;
}
/* Iframe inside the rotated stage (table — Questions Typology HTML
   sub-page). Initial dimensions are generous (1400 × 1000); the
   post-load fitRotatedIframe() in menu.js measures the sub-page's
   natural content size and applies a uniform scale transform so the
   rendered output fills the 9.05in × 6.7in stage interior. */
#richard-print-output .richard-doc-html-frame {
  width: 1400px;
  height: 1000px;
  border: 0;
  display: block;
  background: #fff;
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
}
/* Image embed inside the rotated stage (chart — Periodic Table of
   Questions PNG poster, rendered at 200 dpi from the standalone PDF).
   object-fit: contain keeps the poster's aspect ratio and centers it
   inside the stage; max-width / max-height let the image scale down
   to fit the stage without exceeding it. */
#richard-print-output .richard-doc-html-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center center;
  background: #fff;
}

.richard-print-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.1rem 0;
  font-size: 0.93rem;
  cursor: pointer;
  line-height: 1.3;
}
.richard-print-row.is-disabled {
  color: rgba(0, 0, 0, 0.32);
  cursor: not-allowed;
}
.richard-print-row input {
  margin: 0;
  cursor: pointer;
  flex-shrink: 0;
}
.richard-print-row.is-disabled input { cursor: not-allowed; }

.richard-print-actions {
  margin-top: 1.1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.richard-print-presets {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  align-items: center;
}
.richard-print-toggle {
  font-size: 0.88rem;
  color: rgba(0, 0, 0, 0.65);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
  background: transparent;
  border: 0;
  padding: 0.25rem 0;
}
.richard-print-toggle:hover {
  color: #000;
}
.richard-print-actions-end {
  display: flex;
  gap: 0.6rem;
  margin-left: auto;
}
.richard-print-actions button {
  font: inherit;
  font-size: 0.95rem;
  padding: 0.5rem 1.2rem;
  border-radius: 3px;
  border: 1px solid rgba(0, 0, 0, 0.25);
  cursor: pointer;
  background: #fff;
  color: inherit;
}
.richard-print-actions button:hover { background: #f0e9d8; }
.richard-print-actions .richard-print-preset {
  background: transparent;
  border: 1px dashed rgba(0, 0, 0, 0.3);
  font-style: italic;
  color: rgba(0, 0, 0, 0.78);
}
.richard-print-actions .richard-print-preset:hover {
  background: rgba(0, 0, 0, 0.04);
  border-style: solid;
  color: #000;
}
.richard-print-actions .richard-print-build {
  background: #1a1a1a;
  color: #f5f0e6;
  border-color: #1a1a1a;
}
.richard-print-actions .richard-print-build:hover {
  background: #000;
}

@media (max-width: 620px) {
  .richard-print-groups { grid-template-columns: 1fr; }
}

#richard-print-output { display: none; }

/* ============================================================
   Richard-PDF assembled output — measurement + print
   ============================================================
   The CSS for the assembled content lives at top level (not in
   @media print) so the JS can render the content off-screen at
   print-equivalent dimensions, measure each section's height, and
   compute the page number every section lands on. Once the page
   numbers are spliced into the TOC rows, the off-screen flag is
   removed and the browser's native print is invoked.
   ============================================================ */

/* Measurement mode: container is rendered at print width, but
   positioned off-screen so it doesn't show in the live UI. */
#richard-print-output.is-measuring {
  display: block;
  position: absolute;
  left: -10000px;
  top: 0;
  width: 5.5in;
  visibility: hidden;
}

/* Content styling — applies in BOTH measurement and print mode.
   Body type is Mercure (matching the on-screen reader), sized for
   hand-annotation comfort: two steps up from the original 13pt / 1.6
   (now 16pt / 1.85). Display elements (titles, page numbers, dividers)
   override to King's Caslon below. */
#richard-print-output .richard-print-doc {
  color: #000;
  background: #fff;
  margin: 0;
  padding: 0;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 16pt;
  line-height: 1.85;
}

/* ---- Title / Table of Contents page (always page 1) ---- */
#richard-print-output .richard-toc-page {
  page-break-after: always;
  break-after: page;
}
#richard-print-output .richard-toc-titleblock {
  text-align: center;
  margin: 0 0 0.5in;
  padding-bottom: 0.25in;
  border-bottom: 1.5px solid #000;
}
#richard-print-output .richard-toc-kicker {
  font-size: 10pt;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
  margin-bottom: 0.18in;
}
/* Cover title: "Richard Saul Wurman" in HN Thin, the "5" in HN Black.
   The two weights ride the same 36pt baseline so the volume number
   pops as a numeral. */
#richard-print-output .richard-toc-title {
  font-family: "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 200;
  font-size: 36pt;
  line-height: 1.1;
  margin: 0;
  letter-spacing: 0;
}
#richard-print-output .richard-toc-five {
  font-family: "HN Black", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 900;
  font-feature-settings: "lnum";
}
/* Byline below the title: HN UltraLight (the lightest sans we have on
   board, standing in for "HN Light"), small caps via uppercase, no
   italic — reads as a quiet line of credits beneath the masthead. */
#richard-print-output .richard-toc-byline {
  font-family: "HN UltraLight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 10.5pt;
  font-style: normal;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.7);
  margin-top: 0.2in;
}
#richard-print-output .richard-toc-heading {
  font-size: 14pt;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  margin: 0 0 0.25in;
}
#richard-print-output .richard-toc-group {
  font-size: 9.5pt;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.6);
  margin: 0.28in 0 0.1in;
  padding-bottom: 0.05in;
  border-bottom: 0.5px solid rgba(0, 0, 0, 0.25);
}
#richard-print-output .richard-toc-group:first-child { margin-top: 0; }
#richard-print-output .richard-toc-row {
  display: flex;
  align-items: baseline;
  text-decoration: none;
  color: inherit;
  font-size: 12.5pt;
  line-height: 1.45;
  padding: 0.05in 0;
  break-inside: avoid;
}
#richard-print-output .richard-toc-row .toc-title {
  flex: 1 1 auto;
  overflow: hidden;
  /* Dotted leader between title and page number */
  background-image: radial-gradient(circle, rgba(0,0,0,0.55) 0.6px, transparent 0.7px);
  background-position: bottom left;
  background-size: 6px 6px;
  background-repeat: repeat-x;
  padding-right: 0.5em;
}
/* Page number is injected at print/measurement time by buildAndPrint. */
#richard-print-output .richard-toc-row .toc-page-num {
  font-feature-settings: "lnum";
  font-weight: 600;
  margin-left: 0.5em;
  flex: 0 0 auto;
}

/* General orphan-heading guard for the review-copy PDF output. Any
   heading inside the print doc stays with the content that follows
   it (break-after: avoid) and never splits across pages itself
   (break-inside: avoid). Backstop for the specific cases handled by
   .richard-doc-entry-title etc.; ensures Citation, Production, or
   any new section heading can't dangle alone at the foot of a page. */
#richard-print-output h1,
#richard-print-output h2,
#richard-print-output h3,
#richard-print-output h4 {
  page-break-after: avoid;
  break-after: avoid-page;
  page-break-inside: avoid;
  break-inside: avoid;
}

/* ============================================================
   Description frontmatter
   ============================================================
   Project-spanning description that opens any multi-volume PDF, or
   the matching volume slice that opens any single-volume PDF.
   Inserted by buildDescriptionFrontmatter() between the Contents
   page and the first volume divider. Slipcase-only and Timeline-
   only builds render no frontmatter and skip this entire block.

   Type system honours the surrounding print CSS: HN Thin + HN Black
   for the project title (matching the TOC masthead), HN UltraLight
   small caps for the byline, Mercure for body and volume-card
   sub-heads, small-caps tracking for kickers and section labels. */

#richard-print-output .richard-frontmatter {
  page-break-before: always;
  break-before: page;
}

/* ---- Single-volume case: one card, one page ---- */
#richard-print-output .richard-frontmatter-single {
  padding-top: 1.6in;
  page-break-after: always;
  break-after: page;
  max-width: 5.5in;
  margin: 0 auto;
}
#richard-print-output .richard-frontmatter-single .richard-frontmatter-kicker {
  text-align: center;
  margin-bottom: 0.6in;
}
#richard-print-output .richard-frontmatter-single .richard-frontmatter-body p {
  margin: 0 0 1em;
  text-align: justify;
  hyphens: auto;
}
#richard-print-output .richard-frontmatter-single .richard-frontmatter-body
                     > p:first-child > strong:first-child {
  display: block;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 24pt;
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.15;
  margin-bottom: 0.35em;
}
#richard-print-output .richard-frontmatter-single .richard-frontmatter-body
                     > p:first-child > strong:first-child em {
  font-style: italic;
  font-weight: 600;
}

/* ---- Multi-volume case: title page + prelude + per-volume cards +
        epilogue (Citation, Production) ---- */
#richard-print-output .richard-frontmatter-kicker {
  font-size: 10pt;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
  margin-bottom: 0.45in;
}
#richard-print-output .richard-frontmatter-head {
  text-align: center;
  padding-top: 2.5in;
  padding-bottom: 0.8in;
  page-break-after: always;
  break-after: page;
}
#richard-print-output .richard-frontmatter-title {
  font-family: "HN Thin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 200;
  font-size: 48pt;
  line-height: 1.05;
  letter-spacing: 0;
  margin: 0;
}
#richard-print-output .richard-frontmatter-title .richard-toc-five {
  font-family: "HN Black", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 900;
  font-feature-settings: "lnum";
}
#richard-print-output .richard-frontmatter-byline {
  font-family: "HN UltraLight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 10.5pt;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.7);
  margin-top: 0.5in;
}

/* ---- Prelude (intro paragraphs + "The five volumes" section break) ---- */
#richard-print-output .richard-frontmatter-prelude {
  padding-top: 1in;
  max-width: 5.5in;
  margin: 0 auto;
  page-break-after: always;
  break-after: page;
}
#richard-print-output .richard-frontmatter-prelude p {
  margin: 0 0 1em;
  text-align: justify;
  hyphens: auto;
}
/* Opening paragraph leads with a small drop-cap-style first capital
   to give the description an unhurried first breath. */
#richard-print-output .richard-frontmatter-prelude > p:first-of-type::first-letter {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 2.6em;
  font-weight: 600;
  float: left;
  line-height: 0.95;
  padding: 0.05em 0.08em 0 0;
  color: #000;
}
#richard-print-output .richard-frontmatter-prelude blockquote {
  margin: 1.4em auto;
  padding: 0.4em 0 0.4em 0.5in;
  border-left: 1.5px solid rgba(0, 0, 0, 0.4);
  font-family: "HN UltraLight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 12.5pt;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.6;
  color: rgba(0, 0, 0, 0.78);
  font-style: normal;
}
#richard-print-output .richard-frontmatter-prelude h2 {
  margin: 1.6in auto 0;
  text-align: center;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 22pt;
  font-weight: 600;
  letter-spacing: -0.005em;
  padding-top: 0.55in;
  border-top: 1px solid rgba(0, 0, 0, 0.35);
  max-width: 4in;
  color: rgba(0, 0, 0, 0.88);
}

/* ---- Per-volume cards (one per page) ---- */
#richard-print-output .richard-frontmatter-vol-cards {
  /* Wrapper for breaking; each child card forces its own page. */
}
#richard-print-output .richard-frontmatter-vol-card {
  page-break-before: always;
  break-before: page;
  padding-top: 1.4in;
  max-width: 5.5in;
  margin: 0 auto;
}
/* Section kicker that opens Volume 1's card ("The five volumes" — lifted
   out of the prelude so it doesn't dangle there alone). Small-caps
   tracking centered above the bold run-in, with a thin rule beneath
   so it reads as a section header for the per-volume run. Subsequent
   volume cards skip the kicker. */
#richard-print-output .richard-frontmatter-section-kicker {
  text-align: center;
  font-size: 10pt;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
  margin: 0 auto 0.7in;
  padding-bottom: 0.18in;
  border-bottom: 0.5px solid rgba(0, 0, 0, 0.35);
  max-width: 3in;
}
#richard-print-output .richard-frontmatter-vol-card p {
  margin: 0 0 1em;
  text-align: justify;
  hyphens: auto;
}
/* First paragraph in each card opens with the bold "Volume N, _Title_
   (Vn)" run-in. Promote that strong to a display-line sub-head so the
   card reads as its own small title page. */
#richard-print-output .richard-frontmatter-vol-card > p:first-child > strong:first-child {
  display: block;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 26pt;
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.12;
  margin-bottom: 0.4em;
}
#richard-print-output .richard-frontmatter-vol-card > p:first-child > strong:first-child em {
  font-style: italic;
  font-weight: 600;
}

/* ---- Epilogue (Citation + Production sections) ---- */
#richard-print-output .richard-frontmatter-epilogue {
  page-break-before: always;
  break-before: page;
  padding-top: 1.1in;
  max-width: 5.5in;
  margin: 0 auto;
}
#richard-print-output .richard-frontmatter-epilogue h2 {
  margin: 1.5em 0 0.5em;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 14pt;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.7);
  text-align: center;
  padding-bottom: 0.18in;
  border-bottom: 0.5px solid rgba(0, 0, 0, 0.3);
}
#richard-print-output .richard-frontmatter-epilogue h2:first-of-type {
  margin-top: 0;
}
#richard-print-output .richard-frontmatter-epilogue p {
  margin: 0 0 1em;
  text-align: justify;
  hyphens: auto;
}
#richard-print-output .richard-frontmatter-epilogue blockquote {
  margin: 1.2em auto;
  padding: 0.4em 0 0.4em 0.5in;
  border-left: 1.5px solid rgba(0, 0, 0, 0.4);
  font-family: "HN UltraLight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 11.5pt;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.6;
  color: rgba(0, 0, 0, 0.78);
  font-style: normal;
}

/* ---- Volume divider (full page, when crossing into a new volume) ---- */
#richard-print-output .richard-volume-divider {
  page-break-after: always;
  break-after: page;
  page-break-before: always;
  text-align: center;
  padding-top: 3in;
}
#richard-print-output .richard-volume-divider .vol-roman {
  font-size: 13pt;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.62);
  margin-bottom: 0.45in;
}
#richard-print-output .richard-volume-divider .vol-title {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 54pt;
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.005em;
}
#richard-print-output .richard-volume-divider .vol-subtitle {
  margin: 0.45in auto 0;
  max-width: 4.5in;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 14pt;
  line-height: 1.45;
  color: rgba(0, 0, 0, 0.72);
  text-align: center;
}
#richard-print-output .richard-volume-divider .vol-subtitle em {
  font-style: italic;
}
#richard-print-output .richard-volume-divider .vol-subtitle .vol-cite {
  display: block;
  margin-top: 0.18in;
  font-style: italic;
  font-size: 11pt;
  color: rgba(0, 0, 0, 0.58);
}

/* ---- Chapter divider (full page, for every selected piece) ---- */
#richard-print-output .richard-chapter-divider {
  page-break-after: always;
  break-after: page;
  page-break-before: always;
  text-align: center;
  padding-top: 2.6in;
}
#richard-print-output .richard-chapter-divider .ch-address {
  font-size: 10pt;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
  margin-bottom: 0.4in;
}
#richard-print-output .richard-chapter-divider .ch-title {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 38pt;
  font-weight: 600;
  line-height: 1.15;
  margin: 0;
}
#richard-print-output .richard-chapter-divider .ch-subtitle {
  margin-top: 0.22in;
  font-style: italic;
  font-size: 18pt;
  color: rgba(0, 0, 0, 0.72);
  line-height: 1.3;
}
#richard-print-output .richard-chapter-divider .ch-byline,
#richard-print-output .richard-chapter-divider .ch-citation {
  margin-top: 0.22in;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 11pt;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.6);
}
/* Essay/piece title sub-head between the big chapter title and the
   subtitle/citation. Larger than the subtitle and not italic so the
   visual hierarchy reads: chapter label → essay title → subtitle →
   citation. */
#richard-print-output .richard-chapter-divider .ch-piece-title {
  margin-top: 0.3in;
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-weight: 400;
  font-size: 22pt;
  line-height: 1.2;
  color: rgba(0, 0, 0, 0.78);
}

/* ---- Body sections (one per selected piece) ---- */
#richard-print-output .richard-doc {
  page-break-after: always;
  break-after: page;
}
#richard-print-output .richard-doc:last-child {
  page-break-after: auto;
  break-after: auto;
}

/* ---- Timeline nodes (timeline-only mode: one per page) ---- */
#richard-print-output .richard-timeline-node {
  page-break-after: always;
  break-after: page;
  page-break-inside: avoid;
}
#richard-print-output .richard-timeline-node:last-child {
  page-break-after: auto;
  break-after: auto;
}
#richard-print-output .richard-timeline-node h2 {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 26pt;
  font-weight: 600;
  line-height: 1.18;
  margin: 0 0 0.4em;
}

/* Per-entry title at the top of each .richard-doc body when the
   parent item bundles multiple docs (marginalia, V5 Prior Fables).
   The chapter divider above only labels the bundle as a whole, so
   without this heading each entry would print as untitled prose. */
#richard-print-output .richard-doc-entry-title {
  font-family: "Mercure", Georgia, "Times New Roman", serif;
  font-size: 22pt;
  font-weight: 600;
  line-height: 1.2;
  margin: 0 0 0.18em;
  page-break-after: avoid;
  break-after: avoid;
}
#richard-print-output .richard-doc-entry-subtitle {
  margin: 0 0 0.9em;
  font-style: italic;
  font-size: 13pt;
  color: rgba(0, 0, 0, 0.7);
  page-break-after: avoid;
  break-after: avoid;
}

/* ---- Timeline TOC (350+ rows; tighter row spacing) ----
   Three-column row: dated era on the left, title in the middle (with
   dotted leader), page number on the right. The date column is a
   fixed monospace-feeling tabular column so the era stack reads as a
   chronology running down the left margin. */
#richard-print-output .richard-toc.richard-toc-timeline {
  font-size: 10.5pt;
  line-height: 1.3;
}
#richard-print-output .richard-toc-timeline .richard-toc-row {
  font-size: 10.5pt;
  padding: 0.02in 0;
  line-height: 1.3;
}
#richard-print-output .richard-toc-timeline .toc-date {
  flex: 0 0 auto;
  width: 10em;
  padding-right: 0.6em;
  font-size: 9.5pt;
  font-variant-numeric: lining-nums;
  color: rgba(0, 0, 0, 0.6);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
}
#richard-print-output h2,
#richard-print-output h3,
#richard-print-output h4 {
  page-break-after: avoid;
  break-after: avoid;
}
/* Paragraphs that are wholly bold (a single <strong> child) are
   manuscript sub-section headings rendered from "**Header text**" in
   markdown. Keep them with the following paragraph so a heading never
   strands itself at the bottom of a page. */
#richard-print-output p:has(> strong:only-child),
#richard-print-output p:has(> b:only-child) {
  page-break-after: avoid;
  break-after: avoid;
  page-break-inside: avoid;
  break-inside: avoid;
  margin-top: 1.2em;
}
#richard-print-output p,
#richard-print-output blockquote,
#richard-print-output figure {
  orphans: 3;
  widows: 3;
}
#richard-print-output figure.fable-aside {
  border: 1px solid rgba(0, 0, 0, 0.4);
  background: none;
  padding: 0.28in 0.36in;
  page-break-inside: avoid;
  break-inside: avoid;
}
#richard-print-output figure.fable-aside figcaption {
  color: rgba(0, 0, 0, 0.6);
  border-bottom: 1px solid rgba(0, 0, 0, 0.35);
}
#richard-print-output .kc-amp {
  font-family: "KingsCaslon", Georgia, serif;
}

/* ============================================================
   @media print — show only the assembled output and set up
   the @page box (paper, margins, page-number footer).
   ============================================================ */
@media print {
  body.richard-print-printing > *:not(#richard-print-output) {
    display: none !important;
  }
  body.richard-print-printing #richard-print-output {
    display: block !important;
    position: static !important;
    left: auto !important;
    top: auto !important;
    width: auto !important;
    visibility: visible !important;
  }
  @page {
    size: letter;
    margin: 1.5in 1.5in 1.6in 1.5in;
    /* Footer credit line opposite the page number. The reader's own
       @page block (defined earlier in this file) tries to populate
       @bottom-left with a citation breadcrumb via string(citation);
       writing a static string here overrides that leak so the credit
       reads cleanly on every page. */
    @bottom-left {
      /* Content is set dynamically by buildAndPrint via an injected
         <style id="richard-print-date-style"> tag right before
         window.print(). Format: "3:49pm 26 May 2026". */
      content: "";
      font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      font-weight: 300;
      font-size: 7.5pt;
      letter-spacing: 0.16em;
      text-transform: uppercase;
      color: #888;
      vertical-align: bottom;
      padding-bottom: 0.35in;
    }
    @bottom-center { content: ""; }
    @top-left      { content: ""; }
    @top-center    { content: ""; }
    @top-right     { content: ""; }
    @bottom-right {
      /* Half the size of the cover's "5", weight stepped down from
         Black (900) to Bold (700). We don't register an HN Bold
         @font-face, so the cascade falls through to system Helvetica
         Neue Bold; Arial Bold is the final fallback.
         vertical-align: bottom + matching padding-bottom keeps the
         page number on the same baseline as the @bottom-left credit
         opposite it. */
      content: counter(page);
      font-family: "Helvetica Neue", "HN Medium", Helvetica, Arial, sans-serif;
      font-weight: 700;
      font-size: 18pt;
      color: #000;
      letter-spacing: 0;
      vertical-align: bottom;
      padding-bottom: 0.3in;
    }
  }
}


/* ============================================================
   .forthcoming — fade-back for content that's referenced in the
   manuscript but hasn't been written yet. Applied via inline
   <span class="forthcoming">…</span> in the markdown source.
   Used in V1 Act II to muted the side-quest names that don't
   yet have vignettes (Kyoto, Angkor, Khajuraho, London) while
   leaving Rome at full strength. */
#webapp-reader .reader-body .forthcoming,
#richard-print-output .forthcoming {
  opacity: 0.42;
}

/* ============================================================
   .page-break-after-this — manuscript-side page break helper.
   Placed in markdown as <div class="page-break-after-this"></div>
   to force a hard page break in any print context (the reader's
   own print path AND the Richard PDF build). Zero-height on
   screen; emits a break-after:page in print. */
.page-break-after-this {
  height: 0;
  overflow: hidden;
  margin: 0;
  padding: 0;
}
@media print {
  .page-break-after-this {
    page-break-after: always;
    break-after: page;
  }
}
