data-theme="dark"DESIGN.md used to say dark mode was undefined and warn against improvising a full inversion.
That warning still holds — so this is not an inversion and not a second palette. The canvas is
--ink-band, the footer slab the source already shipped. Every text value is a ramp the
source already measured. Only three things are genuinely new, and each exists because a measurement forced it.
| Addition | Forced by | Derivation |
|---|---|---|
| A lifted surface ladder #1d3828 · #2a4534 · #304b39 · #3c5745 |
A dark canvas with no raised surface has nowhere to put a card — the panel and the page would be the same colour. | Same hue and chroma as --ink-band (oklch(L .045 155.4)), stepped in L: .258 → .315 → .363 → .385 → .430. |
| A lighter action colour #7fbc8a |
--forest measures 2.16:1 on this canvas. It fails AA outright — links would be unreadable. |
Lifted up the existing ramp past --moss until it clears 4.5:1 on all three dark surfaces — 6.93 / 5.74 / 4.73. The readiness audit caught --moss at only 3.74:1 on --evidence-inset, which is where the record table's header text sits. |
| A lifted amber #e0ae5d |
--amber-ink is far too dark to read on a dark surface, and status must never rely on a colour you cannot see. |
Same hue as --amber (77.7°), lifted to oklch(.78 .115 77.7). Still the one permitted hue break. |
Everything else — volt, the register ramp, the two dark bands, all
spacing, radius and motion — is unchanged between themes. --moss was one of four
tokens the audit found declared but never referenced; it now has a real job.
Resident-built, source-linked, and candid about its own gaps.
Corpus scan verified 2026-07-15.
Resident-built, source-linked, and candid about its own gaps.
Corpus scan verified 2026-07-15.
Note what did not move: the filing panel's header is
--slab-feature, dark in both themes, so the one component that was already dark
needs no dark variant at all. That is the payoff of naming the role — the panel header was never "a dark
colour", it was "the feature slab."
| Pair | Light | Dark | AA target |
|---|---|---|---|
--ink on --canvas |
15.05:1 | 12.98:1 | 4.5:1 body |
--ink-prose on --canvas |
8.01:1 | 10.73:1 | 4.5:1 body |
--ink-quiet on --canvas |
5.13:1 | 6.72:1 | 4.5:1 body |
--ink-margin on --canvas |
5.14:1 | 6.86:1 | 4.5:1 body |
--ink-quiet on --evidence |
5.53:1 | 5.57:1 | 4.5:1 body |
--ink-margin on --evidence |
5.54:1 | 5.68:1 | 4.5:1 body |
--action on --canvas |
6.61:1 | 6.93:1 | 4.5:1 body |
--action on --evidence |
7.13:1 | 5.74:1 | 4.5:1 body |
--action-on on --action fill |
7.13:1 | 6.93:1 | 6.93:1 body |
--status-pending on its bg |
5.05:1 | 6.48:1 | 4.5:1 body |
--rule on --canvas |
1.29:1 | 1.93:1 | decorative — not a boundary |
--volt on --slab |
14.32:1 | 15.89:1 | 3:1 UI |
The one honest caveat: --rule
does not reach 3:1 in either theme. That is deliberate — it is a hairline that organises the page, never the
sole indicator of a control boundary or a state. Every interactive element carries a label, a fill or a focus
ring as well. If you ever make a rule the only thing distinguishing two states, it must move to
--ink-quiet.
The slab sits one step below the canvas so the footer still reads as a distinct band in dark — inverting that would make the footer the brightest thing on the page.
| Rule | Why |
|---|---|
| Depth comes from the surface ladder, not from shadows. | A drop shadow on a dark canvas is nearly invisible. In dark, --shadow-* become hairline rings plus a much deeper ambient blur. |
| Hover goes lighter, not darker. | --action-strong is --forest-deep in light and --sage in dark. "Stronger" means "more contrast against the canvas", which reverses direction. |
| The grade ramp inverts. | Darkest = strongest only works on a light canvas. In dark, --grade-1 is the lightest step so weight still reads as confidence. |
| Volt does not change. | It was always a dark-only colour. Its four roles and its budget are identical in both themes. |
| The two dark bands do not get a dark variant. | .feat and the panel header are already --slab-feature. Their --on-dark-* text ramps hold in both themes. |
| Do not ship dark as an auto media query yet. | The source declares color-scheme: light. This theme is opt-in until a real product decision says otherwise — see IMPLEMENTATION.md. |