/* ═══════════════════════════════════════════════════════ 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; /* A deliberate, acknowledged ninth: the fastext nav has eight destinations and only five of the locked eight read as legible text on black once red/green/yellow/cyan/magenta/blue are already spoken for (Activity ran out — a dithered swatch alone read as unfinished, and dithering the word itself was tried and found illegible). Not "one of the eight" — used nowhere else. */ --tt-orange: #ff8000; /* ── 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; }