Docs Interfaces & theming

Contrast & WCAG conformance

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.