Skip to content

Author the colour palette and apply the design system everywhere - #42

Merged
botre merged 4 commits into
masterfrom
feat/authored-palette
Aug 8, 2026
Merged

Author the colour palette and apply the design system everywhere#42
botre merged 4 commits into
masterfrom
feat/authored-palette

Conversation

@botre

@botre botre commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Started as "the indigo looks like a framework default" and turned into the palette being authored rather than inherited, plus the component system finally being used on every page.

The palette is authored

Every colour came from Tailwind's defaults: stock slate for the chassis, stock indigo for the accent, seven unrelated stock hues for the badges. It is written in OKLCH now, in src/styles/theme.css, and Tailwind's defaults are cleared outright so a stock utility renders nothing rather than quietly reintroducing a colour nobody chose.

  • Neutrals sit on the mark's hue at very low chroma, so the greys belong to the brand instead of being generic blue-grey.
  • The accent carries the mark's hue and its chroma. The mark itself measures 3.6:1 against white and cannot hold a label, so the fill is that colour darkened to 5.74:1; the logo keeps #707ee7 exactly.
  • Method badges keep conventional meanings but are built to one construction: every ink at 50% lightness, every wash at 97%, chroma tuned per hue. They measure 4.97:1 to 9.48:1. PATCH and GET are spaced away from the accent so a badge is never mistaken for an action.

One edge per surface

Panels carried a seam and a shadow. There are no shadows anywhere now; depth is the tonal step plus a 1px seam.

Removing them exposed a bug the shadow had hidden: white surfaces hovered to the same colour as the page behind them, so a control dissolved into the background exactly when it should respond. That turned out to be a recurring class of bug, hit three times in review, and it is now a written rule.

The system is used on every page

The components were extracted and then applied to one page out of three: index.html and contact.html used zero component classes and re-spelled panels, fields and buttons by hand. That is why a contact input and a send-panel input looked like different controls.

Both pages compose the components now, no template re-spells one, and there are no arbitrary hex values left in markup.

The contact form's second label style was drift, not intent — described in the design record during documentation and then cited back as justification. There is one label component.

Interaction defects found in review

  • The disclosure summary was rounded-lg on all corners with an outside ring, so when open the focus ring and hover fill curved into the panel below and collided with its border. Squares its bottom corners now, ring drawn inside.
  • Labels sat 4px from their fields while groups sat 12px apart. Now 8px and 16px, so a label groups with what it names.
  • The confirm button was danger-50 on a danger-50 banner. One solid destructive button now, and the toolbar control that merely opens the confirmation is a plain secondary: colour marks the action that destroys, not the one that asks.
  • .btn-inline was a control using the data radius.

The design record

Repaired against the build. Its frontmatter is the normative layer and was broken: four component tokens referenced a colour the theme does not define, seven ramp steps were missing, the syntax colours had been dropped while the prose still documented them, and the component tokens named classes that are called something else. Four prose claims contradicted the build, and the colour vocabulary was doubled throughout.

Also records what the build gained and the record never mentioned: the 40k highlight cap, the 25-card render window, the mono field variant, and the rules that came out of review.

Verification

Frontmatter parses, no broken token refs, the record and the theme define exactly the same colours, component tokens map one-to-one to real classes, sidecar keys resolve, zero stale terms. Detector clean, prettier --check . clean, go vet, unit tests, Playwright 39/39. Checked in a browser at desktop and 390px.

Not addressed

Still open from the earlier reviews, both backend: POST /endpoint has no CSRF protection, and / ships with no security headers while every other route has them. The request card is also still a tall dossier, which was a deliberate call.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt

botre added 4 commits August 8, 2026 18:11
Every colour came from Tailwind's defaults: stock slate for the chassis, stock
indigo for the accent, seven unrelated stock hues for the method badges. That is
what made the interface read as a framework rather than as this product.

The palette is authored in OKLCH now. The neutral chassis sits on the mark's hue
at very low chroma, so the greys belong to the brand rather than being a generic
blue-grey. The accent carries the mark's hue and its chroma; the mark itself
measures 3.6:1 against white and cannot hold a label, so the fill is that colour
darkened until it clears the floor, and the logo keeps #707ee7 exactly.

The method spectrum keeps conventional meanings, because GET-blue and POST-green
are near-universal in HTTP tooling, but every ink is built at one lightness and
every wash at another, so the seven carry equal weight. PATCH and GET are spaced
away from the accent's hue so a badge is never mistaken for an action.

Tailwind's defaults are cleared outright. A stock utility now renders nothing
rather than quietly reintroducing a colour nobody chose.

Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
Panels carried a hairline seam and a shadow together: two mechanisms declaring
one edge, each weakening the other. There are no shadows at all now. Depth is the
tonal step between field and panel plus a 1px seam, which is what keeps a page of
stacked panels calm.

Removing them exposed a bug the shadow had been hiding: white surfaces hovered to
the same colour as the page they sit on, so a control dissolved into the
background at the moment it should respond. They step to neutral-100 and darken
their seam instead.

Also completes the component set that only the endpoint page had been using:
a large button for the landing call to action, a single solid destructive button,
and label spacing that groups a label with its field rather than floating it
equidistant between two things. Inline text actions take the control radius, not
the data radius.

Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
The component classes were extracted and then applied to one page out of three.
The landing and contact pages re-spelled panels, fields and buttons as raw
utility strings, which is how a contact input and a send-panel input ended up
looking like different controls. Both pages compose the components now, and no
template re-spells one by hand.

The contact form used a second label style, sentence case at body size. That was
never a decision: it was drift, described in the design record during
documentation and then cited back as if it were intent. There is one label
component.

The example capture on the landing page referenced the syntax colours as literal
hex; they are tokens like everything else.

The disclosure summary drops to the control type size, because it is a control
rather than a section heading, and it squares its bottom corners when open so its
focus ring and hover fill stop curving into the panel below.

Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
The record was edited section by section through the palette rework, the removal
of shadows and the component extraction, and each edit left its neighbours
asserting the old truth.

Its frontmatter is the normative layer, and it was broken: four component tokens
referenced a colour the theme does not define, seven ramp steps were missing, and
the syntax colours had been dropped while the prose still documented them. The
component tokens named a vocabulary nobody could use, against classes that are
actually called something else.

Four prose claims contradicted the build: buttons in "two sizes only" when there
are three, the Title role covering a summary that is no longer that size,
liveness signalled only in browser chrome when an indicator sits on the page, and
a three-radii rule the code itself broke.

The colour vocabulary was doubled throughout, with retired descriptive names
appearing beside the ramp names for the same values.

Also records what the build gained and the record never mentioned: the highlight
size cap, the render window, the mono field variant, and the rules that came out
of review, including that a surface must never hover to the colour of the page
behind it, and that the destructive button marks the action that destroys rather
than the one that asks.

The design hook is enabled for the project.

Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
@botre
botre merged commit 86dca5a into master Aug 8, 2026
3 checks passed
@botre
botre deleted the feat/authored-palette branch August 8, 2026 16:14
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