Colour — semantic

The design language. This is what product code should reach for.

34 tokens — 34 house.

tokenlightdarkverdictresolves through
--content-alert#8537ad#c084fchouselight: --color-purple-500
dark: --color-purple-300
--content-default#203053#e5e5e5houselight: --color-gray-800
dark: --color-neutral-200
--content-error#c8223d#f87171houselight: --color-red-500
dark: --color-red-400d
--content-info#102984#60a5fahouselight: --color-azure-700
dark: --color-azure-350d
--content-muted#67789d#8b8b8bhouselight: --color-gray-600
dark: --color-neutral-500
--content-secondary#415377#a3a3a3houselight: --color-gray-700
dark: --color-neutral-400
--content-subtle#7a86a6#737373houselight: --color-gray-550
dark: --color-neutral-550
--content-success#175c41#4ade80houselight: --color-green-700
dark: --color-green-400d
--content-success-accent#29a575#4ade80houselight: --color-green-500
dark: --color-green-400d
--content-warning#845714#fbbf24houselight: --color-yellow-700
dark: --color-yellow-400d
--content-warning-accent#ec9c24#fbbf24houselight: --color-yellow-500
dark: --color-yellow-400d
--edge-default#d9dde7#383838houselight: --color-gray-200
dark: --color-neutral-750
--edge-error#edb8c1#701322houselight: --color-red-200
dark: --color-red-700
--edge-info#8ebffb#102984houselight: --color-azure-200
dark: --color-azure-700
--edge-muted#f5f7f9#252525houselight: --color-gray-100
dark: --color-neutral-825
--edge-success#bbe2d3#175c41houselight: --color-green-200
dark: --color-green-700
--edge-warning#f9dfb9#845714houselight: --color-yellow-200
dark: --color-yellow-700
--link#4a6ae8#60a5fahouselight: --color-azure-400
dark: --color-azure-350d
--link-hover#1b44da#4a6ae8houselight: --color-azure-500
dark: --color-azure-400
--span-background-jobs#5aba93#7ed4b0houselight: declared directly (theme-tokens.css:69)
dark: declared directly (theme-tokens.css:127)
--span-cache#67789e#97aaf2houselight: declared directly (theme-tokens.css:66)
dark: declared directly (theme-tokens.css:124)
--span-database-orm#eb84a6#f5b3cchouselight: declared directly (theme-tokens.css:65)
dark: declared directly (theme-tokens.css:123)
--span-http#177373#45c9b5houselight: declared directly (theme-tokens.css:67)
dark: declared directly (theme-tokens.css:125)
--span-others#711323#e18896houselight: declared directly (theme-tokens.css:70)
dark: declared directly (theme-tokens.css:128)
--span-templating#618ccc#91b8f0houselight: declared directly (theme-tokens.css:68)
dark: declared directly (theme-tokens.css:126)
--span-web-server#1b44da#7b9ff5houselight: declared directly (theme-tokens.css:64)
dark: declared directly (theme-tokens.css:122)
--surface-canvas#f5f7f9#141414houselight: --color-gray-100
dark: --color-neutral-950
--surface-default#ffffff#1e1e1ehouselight: --color-white
dark: --color-neutral-850
--surface-error#fbedef#440c15houselight: --color-red-100
dark: --color-red-800
--surface-highlight#eff3fa#141414houselight: --color-blue-100
dark: --color-azure-950
--surface-info#e4e9fc#0b1b56houselight: --color-azure-100
dark: --color-azure-800
--surface-raised#f5f7f9#141414houselight: --color-gray-100
dark: --color-neutral-950
--surface-success#eef8f4#0e3828houselight: --color-green-100
dark: --color-green-800
--surface-warning#fdf7ed#50350chouselight: --color-yellow-100
dark: --color-yellow-800

Contrast

These tables say which text and edge colours may sit on which surface, measured against WCAG 2.1. Every foreground is paired with every surface, so a row does not mean the product uses that pairing. It means the pairing is allowed.

Read a cell as the contrast ratio followed by the use it is good for:

verdictmeaning
AAApasses for any text, including at the stricter AAA level
AApasses for text of any size
large onlypasses only for text at least 24px, or at least 18.66px and bold
failsnot allowed for text
passesallowed for a boundary or focus indicator (non-text, 3:1)

Most text in the product is smaller than the large-text threshold, so treat "large only" as a fail unless the text is a heading at that size. WCAG exempts placeholder text and disabled controls from these floors, so a muted colour that fails here can still be correct for those.

The non-text floor applies only to a boundary a reader needs in order to find a control, such as the border of an input. A divider or a card outline that only decorates is exempt, so an edge that fails here is not wrong by itself. It is wrong when it is the only thing showing where a control is.

The ratios are computed from the resolved token values on every build. They cover the semantic tokens only. A primitive colour used directly, such as a grey border, is not in these tables.

Text on surfaces, light

13 × 8 pairings, light theme. Floor 4.5:1 for normal text, 3:1 for large text. 16 fail even as large text.

textsurface-canvassurface-defaultsurface-errorsurface-highlightsurface-infosurface-raisedsurface-successsurface-warning
content-alert6.21 AA6.67 AA5.86 AA5.99 AA5.51 AA6.21 AA6.15 AA6.26 AA
content-default12.15 AAA13.05 AAA11.47 AAA11.72 AAA10.78 AAA12.15 AAA12.03 AAA12.24 AAA
content-error5.21 AA5.59 AA4.92 AA5.02 AA4.62 AA5.21 AA5.16 AA5.25 AA
content-info11.69 AAA12.55 AAA11.03 AAA11.28 AAA10.38 AAA11.69 AAA11.58 AAA11.78 AAA
content-muted4.11 large only4.42 large only3.88 large only3.97 large only3.65 large only4.11 large only4.07 large only4.14 large only
content-secondary7.16 AAA7.69 AAA6.76 AA6.91 AA6.36 AA7.16 AAA7.09 AAA7.22 AAA
content-subtle3.37 large only3.62 large only3.18 large only3.26 large only2.99 fails3.37 large only3.34 large only3.40 large only
content-success7.39 AAA7.94 AAA6.98 AA7.13 AAA6.56 AA7.39 AAA7.32 AAA7.45 AAA
content-success-accent2.90 fails3.11 large only2.74 fails2.80 fails2.57 fails2.90 fails2.87 fails2.92 fails
content-warning5.82 AA6.26 AA5.50 AA5.62 AA5.17 AA5.82 AA5.77 AA5.87 AA
content-warning-accent2.09 fails2.24 fails1.97 fails2.01 fails1.85 fails2.09 fails2.07 fails2.10 fails
link4.32 large only4.64 AA4.08 large only4.17 large only3.84 large only4.32 large only4.28 large only4.36 large only
link-hover6.77 AA7.27 AAA6.39 AA6.53 AA6.01 AA6.77 AA6.71 AA6.82 AA

Text on surfaces, dark

13 × 8 pairings, dark theme. Floor 4.5:1 for normal text, 3:1 for large text. 4 fail even as large text.

textsurface-canvassurface-defaultsurface-errorsurface-highlightsurface-infosurface-raisedsurface-successsurface-warning
content-alert6.97 AA6.30 AA6.07 AA6.97 AA6.08 AA6.97 AA4.92 AA4.28 large only
content-default14.62 AAA13.23 AAA12.73 AAA14.62 AAA12.77 AAA14.62 AAA10.32 AAA8.98 AAA
content-error6.66 AA6.02 AA5.79 AA6.66 AA5.81 AA6.66 AA4.70 AA4.09 large only
content-info7.24 AAA6.55 AA6.30 AA7.24 AAA6.32 AA7.24 AAA5.11 AA4.45 large only
content-muted5.40 AA4.89 AA4.70 AA5.40 AA4.72 AA5.40 AA3.81 large only3.32 large only
content-secondary7.30 AAA6.60 AA6.35 AA7.30 AAA6.37 AA7.30 AAA5.15 AA4.48 large only
content-subtle3.88 large only3.51 large only3.38 large only3.88 large only3.39 large only3.88 large only2.74 fails2.38 fails
content-success10.57 AAA9.56 AAA9.20 AAA10.57 AAA9.23 AAA10.57 AAA7.46 AAA6.49 AA
content-success-accent10.57 AAA9.56 AAA9.20 AAA10.57 AAA9.23 AAA10.57 AAA7.46 AAA6.49 AA
content-warning11.03 AAA9.98 AAA9.60 AAA11.03 AAA9.63 AAA11.03 AAA7.78 AAA6.77 AA
content-warning-accent11.03 AAA9.98 AAA9.60 AAA11.03 AAA9.63 AAA11.03 AAA7.78 AAA6.77 AA
link7.24 AAA6.55 AA6.30 AA7.24 AAA6.32 AA7.24 AAA5.11 AA4.45 large only
link-hover3.96 large only3.58 large only3.45 large only3.96 large only3.46 large only3.96 large only2.79 fails2.43 fails

Edges on surfaces, light

6 × 8 pairings, light theme. Floor 3:1 for non-text. 48 fail.

non-textsurface-canvassurface-defaultsurface-errorsurface-highlightsurface-infosurface-raisedsurface-successsurface-warning
edge-default1.26 fails1.35 fails1.19 fails1.22 fails1.12 fails1.26 fails1.25 fails1.27 fails
edge-error1.59 fails1.71 fails1.50 fails1.54 fails1.41 fails1.59 fails1.58 fails1.61 fails
edge-info1.77 fails1.90 fails1.67 fails1.71 fails1.57 fails1.77 fails1.76 fails1.79 fails
edge-muted1.00 fails1.07 fails1.05 fails1.03 fails1.12 fails1.00 fails1.00 fails1.00 fails
edge-success1.30 fails1.40 fails1.23 fails1.26 fails1.16 fails1.30 fails1.29 fails1.31 fails
edge-warning1.20 fails1.28 fails1.13 fails1.15 fails1.06 fails1.20 fails1.18 fails1.21 fails

Edges on surfaces, dark

6 × 8 pairings, dark theme. Floor 3:1 for non-text. 48 fail.

non-textsurface-canvassurface-defaultsurface-errorsurface-highlightsurface-infosurface-raisedsurface-successsurface-warning
edge-default1.57 fails1.42 fails1.36 fails1.57 fails1.37 fails1.57 fails1.10 fails1.03 fails
edge-error1.58 fails1.43 fails1.37 fails1.58 fails1.38 fails1.58 fails1.11 fails1.02 fails
edge-info1.46 fails1.32 fails1.27 fails1.46 fails1.28 fails1.46 fails1.03 fails1.10 fails
edge-muted1.20 fails1.08 fails1.04 fails1.20 fails1.04 fails1.20 fails1.17 fails1.35 fails
edge-success2.31 fails2.09 fails2.01 fails2.31 fails2.02 fails2.31 fails1.63 fails1.42 fails
edge-warning2.94 fails2.66 fails2.56 fails2.94 fails2.56 fails2.94 fails2.07 fails1.80 fails

For a lint check

The same data is published as JSON at /data/contrast.json, with one entry per pairing and a pass or fail for each floor in both themes. A check in the product repository can fetch it and fail a pull request on a disallowed pairing.