SFDS color system — v2 (OKLCH · APCA-contracted)

Generated from the committed token pipeline (tokens/color-gen.mjs → dist/tokens.json) so this page can't drift. Every value solved in OKLCH: 12-step role scales per family per mode, chroma-cusp solids, APCA-bisected text steps, no purple. Signature sampled from the 😱 (face gold #d88507, crown blue #8fadde). Swatches show step · role · hex, with APCA badges on solids (9) and text (11/12).
The signature & the gain-grad
The one sanctioned gradient (gain-grad): symmetric gold→luminous→blue, mirroring the 😱. Fills / bars / accents only — never a text overlay.
gain-grad · light
gain-grad · dark
Primitive scales — 6 families × 12 steps × light/dark
Step-as-role (Radix-class): 1 bg · 2 surface · 3–5 component bg/hover/active · 6–8 border/focus · 9 solid (chroma cusp) · 10 solid-hover · 11–12 text (APCA-solved). Badges: solid-9 shows chosen fg (● black / ○ white) + APCA; text 11/12 show achieved/target. Dark isn't an invert — chroma reduced ~25%.
neutral near-achromatic · warm whisper
light
1
bg
#fefdfa
2
surface
#f7f6f3
3
ui-bg
#efedea
4
hover
#e5e4e1
5
active
#dbd9d7
6
bd-sub
#d0cfcc
7
bd
#c4c3c0
8
bd-str
#b7b6b3
9
solid
#646361
10
sol-hov
#595855
11
text-lo
#858381
60/60
12
text-hi
#3e3c3a
90/90
dark
1
bg
#080706
2
surface
#100f0d
3
ui-bg
#191816
4
hover
#22211f
5
active
#2d2c2a
6
bd-sub
#393836
7
bd
#494745
8
bd-str
#5c5b59
9
solid
#646361
10
sol-hov
#706e6c
11
text-lo
#b3b1af
60/60
12
text-hi
#e5e3e1
90/90
gold cusp L=0.779 C=0.173 H=66.7°
light
1
bg
#fffdfa
2
surface
#faf5f0
3
ui-bg
#f4ece4
4
hover
#ece2d8
5
active
#e4d7cb
6
bd-sub
#dcccbd
7
bd
#d3c0ac
8
bd-str
#cab198
9
solid
#ec9f3f
● 61
10
sol-hov
#db9439
11
text-lo
#a97941
60/60
12
text-hi
#563300
90/90
dark
1
bg
#080706
2
surface
#110e0c
3
ui-bg
#1b1713
4
hover
#26201b
5
active
#322b23
6
bd-sub
#3f362d
7
bd
#514539
8
bd-str
#685847
9
solid
#dea564
● 61
10
sol-hov
#e9b275
11
text-lo
#d1ab81
60/60
12
text-hi
#ffdebb
90/90
blue cusp L=0.597 C=0.221 H=258.0°
light
1
bg
#fcfdff
2
surface
#f2f6fe
3
ui-bg
#e7eefa
4
hover
#dbe5f3
5
active
#cfdbed
6
bd-sub
#c1d0e7
7
bd
#b2c5e1
8
bd-str
#9fb8db
9
solid
#4b91f0
○ 64
10
sol-hov
#4185de
11
text-lo
#4e85ca
60/60
12
text-hi
#0f3b6e
90/90
dark
1
bg
#060709
2
surface
#0d0f13
3
ui-bg
#14181e
4
hover
#1d222a
5
active
#262c37
6
bd-sub
#303846
7
bd
#3d485a
8
bd-str
#4c5c74
9
solid
#6093d9
○ 64
10
sol-hov
#6ea0e3
11
text-lo
#8bb5eb
60/60
12
text-hi
#d3e6ff
90/90
green cusp L=0.874 C=0.246 H=149.1°
light
1
bg
#fafffb
2
surface
#f0f9f2
3
ui-bg
#e5f1e7
4
hover
#d9e9dc
5
active
#cce0cf
6
bd-sub
#bed7c1
7
bd
#aecdb2
8
bd-str
#9bc29f
9
solid
#28fe6c
● 87
10
sol-hov
#2fef64
11
text-lo
#3f954c
60/60
12
text-hi
#004611
90/90
dark
1
bg
#060806
2
surface
#0c100d
3
ui-bg
#131a14
4
hover
#1b241d
5
active
#243026
6
bd-sub
#2d3c30
7
bd
#3a4d3d
8
bd-str
#49634c
9
solid
#74f68c
● 86
10
sol-hov
#95ffa3
11
text-lo
#82bf88
60/60
12
text-hi
#bef1c0
90/90
amber cusp L=0.885 C=0.182 H=95.0°
light
1
bg
#fefdf9
2
surface
#f8f6ef
3
ui-bg
#f1ede3
4
hover
#e8e4d7
5
active
#dfdac9
6
bd-sub
#d5cfba
7
bd
#cac4aa
8
bd-str
#bfb694
9
solid
#fdd704
● 84
10
sol-hov
#edcb0c
11
text-lo
#938234
60/60
12
text-hi
#463c00
90/90
dark
1
bg
#080706
2
surface
#100f0c
3
ui-bg
#191812
4
hover
#24221a
5
active
#2f2c22
6
bd-sub
#3b382b
7
bd
#4c4837
8
bd-str
#615c45
9
solid
#f4d967
● 84
10
sol-hov
#ffe77c
11
text-lo
#beb27b
60/60
12
text-hi
#eee4b6
90/90
red cusp L=0.630 C=0.255 H=24.8°
light
1
bg
#fffcfc
2
surface
#fff3f2
3
ui-bg
#fbe9e7
4
hover
#f5dedc
5
active
#efd2cf
6
bd-sub
#e9c5c2
7
bd
#e3b7b3
8
bd-str
#dda6a0
9
solid
#ff0325
○ 70
10
sol-hov
#ea001c
11
text-lo
#cd6056
60/60
12
text-hi
#6c1c17
90/90
dark
1
bg
#090706
2
surface
#130d0d
3
ui-bg
#1e1515
4
hover
#2a1e1d
5
active
#382726
6
bd-sub
#473230
7
bd
#5b403d
8
bd-str
#75514d
9
solid
#e64c47
○ 70
10
sol-hov
#f05e55
11
text-lo
#f19a90
60/60
12
text-hi
#ffddd7
90/90
Semantic layer — app vs marketing, in components
Shared primitives; one alias differs. APP → blue accent · MARKETING → gold accent. Gold is always brand + gain/SOTA. Same roles, wired into real UI: primary button, link, bordered chip, gain badge, gain-grad bar, danger text, body/secondary on surface.
APP · light
A hyperlink examplestrong border
+10.2% vs SOTAgain-grad bardanger text sample
Primary text on surface. Secondary text on surface.
APP · dark
A hyperlink examplestrong border
+10.2% vs SOTAgain-grad bardanger text sample
Primary text on surface. Secondary text on surface.
MARKETING · light
A hyperlink examplestrong border
+10.2% vs SOTAgain-grad bardanger text sample
Primary text on surface. Secondary text on surface.
MARKETING · dark
A hyperlink examplestrong border
+10.2% vs SOTAgain-grad bardanger text sample
Primary text on surface. Secondary text on surface.
Data visualization
Categorical: 10 colorblind-aware hues, no purple, fixed order. 5-step ramps per hue for magnitude. Sequential = gold. Diverging = blue↔neutral↔gold ("below / above SOTA"), never through purple.
Categorical (light)
azure
green
vermillion
cyan
rose
olive
teal
brown
slate
wine
Categorical (dark)
azure
green
vermillion
cyan
rose
olive
teal
brown
slate
wine
5-step ramps (per hue)
azure
green
vermillion
cyan
rose
olive
teal
brown
slate
wine
Sequential & diverging
sequential (gold)
#ffead8
#e4c1a1
#c69a6f
#a7743b
#855100
#5a3500
#321c00
diverging (blue ↔ neutral ↔ gold)
#002f6d
#1c56a8
#5d84bf
#9ab1d3
#d9dee6
#c4aa91
#a47a4e
#7f4c00
#4a2a00
Alpha overlays
Neutral (black-on-light / white-on-dark) + per-theme accent tints at 5/10/20/40/60% — scrims, hovers, overlays.
neutral · light
neutral · dark
accent-app · light
accent-app · dark
accent-marketing · light
accent-marketing · dark
Contrast — APCA (WCAG-3) gate
✓ All 24 text-step contracts pass (step 11 ≥ Lc60, step 12 ≥ Lc90, per family × mode) · ✓ all 10 solid-9 foreground contracts pass · ✓ 0 values in the 280–330° purple band. The build refuses to emit tokens unless this gate is green.