Design system
Tokens
The raw CSS custom properties exposed by <code>src/css/global/variables.css</code>. Foundations describes how each token is used; this section is the flat reference.
Color tokens
Every --color-*, --glass-*, and --gradient-* token from variables.css. Source values are oklch() for perceptual lightness; transparency is expressed in-channel (oklch(… / 0.6)) rather than as a separate alpha token. For deeper context on how the palette composes — brand vs neutral vs surface — see Foundations › Colour.
Brand
--color-blue
oklch(66.623% 0.1177 217.10)
#0aa5c3
--color-blue-light
oklch(77.31% 0.13351 211.702)
#0bcbe6
--color-blue-dark
oklch(58.216% 0.1005 212.646)
--color-green
oklch(77.183% 0.1766 131.692)
#8acb46
--color-green-dark
oklch(64.020% 0.1502 131.396)
Neutral ramp
--color-white
oklch(96.826% 0.0069 247.896)
--color-grey-50
oklch(20.768% 0.0398 265.755)
--color-grey-100
oklch(23.157% 0.0398 262.510)
--color-grey-200
oklch(27.950% 0.0368 260.031)
--color-grey-300
oklch(37.170% 0.0392 257.287)
--color-grey-400
oklch(71.067% 0.0351 256.788)
--color-grey-500
oklch(55.439% 0.0407 257.417)
--color-grey-600
oklch(86.898% 0.0198 252.894)
--color-grey-700
oklch(92.876% 0.0126 255.508)
--color-grey-800
oklch(96.826% 0.0069 247.896)
--color-grey-900
oklch(98.415% 0.0034 247.858)
Lightness is the first OKLCH channel — in this dark palette, low numbers are deep panels and high numbers are bright text. The opposite of a Tailwind ramp.
Surfaces
--color-body-bg
oklch(16.140% 0.0289 266.826)
--color-surface-solid
oklch(18.020% 0.0325 266.625)
--color-header-solid-bg
oklch(16.140% 0.0289 266.826 / 0.95)
Text
--color-text
oklch(86.898% 0.0198 252.894)
--color-text-muted
oklch(71.067% 0.0351 256.788)
--color-heading
oklch(96.826% 0.0069 247.896)
Glass
--glass-bg
oklch(20.768% 0.0398 265.755 / 0.6)
--glass-bg-light
oklch(20.768% 0.0398 265.755 / 0.4)
--glass-border
oklch(71.067% 0.0351 256.788 / 0.12)
--glass-border-hover
oklch(71.067% 0.0351 256.788 / 0.22)
--glass-blur
1rem
Gradients
--gradient-accent
linear-gradient(135deg, blue/grey 0-10%, green/grey 90-100%)
--gradient-accent-shimmer
linear-gradient(90deg, blue, green, green, blue)
The shimmer gradient pairs with background-size: 200% 100% and an animation: shimmer… keyframe to produce the looping accent. See it live on the animations page.
Grid & shimmer accents
--color-grid-line
oklch(71.067% 0.0351 256.788 / 0.08)
--color-grid-line-light
oklch(71.067% 0.0351 256.788 / 0.06)
--color-shimmer
oklch(100% 0 none / 0.25)
Decorative opacities
Numeric tokens consumed by the hero blob field and other layered backdrop washes. Tune these per surface to dial intensity up or down without changing the base colours.
--hero-blob-blue-1
0.18
--hero-blob-blue-2
0.12
--hero-blob-green-1
0.15
--hero-blob-green-2
0.10
--bg-blue-1
0.10
--bg-blue-2
0.06
--bg-green-1
0.07
--bg-green-2
0.05
Hero signal canvas
Read by src/js/hero-signals.js at runtime to colour the trail dots. Splitting the colour into r/g/b channels lets the canvas pre-compute the alpha lookup without parsing strings every frame. See Brand › Illustration for the recipe.
--signal-trail-r
10
--signal-trail-g
165
--signal-trail-b
195
--signal-trail-multiplier
0.4
--signal-dot
oklch(66.623% 0.1177 217.10 / 0.5)
Components
Single-component tokens kept here rather than in the component CSS so they live alongside the rest of the palette.
--benefits-card-bg
oklch(20.768% 0.0398 265.755 / 0.6)
--partner-item-bg
oklch(26.48% 0.01276 243.42)
--partner-logo-opacity
0.5
--partner-logo-hover-opacity
0.85
Filter tokens (--partner-logo-filter, --partner-logo-hover-filter) drive the partner-logo greyscale-to-colour transition; they have no visual swatch since they describe an image filter, not a colour.
Type tokens
Two family tokens and a 12-step modular size scale, all in variables.css. Sizes are in rem so they respect the user’s root font size; the scale isn’t a strict ratio — spacing between steps tightens at the small end and opens up at the display end so headlines have room to breathe. For the family rationale and weight inventory, see Foundations › Typography.
Families
--font-text
Aa Bb 0 1 2
--font-heading
Aa Bb 0 1 2
Size scale
--font-size-xs
0.75 rem · Aa
--font-size-sm
0.875 rem · Aa
--font-size-base
1 rem · Aa
--font-size-lg
1.125 rem · Aa
--font-size-xl
1.25 rem · Aa
--font-size-2xl
1.5 rem · Aa
--font-size-3xl
1.875 rem · Aa
--font-size-4xl
2.25 rem · Aa
--font-size-5xl
3 rem · Aa
--font-size-6xl
3.75 rem · Aa
--font-size-7xl
4.5 rem · Aa
--font-size-8xl
5.5 rem · Aa
Spacing tokens
Twelve steps on a 0.25 rem base, with a 7th-step skip from --space-6 to --space-8 — a deliberate gap, since 1.75 rem is a value the layout never needs. Use these for every margin, padding, and gap; never fall back to raw rem or px. For the rhythm rationale see Foundations › Spacing.
--space-1
0.25 rem · 4 px
--space-2
0.5 rem · 8 px
--space-3
0.75 rem · 12 px
--space-4
1 rem · 16 px
--space-5
1.25 rem · 20 px
--space-6
1.5 rem · 24 px
--space-8
2 rem · 32 px
--space-10
2.5 rem · 40 px
--space-12
3 rem · 48 px
--space-16
4 rem · 64 px
--space-20
5 rem · 80 px
--space-24
6 rem · 96 px
Adjacent dimensional tokens. Border radii (--radius-sm through --radius-2xl + --radius-full) and shadows (--shadow-sm through --shadow-xl + --shadow-glow) are documented under Foundations › Radii and Foundations › Shadows with their visual specimens, since both read better as showcases than as a flat list.
Motion tokens
Three transition tokens and one stack of z-index layers. Easing is hard-coded as ease on every transition — the spec doesn’t expose a custom-curve token because every callsite that wants something more expressive (the gradient shimmer, the pulse rings, the blob drifts) defines its own keyframe rather than tweaking a global. For the full motion catalogue (named keyframes, hover lifts, scroll-triggered entry) see Animations.
Transitions
--transition-fast
150 ms ease
--transition-base
250 ms ease
--transition-slow
400 ms ease
fast for hover colour swaps and underline accents. base for the skip-link reveal, the dropdown panel fade, and most state changes. slow for the staggered fade-in on the contact page and any decorative scroll-triggered entry. The demo bars above honour prefers-reduced-motion and freeze when set.
Z-index layers
A four-step stack. Treat the named layer as the contract — never write a raw z-index value in component CSS, even for “just one notch above the header”.
--z-background
-1
--z-content
1
--z-header
100
--z-overlay
200
--z-modal
300