Skip to content

Color tokens

The Signal Scarlet color design language — primitive OKLCH ramps, per-mode semantic tokens, and contrast-checked accents, all generated from one source.

Signal Scarlet is the color language: a monochrome graphite base lit by a single high-contrast scarlet accent, with an inverted "bone" light mode. Every color is a token authored in OKLCH — no component hardcodes a color, and the whole palette is generated from a single source (scripts/tokens.mjs) into both the app CSS and the installable registry, so they can never drift.

The signal-* token names map to the brand accent 熾火 Signal Scarlet (#EE343B) — the one loud color in an otherwise achromatic system.

The system has three tiers:

  1. Primitives — OKLCH ramps (50–950) per hue family.
  2. Semantic — per-mode aliases (--background, --primary, …) that point at primitive steps. Components only ever use these.
  3. Utilities — every token and ramp step is exposed to Tailwind as bg-*, text-*, border-*.

Dark is primary. Below, each semantic swatch is split light / dark so you can see how a single token resolves in both modes.

Surfaces & text

The neutral spine of the UI: backgrounds, surfaces, borders and text. These come from two fully achromatic graphite ramps — light bone and dark carbon — and flip between modes for contrast.

light / dark — each token resolves per mode.

--background

App background

--foreground

Primary text

--card

Card surface

--card-foreground

Text on cards

--popover

Raised / floating surface

--surface-2

Inset & control surface

--muted

Muted surface

--muted-foreground

Secondary / label text

--border

Hairline border

--border-strong

Emphasized border

--input

Input border

Primary & focus

The signature accent. --primary is Signal Scarlet (#EE343B) in both modes — the red is dark enough to read on the light "bone" surface, so no light-mode swap is needed. The focus --ring shares it, and --signal-spark (red-on-bone text and hover accents) deepens slightly in light mode for contrast.

--primary

Primary action — Signal Scarlet (both modes)

--primary-foreground

Text on primary

--ring

Focus ring

--signal-spark

Scarlet accent spark (icons, brackets, rules)

Accents

Status and category colors with shared hues across both modes. Each fill has a paired foreground token (--magenta-foreground, --success-foreground, …) chosen for legibility — the ratio shown on each chip is the measured WCAG contrast, and the build fails if any pair drops below AA (4.5:1).

destructive
bg-destructive5.39:1
magenta
bg-magenta5.08:1
cyan
bg-cyan11.56:1
warning
bg-warning10.41:1
success
bg-success10.26:1
info
bg-info6.63:1
special
bg-special5.20:1
destructive-spark/text
bg-destructive-spark/textL 6.54 / D 5.85
success-spark/text
bg-success-spark/textL 7.05 / D 8.64
warning-spark/text
bg-warning-spark/textL 7.00 / D 8.76
info-spark/text
bg-info-spark/textL 5.45 / D 5.58
cyan-spark/text
bg-cyan-spark/textL 6.64 / D 9.73
magenta-spark/text
bg-magenta-spark/textL 6.49 / D 5.76
special-spark/text
bg-special-spark/textL 6.38 / D 5.88
destructive-spark/card
bg-destructive-spark/cardL 7.86 / D 6.42
success-spark/card
bg-success-spark/cardL 8.47 / D 9.47
warning-spark/card
bg-warning-spark/cardL 8.41 / D 9.60
info-spark/card
bg-info-spark/cardL 6.55 / D 6.11
cyan-spark/card
bg-cyan-spark/cardL 7.98 / D 10.67
magenta-spark/card
bg-magenta-spark/cardL 7.79 / D 6.32
special-spark/card
bg-special-spark/cardL 7.67 / D 6.45
signal-spark/bg
bg-signal-spark/bgL 6.47 / D 4.85
border-field/surface-2
bg-border-field/surface-2L 4.91 / D 5.15

Primitive ramps

Every hue family as a full 50–950 OKLCH ramp. The design's signature values are pinned at their natural step (e.g. signal-400, magenta-500); the rest of each scale is generated for hover, active and subtle-background states. Use them directly when a semantic token isn't enough — e.g. bg-magenta-300 for a faint wash or border-cyan-700 for a darker edge.

signal
50
100
200
300
400
500
600
700
800
900
950
magenta
50
100
200
300
400
500
600
700
800
900
950
cyan
50
100
200
300
400
500
600
700
800
900
950
warning
50
100
200
300
400
500
600
700
800
900
950
success
50
100
200
300
400
500
600
700
800
900
950
info
50
100
200
300
400
500
600
700
800
900
950
special
50
100
200
300
400
500
600
700
800
900
950
destructive
50
100
200
300
400
500
600
700
800
900
950
bone
50
100
200
300
400
500
600
700
800
900
950
carbon
50
100
200
300
400
500
600
700
800
900
950

Usage

  • Never hardcode a color. Reach for a semantic utility first (bg-primary, text-muted-foreground, border-border-strong), then a ramp step (bg-success-200) when you need a specific tint.
  • Pair fills with their foreground. On an accent fill, use the matching text-*-foreground token so contrast stays correct.
  • To change the palette, edit scripts/tokens.mjs and run pnpm gen:tokens — the CSS, the registry, and this page all update together.

On this page