--- name: vidtheque description: The projection room — a dark, gold-on-black surface where mono means the machine said it, lime means the machine read it off the screen, and nothing moves unless the machine is working. scheme: dark-only colors: # ── the ground, deepest first. Names are v5's own, so CSS ports without translation. pitch: "#040405" void: "#08080a" console: "#0a0a0e" plate: "#0e0e12" plate2: "#141419" plate3: "#1a1a20" seam: "#242429" seam2: "#33333b" black: "#000000" over: "rgba(8,8,11,.92)" seam-over: "rgba(255,255,255,.07)" edge-in: "rgba(255,255,255,.06)" scrim: "rgb(0 0 0 / 0.66)" # ── the ink fg: "#f3f0ea" fg2: "#9d968c" fg3: "#6b665e" fg-max: "#ffffff" fg-over: "#c9c2b6" # cool on-image ink for receipt slugs over video frames — deliberately cooler # than fg-over: over thumbnails the cool cast reads as chrome, not content. slug-ink: "rgba(226,236,246,.66)" slug-ink-dim: "rgba(226,236,246,.45)" # ── the one accent: gold gold: "#e7b455" gold-hi: "#f6cd78" gold-ink: "#120c02" gold-6: "rgba(231,180,85,.06)" gold-12: "rgba(231,180,85,.12)" gold-24: "rgba(231,180,85,.24)" gold-44: "rgba(231,180,85,.44)" # ── the seen channel: reserved, semantic, never decoration (The Lime Rule) seen: "#c9f938" seen-ink: "#0a1400" seen-10: "rgba(201,249,56,.10)" seen-24: "rgba(201,249,56,.24)" seen-48: "rgba(201,249,56,.48)" # ── the state tones. Ink is a hex; ground and border are mixed from it. tone-ok: "#71d083" tone-ok-bg: "color-mix(in srgb, {colors.tone-ok} 10%, {colors.plate})" tone-ok-line: "color-mix(in srgb, {colors.tone-ok} 26%, {colors.plate})" tone-warn: "#ffa057" tone-warn-bg: "color-mix(in srgb, {colors.tone-warn} 10%, {colors.plate})" tone-warn-line: "color-mix(in srgb, {colors.tone-warn} 26%, {colors.plate})" tone-bad: "#ff9592" tone-bad-bg: "color-mix(in srgb, {colors.tone-bad} 10%, {colors.plate})" tone-bad-line: "color-mix(in srgb, {colors.tone-bad} 26%, {colors.plate})" tone-work: "#70b8ff" tone-work-bg: "color-mix(in srgb, {colors.tone-work} 10%, {colors.plate})" tone-work-line: "color-mix(in srgb, {colors.tone-work} 26%, {colors.plate})" tone-wait: "{colors.fg2}" tone-wait-bg: "color-mix(in srgb, {colors.fg2} 10%, {colors.plate})" tone-wait-line: "color-mix(in srgb, {colors.fg2} 26%, {colors.plate})" tone-neutral: "{colors.tone-wait}" tone-neutral-bg: "{colors.tone-wait-bg}" tone-neutral-line: "{colors.tone-wait-line}" # ── the six pinned role names. Aliases only: an alias never carries its own value. bg: "{colors.pitch}" muted: "{colors.fg2}" line: "{colors.seam}" accent: "{colors.gold}" raised: "{colors.plate}" panel: "{colors.plate2}" rule: "{colors.seam2}" mark: "{colors.fg3}" film: rest: "brightness(.52) saturate(.72) contrast(1.05)" dim: "brightness(.13) saturate(.2)" lit: "brightness(1.34) saturate(1.04) contrast(1.02)" band: "saturate(.78) brightness(.7)" full: "none" typography: brand: fontFamily: "Archivo VF, system-ui, -apple-system, sans-serif" fontSize: "16.5px" fontWeight: 500 lineHeight: 1.1 letterSpacing: "-0.035em" brand-lg: fontFamily: "{typography.brand.fontFamily}" fontSize: "clamp(2.2rem, 4.4vw, 4rem)" fontWeight: 250 lineHeight: 0.9 letterSpacing: "-0.045em" display: fontFamily: "{typography.brand.fontFamily}" fontSize: "clamp(2.7rem, 5.6vw, 5.6rem)" fontWeight: 200 lineHeight: 0.96 letterSpacing: "-0.04em" headline: fontFamily: "{typography.brand.fontFamily}" fontSize: "clamp(1.9rem, 3.5vw, 3.35rem)" fontWeight: 210 lineHeight: 1.0 letterSpacing: "-0.034em" question: fontFamily: "{typography.brand.fontFamily}" fontSize: "clamp(1.05rem, 1.6vw, 1.5rem)" fontWeight: 250 lineHeight: 1.26 letterSpacing: "-0.028em" quote: fontFamily: "{typography.brand.fontFamily}" fontSize: "clamp(1rem, 1.24vw, 1.24rem)" fontWeight: 330 lineHeight: 1.36 letterSpacing: "-0.022em" lede: fontFamily: "{typography.brand.fontFamily}" fontSize: "clamp(0.98rem, 1.12vw, 1.1rem)" fontWeight: 340 lineHeight: 1.62 letterSpacing: "-0.004em" body: fontFamily: "{typography.brand.fontFamily}" fontSize: "16px" fontWeight: 340 lineHeight: 1.55 letterSpacing: "-0.004em" prose: fontFamily: "{typography.brand.fontFamily}" fontSize: "15.5px" fontWeight: 340 lineHeight: 1.68 letterSpacing: "-0.004em" action: fontFamily: "{typography.brand.fontFamily}" fontSize: "15px" fontWeight: 600 lineHeight: 1.1 letterSpacing: "-0.012em" cell: fontFamily: "{typography.brand.fontFamily}" fontSize: "14px" fontWeight: 340 lineHeight: 1.4 letterSpacing: "-0.012em" cell-strong: fontFamily: "{typography.brand.fontFamily}" fontSize: "14px" fontWeight: 520 lineHeight: 1.4 letterSpacing: "-0.02em" machine: fontFamily: "JetBrains Mono VF, ui-monospace, SFMono-Regular, monospace" fontSize: "13px" fontWeight: 400 lineHeight: 1.4 letterSpacing: "-0.01em" fontFeature: "tabular-nums; ligatures none" query: fontFamily: "{typography.machine.fontFamily}" fontSize: "13.5px" fontWeight: 400 lineHeight: 1.2 letterSpacing: "normal" fontFeature: "ligatures none" log: fontFamily: "{typography.machine.fontFamily}" fontSize: "12.5px" fontWeight: 400 lineHeight: 1.85 letterSpacing: "normal" fontFeature: "tabular-nums; ligatures none" machine-sm: fontFamily: "{typography.machine.fontFamily}" fontSize: "11px" fontWeight: 400 lineHeight: 1.55 letterSpacing: "0.005em" fontFeature: "tabular-nums; ligatures none" label: fontFamily: "{typography.machine.fontFamily}" fontSize: "10px" fontWeight: 600 lineHeight: 1.4 letterSpacing: "0.19em" textTransform: "uppercase" fontFeature: "ligatures none" label-sm: fontFamily: "{typography.machine.fontFamily}" fontSize: "9.5px" fontWeight: 600 lineHeight: 1.4 letterSpacing: "0.17em" textTransform: "uppercase" fontFeature: "ligatures none" tag: fontFamily: "{typography.machine.fontFamily}" fontSize: "8.5px" fontWeight: 700 lineHeight: 1.1 letterSpacing: "0.14em" textTransform: "uppercase" fontFeature: "ligatures none" # the micro-slug tier, below tag: on-image receipt labels only (the wall's # per-tile id+timecode at 7.5px; the query state cell compresses to 7.6px at # bp-hand). Captured 2026-08-11 from the landing — the reference page these # tokens were derived from — after the graduation surfaced them as unnamed. wall-slug: fontFamily: "{typography.machine.fontFamily}" fontSize: "7.5px" fontWeight: 400 lineHeight: 1 letterSpacing: "0.04em" fontFeature: "ligatures none" slug-st-hand: fontFamily: "{typography.machine.fontFamily}" fontSize: "7.6px" fontWeight: 600 lineHeight: 1.4 letterSpacing: "0.13em" textTransform: "uppercase" fontFeature: "ligatures none" figure: fontFamily: "{typography.machine.fontFamily}" fontSize: "clamp(1.6rem, 2.5vw, 2.5rem)" fontWeight: 300 lineHeight: 1.0 letterSpacing: "-0.045em" fontFeature: "tabular-nums; ligatures none" weights: display: 200 display-2: 250 body: 340 strong: 500 action: 600 mono-label: 600 mono-tag: 700 rounded: none: "0" spacing: s1: "0.25rem" s2: "0.5rem" s3: "0.75rem" s4: "1rem" s5: "1.25rem" s6: "1.5rem" s8: "2rem" s10: "2.5rem" s12: "3rem" layout: maxw: "1760px" gut: "clamp(20px, 4.2vw, 72px)" beat: "clamp(64px, 7.4vw, 124px)" gap-block: "clamp(34px, 4vw, 58px)" gap-head: "clamp(22px, 2.4vw, 34px)" gap-copy: "clamp(16px, 1.9vw, 26px)" prose: "70ch" lede: "60ch" quote: "58ch" note: "74ch" query-w: "72rem" console-w: "92rem" console-read: "60rem" bp-stack: "1120px" bp-hand: "780px" elevation: drop: "0 40px 90px -24px rgba(0,0,0,.94)" drop-sm: "0 22px 50px -18px rgba(0,0,0,.9)" edge: "inset 0 0 0 1px {colors.edge-in}" edge-hit: "inset 0 0 0 2px {colors.gold}" motion: ease-lift: "cubic-bezier(.22,.72,.2,1)" ease-acquire: "cubic-bezier(.16,1,.3,1)" t-fast: "0.16s" t-state: "0.25s" t-film: "0.5s" t-veil: "0.55s" t-lift: "0.82s" t-acquire: "0.45s" blink: "1.05s steps(1,end) infinite" drift-gate: "150s ease-in-out infinite alternate" drift-band: "900s linear infinite" components: wordmark: textColor: "{colors.fg}" typography: "{typography.brand}" accentGlyph: "{colors.gold}" wordmark-lg: textColor: "{colors.fg}" typography: "{typography.brand-lg}" accentGlyph: "{colors.gold}" kicker: textColor: "{colors.gold}" typography: "{typography.label}" rule: "34px x 1px {colors.gold}, 12px gap" micro-label: textColor: "{colors.fg2}" typography: "{typography.label}" button-primary: backgroundColor: "{colors.gold}" textColor: "{colors.gold-ink}" borderColor: "{colors.gold}" rounded: "{rounded.none}" padding: "14px 20px 14px 22px" typography: "{typography.action}" button-primary-hover: backgroundColor: "{colors.gold-hi}" button-ghost: backgroundColor: "transparent" textColor: "{colors.fg2}" borderColor: "{colors.seam2}" rounded: "{rounded.none}" padding: "0 12px" height: "2.125rem" typography: "{typography.label}" button-ghost-hover: textColor: "{colors.gold}" borderColor: "{colors.gold-44}" chip: backgroundColor: "transparent" textColor: "{colors.fg3}" borderColor: "{colors.seam}" rounded: "{rounded.none}" padding: "0 12px" height: "2.75rem" typography: "{typography.label-sm}" chip-hover: textColor: "{colors.fg}" chip-on: backgroundColor: "{colors.gold-12}" textColor: "{colors.gold}" input-text: backgroundColor: "{colors.console}" textColor: "{colors.fg}" borderColor: "{colors.seam2}" rounded: "{rounded.none}" padding: "0 13px" height: "2.75rem" typography: "{typography.query}" picker: backgroundColor: "{colors.console}" textColor: "{colors.fg}" borderColor: "{colors.seam2}" rounded: "{rounded.none}" padding: "0 24px 0 13px" height: "2.125rem" typography: "{typography.query}" appearance: "none — the platform draws none of it" mark: "6px square, right + bottom 1px {colors.fg2}, rotated 45deg, 12px from the right edge" markHover: "{colors.gold}" hint: backgroundColor: "{colors.plate}" textColor: "{colors.fg2}" borderColor: "{colors.seam2}" rounded: "{rounded.none}" padding: "8px 12px" maxWidth: "24rem" shadow: "none — it is one plate above the page, not lifted off the wall" typography: "{typography.machine-sm}" input-textarea: backgroundColor: "{colors.console}" textColor: "{colors.fg}" borderColor: "{colors.seam2}" rounded: "{rounded.none}" padding: "0.75rem" minHeight: "8.5rem" typography: "{typography.machine}" query-bar: backgroundColor: "{colors.over}" borderColor: "{colors.seam2}" height: "52px" shadow: "{elevation.drop-sm}" typography: "{typography.query}" query-caret: backgroundColor: "{colors.gold}" width: "8px" height: "17px" animation: "{motion.blink}" status-cell: backgroundColor: "{colors.console}" textColor: "{colors.fg3}" borderColor: "{colors.seam}" padding: "0 14px" typography: "{typography.tag}" status-cell-active: backgroundColor: "{colors.gold}" textColor: "{colors.gold-ink}" panel: backgroundColor: "{colors.plate}" borderColor: "{colors.seam2}" rounded: "{rounded.none}" cornerTick: "12px x 1px + 1px x 12px {colors.gold} at the top-left corner" panel-lifted: backgroundColor: "{colors.plate}" borderColor: "{colors.seam2}" shadow: "{elevation.drop}" panel-head: backgroundColor: "{colors.plate2}" borderColor: "{colors.seam}" padding: "9px 14px" minHeight: "32px" typography: "{typography.label}" panel-foot: backgroundColor: "{colors.plate2}" borderColor: "{colors.seam}" padding: "11px 16px" typography: "{typography.label}" panel-note: textColor: "{colors.gold}" typography: "{typography.machine-sm}" prefix: "note: in {colors.fg3}" frame: backgroundColor: "{colors.black}" aspectRatio: "16/9" rounded: "{rounded.none}" shadow: "{elevation.edge}" det-box: borderColor: "{colors.seen-24}" borderWidth: "1px" rounded: "{rounded.none}" det-box-on: borderColor: "{colors.seen}" borderWidth: "1.5px" det-tag: backgroundColor: "{colors.seen}" textColor: "{colors.seen-ink}" padding: "2.5px 6px" typography: "{typography.tag}" receipt: backgroundColor: "{colors.gold-6}" textColor: "{colors.gold}" borderColor: "{colors.gold}" rounded: "{rounded.none}" padding: "9px 0 9px 11px" typography: "{typography.machine}" fontWeight: 600 receipt-action: backgroundColor: "{colors.gold}" textColor: "{colors.gold-ink}" padding: "9px 11px" fontWeight: 700 receipt-hover: backgroundColor: "{colors.gold-12}" quote-block: textColor: "{colors.fg}" borderLeft: "1px solid {colors.gold}" padding: "0 0 0 14px" typography: "{typography.quote}" maxWidth: "{layout.quote}" ledger: backgroundColor: "{colors.plate}" borderColor: "{colors.seam2}" dividerColor: "{colors.seam}" padding: "20px 22px 22px" ledger-label: textColor: "{colors.fg2}" typography: "{typography.label-sm}" ledger-figure: textColor: "{colors.fg}" typography: "{typography.figure}" unitColor: "{colors.gold}" log: backgroundColor: "{colors.console}" textColor: "{colors.fg2}" borderColor: "{colors.seam2}" padding: "clamp(22px,2.4vw,36px) clamp(18px,2.4vw,36px)" typography: "{typography.log}" log-call: textColor: "{colors.fg}" keyColor: "{colors.gold}" argColor: "{colors.fg2}" typography: "{typography.log}" wall-tile: backgroundColor: "{colors.black}" filter: "{film.band}" shadow: "{elevation.edge}" wall-tile-slug: backgroundColor: "rgba(3,5,8,.72)" textColor: "{colors.fg2}" padding: "2.5px 5px 3px" typography: "{typography.tag}" wall-tile-hit: filter: "{film.lit}" shadow: "{elevation.edge-hit}" pill: backgroundColor: "{colors.tone-neutral-bg}" textColor: "{colors.tone-neutral}" borderColor: "{colors.tone-neutral-line}" rounded: "{rounded.none}" padding: "1px 0.5rem" typography: "{typography.label-sm}" table-head: backgroundColor: "{colors.plate2}" textColor: "{colors.fg2}" borderColor: "{colors.seam2}" typography: "{typography.label}" padding: "0.5rem" table-head-sorted: textColor: "{colors.fg}" borderColor: "{colors.gold}" table-row: backgroundColor: "transparent" textColor: "{colors.fg}" borderColor: "{colors.seam}" typography: "{typography.cell}" padding: "0.5rem" height: "2.125rem" table-row-hover: backgroundColor: "{colors.plate}" shadow: "inset 1px 0 0 {colors.gold}" nav-rail: backgroundColor: "{colors.void}" borderColor: "{colors.seam}" width: "15rem" nav-group: textColor: "{colors.fg3}" typography: "{typography.label}" padding: "0.75rem 1rem 0.25rem" nav-link: backgroundColor: "transparent" textColor: "{colors.fg2}" typography: "{typography.cell}" padding: "0.5rem 1rem" height: "2.125rem" nav-link-hover: backgroundColor: "{colors.plate}" textColor: "{colors.fg}" nav-link-active: backgroundColor: "{colors.pitch}" textColor: "{colors.gold}" shadow: "inset 2px 0 0 {colors.gold}" field-help: textColor: "{colors.fg2}" typography: "{typography.machine-sm}" empty-lead: textColor: "{colors.fg}" typography: "{typography.cell-strong}" empty-note: textColor: "{colors.fg2}" typography: "{typography.cell}" next-affordance: backgroundColor: "transparent" textColor: "{colors.gold}" borderColor: "{colors.gold-44}" borderStyle: "1px dashed, offset -4px" typography: "{typography.label}" next-affordance-hover: backgroundColor: "{colors.gold-6}" focus-ring: outline: "2px solid {colors.gold}" outlineOffset: "2px" selection: backgroundColor: "{colors.gold}" textColor: "{colors.gold-ink}" --- # Design System: vidtheque — the projection room Normative for every **product** web surface: the landing page at `/`, the public demo at `/demo`, and the dashboard at `/dashboard`. One world, three densities. This file does **not** override `docs/design/demo-site.md` or `docs/design/dashboard.md` on function, data, clamps or copy, and it does not override `docs/design/positioning.md` on voice. It owns how the surfaces look, and nothing else. **Reference implementation:** `web/src/app/(public)/page.tsx`, its components under `web/src/components/public/landing/`, its data under `web/src/components/public/landing/data/` and its stills under `web/public/landing/` ("projection room"). Tom picked it on 2026-08-10 as the product's visual identity; it graduated out of `lab/versions/v5.html` to the served landing on 2026-08-11 (demo-site.md §6.1) and left the Python package for the Next.js front end on 2026-09-05 — the same page each time. Every token below was read out of v5 as shipped; where a value is an extension rather than a readout it says so in the prose. When this file and the landing disagree, **this file wins**; but say why in the amending commit, because that page is the thing Tom actually approved. *Amended 2026-10-04 (Tom, #196):* the landing keeps the projection room's wall, faces and tokens and drops its light table, stills, wall band and booth log; it now leads with the positioning sentence and three live recommendations (demo-site.md §8.4). The wall's frames stay under `web/public/landing/grid/`. **The amendment rule.** The frontmatter tokens above are normative. Any agent may **use** any token and may **add** a `components:` entry for a component it is the first to build. No agent may introduce a raw colour, a font size outside the ladder, a font weight off the weight ladder, a non-zero border radius, or a layout spacing value off the 4px grid. If a page genuinely needs a new primitive, the agent edits this file **in the same commit** as the CSS and says why — the same discipline `CLAUDE.md` already requires when an implementation diverges from a design contract. Write `var(--token)`, never a hex. The system is **dark only**: there is one scheme, `color-scheme: dark` is declared, and there is no light palette, no `prefers-color-scheme` block and no toggle. A projection room does not have a day mode. **What happened to the warm-paper system.** Removed, 2026-08-10, on Tom's order. The previous contract — Radix `sand`/`amber` on paper `#fbfaf9`, Inter + Instrument Serif, 3/5/8px radii, light and dark as peers — is replaced in full by the palette, faces and rules below. Git history keeps it (`git show HEAD~1:DESIGN.md`); nothing here is a deprecated appendix, because a dead palette left in the contract is a palette somebody uses. Three ideas survived the change and are re-stated below in their new clothes: the Two-Channel Rule, the Word-and-Colour Rule and the One Signal Rule. ## Overview **Creative North Star: "the projection room."** The room is dark because the corpus is footage and the only lit things in a projection room are the ones being looked at. The page ground is near-black, the frames are the light, and one gold accent marks the moment you are pointing at — the receipt, the CTA, the found frame. A second hue exists and is spent on exactly one meaning: lime is what the machine **read off the screen**. The derivation is the product's own machinery — the gate, the light table, the wall of watched frames, the booth log — and it shows up as behaviour, not as decoration: the wall drifts because the projector is running, the query types itself because the agent is querying, the frame lifts off the wall onto the table because that is what "found it" looks like. It must never show up as film sprockets, clapperboards, faux-CRT, scan lines or a glow. **Key characteristics:** - Two faces, one meaning each: Archivo for human text, JetBrains Mono for machine text. No third face — the wordmark is the sans, not a serif. - Gold on black, one accent; lime reserved for on-screen-text evidence. - **Zero radius everywhere.** `*{border-radius:0}` is in the reset. - Hairlines and plates, not cards. A shadow means *lifted off the wall*. - Every state is a word as well as a colour. - Movement only where the machine is working; everything freezes under `prefers-reduced-motion`. - Zero layout shift: every image has explicit dimensions or a fixed-aspect box. ## Colors ### The ground Six plates and two seams, deepest first. They are a depth scale, not a set of options: a thing sits one plate above what contains it, and no further. - **Pitch** (`--pitch` #040405) — the page ground. - **Void** (`--void` #08080a) — a section band and the footer; the one step off the page ground that separates a beat without a rule. - **Console** (`--console` #0a0a0e) — the ground of a log, a terminal, a query field: a surface the machine writes into. - **Plate** (`--plate` #0e0e12) — a real box's ground (a panel, the ledger, a copy box). - **Plate 2** (`--plate2` #141419) — the head or foot band *inside* a box. - **Plate 3** (`--plate3` #1a1a20) — the topmost plate; swatches and inert fills. Nothing sits above it. - **Seam** (`--seam` #242429) — the hairline. Every rule and border that separates without announcing. - **Seam 2** (`--seam2` #33333b) — the edge of a real box, one step louder. - **Black** (`--black` #000) — the ground *behind a frame*. Image boxes only, so a still that has not decoded yet leaves black rather than a coloured plate. Three values exist for chrome that floats over imagery, where a plate would read as a hole: `--over` (a control's ground), `--seam-over` (a rule), and `--edge-in` (the 1px inset hairline that keeps an image from bleeding into the page). `--scrim` is the modal `::backdrop` and is deliberately a literal black alpha — a scrim has to darken whatever is behind it. ### The ink - **Fg** (`--fg` #f3f0ea) — body text. 18.02:1 on `--pitch`, 16.94:1 on `--plate`. - **Fg2** (`--fg2` / `--muted` #9d968c) — secondary prose, ledes, notes, labels that carry a fact. 7.00:1 on `--pitch`, 6.58:1 on `--plate`. - **Fg3** (`--fg3` / `--mark` #6b665e) — **3.60:1 on `--pitch`, 3.38:1 on `--plate`.** Over the 3:1 non-text floor, under the 4.5:1 text floor. It is therefore *atmosphere*: the landing may set decorative micro-labels and non-load-bearing captions in it, and **no label that is the only carrier of a fact may use it on any surface**. On the demo and the dashboard, label ink is `--fg2`. This is the one measured exception in the system; if you find you need a second, measure it and write it here. - **Fg-max** (`--fg-max` #fff) — the display headline only. Pure white is the top of the ladder and it is spent on one element per page. - **Fg-over** (`--fg-over` #c9c2b6) — body set over imagery, with the text shadow the hero uses. Not for use on a plate. ### Gold — the one accent **Gold** (`--gold` #e7b455, 10.79:1 on `--pitch`, 10.14:1 on `--plate`) means exactly one thing: *this is the moment you are pointing at*. The receipt slab, the CTA, the focus ring, the found tile's outline, one word of the H1, the active nav item, the timecode worth clicking, the ledger's unit. If everything is gold, nothing is. `--gold-hi` (#f6cd78) is the hover step of a gold fill. `--gold-ink` (#120c02, 10.25:1 on gold) is the text on it — never `--pitch` and never black. The alpha ladder (`--gold-6` / `-12` / `-24` / `-44`) is the accent as a *ground*: a wash under a receipt, an active chip, a landing pad, a dashed "next" outline. ### Lime — the seen channel **Seen** (`--seen` #c9f938, 15.68:1 on `--plate`) with `--seen-ink` (#0a1400, 15.36:1 on it) and the alpha ladder `--seen-10` / `-24` / `-48`. ### The state tones Five tones, each with three tokens: `--tone-X` is the ink, `--tone-X-bg` its ground, `--tone-X-line` its border. Ground and border are **mixed from the ink** — `color-mix(in srgb, var(--tone-X) 10%, var(--plate))` and the same at 26% — which is the pattern the gold and seen alpha ladders already use, so a tone needs one hex and not three. - **Grass** (`--tone-ok` #71d083): done, ready, present, allowed. 10.14:1 on `--plate`, 8.67:1 on its own ground. - **Orange** (`--tone-warn` #ffa057): deferred, cancel requested, held. 9.56:1 / 8.19:1. **This is the one hand-held colour in the system and the one place the palette is extended rather than read out of v5**, which has no state tones: the obvious pick, the vendored dark `amber-11` #ffca16, sits 7° of hue from `--gold` and would read as the accent, which the One Signal Rule forbids. - **Signal Red** (`--tone-bad` #ff9592): failed, refused, drifted, degraded. 9.14:1 / 7.86:1. The dark `red-11` the dashboard's stylesheet vendored. - **Instrument Blue** (`--tone-work` #70b8ff): running, indexing, mid-pipeline. 9.16:1 / 7.88:1. The dark `blue-11` already vendored. - **Fg2** (`--tone-wait` / `--tone-neutral`): queued, skipped, absent, unrecognised. It is `--fg2` itself — a waiting state is the absence of a colour, not a fifth one. Provenance, so nobody re-derives it: ok / bad / work are the dark Radix steps `dashboard/static/dashboard.css` vendored (`grass-11`, `red-11`, `blue-11`), carried over unchanged because they were measured for a dark ground and this ground is darker still. warn is new and hand-held. wait is ours. *That file was deleted with the dashboard's pages on 2026-09-06; the three steps live in `web/src/styles/tokens.css` now, and the names are kept here because they are what a reader greps Radix for.* ### The film filters The four looks a still can have are tokens, because "how bright is the wall" is a system decision and not a per-page one: `--film-rest` (the wall at rest, the projector idling), `--film-dim` (the wall while a query is running — everything that is not the answer), `--film-lit` (the found frame, lit *past* the scrim, not merely back to normal), `--film-band` (a still in an evidence wall you can read ids off). Full brightness (`none`) is the hover of a band tile and the resting state of a frame on the light table: a frame you are being shown is never dimmed. ### Named Rules **The Lime Rule** (hard, like the Two-Channel Rule). `--seen` and its alpha ladder mark exactly one thing: **evidence the machine read off the screen** — an OCR detection box, its tag, an on-screen-text line, the legend swatch that names those, and the `seen` label of the on-screen-text channel. It is never a second accent, never a highlight, never a hover, never a link, never a chart series, never a "success" green, never a decoration, and never the ground of anything larger than a detection box. If lime appears on a surface with no on-screen-text evidence on it, that is a bug — delete it, do not re-tint it. The whole point is that a viewer learns in one screen that lime = *the machine read this off the slide*, which is the product's single hardest claim to make in a picture. v3 leaked lime onto a rail dot and a video id; v4 fixed it; the fix is now the contract. **The One Signal Rule.** `--accent` (gold) means *this is the moment you are pointing at*. See above. Gold and lime never touch the same object: gold is what you asked for, lime is what the machine saw. **The Word-and-Colour Rule.** Every state prints its own word. Colour is reinforcement, never the message. A state you can only read by seeing hue is a bug, and the four state vocabularies in this product are deliberately not unified — no surface may invent a fifth. **The Plate Rule.** A thing sits exactly one plate above what contains it: `--pitch` page → `--plate` box → `--plate2` band inside the box. Three plates of nesting is a card in a card and the answer is a hairline. ## Typography **Text / display face:** Archivo VF (variable, `wght` 100–900), with `system-ui` as fallback. **Machine face:** JetBrains Mono VF (variable, `wght` 100–800), with `ui-monospace` as fallback. **There is no third face.** The serif is gone: the wordmark is set in Archivo (see **The Font-Logo Rule**), so `--font-display` no longer exists as a distinct family and Instrument Serif is retired from the product surfaces. Both faces are vendored, latin subset, SIL OFL 1.1 — see **Fonts** below. **Character.** Archivo is a grotesque with a wide weight axis that stays sturdy at 200 across a 90px headline, which is what makes the display voice possible without a second family. JetBrains Mono is chosen for one measurable property: it draws `0`/`O` and `1`/`l`/`I` apart, which stops being cosmetic when the machine strings on these surfaces include YouTube ids like `kCc8FmEb1nY`. ### The ladder Sans, largest first: **display** (200) → **headline** (210) → **question** (250) → **quote** (330) → **lede** (340) → **body** (340, 16px; 15px below `--bp-hand`) → **prose** (340, 15.5px) → **action** (600, 15px) → **cell** / **cell-strong** (340 / 520, 14px). Mono: **query** (13.5px) → **machine** (13px) → **log** (12.5px) → **machine-sm** (11px) → **label** (10px, 0.19em, uppercase) → **label-sm** (9.5px, 0.17em) → **tag** (8.5px, 0.14em) → **figure** (300, clamp to 2.5rem, tabular). **The weight law.** Five sans rungs and no sixth: **200** display, **250** secondary display, **340** body, **500** strong, **600** action. Mono has three: **400** text, **600** label, **700** tag. A variable face makes optical adjustment free, so a value **within ±20 of a rung** is an optical tweak and needs no amendment — that is what v5's 210 on the h2, 330 on the pulled quote and 520/560 inside a line are. Anything further from a rung is a new primitive and gets written here. **The size floor.** 8.5px `tag` and 9.5px `label-sm` exist for marks drawn **on top of an image** and for a ledger's column name — strings of two or three tracked words that the reader is not asked to parse in sequence. Running text never goes below `machine-sm` (11px), and on the dashboard the smallest text that carries a fact is `label` (10px) in `--fg2`. ### Named Rules **The Two-Channel Rule** (unchanged, and it is still the system). Mono means the machine said it; sans means a human wrote it. Every timecode, duration, id, `model_key`, `error_code`, count, clock, confidence, byte figure, query string and tool call is mono and tabular. Every title, channel name, description, sentence and label a human wrote is Archivo. The eye learns this in ten seconds and then the page reads itself. Note the one thing that changed shape: micro-labels (`label`, `label-sm`, `tag`) are **mono**, because a column name, a channel name like `SEEN`, and a status word like `SCANNING` are the machine's own vocabulary. Sentence-length human text is never uppercased and never tracked. **The Font-Logo Rule** (replaces the Wordmark-Only Rule, 2026-08-10). The wordmark is set in the text face; there is no separate brand family and no drawn mark in the lockup. See **The logo** below. Because the identity is now carried by the *word*, the old fence — "exactly two selectors may name `--font-display`" — is retired with the serif it fenced. **The Dead-Feature Rule.** Do not set `font-feature-settings` for stylistic sets you have not opened the file to confirm. `tabular-nums` (`tnum`) is the one that matters and both vendored faces carry it. Every mono context sets `font-variant-ligatures: none`, because JetBrains Mono ships `calt` and the literal characters of an id are the information. ## The logo The logo is **the word, and nothing else**: `vidtheque` in lower case, in the text face, with the full stop in gold. The period is the receipt's full stop — the product's whole argument is that an answer ends in a citation, and the mark ends in a dot. It is one string, so it is a `` with an `` around the period, not an image and not an SVG. The two sizes in the system, both read out of v5 as shipped: | slot | face | weight | size | tracking | line-height | |---|---|---|---|---|---| | **rail / masthead** (`.mark b`) | Archivo VF | **500** | **16.5px** (15px below `--bp-hand`) | **−0.035em** | 1.1 | | **footer signature** (`.fmark b`) | Archivo VF | **250** | **clamp(2.2rem, 4.4vw, 4rem)** | **−0.045em** | **0.9** | The period is `--gold`, `font-style: normal` on the ``, and it inherits everything else. The lockup is `display:flex; align-items:baseline; gap:12px` — the gap is for what sits *beside* the word (a corpus count, a state), never for a drawing. **The refinement, so it is not re-relitigated.** v4 shipped the rail mark at **460 / 17.5px / −0.028em** with the note "the font logo: the period is the receipt's full stop". v5 tightened it to **500 / 16.5px / −0.035em**: heavier so the word holds its own against a lit wall behind it, smaller and tighter so it reads as a mark rather than as a heading. **v5's numbers are the contract.** The footer signature is unchanged between v4 and v5 and is the one place the word is allowed to be large — a signature, at the end, after the argument. The favicon is **the v.** (Tom's pick, 2026-08-11): the wordmark's `v` with its gold full stop, floating on a transparent ground — gold core, a 1-unit `--gold-ink` keyline so the same bytes read on light and dark tab strips (the keyline melts into dark chrome, and becomes the silhouette on white). It is the word abbreviated, not a drawing beside it, so the tab and the rail lockup say the same thing. It is a favicon and not a brandmark: it never appears inside a page beside the word. The drawn film frame it replaced lives in git history. ## Motion — the law **Movement only where the machine is working.** (Tom, locked 2026-08-10.) Motion on these surfaces is an honest signal that something is running; it is never atmosphere. If you cannot name the machine work a moving thing is reporting, it does not move. **Sanctioned motion, and what each one reports:** | motion | what it means | token | |---|---|---| | the projector gate's slow drift on a wall of stills | the projector is running / the corpus is being watched | `--drift-gate` (150s, alternate) | | an evidence wall tracking sideways at a constant few px/s | this corpus was watched, and there is more of it than fits | `--drift-band` (900s linear) | | a query typing itself, with a caret that blinks **only while typing** | the agent is asking | `--blink` | | the wall dimming and one tile lighting | the search ran and this is the hit | `--t-film`, `--t-state` | | a frame lifting off the wall onto the light table | found it — this frame is the evidence | `--t-lift`, `--ease-lift` | | detection boxes acquiring, staggered | the machine is reading the screen | `--t-acquire`, `--ease-acquire` | | a counter ticking up | counts are counts | — | | a panel un-veiling as its data arrives | the answer landed | `--t-veil` | | a light passing through the text of **the one step in flight**, on one line that each new step replaces, each line held long enough to be read | the model is running that step, or deciding the next | `--t-state`, `--ease-lift`; a step holds 2s, "Thinking" 0.6s | | a panel following its content's height | the machine's answer is taking the room it needs | `--t-state` | **Banned outright, with no exception and no "but it's subtle":** - pulsing or breathing dots, badges or rings; - scan lines, CRT flicker, film grain, vignettes that move; - ambient glow, halos, glimmer, shimmer, aurora, gradient animation — *ambient* is the word: the one sanctioned light sits on the single row that names work in flight and stops the moment that work does (Tom, 2026-09-19). On a heading, a finished row, a card or a background it is still banned; - decorative hover motion — no lift, no scale, no translate, no wiggle, no parallax, no tilt, on anything, ever; - entrance animation on scroll (fade-up, stagger-in) for content that is simply there; - spinners as decoration. A spinner is allowed only while a real request is in flight, and it is replaced by the word for the state as soon as one is known. **Hover may change colour, not geometry.** A hovered control may move its ground, ink, border or image filter, at `--t-fast`. It may not move, scale or shadow-lift. `--film-band` → `none` on a wall tile is the sanctioned example: pointing at a still un-dims it, and nothing shifts. **Everything freezes under `prefers-reduced-motion: reduce`,** and freezing means **painting the end state**, never dropping the content: drifts stop, carets stop blinking, transitions go to `none`, veiled things are simply visible, `scroll-behavior` goes to `auto`. A surface that hides information when motion is reduced has failed the rule twice. The lab's `?still=1` switch does the same thing for screenshots; a product surface with a demo animation must offer the same escape. ## Layout, shape and depth **Chassis.** A page is a stack of **beats**: full-bleed bands on `--void` or `--pitch`, separated by a `--seam` hairline, each padded `--beat` vertically, with their content in a `--maxw` (1460px) column at `--gut` gutters. Inside a beat: `--gap-head` under a heading block, `--gap-block` before a major object, `--gap-copy` between the lines of a copy stack. **Measures.** Prose is capped and grids are not: `--prose` 70ch for running text, `--lede` 60ch for a lede (46ch when it is set over imagery), `--quote` 58ch for a pulled sentence, `--note` 74ch for a machine note. **Spacing.** Layout spacing — gaps, tracks, section rhythm — is on the 4px grid (`--s1` 4px … `--s12` 48px) or one of the fluid clamps above. **Component padding is optical** and lives in the component's own entry (a 52px query bar is `0 13px`, a panel head is `9px 14px`): those are read out of v5 and are not required to land on the grid, but a *new* component's padding is a new primitive and gets written here. **Breakpoints**, and what each one is for: - **`--bp-stack` 1120px** — two-column hero and split zones become one column; side-by-side plates stack with the still above its text. - **`--bp-hand` 780px** — body drops to 15px, the wordmark to 15px, chrome tightens, wall tiles shrink, on-image tags (`typography.tag`) are dropped rather than shrunk, and multi-column grids go to one column. A surface may add **one** breakpoint of its own for a real structural change (the dashboard's tables stop being tables somewhere around 52rem) and documents it in its own section here. It may not add a third for taste. Registered surface breakpoints: - **Demo: `--bp-wide` 1380px** (2026-08-11, commit 334f1f7) — the ask pane goes two-column: answer at its 70ch measure left, Sources right, a hairline column rule between. Below it the pane is one column at the measure. The structural change is real (the pane owns the full `--maxw` column above the break); the measure itself never widens. **The page body never scrolls horizontally at any width.** A grid too wide to stack scrolls inside its own wrapper, which is `position: relative` so an absolutely-positioned child cannot escape the clip. Every slot that prints a corpus string — a title, an error, an id — carries `overflow-wrap: anywhere` (`anywhere`, not `break-word`: only `anywhere` also reports a zero min-content width, which is what stops a flex or grid parent being *widened* by an 80-character token). **Shape: there is no radius.** The reset is `*{border-radius:0}` and a rounded corner anywhere is a bug. Nothing is a circle. This is not a style preference — a frame has square corners, and every box on these surfaces is either a frame, a plate, or a rule. **Borders.** 1px `--seam` is the hairline that separates; 1px `--seam2` is the edge of a real box. 2px exists in exactly two places and both are gold: the found tile's inset outline and the focus ring. A dashed 1px `--gold-44` at `-4px` offset is the one honest-about-being-next affordance (a roadmap slot); dashed means nothing else. **Depth: a shadow means lifted off the wall.** Four things in v5 cast one and all four are objects that have been taken *out* of the room and put in front of you: the light table, a frame in flight, the booth log, the query bar. `--drop` is that gesture; `--drop-sm` is its smaller sibling for a control. Everything else — panels, ledgers, table rows, nav, pills, chips — has **no shadow at all** and is separated by plate and hairline. `--edge` (a 1px inset white hairline) is not elevation; it is the glass in front of a still. The signature detail on a panel is the **corner tick**: a 12×1px and a 1×12px gold rule meeting at the top-left corner, drawn with `::before`/`::after`. It is the mark of a plate on a light table, it costs no box, and it is the system's one ornament. One per panel; never on all four corners. ## Per-surface guidance The same world at three densities. Function, data and copy still come from `docs/design/*.md`; this section is about how much of the world each surface spends. ### The landing page — the maximal expression **The Next front end's landing is the reference** (`web/src/app/(public)/page.tsx`, v5 as it graduated). Full-bleed imagery, the display ladder at its top rungs, the drifting wall, the lift, the light table, the evidence wall, the booth log. This is the only surface where a beat may exist purely to make an argument, and the only one that may spend a whole viewport on one idea. Motion inventory as v5 ships it; nothing is added to it without Tom. ### The demo page — the same world, selling, functional-first The demo is the landing's continuation, not a second product and not a stripped-down clone. It keeps the ground, the gold, the lime, the faces, the zero radius, the wordmark, the receipt slab, the frame-and-detection treatment and the motion law — a visitor arriving from the landing must not feel a seam. What changes is the ratio: **the demo's job is to be used.** The search input, the results, the receipts and the frames are the page; imagery serves a result rather than a mood. So: - The hero is at most one screen and it contains the working input. No beat exists that a visitor cannot act on. - The display ladder is used one rung down from the landing: `headline` for the page's one big line, not `display` at 5.6rem. - Motion is only the motion that reports *this visitor's* query running — typing, dimming, lifting, acquiring, counting. The ambient gate drift is a landing move; on the demo, an idle wall is idle. - Every result carries its receipt (`youtu.be/ID?t=`), every OCR line carries its lime box, every machine string is mono. The demo's whole persuasion is that the receipts are real. - `docs/design/demo-site.md` wins on function, data, clamps and copy — including token discipline: caps, `has_more`, and server-side clamps are not design decisions. ### The dashboard — the minimalist end of the same system A true minimalist, informative control surface. Same world, no spectacle: the operator is scanning sixty rows at 03:00 over an SSH tunnel. - **Density first.** 34px table rows, 14px cells, 8px padding, hairline separation, sticky heads on `--plate2`. Information per screen is the metric. - **The tones do the talking.** This is the surface the five state tones exist for. Every state is a word in its tone; the pill is the primitive. - **Gold stays scarce.** The active nav item, the focus ring, the sorted column's underline, the timecode worth clicking, the hovered row's 1px inset edge. Nothing else. - **Lime only where there is on-screen-text evidence** — the OCR overlay and its line list on video detail. On every other dashboard page there is no lime at all. (The Lime Rule.) - **No imagery as decoration.** Keyframes appear because they are the data. There is no hero, no wall, no drift, no lift, no scrim. The dashboard's only motion is a live countdown ticking and a real request in flight. - **No display type.** The ladder starts at `headline` for a page title and drops immediately to `label`/`cell`/`machine`. The wordmark appears twice — rail and footer — and is the only brand gesture on the surface. - **No shadow at all**, corner ticks used at most once per page (the signature panel), and no card ever. - **Quiet when fine, loud when not** (Tom, 2026-10-04, #182). A zero count is not printed. A section with nothing to act on says so in one line (`AllClear`, a 7px `--tone-ok` square before the sentence). A problem is a toned `Notice` at the top of the page: a `--tone-*-bg` band inside a 1px `--tone-*-line` border, its title in the tone, its detail in `--fg`. - **Human labels.** Panel headings, table heads and figure labels are sans, sentence case, at 13–15px. Mono is for ids, hashes, model names and aligned numbers; a key that reads like an identifier is a bug. The `t-label` caps stay on the pills and controls. - **A reading width.** `Page` lays a page's body on a centred `--console-read` (60rem) column; only `Wide` blocks, a table that needs the room, use the whole main area. The page head has no rule under it, so the first panel's hairline is the page's first rule. - **Statistics on demand.** Counts and breakdowns that act on nothing sit behind `Fold`, a text toggle with a drawn chevron, closed by default. - `docs/design/dashboard.md` wins on function, data, clamps and copy. ### The Android app — Material 3 Expressive (Tom, 2026-10-03) The app (`android/`, companion.md §6) is **not** the projection room. Tom picked Material 3 Expressive over a port of this system because it should feel native next to the phone's other apps. So on Android only, these rules give way to Material's: radius (Expressive shapes), motion (the expressive motion scheme's springs), the type ladder (Material's type scale in Roboto Flex) and the Two-Channel Rule (**no JetBrains Mono anywhere in the app**). What carries over: gold `#E7B455` as primary, on a tonal scheme seeded from it (`ui/theme/Theme.kt`); the wordmark in Archivo 500 with its gold full stop; the Word-and-Colour Rule (a score always prints its word); the Lime Rule. A dial (Material's circular progress indicator) shows a value the reader acts on, the verdict score and a profile weight, and appears nowhere as decoration. *Amended 2026-10-03 (Tom's first use):* the app follows the phone's light or dark mode instead of being dark only, since the colours Tom asked for (green and red profile matches) have to read in both. The light scheme takes the same palettes at Material's light tones, so gold drops to tone 40 as primary. The match colours are the one addition to Material's roles: a green tonal pair for "more of this" and the scheme's error container for "less of this". ## Fonts — one canonical location The two faces are vendored `.woff2`, latin subset, SIL OFL 1.1, with their licence texts beside them. **The canonical location is `mcp/src/vidtheque_mcp/public/static/fonts/`:** | file | family | axis | bytes | |---|---|---|---| | `archivo-latin-wght-normal.woff2` | Archivo | `wght` 100–900 | 34,928 | | `jetbrains-mono-latin-wght-normal.woff2` | JetBrains Mono | `wght` 100–800 | 40,404 | with `Archivo-OFL.txt` and `JetBrainsMono-OFL.txt`. This is now the *only* copy on the public surface: the landing carried a byte-identical set of its own under `lab/versions/v5-assets/fonts/` and dropped it when it graduated (2026-08-11), so both documents load the same two files. The JetBrains Mono file is byte-identical to the one the dashboard shipped until 2026-08-11 (`md5 b058178d…`). Provenance: the fontsource variable packages, filenames verbatim; `public/static/fonts/PROVENANCE.md` carries the full record, and Archivo arrived with lab v4 (commit `1251269`). **Rules for the builders:** 1. `public/static/fonts/` is the **document of record**. New face, new subset, new version: it lands there first. *Amended 2026-09-01:* the Next.js front end in `web/` is a separate deployable and carries a byte-identical copy at `web/src/fonts/`, loaded through `next/font/local`; `mcp/tests/test_web_assets.py` fails the suite the day the two differ. *Amended 2026-10-03:* the Android app (`android/`) cannot read woff2 and carries a TTF decompression of the Archivo file, for its wordmark only, in `android/app/src/main/res/font/`; regenerate it from this directory. 2. **Nothing in `mcp/` routes these files.** The public `/static/` asset route left with the welcome page (2026-09-05) and the dashboard's `fonts/` alias left with its own pages (2026-09-06), so the directory is a record rather than a served path. It had been the alias since 2026-08-11, which is when the byte-identical copy at `dashboard/static/fonts/` went; the copy that exists now is `web/src/fonts/`, and rule 1's diff is what keeps it honest. 3. **`@font-face src` is relative** (`fonts/…woff2`), never built from `PUBLIC_URL`. These surfaces are served through an SSH tunnel on a port nobody predicted. 4. `font-display: block` for both, matching v5: these faces carry the display voice and a FOUT on a 5.6rem headline is worse than 100ms of nothing. Only the text face is preloaded. 5. ~~**The dashboard's asset route types responses by suffix**~~ *(retired 2026-09-06.)* `_MEDIA` in `dashboard/__init__.py` was the last such map in Python and it went with that route. The rule it existed for — a font served as `text/javascript` stops loading the moment anything in front of the app sets `X-Content-Type-Options: nosniff` — is now whatever serves the assets, which is `web/`. ## Migration notes for the rebuild The old system is pinned by tests. Whoever gets there first updates them, in the same commit as their CSS, and says so: - ~~`test_dashboard.py::test_the_dashboard_palette_matches_the_front_ends`~~ and ~~`test_dashboard.py::test_both_schemes_and_a_mobile_viewport_are _declared`~~ *(deleted 2026-09-06 with the stylesheet and the templates they read — dashboard.md §23.)* The first asserted twelve `--bg/--fg/--muted/--line/--accent/--raised` declarations and that `dashboard.css` and `web/src/styles/tokens.css` agreed; the second asserted two `theme-color` metas. **Both properties still matter and no test in `mcp/` can see them any more**: there is one stylesheet now, `web/src/styles/tokens.css`, generated from this file, and whoever rebuilds the system asserts the six declarations and the single `theme-color` (`#040405`, `content="dark"`) in `web/`. - Any test asserting a radius, a serif wordmark, `--font-display`, or a warm-paper hex. - `.impeccable/design.json` is a generated mirror of this file's frontmatter and is stale until regenerated; it is not a second source of truth. ## Do's and Don'ts ### Do: - **Do** put every timecode, duration, id, `model_key`, `error_code`, count, clock and byte figure in the mono face with `tabular-nums` and ligatures off. **The Two-Channel Rule** is the system. - **Do** print the word for every state, in its tone. Colour reinforces. - **Do** keep gold for "this is the moment you are pointing at", and lime for "the machine read this off the screen". Nothing else gets either. - **Do** separate with plates and hairlines. A panel is a plate, an edge and a heading. - **Do** name the machine work behind anything that moves — and freeze it all under `prefers-reduced-motion`, painting end states. - **Do** give every image explicit `width`/`height` or a fixed-aspect box on `--black`. - **Do** write `var(--token)`. If the token does not exist, amend this file in the same commit. - **Do** keep the contrast sweep green: text ≥4.5:1, non-text marks ≥3:1, with `--fg3` the single measured exception and fenced as above. - **Do** clamp lists server-side and print `has_more`, never a total. ### Don't: - **Don't** add a border radius. Anywhere. The reset is zero. - **Don't** spend lime on anything that is not on-screen-text evidence. **The Lime Rule** is as hard as the type rule. - **Don't** add a second accent, a chart palette, or a "success green" beside the tones. - **Don't** animate anything you cannot name the machine work for — and never a pulse, a scan line, an ambient glow, or a hover transform. - **Don't** ship a shadow on anything that has not been lifted off the wall. No cards, no glass, no gradient used as a tonal ramp for looks. (*Gradient* means a decorative ramp, not the CSS function: the hero scrim is two layered gradients doing a legibility job, and a hatch encoding a fact is fine. A surface that fades because fading looks expensive is not.) - **Don't** reach for film sprockets, clapperboards, reel icons or faux-CRT. "Projection room" is a derivation, not a decoration. (The old film-frame favicon was the one sanctioned exception; it retired 2026-08-11 for the v.) - **Don't** introduce a third font family, or a serif for the wordmark. - **Don't** put a raw colour, an off-ladder font size, an off-ladder weight, or an off-4px layout spacing value in a stylesheet. - **Don't** build an absolute asset URL from `PUBLIC_URL`. Relative or root-relative, fonts included. - **Don't** add an inline `