Foundations

Color

Six oklch ramps × eleven steps, sitting under a semantic layer that components reference by name. Brand sits at primary 500. Status hues sit 38°+ apart in hue space so they read as distinct signals.

01Primitive palettes

The raw scales. Hex on the surface for design-tool fluency, oklch in the CSS for perceptually even ramps. Hover any swatch for the full triple — oklch, hex, token.

Primary

hue 262°

Confident modern blue. Brand #1464FF = oklch(0.562 0.241 262) lives at step 500. Slightly more saturated than the status palettes because brand earns extra visual prominence.

50

#e1efff

--primary-50

100

#b7d6ff

--primary-100

200

#8dbcff

--primary-200

300

#63a0ff

--primary-300

400

#3a82ff

--primary-400

500Brand

#1464ff

--primary-500

600

#004be1

--primary-600

700

#0037b7

--primary-700

800

#00278a

--primary-800

900

#00185e

--primary-900

950

#000b35

--primary-950

Neutral

hue 0°

shadcn / Tailwind v4 default neutral. Pure gray (chroma 0, no hue tilt). The only gray in the system.

50

#fafafa

--neutral-50

75

#f7f7f7

--neutral-75

100

#f5f5f5

--neutral-100

150

#ededed

--neutral-150

200

#e5e5e5

--neutral-200

250

#dcdcdc

--neutral-250

300

#d4d4d4

--neutral-300

400

#a1a1a1

--neutral-400

500

#737373

--neutral-500

600

#525252

--neutral-600

700

#404040

--neutral-700

800

#262626

--neutral-800

850

#1e1e1e

--neutral-850

900

#171717

--neutral-900

950

#0a0a0a

--neutral-950

Error

hue 22°

Destructive actions, error states, validation failures. Warm crimson — anchored at error-50 (#FAEEEE, container bg) and error-700 (#8E3235, ink). Reads serious, not alarming.

50

#faeeed

--error-50

100

#fed6d4

--error-100

200

#fcb3b0

--error-200

300

#f58e8b

--error-300

400

#df6465

--error-400

500

#c33d43

--error-500

600

#a8353a

--error-600

700

#8e3235

--error-700

800

#682224

--error-800

900

#441415

--error-900

950

#260909

--error-950

Success

hue 170°

Confirmation, positive state, completed actions. Teal-leaning forest green — anchored at success-50 (#E8F4F0, container bg) and success-700 (#256652, ink). Softer chroma than the status default so it reads calm next to UI text.

50

#e8f4ef

--success-50

100

#d0e8de

--success-100

200

#add3c4

--success-200

300

#8bbeab

--success-300

400

#61a18b

--success-400

500

#38856d

--success-500

600

#2d755f

--success-600

700

#256652

--success-700

800

#174a3b

--success-800

900

#0d3025

--success-900

950

#061913

--success-950

Warning

hue 65°

Caution. Amber/honey that drifts from warm yellow (78°) at the light end to deeper orange (60°) at the dark end — yellow's natural perceptual shift toward orange as lightness drops. Anchored at warning-50 (#FFF6E7, container bg) and warning-700 (#AB6625, ink).

50

#fff6e7

--warning-50

100

#fce8cf

--warning-100

200

#f7cda1

--warning-200

300

#f1b277

--warning-300

400

#d99351

--warning-400

500

#bf7a39

--warning-500

600

#b67030

--warning-600

700

#ab6624

--warning-700

800

#844f1e

--warning-800

900

#583310

--warning-900

950

#331b06

--warning-950

Info

hue 238°

Informational ocean blue. Anchored at info-50 (#F0F9FF, container bg) and info-700 (#024C6F, ink). Reads informational without competing with the brand primary's vivid signal.

50

#f0f9ff

--info-50

100

#dbedf8

--info-100

200

#b9d9ef

--info-200

300

#92c0de

--info-300

400

#65a2c8

--info-400

500

#2c83b3

--info-500

600

#166792

--info-600

700

#024c6f

--info-700

800

#00344f

--info-800

900

#001f31

--info-900

950

#000d18

--info-950

Purple

hue 300°

Editorial / non-status categorical use — premium tags, editorial labels, categorical chips that aren't alarms. Hue 300 (violet). Anchored at purple-50 (#F5F2F9, container bg) and purple-700 (#5B4091, ink).

50

#f5f2f9

--purple-50

100

#e9e3f5

--purple-100

200

#d6caee

--purple-200

300

#bfaee6

--purple-300

400

#a38cd7

--purple-400

500

#8366c3

--purple-500

600

#6e52aa

--purple-600

700

#5b4091

--purple-700

800

#422d6b

--purple-800

900

#2b1c48

--purple-900

950

#140b26

--purple-950

Denim

hue 266°

Softer, more muted blue than the brand primary (#1464FF). Use when blue is wanted but should feel calmer / less alarming — secondary CTAs, info chips, editorial labels. Anchored at denim-50 (#EEF2FB) and denim-700 (#4B72D9).

50

#eef2fb

--denim-50

100

#dde5f6

--denim-100

200

#c2d1f3

--denim-200

300

#9fb8f0

--denim-300

400

#81a1eb

--denim-400

500

#6a8ee8

--denim-500

600

#5a80e3

--denim-600

700

#4b72d9

--denim-700

800

#3755a6

--denim-800

900

#203365

--denim-900

950

#0c1731

--denim-950

Sage

hue 139°

Muted natural green, distinct from success's teal forest. Use for editorial/categorical green that reads organic, not status. Anchored at sage-50 (#E9F8E5) and sage-700 (#2A531E).

50

#e9f8e5

--sage-50

100

#d3e9cd

--sage-100

200

#b7d5af

--sage-200

300

#99bd8f

--sage-300

400

#779f6c

--sage-400

500

#558049

--sage-500

600

#436d37

--sage-600

700

#2a531e

--sage-700

800

#1a3911

--sage-800

900

#0e2308

--sage-900

950

#061103

--sage-950

Pink

hue 348°

Warm berry/rose pink. Hue 348 — dusty rose register, NOT cotton-candy sugar. Use for editorial chips, fresh signals, or playful categorical labels where a grounded berry pink fits better than the airy pastel of cotton candy.

50

#fbeef4

--pink-50

100

#f5dde8

--pink-100

200

#eec3d7

--pink-200

300

#e1a1c1

--pink-300

400

#d07aa7

--pink-400

500

#bb528d

--pink-500

600

#a8427c

--pink-600

700

#99366f

--pink-700

800

#6e224f

--pink-800

900

#461431

--pink-900

950

#260819

--pink-950

Cotton Candy

hue 354°

Pastel bubblegum pink. Hue 354 (closer to pure pink than berry pink's 348). Pushed LIGHTER than pink at every step — reads as confectionery / airy / sugar rather than dusty rose. Use for playful, brand-bright accents where pink would feel too grounded.

50

#fef5f8

--cottoncandy-50

100

#fee7ef

--cottoncandy-100

200

#fdcddf

--cottoncandy-200

300

#f8a9c8

--cottoncandy-300

400

#f085b2

--cottoncandy-400

500

#e0609b

--cottoncandy-500

600

#c14a82

--cottoncandy-600

700

#a13c6c

--cottoncandy-700

800

#76294d

--cottoncandy-800

900

#4b1a31

--cottoncandy-900

950

#280b19

--cottoncandy-950

Orange

hue 44°

Burnt warm orange, distinct from warning's amber. Use for editorial categorical orange (energy, fresh, beta features) — no alarm meaning.

50

#fff1e7

--orange-50

100

#fbdecd

--orange-100

200

#f8c4a9

--orange-200

300

#eda480

--orange-300

400

#d7825b

--orange-400

500

#bd6238

--orange-500

600

#ae5429

--orange-600

700

#a24a1f

--orange-700

800

#74310e

--orange-800

900

#4a1e08

--orange-900

950

#280d03

--orange-950

Teal

hue 195°

Clean cyan-teal. Fills the gap between success (forest green) and info (sky cyan). Use for fresh, cool accents and data-vis emphasis.

50

#e5f3f2

--teal-50

100

#cbe8e7

--teal-100

200

#a4dad9

--teal-200

300

#73c5c4

--teal-300

400

#3badad

--teal-400

500

#009494

--teal-500

600

#007e7f

--teal-600

700

#006868

--teal-700

800

#004a4b

--teal-800

900

#003030

--teal-900

950

#001616

--teal-950

Lime

hue 125°

Vivid lime-green. Hue pulled from yellow-green (110) to true lime (125) so it reads sharper / more citrus. Bright signal of newness / growth, distinct from sage's muted natural and warning's amber.

50

#f1f9e5

--lime-50

100

#deefc3

--lime-100

200

#c5e292

--lime-200

300

#a7cc60

--lime-300

400

#8db337

--lime-400

500

#779b1e

--lime-500

600

#61800d

--lime-600

700

#4d670a

--lime-700

800

#354704

--lime-800

900

#202d03

--lime-900

950

#0d1500

--lime-950

Magenta

hue 330°

Vivid berry. Editorial emphasis / marketing use. Sits between purple's violet and pink's rose.

50

#f7edf6

--magenta-50

100

#eddbeb

--magenta-100

200

#e3bfdf

--magenta-200

300

#d59dd0

--magenta-300

400

#c176bb

--magenta-400

500

#aa51a4

--magenta-500

600

#93408e

--magenta-600

700

#7e3179

--magenta-700

800

#5b1f58

--magenta-800

900

#3b1238

--magenta-900

950

#1d061c

--magenta-950

Mint

hue 180°

Fresh seafoam green. Hue 180 — fills the gap between success (170, forest) and teal (195, cyan-teal). Reads clean / cool / fresh / sub-zero, providing opposite-side balance to the system's many warm tones. For 'available' / 'fresh' / 'new-listing' categorical use.

50

#e8f8f5

--mint-50

100

#c7eee6

--mint-100

200

#9aded0

--mint-200

300

#61c8b5

--mint-300

400

#1aae99

--mint-400

500

#00937f

--mint-500

600

#007d6a

--mint-600

700

#006455

--mint-700

800

#00473b

--mint-800

900

#002c24

--mint-900

950

#00140f

--mint-950

Slate

hue 250°

Cool blue-gray with very low chroma. Corporate secondary tone — distinct from neutral's pure gray when you want a slightly cool wash without crossing into denim's blue.

50

#edf1f6

--slate-50

100

#dbe2e9

--slate-100

200

#c4cfdb

--slate-200

300

#a3b3c4

--slate-300

400

#7f93a9

--slate-400

500

#5f7790

--slate-500

600

#4d6379

--slate-600

700

#3c4f62

--slate-700

800

#2a3847

--slate-800

900

#18212c

--slate-900

950

#090f15

--slate-950

Mustard

hue 80°

Earthy desaturated yellow. Sits between warning (65) and lime (110). Vintage / editorial yellow alternative — calm, never alarmed.

50

#f9f3e6

--mustard-50

100

#f1e3c9

--mustard-100

200

#e7cc9b

--mustard-200

300

#d5ae67

--mustard-300

400

#bd8e35

--mustard-400

500

#a17000

--mustard-500

600

#8b5e00

--mustard-600

700

#734b00

--mustard-700

800

#513400

--mustard-800

900

#342000

--mustard-900

950

#180d00

--mustard-950

Deep Violet

hue 280°

Deep Violet — pushed DARKER overall, hue 280. Every step shifts down in L vs a normal violet: 50 starts at #e9ebfe (already darker than other -50s), 500 lands at #4e3ad2 with peak chroma 0.220 (most saturated in the system), and 700 sits at #29157d — substantially deeper than purple's #5b4091. The whole ramp reads as a 'deep' statement palette, never lavender. Use for hero / premium / ultra-category emphasis.

50

#e9ebfe

--violet-50

100

#d3d8fd

--violet-100

200

#b3b9fc

--violet-200

300

#8f93fb

--violet-300

400

#6c68ea

--violet-400

500

#4e3ad2

--violet-500

600

#3a24a8

--violet-600

700

#29157d

--violet-700

800

#180755

--violet-800

900

#090130

--violet-900

950

#020010

--violet-950

Crimson

hue 12°

Deep wine red. Hue 12 — distinct from error's signal red (22) by being darker, more vinous. For premium-intensity / elite-loss / high-stakes categorical markers where alarm-red feels too operational.

50

#f9eded

--crimson-50

100

#f5dadc

--crimson-100

200

#efbbc0

--crimson-200

300

#e5969f

--crimson-300

400

#d76c7c

--crimson-400

500

#bf3e59

--crimson-500

600

#a22544

--crimson-600

700

#830b30

--crimson-700

800

#60001f

--crimson-800

900

#3d000f

--crimson-900

950

#1f0005

--crimson-950

Canary

hue 95°

Vivid lemon yellow. Hue 95 — sits between warning (65, amber) and lime (125, lime-green). Pure cheerful yellow signal distinct from mustard's earthy desaturated and warning's orange-leaning amber. For high-energy categorical, highlight, sunshine.

50

#fbf8e9

--canary-50

100

#f6eec6

--canary-100

200

#ebdc96

--canary-200

300

#dbc25c

--canary-300

400

#c7a706

--canary-400

500

#ae8c00

--canary-500

600

#937400

--canary-600

700

#775c00

--canary-700

800

#554000

--canary-800

900

#362700

--canary-900

950

#1a1200

--canary-950

Cobalt

hue 246°

Saturated industrial blue. Hue 246 — sits between info (238, ocean blue) and slate (250, low-chroma gray-blue). Peak chroma 0.215 at step 500. Pure vivid blue for engineering / infrastructure / technical-data categorical use — distinct from primary (262) by being purer blue, not violet-leaning.

50

#e2f0ff

--cobalt-50

100

#bee1ff

--cobalt-100

200

#8bc9ff

--cobalt-200

300

#44aafa

--cobalt-300

400

#0088ec

--cobalt-400

500

#0063d3

--cobalt-500

600

#004ab3

--cobalt-600

700

#00358e

--cobalt-700

800

#002367

--cobalt-800

900

#001241

--cobalt-900

950

#00041f

--cobalt-950

Cocoa

hue 55°

Warm brown earth tone. Hue 55 with low chroma so it reads brown (the only brown in the system). Fills the brown gap — for dormant / archived / neutral-warm categorical use where a chromatic neutral fits better than gray.

50

#f6efea

--cocoa-50

100

#ecdcd2

--cocoa-100

200

#ddc1af

--cocoa-200

300

#c7a087

--cocoa-300

400

#ad7f60

--cocoa-400

500

#936240

--cocoa-500

600

#7a4d2e

--cocoa-600

700

#633b1f

--cocoa-700

800

#472811

--cocoa-800

900

#2b1606

--cocoa-900

950

#150802

--cocoa-950

Emerald

hue 155°

Jewel green. Hue 155 — sits between sage (139, muted) and success (170, forest). Reads verified / premium / gem-tier — brighter and bluer than success's operational status green.

50

#e9f4ed

--emerald-50

100

#d2e8d9

--emerald-100

200

#abd7bb

--emerald-200

300

#7cc296

--emerald-300

400

#40a970

--emerald-400

500

#008e49

--emerald-500

600

#007537

--emerald-600

700

#005d28

--emerald-700

800

#004118

--emerald-800

900

#00260b

--emerald-900

950

#001004

--emerald-950

Sky

hue 215°

Airy cyan-blue. Hue 215 — sits between teal (195) and info (238). Reads fresh / live / current — modern atmospheric blue for active data, live signals, and time-sensitive categorical use.

50

#eaf6fa

--sky-50

100

#d1eaf1

--sky-100

200

#a9d9e5

--sky-200

300

#7cc2d4

--sky-300

400

#4aaac0

--sky-400

500

#0092ab

--sky-500

600

#007c93

--sky-600

700

#00667a

--sky-700

800

#004958

--sky-800

900

#002e38

--sky-900

950

#00151b

--sky-950

02Step usage by convention

Each step (50, 100, …, 950) has a conventional role. This isn't enforced by the code — it's the discipline that keeps the system feeling coherent across components.

50

Subtle background

Tinted backgrounds for alerts, soft chips, ghost-hover surfaces.

100

Muted surface

Secondary fill (`--secondary`), muted backgrounds, hover surfaces on neutral.

200

Hairline border

Tinted borders on subtle surfaces. Default `--border` on neutral.

300

Soft divider

Optional secondary border weight. Rarely the main role.

400

Pre-mid

Bridge step. Use sparingly — usually 300 or 500 reads better.

500

Brand / default fill

The solid color. Primary buttons, status icon fills, focus ring.

600

Hover

Hover state of step 500 (one notch darker on light, lifted on dark).

700

Active / ink

Pressed state. Also ink-on-subtle (text inside a tinted alert).

800

Dark border

Border on subtle surfaces in dark mode.

900

Surface (dark)

Card / popover surface in dark mode.

950

Background (dark)

Page background in dark mode. Foreground text on light bg.

03Anatomy of a status family

A status color isn't one value. It's a coordinated set — DEFAULT, -subtle, -border, -foreground, -ink — that composes into a complete alert / badge / chip. Built the same way for every status.

The composed alert

Profile updated

Your changes have been saved. They'll appear on your public profile in a minute or two.

What's wired to what

--success-subtle

Alert background

--success-border

Hairline around alert

--success

Icon fill

--success-foreground

Icon glyph

--success-ink

Title + body text

Every status family composes the same way. Swap success for error, warning, or info and the alert switches signal without a single layout change. That's the system doing its job.

04Light & dark

The same component, same tokens, two semantic remappings. Brand stays brand. Hover lifts in dark instead of darkening. Subtle backgrounds use color-mix at low alpha to keep tint readable on dark surfaces.

Light

CARD

Marcus Reed

Quarterback · 6'2" · LSU commit

Dark

CARD

Marcus Reed

Quarterback · 6'2" · LSU commit

05Do / don't

The structural rules. If everyone follows them, divergence becomes impossible rather than discouraged.

✓

Use semantic tokens (--primary, --success-subtle) in components, never primitives directly.

✓

Pair status families correctly — success-subtle bg + success-border border + success-ink text. Don't cross.

✓

Use --ring for every focus ring, regardless of variant. Brand-color focus is a system-wide cue.

✕

Hardcode hex values in component code. If you reach for one, the token is missing.

✕

Use a different gray ramp. Neutral is the only gray. No slate, no zinc, no parallel grays.

✕

Darken with opacity to fake a hover state. Use the -hover semantic token, which maps to a deliberate palette step.