Foundations / Colors

Colors.

Color in this system is semantic. Tokens describe the job a color performs rather than a specific hue, which keeps components stable while the theme shifts between light and dark.

How color behaves here

The palette is intentionally restrained. Most of the interface is built from neutrals, with a single pink accent carrying emphasis across navigation, headings, status markers, and actions.

That balance is already visible across the codebase: foreground handles the bulk of reading, muted foreground supports secondary copy, and primary is reserved for moments that need focus.

Source of truth

The live token values come from global CSS custom properties. Components should consume semantic classes and CSS variables, not raw color values.

Core roles

These are the roles that carry most of the interface. When a new component needs color, start with one of these before introducing anything more specific.

Background

--background

Default page surface for layouts and reading-heavy views.

Foreground

--foreground

Primary text color for headings, body copy, and high-emphasis content.

Primary

--primary

Deliberate accent for active states, highlights, and calls to action.

Muted

--muted / --muted-foreground

Secondary surfaces and supporting copy that should stay visually quiet.

Border

--border

Low-emphasis structure for separators, rails, and contained UI.

Card / Popover

--card / --popover

Elevated surfaces for temporary or grouped content.

Destructive

--destructive

Error messaging and destructive actions only.

Theme behavior

Each semantic token maps to a different OKLCH value in light and dark mode, but the role stays consistent. That means the component API does not change when the theme changes.

Light mode

background
oklch(0.98 0 0)
foreground
oklch(0.18 0 0)
primary
oklch(0.58 0.20 350)
mutedForeground
oklch(0.50 0 0)
border
oklch(0.92 0 0)

Dark mode

background
oklch(0.13 0 0)
foreground
oklch(0.96 0 0)
primary
oklch(0.74 0.20 350)
mutedForeground
oklch(0.66 0 0)
border
oklch(0.26 0 0)

Guidelines

  • Use semantic tokens instead of hard-coded OKLCH values in components.
  • Prefer border and spacing for hierarchy before adding stronger fills.
  • Keep primary sparse so emphasis stays meaningful.
  • Use muted foreground for metadata, helper copy, and descriptions rather than core reading content.
  • Let theme switching happen through tokens instead of branching component styles for light and dark mode.

In practice

Is this the default canvas?

Use background.

Should this read first?

Use foreground.

Does this need emphasis?

Use primary.

Is this supporting information?

Use muted foreground.

Is this only creating structure?

Use border.