Accessibility
Every token pair in the system, scored against WCAG 2.x at build time. Four combinations fail; all four are named here with the substitute to use instead.
- Pairs measured
- 86
- Pass AA body · 4.5:1
- 46
- Pass AA large · 3:1
- 52
- Pass AAA · 7:1
- 29
4 combinations in the palette do not meet their threshold. They are documented rather than removed, because they are already in circulation. A rule nobody knows they are breaking is not a rule.
Still failing
Stone is captioned as text and cannot be text
The Figma colour sheet labels Stone #AA9F8D "Muted text", and it has been used that way in decks and in early product screens.
Stone fails AA at every size, on every surface in the system. It is not a marginal miss. On Bone, the warm surface it most often appears over, it is less than half the required ratio. It stays in the palette as a decorative colour: rules, fills, illustration, texture. Never a glyph.
- Stone on Near-white 1002.54:1 AA fails AA-L fails AAA fails
- Stone on Bone2.03:1 AA fails AA-L fails AAA fails
- Stone on Sage2.06:1 AA fails AA-L fails AAA fails
- Near-white 700 on Near-white 1008.24:1 AA passes AA-L passes AAA passes
Use instead:
--haux-white-700on--haux-white-100· 8.24:1.Still failing
White on Orange 500 fails AA body
White text on an orange button is the default instinct, and it is what most of the early mockups do.
It misses AA body by more than a point. There are two fixes and both are in the token set already: keep the Orange 500 fill and set the label in Near-black, or keep the white label and step the fill to Orange 600. The first is the house style, because --on-accent resolves to Near-black 900 for exactly this reason.
- Near-white 100 on Orange 5003.47:1 AA fails AA-L passes AAA fails
- Near-black 900 on Orange 5005.72:1 AA passes AA-L passes AAA fails
Use instead:
--haux-black-900on--haux-orange-500· 5.72:1.Still failing
Orange 500 is not a text colour on light surfaces
The accent is the brand, so it gets reached for as a link colour and as a heading colour.
As text on Near-white it lands in the same place as white-on-orange: enough to be seen, not enough to be read. Orange 700 carries the same accent identity at more than twice the ratio, and is what --accent-text resolves to. Orange 500 remains correct as a fill, a rule, or a mark.
- Orange 500 on Near-white 1003.47:1 AA fails AA-L passes AAA fails
- Orange 700 on Near-white 1008.54:1 AA passes AA-L passes AAA passes
Use instead:
--haux-orange-700on--haux-white-100· 8.54:1.Still failing
Silver misses the 3:1 non-text threshold
Silver #AFAFAF is specified as the border colour, and --border resolved to it.
Borders and focus rings are held to 3:1 under WCAG 2.x §1.4.11, and Silver does not reach it on Near-white. This is the failure that audits miss, because contrast tooling looks at text. Silver stays as a decorative rule; anything a person has to locate (an input boundary, a focus ring) uses a darker step.
- Silver on Near-white 1002.14:1 3:1 non-text fails
- Near-white 500 on Near-white 1003.28:1 3:1 non-text passes
Use instead:
--haux-white-500on--haux-white-100· 3.28:1.
Every ink against every surface, in both themes. Computed at build time from the token values, so this table cannot disagree with the colour section.
- AAA · 7:1 and above
- AA body · 4.5:1
- AA large only · 3:1
- Below 3:1 · text prohibited
Light theme
Every ink the system offers, against every surface it can land on. Ratios are measured against Near-white 100, the actual value of --surface, not against pure white.
| Ink \ Surface | Near-white 100--surface | Cloud--surface-subtle | Sage--surface-raised | Bone--surface-warm | Near-black 900--surface-inverse | Orange 500--accent | Orange 600--accent-fill |
|---|---|---|---|---|---|---|---|
Near-black 900--ink | 19.87Near-black 900 on Near-white 100, 19.87:1, passes AAA | 16.94Near-black 900 on Cloud, 16.94:1, passes AAA | 16.09Near-black 900 on Sage, 16.09:1, passes AAA | 15.89Near-black 900 on Bone, 15.89:1, passes AAA | Same colour, not applicable | 5.72Near-black 900 on Orange 500, 5.72:1, passes AA body | 3.58Near-black 900 on Orange 600, 3.58:1, passes AA large text only |
Umber--ink-secondary | 7.46Umber on Near-white 100, 7.46:1, passes AAA | 6.36Umber on Cloud, 6.36:1, passes AA body | 6.04Umber on Sage, 6.04:1, passes AA body | 5.96Umber on Bone, 5.96:1, passes AA body | 2.66Umber on Near-black 900, 2.66:1, fails at every size | 2.15Umber on Orange 500, 2.15:1, fails at every size | 1.34Umber on Orange 600, 1.34:1, fails at every size |
Near-white 700--ink-muted | 8.24Near-white 700 on Near-white 100, 8.24:1, passes AAA | 7.03Near-white 700 on Cloud, 7.03:1, passes AAA | 6.68Near-white 700 on Sage, 6.68:1, passes AA body | 6.59Near-white 700 on Bone, 6.59:1, passes AA body | 2.41Near-white 700 on Near-black 900, 2.41:1, fails at every size | 2.37Near-white 700 on Orange 500, 2.37:1, fails at every size | 1.48Near-white 700 on Orange 600, 1.48:1, fails at every size |
| Stone | 2.54Stone on Near-white 100, 2.54:1, fails at every size | 2.17Stone on Cloud, 2.17:1, fails at every size | 2.06Stone on Sage, 2.06:1, fails at every size | 2.03Stone on Bone, 2.03:1, fails at every size | 7.82Stone on Near-black 900, 7.82:1, passes AAA | 1.37Stone on Orange 500, 1.37:1, fails at every size | 2.19Stone on Orange 600, 2.19:1, fails at every size |
Orange 500--accent | 3.47Orange 500 on Near-white 100, 3.47:1, passes AA large text only | 2.96Orange 500 on Cloud, 2.96:1, fails at every size | 2.81Orange 500 on Sage, 2.81:1, fails at every size | 2.78Orange 500 on Bone, 2.78:1, fails at every size | 5.72Orange 500 on Near-black 900, 5.72:1, passes AA body | Same colour, not applicable | 1.60Orange 500 on Orange 600, 1.60:1, fails at every size |
Orange 600--accent-fill | 5.56Orange 600 on Near-white 100, 5.56:1, passes AA body | 4.74Orange 600 on Cloud, 4.74:1, passes AA body | 4.50Orange 600 on Sage, 4.50:1, passes AA body | 4.44Orange 600 on Bone, 4.44:1, passes AA large text only | 3.58Orange 600 on Near-black 900, 3.58:1, passes AA large text only | 1.60Orange 600 on Orange 500, 1.60:1, fails at every size | Same colour, not applicable |
Orange 700--accent-text | 8.54Orange 700 on Near-white 100, 8.54:1, passes AAA | 7.28Orange 700 on Cloud, 7.28:1, passes AAA | 6.92Orange 700 on Sage, 6.92:1, passes AA body | 6.83Orange 700 on Bone, 6.83:1, passes AA body | 2.33Orange 700 on Near-black 900, 2.33:1, fails at every size | 2.46Orange 700 on Orange 500, 2.46:1, fails at every size | 1.54Orange 700 on Orange 600, 1.54:1, fails at every size |
Near-white 100--ink-inverse | Same colour, not applicable | 1.17Near-white 100 on Cloud, 1.17:1, fails at every size | 1.23Near-white 100 on Sage, 1.23:1, fails at every size | 1.25Near-white 100 on Bone, 1.25:1, fails at every size | 19.87Near-white 100 on Near-black 900, 19.87:1, passes AAA | 3.47Near-white 100 on Orange 500, 3.47:1, passes AA large text only | 5.56Near-white 100 on Orange 600, 5.56:1, passes AA body |
Dark theme
The derived dark token set. The accent moves from Orange 500 to Orange 400 here, which is the whole reason the dark theme needed its own audit rather than an assumption.
| Ink \ Surface | Near-black 900--surface | Near-white 900--surface-subtle | Near-black 800--surface-raised | Espresso--surface-warm | Orange 500--accent-fill | Orange 400--accent |
|---|---|---|---|---|---|---|
Near-white 100--ink | 19.87Near-white 100 on Near-black 900, 19.87:1, passes AAA | 18.26Near-white 100 on Near-white 900, 18.26:1, passes AAA | 15.69Near-white 100 on Near-black 800, 15.69:1, passes AAA | 12.61Near-white 100 on Espresso, 12.61:1, passes AAA | 3.47Near-white 100 on Orange 500, 3.47:1, passes AA large text only | 2.56Near-white 100 on Orange 400, 2.56:1, fails at every size |
Near-white 300--ink-secondary | 12.69Near-white 300 on Near-black 900, 12.69:1, passes AAA | 11.67Near-white 300 on Near-white 900, 11.67:1, passes AAA | 10.03Near-white 300 on Near-black 800, 10.03:1, passes AAA | 8.06Near-white 300 on Espresso, 8.06:1, passes AAA | 2.22Near-white 300 on Orange 500, 2.22:1, fails at every size | 1.63Near-white 300 on Orange 400, 1.63:1, fails at every size |
Near-white 400--ink-muted | 9.08Near-white 400 on Near-black 900, 9.08:1, passes AAA | 8.35Near-white 400 on Near-white 900, 8.35:1, passes AAA | 7.18Near-white 400 on Near-black 800, 7.18:1, passes AAA | 5.76Near-white 400 on Espresso, 5.76:1, passes AA body | 1.59Near-white 400 on Orange 500, 1.59:1, fails at every size | 1.17Near-white 400 on Orange 400, 1.17:1, fails at every size |
Orange 400--accent | 7.76Orange 400 on Near-black 900, 7.76:1, passes AAA | 7.13Orange 400 on Near-white 900, 7.13:1, passes AAA | 6.13Orange 400 on Near-black 800, 6.13:1, passes AA body | 4.93Orange 400 on Espresso, 4.93:1, passes AA body | 1.36Orange 400 on Orange 500, 1.36:1, fails at every size | Same colour, not applicable |
Orange 300--accent-text | 11.65Orange 300 on Near-black 900, 11.65:1, passes AAA | 10.71Orange 300 on Near-white 900, 10.71:1, passes AAA | 9.20Orange 300 on Near-black 800, 9.20:1, passes AAA | 7.39Orange 300 on Espresso, 7.39:1, passes AAA | 2.03Orange 300 on Orange 500, 2.03:1, fails at every size | 1.50Orange 300 on Orange 400, 1.50:1, fails at every size |
Near-black 900--ink-inverse | Same colour, not applicable | 1.09Near-black 900 on Near-white 900, 1.09:1, fails at every size | 1.27Near-black 900 on Near-black 800, 1.27:1, fails at every size | 1.58Near-black 900 on Espresso, 1.58:1, fails at every size | 5.72Near-black 900 on Orange 500, 5.72:1, passes AA body | 7.76Near-black 900 on Orange 400, 7.76:1, passes AAA |
Borders, focus rings and dividers are held to 3:1 under WCAG 2.x §1.4.11. This is the threshold that gets skipped, because contrast tooling measures text.
| Use | Pair | Ratio | 3:1 | Verdict |
|---|---|---|---|---|
| Input border · Silver on Near-white 100 | --haux-silver | 2.14:1 | 3:1 fails | Fails. Silver is a decorative rule only. Interactive borders use Near-white 500 or darker. |
| Substitute · Near-white 500 on Near-white 100 | --haux-white-500 | 3.28:1 | 3:1 passes | Passes the 3:1 non-text threshold. Use this for input borders and any boundary a person has to find. |
| Divider · Mist on Near-white 100 | --haux-mist | 1.44:1 | 3:1 fails | Below 3:1, and that is acceptable: a divider is decoration, not a control boundary. |
| Focus ring · Orange 600 on Near-white 100 | --haux-orange-600 | 5.56:1 | 3:1 passes | Passes. This is what --focus-ring resolves to in the light theme. |
| Focus ring · Orange 500 on Near-white 100 | --haux-orange-500 | 3.47:1 | 3:1 passes | Passes 3:1 by a margin thin enough to disappear on a poor display. Orange 600 is the specified ring. |
| Focus ring · Orange 300 on Near-black 900 | --haux-orange-300 | 11.65:1 | 3:1 passes | Passes. This is what --focus-ring resolves to in the dark theme. |
| Border · Near-black 700 on Near-black 900 | --haux-black-700 | 1.82:1 | 3:1 fails | Fails 3:1. Dark-theme control borders need Near-black 500 or lighter. |
| Substitute · Near-black 500 on Near-black 900 | --haux-black-500 | 4.62:1 | 3:1 passes | Passes. Use for interactive boundaries in the dark theme. |