Overview
The biggest blocker sat in the tokens. Their names described where a token was used rather than what it meant, so the same visual intent needed different tokens in different components.
In my report I proposed a semantic structure: tokens named after their role, such as surface, text, action and feedback, referencing a shared set of base values.
Ready for machines as well as people
I structured the architecture to be machine-readable as well as human-readable: predictable names, one clear role per token, and relationships defined rather than implied. A designer can read a token and know where it belongs, and so can a tool.
That groundwork meant the system was ready for AI tooling later on, such as connecting it to Claude through MCP for new component creation, rapid prototyping and system governance, without having to restructure it first.
Figma, the platforms and Claude MCP all read and write the same machine-readable tokens, so a change in one flows through to the others.
Three layers
Every token sits in one of three layers. Components never reach into the palette directly: they use a semantic token, which points at a palette step. Change the step, and every component using that role follows.
One colour through the three layers.
Naming by purpose
Each token name now says what it does, so it can be reused across any component with the same intent.
theme.color.bg.control.muted.selected.hover theme.color.text.action.branded.secondary.default theme.color.border.control.emphasis.unselected.disabled
Six levels deep, tied to one component.
color.action.secondary.bg.hover color.action.secondary.text.default color.action.secondary.border.disabled
Four levels, reusable across any interactive element.
One spacing scale
Padding, gap and margin were separate scales resolving to the same values. Merging them into one 4pt scale gave design and engineering a single vocabulary.
padding: theme.padding.pMd // 16px gap: theme.gap.gMd // 16px margin: theme.margin.mMd // 16px
Three names for the same value.
padding: space[4] // 16px gap: space[4] // 16px margin: space[4] // 16px
One name, one scale.
A calmer palette
The palette had grown into 12-step ramps with uneven steps, muddy mid-tones and duplicate values. I used OKLCH as a perceptual lens to find the problems HSL and RGB hide, then rebuilt every ramp to nine steps, from 100 to 900.
Brand-critical CTA colours, Teal 500 and 900, stayed exactly as they were. Warm Grey, Sage and Dusty Teal were removed, Orange was renamed Coral, and Yellow gained true dark steps in a mustard lane of its own, clear of Coral.
The final nine-step ramps.
States as overlays
Instead of a hover, pressed and disabled colour for every action role, interaction states became overlays: a base colour plus one of 12 alpha tokens, black on light surfaces and white on dark.
That removed a whole set of state-specific tokens, and let us collapse three neutral action roles into one and three disabled variants into one.
Six non-linear steps each, over Teal 500 and Teal 900.
The result
Engineering built the new system on this architecture, and wrote a migration script that mapped existing usage onto the new tokens and removed the ones that no longer matched.
Fewer tokens overall, from 550 to 186
Fewer colour tokens, from 470 to 106
