Skip to content

fix(themes): read heritage light/dark from canon instead of deriving both from one seed - #131

Open
bryanfawcett wants to merge 1 commit into
mainfrom
claude/heritage-canon-derivation
Open

fix(themes): read heritage light/dark from canon instead of deriving both from one seed#131
bryanfawcett wants to merge 1 commit into
mainfrom
claude/heritage-canon-derivation

Conversation

@bryanfawcett

Copy link
Copy Markdown
Contributor

The defect

src/lib/themes.ts documented its own bug:

"Build a washed theme from a single heritage hex. mzizi's heritage records ship only the hex, so we derive the container (wash) by mixing the hex into the active surface (~8% light / ~14% dark) and pick an AAA on-container."

The premise is false. Heritage records ship both lightHex and darkHex — see mzizi-registry/lib/tokens/palette.source.ts (the source of truth on disk), the same pair returned by GET /v1/brand. heritage() took one hex and synthesised the dark accent from it (color-mix(hex 62%, white)), so all 14 heritage values were wrong (7 families x 2 modes) — and, being a derivation rather than a constant, wrong again on every regeneration.

The fix

heritage(name, lightHex, darkHex) — each mode takes its accent straight from canon. The comment carrying the false premise is corrected, since it is why the bug survived.

Only the light/dark derivation was wrong. The wash/container mixing is preserved exactly: the container is still mixed from the mode's accent into the active surface (~8% light / ~14% dark), the on-container is still solved to an AAA-safe foreground, and the wash stays surface-relative via color-mix.

globals.css

Carried the same pre-Seven, Material-derived values as static tokens (#1A237E = Indigo 900, #A5D6A7 = Green 200, #80DEEA = Cyan 200), and was missing hematite and kalahari entirely — the two families added when heritage expanded to seven. Both blocks are now canon and complete, with the two new families exposed as Tailwind colour tokens alongside the other five.

family was (light / dark) now (canon)
indigo #1A237E / #8C9EFF #4527A0 / #7986CB
savanna #5D4037 / #FFCC80 #8D6E1A / #E5C158
baobab #2E4A2E / #A5D6A7 #4E342E / #A1887F
sunset #8B2500 / #FF8A80 #D84315 / #FF7043
river #00525A / #80DEEA #006064 / #4DD0E1
hematite absent #546E7A / #90A4AE
kalahari absent #C9B589 / #E8D9B5

Verified, not changed

--on-container-sodalite: #1A237E is left alone. It is Material Indigo 900 in a sodalite on-container role, not heritage-indigo — it matched the grep but is not this bug.

Verification

All 14 heritage accents now equal canon in both modes:

PASS indigo    light=#4527A0 dark=#7986CB
PASS savanna   light=#8D6E1A dark=#E5C158
PASS baobab    light=#4E342E dark=#A1887F
PASS sunset    light=#D84315 dark=#FF7043
PASS river     light=#006064 dark=#4DD0E1
PASS hematite  light=#546E7A dark=#90A4AE
PASS kalahari  light=#C9B589 dark=#E8D9B5

Wash mechanism intact (river light): color-mix(in srgb, #006064 8%, var(--surface)). Theme count still 15 (1 default + 7 heritage + 7 experimental), satisfying themes.test.ts.

Note: vitest could not be run in this environment — package-lock.json on main is out of sync with package.json (missing @tailwindcss/oxide and lightningcss platform binaries), and the existing node_modules lacks vitest-axe. Both are pre-existing on main and unrelated to this change; the lockfile is deliberately untouched. The derivation was instead verified by transpiling themes.ts and asserting every value against canon, as above.

🤖 Generated with Claude Code

…both from one seed

`heritage()` took a single hex and synthesised the dark accent from it
(`color-mix(hex 62%, white)`), on the stated premise that "mzizi's heritage
records ship only the hex". That premise is false: heritage records ship both
`lightHex` and `darkHex` (mzizi-registry/lib/tokens/palette.source.ts, also
visible on GET /v1/brand). Deriving both modes from one seed made all fourteen
heritage values wrong — 7 families x 2 modes — and, being a derivation rather
than a constant, wrong again on every regeneration.

The function now takes the canonical pair and each mode uses its own accent.
The comment that carried the false premise is corrected, since it is the reason
the bug survived.

Only the light/dark derivation was wrong. The wash/container mixing is
unchanged: the container is still mixed from the mode's accent into the active
surface (~8% light / ~14% dark) and the on-container is still solved to an
AAA-safe foreground, keeping the wash surface-relative.

globals.css carried the same pre-Seven, Material-derived values as static
tokens (`#1A237E` Indigo 900, `#A5D6A7` Green 200, `#80DEEA` Cyan 200) and was
missing hematite and kalahari entirely — the two families added when heritage
expanded to seven. Both blocks are now canon and complete, and the two new
families are exposed as Tailwind colour tokens alongside the other five.

Deliberately unchanged: `--on-container-sodalite: #1A237E`. That is Material
Indigo 900 in a sodalite on-container role, not heritage-indigo.

Verified: all 14 heritage accents now equal canon in both modes.

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

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nhimbe Ready Ready Preview Sep 11, 2026 4:45pm UTC

Request Review

@claude

claude Bot commented Sep 11, 2026

Copy link
Copy Markdown

Claude encountered an error —— View job


I'll analyze this and get back to you.

@bryanfawcett
bryanfawcett added this pull request to the merge queue Sep 11, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to Branch Protection failures Sep 11, 2026
You're not authorized to push to this branch. Visit "About protected branches" for more information.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant