/* Spec §8. Grayscale; colour is reserved for live elements (bid/ask) and nothing else. */

:root {
  --bg: #FDFDFC;
  --ink: #1A1A18;
  --muted: #6B6B66;

  /* 1.25 scale off an 18px body */
  --t-0: 1.125rem;   /* 18px */
  --t-1: 1.406rem;
  --t-2: 1.758rem;
  --t-3: 2.197rem;

  --serif: Charter, "Bitstream Charter", "Iowan Old Style", Georgia, serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* One line of body text: --t-0 × 1.6. Every prose block gap is exactly this, so the
     page keeps a rhythm without anyone tuning margins block by block. */
  --lead: 1.8rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #131312;
    --ink: #E8E8E4;
    --muted: #93938C;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 4rem 1.5rem;
  background: var(--bg);
  color: var(--ink);
  font: var(--t-0)/1.6 var(--serif);
  /* ponytail: system serif stack until the self-hosted variable woff2 (<=40KB) lands */
}

/* The page never scrolls sideways, whatever the engine puts in it. Anything genuinely wider
   than a phone carries its own scroll box — `.scroll-x` for the tables, `.log li` for a long
   event line — and this is the backstop for whatever gets added next, so a new wide widget
   degrades to a clipped edge rather than to a page that slides under the thumb.
   `hidden` rather than `clip`, which is the tidier value but lands nothing before Safari 16.
   The usual objection to `hidden` — that it makes body a scroll container and breaks
   position:sticky — costs nothing here, because nothing on this page is sticky. The nested
   scroll boxes are unaffected either way: a scroll container inside a clipped ancestor
   still scrolls, which is checked at 320px with both tables full. */
html, body { overflow-x: hidden; }

/* Two measures on one page. Prose holds 66ch; the engine's own widgets — ladder, gauge,
   position table, log — are allowed the full 80ch. The width change is what says "this is
   the machine, not the essay", which is the argument the page is making anyway. */
main { max-width: 80ch; margin: 0 auto; }
h1, h2, h3, p, .numbers, .track, .practices { max-width: 66ch; }

p, ul, ol, dl, fieldset { margin: 0 0 var(--lead); }

/* Hierarchy through scale, not weight. */
h1, h2 { font-weight: normal; line-height: 1.25; }
h1 { font-size: var(--t-3); margin: 0; }

/* Section grammar with no colour and no images: uppercase, letter-spaced, hairline under.
   The rule carries the break that size used to, which frees h2 back to body size and keeps
   the scale flat. */
h2 {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 4rem 0 var(--lead);
}
h2::after {
  content: "";
  display: block;
  border-top: 1px solid currentColor;
  margin-top: 0.4rem;
  opacity: 0.5;
}

.lede { font-size: var(--t-1); margin: 0.5rem 0 0; }
.meta { color: var(--muted); margin: 0.5rem 0 0; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:focus-visible, :focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* Digits must not jitter as the book ticks. */
.numbers, .track, table, b { font-variant-numeric: tabular-nums; }

.numbers { list-style: none; padding: 0; }
.numbers li { margin: 0.35rem 0; }
.numbers b { font-weight: normal; font-family: var(--mono); }

.practices { list-style: none; padding: 0; }
.practices li { margin: 0.5rem 0; }

/* Role and years share a baseline with the years pushed right, which is the one alignment
   that survives a role title long enough to wrap. */
.track > div { margin: 0 0 var(--lead); }
.track dt { display: flex; flex-wrap: wrap; gap: 0 1.5rem; justify-content: space-between; align-items: baseline; margin: 0; }
.track dt span { color: var(--muted); font-family: var(--mono); font-size: 0.9rem; }
.track dd { margin: 0.35rem 0 0; }
.track .sub { color: var(--muted); margin: 0; }
.track ul { margin: 0.5rem 0 0; padding-left: 1.1rem; }
.track li { margin: 0.5rem 0; }

/* ── The explorable ─────────────────────────────────────────────────────────────────
   Colour appears here and nowhere else on the page, because this is the only part that
   is live. Bid and ask are labelled in the table header as well as coloured — the colour
   is a second channel, never the only one (§9). All four pass WCAG AA on both grounds. */

:root { --bid: #0B6E3F; --ask: #A31E14; }
@media (prefers-color-scheme: dark) {
  :root { --bid: #4ADE80; --ask: #F87171; }
}

h3 { font-size: var(--t-0); font-weight: normal; margin: 2.5rem 0 0.5rem; color: var(--muted); }

/* Controls appear only once the engine is running: with JS off the reader gets the essay
   and a readable book, not buttons that do nothing (§9). Hung off the root rather than
   written as a bare `.needs-js`, which any later single-class rule would out-specify —
   that is exactly how the gauge stayed visible with JS off. */
html:not([data-js]) .needs-js { display: none; }

table { border-collapse: collapse; width: 100%; margin: 0 0 var(--lead); font-family: var(--mono); font-size: 0.9rem; }
caption { text-align: left; color: var(--muted); padding-bottom: 0.5rem; font-family: var(--serif); }
th { font-weight: normal; color: var(--muted); text-align: right; }
th, td { padding: 0.2rem 0.5rem; text-align: right; }
th:first-child, td:first-child { text-align: left; padding-left: 0; }
th:last-child, td:last-child { padding-right: 0; }
thead th { border-bottom: 1px solid currentColor; }

/* Six numeric columns are wider than a phone. The table scrolls inside its own box
   rather than widening the page, and cells never wrap, so min-content is the full
   figure — without this a squeezed cell breaks "−$2.48" across two lines. */
.scroll-x { overflow-x: auto; }
.positions th, .positions td { white-space: nowrap; }

.ladder td { width: 25%; }
.bid { color: var(--bid); }
.ask { color: var(--ask); }

/* The ladder holds five rows whether or not the book does, so the page does not jump as
   levels are consumed and re-quoted. */
.ladder tbody { min-height: 5rem; }
.ladder tbody tr { height: 1.4rem; }

.ticket fieldset { border: 1px solid var(--muted); padding: 0.5rem 1rem 1rem; margin: 0 0 var(--lead); }
.ticket legend { color: var(--muted); font-family: var(--serif); }
.ticket p { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-items: baseline; margin: 0.5rem 0; }
/* The flex rule above out-specifies the `hidden` attribute's UA style, which is how the
   limit-price field stayed visible for market orders. */
.ticket p[hidden] { display: none; }
.ticket label { flex: 0 0 17ch; color: var(--muted); font-size: 0.9rem; }
.ticket input, .ticket select { flex: 1 1 8rem; min-width: 0; }

button, select, input {
  font: inherit;
  font-size: 0.9rem;
  font-family: var(--mono);
  color: inherit;
  background: transparent;
  border: 1px solid var(--muted);
  padding: 0.25rem 0.6rem;
}
button { cursor: pointer; }
button:hover { border-color: currentColor; }
button[aria-pressed="true"] { border-color: currentColor; box-shadow: inset 0 0 0 1px currentColor; }

.controls { margin: 0 0 var(--lead); }
.controls p { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; margin: 0.5rem 0; }
.controls label { color: var(--muted); font-size: 0.9rem; }

.gauge { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 1rem; margin: 0 0 var(--lead); }
.gauge dt { color: var(--muted); font-size: 0.9rem; }
.gauge dd { margin: 0.2rem 0 0; font-family: var(--mono); font-size: var(--t-1); }

.log {
  font-family: var(--mono); font-size: 0.8rem; line-height: 1.7;
  list-style: none; padding: 0; margin: 0 0 var(--lead);
  max-height: 18rem; overflow-y: auto;
  color: var(--muted);
}
.log li { white-space: pre; overflow-x: auto; }
.log .mark { color: var(--ink); }

.muted { color: var(--muted); }
.small { font-size: 0.9rem; }

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

footer { margin-top: 4rem; color: var(--muted); }

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