LLOS.ai
Colour
● Colour · Module 6 · System

The Colour System

A palette you have to remember is a palette you will break.

Picture the day it matters. Someone walks over: “can we change the blue?” If that blue lives in your head and in ninety copy-pasted hex codes, you lose the afternoon to find-and-replace — and still ship one you missed. If it lives in a system, you change one line and the whole product turns.

That’s the shift here: you stop painting screens and start naming decisions. Give each colour a job. Grow a family from one hue. Make dark mode a switch, not a second codebase. Three small labs below, and it all lands faster in your hands than on the page — so go and play.

~9 min3 real-colour labsa repair diagnostic10-question bankglossary · FAQ
The transformation, end to end
colourperception
rampa family
primitiveraw name
semantica job
componenton screen
themeremapped
The palette chose the colours. The system decides where they’re allowed to go.
What you’ll be able to do
01 · One hue, a whole family

Generate a ramp

A system doesn’t start with five colours — it starts with a ramp: one hue stepped from near-white to near-black, ten tints and shades that all obviously belong. The light steps become backgrounds and hovers; the dark steps become text and borders. One hue, a dozen jobs.

Pick a hue and read the tokens below. Then flip the colour space: in OKLCH every step looks evenly spaced; in HSL, the same even numbers bunch and lurch. That’s the whole reason systems moved to OKLCH.

The Tonal Ramp Generator
One hue, ten steps, copyable tokens. Toggle the colour space to feel why OKLCH wins.
235°
safe
Ramp tokens

      
02 · Name by role

Change one token

This is the move that turns a palette into a system. Give a colour a nickname for its job — call it “the action colour”. (In CSS you write that as --action; the double dash is just how the syntax works — read it as a name you invented.) Now every button, link and badge asks for the action colour instead of naming a specific blue.

Here’s the payoff: change what the action colour is, and all of them follow at once — because none of them ever knew it was blue. It’s far easier felt than read, so go feel it. The lab is one square and one instruction.

The Token Cascade
One name drives everything above. The hardcoded copy below can’t follow.
Tap the colour square and pick anything. Watch it ripple left → right — the name, then the button, link, badge, tab and focus ring, all at once. Then look at the hardcoded row: it can’t move.
Primitive
Semantic--action
Components
Save Learn more New Home
Focused field
✗ The hardcoded alternative — #3b82f6 typed into 5 rules, frozen
SaveLearn moreNewHome
Focused field

You just watched --action move the whole UI — so which name scales? Each token below is named for what it looks like. Tap to reveal the name that says what it does.

--blue-button--action-primarytap to reveal
--orange-alert--state-warningtap to reveal
--light-grey-card--surface-cardtap to reveal
--green-success--state-successtap to reveal
03 · One source, two themes

Flip light and dark

Dark mode isn’t an inversion — invert a light theme and you get glaring text, muddy shadows and buzzing accents. It’s a remap: the same semantic tokens (--bg, --surface, --text, --accent) point at different values in each theme, and the components never change at all.

Flip the toggle. The card, text and button stay exactly the same markup — only their tokens are reassigned. Notice the accent’s chroma is eased in dark mode so it doesn’t vibrate against the near-black.

Light / Dark Flip
One semantic token set, two themes. Same components; remapped values.
Weekly summary
Three projects on track, one in review.
Updated 4 minutes ago · muted text
Open reportBeta
03b · Status by meaning, not loudness

State colours, one value

Success, warning, danger, info — the four colours a system uses most. Picked one at a time they drift to wildly different lightness, so the UI jumps in brightness as states change and a warning can shout louder than a danger. Generate them at a matched value and they differ only by meaning.

The State Ramp
Toggle between ad-hoc picks and a matched-value set. Watch the loudness even out.
The craft, beyond the tokens

The one distinction that holds it together

Ramps, tokens and themes all rest on a single idea. Get it and a colour system almost builds itself; miss it and the tokens become just longer names for the same mess.

Primitives describe appearance. Semantic tokens describe intention.

A primitive is a raw colour with a literal name: --blue-600, --neutral-100. It says what the colour is. A semantic token has a job name: --action-primary, --text-muted, --surface. It says what the colour is for. Components should only ever reference the semantic layer — a button uses --action-primary, never --blue-600 — because then the meaning of “primary action” can move from blue-600 to blue-500, or to a completely different hue, without touching a single component.

There’s a third layer above those two: a component token — where a decision actually lands on screen. Three layers, one line worth memorising: --blue-600 is a colour. --action-primary is a decision. The button’s background is where the decision appears. The paint shelf, the job title, and the actor on stage — and the whole mistake is stopping at the paint shelf.

This one seam is what makes everything else possible. Theming is just pointing the semantic tokens at different primitives per mode. A rebrand is re-pointing them once. Accessibility is baked in when the semantic pairs (text on surface) are chosen to pass contrast by default. And a rename audit stops being terrifying, because the colour lives in exactly one place.

So the rule is short and strict: generate primitives as ramps, define semantic tokens on top of them, and let components speak only semantics. Name by role, not by hue — and the system survives every change you throw at it.

Now fix one

Repair this hardcoded palette

A component with the same blue typed in five times and a grey typed in four. Walk it into a system — lift the raw colours into primitives, then wire the components to semantic tokens.

component.css

      
Cast your vote

Which is built to scale?

Five face-offs. Two ways to do the same thing — one survives change, one breaks under it. Pick the stronger, then see the verdict.

Round 1 of 5 · Tokens Score 0
Real lessons from the field

When the system paid off

Three teams learned the value of tokens the hard way — usually one rebrand or one dark-mode request too late. Hit greyscale test to see the structure a good ramp gives you.

The overnight rebrand

A startup switched its brand hue the night before a launch. The team with semantic tokens changed one primitive and shipped; the team with hardcoded blues spent the night hunting hexes and still missed a few.

The dark-mode request

“Can we add dark mode?” broke a product with colours baked into components — weeks of work. A token-based sibling shipped it in a day: one extra theme block re-pointing the same semantic names.

The mismatched states

Success, warning, danger and info were picked ad hoc, at wildly different lightness — the UI flickered as states changed. Regenerating all four at one matched value made state changes feel calm and consistent.

Seen in the wild

State colours, one value

The mark of a system: the four semantic state colours are different hues but the same perceived value, so switching between them never jumps in brightness. Generated, not hand-picked.

success
warning
danger
info
Matched value
A state ramp

Four hues, one lightness. Because the value is held constant, no state feels louder than another — and each still has a light tint for its background.

Dark, remapped
The same tokens, dark

Base, surface, text and a chroma-eased accent — identical semantic names, different primitives. One source of truth, two skins.

Where the system meets the rest of the series

The system is where every earlier module gets encoded. The palette becomes primitives; the roles become semantic tokens; value defines the ramp steps; contrast floors are baked into the semantic pairings so accessible-by-default is the starting point. All that remains is the human layer — what these colours mean to people — which is the next module, before the capstone ties everything together.

Take it with you

Your starter system

The whole module on one clipboard: an OKLCH primitive ramp, semantic tokens named by role, and a light/dark theme map. Copy it as the seed for your next project — and for the capstone.

colour-system.css

    
The vocabulary

The System glossary

Six words that turn “the colours are a mess” into a fixable structure. Tap a card to flip it.

The nuance

Questions you actually ask

Busting the myths

What people get wrong

Myth
“Design tokens are just for engineers.”
Tokens are a design decision written down. Naming a colour by its job — action, surface, danger — is design thinking; the code is just where it’s stored.
Myth
“Dark mode is inverted light mode.”
Inversion glares and buzzes. Dark mode is a remap — new surfaces, eased chroma, rebalanced contrast — from the same semantic tokens.
Myth
“Name colours for what they look like.”
Name primitives for appearance (blue-600), but components should use semantic names (action-primary) — so the hue can change without touching them.
Myth
“HSL is fine for building ramps.”
HSL’s lightness isn’t perceptual, so its ramps look lumpy. OKLCH steps land evenly to the eye — which is why systems are moving to it.
Myth
“Tokens are just variables.”
A variable stores a value; a token stores a design decision — that “primary action” is a concept worth naming, separate from whichever hue fills it today.
Myth
“A ramp is just lighter and darker colours.”
A ramp is ten usable distances — each step has a job (background, border, hover, text). Even spacing is what makes those jobs predictable across every hue.
Train the eye

Build the system

Ten questions in seven formats, tagged by thinking level — each with layered hints: a nudge, the reasoning, then a deeper connection. A wrong answer opens a door, never a dead end. Served from the question bank, never hardcoded.

Loading the question bank…
Question 1 of 10
Multiple choice
Keep going

Where this connects

▶ Play the colour labs