OKLCH Studio · Accessible palettes · Product & UI

Accessible color palette for forms and status messages (WCAG 2.2 verified)

Updated 2026-10-19

Forms are where accessibility failures cost the most. A user who cannot read an error message cannot finish a purchase, a registration or a job application. The common failures are pale red text on white, an error indicated only by a red border, and success and error messages that differ only in green and red.

This palette focuses on the four feedback roles: error, warning, success and info. Each is given as text on the page and card surfaces and as a filled badge with its own label colour, all at AAA here, 7:1, because short messages are the part of a form people most need to read correctly. Borders and focus rings are at 3:1 or better.

WCAG covers the behaviour as well as the colour: success criterion 1.4.1 says colour must not be the only means of conveying information, and 3.3.1 asks that errors are identified in text. This page assumes you will do both and gives you colours that are safe to use with them.

How to build a palette like this by hand is explained in the accessible colour palette guide; this page is the finished, verified result.

The palette: light and dark

Hex values are the sRGB result after gamut mapping. The oklch() values are those of the final hex, so converting either gives the same colour.

Appointment confirmed

Secondary text sits on the surface colour.

Link in primary · Accent text

Primary buttonSuccessWarningErrorInfo

Light theme

  • Background

    #F4F7FA

    oklch(0.975 0.005 247.9)

    Sample text

  • Surface

    #FCFEFF

    oklch(0.996 0.003 228.8)

    Sample text

  • Text

    #191B1D

    oklch(0.221 0.005 248.1)

    Sample text

  • Muted text

    #55585C

    oklch(0.459 0.008 255.5)

    Sample text

  • Primary

    #2863AB

    oklch(0.499 0.130 255.3)

    Sample text

  • Primary foreground

    #FBFCFD

    oklch(0.991 0.002 247.8)

    Sample text

  • Accent

    #7555A8

    oklch(0.521 0.130 299.7)

    Sample text

  • Border

    #8B8E93

    oklch(0.646 0.008 260.7)

    Sample text

  • Focus ring

    #17559B

    oklch(0.4508 0.1295 254.79)

    Sample text

  • Success

    #005F4A

    oklch(0.432 0.085 171.0)

    Sample text

  • Success fill

    #00634C

    oklch(0.444 0.088 169.8)

    Sample text

  • Success fill label

    #FBFCFD

    oklch(0.991 0.002 247.8)

    Sample text

  • Warning

    #874000

    oklch(0.455 0.116 52.5)

    Sample text

  • Warning fill

    #FFB538

    oklch(0.8234 0.1564 75.53)

    Sample text

  • Warning fill label

    #0F0F10

    oklch(0.169 0.002 286.2)

    Sample text

  • Error

    #A90021

    oklch(0.464 0.187 22.8)

    Sample text

  • Error fill

    #B1001B

    oklch(0.479 0.194 24.9)

    Sample text

  • Error fill label

    #FBFCFD

    oklch(0.991 0.002 247.8)

    Sample text

  • Info

    #00578C

    oklch(0.442 0.112 245.2)

    Sample text

  • Info fill

    #005A95

    oklch(0.455 0.120 247.1)

    Sample text

  • Info fill label

    #FBFCFD

    oklch(0.991 0.002 247.8)

    Sample text

Appointment confirmed

Secondary text sits on the surface colour.

Link in primary · Accent text

Primary buttonSuccessWarningErrorInfo

Dark theme

  • Background

    #151618

    oklch(0.200 0.004 264.5)

    Sample text

  • Surface

    #1F2123

    oklch(0.246 0.005 248.0)

    Sample text

  • Text

    #ECEFF2

    oklch(0.951 0.005 247.9)

    Sample text

  • Muted text

    #BABEC3

    oklch(0.800 0.008 253.9)

    Sample text

  • Primary

    #83C1FF

    oklch(0.793 0.109 249.4)

    Sample text

  • Primary foreground

    #0D0D0E

    oklch(0.160 0.002 286.2)

    Sample text

  • Accent

    #D1B0FF

    oklch(0.814 0.114 303.1)

    Sample text

  • Border

    #686C70

    oklch(0.529 0.008 248.0)

    Sample text

  • Focus ring

    #83C1FF

    oklch(0.793 0.109 249.4)

    Sample text

  • Success

    #41E8CA

    oklch(0.8400 0.1404 177.70)

    Sample text

  • Success fill

    #00D0B1

    oklch(0.7666 0.1424 176.76)

    Sample text

  • Success fill label

    #0F0F10

    oklch(0.169 0.002 286.2)

    Sample text

  • Warning

    #FFB84F

    oklch(0.831 0.144 73.8)

    Sample text

  • Warning fill

    #F29B00

    oklch(0.759 0.165 69.9)

    Sample text

  • Warning fill label

    #0F0F10

    oklch(0.169 0.002 286.2)

    Sample text

  • Error

    #FF8989

    oklch(0.760 0.143 21.0)

    Sample text

  • Error fill

    #FF6E73

    oklch(0.717 0.177 20.6)

    Sample text

  • Error fill label

    #0F0F10

    oklch(0.169 0.002 286.2)

    Sample text

  • Info

    #55C4FE

    oklch(0.780 0.130 234.8)

    Sample text

  • Info fill

    #3BBEFE

    oklch(0.759 0.143 235.0)

    Sample text

  • Info fill label

    #0F0F10

    oklch(0.169 0.002 286.2)

    Sample text

Contrast table: every verified pair

Pass or fail uses the raw WCAG 2.x ratio; the ratio shown is floored to two decimals so a near miss is never rounded up. APCA Lc is signed: positive is dark on light, negative is light on dark. Each row opens the pair in the checker.

Light theme: 25 pairs
PairWCAG ratioTargetNormal AA / AAALarge AA / AAAAPCA LcAPCA tierCheck
Text on background#191b1d on #f4f7fa16.06:1AAA 7:1Pass / PassPass / Pass+99.1Lc 75: body textOpen in checker
Text on surface#191b1d on #fcfeff17.07:1AAA 7:1Pass / PassPass / Pass+103.3Lc 75: body textOpen in checker
Muted text on background#55585c on #f4f7fa6.65:1AA 4.5:1Pass / FailPass / Pass+79.8Lc 75: body textOpen in checker
Muted text on surface#55585c on #fcfeff7.06:1AA 4.5:1Pass / PassPass / Pass+84.0Lc 75: body textOpen in checker
Primary as link text on background#2863ab on #f4f7fa5.64:1AA 4.5:1Pass / FailPass / Pass+74.9Lc 60: larger content textOpen in checker
Primary as link text on surface#2863ab on #fcfeff5.99:1AA 4.5:1Pass / FailPass / Pass+79.1Lc 75: body textOpen in checker
Button label on primary#fbfcfd on #2863ab5.90:1AA 4.5:1Pass / FailPass / Pass−83.0Lc 75: body textOpen in checker
Accent text on background#7555a8 on #f4f7fa5.39:1AA 4.5:1Pass / FailPass / Pass+73.8Lc 60: larger content textOpen in checker
Accent text on surface#7555a8 on #fcfeff5.73:1AA 4.5:1Pass / FailPass / Pass+78.0Lc 75: body textOpen in checker
Border on background#8b8e93 on #f4f7fa3.05:13:1 (WCAG 1.4.11)Fail / FailPass / Fail+55.2Lc 45: headlines and large textOpen in checker
Border on surface#8b8e93 on #fcfeff3.24:13:1 (WCAG 1.4.11)Fail / FailPass / Fail+59.4Lc 45: headlines and large textOpen in checker
Focus ring on background#17559b on #f4f7fa6.95:13:1 (WCAG 1.4.11)Pass / FailPass / Pass+80.5Lc 75: body textOpen in checker
Focus ring on surface#17559b on #fcfeff7.39:13:1 (WCAG 1.4.11)Pass / PassPass / Pass+84.7Lc 75: body textOpen in checker
Success text on background#005f4a on #f4f7fa7.13:1AAA 7:1Pass / PassPass / Pass+81.1Lc 75: body textOpen in checker
Success text on surface#005f4a on #fcfeff7.58:1AAA 7:1Pass / PassPass / Pass+85.3Lc 75: body textOpen in checker
Success badge label on fill#fbfcfd on #00634c7.07:1AAA 7:1Pass / PassPass / Pass−87.5Lc 75: body textOpen in checker
Warning text on background#874000 on #f4f7fa7.06:1AAA 7:1Pass / PassPass / Pass+80.8Lc 75: body textOpen in checker
Warning text on surface#874000 on #fcfeff7.51:1AAA 7:1Pass / PassPass / Pass+85.0Lc 75: body textOpen in checker
Warning badge label on fill#0f0f10 on #ffb53810.87:1AAA 7:1Pass / PassPass / Pass+71.3Lc 60: larger content textOpen in checker
Error text on background#a90021 on #f4f7fa7.20:1AAA 7:1Pass / PassPass / Pass+79.3Lc 75: body textOpen in checker
Error text on surface#a90021 on #fcfeff7.66:1AAA 7:1Pass / PassPass / Pass+83.5Lc 75: body textOpen in checker
Error badge label on fill#fbfcfd on #b1001b7.08:1AAA 7:1Pass / PassPass / Pass−85.6Lc 75: body textOpen in checker
Info text on background#00578c on #f4f7fa7.12:1AAA 7:1Pass / PassPass / Pass+81.0Lc 75: body textOpen in checker
Info text on surface#00578c on #fcfeff7.57:1AAA 7:1Pass / PassPass / Pass+85.2Lc 75: body textOpen in checker
Info badge label on fill#fbfcfd on #005a957.05:1AAA 7:1Pass / PassPass / Pass−87.4Lc 75: body textOpen in checker
Dark theme: 25 pairs
PairWCAG ratioTargetNormal AA / AAALarge AA / AAAAPCA LcAPCA tierCheck
Text on background#eceff2 on #15161815.68:1AAA 7:1Pass / PassPass / Pass−96.2Lc 75: body textOpen in checker
Text on surface#eceff2 on #1f212313.99:1AAA 7:1Pass / PassPass / Pass−94.9Lc 75: body textOpen in checker
Muted text on background#babec3 on #1516189.69:1AA 4.5:1Pass / PassPass / Pass−66.3Lc 60: larger content textOpen in checker
Muted text on surface#babec3 on #1f21238.64:1AA 4.5:1Pass / PassPass / Pass−65.0Lc 60: larger content textOpen in checker
Primary as link text on background#83c1ff on #1516189.51:1AA 4.5:1Pass / PassPass / Pass−65.4Lc 60: larger content textOpen in checker
Primary as link text on surface#83c1ff on #1f21238.48:1AA 4.5:1Pass / PassPass / Pass−64.1Lc 60: larger content textOpen in checker
Button label on primary#0d0d0e on #83c1ff10.20:1AA 4.5:1Pass / PassPass / Pass+67.4Lc 60: larger content textOpen in checker
Accent text on background#d1b0ff on #1516189.79:1AA 4.5:1Pass / PassPass / Pass−66.9Lc 60: larger content textOpen in checker
Accent text on surface#d1b0ff on #1f21238.74:1AA 4.5:1Pass / PassPass / Pass−65.6Lc 60: larger content textOpen in checker
Border on background#686c70 on #1516183.42:13:1 (WCAG 1.4.11)Fail / FailPass / Fail−24.5Below Lc 30Open in checker
Border on surface#686c70 on #1f21233.05:13:1 (WCAG 1.4.11)Fail / FailPass / Fail−23.2Below Lc 30Open in checker
Focus ring on background#83c1ff on #1516189.51:13:1 (WCAG 1.4.11)Pass / PassPass / Pass−65.4Lc 60: larger content textOpen in checker
Focus ring on surface#83c1ff on #1f21238.48:13:1 (WCAG 1.4.11)Pass / PassPass / Pass−64.1Lc 60: larger content textOpen in checker
Success text on background#41e8ca on #15161811.74:1AAA 7:1Pass / PassPass / Pass−77.7Lc 75: body textOpen in checker
Success text on surface#41e8ca on #1f212310.47:1AAA 7:1Pass / PassPass / Pass−76.3Lc 75: body textOpen in checker
Success badge label on fill#0f0f10 on #00d0b19.72:1AAA 7:1Pass / PassPass / Pass+66.1Lc 60: larger content textOpen in checker
Warning text on background#ffb84f on #15161810.53:1AAA 7:1Pass / PassPass / Pass−71.1Lc 60: larger content textOpen in checker
Warning text on surface#ffb84f on #1f21239.40:1AAA 7:1Pass / PassPass / Pass−69.8Lc 60: larger content textOpen in checker
Warning badge label on fill#0f0f10 on #f29b008.63:1AAA 7:1Pass / PassPass / Pass+60.2Lc 60: larger content textOpen in checker
Error text on background#ff8989 on #1516187.92:1AAA 7:1Pass / PassPass / Pass−56.6Lc 45: headlines and large textOpen in checker
Error text on surface#ff8989 on #1f21237.07:1AAA 7:1Pass / PassPass / Pass−55.2Lc 45: headlines and large textOpen in checker
Error badge label on fill#0f0f10 on #ff6e737.05:1AAA 7:1Pass / PassPass / Pass+51.6Lc 45: headlines and large textOpen in checker
Info text on background#55c4fe on #1516189.23:1AAA 7:1Pass / PassPass / Pass−64.1Lc 60: larger content textOpen in checker
Info text on surface#55c4fe on #1f21238.24:1AAA 7:1Pass / PassPass / Pass−62.8Lc 60: larger content textOpen in checker
Info badge label on fill#0f0f10 on #3bbefe9.10:1AAA 7:1Pass / PassPass / Pass+62.7Lc 60: larger content textOpen in checker

Status colours and colour blindness

The four status fills were simulated for protanopia, deuteranopia and tritanopia (Machado et al., 2009). Success against error, the pair most often confused, must stay at least 7 ΔE-OK ×100 apart under every simulation. The other pairs are shown for information, so keep an icon and a word on every status.

Light theme, status fills
PairNormal visionProtanopiaDeuteranopiaTritanopiaHeld to 7
success / warning42.235.046.938.6Shown only
success / error27.324.79.331.8Yes
success / info13.312.812.32.6Shown only
warning / error37.759.252.326.0Shown only
warning / info46.039.950.837.5Shown only
error / info29.528.220.131.8Shown only

Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia

Dark theme, status fills
PairNormal visionProtanopiaDeuteranopiaTritanopiaHeld to 7
success / warning24.715.422.730.4Shown only
success / error31.717.710.334.5Yes
success / info13.911.710.73.7Shown only
warning / error14.916.413.85.4Shown only
warning / info30.526.630.829.5Shown only
error / info30.922.620.533.2Shown only

Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia

Why these colours

Status hues are chosen to differ in more than hue. Error is a red-orange near OKLCH hue 22, warning an amber at 70, success a blue-leaning green at 178 and info a blue at 235. Success and error are the pair most often confused, so the generator makes the error colour darker than the success colour and reports the gap under simulated colour-vision deficiency.

Because the target here is AAA, the text forms end up darker than in most palettes, and the page lists their exact values. The filled forms are lighter and more saturated, with a dark or white label chosen per hue: ink on amber and in dark mode, white on the deep fills in light mode. The neutrals and primary are standard.

The generator solved 50 pairs (25 light, 25 dark), and all of them meet their target on the raw WCAG ratio. The tightest is error badge label on fill in the dark theme at 7.05:1 against a target of 7:1. After gamut mapping to sRGB the light primary keeps 100% of the requested chroma; hue was held throughout.

How to use it

  • Write the error in words next to the field, link it from a summary at the top, and set aria-invalid and aria-describedby on the input.
  • Add an icon and a word, such as Error or Warning, to every message so colour is not the only signal.
  • Use the warning colour for things that need attention but do not block, and the info colour for neutral notes.
  • Keep success messages visible long enough to read, and announce them to screen readers with a live region.
  • Give invalid inputs a border colour from the error text role, which is 3:1 or better, in addition to the message.

Export

Generated from the verified values above, never typed by hand. Light and dark are both included.

CSS custom properties (hex, then oklch())

/* sRGB hex first: every browser. */
:root {
  --color-background: #f4f7fa;
  --color-surface: #fcfeff;
  --color-text: #191b1d;
  --color-text-muted: #55585c;
  --color-primary: #2863ab;
  --color-primary-foreground: #fbfcfd;
  --color-accent: #7555a8;
  --color-border: #8b8e93;
  --color-focus-ring: #17559b;
  --color-success: #005f4a;
  --color-success-solid: #00634c;
  --color-success-solid-foreground: #fbfcfd;
  --color-warning: #874000;
  --color-warning-solid: #ffb538;
  --color-warning-solid-foreground: #0f0f10;
  --color-error: #a90021;
  --color-error-solid: #b1001b;
  --color-error-solid-foreground: #fbfcfd;
  --color-info: #00578c;
  --color-info-solid: #005a95;
  --color-info-solid-foreground: #fbfcfd;
}
.dark {
  --color-background: #151618;
  --color-surface: #1f2123;
  --color-text: #eceff2;
  --color-text-muted: #babec3;
  --color-primary: #83c1ff;
  --color-primary-foreground: #0d0d0e;
  --color-accent: #d1b0ff;
  --color-border: #686c70;
  --color-focus-ring: #83c1ff;
  --color-success: #41e8ca;
  --color-success-solid: #00d0b1;
  --color-success-solid-foreground: #0f0f10;
  --color-warning: #ffb84f;
  --color-warning-solid: #f29b00;
  --color-warning-solid-foreground: #0f0f10;
  --color-error: #ff8989;
  --color-error-solid: #ff6e73;
  --color-error-solid-foreground: #0f0f10;
  --color-info: #55c4fe;
  --color-info-solid: #3bbefe;
  --color-info-solid-foreground: #0f0f10;
}

/* oklch() where supported: the same colours, unclipped values of the hex above. */
@supports (color: oklch(0 0 0)) {
  :root {
    --color-background: oklch(0.975 0.005 247.9);
    --color-surface: oklch(0.996 0.003 228.8);
    --color-text: oklch(0.221 0.005 248.1);
    --color-text-muted: oklch(0.459 0.008 255.5);
    --color-primary: oklch(0.499 0.130 255.3);
    --color-primary-foreground: oklch(0.991 0.002 247.8);
    --color-accent: oklch(0.521 0.130 299.7);
    --color-border: oklch(0.646 0.008 260.7);
    --color-focus-ring: oklch(0.4508 0.1295 254.79);
    --color-success: oklch(0.432 0.085 171.0);
    --color-success-solid: oklch(0.444 0.088 169.8);
    --color-success-solid-foreground: oklch(0.991 0.002 247.8);
    --color-warning: oklch(0.455 0.116 52.5);
    --color-warning-solid: oklch(0.8234 0.1564 75.53);
    --color-warning-solid-foreground: oklch(0.169 0.002 286.2);
    --color-error: oklch(0.464 0.187 22.8);
    --color-error-solid: oklch(0.479 0.194 24.9);
    --color-error-solid-foreground: oklch(0.991 0.002 247.8);
    --color-info: oklch(0.442 0.112 245.2);
    --color-info-solid: oklch(0.455 0.120 247.1);
    --color-info-solid-foreground: oklch(0.991 0.002 247.8);
  }
  .dark {
    --color-background: oklch(0.200 0.004 264.5);
    --color-surface: oklch(0.246 0.005 248.0);
    --color-text: oklch(0.951 0.005 247.9);
    --color-text-muted: oklch(0.800 0.008 253.9);
    --color-primary: oklch(0.793 0.109 249.4);
    --color-primary-foreground: oklch(0.160 0.002 286.2);
    --color-accent: oklch(0.814 0.114 303.1);
    --color-border: oklch(0.529 0.008 248.0);
    --color-focus-ring: oklch(0.793 0.109 249.4);
    --color-success: oklch(0.8400 0.1404 177.70);
    --color-success-solid: oklch(0.7666 0.1424 176.76);
    --color-success-solid-foreground: oklch(0.169 0.002 286.2);
    --color-warning: oklch(0.831 0.144 73.8);
    --color-warning-solid: oklch(0.759 0.165 69.9);
    --color-warning-solid-foreground: oklch(0.169 0.002 286.2);
    --color-error: oklch(0.760 0.143 21.0);
    --color-error-solid: oklch(0.717 0.177 20.6);
    --color-error-solid-foreground: oklch(0.169 0.002 286.2);
    --color-info: oklch(0.780 0.130 234.8);
    --color-info-solid: oklch(0.759 0.143 235.0);
    --color-info-solid-foreground: oklch(0.169 0.002 286.2);
  }
}

Tailwind CSS v4 @theme

@theme {
  /* light */
  --color-background: oklch(0.975 0.005 247.9); /* #f4f7fa */
  --color-surface: oklch(0.996 0.003 228.8); /* #fcfeff */
  --color-text: oklch(0.221 0.005 248.1); /* #191b1d */
  --color-text-muted: oklch(0.459 0.008 255.5); /* #55585c */
  --color-primary: oklch(0.499 0.130 255.3); /* #2863ab */
  --color-primary-foreground: oklch(0.991 0.002 247.8); /* #fbfcfd */
  --color-accent: oklch(0.521 0.130 299.7); /* #7555a8 */
  --color-border: oklch(0.646 0.008 260.7); /* #8b8e93 */
  --color-focus-ring: oklch(0.4508 0.1295 254.79); /* #17559b */
  --color-success: oklch(0.432 0.085 171.0); /* #005f4a */
  --color-success-solid: oklch(0.444 0.088 169.8); /* #00634c */
  --color-success-solid-foreground: oklch(0.991 0.002 247.8); /* #fbfcfd */
  --color-warning: oklch(0.455 0.116 52.5); /* #874000 */
  --color-warning-solid: oklch(0.8234 0.1564 75.53); /* #ffb538 */
  --color-warning-solid-foreground: oklch(0.169 0.002 286.2); /* #0f0f10 */
  --color-error: oklch(0.464 0.187 22.8); /* #a90021 */
  --color-error-solid: oklch(0.479 0.194 24.9); /* #b1001b */
  --color-error-solid-foreground: oklch(0.991 0.002 247.8); /* #fbfcfd */
  --color-info: oklch(0.442 0.112 245.2); /* #00578c */
  --color-info-solid: oklch(0.455 0.120 247.1); /* #005a95 */
  --color-info-solid-foreground: oklch(0.991 0.002 247.8); /* #fbfcfd */
  /* dark: use as dark:bg-background-dark, or remap under a .dark selector */
  --color-background-dark: oklch(0.200 0.004 264.5); /* #151618 */
  --color-surface-dark: oklch(0.246 0.005 248.0); /* #1f2123 */
  --color-text-dark: oklch(0.951 0.005 247.9); /* #eceff2 */
  --color-text-muted-dark: oklch(0.800 0.008 253.9); /* #babec3 */
  --color-primary-dark: oklch(0.793 0.109 249.4); /* #83c1ff */
  --color-primary-foreground-dark: oklch(0.160 0.002 286.2); /* #0d0d0e */
  --color-accent-dark: oklch(0.814 0.114 303.1); /* #d1b0ff */
  --color-border-dark: oklch(0.529 0.008 248.0); /* #686c70 */
  --color-focus-ring-dark: oklch(0.793 0.109 249.4); /* #83c1ff */
  --color-success-dark: oklch(0.8400 0.1404 177.70); /* #41e8ca */
  --color-success-solid-dark: oklch(0.7666 0.1424 176.76); /* #00d0b1 */
  --color-success-solid-foreground-dark: oklch(0.169 0.002 286.2); /* #0f0f10 */
  --color-warning-dark: oklch(0.831 0.144 73.8); /* #ffb84f */
  --color-warning-solid-dark: oklch(0.759 0.165 69.9); /* #f29b00 */
  --color-warning-solid-foreground-dark: oklch(0.169 0.002 286.2); /* #0f0f10 */
  --color-error-dark: oklch(0.760 0.143 21.0); /* #ff8989 */
  --color-error-solid-dark: oklch(0.717 0.177 20.6); /* #ff6e73 */
  --color-error-solid-foreground-dark: oklch(0.169 0.002 286.2); /* #0f0f10 */
  --color-info-dark: oklch(0.780 0.130 234.8); /* #55c4fe */
  --color-info-solid-dark: oklch(0.759 0.143 235.0); /* #3bbefe */
  --color-info-solid-foreground-dark: oklch(0.169 0.002 286.2); /* #0f0f10 */
}

shadcn/ui variables (:root and .dark)

:root {
  --background: oklch(0.975 0.005 247.9);
  --foreground: oklch(0.221 0.005 248.1);
  --card: oklch(0.996 0.003 228.8);
  --card-foreground: oklch(0.221 0.005 248.1);
  --popover: oklch(0.996 0.003 228.8);
  --popover-foreground: oklch(0.221 0.005 248.1);
  --primary: oklch(0.499 0.130 255.3);
  --primary-foreground: oklch(0.991 0.002 247.8);
  --secondary: oklch(0.996 0.003 228.8);
  --secondary-foreground: oklch(0.221 0.005 248.1);
  --muted: oklch(0.996 0.003 228.8);
  --muted-foreground: oklch(0.459 0.008 255.5);
  --accent: oklch(0.996 0.003 228.8);
  --accent-foreground: oklch(0.221 0.005 248.1);
  --destructive: oklch(0.479 0.194 24.9);
  --destructive-foreground: oklch(0.991 0.002 247.8);
  --border: oklch(0.646 0.008 260.7);
  --input: oklch(0.646 0.008 260.7);
  --ring: oklch(0.4508 0.1295 254.79);
  --success: oklch(0.444 0.088 169.8);
  --success-foreground: oklch(0.991 0.002 247.8);
  --warning: oklch(0.8234 0.1564 75.53);
  --warning-foreground: oklch(0.169 0.002 286.2);
  --info: oklch(0.455 0.120 247.1);
  --info-foreground: oklch(0.991 0.002 247.8);
  --brand-accent: oklch(0.521 0.130 299.7);
}

.dark {
  --background: oklch(0.200 0.004 264.5);
  --foreground: oklch(0.951 0.005 247.9);
  --card: oklch(0.246 0.005 248.0);
  --card-foreground: oklch(0.951 0.005 247.9);
  --popover: oklch(0.246 0.005 248.0);
  --popover-foreground: oklch(0.951 0.005 247.9);
  --primary: oklch(0.793 0.109 249.4);
  --primary-foreground: oklch(0.160 0.002 286.2);
  --secondary: oklch(0.246 0.005 248.0);
  --secondary-foreground: oklch(0.951 0.005 247.9);
  --muted: oklch(0.246 0.005 248.0);
  --muted-foreground: oklch(0.800 0.008 253.9);
  --accent: oklch(0.246 0.005 248.0);
  --accent-foreground: oklch(0.951 0.005 247.9);
  --destructive: oklch(0.717 0.177 20.6);
  --destructive-foreground: oklch(0.169 0.002 286.2);
  --border: oklch(0.529 0.008 248.0);
  --input: oklch(0.529 0.008 248.0);
  --ring: oklch(0.793 0.109 249.4);
  --success: oklch(0.7666 0.1424 176.76);
  --success-foreground: oklch(0.169 0.002 286.2);
  --warning: oklch(0.759 0.165 69.9);
  --warning-foreground: oklch(0.169 0.002 286.2);
  --info: oklch(0.759 0.143 235.0);
  --info-foreground: oklch(0.169 0.002 286.2);
  --brand-accent: oklch(0.814 0.114 303.1);
}

Design tokens (DTCG-style JSON)

{
  "color": {
    "light": {
      "background": {
        "$type": "color",
        "$value": "oklch(0.975 0.005 247.9)",
        "$description": "sRGB #f4f7fa"
      },
      "surface": {
        "$type": "color",
        "$value": "oklch(0.996 0.003 228.8)",
        "$description": "sRGB #fcfeff"
      },
      "text": {
        "$type": "color",
        "$value": "oklch(0.221 0.005 248.1)",
        "$description": "sRGB #191b1d"
      },
      "text-muted": {
        "$type": "color",
        "$value": "oklch(0.459 0.008 255.5)",
        "$description": "sRGB #55585c"
      },
      "primary": {
        "$type": "color",
        "$value": "oklch(0.499 0.130 255.3)",
        "$description": "sRGB #2863ab"
      },
      "primary-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.002 247.8)",
        "$description": "sRGB #fbfcfd"
      },
      "accent": {
        "$type": "color",
        "$value": "oklch(0.521 0.130 299.7)",
        "$description": "sRGB #7555a8"
      },
      "border": {
        "$type": "color",
        "$value": "oklch(0.646 0.008 260.7)",
        "$description": "sRGB #8b8e93"
      },
      "focus-ring": {
        "$type": "color",
        "$value": "oklch(0.4508 0.1295 254.79)",
        "$description": "sRGB #17559b"
      },
      "success": {
        "$type": "color",
        "$value": "oklch(0.432 0.085 171.0)",
        "$description": "sRGB #005f4a"
      },
      "success-solid": {
        "$type": "color",
        "$value": "oklch(0.444 0.088 169.8)",
        "$description": "sRGB #00634c"
      },
      "success-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.002 247.8)",
        "$description": "sRGB #fbfcfd"
      },
      "warning": {
        "$type": "color",
        "$value": "oklch(0.455 0.116 52.5)",
        "$description": "sRGB #874000"
      },
      "warning-solid": {
        "$type": "color",
        "$value": "oklch(0.8234 0.1564 75.53)",
        "$description": "sRGB #ffb538"
      },
      "warning-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.002 286.2)",
        "$description": "sRGB #0f0f10"
      },
      "error": {
        "$type": "color",
        "$value": "oklch(0.464 0.187 22.8)",
        "$description": "sRGB #a90021"
      },
      "error-solid": {
        "$type": "color",
        "$value": "oklch(0.479 0.194 24.9)",
        "$description": "sRGB #b1001b"
      },
      "error-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.002 247.8)",
        "$description": "sRGB #fbfcfd"
      },
      "info": {
        "$type": "color",
        "$value": "oklch(0.442 0.112 245.2)",
        "$description": "sRGB #00578c"
      },
      "info-solid": {
        "$type": "color",
        "$value": "oklch(0.455 0.120 247.1)",
        "$description": "sRGB #005a95"
      },
      "info-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.002 247.8)",
        "$description": "sRGB #fbfcfd"
      }
    },
    "dark": {
      "background": {
        "$type": "color",
        "$value": "oklch(0.200 0.004 264.5)",
        "$description": "sRGB #151618"
      },
      "surface": {
        "$type": "color",
        "$value": "oklch(0.246 0.005 248.0)",
        "$description": "sRGB #1f2123"
      },
      "text": {
        "$type": "color",
        "$value": "oklch(0.951 0.005 247.9)",
        "$description": "sRGB #eceff2"
      },
      "text-muted": {
        "$type": "color",
        "$value": "oklch(0.800 0.008 253.9)",
        "$description": "sRGB #babec3"
      },
      "primary": {
        "$type": "color",
        "$value": "oklch(0.793 0.109 249.4)",
        "$description": "sRGB #83c1ff"
      },
      "primary-foreground": {
        "$type": "color",
        "$value": "oklch(0.160 0.002 286.2)",
        "$description": "sRGB #0d0d0e"
      },
      "accent": {
        "$type": "color",
        "$value": "oklch(0.814 0.114 303.1)",
        "$description": "sRGB #d1b0ff"
      },
      "border": {
        "$type": "color",
        "$value": "oklch(0.529 0.008 248.0)",
        "$description": "sRGB #686c70"
      },
      "focus-ring": {
        "$type": "color",
        "$value": "oklch(0.793 0.109 249.4)",
        "$description": "sRGB #83c1ff"
      },
      "success": {
        "$type": "color",
        "$value": "oklch(0.8400 0.1404 177.70)",
        "$description": "sRGB #41e8ca"
      },
      "success-solid": {
        "$type": "color",
        "$value": "oklch(0.7666 0.1424 176.76)",
        "$description": "sRGB #00d0b1"
      },
      "success-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.002 286.2)",
        "$description": "sRGB #0f0f10"
      },
      "warning": {
        "$type": "color",
        "$value": "oklch(0.831 0.144 73.8)",
        "$description": "sRGB #ffb84f"
      },
      "warning-solid": {
        "$type": "color",
        "$value": "oklch(0.759 0.165 69.9)",
        "$description": "sRGB #f29b00"
      },
      "warning-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.002 286.2)",
        "$description": "sRGB #0f0f10"
      },
      "error": {
        "$type": "color",
        "$value": "oklch(0.760 0.143 21.0)",
        "$description": "sRGB #ff8989"
      },
      "error-solid": {
        "$type": "color",
        "$value": "oklch(0.717 0.177 20.6)",
        "$description": "sRGB #ff6e73"
      },
      "error-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.002 286.2)",
        "$description": "sRGB #0f0f10"
      },
      "info": {
        "$type": "color",
        "$value": "oklch(0.780 0.130 234.8)",
        "$description": "sRGB #55c4fe"
      },
      "info-solid": {
        "$type": "color",
        "$value": "oklch(0.759 0.143 235.0)",
        "$description": "sRGB #3bbefe"
      },
      "info-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.002 286.2)",
        "$description": "sRGB #0f0f10"
      }
    }
  }
}

Open in the studio

Take the primary colour into the picker, build a tonal scale from it, or check any pair of your own.

Open #2863AB in the OKLCH picker →Build a tonal scale →Check a pair

FAQ

Are red and green safe if I add icons?
Icons and words satisfy WCAG 1.4.1. This palette adds a second layer, a lightness gap, so the two are still distinguishable when someone ignores the icon.
Why do warning badges use dark labels?
Amber and yellow are light colours. White text on them cannot reach contrast without turning the fill brown, so a dark label on a light amber fill is the readable choice.
What does the colour-vision table show?
The smallest ΔE-OK difference between each pair of status fills when simulated for protanopia, deuteranopia and tritanopia. Only success against error is held to a threshold.
Can I use these in toasts?
Yes, with the badge pairs. Toasts also need enough time on screen and a way to dismiss them with the keyboard.

← All accessible palettes