arr-summary/static/css/base.css
Barely Removable bc7779e590 Fix the finish review's 8 material findings on the teletext redesign
Applies the fix round from the finish-reviewer's disposition on commit
4b19cbd, in one batch:

- System's disk table is unreadable below 560px: horizontal-scrolling a
  6-column table hid the usage bar and the temperature, the two
  readings that matter most (discipline 3 — one shared ruler — was
  unauditable as a result). Added a disk_row() macro and a phone-only
  .tt-disk-rows reflow (name + full 20-cell bar + temp on one line,
  device/free/total beneath), CSS-toggled against the existing table
  at the same breakpoint.
- Contrast failure on the highest-severity state: white text on the
  red .tt-field.crit/.tt-toast.error/.tt-btn.armed reversals measured
  4.0:1, under the 4.5:1 floor. Switched to black text (5.25:1),
  matching the black-on-yellow .warn pattern already in use — and
  fixed a second instance of the same bug: .tt-field.crit had no
  .tt-field-meta override, unlike .warn.
- Two type families where the direction contract names one blocky
  monospace: unified on a single self-hosted face (Space Mono, one
  weight, no bold) for both body and the double-height row.
- FIRST VIEWPORT proportion: an unpromised 6-item Just Added grid was
  competing with NOW SHOWING for the fold instead of the contract's
  "lower two-thirds in double-height cyan." Cut to a fixed 3-item,
  fixed-3-column row, which also fixes the orphaned-tile grid defect
  as a side effect (a fixed count can't leave a lone tile beside empty
  tracks).
- Three flat mid-grey fills contradicted discipline 1 (no in-between
  tone): .tt-tile-art, .tt-btn:disabled, and .tt-err pre all painted a
  solid --ink-dimmer background. Centralized the dither .tt-tile-art
  already used correctly into a shared --dither-mid generator and
  applied it to all three.
- Google Fonts dependency on a LAN-only home server: a dropped webfont
  request was a silent identity change, not a graceful fallback.
  Self-hosted Space Mono under static/fonts/ via @font-face; dropped
  the <link> tags from _shell.html and login.html.
- Deliberately deferred: "pages differ in stock" (discipline 5) still
  fires on only one band service-wide. Every other finding was a
  bounded fix to existing code; this one asks for a new mechanism (an
  aggregate status band on P100) rather than a correction, so it's
  flagged for a follow-up rather than rushed into this batch.

Recaptured desktop.png, mobile.png, desktop-system.png and
mobile-system.png (the four files the reviewer's findings cited)
through the same true-390px iframe method as the prior round, and
returned them for the fix round's verdict pass.

Known follow-up: DESIGN.md's typography section (written by the
documenter before this batch) still names the old two-family pairing
and needs a re-run now that the font system changed under it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBw1QodG8ZMYHrGeQfqyDS
2026-08-29 21:18:11 -07:00

178 lines
8.3 KiB
CSS

/* ═══════════════════════════════════════════════════════
MEDIA CENTRE — "Page 100"
A broadcast information service, not a dashboard. The world
is teletext (Ceefax, and the cable guide channel that did the
same job in America): a locked eight-colour palette on pure
black, one blocky monospace at exactly two heights, a strict
character-cell grid, and grouping carried by colour fields and
row weight — never by a border, never by a box.
Five disciplines this world is held to. Breaking one is a
regression, not a variation:
1. NO IN-BETWEEN TONE. There are eight colours. A mid-grey is
an ordered dither of two of them (--dither-*), never a
ninth colour smuggled into the palette.
2. NO ENCLOSURE. Nothing is ever surrounded by a border or a
box. Grouping is a coloured field row, indentation, and
weight. This is the exact reflex the old design was built
on and the main thing this world refuses.
3. ONE RULER. Every bar, meter and percentage on every page
shares one scale (--bar-cells), so 60% on the array and
60% on an indexer are the same width and compare directly.
4. EVERY READING CARRIES ITS DIRECTION. A value shows where
it is heading, so a disk becoming a problem is visible
before it is one.
5. PAGES DIFFER IN STOCK. A page holding critical state is
set heavier than a quiet one. Uniform texture across seven
pages is a failure.
═══════════════════════════════════════════════════════ */
/* Self-hosted, deliberately: this app runs on a LAN-only home server
behind a filtered/offline-capable network, where a Google Fonts
request can simply fail. A dropped @font-face request means every
character on the page silently falls back to whatever monospace the
OS ships — a different world by accident, not a variation of this
one. One weight only (400): there is no bold in this system. */
@font-face {
font-family: 'Space Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('../fonts/SpaceMono-Regular.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
:root {
/* ── The locked eight ──────────────────────────────────
Teletext had exactly these, at full saturation, and the
product's semantics were already the same semantics:
green runs, yellow works, red is off air. Do not soften
them; the emissive-on-black scene is what they are for. */
--tt-black: #000000;
--tt-red: #ff0000;
--tt-green: #00ff00;
--tt-yellow: #ffff00;
--tt-blue: #0000ff;
--tt-magenta: #ff00ff;
--tt-cyan: #00ffff;
--tt-white: #ffffff;
/* ── Roles ─────────────────────────────────────────────
Each colour means one thing across all nine pages. */
--ink: var(--tt-white); /* body text */
--voice: var(--tt-yellow); /* the service speaking: mastheads, page numbers */
--live: var(--tt-cyan); /* live values, now showing */
--ok: var(--tt-green); /* running, healthy, available */
--alert: var(--tt-red); /* off air, failed, danger */
--pending: var(--tt-magenta); /* requested, waiting on a human */
--field: var(--tt-blue); /* the only "background" colour — header fields */
/* ── Dither ────────────────────────────────────────────
The only legal way to make a tone that isn't one of the
eight. A checkerboard of the colour against black at cell
scale, exactly how a 16-colour screen faked a gradient.
Used for inactive bar cells and secondary text grounds. */
--dither-size: 2px;
/* --ink-dim is the ONLY dimmed value allowed to carry text: at 58% it
clears 4.5:1 on black. --ink-dimmer is for graphics only — bar
troughs, the dither field, the separator — because at 30% it does
not, and secondary text set in it was failing contrast outright. */
--ink-dim: color-mix(in srgb, var(--tt-white) 58%, var(--tt-black));
--ink-dimmer: color-mix(in srgb, var(--tt-white) 30%, var(--tt-black));
/* The one legal way to fill an area with a mid-tone: every "flat
grey panel" in the codebase (a disabled button, an unloaded poster,
a code block behind an error detail) draws from this generator
rather than declaring --ink-dimmer as a solid background. A solid
fill of a dimmed token is still a ninth colour by another name. */
--dither-mid: repeating-linear-gradient(45deg,
var(--ink-dimmer) 0 1px, var(--tt-black) 1px calc(var(--dither-size) * 2));
/* ── Type: one face, exactly two heights ───────────────
Teletext's entire scale — ONE family, not one for body and a
different one for the double-height row. Emphasis comes from
colour and from doubling the height, never from a weight ramp
(this face loads a single weight, 400, on purpose — there is
no bold anywhere to reach for) and never from a third size. */
--fs: 0.9375rem; /* 15px — the single body size */
--fs2: 1.875rem; /* 30px — double height, the only other size */
--lh: 1.45;
--row: calc(var(--fs) * var(--lh)); /* one character row */
--cell: 1ch;
--font: 'Space Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
--font-dh: var(--font);
/* ── Measure ───────────────────────────────────────────
A teletext page was 40 columns. A screen this wide gets
double that, so density survives without the grid dying. */
--page-cols: 92ch;
--gutter: 1.5rem;
/* ── The one ruler (discipline 3) ──────────────────────
Every bar on every page is this many cells wide, so any
two percentages anywhere in the service are comparable. */
--bar-cells: 20;
--bar-cell-w: 0.62em;
--tap: 44px;
}
*, *::before, *::after { box-sizing: border-box; }
html { background: var(--tt-black); }
body {
margin: 0;
background: var(--tt-black);
color: var(--ink);
font-family: var(--font);
font-size: var(--fs);
line-height: var(--lh);
font-variant-numeric: tabular-nums;
/* Teletext never anti-aliased into a soft grey edge. Keep the
letterforms crisp rather than letting the browser blend them
toward tones the palette does not contain. */
-webkit-font-smoothing: antialiased;
text-rendering: optimizeSpeed;
}
/* Phosphor bloom. Applied only where the world is speaking loudly —
double-height rows and status glyphs — because bloom under a dense
table of figures costs more legibility than it buys character. */
.bloom {
text-shadow: 0 0 0.4em color-mix(in srgb, currentColor 55%, transparent);
}
a { color: var(--live); text-decoration: none; }
a:hover { color: var(--tt-black); background: var(--live); }
/* Focus is a reversed cell, the way a teletext menu row selected
itself. No outline ring — a ring is an enclosure. */
:focus-visible {
outline: none;
background: var(--voice);
color: var(--tt-black);
}
::selection { background: var(--live); color: var(--tt-black); }
/* Browser furniture, themed to the palette rather than left at the
defaults that belong to no design system. */
* { scrollbar-color: var(--ink-dimmer) var(--tt-black); scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--tt-black); }
::-webkit-scrollbar-thumb { background: var(--ink-dimmer); }
::-webkit-scrollbar-thumb:hover { background: var(--ink-dim); }
::-webkit-scrollbar-corner { background: var(--tt-black); }
input { caret-color: var(--voice); }
.visually-hidden {
position: absolute; width: 1px; height: 1px;
padding: 0; margin: -1px; overflow: hidden;
clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}