Chapter 00 · Design system Stratos

A design system that
argues with itself.

Stratos is the design system behind acaldwell.dev — twenty Svelte 5 components, three layers of tokens, one signature move: chroma-as-interaction. Hover doesn’t darken; it raises saturation. Dark mode runs warm cream on cool charcoal. Built in OKLCH from the ground up, not converted from sRGB.

Chapter 01

The intent

Most design systems borrow their color from Material or Tailwind, then tune from there. Stratos starts with the question: what do I want a hover state to feel like? The answer — “more saturated, same hue” — pulls the rest of the architecture along behind it.

So OKLCH is non-negotiable. Hue is a name; chroma is a verb; lightness is a place on the page. Fifteen hex values pinned to a moodboard wouldn’t survive translation to dark mode, accessibility audits, or the inevitable third color a portfolio site picks up over a year of writing.

The output is a token graph — primitives down to component variables — that any framework target can compile against. The site you’re reading is one consumer. The Mitosis-bound component library is another.

Chapter 02

Two brands, one spine

Mongoose carries action; Mountbatten carries personality; Edward sits between brand and structure; Gray Nurse and Abbey are the same hue at opposite lightness ends — one ramp masquerading as two namespaces. Honest about which colors are colors and which are scaffolding.

Brand colors

2 · chromatic
H:75 Primary

Mongoose

soft --palette-mongoose-100
main --palette-mongoose-500
dark --palette-mongoose-900

Warm gold. The brand. Carries every primary action and signature flourish. Chroma scales from 0.020 (soft) up to 0.070 (dark) — high enough to read unmistakably as gold.

H:330 Accent

Mountbatten

soft --palette-mountbatten-100
main --palette-mountbatten-500
dark --palette-mountbatten-700

Dusty mauve. Personality color — the 2016 pink, kept on purpose. Chroma 0.015–0.060, deliberately low so it reads as accent, not exclamation.

Quiet accent

1 · near-neutral
H:195 Quiet accent

Edward

soft
300
main
dark
900

Gray-teal at chroma 0.006–0.018 — barely chromatic. On its own it reads as gray; placed next to Mongoose it tilts cool. Used where the system needs faint personality without the visual weight of a brand color: borders, supporting type, hover edges.

Neutral spine

H:260 · one hue, two namespaces

Both Gray Nurse and Abbey live on the same H:260, separated only by where they fall on the lightness scale. The shared hue is what lets dark mode feel like the same palette as light mode at a different brightness — not a different palette.

gn-50 L:99
gn-200 L:95
gn-400 L:88
gn-500 L:80
gn-700 L:50
abbey-500 L:38
abbey-700 L:23
abbey-900 L:14
Chapter 03

Token cascade

Three layers. Primitives are the raw OKLCH values, semantic tokens give them meaning, component tokens specialise them for context. Everything below is verified against the actual JSON — if it’s in the diagram, you can grep for it.

Solid primary action
primitive --palette-mongoose-500 oklch(74% 0.050 75)
semantic --color-primary-main → palette.mongoose.500
component --button-primary-background → color.primary.main
Soft brand surface
primitive --palette-mongoose-100 oklch(95% 0.020 75)
semantic --color-primary-soft → palette.mongoose.100
component --badge-primary-background → color.primary.soft
Spacing — one primitive, two consumers
primitive --spacing-6 1.5rem
component --button-padding-x-lg → spacing.6
component --card-body-padding → spacing.6
Chapter 04

Type in context

Four families pulling distinct weight: Bricolage Grotesque for display, DM Sans for body, IBM Plex Mono for code, and Caveat for the handwritten asides that make the site feel inhabited. Sample lifted from a working blog post:

Chapter 05

Motion as personality

Three timing tiers. Each one earns its duration — micro for the things you should barely notice, state for the things you do, enter for the things that arrive. Try them.

100ms · chroma rises, hue holds, lightness barely moves.

Barely perceptible. The hover state on a button rises by chroma rather than darkness — the eye reads it as “more itself” rather than “different.” Animated via @property --chroma.

300ms · slide + fade, @starting-style, never instant.