Colour

Three 12-step scales in two modes, their step roles, and the contrast rules that govern them.

The palette is three scales — midnight, orange, and slate — each expressed as a 12-step ramp in a light and a dark variant. The step numbering follows the Radix convention, which assigns every step a role. Using a step outside its role is the single most common way to break the system.

Core colours

These are the named aliases most projects reach for first. They are shortcuts into the scales, not a separate palette.

  • Primary
    #1d3352
    Text, headings, primary surfaces
  • Primary Light
    #2b4d78
    Hover states, dark-mode primary
  • Primary Dark
    #132440
    Dark backgrounds, navbar, code blocks
  • Accent
    #E05232
    CTAs, highlights, active states
  • Accent Light
    #ea7558
    Accent hover on dark, syntax strings
  • Accent Dark
    #b84228
    Accent pressed state
  • Accent Solid
    #cc4528
    Fill for solid controls with white text (4.72:1)
  • Secondary
    #546a82
    Supporting text, borders

Step roles

Every scale uses the same twelve roles in the same order:

StepsRoleUsed for
1–2App and subtle backgroundsPage and section surfaces
3–5Element backgroundsComponent fills, hover, active
6–8BordersSubtle, default, and strong borders
9–10SolidSolid fills and their hover state
11–12TextLow-emphasis and high-emphasis text

Midnight

Midnight light · step 9 #1d3352
1 App bg
2 Subtle bg
3 Elem bg
4 Hover bg
5 Active bg
6 Subtle brd
7 Border
8 Strong brd
9 Solid bg
10 Solid hvr
11 Lo text
12 Hi text
Midnight dark · step 9 #1d3352
1 App bg
2 Subtle bg
3 Elem bg
4 Hover bg
5 Active bg
6 Subtle brd
7 Border
8 Strong brd
9 Solid bg
10 Solid hvr
11 Lo text
12 Hi text

Midnight is the primary. It carries structure, text, and the calm end of the system. Step 9 (#1d3352) is the brand primary and is identical in both modes.

Orange

Orange light · step 9 #E05232
1 App bg
2 Subtle bg
3 Elem bg
4 Hover bg
5 Active bg
6 Subtle brd
7 Border
8 Strong brd
9 Solid bg
10 Solid hvr
11 Lo text
12 Hi text
Orange dark · step 9 #E05232
1 App bg
2 Subtle bg
3 Elem bg
4 Hover bg
5 Active bg
6 Subtle brd
7 Border
8 Strong brd
9 Solid bg
10 Solid hvr
11 Lo text
12 Hi text

Orange is the accent. It marks the primary action, the active state, and little else. Step 9 (#E05232) is constant across modes.

Do

Use orange for the single most important action in a view, active navigation state, and focus emphasis.

Don't

Use orange for large background fills, body text, or more than one competing call to action on the same screen.

Slate

Slate light · step 9 #546a82
1 App bg
2 Subtle bg
3 Elem bg
4 Hover bg
5 Active bg
6 Subtle brd
7 Border
8 Strong brd
9 Solid bg
10 Solid hvr
11 Lo text
12 Hi text
Slate dark · step 9 #546a82
1 App bg
2 Subtle bg
3 Elem bg
4 Hover bg
5 Active bg
6 Subtle brd
7 Border
8 Strong brd
9 Solid bg
10 Solid hvr
11 Lo text
12 Hi text

Slate is the secondary — supporting text, borders, and neutral surfaces. Step 9 (#546a82) is the brand secondary and is constant across modes.

Contrast rules

  • Never use pure #000 or #fff as text. Use step 12 of the relevant scale: #142438 on light, #c5daf0 on dark.
  • Step 9 is constant across modes. The solid accent does not shift when the theme changes.
  • Body text targets 4.5:1, large text (≥24px, or ≥18.66px bold) targets 3:1.
  • Verify against the actual surface. A step that passes on the app background may fail on an elevated panel.

Where an identity colour cannot carry text

Being the brand colour does not make a value a legible background. White on orange-9 (#E05232) measures 3.87:1 — fine as a mark or a border, but below the floor for button labels. Rather than dilute the accent, the system adds a separate fill for that job:

TokenHexWith white text
--color-accent#E052323.87:1 — identity only, not for text
--color-accent-solid#cc45284.72:1 — solid controls
--color-accent-dark#b842285.46:1 — hover and pressed

The same principle produced the code-comment token: when no existing step can do the job accessibly, name a new one rather than misuse a step.

Semantic colours are mode-specific

The callout hues are tuned for dark text on tinted light backgrounds. Used as foregrounds on the dark app surface they fall below AA, so dark mode has its own set:

RoleLightDarkOn #0e1720
Success#2f7d65#6cc0903.65:1 → 8.24:1
Warning#8b6508#e0a92a3.41:1 → 8.50:1
Danger#a8261c#f08b802.55:1 → 7.49:1
Info#3a5a82#8aacc82.55:1 → 7.59:1

Dark mode

Both modes are equally supported. See Dark mode for the implementation rules — theme switching, persistence, image treatment, and the always-dark code surface.