diff --git a/CLAUDE.md b/CLAUDE.md index 0984715..10ca8d5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -66,7 +66,12 @@ the user's Unraid home server. Server-side project directory is still named than a variation: 1. **No in-between tone.** There are eight colours (the teletext primaries). A mid-grey is an ordered dither of two of them, never a - ninth colour. + ninth colour — except `--tt-orange`, the one deliberate, acknowledged + break in `base.css`, added when the fastext nav ran out of legible + colours for its eighth destination (Activity) and dithering the + word itself proved illegible. Treat a *second* ninth colour showing + up as the regression this discipline warns about; this one is a + one-time, explained exception, not a precedent. 2. **No enclosure.** Nothing is surrounded by a border or a box. There is zero `border-radius` in the codebase. Grouping is a coloured field row (`.tt-field`), indentation, and weight. This is the single thing the @@ -106,23 +111,27 @@ the user's Unraid home server. Server-side project directory is still named other nav, so it needs no scroll to reach. The index overrides it with `HOME_FASTEXT`, the original four-entry row, as its own closing line, since its body already lists every destination once. Every - destination gets its own distinct mark. Six get a flat colour, text - and swatch both: Index/Library/Discover/System keep their `r`/`g`/ - `y`/`c` shortcut; Requests gets magenta/`--pending` with no - shortcut (a deliberate fit — Requests already is "waiting on a - human" everywhere else magenta appears); Watch gets blue (`.k-blue`) - with no shortcut. Blue is a known exception to the app's own 4.5:1 + destination gets its own distinct flat colour, text and swatch + both: Index/Library/Discover/System keep their `r`/`g`/`y`/`c` + shortcut; Requests gets magenta/`--pending` with no shortcut (a + deliberate fit — Requests already is "waiting on a human" + everywhere else magenta appears); Watch gets blue (`.k-blue`) with + no shortcut. Blue is a known exception to the app's own 4.5:1 text-contrast bar (it clears ~2.4:1 on black) — kept anyway, at the visitor's request, over the alternative of a swatch-only accent - that read as unfinished next to six fully-coloured neighbours. - Activity gets an ordered-dither swatch (`.k-dither`, same mechanism - as `--dither-mid`) instead of a flat colour — the one other legal - way to get a distinct mark without a ninth hue. Settings alone - keeps plain ink with no swatch treatment — deliberately, as the one - page with no live status of its own. Whichever entry matches the - current page renders as a `.fastext-here` span instead of a link — - a page linking to itself did nothing, so it isn't offered as a - click. + that read as unfinished next to its fully-coloured neighbours. + Activity gets `--tt-orange` (`.k-orange`) — a genuine ninth colour, + the one destination that breaks "eight colours, no ninth" + outright, defined and explained in `base.css` right after the + locked eight. It's there because the palette ran out at six + (dithering a swatch alone read as unfinished, and dithering the + word itself renders illegible) and the visitor wanted every + destination to look different, not merely as different as eight + colours allow. Settings alone keeps plain ink — deliberately, as + the one page with no live status of its own. Whichever entry + matches the current page renders as a `.fastext-here` span instead + of a link — a page linking to itself did nothing, so it isn't + offered as a click. - **Nothing is clipped, hidden, or sticky.** All seven page numbers and every fastext entry stay visible at every width, reflowing to another row rather than scrolling, truncating, or folding into a menu. No diff --git a/DESIGN.md b/DESIGN.md index ecaf3e4..58273d9 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -181,7 +181,7 @@ Teletext had exactly eight colours, at full saturation, and the product's semant ### Named Rules -**The Locked Eight Rule.** Eight colours exist. Adding a ninth hue, or desaturating one of the eight to make it sit more politely, is a regression rather than a variation. If a new state needs a colour, it takes one of the eight and inherits that colour's meaning. +**The Locked Eight Rule.** Eight colours exist. Adding a ninth hue, or desaturating one of the eight to make it sit more politely, is a regression rather than a variation. If a new state needs a colour, it takes one of the eight and inherits that colour's meaning. **One acknowledged exception:** `--tt-orange` in `base.css`, added for the fastext nav's eighth destination once the locked eight ran out of colours legible as text on black — a one-time, explained break, not a precedent for a second. **The Dither Rule.** A mid-tone is an ordered dither of two of the eight at cell scale — a checkerboard or a repeating gradient stepped at `--dither-size: 2px` or at `--bar-cell-w` — exactly how a 16-colour screen faked a gradient. It is never a ninth colour smuggled into the palette. The two derived greys are the sanctioned exception, and they derive from white by `color-mix`, not by hand. diff --git a/app.py b/app.py index 1ff1171..69f014c 100644 --- a/app.py +++ b/app.py @@ -1304,20 +1304,22 @@ def service_urls(): # Every destination, for the top of every page but the index, each -# with its own distinct treatment. Order matches nav_items. Six of the -# eight get a flat colour, text and swatch both: the four with a real -# keyboard shortcut (r/g/y/c), plus magenta for Requests (the same -# --pending magenta a request already shows once approved elsewhere — -# Requests IS "waiting on a human") and blue for Watch. Blue is ~2.4:1 -# contrast on black, well under the 4.5:1 every other body text here -# clears — a known, deliberate exception, not an oversight; it's set -# this way because coloured-icon-only for Watch read as unfinished -# next to six fully-coloured neighbours. Activity gets an ordered -# dither swatch instead of a flat colour, the one other legal way to -# get a distinct mark out of this palette without smuggling in a ninth -# hue. Settings alone keeps plain ink — deliberately, as the one page -# with no live status of its own, so it's the one that gets no colour -# rather than an arbitrary leftover. +# with its own distinct colour. Order matches nav_items. The four +# with a real keyboard shortcut (r/g/y/c) keep their original colours; +# Requests gets magenta (the same --pending magenta a request already +# shows once approved elsewhere — Requests IS "waiting on a human"); +# Watch gets blue, ~2.4:1 contrast on black versus the 4.5:1 every +# other body text here clears — a known, deliberate exception, kept +# anyway because a swatch-only accent read as unfinished next to six +# fully-coloured neighbours. That's every colour the locked eight +# palette has to give (black's invisible on black); Activity's colour, +# --tt-orange, is a genuine ninth on top of it — a dithered swatch +# alone read as unfinished, and dithering the word itself renders +# illegible, so it's a deliberate, acknowledged break from "eight +# colours, no ninth" rather than a fix that stays inside it. Settings +# alone keeps plain ink — deliberately, as the one page with no live +# status of its own, so it's the one that gets no colour rather than +# an arbitrary leftover. FULL_FASTEXT = [ ("k-red", "r", "100", "Index", "/"), ("k-blue", "", "101", "Watch", "/watch"), @@ -1325,7 +1327,7 @@ FULL_FASTEXT = [ ("k-yellow", "y", "103", "Discover", "/discover"), ("k-magenta", "", "104", "Requests", "/requests"), ("k-cyan", "c", "105", "System", "/system"), - ("k-dither", "", "106", "Activity", "/activity"), + ("k-orange", "", "106", "Activity", "/activity"), ("", "", "900", "Settings", "/settings"), ] diff --git a/static/css/base.css b/static/css/base.css index 634ca04..69780b8 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -61,6 +61,14 @@ --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 */ diff --git a/static/css/teletext.css b/static/css/teletext.css index 19def98..a8b6b4a 100644 --- a/static/css/teletext.css +++ b/static/css/teletext.css @@ -533,9 +533,7 @@ a.tt-row:focus-visible .tt-row-sub { color: var(--tt-black); } text-overflow: ellipsis; } /* The key's identity is carried by a cell at its head — the physical - coloured button on the remote. Solid for most; k-blue and k-dither - override its background below, since a flat swatch can't carry - every one of the eight destinations without repeating a colour. */ + coloured button on the remote. */ .fastext a > span, .fastext-here > span { min-width: 0; overflow: hidden; @@ -564,10 +562,9 @@ a.tt-row:focus-visible .tt-row-sub { color: var(--tt-black); } other body text in this app clears — but the word carries the colour like every other key here, at the visitor's request. */ .fastext .k-blue { color: var(--field); } -/* The one other legal way to get a distinct mark out of eight colours - without a ninth: an ordered dither, same mechanism as --dither-mid, - in place of a flat swatch. */ -.fastext .k-dither::before { background: var(--dither-mid); } +/* --tt-orange is a genuine ninth colour, not one of the locked eight — + see its definition in base.css for why the palette ran out here. */ +.fastext .k-orange { color: var(--tt-orange); } .fastext a:hover, .fastext a:focus-visible { background: currentColor; outline: none;