/* celegans-sim viewer.

   Colour roles follow the data-viz reference palette: sequential blue for magnitude
   (neuron activation, muscle tension), diverging blue-red with a neutral grey midpoint
   for signed curvature, and the fixed categorical order for identity.

   Two modes, one switch (html[data-mode], set by controls.js -- on the root element,
   not body, because the canvas renderers read their colours off documentElement's
   computed style and must see the light palette too). A mode binds a dish painter to a
   chrome language:

     dark    the digital plate under terminal chrome -- monospace, phosphor-green
             actives, corner-ticked panels, a blinking cursor in the brand. The plate
             rendering itself is locked and untouched; the terminal look is for the
             instruments around it.
     light   the realistic plate under paper chrome -- serif, ink on paper, hairline
             and double rules, small-caps panel titles. A white paper about an animal,
             with the animal alive in the middle of it.

   The chrome speaks the mode's language; the data does not. Series colours, the
   diverging curvature ramp and the sequential activation ramp are identical in both
   modes, because a measurement should not change meaning with the decor. Dark is the
   default and everything below is written in it; the light block at the end of the
   file re-states only what changes. */

:root {
  color-scheme: dark;

  --plane:          #0d0d0d;
  --surface-1:      #1a1a19;
  --surface-2:      #201f1e;
  --text-primary:   #ffffff;
  --text-secondary: #c3c2b7;
  --text-muted:     #898781;
  --gridline:       #2c2c2a;
  --baseline:       #383835;
  --border:         rgba(255, 255, 255, 0.10);

  --series-1: #3987e5;   /* blue    */
  --series-2: #d95926;   /* orange  */
  --series-3: #199e70;   /* aqua    */
  --series-4: #c98500;   /* yellow  */
  --series-5: #d55181;   /* magenta */
  --series-6: #008300;   /* green   */

  --good:     #0ca30c;
  --warning:  #fab219;
  --critical: #d03b3b;

  --dorsal:  #e66767;    /* diverging warm pole */
  --ventral: #3987e5;    /* diverging cool pole */

  /* The chrome's active colour -- pressed buttons, focus rings, the slider thumb. A
     phosphor green that is deliberately NOT one of the six series colours: a control
     that is on must never look like a data series that is high. */
  --accent: #3ddc97;

  --radius: 8px;
  --gap: 10px;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--plane);
  color: var(--text-primary);
  overflow: hidden;
}

#app {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(340px, 26vw);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "head  head"
    "dish  side"
    "foot  foot";
  gap: var(--gap);
  padding: var(--gap);
  height: 100%;
  transition: grid-template-columns 220ms ease;
}
/* Showcase: the rail folds away and the dish takes the whole width. */
#app.norail { grid-template-columns: minmax(0, 1fr) 0px; }
#app.norail aside { opacity: 0; pointer-events: none; }

/* ---------------------------------------------------------------- header ------ */
header {
  grid-area: head;
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

.brand { display: flex; align-items: baseline; gap: 10px; }
.brand h1 { font-size: 15px; font-weight: 650; margin: 0; letter-spacing: -0.01em; }
/* The terminal's cursor, parked after the brand: the one animated flourish the dark
   chrome allows itself. steps(1) so it blinks rather than fades -- a cursor that fades
   is a loading spinner. Removed under reduced motion and in light mode. */
.brand h1::after {
  content: "\258C";              /* left half block */
  margin-left: 5px;
  color: var(--accent);
  animation: brand-cursor 1.1s steps(1, end) infinite;
}
@keyframes brand-cursor { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .brand h1::after { animation: none; opacity: 1; }
}
.brand .sub { font-size: 12px; color: var(--text-muted); }
/* One instrument, two plates. The dish tabs live in the brand row; which dish is on
 * stage is the app's data-dish attribute, and everything arena-specific -- the Track B
 * warning, the dish-level stat tiles, the corpse and energy chips -- is tagged
 * .arena-only and simply not shown on the reference dish. The arena tab selects in
 * amber, the evolution track's colour throughout, so the chrome itself says which side
 * of the fence you are on. */
.brand .warn { font-size: 11px; color: var(--warning); }
/* The museum's door: a quiet pill in the brand row, amber-edged like everything on the
 * evolution side of the fence, because the museum is where that side's discoveries are
 * catalogued. */
.museum-door {
  font-size: 12px; padding: 4px 12px; border-radius: 999px;
  border: 1px solid rgba(217, 164, 65, 0.4);
  color: var(--text-secondary); text-decoration: none; white-space: nowrap;
}
.museum-door:hover { background: rgba(217, 164, 65, 0.12); color: var(--text-primary); }
#app:not([data-dish="arena"]) .arena-only { display: none; }
/* The arena tab keeps its solid amber when selected -- Track B's colour, a fence the
   mode work does not move -- while the animal tab takes the ordinary phosphor active. */
#app[data-dish="arena"] #dish-tabs button[aria-pressed="true"] { background: var(--warning); color: #1c1913; box-shadow: none; }

.stats { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }

.stat {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 5px 11px 6px;
  min-width: 78px;
}
.stat .label {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted);
  display: flex; align-items: center; gap: 5px;
}
.stat .value {
  font-size: 16px; font-weight: 600; line-height: 1.15;
  font-variant-numeric: tabular-nums;
  /* A faint phosphor bloom on the readouts -- the terminal look at its most restrained.
     The text stays white; only the halo is green. Light mode removes it. */
  text-shadow: 0 0 8px rgba(61, 220, 151, 0.20);
}
.stat .value small { font-size: 10px; font-weight: 500; color: var(--text-muted); }

/* The pump lamp. It flashes once per pharyngeal pump, which at 250 a minute on food is
   a visible flicker and off food is an occasional blink -- the feeding rate as a thing
   you watch rather than a number you read. */
#pump-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--gridline);
  box-shadow: none;
  transition: background 60ms linear, box-shadow 60ms linear;
}
#pump-dot.on {
  background: var(--series-3);
  box-shadow: 0 0 7px var(--series-3);
}
/* The egg lamp is not a flash -- it is lit for the whole active phase, which lasts a
   couple of minutes. A steady state, so it does not need the reduced-motion treatment the
   pump lamp does. */
#egg-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--gridline);
  transition: background 200ms linear;
}
#egg-dot.on { background: var(--series-6); box-shadow: 0 0 7px var(--series-6); }

/* ------------------------------------------------------------------ dish ------ */
#dish {
  grid-area: dish;
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--plane);
}
#dish canvas { display: block; width: 100%; height: 100%; cursor: grab; }
#dish canvas.dragging { cursor: grabbing; }

.floating {
  position: absolute; z-index: 3;
  display: flex; flex-direction: column; gap: 7px;
  align-items: flex-start;
}
.floating.tl { top: 10px; left: 10px; }
.floating.tr { top: 10px; right: 10px; align-items: flex-end; }
.floating.bl { bottom: 10px; left: 10px; }

.dish-hint {
  position: absolute; bottom: 12px; right: 12px; z-index: 3;
  font-size: 10px; color: var(--text-muted); pointer-events: none;
  text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}

/* The controls float on the plate, so on the two light plates they have to invert or
   they read as smudges. The chrome is not part of the illusion -- it should stay legible
   in every mode rather than joining in. */
#dish[data-plate="light"] .seg,
#dish[data-plate="light"] .zoomrow,
#dish[data-plate="light"] .chip {
  background: rgba(252,250,245,0.86);
  border-color: rgba(30,26,20,0.18);
  color: #2b2722;
}
#dish[data-plate="light"] .seg button,
#dish[data-plate="light"] .zoomrow .sq,
#dish[data-plate="light"] .readout { color: #4a443b; }
#dish[data-plate="light"] .seg button[aria-pressed="true"] { color: #fff; }
#dish[data-plate="light"] .seg button.ghost:hover,
#dish[data-plate="light"] .zoomrow .sq:hover { background: rgba(30,26,20,0.10); color: #1c1913; }
#dish[data-plate="light"] .chip { color: rgba(43,39,34,0.45); }
#dish[data-plate="light"] .chip[aria-pressed="true"] { color: #2b2722; }
#dish[data-plate="light"] .dish-hint {
  color: rgba(43,39,34,0.62); text-shadow: 0 1px 2px rgba(255,255,255,0.5);
}

/* Segmented control: one job, three mutually exclusive answers. */
.seg {
  display: inline-flex; align-items: center;
  background: rgba(13,13,13,0.78);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 2px;
  backdrop-filter: blur(7px);
}
.seg button {
  border: 0; background: transparent; border-radius: 6px;
  padding: 4px 10px; font-size: 11px; color: var(--text-secondary);
}
.seg button[aria-pressed="true"] {
  background: rgba(61, 220, 151, 0.14);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px rgba(61, 220, 151, 0.45);
}
.seg button.ghost { color: var(--text-muted); }
.seg button.ghost:hover { color: var(--text-primary); background: rgba(255,255,255,0.08); }

.zoomrow {
  display: inline-flex; align-items: center; gap: 5px;
  background: rgba(13,13,13,0.78);
  border: 1px solid var(--border);
  border-radius: 8px; padding: 2px 7px 2px 2px;
  backdrop-filter: blur(7px);
}
.zoomrow .sq {
  width: 22px; height: 22px; padding: 0; font-size: 13px; line-height: 1;
  border: 0; background: transparent; color: var(--text-secondary); border-radius: 5px;
}
.zoomrow .sq:hover { background: rgba(255,255,255,0.09); color: #fff; }
.zoomrow .readout { font-size: 10px; min-width: 46px; text-align: right; }

/* Layer chips carry their own swatch, so the legend is the control. */
.chips { display: flex; flex-direction: column; gap: 4px; align-items: flex-end; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(13,13,13,0.78);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px 3px 7px;
  font-size: 11px; color: var(--text-muted);
  backdrop-filter: blur(7px);
}
.chip[aria-pressed="true"] { color: var(--text-primary); }
.chip .sw {
  width: 9px; height: 9px; border-radius: 3px; display: inline-block;
  opacity: 0.28; transition: opacity 120ms;
}
.chip[aria-pressed="true"] .sw { opacity: 1; }
.sw.food  { background: var(--series-3); }
.sw.att   { background: var(--series-1); }
.sw.rep   { background: var(--critical); }
.sw.egg   { background: #e2dcbe; }
.sw.grid  { background: var(--baseline); }
.sw.trail { background: var(--text-secondary); }

/* ---------------------------------------------------------------- panels ------ */
aside {
  grid-area: side;
  display: flex; flex-direction: column;
  gap: var(--gap);
  min-height: 0;
  transition: opacity 160ms ease;
}

.panel {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  position: relative;
  overflow: hidden;
  display: flex; flex-direction: column;
  /* Every panel needs a real basis, not zero. flex-grow shares the *leftover* equally,
     so a panel that starts at 0 ends up with only its share of the slack while one that
     declares a basis keeps that on top -- which left the nervous system showing a single
     row of neurons next to a muscle panel four times its height. Sizing them all in
     proportion and letting them shrink together is what the layout actually wanted. */
  flex: 1 1 var(--basis, 150px);
  min-height: 0;
}
/* Collapsed panels give their space back to the ones still open, rather than every
   panel shrinking to fit. */
.panel.collapsed { flex: 0 0 auto; }
.panel.collapsed .pbody { display: none; }

/* Corner ticks: the terminal chrome's registration marks, one at the top-left and one
   at the bottom-right of every instrument panel. Two pseudo-elements, no extra markup;
   pointer-events off so they never eat a click meant for the header. Light mode drops
   them -- paper has rules, not ticks. */
.panel::before, .panel::after {
  content: "";
  position: absolute;
  width: 9px; height: 9px;
  border: 0 solid rgba(61, 220, 151, 0.45);
  pointer-events: none;
  z-index: 2;
}
.panel::before { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.panel::after  { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }

.phead {
  all: unset;
  display: flex; align-items: center; gap: 7px;
  padding: 7px 11px 6px;
  cursor: pointer;
  flex: 0 0 auto;
}
.phead:hover .chev, .phead:hover h2 { color: var(--text-secondary); }
.phead h2 {
  margin: 0; font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-muted);
}
.phead .hint { margin-left: auto; font-size: 10px; color: var(--text-muted); }
.chev {
  width: 0; height: 0; flex: 0 0 auto;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--text-muted);
  transition: transform 150ms ease;
}
.panel.collapsed .chev { transform: rotate(-90deg); }

.pbody { position: relative; flex: 1 1 auto; min-height: 0; }
.pbody canvas { display: block; width: 100%; height: 100%; }

/* ---------------------------------------------------------------- footer ------ */
footer {
  grid-area: foot;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 9px 12px;
}

.group { display: flex; align-items: center; gap: 7px; }
.group + .group { border-left: 1px solid var(--border); padding-left: 14px; }
.group > .cap {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted);
}

button {
  font: inherit; font-size: 12px;
  color: var(--text-secondary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 11px;
  cursor: pointer;
  transition: background 120ms, color 120ms, border-color 120ms;
}
button:hover { background: #2a2a28; color: var(--text-primary); }
button[aria-pressed="true"] {
  background: rgba(61, 220, 151, 0.14);
  border-color: rgba(61, 220, 151, 0.55);
  color: var(--accent);
}
button:disabled { opacity: 0.45; cursor: default; }
button.play { min-width: 74px; font-weight: 600; color: var(--text-primary); }
.seg button, .chip { cursor: pointer; }

input[type="range"] { width: 116px; accent-color: var(--accent); }

/* The scrubber takes whatever width the footer has left. It is the one control here that
   is a position in something rather than a value, so a fixed 116px would make a minute of
   history and ten seconds of it feel identical to drag through. */
.group.grow { flex: 1 1 200px; min-width: 170px; }
.group.grow input[type="range"] { width: auto; flex: 1 1 auto; min-width: 90px; }
#o-scrub { min-width: 82px; text-align: right; }

.readout {
  font-size: 12px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums; min-width: 40px;
}

/* The worm selector sits in the footer rather than over the dish: it is about which
   animal the panels describe, and the panels are chrome, not plate. */
#worm-sel { background: var(--surface-2); padding: 2px; }
#worm-sel button { min-width: 24px; padding: 3px 7px; font-variant-numeric: tabular-nums; }
#b-worm-add, #b-worm-del { min-width: 28px; padding: 5px 8px; font-weight: 600; }

.legend {
  display: flex; gap: 10px; align-items: center; margin-left: auto;
  font-size: 11px; color: var(--text-secondary);
}
.legend span { display: inline-flex; align-items: center; gap: 5px; }
.legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }

#tooltip {
  position: fixed; z-index: 50; pointer-events: none;
  background: #000; border: 1px solid var(--border);
  border-radius: 7px; padding: 6px 9px;
  font-size: 11px; line-height: 1.45; color: var(--text-primary);
  opacity: 0; transition: opacity 90ms;
  max-width: 260px;
}
#tooltip.on { opacity: 1; }
#tooltip .k { color: var(--text-muted); }

#banner {
  position: fixed; inset: 0; display: grid; place-items: center;
  background: rgba(13, 13, 13, 0.94); z-index: 100;
  font-size: 13px; color: var(--text-secondary); text-align: center;
  transition: opacity 200ms; padding: 24px;
}
#banner.gone { opacity: 0; pointer-events: none; }
#banner b { color: var(--text-primary); display: block; margin-bottom: 6px; font-size: 15px; }
#banner code {
  display: inline-block; margin-top: 12px; padding: 5px 9px;
  background: var(--surface-1); border-radius: 6px; color: var(--text-primary);
}

@media (max-width: 1080px) {
  #app {
    grid-template-columns: minmax(0, 1fr);
    /* Transport before the panels. Stacked, the rail is five panels tall, which put
       Pause, Rate, Medium and Touch about 1500 px down the page -- past everything, on a
       device where "scroll to it" is the whole interaction. The controls that change what
       the simulation is doing belong within reach of the thing they change. */
    grid-template-rows: auto minmax(260px, 46vh) auto auto;
    grid-template-areas: "head" "dish" "foot" "side";
    height: auto; min-height: 100%;
  }
  #app.norail { grid-template-columns: minmax(0, 1fr); }
  #app.norail aside { display: none; }
  /* Let the *document* scroll, not the body box. With html and body both pinned to 100%
     the overflow became an internal scroll on <body>: it worked, but window.scrollY never
     moved and iOS treats a body-height scroller as a second, laggier scroll surface. */
  html, body { height: auto; min-height: 100%; overflow-x: hidden; overflow-y: visible; }
  /* The layer toggles used to be display:none here, which removed the only way to see or
     hide the chemical fields on exactly the devices with the least screen to spare. They
     stay; they just stop being a tall column pinned to the right edge and become a
     wrapping row tucked under the view switcher. */
  .floating.tr {
    top: 52px; left: 10px; right: 10px;
    align-items: flex-start;
  }
  .chips { flex-direction: row; flex-wrap: wrap; align-items: center; }
  /* Stacked, the rail has no fixed height to share out, so panels take their natural
     size and the page scrolls. Sharing a fraction of nothing collapsed all five to a
     hairline. */
  aside { min-height: 0; }
  .panel { flex: 0 0 auto; height: var(--mobile, 190px); }
  .panel[data-panel="muscle"] { --mobile: 130px; }
  .panel[data-panel="senses"] { --mobile: 176px; }
  .panel.collapsed { height: auto; }
}

/* Nothing may push the page sideways. A stat card or a legend that overflows turns every
   vertical scroll into a fight with a horizontal one. */
@media (max-width: 1080px) {
  header, footer { max-width: 100%; }
  .stats { margin-left: 0; }
  .legend { margin-left: 0; }
  .group + .group { border-left: 0; padding-left: 0; }
}

/* --- touch ----------------------------------------------------------------------- */
/* Sized for a finger, not a cursor: 44 px is the smallest target most people can hit
   reliably, and several of these controls were 22.
   Two triggers, not one. `pointer: coarse` is the honest signal, but it is not the only
   one that matters and it is not always told the truth -- an emulated 390 px viewport
   reports a fine pointer, and so does a touchscreen laptop. The stacked layout below
   1080 px is the touch-oriented layout whoever is using it has been given, so it gets
   touch-sized targets either way. The desktop layout above 1080 px is untouched. */
@media (pointer: coarse), (max-width: 1080px) {
  button, .seg button, .chip {
    min-height: 44px; min-width: 44px;
    padding-top: 10px; padding-bottom: 10px;
  }
  .seg button, .chip { padding-left: 14px; padding-right: 14px; }
  .zoomrow .sq { width: 44px; height: 44px; font-size: 17px; }
  .zoomrow { padding: 2px 10px 2px 2px; gap: 8px; }
  #worm-sel button { min-width: 44px; }
  #b-worm-add, #b-worm-del { min-width: 44px; }
  .phead { padding: 14px 11px; min-height: 44px; }
  input[type="range"] { height: 44px; width: 140px; }
  .chips { gap: 6px; }
  /* Three mouse gestures, described on the layout that has no mouse -- and at this width
     the line runs straight through the zoom controls. */
  .dish-hint { display: none; }
}

/* --- keyboard -------------------------------------------------------------------- */
/* Every interactive thing here is either a <button> or a <canvas tabindex=0>, and the
   panel headers use `all: unset`, which throws the focus ring away with everything else.
   One rule, applied to all of them, so tabbing through the viewer is followable. */
:where(button, [tabindex], input, .phead):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}
#dish :where(button):focus-visible { outline-color: #fff; }
#dish[data-plate="light"] :where(button):focus-visible { outline-color: #2b2722; }
/* The neuron panel takes focus as a whole and moves a cursor inside itself, so the ring
   goes round the panel body rather than round one 3 px cell. */
#c-neurons:focus-visible { outline-offset: -2px; }

/* --- reduced motion -------------------------------------------------------------- */
/* The pump lamp is the one piece of this interface that flickers by design: once per
   pharyngeal pump, up to four times a second on food. That is exactly the kind of thing
   this preference exists to switch off. It keeps its two states -- pumping or not -- and
   loses the flash. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  #pump-dot { box-shadow: none !important; }
  #pump-dot.on { box-shadow: none; }
}

/* --- what it senses -------------------------------------------------------------- */
/* Scalars the server has always sent. Each row is a labelled bar so a receptor
   responding is visible at a glance. */
#senses {
  position: absolute; inset: 2px 11px 8px;
  display: grid;
  grid-template-columns: auto minmax(28px, 1fr) auto;
  grid-auto-rows: 1fr;
  gap: 2px 8px;
  align-items: center;
  font-size: 10px;
}
#senses .s-name { color: var(--text-muted); white-space: nowrap;
                  overflow: hidden; text-overflow: ellipsis; }
#senses .s-val  { color: var(--text-secondary); font-variant-numeric: tabular-nums;
                  text-align: right; white-space: nowrap; }
/* display:block on both -- these are spans, and width is ignored on inline boxes. */
#senses .s-bar  { display: block; height: 4px; background: var(--gridline);
                  border-radius: 2px; overflow: hidden; }
#senses .s-fill { display: block; height: 100%; border-radius: 2px;
                  transition: width 80ms linear; }

/* --- light mode: the paper chrome -------------------------------------------------- */
/* Ink on paper around the realistic plate: serif, hairline and double rules, small-caps
   panel titles, buttons as ink-outlined boxes. Almost everything re-stated here is a
   custom property, so most of the file above needs no light-mode twin; the handful of
   structural rules below are the ones where the paper genuinely disagrees with the
   terminal, plus explicit removals of the terminal's decorations (glow, ticks, cursor).

   The data palette is deliberately NOT re-stated: the six series colours, the diverging
   curvature poles and the status colours are mid-tone by design and hold on both grounds. */
html[data-mode="light"] {
  color-scheme: light;

  --plane:          #f6f1e5;
  --surface-1:      #fbf8f0;
  --surface-2:      #efe8d8;
  --text-primary:   #221d15;
  --text-secondary: #45403a;
  --text-muted:     #877f6e;
  --gridline:       #ddd3bf;
  --baseline:       #c8bda6;
  --border:         rgba(34, 29, 21, 0.22);

  /* On paper the accent is the ink itself: an active control is a filled box, not a
     glowing one. */
  --accent: #221d15;

  --radius: 4px;
  font-family: Georgia, "Iowan Old Style", "Times New Roman", serif;
}

/* The terminal's decorations, switched off. */
html[data-mode="light"] .stat .value { text-shadow: none; }
html[data-mode="light"] .panel::before,
html[data-mode="light"] .panel::after { content: none; }
html[data-mode="light"] .brand h1::after { content: none; }

/* The paper's own structure: a double rule under the masthead and over the colophon. */
html[data-mode="light"] header {
  border-bottom: 3px double rgba(34, 29, 21, 0.45);
  padding-bottom: 9px;
}
html[data-mode="light"] footer {
  border: 1px solid var(--border);
  border-top: 3px double rgba(34, 29, 21, 0.45);
}

html[data-mode="light"] .phead h2 {
  text-transform: none;
  font-variant-caps: small-caps;
  letter-spacing: 0.09em;
  font-size: 12.5px;
}

html[data-mode="light"] button {
  background: var(--surface-1);
  border: 1px solid rgba(34, 29, 21, 0.5);
  border-radius: 3px;
  color: var(--text-primary);
}
html[data-mode="light"] button:hover { background: var(--surface-2); color: var(--text-primary); }
html[data-mode="light"] button[aria-pressed="true"] {
  background: #221d15;
  border-color: #221d15;
  color: #f6f1e5;
}
html[data-mode="light"] button:disabled { opacity: 0.4; }

/* Segmented controls keep their internal buttons borderless -- the ink border belongs
   to the group -- and a pressed segment is a filled ink box, not a phosphor pane. */
html[data-mode="light"] .seg {
  background: rgba(251, 248, 240, 0.92);
  border-color: rgba(34, 29, 21, 0.35);
}
html[data-mode="light"] .seg button { border: 0; background: transparent; color: var(--text-secondary); }
html[data-mode="light"] .seg button[aria-pressed="true"] {
  background: #221d15;
  color: #f6f1e5;
  box-shadow: none;
}
html[data-mode="light"] .seg button.ghost:hover { background: rgba(34, 29, 21, 0.10); color: #221d15; }
html[data-mode="light"] .zoomrow {
  background: rgba(251, 248, 240, 0.92);
  border-color: rgba(34, 29, 21, 0.35);
}
html[data-mode="light"] .zoomrow .sq { border: 0; background: transparent; }
html[data-mode="light"] .zoomrow .sq:hover { background: rgba(34, 29, 21, 0.10); color: #221d15; }
html[data-mode="light"] .chip {
  background: rgba(251, 248, 240, 0.92);
  border-color: rgba(34, 29, 21, 0.30);
}

/* Track B's amber, darkened to an ochre the cream ground can carry. Only the *chrome*
   uses of the colour -- the warning line and the arena tab -- not the --warning variable
   itself, which the charts use as a status colour and which stays put in both modes. */
html[data-mode="light"] .brand .warn { color: #9a6a10; }
html[data-mode="light"] #app[data-dish="arena"] #dish-tabs button[aria-pressed="true"] {
  background: #b98a1e; color: #fff;
}

html[data-mode="light"] .museum-door { border-color: rgba(160, 110, 20, 0.55); }
html[data-mode="light"] .museum-door:hover { background: rgba(217, 164, 65, 0.18); color: #221d15; }

html[data-mode="light"] #tooltip {
  background: #fbf8f0;
  border-color: rgba(34, 29, 21, 0.4);
  box-shadow: 0 2px 10px rgba(34, 29, 21, 0.15);
}
html[data-mode="light"] #banner { background: rgba(246, 241, 229, 0.96); }

/* The egg swatch is parchment-coloured, which on parchment is invisible. */
html[data-mode="light"] .sw.egg { background: #a4906a; }
html[data-mode="light"] .sw.trail { background: #6a6254; }
