Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 7bb1df046879f7b8afe2b2ff353f78f16e9dfe46
parent c2bc533abfdb7f617fc33f23f94dddf0912cdd45
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Fri, 25 Sep 2026 22:26:14 -0400

common: sepia status colours read at 4.5:1 on their own soft fills (brand S2 review)

The sheet promises that each status colour reads as TEXT on its -soft fill.
Sepia fell short: warning 4.32 and info 4.46 over the ground. They are now
#8c4c00 (4.65 on its fill over the ground, 4.96 over a card; 5.66 on the
ground) and #1858bc (4.74 / 5.07; 5.64), each with its -soft rgba to match.

The new test found two more:
- sepia success was 4.49, and is now #256829 (4.73 / 5.05);
- dark gone over a card was 4.37: its -soft alpha is now 0.12 (4.94 / 4.60).

themeTokens.test.ts now checks success, warning, info, destructive and gone on
their soft fills over the ground and a card, on sepia and dark. Light's
success and warning (4.18 / 3.89) predate the themes and are left, as noted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Mcommon/components/themeTokens.test.ts | 35+++++++++++++++++++++++++++++++++++
Mcommon/styles/tokens.css | 16+++++++++-------
2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/common/components/themeTokens.test.ts b/common/components/themeTokens.test.ts @@ -202,3 +202,38 @@ test("text tokens read at 4.5:1 on each base's ground and card", () => { assert.ok(inkOn >= 4.5, `${base}: primary-foreground on primary is ${inkOn.toFixed(2)}:1`); } }); + +// "Soft = a low-alpha tint of the hue for badge/alert fills; the base color is +// tuned to read as TEXT on that soft fill" (tokens.css @theme). Sepia and dark +// keep that promise on the ground and on a card. The light block's success and +// warning (4.18 / 3.89 on their soft fills) predate the base × accent themes +// and are not covered here. +function compositeOver(rgba: string, ground: string): string { + const m = /^rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)$/.exec(rgba); + assert.ok(m, `not an rgba(): ${rgba}`); + const a = Number(m[4]); + const g = parseInt(ground.slice(1), 16); + const G = [(g >> 16) & 255, (g >> 8) & 255, g & 255]; + const out = [1, 2, 3].map((i, k) => Math.round(Number(m[i]) * a + G[k] * (1 - a))); + return `#${out.map((v) => v.toString(16).padStart(2, "0")).join("")}`; +} + +test("status text reads at 4.5:1 on its own soft fill (sepia and dark)", () => { + const PAIRS = [ + ["--success", "--success-soft"], + ["--warning", "--warning-soft"], + ["--info", "--info-soft"], + ["--destructive", "--destructive-soft"], + ["--state-gone", "--state-gone-soft"], + ] as const; + for (const base of ["sepia", "dark"] as const) { + const r = rule(BASE_SELECTOR[base]); + for (const bg of ["--background", "--card"]) { + for (const [text, soft] of PAIRS) { + const fill = compositeOver(r.decls.get(soft)!, r.decls.get(bg)!); + const ratio = contrastRatio(r.decls.get(text)!, fill); + assert.ok(ratio >= 4.5, `${base}: ${text} on ${soft} over ${bg} is ${ratio.toFixed(2)}:1`); + } + } + } +}); diff --git a/common/styles/tokens.css b/common/styles/tokens.css @@ -247,15 +247,17 @@ html[data-base="sepia"] { --panel: rgba(250, 244, 230, 0.72); --panel-2: rgba(236, 226, 202, 0.72); - --success: #276c2b; + /* Each deep enough to read at 4.5:1 on its OWN soft fill over the ground + and the card, as the @theme note promises (themeTokens.test.ts). */ + --success: #256829; --success-foreground: #ffffff; - --success-soft: rgba(39, 108, 43, 0.14); - --warning: #945000; + --success-soft: rgba(37, 104, 41, 0.14); + --warning: #8c4c00; --warning-foreground: #ffffff; - --warning-soft: rgba(148, 80, 0, 0.14); - --info: #1a5cc4; + --warning-soft: rgba(140, 76, 0, 0.14); + --info: #1858bc; --info-foreground: #ffffff; - --info-soft: rgba(26, 92, 196, 0.12); + --info-soft: rgba(24, 88, 188, 0.12); /* Each named accent's on-sepia value (lib/brand.ts ACCENTS.onSepia). */ --swatch-signal: #2b756e; @@ -349,7 +351,7 @@ html[data-base="dark"] { --brand-ink: #0c0a08; --state-gone: #d9644f; - --state-gone-soft: rgba(217, 100, 79, 0.16); + --state-gone-soft: rgba(217, 100, 79, 0.12); /* Same hue order, stepped into the validator's dark lightness band. Adjacent pairs pass every check; all pairs pass with green ↔ magenta in