Every contractual token pairing, the WCAG 2.1 level it is held to,
and its measured sRGB ratio per theme. Generated from the resolved token
model (tokens/resolved.json) so it cannot drift from the palette, and
gated: npm run check fails if any pairing drops below its floor.
Guaranteed level
Body / UI text pairings are guaranteed WCAG 2.1 AA — 4.5:1
(1.4.3). This covers --text, --text-soft, --text-dim,
--accent-text, neutral text on soft accent-tint components, and the
primary-button label.
Non-text UI (focus ring, accent fill, status colour) is guaranteed
3:1 (1.4.11 non-text contrast / the large-text bar). These are
deliberately not held to 4.5:1 — a focus
ring is a UI boundary, not body copy, and WCAG agrees.
Hairlines (--line, --line-strong) are a deliberate identity
choice and are reported but not gated: WCAG 1.4.11 exempts
decorative borders that are not the sole identifier of a control. Where
a boundary must be perceivable, the forced-colors /
data-contrast="high" paths re-assert it (see
theming.md). The low hairline ratio is published here on
purpose — hiding it would defeat the point of a gate.
AAA (7:1) is not guaranteed; the high-contrast preset
(data-contrast="high" / prefers-contrast: more) raises ratios
further but is out of scope for this gated baseline.
Translucent foregrounds (soft fills) are alpha-flattened over their
background before measuring. When a translucent background is a component
tint, the table names the neutral base it is composited over.
Overall: all contractual pairings meet their floor ✅.
Light theme
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
17.98:1
Lc 99.2
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
19.80:1
Lc 105.8
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
16.74:1
Lc 94.5
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.16:1
Lc 91.4
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
12.29:1
Lc 98.1
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
10.39:1
Lc 86.7
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
5.09:1
Lc 71.4
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
5.60:1
Lc 78.0
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
4.74:1
Lc 66.7
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
6.32:1
Lc 75.4
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
6.96:1
Lc 82.1
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
8.88:1
Lc 77.0
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
5.91:1
Lc 71.0
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
6.31:1
Lc 75.3
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
5.18:1
Lc 78.9
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
5.18:1
Lc 78.9
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
4.71:1
Lc 66.8
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
5.18:1
Lc 73.5
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
4.71:1
Lc 66.8
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
5.04:1
Lc 74.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
5.60:1
Lc 77.8
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
6.21:1
Lc 78.9
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
5.77:1
Lc 78.3
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
5.09:1
Lc 71.4
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
5.60:1
Lc 78.0
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.39:1
Lc 47.1
ℹ️ not gated
Dark theme
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
15.01:1
Lc 91.1
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
13.65:1
Lc 90.1
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
12.44:1
Lc 88.9
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.20:1
Lc 72.7
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
10.19:1
Lc 71.7
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
9.28:1
Lc 70.6
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
7.16:1
Lc 50.3
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
6.52:1
Lc 49.3
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
5.94:1
Lc 48.1
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
6.42:1
Lc 46.6
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
5.84:1
Lc 45.6
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
8.05:1
Lc 68.4
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
2.42:1
Lc 42.2
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
2.63:1
Lc 47.4
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
5.95:1
Lc 42.9
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
5.95:1
Lc 42.9
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
5.31:1
Lc 40.0
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
4.83:1
Lc 39.0
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
5.31:1
Lc 40.0
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
7.58:1
Lc 56.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
9.29:1
Lc 66.6
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
5.23:1
Lc 41.5
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
7.33:1
Lc 54.8
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
7.16:1
Lc 50.3
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
6.52:1
Lc 49.3
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.29:1
Lc 14.5
ℹ️ not gated
Display colorways (skins)
The opt-in data-bronto-skin colorways (@ponchia/ui/css/skins.css,
authored in tokens/skins.js) re-point the one accent to a different single
hue. Because a shipped colorway is part of the framework — not an arbitrary
consumer re-brand — its accent is gated to the same floors as the core:
the primary-button label, accent-as-text, and the focus ring/accent fill. Only
the accent-touching pairings are shown (a skin leaves the canvas and status
palette untouched). Accents are authored in OKLCH; --accent-text is the
color-mix-derived --accent-strong, exactly as in the core palette.
Amber CRT — light
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
17.97:1
Lc 99.0
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
19.84:1
Lc 105.8
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
16.77:1
Lc 94.4
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.20:1
Lc 91.3
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
12.37:1
Lc 98.1
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
10.45:1
Lc 86.8
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
5.11:1
Lc 71.4
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
5.64:1
Lc 78.2
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
4.77:1
Lc 66.9
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
6.73:1
Lc 78.7
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
7.44:1
Lc 85.6
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
9.19:1
Lc 78.7
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
6.48:1
Lc 76.1
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
6.85:1
Lc 79.9
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
5.66:1
Lc 83.3
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
5.66:1
Lc 83.3
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
5.13:1
Lc 71.2
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
5.66:1
Lc 78.0
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
5.13:1
Lc 71.2
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
5.04:1
Lc 74.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
5.60:1
Lc 77.8
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
6.21:1
Lc 78.9
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
5.77:1
Lc 78.3
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
5.07:1
Lc 71.2
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
5.60:1
Lc 78.0
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.41:1
Lc 47.4
ℹ️ not gated
Amber CRT — dark
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
15.01:1
Lc 91.0
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
13.64:1
Lc 90.0
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
12.43:1
Lc 88.9
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.19:1
Lc 72.7
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
10.18:1
Lc 71.7
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
9.27:1
Lc 70.5
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
7.16:1
Lc 50.2
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
6.51:1
Lc 49.2
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
5.93:1
Lc 48.1
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
11.84:1
Lc 76.1
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
10.77:1
Lc 75.1
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
6.82:1
Lc 65.4
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
1.46:1
Lc 20.8
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
1.51:1
Lc 23.2
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
11.88:1
Lc 71.6
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
11.88:1
Lc 71.6
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
10.60:1
Lc 69.8
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
9.64:1
Lc 68.9
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
10.60:1
Lc 69.8
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
7.58:1
Lc 56.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
9.29:1
Lc 66.6
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
5.23:1
Lc 41.5
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
7.33:1
Lc 54.8
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
7.17:1
Lc 50.3
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
6.52:1
Lc 49.3
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.28:1
Lc 14.5
ℹ️ not gated
E-ink — light
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
17.98:1
Lc 99.2
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
19.79:1
Lc 105.8
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
16.73:1
Lc 94.5
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.16:1
Lc 91.4
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
12.29:1
Lc 98.0
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
10.39:1
Lc 86.7
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
5.09:1
Lc 71.4
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
5.61:1
Lc 78.0
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
4.74:1
Lc 66.7
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
12.23:1
Lc 93.3
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
13.47:1
Lc 99.9
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
8.78:1
Lc 76.3
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
11.31:1
Lc 88.2
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
12.15:1
Lc 92.8
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
11.74:1
Lc 100.6
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
11.74:1
Lc 100.6
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
10.66:1
Lc 90.4
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
11.74:1
Lc 97.0
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
10.66:1
Lc 90.4
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
5.04:1
Lc 74.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
5.60:1
Lc 77.8
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
6.21:1
Lc 78.9
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
5.77:1
Lc 78.3
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
5.09:1
Lc 71.4
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
5.60:1
Lc 78.0
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.39:1
Lc 47.1
ℹ️ not gated
E-ink — dark
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
15.02:1
Lc 91.1
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
13.66:1
Lc 90.1
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
12.45:1
Lc 89.0
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.20:1
Lc 72.8
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
10.19:1
Lc 71.8
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
9.29:1
Lc 70.6
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
7.17:1
Lc 50.3
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
6.52:1
Lc 49.3
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
5.94:1
Lc 48.2
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
12.72:1
Lc 80.3
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
11.57:1
Lc 79.3
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
6.67:1
Lc 65.0
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
1.38:1
Lc 18.0
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
1.42:1
Lc 19.9
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
12.86:1
Lc 75.6
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
12.86:1
Lc 75.6
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
11.47:1
Lc 74.1
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
10.44:1
Lc 73.1
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
11.47:1
Lc 74.1
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
7.58:1
Lc 56.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
9.29:1
Lc 66.6
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
5.23:1
Lc 41.5
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
7.33:1
Lc 54.8
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
7.16:1
Lc 50.3
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
6.52:1
Lc 49.3
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.29:1
Lc 14.6
ℹ️ not gated
Phosphor Green — light
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
18.02:1
Lc 99.5
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
19.72:1
Lc 105.8
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
16.67:1
Lc 94.4
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.10:1
Lc 91.5
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
12.14:1
Lc 97.7
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
10.26:1
Lc 86.4
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
5.06:1
Lc 71.4
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
5.53:1
Lc 77.7
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
4.68:1
Lc 66.3
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
6.26:1
Lc 77.1
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
6.85:1
Lc 83.3
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
9.05:1
Lc 78.5
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
5.98:1
Lc 74.1
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
6.32:1
Lc 77.7
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
5.19:1
Lc 80.7
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
5.19:1
Lc 80.7
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
4.74:1
Lc 69.1
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
5.19:1
Lc 75.3
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
4.74:1
Lc 69.1
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
5.04:1
Lc 74.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
5.60:1
Lc 77.8
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
6.21:1
Lc 78.9
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
5.77:1
Lc 78.3
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
5.12:1
Lc 71.8
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
5.60:1
Lc 78.0
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.35:1
Lc 46.4
ℹ️ not gated
Phosphor Green — dark
Foreground
Background
Role
Held to
Ratio
APCA (advisory)
Verdict
--text
--bg
Body text on page background
AA text (4.5:1)
15.11:1
Lc 91.8
✅ pass
--text
--surface
Body text on a card/panel
AA text (4.5:1)
13.80:1
Lc 90.8
✅ pass
--text
--surface-muted
Body text on a muted panel
AA text (4.5:1)
12.57:1
Lc 89.6
✅ pass
--text-soft
--bg
Secondary text on page background
AA text (4.5:1)
11.28:1
Lc 73.3
✅ pass
--text-soft
--surface
Secondary text on a card
AA text (4.5:1)
10.30:1
Lc 72.4
✅ pass
--text-soft
--surface-muted
Secondary text on a muted panel
AA text (4.5:1)
9.38:1
Lc 71.2
✅ pass
--text-dim
--bg
Dim/meta text on page background
AA text (4.5:1)
7.22:1
Lc 50.8
✅ pass
--text-dim
--surface
Dim/meta text on a card
AA text (4.5:1)
6.60:1
Lc 49.8
✅ pass
--text-dim
--surface-muted
Dim/meta text on a muted panel
AA text (4.5:1)
6.01:1
Lc 48.7
✅ pass
--accent-text
--bg
Accent text on page background
AA text (4.5:1)
13.13:1
Lc 82.8
✅ pass
--accent-text
--surface
Accent text on a card
AA text (4.5:1)
11.99:1
Lc 81.8
✅ pass
--text-soft
--accent-soft over --surface-muted
Neutral tag/badge text on an accent tint
AA text (4.5:1)
6.74:1
Lc 65.6
✅ pass
--accent-text
--accent-soft
Accent text on an accent tint
Advisory (translucent tint — not gated)
1.33:1
Lc 15.3
ℹ️ not gated
--accent-text
--bg-accent
Accent text on an accent-tinted surface
Advisory (translucent tint — not gated)
1.37:1
Lc 17.3
ℹ️ not gated
--button-text
--accent
Label on the primary button
AA text (4.5:1)
13.75:1
Lc 79.7
✅ pass
--on-accent
--accent
Ink on an accent fill
AA text (4.5:1)
13.75:1
Lc 79.7
✅ pass
--focus-ring
--bg
Focus ring vs page background
UI / large (3:1)
12.22:1
Lc 78.5
✅ pass
--focus-ring
--surface
Focus ring vs a card
UI / large (3:1)
11.16:1
Lc 77.5
✅ pass
--accent
--bg
Accent fill vs page background
UI / large (3:1)
12.22:1
Lc 78.5
✅ pass
--success
--surface
Success indicator vs a card
UI / large (3:1)
7.58:1
Lc 56.6
✅ pass
--warning
--surface
Warning indicator vs a card
UI / large (3:1)
9.29:1
Lc 66.6
✅ pass
--danger
--surface
Danger indicator vs a card
UI / large (3:1)
5.23:1
Lc 41.5
✅ pass
--info
--surface
Info indicator vs a card
UI / large (3:1)
7.33:1
Lc 54.8
✅ pass
--edge
--bg
Relationship line vs page background
UI / large (3:1)
7.14:1
Lc 50.2
✅ pass
--edge
--surface
Relationship line vs a card
UI / large (3:1)
6.52:1
Lc 49.3
✅ pass
--line-strong
--surface
Strong hairline vs a card
Decorative (1.4.11-exempt)
2.33:1
Lc 15.1
ℹ️ not gated
Data-viz palette (advisory)
The opt-in Tier-4 categorical palette (@ponchia/ui/css/dataviz.css, authored
in tokens/charts.js) is gated differently: each slot sits inside the theme's
OKLCH lightness band and above the chroma floor, and adjacent slots stay apart
under simulated protanopia/deuteranopia and in normal vision (check:charts,
OKLab ΔE). Colour is never the sole signal — each series ships a matching
--chart-pattern-* dot-matrix fill. So the WCAG ratios below are advisory
(a chart fill is not body text); for thin lines, points or text use the slot's
--cat-N-ink, which check:charts holds to 4.5:1. No slot is the accent.
Light theme — categorical vs --bg
Series
Colour
Ratio (advisory)
APCA (advisory)
1 (accent)
#2a78d6
4.01:1
Lc 63.5
2
#eb6834
2.91:1
Lc 51.8
3
#1baf7a
2.56:1
Lc 46.9
4
#eda100
1.97:1
Lc 35.5
5
#e87ba4
2.44:1
Lc 45.2
6
#008300
4.49:1
Lc 66.8
7
#4a3aa7
7.77:1
Lc 82.3
8
#e34948
3.59:1
Lc 59.1
Dark theme — categorical vs --bg
Series
Colour
Ratio (advisory)
APCA (advisory)
1 (accent)
#3987e5
5.15:1
Lc 37.5
2
#d95926
4.82:1
Lc 35.6
3
#199e70
5.50:1
Lc 40.1
4
#c98500
6.10:1
Lc 43.9
5
#d55181
4.75:1
Lc 35.0
6
#008300
3.79:1
Lc 27.7
7
#9085e9
5.99:1
Lc 43.0
8
#e66767
5.80:1
Lc 42.2
Scope & caveats
This gates the framework token contract (core palette and every
shipped colorway), not arbitrary consumer re-brands. Re-accenting via
--accent yourself is your contrast obligation (see
Re-brand obligations); this table is the
guarantee for the shipped palettes and skins only.
Status colours (--success / --warning / --danger) are gated
as indicators (3:1). If you set status text as body copy on a
surface, verify 4.5:1 yourself or pair it with an icon/label.
The gated Ratio is sRGB WCAG 2.1 AA — the testable legal / axe-compatible
baseline the e2e suite also asserts. The APCA column (APCA-W3 0.1.9 Lc)
is advisory only: a perceptual cross-check that, unlike WCAG 2.1's
symmetric ratio, accounts for polarity and is the WCAG 3 candidate. It does
not gate the build while WCAG 3 is a Working Draft — use it to tune
quality, not to override the WCAG 2.1 floor. As a rough read, body text wants
Lc ≥ 75 and non-text/large ≥ 45–60.