/* ==========================================================================
   whaternion — shared lesson stylesheet
   One stylesheet for every lesson and reference sheet, so the course reads as
   one book rather than a pile of one-offs.

   Design notes
   - Wears the Impractical Instruments storybook brand: the design system is
     vendored under `assets/brand/` and imported below, so every colour, font
     and edge here comes from the same tokens the studio site uses. See
     `assets/brand/README.md` before editing anything in that directory.
       Voices, and where each one is used:
         display (Luckiest Guy)  page + section titles, buttons
         body    (Besley)        all running prose, tables, captions
         mono    (Courier Prime) labels, chrome, readouts, code
         hand    (Schoolbell)    the one hand-written aside per page
   - Tufte-ish underneath: generous margins, serif prose, wide figures.
   - Two convention accents used consistently across ALL lessons:
       Unity  = deepened bulb yellow  (--unity)
       glTF   = deepened turquoise    (--gltf)
     Both are brand hues taken dark enough to read as text. Never use them for
     anything else.
   - Axis colours are the universal X/Y/Z = red/green/blue, deliberately left
     outside the brand palette. Arrows are ALWAYS also labelled with text, so
     colour is never the only channel.
   - The page is bracketed in full-bleed sky bands, masthead and footer, the
     way the studio site alternates its grounds. Surfaces between them are the
     sky thinned to a tint; the key callout is butter, the read-next cards are
     bulb yellow.
   - Light + dark. Dark is the same storybook after dusk — a deep sky-navy
     ground with the ink inverted to warm paper — not the brand's ops palette.
     Print styles at the bottom (reference sheets must print).
   ========================================================================== */

@import "brand/design-system.css";

/* ---------- tokens ----------
   The brand supplies --paper, --ink, --sky, --butter, --persimmon, the type
   families, the spacing/border/shadow scale. Everything below either names a
   brand token or is a brand hue taken to a value that survives on paper.

   Values are literal hex, not color-mix(), because `assets/viz3d.js` reads
   these properties and hands them straight to a canvas 2D context. */

:root {
  --ink-soft:   #414a4e;
  --ink-faint:  #7a868b;
  --rule:       #c3d5dd;
  --rule-soft:  #e1ebef;
  --panel:      #e9f1f5;   /* sky, thinned to a page-safe ground */
  --panel-2:    #dce8ee;

  /* The band colour for anything text-heavy. White on the brand sky is a
     hero effect — it holds a poster title and fails a paragraph. Bands the
     eye has to read (the footer, its sources) take the sky darkened until
     small paper text clears 4.5:1; the masthead keeps the true hue. */
  --sky-deep:   #3d707f;

  /* Text on a sky band. Deliberately NOT --paper: that token is the page
     ground, so it inverts to near-black after dusk and would take the
     masthead title with it. The bands stay light in both schemes. */
  --band-ink:   #f7f2e8;

  --unity:      #9c6b08;   /* --ii-yellow, deepened to text contrast */
  --unity-bg:   #fff3c9;
  --gltf:       #0f6f78;   /* --ii-turquoise, likewise */
  --gltf-bg:    #cdeaec;

  --axis-x:     #c0392b;
  --axis-y:     #2e7d32;
  --axis-z:     #1f5fa8;

  --good:       #46783f;   /* --moss, deepened */
  --bad:        #b3261e;
  --warn:       #a8760a;

  /* Type: brand families under the names the rest of this file uses.
     --ui is the chrome voice (labels, controls, table heads); running text is
     always --serif. */
  --mono:  var(--font-mono);
  --serif: var(--font-body);
  --ui:    var(--font-mono);
  --hand:  var(--font-hand);

  --measure: 34rem;   /* prose column */
  --wide:    58rem;   /* figures may bleed to here */
}

@media (prefers-color-scheme: dark) {
  /* The same storybook after dusk — not the brand's ops palette. The ground
     goes to deep sky-navy rather than black, the ink inverts to warm paper
     so the outlines and shadows survive, and butter and persimmon lift
     until they still read as a lit window and a label. */
  :root {
    --paper:      #16232b;
    --ink:        #f2ebde;
    --ink-soft:   #bcc7cc;
    --ink-faint:  #8b9aa1;
    --rule:       #35505c;
    --rule-soft:  #263843;
    --panel:      #1e2f38;
    --panel-2:    #263b45;

    --sky:        #2e5a6b;   /* the hero band, after dusk */
    --sky-deep:   #24485a;
    --ii-yellow:  #e8c84b;   /* the bulb, turned down for night reading */
    --butter:     #43371a;
    /* Persimmon at its paper value cannot label anything on a night ground.
       Lifting the token lifts --link with it: the brand defines one from
       the other, and custom-property substitution is live. */
    --persimmon:  #ff8a5c;
    --string:     #ff6b6b;
    --moss:       #7fc46f;

    --unity:      #e8b33d;
    --unity-bg:   #33280f;
    --gltf:       #70e0e5;   /* after dark the brand turquoise stands as-is */
    --gltf-bg:    #123036;

    --axis-x:     #f0857a;
    --axis-y:     #7fcf82;
    --axis-z:     #7fb4f0;

    --good:       #7fc46f;
    --bad:        #f0857a;
    --warn:       #e8b44d;

    /* Paper shadows stay — they just fall as night, not as ink. */
    --shadow-paper:     4px 4px 0 #0b1216;
    --shadow-paper-sm:  2px 2px 0 #0b1216;
    --shadow-paper-pop: 6px 6px 0 var(--ii-turquoise);
  }
}

/* ---------- reset-ish ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  /* The masthead bleeds to the viewport edge with a 100vw-based negative
     margin, which overshoots by the width of a classic scrollbar. Clip it. */
  overflow-x: clip;
}

body {
  margin: 0;
  padding: 0 1.5rem 8rem;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--text-base);
  line-height: 1.62;
  font-kerning: normal;
  text-rendering: optimizeLegibility;

  /* Tufte layout, in plain block flow:

       ┌──────────────┬────────────────┐
       │ prose        │ figure bleed   │
       └──────────────┴────────────────┘

     The page is one centred column `--wide` across. Prose is capped at
     `--measure`; figures, tables and callouts get the full width. Everything
     therefore shares one left edge and wide things extend right.

     Deliberately NOT grid or flex. Blocks like <pre> that scroll sideways are
     scroll containers, and a scroll container's automatic minimum size is
     zero — as a grid or flex item it gets squashed flat by its own track.
     Block flow sizes them from their content and sidesteps that entirely. */
  max-width: var(--wide);
  margin-inline: auto;
}

/* Prose measure. Left/right margins stay 0 throughout, so the per-element
   `margin` shorthands further down cannot disturb the alignment. */
body > * { max-width: var(--measure); }

body > .masthead,
body > figure,
body > .callout,
body > .spec,
body > .formula,
body > .tbl-wrap,
body > .quiz,
body > .panes,
body > pre,
body > .lesson-foot,
body > .wide {
  max-width: none;
}

/* ---------- masthead ----------
   The studio site opens on a full-bleed sky band with poster caps over it.
   Same band here, achieved without touching a single page's markup: the
   negative margin pulls the header out to the viewport edges, and the
   matching padding puts its text back on the body's own left edge. */

.masthead {
  max-width: var(--wide);
  background: var(--sky);
  color: var(--band-ink);
  border-bottom: var(--border-w) solid var(--ink);
  margin-block: 0 2.75rem;
  margin-inline: calc(50% - 50vw);
  padding: 2.75rem calc(50vw - 50%) 2.5rem;

  /* Axis colours are a teaching channel, so the standfirst keeps them — but
     the page values are chosen for paper and go muddy on the sky ground.
     Tints, scoped to the band, keep both the coding and the contrast. */
  --axis-x: #ffb5a9;
  --axis-y: #bff0b6;
  --axis-z: #c3dcff;
}

/* The studio's hero kicker: a paper pill, hand-inked. */
.masthead .kicker {
  font-family: var(--ui);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #1a1a1a;
  background: var(--band-ink);
  border: 2px solid #1a1a1a;
  border-radius: var(--radius-wobble-sm);
  padding: 0.4rem 0.85rem 0.3rem;
  margin: 0 0 1.1rem;
  display: inline-flex;
  gap: 0.6rem;
  align-items: baseline;
  flex-wrap: wrap;
}

.masthead h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.1rem, 5.6vw, 3.6rem);
  line-height: 0.98;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--band-ink);
  text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
  margin: 0 0 0.85rem;
  text-wrap: balance;
}

.masthead .standfirst {
  font-size: 1.15rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.92);
  margin: 0;
  max-width: 38rem;
  text-wrap: pretty;
}

.masthead a { color: var(--ii-yellow); }

/* ---------- prose ---------- */

/* Section heads are the studio's persimmon mono label with a trailing rule. */
h2 {
  font-family: var(--ui);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--persimmon);
  margin: 3.5rem 0 0.9rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
h2::after {
  content: "";
  flex: 1;
  height: 2px;
  background: var(--ink);
  opacity: 0.18;
}

h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.3rem;
  line-height: 1.15;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 2.4rem 0 0.5rem;
  text-wrap: balance;
}

h4 {
  font-family: var(--ui);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 1.75rem 0 0.35rem;
}

p { margin: 0 0 1.1rem; text-wrap: pretty; }

a {
  color: var(--link);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.16em;
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
}
a:hover { text-decoration-color: currentColor; }

strong { font-weight: 700; }

em { font-style: italic; }

code, kbd, samp {
  font-family: var(--mono);
  font-size: 0.9em;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: 0.06em 0.32em;
}

pre {
  font-family: var(--mono);
  font-size: 0.85rem;
  line-height: 1.6;
  background: var(--panel);
  border: var(--border-ink-thin);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-paper-sm);
  padding: 0.95rem 1.15rem;
  overflow-x: auto;
  margin: 0 0 1.5rem;
}
pre code { background: none; border: 0; padding: 0; font-size: inherit; }

ul, ol { margin: 0 0 1.2rem; padding-left: 1.35rem; }
li { margin-bottom: 0.4rem; }
li > ul, li > ol { margin-top: 0.4rem; margin-bottom: 0.3rem; }

hr {
  border: 0;
  border-top: 2px solid var(--rule);
  margin: 3rem 0;
}

blockquote {
  margin: 0 0 1.25rem;
  padding: 0.1rem 0 0.1rem 1.1rem;
  border-left: 3px solid var(--rule);
  color: var(--ink-soft);
  font-style: italic;
}
blockquote p:last-child { margin-bottom: 0; }

/* ---------- the spec quote: primary-source evidence ----------
   Turquoise drop shadow — the brand's "pop" — so quoted spec text is visibly
   a different kind of thing from the lesson's own voice. */

.spec {
  max-width: var(--wide);
  margin: 1.75rem auto 2rem;
  padding: 1.1rem 1.3rem;
  background: var(--paper);
  border: var(--border-ink-thin);
  border-radius: var(--radius-wobble-sm);
  box-shadow: var(--shadow-paper-pop);
  font-size: 1rem;
}
.spec .src {
  display: block;
  font-family: var(--ui);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--persimmon);
  margin-bottom: 0.6rem;
}
.spec q { font-style: italic; }
.spec p:last-child { margin-bottom: 0; }

/* ---------- convention badges (Unity / glTF) ---------- */

.tag {
  font-family: var(--ui);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.16em 0.5em;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  vertical-align: 0.08em;
}
.tag.unity { color: var(--unity); background: var(--unity-bg); border: 1px solid color-mix(in srgb, var(--unity) 40%, transparent); }
.tag.gltf  { color: var(--gltf);  background: var(--gltf-bg);  border: 1px solid color-mix(in srgb, var(--gltf) 40%, transparent); }

/* Marks a table row we rely on but could not trace to a quotable sentence.
   The whole point of the reference sheet is that it settles arguments, which
   an uncited row cannot do — so it says which rows those are. */
.uncited {
  color: var(--ink-faint);
  font-weight: 700;
  cursor: help;
}

.ax { font-family: var(--mono); font-weight: 700; }
.ax.x { color: var(--axis-x); }
.ax.y { color: var(--axis-y); }
.ax.z { color: var(--axis-z); }

/* ---------- figures ----------
   Each figure is an inked plate, the same card the studio site hangs its
   photographs in. Corners stay a plain radius rather than the wobble: the
   canvas draws to its own edges and a blob radius would crop the geometry. */

figure {
  max-width: var(--wide);
  margin: 2.25rem auto 2.5rem;
}

figure canvas {
  display: block;
  width: 100%;
  background: var(--panel);
  border: var(--border-ink-thin);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-paper-sm);
  touch-action: none;
  cursor: grab;
}
figure canvas.dragging { cursor: grabbing; }

figcaption {
  font-family: var(--serif);
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-top: 0.85rem;
  text-wrap: pretty;
}
figcaption b { color: var(--ink); font-weight: 700; }

/* two panes side by side — the workhorse layout of this course */
.panes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
@media (max-width: 44rem) {
  .panes { grid-template-columns: 1fr; }
}

/* A grid item defaults to min-width:auto, whose automatic minimum is the
   item's min-content size. Put a horizontal scroll container in one — a
   `.readout`, a `pre`, a `.tbl-wrap` — and the column grows to the content's
   full width instead of scrolling, overflowing the grid. (Measured: 920px of
   readout in an 880px `.panes` row.) This is the INLINE-axis half of the
   gotcha in NOTES.md, and it is the half that bites here.

   Applied to every column rather than to `.pane`, so a lesson that drops a
   bare <div> into a `.panes` row cannot reintroduce it. */
.panes > * { min-width: 0; }

.pane > .pane-hd {
  font-family: var(--ui);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 0.5rem;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}
.pane.unity > .pane-hd { color: var(--unity); }
.pane.gltf  > .pane-hd { color: var(--gltf); }
.pane.unity canvas { border-color: var(--unity); }
.pane.gltf  canvas { border-color: var(--gltf); }
.pane-hd .note { font-weight: 400; letter-spacing: 0.02em; text-transform: none; color: var(--ink-faint); font-size: 0.72rem; }

/* ---------- callouts ----------
   Inked cards with a flat paper shadow. The shadow carries the meaning:
   ink for a plain aside, coral for a trap, moss for a win, and the key
   callout sits on butter so it reads as the page's one lit window. */

.callout {
  max-width: var(--wide);
  margin: 2rem auto;
  padding: 1.15rem 1.35rem;
  background: var(--panel);
  border: var(--border-ink-thin);
  border-radius: var(--radius-wobble-sm);
  box-shadow: var(--shadow-paper-sm);
  font-size: 1rem;
}
.callout > .hd {
  font-family: var(--ui);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 0.55rem;
  color: var(--ink-faint);
}
.callout p:last-child, .callout ul:last-child, .callout ol:last-child { margin-bottom: 0; }

.callout.key {
  background: var(--butter);
  border: var(--border-ink);
  box-shadow: var(--shadow-paper);
}
.callout.key > .hd { color: var(--ink); }
.callout.key .big {
  font-size: 1.2rem;
  line-height: 1.45;
  font-weight: 700;
  margin-bottom: 0.7rem;
  text-wrap: pretty;
}

.callout.trap { box-shadow: 4px 4px 0 var(--string); }
.callout.trap > .hd { color: var(--bad); }

.callout.win { box-shadow: 4px 4px 0 var(--moss); }
.callout.win > .hd { color: var(--good); }

/* ---------- formula display ---------- */

.formula {
  max-width: var(--wide);
  margin: 1.5rem auto 1.75rem;
  padding: 1rem 1.2rem;
  background: var(--panel);
  border: var(--border-ink-thin);
  border-radius: var(--radius-md);
  font-family: var(--mono);
  font-size: 1rem;
  line-height: 1.9;
  text-align: center;
  overflow-x: auto;
}
.formula .lbl {
  display: block;
  font-family: var(--ui);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--persimmon);
  margin-bottom: 0.45rem;
}

/* ---------- tables ---------- */

.tbl-wrap { max-width: var(--wide); margin: 1.75rem auto 2rem; overflow-x: auto; }

table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--serif);
  font-size: 0.97rem;
}
caption {
  caption-side: bottom;
  font-family: var(--serif);
  font-size: 0.9rem;
  color: var(--ink-soft);
  text-align: left;
  padding-top: 0.7rem;
}
th, td {
  text-align: left;
  padding: 0.55rem 0.9rem 0.55rem 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
thead th {
  font-family: var(--ui);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--persimmon);
  border-bottom: 2px solid var(--ink);
  white-space: nowrap;
}
tbody tr:last-child td { border-bottom: 0; }
td code { font-size: 0.85rem; }

/* ---------- footer / nav ---------- */

/* The page is bracketed in sky: the masthead band opens it, this one closes
   it. Same bleed trick, and the negative bottom margin eats the body's
   closing padding so the band runs to the foot of the page. */
.lesson-foot {
  max-width: var(--wide);
  background: var(--sky-deep);
  color: var(--band-ink);
  border-top: var(--border-w) solid var(--ink);
  margin: 5rem 0 -8rem;
  margin-inline: calc(50% - 50vw);
  padding: 2.5rem calc(50vw - 50%) 3.5rem;
}

/* On a band, the section label goes yellow and its rule goes paper —
   the studio does exactly this wherever a label lands on sky. */
.lesson-foot h2 { color: var(--ii-yellow); }
.lesson-foot h2::after { background: var(--band-ink); opacity: 0.35; }
.lesson-foot a { color: var(--ii-yellow); }

/* Cards that behave like the studio's call-to-action: bulb yellow, inked,
   lifting into the turquoise on hover and pressing back down on click. */
.readnext {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  margin-bottom: 2.25rem;
}
.lesson-foot .readnext a,
.readnext a {
  display: block;
  padding: 1rem 1.15rem;
  background: var(--ii-yellow);
  border: var(--border-ink);
  border-radius: var(--radius-wobble-sm);
  box-shadow: var(--shadow-paper);
  text-decoration: none;
  color: var(--ink);
  font-family: var(--serif);
  font-size: 0.95rem;
  line-height: 1.45;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.readnext a:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ii-turquoise); }
.readnext a:active { transform: translate(2px, 2px); box-shadow: var(--shadow-paper-sm); }
.readnext a .lbl {
  display: block;
  font-family: var(--ui);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* Persimmon goes muddy on bulb yellow; this is the same hue, taken down
     until the label separates from the card. */
  color: #8f2e0b;
  margin-bottom: 0.35rem;
}
.readnext a b { font-weight: 700; }

@media (prefers-color-scheme: dark) {
  /* The card keeps its yellow at night — dimmed to a gold, and its text
     inverted, since the page ink is now paper-coloured. */
  .lesson-foot .readnext a,
  .readnext a { color: var(--paper); border-color: var(--paper); }
  .readnext a .lbl { color: #7a2c0c; }
}

/* The one hand-written aside per page. */
.ask {
  font-family: var(--serif);
  font-size: 0.97rem;
  line-height: 1.55;
  color: var(--ink-soft);
  background: var(--panel);
  border: 2px dashed var(--ink-faint);
  border-radius: var(--radius-wobble-sm);
  padding: 1rem 1.15rem;
  margin-bottom: 2rem;
}
.ask b {
  font-family: var(--hand);
  font-weight: 400;
  font-size: 1.35em;
  color: var(--persimmon);
}

.colophon {
  font-family: var(--ui);
  font-size: 0.78rem;
  letter-spacing: 0.03em;
  color: var(--ink-faint);
  line-height: 1.7;
}
.colophon a { color: var(--ink-soft); }

/* ---------- source list ---------- */

.sources { font-family: var(--serif); font-size: 0.94rem; line-height: 1.55; }
.sources li { margin-bottom: 0.55rem; color: var(--ink-soft); }
.sources li b { color: var(--ink); font-weight: 700; }

/* Everything else the band carries, turned to paper. Scoped here rather
   than on the components, so a callout or a source list dropped into the
   page body keeps its page colours. */
.lesson-foot .sources li { color: rgba(255, 255, 255, 0.9); }
.lesson-foot .sources li b { color: var(--band-ink); }
.lesson-foot .colophon { color: rgba(255, 255, 255, 0.72); }
.lesson-foot .colophon a { color: var(--ii-yellow); }
/* The ask is a paper card sitting on the band, so its links stay page
   links — yellow would be a link to nowhere on that ground. */
.lesson-foot .ask { border-color: var(--ink-faint); }
.lesson-foot .ask a { color: var(--link); }
/* Inline code keeps its own pale ground anywhere it appears, so on the band
   it needs the page's ink back or it is paper on paper. */
.lesson-foot code { color: var(--ink); }

/* ---------- utility ---------- */

.wide { max-width: var(--wide); }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.small { font-size: 0.9em; }
.muted { color: var(--ink-soft); }
.sans { font-family: var(--ui); }

/* ==========================================================================
   controls (assets/ui.js)
   The instrument panel. This is the brand's ops voice — Courier, flat
   surfaces, hairline rules — sitting under the storybook plates.
   ========================================================================== */

.ctl-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem 1.5rem;
  margin-top: 0.9rem;
  padding: 0.9rem 1.05rem;
  background: var(--panel);
  border: var(--border-ink-thin);
  border-radius: var(--radius-md);
  font-family: var(--ui);
}

.ctl-bar-label {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--persimmon);
  align-self: center;
}

.ctl { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }
.ctl-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; }

.ctl-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.ctl-value { font-family: var(--mono); font-size: 0.78rem; color: var(--ink); font-variant-numeric: tabular-nums; }

/* segmented radio group */
.seg { display: inline-flex; border: var(--border-ink-thin); border-radius: var(--radius-sm); overflow: hidden; background: var(--paper); }
.seg-item { position: relative; display: block; }
.seg-item:not(:last-child) { border-right: 2px solid var(--ink); }
.seg-item > span {
  display: block;
  padding: 0.34rem 0.75rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}
.seg-item > span:hover { background: var(--panel-2); color: var(--ink); }
.seg-item input:checked + span { background: var(--ink); color: var(--paper); }
.seg-item input { position: absolute; opacity: 0; pointer-events: none; }
.seg-item input:focus-visible + span { outline: 2px solid var(--gltf); outline-offset: -2px; }

.ctl-slider { min-width: 13rem; flex: 1 1 13rem; }
.ctl-slider input[type=range] { width: 100%; accent-color: var(--persimmon); margin: 0; }

.ctl-check { display: inline-flex; align-items: center; gap: 0.45rem; font-size: 0.84rem; cursor: pointer; color: var(--ink); }
.ctl-check input { accent-color: var(--persimmon); width: 1rem; height: 1rem; }

/* The studio's button: bulb yellow, inked, turquoise shadow, presses down. */
.ctl-btn {
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 400;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 0.45rem 0.9rem 0.3rem;
  color: var(--ink);
  background: var(--ii-yellow);
  border: var(--border-ink-thin);
  border-radius: var(--radius-wobble-sm);
  box-shadow: var(--shadow-paper-sm);
  cursor: pointer;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.ctl-btn:hover { transform: translate(-2px, -2px); box-shadow: 4px 4px 0 var(--ii-turquoise); }
.ctl-btn:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 var(--ink); }
.ctl-btn:disabled { opacity: 0.4; cursor: default; transform: none; box-shadow: var(--shadow-paper-sm); }
.ctl-btn.subtle { background: var(--paper); color: var(--ink-soft); }
.ctl-btn.subtle:hover { color: var(--ink); }

/* live numeric readout */
.readout {
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1.75;
  background: var(--paper);
  border: var(--border-ink-thin);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.8rem;
  min-width: 0;
  overflow-x: auto;
}
.readout-label {
  display: block;
  font-family: var(--ui);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--persimmon);
  margin-bottom: 0.35rem;
}
.readout-body { white-space: pre; font-variant-numeric: tabular-nums; }
.readout-body .k { color: var(--ink-faint); }

/* pass/fail strip */
.status { font-family: var(--ui); font-size: 0.82rem; display: flex; flex-direction: column; gap: 0.3rem; }
.status-row { display: flex; align-items: baseline; gap: 0.45rem; line-height: 1.45; }
.status-row.ok  { color: var(--good); }
.status-row.bad { color: var(--bad); }
.status-mark { font-weight: 700; width: 0.9em; flex: none; }
.status-text b { font-weight: 700; }
.status-detail { color: var(--ink-faint); font-size: 0.78rem; }

/* vector entry */
.vecin {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  font-family: var(--mono);
  font-size: 0.92rem;
  padding: 0.25rem 0.55rem;
  border: var(--border-ink-thin);
  border-radius: var(--radius-sm);
  background: var(--paper);
}
.vecin.ok  { border-color: var(--good); box-shadow: inset 0 0 0 1px var(--good); }
.vecin.bad { border-color: var(--bad);  box-shadow: inset 0 0 0 1px var(--bad); }
.vecin-label { font-family: var(--ui); font-size: 0.74rem; font-weight: 700; color: var(--ink-faint); margin-right: 0.35rem; }
.vecin-paren, .vecin-comma { color: var(--ink-faint); }
.vecin-box {
  width: 3.4rem;
  font-family: var(--mono);
  font-size: 0.92rem;
  text-align: center;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 2px solid var(--rule);
  padding: 0.1rem 0.15rem;
}
.vecin-box:focus { outline: none; border-bottom-color: var(--ink); }
.vecin-box:read-only { color: var(--ink-soft); border-bottom-style: dotted; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   quiz (assets/quiz.js)
   ========================================================================== */

.quiz {
  max-width: var(--wide);
  margin: 2.5rem auto;
  padding: 1.4rem 1.5rem 1.5rem;
  background: var(--panel);
  border: var(--border-ink);
  border-radius: var(--radius-wobble);
  box-shadow: var(--shadow-paper);
}

.quiz-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 0.5rem; }
.quiz-hd h3 { margin: 0; font-size: 1.25rem; }
.quiz-score {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.quiz-intro { font-family: var(--serif); font-size: 0.95rem; color: var(--ink-soft); margin: 0 0 1rem; }

.quiz-list { display: flex; flex-direction: column; gap: 1.4rem; }

.quiz-q { padding-top: 1.2rem; border-top: 1px solid var(--rule); }
.quiz-q:first-child { padding-top: 0.4rem; border-top: 0; }

.quiz-prompt { display: flex; gap: 0.55rem; font-size: 1rem; line-height: 1.5; margin-bottom: 0.8rem; }
.quiz-num { font-family: var(--ui); font-weight: 700; color: var(--persimmon); flex: none; }

.quiz-opts { display: flex; flex-direction: column; gap: 0.5rem; }

.quiz-opt {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--serif);
  font-size: 0.95rem;
  line-height: 1.45;
  padding: 0.6rem 0.85rem;
  color: var(--ink);
  background: var(--paper);
  border: var(--border-ink-thin);
  border-radius: var(--radius-wobble-sm);
  cursor: pointer;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.quiz-opt:hover:not(:disabled) { transform: translate(-2px, -2px); box-shadow: 3px 3px 0 var(--ink); }
.quiz-opt:disabled { cursor: default; transform: none; }
.quiz-opt code { background: var(--panel-2); font-size: 0.86em; }
.quiz-opt.ok  { border-color: var(--good); background: color-mix(in srgb, var(--good) 12%, var(--paper)); box-shadow: 3px 3px 0 var(--good); }
.quiz-opt.bad { border-color: var(--bad);  background: color-mix(in srgb, var(--bad) 12%, var(--paper)); box-shadow: 3px 3px 0 var(--bad); }
.quiz-opt.revealed { border-style: dashed; }
.quiz-opt:disabled:not(.ok):not(.bad) { opacity: 0.5; }

.quiz-vecrow { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }

.quiz-fb {
  display: none;
  font-family: var(--serif);
  font-size: 0.95rem;
  line-height: 1.5;
  margin-top: 0.75rem;
  padding: 0.65rem 0.85rem;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--rule);
  background: var(--paper);
  color: var(--ink-soft);
}
.quiz-fb.show { display: block; }
.quiz-fb.ok  { border-left-color: var(--good); }
.quiz-fb.bad { border-left-color: var(--bad); }
.quiz-fb b { color: var(--ink); font-weight: 700; }
.quiz-fb code { font-size: 0.86em; }

.quiz-foot { margin-top: 1.4rem; padding-top: 1.1rem; border-top: 2px solid var(--ink); }
.quiz-summary { font-family: var(--serif); font-size: 0.95rem; color: var(--ink-soft); margin: 0 0 0.8rem; }
.quiz-summary b { color: var(--ink); }

/* ---------- print (reference sheets must print well) ---------- */

@media print {
  :root {
    --paper: #fff; --ink: #000; --ink-soft: #333; --ink-faint: #555;
    --rule: #bbb; --rule-soft: #ddd; --panel: #f7f7f7; --panel-2: #f0f0f0;
    --unity-bg: #fff; --gltf-bg: #fff;
    /* Ink shadows and blob corners cost toner and page; print is flat. */
    --shadow-paper: none; --shadow-paper-sm: none; --shadow-paper-pop: none;
    --radius-wobble: 3px; --radius-wobble-sm: 3px;
    --border-w: 1px;
    --border-ink: 1px solid #000; --border-ink-thin: 1px solid #000;
  }

  @page { margin: 11mm; }

  /* Reference sheets are meant to end up on a desk, so print is tuned for
     density: one sheet, front and back, at a size still readable at arm's
     length. Verified by page-counting the generated PDF, not by eye. */
  body { padding: 0; max-width: 100%; font-size: 8.6pt; line-height: 1.3; }
  body > * { max-width: 100%; }

  p { margin-bottom: 0.5rem; }
  ul, ol { margin-bottom: 0.5rem; padding-left: 1.1rem; }
  li { margin-bottom: 0.12rem; }

  /* No sky band on paper: the header goes back to a ruled masthead, and the
     axis tints it scoped for the sky go back to their page values. */
  .masthead {
    background: none; color: #000;
    margin: 0 0 0.6rem; padding: 0 0 0.35rem;
    border-bottom: 1px solid #000;
    --axis-x: #c0392b; --axis-y: #2e7d32; --axis-z: #1f5fa8;
  }
  .masthead h1 { font-size: 15pt; margin-bottom: 0.25rem; color: #000; text-shadow: none; }
  .masthead .kicker {
    font-size: 6pt; margin-bottom: 0.3rem; color: #555;
    background: none; border: 0; padding: 0;
  }
  .masthead .standfirst { font-size: 9pt; line-height: 1.32; color: #333; }

  h2 { margin: 0.8rem 0 0.3rem; font-size: 7pt; page-break-after: avoid; }
  h3, h4 { margin: 0.55rem 0 0.15rem; font-size: 9pt; page-break-after: avoid; }

  .callout, .spec { margin: 0.6rem 0; padding: 0.5rem 0.65rem; font-size: 8.4pt; }
  /* The trap/win accent is a colour, not a slab of it: on paper the flat
     shadow becomes a rule down the left edge. */
  .callout.trap { box-shadow: none; border-left: 3px solid var(--string); }
  .callout.win  { box-shadow: none; border-left: 3px solid var(--moss); }
  .callout > .hd, .spec .src { font-size: 6.2pt; margin-bottom: 0.25rem; }
  .callout.key { background: #f2f2f2; }
  .callout.key .big { font-size: 9.4pt; margin-bottom: 0.3rem; }

  .formula { margin: 0.5rem 0; padding: 0.45rem 0.6rem; font-size: 9pt; line-height: 1.4; }
  .formula .lbl { font-size: 6.2pt; margin-bottom: 0.2rem; }

  pre { margin: 0.5rem 0; padding: 0.5rem 0.65rem; font-size: 7.4pt; line-height: 1.42; }

  .tbl-wrap { margin: 0.6rem 0; overflow: visible; }
  table { font-size: 8pt; }
  th, td { padding: 0.22rem 0.6rem 0.22rem 0; }
  thead th { font-size: 6.2pt; border-bottom: 1px solid #000; }
  caption { font-size: 7.2pt; padding-top: 0.35rem; }

  .sources { font-size: 7.2pt; line-height: 1.32; }
  .sources li { margin-bottom: 0.25rem; }

  /* The closing band comes off on paper too — sources are reference matter,
     and they are read, not looked at. */
  .lesson-foot {
    background: none; color: #000;
    margin: 0.9rem 0 0; padding: 0.5rem 0 0;
    border-top: 1px solid #000;
  }
  .lesson-foot h2 { color: #555; }
  .lesson-foot h2::after { background: #bbb; }
  .lesson-foot a { color: #000; }
  .lesson-foot .sources li { color: #333; }
  .lesson-foot .sources li b { color: #000; }
  .lesson-foot .colophon, .lesson-foot .colophon a { color: #555; }
  .colophon { font-size: 6.6pt; }

  /* Never split an atomic block across a page boundary. */
  figure, .callout, table, .formula, .spec, pre, .tbl-wrap { page-break-inside: avoid; }

  .no-print, .ask, .readnext, .quiz, .ctl-bar, .status, .readout { display: none !important; }

  a { text-decoration: none; color: #000; }
  /* Spell out link targets — a printed page cannot be clicked. */
  .sources a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 6.4pt; color: #666; word-break: break-all;
  }
}
