/* GENERATED by build-web.js — edit web.css / common.js / build-web.js instead. */
:root {
  --paper:#fbfbf9; --ink:#1c1a16; --gray:#524e45;
  --red:#a8402f; --blue:#365f9e; --green:#41703f; --faint:#cbc2a9;
}
/* ---- design system, verbatim from common.js BASE_CSS ---- */

* { box-sizing:border-box; margin:0; padding:0; }
@font-face { font-family:'Caveat'; font-weight:700; font-style:normal; src:url('assets/caveat-700.woff2') format('woff2'); }
@font-face { font-family:'Patrick Hand'; font-weight:400; font-style:normal; src:url('assets/patrickhand-400.woff2') format('woff2'); }
@font-face { font-family:'Kalam'; font-weight:700; font-style:normal; src:url('assets/kalam-700.woff2') format('woff2'); }
/* round 30: user picked proto B — Shantell Sans (variable 400–600) is the
   deck-wide body face. Caveat titles + Kalam bold labels keep the identity. */
@font-face { font-family:'Shantell Sans'; font-style:normal; font-weight:400 600; src:url('assets/shantellsans-var.woff2') format('woff2'); }

body {
  font-family:'Shantell Sans', 'Patrick Hand', 'Segoe Print', cursive, sans-serif;
  color:#1c1a16;
  background-color:#fbfbf9;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.055'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(rgba(28,26,22,0.035) 1px, transparent 1.1px);
  background-size: 240px 240px, 26px 26px;
  -webkit-font-smoothing:antialiased;
}

.title-font { font-family:'Caveat', cursive; font-weight:700; }
.label-font { font-family:'Kalam', cursive; font-weight:700; }
b { font-family:'Kalam', cursive; font-weight:700; }

.kicker {
  font-family:'Kalam', cursive; font-weight:700;
  text-transform:uppercase; letter-spacing:.22em; font-size:14px; color:#524e45;
}
.ink { color:#1c1a16; } .gray { color:#524e45; }
.red { color:#a8402f; } .blue { color:#365f9e; } .green { color:#41703f; }

/* sketch containers — JS draws rough borders/fills into these */
.sk-card { position:relative; }
.sk-circle { position:relative; display:inline-flex; align-items:center; justify-content:center; }
.sk-hl { position:relative; display:inline; padding:0 3px; }
.sk-ul { position:relative; display:inline-block; }

/* slight human rotations */
.r-a { transform:rotate(-0.7deg); } .r-b { transform:rotate(0.55deg); }
.r-c { transform:rotate(-0.4deg); } .r-d { transform:rotate(0.8deg); }
.r-0 { transform:rotate(-1.1deg); }

svg text { font-family:'Shantell Sans', 'Patrick Hand', cursive; }

/* ---- fluid layout layer (web.css) ---- */
/* =====================================================================
   web.css — the FLUID LAYOUT LAYER for the /audio long-scroll page.

   This file does NOT restyle the design system. Colours, fonts, paper
   noise, dot grid, .sk-card / .sk-circle / .sk-hl / .sk-ul and the human
   rotation classes (.r-a … .r-0) all still come from common.js's BASE_CSS,
   which build-web.js inlines ahead of this file. What lives here is only
   the part of BASE_CSS the deck hard-locks to 1080x1350:

       html,body { width:1080px; height:1350px; overflow:hidden }
       .page     { width:1080px; height:1350px; ... }

   replaced by a fluid equivalent.

   THE FLUID UNIT
   --------------
   Every size in the deck is a px number measured against a 1080px-wide
   artboard. Instead of rewriting ~104 font sizes by hand, build-web.js
   rewrites every `Npx` in the deck's own CSS to `calc(N * var(--u))`,
   where --u is one fluid "deck pixel". So the whole system — type,
   padding, gaps, figure boxes — scales as one thing and the deck's
   internal rhythm survives untouched.

       --u = 0.825  at 390px viewport   (20px deck body  -> 16.5px)
       --u = 1.0    at >=1193px         (20px deck body  -> 20px)

   LAYOUT
   ------
   >= 900px : each module is a two-column grid — a sticky title rail on
              the left, the deck's card stack on the right at ~895px,
              i.e. within a few px of the deck's own 944px content column.
   <  900px : one column, title above content.
   <= 720px : the deck's *internal* rows (side-by-side cards, mic columns,
              plug rows) collapse to single column. These overrides are
              written with the same specificity as build-web.js's scoped
              module rules (`.m-<slug> .p3-row` == `.mod .p3-row`) and are
              emitted after them, so source order decides.
   ===================================================================== */

:root {
  --u: clamp(0.825px, calc(0.74px + 0.0218vw), 1px);
  --gut: calc(32 * var(--u));
}

/* --- unlock the fixed artboard ------------------------------------- */
html, body { width: auto; height: auto; overflow-y: visible; }
/* Two sources of phantom horizontal overflow, neither of which paints
   anything: the rotated cards (.r-a … .r-0), and sketch.js's highlighter
   SVGs, whose box is sized to the union of a wrapped phrase's line boxes but
   anchored to the first one. `clip` (not `hidden`) removes the scroll without
   turning the viewport into a scroll container, so the sticky title rail
   keeps working. It must be on html as well — Chrome does not propagate a
   clip from body to the viewport. */
html, body { overflow-x: clip; }
body { line-height: 1.4; }
/* NOT `svg { max-width:100% }`: sketch.js injects absolutely-positioned SVGs
   into inline spans (.sk-hl / .sk-ul / .sk-circle), whose containing block is
   0-wide when the span wraps — max-width:100% collapsed them and the
   highlighter/underline silently vanished on any wrapped phrase. */
img { max-width: 100%; }
a { color: inherit; }

.wrap {
  /* round 39 (user): titles sit ABOVE the content now, so the page is one
     column — and that column is exactly the deck's 944px content width
     (1008 − 2×32 gutter). The web sheet reads as the deck unrolled: same
     title-over-cards shape, cards at 1:1 deck proportions (k = 1). */
  max-width: calc(1008 * var(--u));
  margin: 0 auto;
  padding: 0 var(--gut);
}

/* --- site header --------------------------------------------------- */
.site {
  padding: calc(46 * var(--u)) 0 calc(26 * var(--u));
}
.site-word {
  font-family: 'Caveat', cursive; font-weight: 700;
  font-size: calc(56 * var(--u));
  line-height: 1;
  display: inline-block;
}
.toc {
  display: flex; flex-wrap: wrap;
  gap: calc(10 * var(--u)) calc(14 * var(--u));
  margin-top: calc(22 * var(--u));
  padding-top: calc(18 * var(--u));
  border-top: calc(1 * var(--u)) dashed var(--faint);
}
.toc a {
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(16 * var(--u));
  letter-spacing: .04em;
  color: var(--gray);
  text-decoration: none;
  padding: calc(4 * var(--u)) calc(10 * var(--u));
  border: calc(1 * var(--u)) dashed var(--faint);
  border-radius: calc(14 * var(--u));
}
.toc a:hover, .toc a:focus-visible { color: var(--ink); border-color: var(--gray); }

/* round 42 — the list now sits at the END of the scroll rather than under the
   title. It needs its own breathing room there: in the header it was pinned
   against the h1 above and the first module below, but at the bottom it is
   the last thing on an 11,000px page and wants to read as a deliberate index,
   not as leftovers. */
.toc-end {
  margin-top: calc(46 * var(--u));
  padding-top: calc(26 * var(--u));
  padding-bottom: calc(30 * var(--u));
  justify-content: center;
}

/* --- a module ------------------------------------------------------
   round 39 (user): was a two-column grid with a sticky title rail on the
   left. The title block now sits ABOVE the cards, deck-style — one column,
   the permalink chip on the title's baseline, the subtitle under it. */
.mod {
  padding: calc(52 * var(--u)) 0;
  border-top: calc(1 * var(--u)) dashed var(--faint);
  scroll-margin-top: calc(20 * var(--u));
}
.mod:first-of-type { border-top: 0; }

.mod-head {
  display: flex; flex-wrap: wrap; align-items: baseline;
  column-gap: calc(18 * var(--u));
  margin-bottom: calc(26 * var(--u));
  min-width: 0;
}
.mod-num {
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(14 * var(--u)); letter-spacing: .22em;
  color: var(--gray); margin-bottom: calc(8 * var(--u));
}
.mod-title {
  font-family: 'Caveat', cursive; font-weight: 700;
  font-size: calc(62 * var(--u)); line-height: .92;
  display: inline-block;
}
.mod-sub {
  flex: 1 1 100%; order: 3;              /* full row under the title line */
  font-size: calc(21 * var(--u)); color: var(--gray);
  margin-top: calc(10 * var(--u)); line-height: 1.35;
}
/* The module permalink. It prints its own fragment — `#buffer` — because a
   bare `#` names nothing: it reads as debris under a title, it is a 10px
   target, and it needs an aria-label to mean anything. Written out, the link
   IS the thing it teaches: this module lives at /audio#buffer, and that is
   what the click puts in your address bar. Styled as the same dashed chip as
   the table of contents (.toc a), because it is the same object — a chip that
   points at this module — just sitting on the module instead of above it. */
.mod-link {
  /* round 39: rides the title's baseline at the right edge of the head row
     (was a block dropped under the subtitle in the old sticky rail) */
  margin-left: auto;
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(15 * var(--u)); letter-spacing: .04em;
  color: var(--gray);
  text-decoration: none;
  padding: calc(4 * var(--u)) calc(10 * var(--u));
  border: calc(1 * var(--u)) dashed var(--faint);
  border-radius: calc(14 * var(--u));
  white-space: nowrap;
}
/* the hash stays faint, so the WORD leads and the punctuation follows */
.mod-link .hash { color: var(--faint); }
.mod-link:hover, .mod-link:focus-visible { color: var(--red); border-color: var(--red); }
.mod-link:hover .hash, .mod-link:focus-visible .hash { color: var(--red); }

/* the deck's card stack. Per-page `.pc-content { gap:Npx }` rules are
   dropped by build-web.js: those gaps were height-fitting artifacts of the
   1350px box (4px on page 4), not rhythm worth keeping in a scroll. */
/* min-width:0 everywhere a grid/flex item could otherwise be forced wider than
   its track by a max-content child (page 4's gear grid was doing exactly that). */
.pc-content { display: flex; flex-direction: column; gap: calc(20 * var(--u)); min-width: 0; }

/* --- figures -------------------------------------------------------- */
/* Height + label size are finalised in JS (see the inline script in the
   emitted HTML): every [data-fw] box gets height = deckH * k and
   data-fs = deckFs * k, where k = measuredWidth / deckWidth clamped to
   [0.62, 1.05]. The CSS heights that build-web.js carries over from the
   deck are the pre-JS fallback. */
.mod [data-fw] { position: relative; }

/* wide figures get a scroll box ONLY on phones (see the 720px block). Above
   that the wrapper is a plain block, so rough.js's 1-2px stroke overhang
   paints exactly as it does in the deck instead of raising a scrollbar. */
.mod .figscroll { display: block; }

/* ROUND 41 — a hand-drawn border is not a crisp rectangle. rough.js wobbles
   each edge inward and outward by a couple of px, and it strokes at 1.4-2px,
   so the bottom rule of a .sk-card sweeps a band several px tall rather than
   sitting on one line. The deck gives .p4-col 3px of vertical padding
   (2.475px once --u scales it) — narrower than that band. On the 1080px
   artboard it survives because the three columns are narrow and the
   description wraps early, leaving the last line short; on a phone the
   columns stack full width, the description runs edge to edge, and the
   stroke crosses its descenders. Reported from an iPhone screenshot; Chrome
   measures exactly 3px of clearance, which is why it does not reproduce
   there — this is a near-miss everywhere, not a Safari bug.
   web.css is the WEB-ONLY layer, so raising the padding here cannot move a
   single pixel of the print deck.

   SPECIFICITY, not order: build-web.js emits this general section BEFORE the
   deck's page CSS and only the @media block after it, so `.mod .p4-col`
   (0,2,0) loses to `.m-loudness .p4-col` (0,2,0) on source order — it looked
   applied in the file and did nothing in the browser. `.mod .p4-cols .p4-col`
   is (0,3,0) and wins outright, at every width, wherever it is emitted. */
.mod .p4-cols .p4-col { padding-top: calc(6 * var(--u)); padding-bottom: calc(11 * var(--u)); }

/* --- the hearable figures (round 39, SPEC-4.8.1 demos 1-4) ----------
   Rows are emitted [hidden] by build-web.js and revealed by hear.js only
   when a working AudioContext exists; keep [hidden] winning over any
   display rule so the no-JS page stays the plain sheet. Chips use the
   same dashed vocabulary as .toc a / .mod-link — the page's one "this is
   interactive" costume. */
.hear[hidden], .hear-mute[hidden] { display: none !important; }
.hear {
  margin-top: calc(14 * var(--u));
  padding-top: calc(12 * var(--u));
  border-top: calc(1 * var(--u)) dashed var(--faint);
  display: flex; flex-wrap: wrap; align-items: center;
  gap: calc(8 * var(--u)) calc(12 * var(--u));
}
.hear-go, .hear-stop, .hear-tap {
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(15 * var(--u)); letter-spacing: .04em;
  color: var(--gray); background: none; cursor: pointer;
  padding: calc(4 * var(--u)) calc(10 * var(--u));
  border: calc(1 * var(--u)) dashed var(--faint);
  border-radius: calc(14 * var(--u));
}
.hear-go:hover, .hear-stop:hover, .hear-tap:hover,
.hear-go:focus-visible, .hear-stop:focus-visible, .hear-tap:focus-visible {
  color: var(--ink); border-color: var(--gray);
}
.hear-go[aria-pressed="true"] { color: var(--red); border-color: var(--red); border-style: solid; }
.hear-stops { display: flex; flex-wrap: wrap; gap: calc(6 * var(--u)); }
.hear-stop.on { color: var(--blue); border-color: var(--blue); border-style: solid; }
/* ROUND 42 (user): "the TAP button should be coloured in."
   It was wearing the same dashed outline as every chip on the page — the
   stops, the TOC links, the go buttons — so the one control you are meant to
   hit repeatedly read as another label. Filled, in the same blue the selected
   buffer stop uses, so the pairing is obvious: you pick a blue number, you hit
   the blue button. It is also the only percussive control here, so it gets
   press feedback. */
.hear-tap {
  font-size: calc(18 * var(--u));
  padding: calc(10 * var(--u)) calc(30 * var(--u));
  touch-action: manipulation;            /* no double-tap zoom on the pad */
  /* round 42b (user): "it shouldn't be black, make it the yellow from the
     curves." That is GOLD (#c2901c) in sketch.js — the EQ boost-curve ink,
     and the deck's only saturated yellow. 42a's blue fill went black on
     :hover/:active because the shared rule below sets --ink, which is what
     was actually on screen. Gold with ink text instead: the paper is warm,
     so a white-on-gold chip would glare. */
  background: #c2901c; color: var(--ink);
  border-style: solid; border-color: #a87c14;
  -webkit-user-select: none; user-select: none;
}
/* the shared :hover/:focus rule above sets color:var(--ink) and leaves the
   background alone — restate both states so the fill never goes dark. */
.hear-tap:hover, .hear-tap:focus-visible {
  color: var(--ink); background: #d9a52c; border-color: #a87c14;
}
.hear-tap:active {
  transform: translateY(calc(1 * var(--u)));
  color: var(--ink); background: #b07f10; border-color: #8f6a0d;
}
.hear-note { flex: 1 1 100%; font-size: calc(15 * var(--u)); color: var(--gray); }
.hear-fader { flex: 1 1 calc(160 * var(--u)); min-width: calc(120 * var(--u)); accent-color: var(--ink); }
.hear-cal { display: block; }

/* ROUND 42 — the press-and-hold spectrum row. No .hear-go button here: the
   figure IS the control, so this row is an instruction plus a live readout.
   round 42b (user): the dashed rule above it is gone and it sits tight under
   the figure. Every other .hear row is a separate interaction that has earned
   a divider from the card above it; this one IS the figure's own control, so
   a rule between them was drawing a boundary that is not there. */
.hear-freq {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: calc(12 * var(--u));
  border-top: 0;
  padding-top: 0;
  margin-top: calc(2 * var(--u));
}
.hear-freq-lab {
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(15 * var(--u)); letter-spacing: .04em;
  color: var(--blue);
}
/* right-aligned so it appears under the 10k–20k end of the axis, which is
   where the reader's eye already is when they drag up there. */
.hear-readout {
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(17 * var(--u)); color: var(--ink);
  min-height: calc(21 * var(--u));       /* reserve the line so nothing jumps */
  text-align: right; white-space: nowrap;
  margin-left: auto;
}
/* the figure is draggable, so suppress the browser gestures that would
   otherwise fight it — text selection, and touch panning starting on the box. */
.mod .fig-eq { touch-action: none; -webkit-user-select: none; user-select: none; cursor: crosshair; }
.mod .fig-eq[data-holding] { cursor: grabbing; }
.hear-headphones {
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(15 * var(--u)); color: var(--red);
  margin-bottom: calc(8 * var(--u));
}
.hear-cal-t { font-family: 'Kalam', cursive; font-weight: 700; font-size: calc(16 * var(--u)); letter-spacing: .06em; }
.hear-cal-b { font-size: calc(15 * var(--u)); color: var(--gray); margin: calc(4 * var(--u)) 0 calc(8 * var(--u)); }
.hear-cal-row { display: flex; flex-wrap: wrap; align-items: center; gap: calc(10 * var(--u)); }
.hear-mute {
  position: fixed; right: calc(14 * var(--u)); bottom: calc(14 * var(--u)); z-index: 50;
  font-family: 'Kalam', cursive; font-weight: 700;
  font-size: calc(15 * var(--u)); letter-spacing: .04em;
  color: var(--gray); background: var(--paper); cursor: pointer;
  padding: calc(6 * var(--u)) calc(14 * var(--u));
  border: calc(1 * var(--u)) solid var(--gray);
  border-radius: calc(16 * var(--u));
}
.hear-mute[aria-pressed="true"] { color: var(--red); border-color: var(--red); }


/* ---- shared card styles, from deck.js CAROUSEL_CSS ---- */
.mod .pc-url { position:absolute; bottom:calc(20 * var(--u)); right:calc(68 * var(--u)); font-size:calc(15 * var(--u)); color:#524e45; letter-spacing:.04em; }
.mod .pc-card { padding:calc(26 * var(--u)) calc(32 * var(--u)); }
.mod .pc-note { font-size:calc(20 * var(--u)); line-height:1.5; }
.mod .pc-note b, .mod .pc-card b { font-family:'Kalam'; font-weight:700; }
.mod .pc-cardtitle { font-family:'Kalam'; font-weight:700; font-size:calc(19 * var(--u)); letter-spacing:.06em; margin-bottom:calc(9 * var(--u)); }
.mod .qn { font-family:'Kalam'; font-weight:700; font-size:calc(16 * var(--u)); color:#365f9e; padding:0 calc(7 * var(--u)); margin-right:calc(4 * var(--u)); }
.mod .ct-b { color:#365f9e; }
.mod .ct-r { color:#a8402f; }
.mod .ct-g { color:#41703f; }
/* ---- per-module styles, from deck.js PAGE_CSS ---- */
/* --- file-quality (deck page 2) --- */
.m-file-quality .p2-lead { display:flex; gap:calc(26 * var(--u)); align-items:center; font-size:calc(20 * var(--u)); line-height:1.42; padding:calc(14 * var(--u)) calc(28 * var(--u)); }
.m-file-quality .p2-lead-left { flex:1 1 0; min-width:0; }
.m-file-quality .p2-lead-t { font-family:'Caveat'; font-weight:700; font-size:calc(30 * var(--u)); line-height:1.05; margin-bottom:calc(6 * var(--u)); }
.m-file-quality .p2-lead-q { margin:calc(5 * var(--u)) 0; font-size:calc(16.5 * var(--u)); }
.m-file-quality .p2-row12 { display:flex; gap:calc(18 * var(--u)); }
.m-file-quality .p2-col { flex:1 1 0; min-width:0; padding:calc(16 * var(--u)) calc(24 * var(--u)); }
.m-file-quality .p2-col .row { font-size:calc(20 * var(--u)); line-height:1.4; }
.m-file-quality .p2-col .row b { font-size:calc(19 * var(--u)); }
.m-file-quality .p2-col .note { font-size:calc(16.5 * var(--u)); color:#524e45; margin-top:calc(5 * var(--u)); line-height:1.32; }
.m-file-quality .p2-c3 { padding:calc(16 * var(--u)) calc(26 * var(--u)); }
.m-file-quality .p2-c3 .row { font-size:calc(20 * var(--u)); line-height:1.42; }
.m-file-quality .p2-c3 .row b { font-size:calc(19 * var(--u)); }
.m-file-quality .p2-c3 .note { font-size:calc(16.5 * var(--u)); color:#524e45; margin-top:calc(5 * var(--u)); line-height:1.32; }
.m-file-quality .fig-filename { position:relative; width:calc(296 * var(--u)); height:calc(70 * var(--u)); flex:0 0 auto; margin-right:calc(4 * var(--u)); }
.m-file-quality .fn-line { font-family:'Kalam'; font-weight:700; font-size:calc(20 * var(--u)); letter-spacing:calc(.2 * var(--u)); white-space:nowrap; }
.m-file-quality .fn-labels { display:flex; justify-content:space-between; margin-top:calc(26 * var(--u)); padding:0 calc(2 * var(--u)); }
.m-file-quality .fn-labels div { font-size:calc(14 * var(--u)); color:#524e45; line-height:1; white-space:nowrap; }
.m-file-quality .p2-bounce { padding:calc(14 * var(--u)) calc(32 * var(--u)) calc(14 * var(--u)); }
.m-file-quality .p2-bounce-t { font-size:calc(20 * var(--u)); margin-bottom:calc(6 * var(--u)); }
.m-file-quality .p2-bounce-t b { font-family:'Kalam'; font-weight:700; font-size:calc(19 * var(--u)); }
.m-file-quality .p2-bounce-grid { display:flex; flex-direction:column; gap:calc(6 * var(--u)); }
.m-file-quality .p2-bounce-row { display:flex; align-items:baseline; gap:calc(12 * var(--u)); font-size:calc(20 * var(--u)); line-height:1.32; }
.m-file-quality .p2-bounce-row .sit { flex:0 0 calc(322 * var(--u)); text-align:right; }
.m-file-quality .p2-bounce-row .arr { flex:0 0 auto; color:#365f9e; font-family:'Kalam'; font-weight:700; }
.m-file-quality .p2-bounce-row .num { flex:1 1 0; min-width:0; }
.m-file-quality .p2-bounce-row .num b { font-family:'Kalam'; font-weight:700; font-size:calc(19.5 * var(--u)); }

/* --- decibels (deck page 3) --- */
.m-decibels .p3-fig-card { padding:calc(14 * var(--u)) calc(26 * var(--u)) calc(10 * var(--u)); }
.m-decibels .fig-ruler { position:relative; width:100%; height:calc(228 * var(--u)); }
.m-decibels .p3-lead-card { font-size:calc(23 * var(--u)); line-height:1.45; text-align:center; padding:calc(16 * var(--u)) calc(30 * var(--u)); }
.m-decibels .p3-card { padding:calc(16 * var(--u)) calc(28 * var(--u)) calc(17 * var(--u)); }
.m-decibels .p3-card .pc-cardtitle { margin-bottom:calc(5 * var(--u)); }
.m-decibels .p3-line { font-size:calc(21 * var(--u)); line-height:1.46; }
.m-decibels .p3-line b { font-family:'Kalam'; font-weight:700; }
.m-decibels .p3-line + .p3-line { margin-top:calc(5 * var(--u)); }
.m-decibels .p3-row { display:flex; gap:calc(14 * var(--u)); }
.m-decibels .p3-row .p3-card { flex:1 1 0; min-width:0; }

/* --- loudness (deck page 4) --- */
.m-loudness .pc-cardtitle { margin-bottom:calc(4 * var(--u)); }
.m-loudness .p4-split { display:flex; gap:calc(12 * var(--u)); align-items:stretch; }
.m-loudness .p4-half { flex:1 1 0; min-width:0; padding:calc(12 * var(--u)) calc(20 * var(--u)) calc(10 * var(--u)); font-size:calc(20 * var(--u)); line-height:1.36; display:flex; flex-direction:column; }
.m-loudness .p4-comp-card { flex:0.78 1 0; }
.m-loudness .p4-stack { flex:1.22 1 0; min-width:0; display:flex; flex-direction:column; gap:calc(10 * var(--u)); }
.m-loudness .p4-lim-card { flex:0 0 auto; padding:calc(11 * var(--u)) calc(20 * var(--u)) calc(9 * var(--u)); font-size:calc(18.5 * var(--u)); line-height:1.31; }
.m-loudness .p4-beat { margin-bottom:calc(7 * var(--u)); }
.m-loudness .p4-side-card { flex:1 1 auto; padding:calc(10 * var(--u)) calc(20 * var(--u)) calc(9 * var(--u)); font-size:calc(18 * var(--u)); line-height:1.34; }
.m-loudness .p4-split .pc-cardtitle { margin-bottom:calc(5 * var(--u)); }
.m-loudness .p4-fig-card .pc-cardtitle { margin-bottom:calc(2 * var(--u)); }
.m-loudness .p4-chunk + .p4-chunk { margin-top:calc(4 * var(--u)); }
.m-loudness .p4-cols .p4-col:nth-child(1) .p4-name { color:#a8402f; }
.m-loudness .p4-cols .p4-col:nth-child(2) .p4-name { color:#365f9e; }
.m-loudness .p4-cols .p4-col:nth-child(3) .p4-name { color:#41703f; }
.m-loudness .p4-footnote { font-size:calc(16 * var(--u)); color:#524e45; margin-top:auto; padding-top:calc(6 * var(--u)); border-top:calc(1 * var(--u)) dashed #cbc2a9; }
.m-loudness .p4-gear { display:flex; gap:calc(18 * var(--u)); align-items:center; padding:calc(2 * var(--u)) calc(26 * var(--u)); margin-top:calc(1 * var(--u)); }
.m-loudness .fig-rack { position:relative; width:calc(104 * var(--u)); height:calc(34 * var(--u)); flex:0 0 auto; }
.m-loudness .p4-gear-rows { flex:1 1 0; min-width:0; display:grid; grid-template-columns:max-content max-content; justify-content:center; column-gap:calc(18 * var(--u)); row-gap:calc(5 * var(--u)); align-items:baseline; }
.m-loudness .p4-gear-lab { text-align:right; font-family:'Kalam'; font-weight:700; font-size:calc(15 * var(--u)); letter-spacing:.12em; color:#524e45; }
.m-loudness .p4-gear-names { font-family:'Kalam'; font-weight:700; font-size:calc(20 * var(--u)); letter-spacing:.02em; }
.m-loudness .p4-mid { display:flex; gap:calc(12 * var(--u)); align-items:stretch; }
.m-loudness .p4-fig-card { flex:1 1 0; min-width:0; padding:calc(9 * var(--u)) calc(22 * var(--u)) calc(9 * var(--u)); }
.m-loudness .fig-bricked { position:relative; width:100%; height:calc(142 * var(--u)); }
.m-loudness .p4-hero-pre { font-size:calc(16 * var(--u)); color:#524e45; line-height:1.2; margin-top:calc(3 * var(--u)); text-align:center; }
.m-loudness .p4-hero { font-family:'Caveat'; font-weight:700; font-size:calc(38 * var(--u)); line-height:1.05; text-align:center; margin-top:calc(1 * var(--u)); }
.m-loudness .p4-hero-cap { margin-top:calc(5 * var(--u)); padding-top:calc(5 * var(--u)); border-top:calc(1 * var(--u)) dashed #cbc2a9; }
.m-loudness .p4-capline { font-size:calc(16.5 * var(--u)); color:#524e45; text-align:center; line-height:1.34; }
.m-loudness .p4-hero-foot { font-size:calc(15 * var(--u)); color:#524e45; text-align:center; line-height:1.3; margin-top:calc(4 * var(--u)); }
.m-loudness .p4-cols { display:flex; gap:calc(12 * var(--u)); }
.m-loudness .p4-col { flex:1 1 0; padding:calc(3 * var(--u)) calc(14 * var(--u)) calc(3 * var(--u)); }
.m-loudness .fig-meter { position:relative; width:100%; height:calc(26 * var(--u)); }
.m-loudness .p4-name { font-family:'Kalam'; font-weight:700; font-size:calc(18 * var(--u)); margin-top:calc(1 * var(--u)); }
.m-loudness .p4-desc { font-size:calc(16 * var(--u)); line-height:1.26; margin-top:calc(1 * var(--u)); }

/* --- buffer (deck page 5) --- */
.m-buffer .p6-fig-card { padding:calc(26 * var(--u)) calc(36 * var(--u)) calc(24 * var(--u)); }
.m-buffer .fig-bufruler { position:relative; width:100%; height:calc(176 * var(--u)); }
.m-buffer .p6-cap { font-size:calc(19 * var(--u)); color:#524e45; text-align:left; margin-top:calc(4 * var(--u)); line-height:1.34; }
.m-buffer .p6-play { font-size:calc(22 * var(--u)); line-height:1.5; margin-top:calc(14 * var(--u)); padding-top:calc(13 * var(--u)); border-top:calc(1 * var(--u)) dashed #cbc2a9; }
.m-buffer .p6-play b { font-family:'Kalam'; font-weight:700; }
.m-buffer .p6-note-card { padding:calc(22 * var(--u)) calc(36 * var(--u)); font-size:calc(22 * var(--u)); line-height:1.52; }
.m-buffer .p6-line + .p6-line { margin-top:calc(6 * var(--u)); }
.m-buffer .p6-rule { font-size:calc(27 * var(--u)); text-align:center; line-height:1.5; }
.m-buffer .p6-rule b { font-family:'Kalam'; font-weight:700; }

/* --- mics (deck page 6) --- */
.m-mics .p7-cols { display:flex; gap:calc(18 * var(--u)); }
.m-mics .p7-col { flex:1 1 0; padding:calc(15 * var(--u)) calc(24 * var(--u)); text-align:center; }
.m-mics .fig-mic { position:relative; width:calc(112 * var(--u)); height:calc(126 * var(--u)); margin:0 auto; }
.m-mics .p7-name { font-family:'Kalam'; font-weight:700; font-size:calc(23 * var(--u)); margin-top:calc(6 * var(--u)); }
.m-mics .p7-desc { font-size:calc(19 * var(--u)); line-height:1.38; margin-top:calc(4 * var(--u)); text-align:left; }
.m-mics .p7-desc .sk-hl { white-space:nowrap; }
.m-mics .p7-desc .names { color:#524e45; font-size:calc(17 * var(--u)); }
.m-mics .p7-line + .p7-line { margin-top:calc(5 * var(--u)); }
.m-mics .p7-names { margin-top:calc(5 * var(--u)); margin-bottom:calc(10 * var(--u)); }
.m-mics .p7-polar-card { padding:calc(14 * var(--u)) calc(28 * var(--u)) calc(12 * var(--u)); }
.m-mics .p7-polar-row { display:flex; gap:calc(24 * var(--u)); }
.m-mics .p7-polar-cell { flex:1 1 0; min-width:0; text-align:center; }
.m-mics .fig-polar { position:relative; width:calc(248 * var(--u)); height:calc(136 * var(--u)); margin:0 auto; }
.m-mics .p7-polar-lab { font-size:calc(17 * var(--u)); line-height:1.32; margin-top:calc(2 * var(--u)); }
.m-mics .p7-polar-lab b { font-family:'Kalam'; font-weight:700; }
.m-mics .p7-switches { padding:calc(20 * var(--u)) calc(34 * var(--u)); }
.m-mics .p7-sw { font-size:calc(20 * var(--u)); line-height:1.48; margin:calc(6 * var(--u)) 0; }
.m-mics .p7-sw b { font-family:'Kalam'; font-weight:700; }

/* --- plugs (deck page 7) --- */
.m-plugs .p8-row { display:flex; align-items:center; gap:calc(26 * var(--u)); padding:calc(14 * var(--u)) calc(32 * var(--u)); }
.m-plugs .fig-plug { position:relative; width:calc(104 * var(--u)); height:calc(48 * var(--u)); flex:0 0 auto; }
.m-plugs .p8-name { font-family:'Kalam'; font-weight:700; font-size:calc(22 * var(--u)); width:calc(250 * var(--u)); flex:0 0 auto; }
.m-plugs .p8-desc { font-size:calc(20 * var(--u)); line-height:1.32; }
.m-plugs .p8-bal { margin-left:auto; font-family:'Kalam'; font-weight:700; font-size:calc(15.5 * var(--u)); letter-spacing:.05em; }
.m-plugs .p8-bal .g { color:#41703f; }
.m-plugs .p8-bal .r { color:#a8402f; }
.m-plugs .p8-note { font-size:calc(21 * var(--u)); text-align:center; }
.m-plugs .p8-explain { padding:calc(14 * var(--u)) calc(32 * var(--u)); font-size:calc(20 * var(--u)); line-height:1.44; }
.m-plugs .p8-explain b { font-family:'Kalam'; font-weight:700; }
.m-plugs .p8-line + .p8-line { margin-top:calc(5 * var(--u)); }
.m-plugs .p8-computer { padding:calc(14 * var(--u)) calc(32 * var(--u)); font-size:calc(20 * var(--u)); line-height:1.42; text-align:center; }

/* --- signal-chain (deck page 8) --- */
.m-signal-chain .p9-fig-card { padding:calc(12 * var(--u)) calc(26 * var(--u)) calc(7 * var(--u)); }
.m-signal-chain .fig-chain { position:relative; width:100%; height:calc(162 * var(--u)); }
.m-signal-chain .p9-defs { display:flex; gap:calc(13 * var(--u)); }
.m-signal-chain .p9-def { flex:1 1 0; padding:calc(10 * var(--u)) calc(20 * var(--u)); font-size:calc(16 * var(--u)); line-height:1.36; }
.m-signal-chain .p9-def b { font-family:'Kalam'; font-weight:700; }
.m-signal-chain .p9-scale { padding:calc(9 * var(--u)) calc(24 * var(--u)); font-size:calc(16 * var(--u)); line-height:1.36; }
.m-signal-chain .p9-scale b { font-family:'Kalam'; font-weight:700; }
.m-signal-chain .p9-scale div { margin:calc(1 * var(--u)) 0; }
.m-signal-chain .p9-row2 { display:flex; gap:calc(13 * var(--u)); }
.m-signal-chain .p9-row2 .p9-def { font-size:calc(16 * var(--u)); line-height:1.36; }
.m-signal-chain .p9-famous { padding:calc(9 * var(--u)) calc(26 * var(--u)) calc(9 * var(--u)); display:flex; flex-direction:column; }
.m-signal-chain .p9-famous .pc-cardtitle { margin-bottom:0; }
.m-signal-chain .p9-famous .pc-cardtitle .song { font-family:'Shantell Sans'; font-weight:400; letter-spacing:0; color:#1c1a16; font-size:calc(17 * var(--u)); }
.m-signal-chain .fig-famous { position:relative; width:100%; height:calc(180 * var(--u)); }
.m-signal-chain .p9-famous-line { font-size:calc(16 * var(--u)); color:#524e45; text-align:center; margin-top:auto; padding-top:calc(6 * var(--u)); }
.m-signal-chain .p9-famous-note { font-size:calc(13.5 * var(--u)); color:#524e45; text-align:center; margin-top:calc(1 * var(--u)); }
.m-signal-chain .p9-famous-foot { font-size:calc(16 * var(--u)); color:#524e45; text-align:center; margin-top:calc(1 * var(--u)); }
.m-signal-chain .p9-dither { padding:calc(10 * var(--u)) calc(30 * var(--u)); font-size:calc(16 * var(--u)); line-height:1.36; text-align:center; }
.m-signal-chain .p9-dither b { font-family:'Kalam'; font-weight:700; }
.m-signal-chain .p9-dither-lead { margin-bottom:calc(5 * var(--u)); }
.m-signal-chain .p9-dither-two { display:flex; gap:calc(34 * var(--u)); justify-content:center; text-align:center; }
.m-signal-chain .p9-dither-two > div { flex:1 1 0; min-width:0; }
.m-signal-chain .p9-line + .p9-line { margin-top:calc(4 * var(--u)); }

/* --- instruments (deck page 9) --- */
.m-instruments .p5-fig-card { padding:calc(14 * var(--u)) calc(28 * var(--u)) calc(8 * var(--u)); }
.m-instruments .fig-eq { position:relative; width:100%; height:calc(452 * var(--u)); }
.m-instruments .p5-legend { font-size:calc(18 * var(--u)); color:#524e45; text-align:center; margin-top:calc(4 * var(--u)); }
.m-instruments .p5-fig-card .p5-logline { font-size:calc(20 * var(--u)); line-height:1.4; text-align:center; }
.m-instruments .p5-fig-card .p5-legend + .p5-logline { margin-top:calc(11 * var(--u)); padding-top:calc(10 * var(--u)); border-top:calc(1 * var(--u)) dashed #cbc2a9; }
.m-instruments .p5-fig-card b { font-family:'Kalam'; font-weight:700; }
.m-instruments .p5-logline + .p5-logline { margin-top:calc(5 * var(--u)); }
.m-instruments .p5-translator { padding:calc(14 * var(--u)) calc(28 * var(--u)) calc(12 * var(--u)); }
.m-instruments .p5-eqshapes-t { font-family:'Kalam'; font-weight:700; font-size:calc(15 * var(--u)); letter-spacing:.1em;
                   color:#524e45; text-align:center; margin-top:calc(8 * var(--u)); }
.m-instruments .fig-eqshapes { position:relative; width:100%; height:calc(92 * var(--u)); margin-top:calc(3 * var(--u)); }
.m-instruments .p5-eqnote { font-size:calc(18 * var(--u)); color:#524e45; line-height:1.4; margin-top:calc(10 * var(--u)); padding-top:calc(8 * var(--u)); border-top:calc(1 * var(--u)) dashed #cbc2a9; text-align:center; }
.m-instruments .p5-eqnote b { font-family:'Kalam'; font-weight:700; color:#1c1a16; }
.m-instruments .p5-eqline + .p5-eqline { margin-top:calc(3 * var(--u)); }

/* --- recap (deck page 10) --- */
.m-recap .p10-item { display:flex; align-items:center; gap:calc(24 * var(--u)); padding:calc(19 * var(--u)) calc(32 * var(--u)); }
.m-recap .sk-check { position:relative; width:calc(48 * var(--u)); height:calc(48 * var(--u)); flex:0 0 auto; }
.m-recap .p10-text { font-size:calc(28 * var(--u)); }
.m-recap .p10-text b { font-family:'Kalam'; font-weight:700; }
.m-recap .p10-cta { text-align:center; margin-top:calc(14 * var(--u)); }
.m-recap .p10-cta .big { font-family:'Caveat'; font-weight:700; font-size:calc(52 * var(--u)); }
.m-recap .p10-cta .small { font-size:calc(18 * var(--u)); color:#524e45; margin-top:calc(3 * var(--u)); }
/* ===================================================================
   RESPONSIVE OVERRIDES
   Emitted after the scoped module CSS; selectors are `.mod <deck sel>`
   so specificity matches `.m-<slug> <deck sel>` and source order wins.
   =================================================================== */

@media (max-width: 899px) {
  .mod { padding: calc(40 * var(--u)) 0; }
  .mod-head { margin-bottom: calc(18 * var(--u)); }
  .mod-title { font-size: calc(54 * var(--u)); }
  .site { padding: calc(30 * var(--u)) 0 calc(18 * var(--u)); }
  .site-word { font-size: calc(44 * var(--u)); }
}

@media (max-width: 720px) {
  /* A full-width deck figure has a fixed annotation gutter and horizontal
     label runs; under ~500px of drawing width it stops being readable no
     matter how the box scales. The floor + swipe is the fallback for figures
     that have no narrow variant yet. */
  .mod .figscroll { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
  .mod .figscroll > [data-fw] { min-width: calc(640 * var(--u)); }

  /* ROUND 41 — hide the native scrollbar. This is not cosmetics; it fixes a
     card-border bug. A classic (non-overlay) scrollbar reserves ~15px of
     HEIGHT inside .figscroll, and rough.js overhangs its stroke 1-2px past
     the box — enough overflow to raise one on a figure that otherwise fits.
     Sequence: sketch.js draws the .sk-card border at the card's current
     height, the scrollbar then appears, the card grows ~15px, and the drawn
     border is now short by exactly that much — the stroke crosses whatever
     text sits at the bottom. Measured: 5 cards at +14/+15px (p3/p4/p5/p6
     figure cards and the p5 translator), which is the same overlap reported
     on the RMS card from a phone.
     Removing the reservation removes the desync. Nothing is lost: touch
     scrolling is unaffected, and the two figures that genuinely scroll now
     carry their own edge fade and "swipe →" cue below. */
  .mod .figscroll { scrollbar-width: none; }
  .mod .figscroll::-webkit-scrollbar { display: none; }

  /* ROUND 42 — chain and famous now WRAP into rows (sketch.js), so they fit
     and nothing scrolls any more. The floor comes off, they get the height
     three stacked rows need, and the swipe affordance below is dead code kept
     only for a future figure that needs it. User: "the scrolling isnt working
     for me on the chains, stack em and or downsize to fit in the mobile
     width." Downsizing was rejected — see the comment in drawChain. */
  .mod .figscroll > .fig-chain,
  .mod .figscroll > .fig-famous { min-width: 0; }
  /* round 42b: one node per row now (see drawChain). Each row needs ~78px —
     the icons are ~64px tall and do not scale — so 6 nodes want ~470px and
     5 want ~390px. In deck-px at --u 0.825 that is 570 and 475. */
  .mod .fig-chain { height: calc(570 * var(--u)) !important; }
  .mod .fig-famous { height: calc(475 * var(--u)) !important; }

  /* ROUND 41 — a figure that scrolls with no edge looks like a figure that is
     simply cut off, and the reader never swipes. Retained for any figure that
     still overflows; chain and famous no longer do.
     Two cues, both CSS-only, no JS and no state to keep in sync:
       1. a soft fade on the right edge, painted by the wrapper's own
          background-attachment:local trick — it sits still while the content
          moves, so it disappears on its own once you reach the end.
       2. a "swipe" label in Kalam, matching the badge language already on
          the page rather than introducing a new piece of chrome.
     Applied to .figscroll:has(> .fig-chain, > .fig-famous) so it cannot
     attach to a figure that now fits. */
  /* ROUND 42c — chain and famous are NOT in these selectors any more. 42b
     stacked them so they fit, and left the fade and the "swipe →" attached,
     which advertised a scroll that no longer existed. Nothing on the page
     currently overflows, so these two rules match nothing; they stay as the
     ready-made affordance for the next figure that needs one. Add its class
     here and it gets both cues. */
  .mod .figscroll:has(> .fig-needs-swipe) {
    position: relative;
    /* two layers: a fixed white-to-transparent wedge pinned to the right of
       the BOX, and a matching one pinned to the right of the CONTENT. The
       local-attachment layer scrolls away with the content and cancels the
       fixed one at the end of the scroll. */
    background:
      linear-gradient(to left, var(--paper, #faf8f2) calc(6 * var(--u)), transparent calc(56 * var(--u))) right center / calc(56 * var(--u)) 100% no-repeat scroll,
      linear-gradient(to left, transparent, transparent) right center / calc(56 * var(--u)) 100% no-repeat local;
  }
  /* The cue needs its OWN strip. First attempt pinned it to the top-right
     with a negative margin, which dropped it straight onto the A/D box's
     sub-caption ("your interface in…") — the chain draws edge to edge, so
     there is no empty corner anywhere inside the figure to borrow.
     Reserving a band under the drawing is the only placement that cannot
     collide, whatever the figure does. float lands it below the figure block;
     sticky + right:0 keeps it against the right edge of the SCROLLPORT as
     the content moves under it. */
  .mod .figscroll:has(> .fig-needs-swipe) { padding-bottom: calc(22 * var(--u)); }

  .mod .figscroll:has(> .fig-needs-swipe)::after {
    content: 'swipe →';
    /* right:0 ONLY. Adding bottom:0 made it stick to the floor of the
       scrollport, which parked it on the card's drawn bottom border. With no
       vertical inset it just flows under the figure and sticks horizontally,
       which is the only axis that actually scrolls here. */
    position: sticky; float: right; right: 0;
    margin-top: calc(4 * var(--u));
    font-family: 'Kalam', cursive; font-weight: 700;
    font-size: calc(14 * var(--u)); letter-spacing: .06em;
    color: var(--gray, #6b6559); opacity: .75;
    pointer-events: none;
  }

  /* …but these four reflow themselves below their threshold (sketch.js
     NARROW_W / NARROW_BUF), so they must be allowed to reach it. Keeping the
     floor here would pin them at ~525px and the variants would never fire.
     Still floored: chain, famous, bricked — see the backlog.

     ROUND 41 — this rule did nothing for three rounds. It ended in a comma
     and had no declaration block, so all three selectors were swallowed into
     the `.mod .p2-lead` rule below and inherited ITS declarations. Net effect:
     the min-width floor was never lifted, every narrow variant in sketch.js
     was dead code on the phone, and all seven figures sat pinned at ~530px
     inside a ~275px box. `.fig-eqshapes` — the octave curves, the fourth of
     "these four" — was missing from the list as well.
     Verified at 390px: ruler 529->277, buffer 530->260, spectrum 530->274,
     curves 529->273. Do not let this rule end in a comma again. */
  .mod .figscroll > .fig-ruler,
  .mod .figscroll > .fig-eq,
  .mod .figscroll > .fig-eqshapes,
  .mod .figscroll > .fig-bufruler,
  /* round 41: bricked joins them — drawBricked now stacks its two lanes
     below NARROW_W. Needs the extra height too, since the inline sizer
     scales deckH by width and would otherwise hand the stacked layout the
     side-by-side box. !important beats that inline style. */
  .mod .figscroll > .fig-bricked { min-width: 0; }

  .mod .fig-bricked { height: calc(300 * var(--u)) !important; }

  /* page 2 — file quality */
  .mod .p2-lead { flex-direction: column; align-items: stretch; gap: calc(16 * var(--u)); }
  .mod .fig-filename { width: 100%; max-width: calc(316 * var(--u)); margin: 0 auto; }
  .mod .p2-row12 { flex-direction: column; }
  .mod .p2-bounce-row { flex-direction: column; gap: 0; }
  .mod .p2-bounce-row .sit { flex: 1 1 auto; text-align: left; }
  .mod .p2-bounce-row .arr { display: none; }
  .mod .p2-bounce-grid { gap: calc(12 * var(--u)); }

  /* page 3 — recording */
  .mod .p3-row { flex-direction: column; }

  /* ROUND 42 (user) — the TAP button "is placed oddly on mobile".
     The buffer stops wrap to two rows at phone width, and TAP was flowing as
     just another flex item, so it landed tucked under the tail of the second
     row, hard against the left edge. Give it its own full-width row with air
     above it — it is the thing you come to that card to press. */
  .mod .hear-tap { flex: 1 1 100%; margin-top: calc(6 * var(--u)); }
  /* round 42b (user): "2048 should be in line w the rest." Seven stops at the
     shared chip padding measured ~300px against a ~272px row, so exactly one
     chip wrapped — the worst possible outcome, since a lone 2048 on its own
     line reads as a different kind of thing. Tightened just enough to fit
     seven across: the padding does the work, the font barely moves, so they
     still read as the same chips as everywhere else on the page. */
  .mod .hear-stops { width: 100%; flex-wrap: nowrap; gap: calc(4 * var(--u)); }
  .mod .hear-stops .hear-stop {
    flex: 1 1 0; min-width: 0; text-align: center;
    padding-left: calc(2 * var(--u)); padding-right: calc(2 * var(--u));
    font-size: calc(14 * var(--u));
  }

  /* page 4 — exporting */
  /* ROUND 41 — stacked, each meter now has the FULL card width instead of a
     third of it, but the deck's 26px height came from a three-up row. At
     ~320px wide and 26px tall the trace is a squiggle in a letterbox. Taller
     box, same width: the waveform gets room to read as a waveform. */
  /* !important because the inline sizer in the emitted HTML writes an inline
     height (deckH * k) on every [data-fw] box — it had this at 27.3px and
     plain CSS could not touch it. */
  .mod .fig-meter { height: calc(46 * var(--u)) !important; }
  .mod .p4-split { flex-direction: column; }
  .mod .p4-comp-card { flex: 1 1 auto; }
  .mod .p4-stack { flex: 1 1 auto; }
  .mod .p4-mid { flex-direction: column; }
  .mod .p4-cols { flex-direction: column; }
  .mod .p4-gear { flex-direction: column; align-items: center; gap: calc(8 * var(--u)); }
  /* two max-content columns of Kalam names do not fit a phone */
  .mod .p4-gear-rows { grid-template-columns: minmax(0, 1fr); row-gap: calc(2 * var(--u)); text-align: center; }
  .mod .p4-gear-lab { text-align: center; margin-top: calc(6 * var(--u)); }
  .mod .p4-hero-cap { flex-direction: column; gap: calc(6 * var(--u)); }

  /* ROUND 42 (user): "the freq spectrum box can be wider — good margins on
     the sides — and needs more space."
     At 390px the axis was losing ~98px to chrome before drawing anything:
     .wrap contributes 2×--gut (~26px each) and the p5 cards another 2×28
     deck-px (~23px each). This is the one figure where horizontal room IS the
     information — it is a log frequency axis with five labelled zones and a
     tick row, so every pixel back is resolution. Trimming the card's side
     padding and letting the figure bleed a little past it returns ~40px.
     Specificity note: the deck's rule is `.m-instruments .p5-fig-card`
     (0,2,0), so this has to be (0,3,0) to win — see the p4-col trap. */
     ROUND 42b (user): "we might need to revert those new margins… or claw
     them back about 50%, it looks awkward pressed to the edges." Clawed back
     to 18 deck-px — halfway between the deck's 28 and 42a's 9 — and the
     figure no longer bleeds past the card at all. The width that 42a bought
     is mostly kept, but the drawing stops touching the card's drawn border,
     which was the part that read as a mistake. */
  .mod.m-instruments .p5-fig-card,
  .mod.m-instruments .p5-translator {
    padding-left: calc(18 * var(--u));
    padding-right: calc(18 * var(--u));
  }
  /* and more vertical room: the zone band, seven instrument arrows and the
     tick row all have to clear each other, and the narrow variant already
     drops the zone descriptors to make that fit.
     MIND THE UNITS. These overrides compete with the inline sizer, which
     writes height = deckH × k with k clamped to [0.62, 1.05]. fig-eq's deck
     height is 452, so the sizer already gives it 452 × 0.62 ≈ 280px on a
     phone — a `300 * var(--u)` override is 248px and would have SHRUNK the
     one figure this whole block exists to enlarge. Every value here must beat
     deckH × 0.62 × (1/--u) ≈ deckH × 0.75 in deck-px. For 452 that is 340. */
  .mod .fig-eq { height: calc(430 * var(--u)) !important; }

  /* page 7 — mics */
  .mod .p7-cols { flex-direction: column; }
  .mod .p7-polar-row { flex-direction: column; gap: calc(14 * var(--u)); }

  /* page 8 — plugs */
  .mod .p8-row { flex-wrap: wrap; gap: calc(10 * var(--u)) calc(18 * var(--u)); }
  .mod .p8-name { width: auto; flex: 1 1 auto; }
  .mod .p8-desc { flex: 1 1 100%; }
  .mod .p8-bal { margin-left: 0; }

  /* page 9 — signal chain */
  .mod .p9-defs { flex-direction: column; }
  .mod .p9-row2 { flex-direction: column; }
  .mod .p9-dither-two { flex-direction: column; gap: calc(6 * var(--u)); }

  /* page 10 — recap */
  .mod .p10-item { gap: calc(16 * var(--u)); }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
