/* trohS: a green phosphor CRT, built to his two pictures and the palette he wrote out on 3 Nov.
   One container (1120), ONE FACE (JetBrains Mono: a terminal has one), one scale
   (12/14/16/20/24/32/48), one spacing step (4/8/12/16/24/32/48), one ink that glows and one that
   does not. The only warm colour on the site is the fault ink, and it is used for nothing else.
   The instrument is a raster drawn with a beam (tools/art.mjs); every panel is a ruled box, which
   is what a terminal draws a panel with. */

@font-face { font-family: "Mono"; src: url("/font/jetbrains-mono-var.woff2") format("woff2"); font-weight: 100 900; font-display: swap; }

:root {
  --bg: #050A07;                /* the tube with nothing on it */
  --panel: #08120C;             /* a ruled box drawn on the tube */
  --grid: #0E2A18;              /* the graticule, and the fill under a key being pressed */
  --line: #1C4A2E;              /* the rule round a box: the trace at a quarter power */
  --green: #35F06A;             /* the trace: text, numbers, rules. 12.9:1 on the tube */
  --bright: #9CFFBC;            /* where the beam dwells: a live value, in the pad's favour */
  --dim: #4FA86E;               /* a label, a line that is not the point. 6.0:1 on the tube */
  --warn: #FFD166;              /* THE ONLY WARM INK: a fault, a rally against a short, a
                                   liquidation, an exchange refusing. Nothing else, ever. */
  --scan: rgba(0, 0, 0, 0.06);

  --page: 1120px;
  --gutter: 24px;
  --dial: 640px;                /* the instrument fills its share of the hall, so the column
                                   beside it never runs on past a band of empty tube */

  --s4: 4px; --s8: 8px; --s12: 12px; --s16: 16px; --s24: 24px; --s32: 32px; --s48: 48px;
  --glow: 0 0 6px rgba(53, 240, 106, 0.45);
  --glow-strong: 0 0 8px rgba(156, 255, 188, 0.85), 0 0 24px rgba(53, 240, 106, 0.45);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { background: var(--bg); }

body {
  min-height: 100%;
  font-family: Mono, ui-monospace, "JetBrains Mono", "IBM Plex Mono", monospace;
  font-size: 14px;
  line-height: 1.6;
  color: var(--green);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* THE TUBE: the graticule, the scan lines and the glow of the gun, one fixed layer behind
   everything, that the page scrolls over. It takes no clicks. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(58% 48% at 50% 38%, rgba(53, 240, 106, 0.10), rgba(53, 240, 106, 0) 72%),
    repeating-linear-gradient(0deg, var(--grid) 0 1px, transparent 1px 48px),
    repeating-linear-gradient(90deg, var(--grid) 0 1px, transparent 1px 48px),
    var(--bg);
  opacity: 0.9;
}

/* the scan lines, and the slow pass of the gun down the tube */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: repeating-linear-gradient(0deg, var(--scan) 0 1px, transparent 1px 3px);
}

/* one band of light, once every eight seconds, at an amplitude you have to look for */
.sweep {
  position: fixed;
  left: 0;
  right: 0;
  top: -30vh;
  height: 30vh;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(53, 240, 106, 0) 0%, rgba(53, 240, 106, 0.045) 55%, rgba(53, 240, 106, 0) 100%);
  animation: sweep 8s linear infinite;
}
@keyframes sweep {
  0% { transform: translateY(0); }
  100% { transform: translateY(160vh); }
}

/* the hairlines between the instrument and the plates beside it */
#hairlines {
  position: absolute;
  inset: 0;
  width: 100%;
  pointer-events: none;
  z-index: 0;
}

.page {
  position: relative;
  z-index: 3;
  max-width: var(--page);
  margin: 0 auto;
  padding: var(--s24) var(--s24) var(--s48);
}

/* ------------------------------------------------------------------ the hero
   THE SCOPE: the station's own screen, drawn here and not loaded as a picture (his order, 3 Nov:
   the banner was the cover for X and has no business on the site). The ground is the page's own
   graticule at twice the density, scan lines 1 px in 3, and the glow of the gun over the right
   third; the drawing on top of it is one inline SVG (station.js). His vortex keeps its corner.

   The animations move nothing but transform and opacity. Each ring and each mote starts its cycle
   at its own NEGATIVE delay, so under prefers-reduced-motion they are PAUSED rather than removed
   and the sounder freezes as six circles at six radii instead of collapsing into one. */

.hero { position: relative; margin-bottom: var(--s48); padding-bottom: var(--s48); }

.hero .scope {
  position: relative;
  height: 320px;
  overflow: hidden;
  border: 1px solid var(--line);
  background:
    radial-gradient(44% 72% at 72% 50%, rgba(53, 240, 106, 0.16), rgba(53, 240, 106, 0) 72%),
    repeating-linear-gradient(0deg, var(--scan) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(0deg, var(--grid) 0 1px, transparent 1px 24px),
    repeating-linear-gradient(90deg, var(--grid) 0 1px, transparent 1px 24px),
    var(--bg);
}
.hero .scope-svg { position: absolute; inset: 0; }
.hero .scope-art { display: block; width: 100%; height: 100%; }

/* the baseline, its marks and the two cursors on it */
.scope-art .base { fill: none; stroke: var(--line); stroke-width: 1; }
.scope-art .base line:first-of-type { stroke: var(--dim); }
.scope-art .cursor { fill: none; stroke: var(--dim); stroke-width: 1; }
.scope-art .cursor line { stroke-dasharray: 4 7; opacity: 0.75; }
.scope-art .cursor rect { fill: var(--bg); }

/* the echo sounder: six rings born at the centre, each thinner and fainter than the last */
.scope-art .ring {
  fill: none;
  stroke: var(--green);
  transform-box: fill-box;
  transform-origin: center;
  animation: ping 6s linear infinite;
}
.scope-art .ring:nth-of-type(1) { stroke-width: 2.6; stroke-opacity: 1;    animation-delay: 0s; }
.scope-art .ring:nth-of-type(2) { stroke-width: 2.2; stroke-opacity: 0.86; animation-delay: -1s; }
.scope-art .ring:nth-of-type(3) { stroke-width: 1.8; stroke-opacity: 0.72; animation-delay: -2s; }
.scope-art .ring:nth-of-type(4) { stroke-width: 1.5; stroke-opacity: 0.58; animation-delay: -3s; }
.scope-art .ring:nth-of-type(5) { stroke-width: 1.2; stroke-opacity: 0.44; animation-delay: -4s; }
.scope-art .ring:nth-of-type(6) { stroke-width: 1;   stroke-opacity: 0.3;  animation-delay: -5s; }
@keyframes ping {
  0%   { transform: scale(0.04); opacity: 0.25; }
  10%  { opacity: 1; }
  100% { transform: scale(1); opacity: 0; }
}

.scope-art .core { fill: var(--green); opacity: 0.22; }
.scope-art .core-lit { fill: var(--bright); filter: drop-shadow(0 0 6px rgba(156, 255, 188, 0.9)); }

/* the dust drifting in towards the source, fading out as it arrives */
.scope-art .mote {
  fill: var(--green);
  transform-box: fill-box;
  transform-origin: center;
  animation: drift 12s linear infinite;
}
@keyframes drift {
  0%   { transform: translateX(-340px); opacity: 0; }
  14%  { opacity: 0.7; }
  78%  { opacity: 0.5; }
  100% { transform: translateX(520px); opacity: 0; }
}

/* the name, printed on the screen at its top left */
.hero .say { position: absolute; left: var(--s32); top: var(--s32); max-width: 58%; }
.hero h1 {
  font-size: 48px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--bright);
  text-shadow: var(--glow-strong);
}
/* the caret the terminal leaves after the name: half a character wide, one blink a second */
.hero .caret {
  display: inline-block;
  width: 0.5ch;
  height: 0.78em;
  margin-left: 0.18em;
  vertical-align: -0.02em;
  background: var(--green);
  box-shadow: 0 0 8px rgba(53, 240, 106, 0.6);
  animation: blink 1s steps(1) infinite;
}
.hero .what {
  font-size: 14px;
  letter-spacing: 0.18em;
  color: var(--dim);
  margin-top: var(--s12);
  text-transform: uppercase;
}

/* his vortex, over the screen's bottom left corner, a third of it below the edge */
.hero .vortex {
  position: absolute;
  left: var(--s24);
  bottom: 0;
  width: 128px;
  height: 128px;
  border-radius: 50%;
  border: 3px solid var(--bg);
  box-shadow: 0 0 0 1px var(--line), 0 0 28px rgba(53, 240, 106, 0.35);
  object-fit: cover;
  background: var(--bg);
}

/* ------------------------------------------------------------------ the index line
   Four positions of one width, in a ruled channel. The open one is told apart by its ink, never
   by being wider than its neighbours. */

.index {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s24);
  margin-bottom: var(--s32);
}

.track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  width: 100%;
  border: 1px solid var(--line);
  background: var(--panel);
  padding: var(--s4);
  gap: var(--s4);
}

.track a {
  display: block;
  min-height: 44px;
  padding: var(--s12) var(--s16);
  text-decoration: none;
  color: var(--green);
  background: transparent;
  border: 1px solid transparent;
  transition: background 0.18s, color 0.18s, border-color 0.18s, text-shadow 0.18s;
}
.track a:hover { background: var(--grid); border-color: var(--line); text-shadow: var(--glow); }
.track a:active { border-color: var(--bright); }
.track a:focus-visible { outline: 2px solid var(--bright); outline-offset: -2px; }
.track a[aria-current="page"] {
  background: var(--grid);
  border-color: var(--green);
  color: var(--bright);
  text-shadow: var(--glow);
}

.track .name {
  display: block;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.track .count {
  display: block;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.3;
  color: var(--dim);
}
.track a[aria-current="page"] .count { color: var(--green); }

/* the wordmark lives in the hero now; the line that carries it elsewhere keeps this shape */
.wordmark { text-align: right; white-space: nowrap; }
.wordmark b { display: block; font-size: 32px; font-weight: 700; line-height: 1; color: var(--bright); text-shadow: var(--glow-strong); }
.wordmark span { display: block; font-size: 14px; letter-spacing: 0.12em; color: var(--dim); margin-top: var(--s4); }

/* ------------------------------------------------------------------ the two columns */

.hall {
  display: grid;
  grid-template-columns: minmax(0, 58fr) minmax(0, 42fr);
  gap: var(--gutter);
  /* a panel is as tall as what is written on it: stretching one to match the column beside it
     leaves a field of empty rule, which is worse than the uneven foot it was meant to cure */
  align-items: start;
}
/* the instrument is the exception: it has no text to run out of, so it takes the whole row and
   hangs its dial in the middle of it */
.hall > .instrument { align-self: stretch; }
/* one coin: the instrument shares its column with the vault, so it is the smaller of the two
   instruments on the site and the two columns end within a line of each other */
.hall.coin { --dial: 440px; }

/* a page with one thing to say gets one column */
.hall.one { grid-template-columns: minmax(0, 1fr); }

/* ------------------------------------------------------------------ the instrument */

.instrument {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.dial {
  position: relative;
  width: min(100%, var(--dial));
  aspect-ratio: 1 / 1;
  margin: 0 auto;
}
.dial img.face,
.dial img.needle { position: absolute; inset: 0; width: 100%; height: 100%; }
.dial img.needle {
  transform: rotate(var(--angle, 0deg));
  transform-origin: 50% 50%;
  transition: transform 1.1s cubic-bezier(0.22, 1.4, 0.36, 1);
  will-change: transform;
}

/* The readout screwed over the needle. Its corners sit in the wedge 35 degrees either side of six
   o'clock, which is the one place on the face a needle travelling 145 degrees each way cannot
   reach, so it never covers a mark or a numeral at any width. */
.window {
  position: absolute;
  left: 50%;
  top: 59%;
  transform: translateX(-50%);
  width: 38%;
  border: 1px solid var(--green);
  background: rgba(5, 10, 7, 0.92);
  box-shadow: 0 0 18px rgba(53, 240, 106, 0.22), inset 0 0 18px rgba(53, 240, 106, 0.10);
  padding: var(--s16);
  text-align: center;
  color: var(--green);
}
.window .reading { font-size: 24px; font-weight: 700; line-height: 1.1; text-shadow: var(--glow); }
.window .state { font-size: 14px; letter-spacing: 0.12em; margin-top: var(--s4); }
.caption {
  margin-top: var(--s16);
  text-align: center;
  font-size: 14px;
  color: var(--dim);
}
.state-storm { color: var(--bright); text-shadow: var(--glow); }
.state-rally { color: var(--warn); }
.state-calm { color: var(--dim); }

/* ------------------------------------------------------------------ the panels
   A ruled box with a corner tick at each of its four corners, which is how a terminal draws one.
   Every panel on the site is this box: one rule, one padding, one set of ticks. */

.slip, .chip, .barometer, .makers, .readings-box {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  padding: var(--s16) var(--s24);
  color: var(--green);
}
.slip::before, .chip::before, .barometer::before, .makers::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(var(--green), var(--green)) 0 0 / 14px 1px no-repeat,
    linear-gradient(var(--green), var(--green)) 0 0 / 1px 14px no-repeat,
    linear-gradient(var(--green), var(--green)) 100% 0 / 14px 1px no-repeat,
    linear-gradient(var(--green), var(--green)) 100% 0 / 1px 14px no-repeat,
    linear-gradient(var(--green), var(--green)) 0 100% / 14px 1px no-repeat,
    linear-gradient(var(--green), var(--green)) 0 100% / 1px 14px no-repeat,
    linear-gradient(var(--green), var(--green)) 100% 100% / 14px 1px no-repeat,
    linear-gradient(var(--green), var(--green)) 100% 100% / 1px 14px no-repeat;
}

/* ------------------------------------------------------------------ the maker's plate: the links */

.makers { padding: var(--s24) var(--s32); margin-top: var(--s24); }
.makers h2 {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--bright);
  text-shadow: var(--glow);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s16);
}
/* the state of the plate is a stamped badge, not a word floating at the end of the title */
.makers h2 em {
  font-size: 14px;
  font-style: normal;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--bg);
  background: var(--green);
  padding: var(--s8) var(--s16);
  white-space: nowrap;
  text-shadow: none;
}

.mint {
  display: flex;
  gap: var(--s8);
  margin-top: var(--s16);
  align-items: stretch;
}
.mint .value {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  overflow-wrap: anywhere;
  font-size: 14px;
  line-height: 1.5;
  min-height: 48px;
  padding: var(--s12) var(--s16);
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--bright);
  user-select: all;
}
.mint button { flex: 0 0 auto; align-self: stretch; }
.mint .value.empty { color: var(--dim); }

/* ------------------------------------------------------------------ keys */

button, .key {
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  min-height: 48px;
  padding: var(--s12) var(--s24);
  border: 1px solid var(--green);
  border-radius: 0;
  cursor: pointer;
  color: var(--green);
  background: transparent;
  transition: background 0.14s, color 0.14s, border-color 0.14s, text-shadow 0.14s, box-shadow 0.14s;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s8);
}
button:hover, .key:hover {
  background: var(--grid);
  color: var(--bright);
  text-shadow: var(--glow);
  box-shadow: 0 0 14px rgba(53, 240, 106, 0.28);
}
button:active, .key:active { border-color: var(--bright); background: var(--grid); }
button:focus-visible, .key:focus-visible { outline: 2px solid var(--bright); outline-offset: 2px; }
button[disabled], .key[aria-disabled="true"] {
  cursor: not-allowed;
  border-color: var(--line);
  color: var(--dim);
  background: transparent;
  box-shadow: none;
}

.marks {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s8);
  margin-top: var(--s16);
}
.marks .key {
  flex-direction: column;
  gap: var(--s8);
  padding: var(--s12) var(--s16);
  min-height: 80px;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-align: center;
}
.marks img { width: 24px; height: 24px; display: block; object-fit: contain; }
.marks .key[aria-disabled="true"] img { opacity: 0.45; }

/* ------------------------------------------------------------------ the readings */

.readings { margin-top: var(--s32); }
.readings h2 {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s12);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--bright);
  text-shadow: var(--glow);
  margin-bottom: var(--s12);
}
.readings h2 em { font-size: 14px; font-style: normal; font-weight: 400; color: var(--dim); }
.readings .note { color: var(--dim); }
.readings .note.warn { color: var(--warn); }
.readings .note.ok { color: var(--bright); }

.chips { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s16); }
.chip { min-width: 0; }
.chip b { display: block; font-size: 16px; font-weight: 700; letter-spacing: 0.06em; }
.chip .price { display: block; font-size: 16px; margin-top: var(--s4); color: var(--bright); text-shadow: var(--glow); }
.chip small { display: block; font-size: 14px; color: var(--dim); margin-top: var(--s4); overflow-wrap: anywhere; }

@media (max-width: 880px) { .chips { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .chips { grid-template-columns: minmax(0, 1fr); } }

/* ------------------------------------------------------------------ the journal and the vault */

.column { display: flex; flex-direction: column; gap: var(--s24); }

.slip h2 {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--bright);
  text-shadow: var(--glow);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s4) var(--s12);
}
.slip h2 em { font-size: 14px; font-style: normal; font-weight: 400; color: var(--dim); letter-spacing: 0.06em; }
.slip > p { font-size: 14px; color: var(--dim); margin-top: var(--s8); }

.rows { list-style: none; margin-top: var(--s12); }
.rows li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s12);
  padding: var(--s8) var(--s16);
  border-top: 1px solid var(--line);
  align-items: baseline;
  transition: background 0.14s;
}
.rows li:hover { background: rgba(53, 240, 106, 0.06); }
.rows li:first-child { border-top: 0; }
.rows .what { font-size: 14px; color: var(--green); min-width: 0; overflow-wrap: anywhere; }
.rows .what small { display: block; font-size: 14px; color: var(--dim); }
.rows .num { font-size: 14px; text-align: right; white-space: nowrap; color: var(--bright); }
a { color: var(--green); text-decoration: underline dotted; text-underline-offset: 4px; }
a:hover { color: var(--bright); text-decoration: underline solid; text-shadow: var(--glow); }

/* ------------------------------------------------------------------ the wall */

.section-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s16);
  margin: var(--s48) 0 var(--s16);
}
.section-head h2 {
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--bright);
  text-shadow: var(--glow);
}
/* the caret a terminal leaves where it stopped printing */
.section-head h2::after {
  content: "_";
  color: var(--green);
  animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.section-head p { font-size: 14px; color: var(--dim); }

.order { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s8); margin-bottom: var(--s16); }
@media (max-width: 520px) { .order { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.order button {
  font-size: 14px;
  font-weight: 400;
  min-height: 44px;
  padding: var(--s8) var(--s16);
  border-color: var(--line);
  color: var(--dim);
}
.order button:hover { border-color: var(--green); color: var(--bright); }
.order button[aria-pressed="true"] {
  border-color: var(--green);
  background: var(--grid);
  color: var(--bright);
  text-shadow: var(--glow);
}

.wall {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gutter);
}
.barometer {
  display: grid;
  grid-template-columns: 168px 1fr;
  gap: var(--s16);
  text-decoration: none;
  transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
}
.barometer:hover { border-color: var(--green); box-shadow: 0 0 22px rgba(53, 240, 106, 0.22); }
.barometer:focus-visible { outline: 2px solid var(--bright); outline-offset: 3px; }
.coin-dial { position: relative; width: 168px; height: 168px; align-self: center; }
.coin-dial img { position: absolute; inset: 0; width: 100%; height: 100%; }
.coin-dial img.needle { transform: rotate(var(--angle, 0deg)); transition: transform 1.1s cubic-bezier(0.22, 1.4, 0.36, 1); }
.coin-face { display: flex; flex-direction: column; }
.coin-face h3 {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--bright);
  text-shadow: var(--glow);
  display: flex;
  justify-content: space-between;
  gap: var(--s8);
}
.coin-face h3 em { font-size: 14px; font-style: normal; font-weight: 400; color: var(--dim); text-shadow: none; }

/* every cell carries the same rows in the same shape, so the rules line up across the wall */
.facts { list-style: none; margin-top: var(--s8); display: grid; gap: var(--s4); }
.facts li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s8); align-items: baseline; }
.facts .k { font-size: 14px; letter-spacing: 0.04em; color: var(--dim); }
.facts .v { font-size: 14px; text-align: right; color: var(--green); }
/* ONE RULE FOR COLOUR: the bright trace is in the pad's favour, the warm ink is against it, and
   anything that is neither is the plain trace. Written out against the rows and the facts as well,
   because those name their own ink and would otherwise win on specificity and say nothing. */
.v-storm, .rows .num.v-storm, .facts .v.v-storm { color: var(--bright); text-shadow: var(--glow); }
.v-rally, .rows .num.v-rally, .facts .v.v-rally { color: var(--warn); text-shadow: none; }

/* a two column split INSIDE a panel */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s32);
  align-items: start;
}
.split > * { min-width: 0; }
.split > * > *:first-child { margin-top: 0; }
@media (max-width: 880px) { .split { grid-template-columns: minmax(0, 1fr); gap: var(--s16); } }

/* ------------------------------------------------------------------ forms */

.field { display: block; margin-top: var(--s16); }
.field > span { display: block; font-size: 14px; letter-spacing: 0.12em; color: var(--dim); margin-bottom: var(--s4); }
input[type="text"], input[type="number"], textarea, select {
  width: 100%;
  min-height: 44px;
  font-family: inherit;
  font-size: 14px;
  padding: var(--s8) var(--s12);
  color: var(--bright);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 0;
  caret-color: var(--green);
}
input::placeholder, textarea::placeholder { color: var(--dim); opacity: 1; }
input:hover, textarea:hover, select:hover { border-color: var(--green); }
textarea { min-height: 88px; line-height: 1.5; resize: vertical; }
input:focus-visible, textarea:focus-visible, select:focus-visible { outline: 2px solid var(--green); outline-offset: 1px; }
input[type="range"] { width: 100%; accent-color: var(--green); height: 44px; display: block; }

/* A slider says what it is set to and where its ends are, or it is a decoration you drag. */
.range .slide { position: relative; display: block; padding-top: var(--s32); }
.range .bubble {
  position: absolute;
  top: 0;
  left: 0;
  transform: translateX(-50%);
  font-size: 14px;
  line-height: 1.2;
  padding: var(--s12) var(--s16);
  color: var(--bg);
  background: var(--green);
  white-space: nowrap;
  pointer-events: none;
}
.range .ends { display: flex; justify-content: space-between; margin-top: 0; }
.range .ends em { font-size: 14px; font-style: normal; color: var(--dim); }

/* a file input prints the browser's own words in the browser's own language */
input[type="file"] { height: 44px; padding: var(--s12); line-height: 20px; }
.pick { display: flex; align-items: center; gap: var(--s16); margin-top: var(--s4); flex-wrap: wrap; }
.pick output { font-size: 14px; color: var(--dim); overflow-wrap: anywhere; min-width: 0; }

.choice { display: flex; flex-wrap: wrap; gap: var(--s8); margin-top: var(--s4); }
/* a group of answers to one question is a row of equal keys: the widest answer sets the width */
.choice.four { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.choice.two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.choice.four label, .choice.two label { flex-direction: column; gap: var(--s4); text-align: center; }
@media (max-width: 520px) { .choice.four { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 420px) { .choice.four { grid-template-columns: minmax(0, 1fr); } }
.choice label {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s8);
  min-height: 44px;
  padding: var(--s8) var(--s16);
  font-size: 14px;
  color: var(--green);
  background: transparent;
  border: 1px solid var(--line);
  cursor: pointer;
  transition: background 0.14s, border-color 0.14s, color 0.14s;
}
.choice input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.choice label:hover { background: var(--grid); border-color: var(--green); }
.choice label:has(input:checked) {
  background: var(--grid);
  border-color: var(--green);
  color: var(--bright);
  text-shadow: var(--glow);
}
.choice label:has(input:focus-visible) { outline: 2px solid var(--bright); outline-offset: 2px; }
.choice .mono { font-size: 14px; color: var(--dim); }
.choice label:has(input:checked) .mono { color: var(--green); }

.note { font-size: 14px; color: var(--dim); margin-top: var(--s12); }
.warn { color: var(--warn); }
.ok { color: var(--bright); }

/* ------------------------------------------------------------------ odds and ends */

.wide { grid-column: 1 / -1; }
.hidden { display: none !important; }
.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.lead { font-size: 16px; line-height: 1.7; color: var(--green); max-width: 68ch; }
.lead + .lead { margin-top: var(--s12); }
.dim { color: var(--dim); }
.live { color: var(--bright); text-shadow: var(--glow); }

.steps { list-style: none; counter-reset: step; display: grid; gap: var(--s12); margin-top: var(--s16); }
.steps li { display: grid; grid-template-columns: 40px 1fr; gap: var(--s12); align-items: start; }
.steps li::before {
  counter-increment: step;
  content: counter(step);
  font-size: 24px;
  font-weight: 700;
  color: var(--line);
  text-align: right;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: var(--s24);
  transform: translateX(-50%);
  z-index: 40;
  font-size: 14px;
  padding: var(--s12) var(--s24);
  background: var(--panel);
  border: 1px solid var(--green);
  color: var(--bright);
  box-shadow: 0 0 24px rgba(53, 240, 106, 0.3);
}

/* ------------------------------------------------------------------ the widths he checks */

@media (max-width: 1140px) {
  :root { --page: 100%; }
  .page { max-width: 1024px; }
  /* the narrower the window, the more a 42 per cent column wraps and the taller it grows against
     the instrument beside it: at this width the hall is halves */
  .hall { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

@media (max-width: 880px) {
  /* one column: the instrument is no longer paired with the journal, so it takes the room it had
     in both of them rather than leaving a band of nothing beside itself */
  :root { --dial: 560px; }
  .hero .scope { height: 220px; }
  .hero .say { left: var(--s24); top: var(--s24); max-width: 64%; }
  .hero h1 { font-size: 32px; }
  .hall { grid-template-columns: minmax(0, 1fr); }
  .wall { grid-template-columns: minmax(0, 1fr); }
  .index { flex-direction: column; align-items: stretch; gap: var(--s16); }
  .track { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 520px) {
  .page { padding: var(--s16) var(--s16) var(--s32); }
  /* a phone: the screen is 160, the vortex 88 with a third of it below, and the name sits at the
     top left where the vortex cannot reach it */
  .hero { padding-bottom: 29px; }
  .hero .scope { height: 160px; }
  .hero .say { left: var(--s16); top: var(--s16); max-width: 88%; }
  .hero h1 { font-size: 32px; }
  .hero .what { margin-top: var(--s8); letter-spacing: 0.12em; }
  .hero .vortex { width: 88px; height: 88px; left: var(--s16); }
  .wordmark b { font-size: 24px; }
  /* On a phone the window's own text cannot shrink with the dial, so the box would eat the face:
     the reading drops one step of the scale. */
  .window .reading { font-size: 20px; }
  .window .state { font-size: 14px; }
  .barometer { grid-template-columns: 112px 1fr; gap: var(--s12); padding: var(--s16) var(--s24); }
  .coin-dial { width: 112px; height: 112px; }
  .marks { grid-template-columns: repeat(2, 1fr); }
  .mint { flex-direction: column; }
  .makers { padding: var(--s16) var(--s24); }
  .makers h2 { flex-direction: column; align-items: flex-start; gap: var(--s8); }
}

@media (max-width: 420px) {
  /* a narrow phone has no room for a key and its value on one line: the value drops under its key
     and stays left, so nothing ever leaves the panel */
  .barometer { grid-template-columns: minmax(0, 1fr); }
  .coin-dial { margin: 0 auto var(--s12); }
  .facts li { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .facts .v { text-align: left; white-space: normal; overflow-wrap: anywhere; }
  .coin-face h3 { flex-wrap: wrap; }
  .rows li { grid-template-columns: minmax(0, 1fr); }
  .rows .num { text-align: left; white-space: normal; }
}

@media (max-width: 360px) {
  .window { width: 46%; }
  .window .reading { font-size: 16px; }
  /* at 320 two positions do not fit across: the track runs down instead */
  .track { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .dial img.needle, .coin-dial img.needle { transition: none; }
  .sweep { display: none; }
  .section-head h2::after, .hero .caret { animation: none; }
  /* PAUSED, not removed: each ring and mote holds the frame its own negative delay puts it on,
     so the sounder stands still as six rings of six radii. Killing the animation instead (a
     blanket animation-duration: 0.001ms) runs every one of them to its last frame, which is
     scale(1) at zero opacity: an empty screen. */
  .scope-art .ring, .scope-art .mote { animation-play-state: paused; }
}

/* the line under a coin's name on the wall: what it is doing, and whose vault */
.sub { font-size: 14px; color: var(--dim); }

/* the line a coin prints while it waits for the exchange: a fault, in the one warm ink */
.small-gap { margin-top: var(--s4); }

/* X's mark is published in black for light grounds and in white for dark ones. The file in
   public/img/marks is the black one, and this tube is a dark ground: the mark is shown in the
   white of X's own dark-ground variant, which is the same mark and not a redrawn one. */
.marks img[src*="mark-x"] { filter: invert(1); }
