OKLCH Studio · Accessible palettes · Industries

Accessible color palette for e-learning for kids (WCAG 2.2 verified)

Updated 2026-10-19

Children's learning products want colour that feels friendly and energetic, and designers often fear that accessibility will force everything into grey. It does not have to. WCAG sets its contrast rules by the text and its background, not by how lively the brand is, and there is plenty of room for high chroma at the lightness values that pass.

There is no separate WCAG standard for children, so the same criteria apply: 4.5:1 for normal text, 3:1 for large text and interface components. Young readers still learning to read benefit from clear letterforms and strong contrast, and children with colour-vision deficiency are often diagnosed late, so colour must never be the only way to tell right from wrong in a quiz.

This palette uses the AA level throughout, with body text solved at AAA anyway because the cost is small on a warm cream page. The status colours are more saturated than in the adult palettes and are still verified as text and as badges with labels.

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

    #FCF8F0

    oklch(0.980 0.011 84.6)

    Sample text

  • Surface

    #FFFEF6

    oklch(0.996 0.011 100.8)

    Sample text

  • Text

    #1E1A13

    oklch(0.220 0.014 81.6)

    Sample text

  • Muted text

    #5D574D

    oklch(0.459 0.018 80.6)

    Sample text

  • Primary

    #0069C2

    oklch(0.521 0.161 253.0)

    Sample text

  • Primary foreground

    #FDFCF8

    oklch(0.991 0.005 95.1)

    Sample text

  • Accent

    #B53B00

    oklch(0.524 0.167 39.2)

    Sample text

  • Border

    #948E83

    oklch(0.649 0.018 82.8)

    Sample text

  • Focus ring

    #0059B1

    oklch(0.473 0.158 255.4)

    Sample text

  • Success

    #00825B

    oklch(0.537 0.115 163.7)

    Sample text

  • Success fill

    #008459

    oklch(0.5420 0.1193 161.76)

    Sample text

  • Success fill label

    #FDFCF8

    oklch(0.991 0.005 95.1)

    Sample text

  • Warning

    #A56200

    oklch(0.5589 0.1252 65.21)

    Sample text

  • Warning fill

    #FFBA00

    oklch(0.8309 0.1714 81.55)

    Sample text

  • Warning fill label

    #100F0D

    oklch(0.169 0.004 84.6)

    Sample text

  • Error

    #B3001C

    oklch(0.483 0.196 24.8)

    Sample text

  • Error fill

    #DB002F

    oklch(0.563 0.227 22.5)

    Sample text

  • Error fill label

    #FDFCF8

    oklch(0.991 0.005 95.1)

    Sample text

  • Info

    #0077BB

    oklch(0.549 0.137 244.6)

    Sample text

  • Info fill

    #0078C4

    oklch(0.557 0.147 247.1)

    Sample text

  • Info fill label

    #FDFCF8

    oklch(0.991 0.005 95.1)

    Sample text

Appointment confirmed

Secondary text sits on the surface colour.

Link in primary · Accent text

Primary buttonSuccessWarningErrorInfo

Dark theme

  • Background

    #191610

    oklch(0.202 0.012 84.5)

    Sample text

  • Surface

    #23201A

    oklch(0.245 0.012 84.6)

    Sample text

  • Text

    #F3EEE4

    oklch(0.950 0.014 84.6)

    Sample text

  • Muted text

    #C3BDB1

    oklch(0.800 0.018 84.6)

    Sample text

  • Primary

    #00CAFF

    oklch(0.781 0.149 225.4)

    Sample text

  • Primary foreground

    #0E0D0B

    oklch(0.159 0.004 84.6)

    Sample text

  • Accent

    #FF9D2C

    oklch(0.780 0.164 63.5)

    Sample text

  • Border

    #706B60

    oklch(0.529 0.018 86.5)

    Sample text

  • Focus ring

    #00CAFF

    oklch(0.781 0.149 225.4)

    Sample text

  • Success

    #00EDBE

    oklch(0.8425 0.1642 171.51)

    Sample text

  • Success fill

    #00D5A3

    oklch(0.775 0.157 168.2)

    Sample text

  • Success fill label

    #100F0D

    oklch(0.169 0.004 84.6)

    Sample text

  • Warning

    #FFBC19

    oklch(0.835 0.168 81.8)

    Sample text

  • Warning fill

    #EEA000

    oklch(0.764 0.162 74.2)

    Sample text

  • Warning fill label

    #100F0D

    oklch(0.169 0.004 84.6)

    Sample text

  • Error

    #FF5263

    oklch(0.681 0.208 19.2)

    Sample text

  • Error fill

    #FF5A6E

    oklch(0.692 0.200 17.0)

    Sample text

  • Error fill label

    #100F0D

    oklch(0.169 0.004 84.6)

    Sample text

  • Info

    #1FC6FF

    oklch(0.774 0.147 228.6)

    Sample text

  • Info fill

    #00C0FF

    oklch(0.758 0.153 231.1)

    Sample text

  • Info fill label

    #100F0D

    oklch(0.169 0.004 84.6)

    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#1e1a13 on #fcf8f016.35:1AAA 7:1Pass / PassPass / Pass+100.2Lc 75: body textOpen in checker
Text on surface#1e1a13 on #fffef617.12:1AAA 7:1Pass / PassPass / Pass+103.4Lc 75: body textOpen in checker
Muted text on background#5d574d on #fcf8f06.75:1AA 4.5:1Pass / FailPass / Pass+80.8Lc 75: body textOpen in checker
Muted text on surface#5d574d on #fffef67.07:1AA 4.5:1Pass / PassPass / Pass+84.0Lc 75: body textOpen in checker
Primary as link text on background#0069c2 on #fcf8f05.21:1AA 4.5:1Pass / FailPass / Pass+72.8Lc 60: larger content textOpen in checker
Primary as link text on surface#0069c2 on #fffef65.46:1AA 4.5:1Pass / FailPass / Pass+76.0Lc 75: body textOpen in checker
Button label on primary#fdfcf8 on #0069c25.38:1AA 4.5:1Pass / FailPass / Pass−80.1Lc 75: body textOpen in checker
Accent text on background#b53b00 on #fcf8f05.52:1AA 4.5:1Pass / FailPass / Pass+74.1Lc 60: larger content textOpen in checker
Accent text on surface#b53b00 on #fffef65.78:1AA 4.5:1Pass / FailPass / Pass+77.3Lc 75: body textOpen in checker
Border on background#948e83 on #fcf8f03.07:13:1 (WCAG 1.4.11)Fail / FailPass / Fail+55.8Lc 45: headlines and large textOpen in checker
Border on surface#948e83 on #fffef63.21:13:1 (WCAG 1.4.11)Fail / FailPass / Fail+59.0Lc 45: headlines and large textOpen in checker
Focus ring on background#0059b1 on #fcf8f06.47:13:1 (WCAG 1.4.11)Pass / FailPass / Pass+78.9Lc 75: body textOpen in checker
Focus ring on surface#0059b1 on #fffef66.77:13:1 (WCAG 1.4.11)Pass / FailPass / Pass+82.1Lc 75: body textOpen in checker
Success text on background#00825b on #fcf8f04.56:1AA 4.5:1Pass / FailPass / Pass+68.9Lc 60: larger content textOpen in checker
Success text on surface#00825b on #fffef64.77:1AA 4.5:1Pass / FailPass / Pass+72.1Lc 60: larger content textOpen in checker
Success badge label on fill#fdfcf8 on #0084594.60:1AA 4.5:1Pass / FailPass / Pass−75.6Lc 75: body textOpen in checker
Warning text on background#a56200 on #fcf8f04.56:1AA 4.5:1Pass / FailPass / Pass+69.1Lc 60: larger content textOpen in checker
Warning text on surface#a56200 on #fffef64.77:1AA 4.5:1Pass / FailPass / Pass+72.3Lc 60: larger content textOpen in checker
Warning badge label on fill#100f0d on #ffba0011.19:1AA 4.5:1Pass / PassPass / Pass+72.9Lc 60: larger content textOpen in checker
Error text on background#b3001c on #fcf8f06.75:1AA 4.5:1Pass / FailPass / Pass+78.2Lc 75: body textOpen in checker
Error text on surface#b3001c on #fffef67.07:1AA 4.5:1Pass / PassPass / Pass+81.4Lc 75: body textOpen in checker
Error badge label on fill#fdfcf8 on #db002f5.04:1AA 4.5:1Pass / FailPass / Pass−76.2Lc 75: body textOpen in checker
Info text on background#0077bb on #fcf8f04.55:1AA 4.5:1Pass / FailPass / Pass+68.8Lc 60: larger content textOpen in checker
Info text on surface#0077bb on #fffef64.76:1AA 4.5:1Pass / FailPass / Pass+72.0Lc 60: larger content textOpen in checker
Info badge label on fill#fdfcf8 on #0078c44.56:1AA 4.5:1Pass / FailPass / Pass−75.3Lc 75: body textOpen in checker
Dark theme: 25 pairs
PairWCAG ratioTargetNormal AA / AAALarge AA / AAAAPCA LcAPCA tierCheck
Text on background#f3eee4 on #19161015.60:1AAA 7:1Pass / PassPass / Pass−96.1Lc 75: body textOpen in checker
Text on surface#f3eee4 on #23201a14.04:1AAA 7:1Pass / PassPass / Pass−94.8Lc 75: body textOpen in checker
Muted text on background#c3bdb1 on #1916109.65:1AA 4.5:1Pass / PassPass / Pass−66.2Lc 60: larger content textOpen in checker
Muted text on surface#c3bdb1 on #23201a8.68:1AA 4.5:1Pass / PassPass / Pass−65.0Lc 60: larger content textOpen in checker
Primary as link text on background#00caff on #1916109.36:1AA 4.5:1Pass / PassPass / Pass−65.4Lc 60: larger content textOpen in checker
Primary as link text on surface#00caff on #23201a8.42:1AA 4.5:1Pass / PassPass / Pass−64.1Lc 60: larger content textOpen in checker
Button label on primary#0e0d0b on #00caff10.07:1AA 4.5:1Pass / PassPass / Pass+67.3Lc 60: larger content textOpen in checker
Accent text on background#ff9d2c on #1916108.69:1AA 4.5:1Pass / PassPass / Pass−61.2Lc 60: larger content textOpen in checker
Accent text on surface#ff9d2c on #23201a7.82:1AA 4.5:1Pass / PassPass / Pass−60.0Lc 45: headlines and large textOpen in checker
Border on background#706b60 on #1916103.40:13:1 (WCAG 1.4.11)Fail / FailPass / Fail−24.4Below Lc 30Open in checker
Border on surface#706b60 on #23201a3.06:13:1 (WCAG 1.4.11)Fail / FailPass / Fail−23.2Below Lc 30Open in checker
Focus ring on background#00caff on #1916109.36:13:1 (WCAG 1.4.11)Pass / PassPass / Pass−65.4Lc 60: larger content textOpen in checker
Focus ring on surface#00caff on #23201a8.42:13:1 (WCAG 1.4.11)Pass / PassPass / Pass−64.1Lc 60: larger content textOpen in checker
Success text on background#00edbe on #19161011.90:1AA 4.5:1Pass / PassPass / Pass−79.0Lc 75: body textOpen in checker
Success text on surface#00edbe on #23201a10.71:1AA 4.5:1Pass / PassPass / Pass−77.8Lc 75: body textOpen in checker
Success badge label on fill#100f0d on #00d5a310.07:1AA 4.5:1Pass / PassPass / Pass+67.9Lc 60: larger content textOpen in checker
Warning text on background#ffbc19 on #19161010.70:1AA 4.5:1Pass / PassPass / Pass−72.2Lc 60: larger content textOpen in checker
Warning text on surface#ffbc19 on #23201a9.63:1AA 4.5:1Pass / PassPass / Pass−71.0Lc 60: larger content textOpen in checker
Warning badge label on fill#100f0d on #eea0008.81:1AA 4.5:1Pass / PassPass / Pass+61.1Lc 60: larger content textOpen in checker
Error text on background#ff5263 on #1916105.70:1AA 4.5:1Pass / FailPass / Pass−43.2Lc 30: non-text and incidentalOpen in checker
Error text on surface#ff5263 on #23201a5.13:1AA 4.5:1Pass / FailPass / Pass−42.0Lc 30: non-text and incidentalOpen in checker
Error badge label on fill#100f0d on #ff5a6e6.33:1AA 4.5:1Pass / FailPass / Pass+47.5Lc 45: headlines and large textOpen in checker
Info text on background#1fc6ff on #1916109.09:1AA 4.5:1Pass / PassPass / Pass−63.7Lc 60: larger content textOpen in checker
Info text on surface#1fc6ff on #23201a8.18:1AA 4.5:1Pass / PassPass / Pass−62.5Lc 60: larger content textOpen in checker
Info badge label on fill#100f0d on #00c0ff9.10:1AA 4.5:1Pass / PassPass / Pass+63.0Lc 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 6 Δ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 6
success / warning34.726.941.031.3Shown only
success / error32.731.911.235.6Yes
success / info18.217.717.23.8Shown only
warning / error33.658.549.920.3Shown only
warning / info41.836.848.630.1Shown only
error / info34.734.724.235.8Shown only

Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia

Dark theme, status fills
PairNormal visionProtanopiaDeuteranopiaTritanopiaHeld to 6
success / warning23.313.320.729.8Shown only
success / error35.524.38.337.4Yes
success / info16.215.114.82.9Shown only
warning / error19.022.518.59.1Shown only
warning / info30.826.934.629.4Shown only
error / info34.425.622.136.6Shown only

Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia

Why these colours

The primary is a vivid blue at OKLCH hue 240 with chroma 0.19, well above the restrained values used in other palettes. At the lightness needed for white button labels it is a rich royal blue rather than a pale sky. The accent is an energetic orange at hue 55, the complement of blue, which makes buttons and rewards stand out strongly.

The page background is a warm cream instead of white. It lowers glare and makes the saturated colours feel part of a toy box rather than a medical form. For the quiz states, success is a bluish green and error a red-orange, separated in lightness so a wrong answer is not confused with a right one in the common colour-vision deficiencies.

The generator solved 50 pairs (25 light, 25 dark), and all of them meet their target on the raw WCAG ratio. The tightest is info text on background in the light theme at 4.55:1 against a target of 4.5:1. After gamut mapping to sRGB the light primary keeps 85% of the requested chroma; hue was held throughout.

How to use it

  • Mark right and wrong answers with shapes and words, such as a tick and Correct, in addition to green and red.
  • Keep large touch targets and use the border colour to outline answer buttons so their edges are visible against the page.
  • Use the accent orange for rewards and the primary button, but keep paragraphs of instruction in the strong text colour.
  • Avoid animated colour changes as the only feedback, and respect reduced-motion settings.
  • Keep text on illustrated backgrounds inside a solid panel, since busy art removes the contrast guarantee.

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: #fcf8f0;
  --color-surface: #fffef6;
  --color-text: #1e1a13;
  --color-text-muted: #5d574d;
  --color-primary: #0069c2;
  --color-primary-foreground: #fdfcf8;
  --color-accent: #b53b00;
  --color-border: #948e83;
  --color-focus-ring: #0059b1;
  --color-success: #00825b;
  --color-success-solid: #008459;
  --color-success-solid-foreground: #fdfcf8;
  --color-warning: #a56200;
  --color-warning-solid: #ffba00;
  --color-warning-solid-foreground: #100f0d;
  --color-error: #b3001c;
  --color-error-solid: #db002f;
  --color-error-solid-foreground: #fdfcf8;
  --color-info: #0077bb;
  --color-info-solid: #0078c4;
  --color-info-solid-foreground: #fdfcf8;
}
.dark {
  --color-background: #191610;
  --color-surface: #23201a;
  --color-text: #f3eee4;
  --color-text-muted: #c3bdb1;
  --color-primary: #00caff;
  --color-primary-foreground: #0e0d0b;
  --color-accent: #ff9d2c;
  --color-border: #706b60;
  --color-focus-ring: #00caff;
  --color-success: #00edbe;
  --color-success-solid: #00d5a3;
  --color-success-solid-foreground: #100f0d;
  --color-warning: #ffbc19;
  --color-warning-solid: #eea000;
  --color-warning-solid-foreground: #100f0d;
  --color-error: #ff5263;
  --color-error-solid: #ff5a6e;
  --color-error-solid-foreground: #100f0d;
  --color-info: #1fc6ff;
  --color-info-solid: #00c0ff;
  --color-info-solid-foreground: #100f0d;
}

/* oklch() where supported: the same colours, unclipped values of the hex above. */
@supports (color: oklch(0 0 0)) {
  :root {
    --color-background: oklch(0.980 0.011 84.6);
    --color-surface: oklch(0.996 0.011 100.8);
    --color-text: oklch(0.220 0.014 81.6);
    --color-text-muted: oklch(0.459 0.018 80.6);
    --color-primary: oklch(0.521 0.161 253.0);
    --color-primary-foreground: oklch(0.991 0.005 95.1);
    --color-accent: oklch(0.524 0.167 39.2);
    --color-border: oklch(0.649 0.018 82.8);
    --color-focus-ring: oklch(0.473 0.158 255.4);
    --color-success: oklch(0.537 0.115 163.7);
    --color-success-solid: oklch(0.5420 0.1193 161.76);
    --color-success-solid-foreground: oklch(0.991 0.005 95.1);
    --color-warning: oklch(0.5589 0.1252 65.21);
    --color-warning-solid: oklch(0.8309 0.1714 81.55);
    --color-warning-solid-foreground: oklch(0.169 0.004 84.6);
    --color-error: oklch(0.483 0.196 24.8);
    --color-error-solid: oklch(0.563 0.227 22.5);
    --color-error-solid-foreground: oklch(0.991 0.005 95.1);
    --color-info: oklch(0.549 0.137 244.6);
    --color-info-solid: oklch(0.557 0.147 247.1);
    --color-info-solid-foreground: oklch(0.991 0.005 95.1);
  }
  .dark {
    --color-background: oklch(0.202 0.012 84.5);
    --color-surface: oklch(0.245 0.012 84.6);
    --color-text: oklch(0.950 0.014 84.6);
    --color-text-muted: oklch(0.800 0.018 84.6);
    --color-primary: oklch(0.781 0.149 225.4);
    --color-primary-foreground: oklch(0.159 0.004 84.6);
    --color-accent: oklch(0.780 0.164 63.5);
    --color-border: oklch(0.529 0.018 86.5);
    --color-focus-ring: oklch(0.781 0.149 225.4);
    --color-success: oklch(0.8425 0.1642 171.51);
    --color-success-solid: oklch(0.775 0.157 168.2);
    --color-success-solid-foreground: oklch(0.169 0.004 84.6);
    --color-warning: oklch(0.835 0.168 81.8);
    --color-warning-solid: oklch(0.764 0.162 74.2);
    --color-warning-solid-foreground: oklch(0.169 0.004 84.6);
    --color-error: oklch(0.681 0.208 19.2);
    --color-error-solid: oklch(0.692 0.200 17.0);
    --color-error-solid-foreground: oklch(0.169 0.004 84.6);
    --color-info: oklch(0.774 0.147 228.6);
    --color-info-solid: oklch(0.758 0.153 231.1);
    --color-info-solid-foreground: oklch(0.169 0.004 84.6);
  }
}

Tailwind CSS v4 @theme

@theme {
  /* light */
  --color-background: oklch(0.980 0.011 84.6); /* #fcf8f0 */
  --color-surface: oklch(0.996 0.011 100.8); /* #fffef6 */
  --color-text: oklch(0.220 0.014 81.6); /* #1e1a13 */
  --color-text-muted: oklch(0.459 0.018 80.6); /* #5d574d */
  --color-primary: oklch(0.521 0.161 253.0); /* #0069c2 */
  --color-primary-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
  --color-accent: oklch(0.524 0.167 39.2); /* #b53b00 */
  --color-border: oklch(0.649 0.018 82.8); /* #948e83 */
  --color-focus-ring: oklch(0.473 0.158 255.4); /* #0059b1 */
  --color-success: oklch(0.537 0.115 163.7); /* #00825b */
  --color-success-solid: oklch(0.5420 0.1193 161.76); /* #008459 */
  --color-success-solid-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
  --color-warning: oklch(0.5589 0.1252 65.21); /* #a56200 */
  --color-warning-solid: oklch(0.8309 0.1714 81.55); /* #ffba00 */
  --color-warning-solid-foreground: oklch(0.169 0.004 84.6); /* #100f0d */
  --color-error: oklch(0.483 0.196 24.8); /* #b3001c */
  --color-error-solid: oklch(0.563 0.227 22.5); /* #db002f */
  --color-error-solid-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
  --color-info: oklch(0.549 0.137 244.6); /* #0077bb */
  --color-info-solid: oklch(0.557 0.147 247.1); /* #0078c4 */
  --color-info-solid-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
  /* dark: use as dark:bg-background-dark, or remap under a .dark selector */
  --color-background-dark: oklch(0.202 0.012 84.5); /* #191610 */
  --color-surface-dark: oklch(0.245 0.012 84.6); /* #23201a */
  --color-text-dark: oklch(0.950 0.014 84.6); /* #f3eee4 */
  --color-text-muted-dark: oklch(0.800 0.018 84.6); /* #c3bdb1 */
  --color-primary-dark: oklch(0.781 0.149 225.4); /* #00caff */
  --color-primary-foreground-dark: oklch(0.159 0.004 84.6); /* #0e0d0b */
  --color-accent-dark: oklch(0.780 0.164 63.5); /* #ff9d2c */
  --color-border-dark: oklch(0.529 0.018 86.5); /* #706b60 */
  --color-focus-ring-dark: oklch(0.781 0.149 225.4); /* #00caff */
  --color-success-dark: oklch(0.8425 0.1642 171.51); /* #00edbe */
  --color-success-solid-dark: oklch(0.775 0.157 168.2); /* #00d5a3 */
  --color-success-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
  --color-warning-dark: oklch(0.835 0.168 81.8); /* #ffbc19 */
  --color-warning-solid-dark: oklch(0.764 0.162 74.2); /* #eea000 */
  --color-warning-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
  --color-error-dark: oklch(0.681 0.208 19.2); /* #ff5263 */
  --color-error-solid-dark: oklch(0.692 0.200 17.0); /* #ff5a6e */
  --color-error-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
  --color-info-dark: oklch(0.774 0.147 228.6); /* #1fc6ff */
  --color-info-solid-dark: oklch(0.758 0.153 231.1); /* #00c0ff */
  --color-info-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
}

shadcn/ui variables (:root and .dark)

:root {
  --background: oklch(0.980 0.011 84.6);
  --foreground: oklch(0.220 0.014 81.6);
  --card: oklch(0.996 0.011 100.8);
  --card-foreground: oklch(0.220 0.014 81.6);
  --popover: oklch(0.996 0.011 100.8);
  --popover-foreground: oklch(0.220 0.014 81.6);
  --primary: oklch(0.521 0.161 253.0);
  --primary-foreground: oklch(0.991 0.005 95.1);
  --secondary: oklch(0.996 0.011 100.8);
  --secondary-foreground: oklch(0.220 0.014 81.6);
  --muted: oklch(0.996 0.011 100.8);
  --muted-foreground: oklch(0.459 0.018 80.6);
  --accent: oklch(0.996 0.011 100.8);
  --accent-foreground: oklch(0.220 0.014 81.6);
  --destructive: oklch(0.563 0.227 22.5);
  --destructive-foreground: oklch(0.991 0.005 95.1);
  --border: oklch(0.649 0.018 82.8);
  --input: oklch(0.649 0.018 82.8);
  --ring: oklch(0.473 0.158 255.4);
  --success: oklch(0.5420 0.1193 161.76);
  --success-foreground: oklch(0.991 0.005 95.1);
  --warning: oklch(0.8309 0.1714 81.55);
  --warning-foreground: oklch(0.169 0.004 84.6);
  --info: oklch(0.557 0.147 247.1);
  --info-foreground: oklch(0.991 0.005 95.1);
  --brand-accent: oklch(0.524 0.167 39.2);
}

.dark {
  --background: oklch(0.202 0.012 84.5);
  --foreground: oklch(0.950 0.014 84.6);
  --card: oklch(0.245 0.012 84.6);
  --card-foreground: oklch(0.950 0.014 84.6);
  --popover: oklch(0.245 0.012 84.6);
  --popover-foreground: oklch(0.950 0.014 84.6);
  --primary: oklch(0.781 0.149 225.4);
  --primary-foreground: oklch(0.159 0.004 84.6);
  --secondary: oklch(0.245 0.012 84.6);
  --secondary-foreground: oklch(0.950 0.014 84.6);
  --muted: oklch(0.245 0.012 84.6);
  --muted-foreground: oklch(0.800 0.018 84.6);
  --accent: oklch(0.245 0.012 84.6);
  --accent-foreground: oklch(0.950 0.014 84.6);
  --destructive: oklch(0.692 0.200 17.0);
  --destructive-foreground: oklch(0.169 0.004 84.6);
  --border: oklch(0.529 0.018 86.5);
  --input: oklch(0.529 0.018 86.5);
  --ring: oklch(0.781 0.149 225.4);
  --success: oklch(0.775 0.157 168.2);
  --success-foreground: oklch(0.169 0.004 84.6);
  --warning: oklch(0.764 0.162 74.2);
  --warning-foreground: oklch(0.169 0.004 84.6);
  --info: oklch(0.758 0.153 231.1);
  --info-foreground: oklch(0.169 0.004 84.6);
  --brand-accent: oklch(0.780 0.164 63.5);
}

Design tokens (DTCG-style JSON)

{
  "color": {
    "light": {
      "background": {
        "$type": "color",
        "$value": "oklch(0.980 0.011 84.6)",
        "$description": "sRGB #fcf8f0"
      },
      "surface": {
        "$type": "color",
        "$value": "oklch(0.996 0.011 100.8)",
        "$description": "sRGB #fffef6"
      },
      "text": {
        "$type": "color",
        "$value": "oklch(0.220 0.014 81.6)",
        "$description": "sRGB #1e1a13"
      },
      "text-muted": {
        "$type": "color",
        "$value": "oklch(0.459 0.018 80.6)",
        "$description": "sRGB #5d574d"
      },
      "primary": {
        "$type": "color",
        "$value": "oklch(0.521 0.161 253.0)",
        "$description": "sRGB #0069c2"
      },
      "primary-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.005 95.1)",
        "$description": "sRGB #fdfcf8"
      },
      "accent": {
        "$type": "color",
        "$value": "oklch(0.524 0.167 39.2)",
        "$description": "sRGB #b53b00"
      },
      "border": {
        "$type": "color",
        "$value": "oklch(0.649 0.018 82.8)",
        "$description": "sRGB #948e83"
      },
      "focus-ring": {
        "$type": "color",
        "$value": "oklch(0.473 0.158 255.4)",
        "$description": "sRGB #0059b1"
      },
      "success": {
        "$type": "color",
        "$value": "oklch(0.537 0.115 163.7)",
        "$description": "sRGB #00825b"
      },
      "success-solid": {
        "$type": "color",
        "$value": "oklch(0.5420 0.1193 161.76)",
        "$description": "sRGB #008459"
      },
      "success-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.005 95.1)",
        "$description": "sRGB #fdfcf8"
      },
      "warning": {
        "$type": "color",
        "$value": "oklch(0.5589 0.1252 65.21)",
        "$description": "sRGB #a56200"
      },
      "warning-solid": {
        "$type": "color",
        "$value": "oklch(0.8309 0.1714 81.55)",
        "$description": "sRGB #ffba00"
      },
      "warning-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.004 84.6)",
        "$description": "sRGB #100f0d"
      },
      "error": {
        "$type": "color",
        "$value": "oklch(0.483 0.196 24.8)",
        "$description": "sRGB #b3001c"
      },
      "error-solid": {
        "$type": "color",
        "$value": "oklch(0.563 0.227 22.5)",
        "$description": "sRGB #db002f"
      },
      "error-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.005 95.1)",
        "$description": "sRGB #fdfcf8"
      },
      "info": {
        "$type": "color",
        "$value": "oklch(0.549 0.137 244.6)",
        "$description": "sRGB #0077bb"
      },
      "info-solid": {
        "$type": "color",
        "$value": "oklch(0.557 0.147 247.1)",
        "$description": "sRGB #0078c4"
      },
      "info-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.991 0.005 95.1)",
        "$description": "sRGB #fdfcf8"
      }
    },
    "dark": {
      "background": {
        "$type": "color",
        "$value": "oklch(0.202 0.012 84.5)",
        "$description": "sRGB #191610"
      },
      "surface": {
        "$type": "color",
        "$value": "oklch(0.245 0.012 84.6)",
        "$description": "sRGB #23201a"
      },
      "text": {
        "$type": "color",
        "$value": "oklch(0.950 0.014 84.6)",
        "$description": "sRGB #f3eee4"
      },
      "text-muted": {
        "$type": "color",
        "$value": "oklch(0.800 0.018 84.6)",
        "$description": "sRGB #c3bdb1"
      },
      "primary": {
        "$type": "color",
        "$value": "oklch(0.781 0.149 225.4)",
        "$description": "sRGB #00caff"
      },
      "primary-foreground": {
        "$type": "color",
        "$value": "oklch(0.159 0.004 84.6)",
        "$description": "sRGB #0e0d0b"
      },
      "accent": {
        "$type": "color",
        "$value": "oklch(0.780 0.164 63.5)",
        "$description": "sRGB #ff9d2c"
      },
      "border": {
        "$type": "color",
        "$value": "oklch(0.529 0.018 86.5)",
        "$description": "sRGB #706b60"
      },
      "focus-ring": {
        "$type": "color",
        "$value": "oklch(0.781 0.149 225.4)",
        "$description": "sRGB #00caff"
      },
      "success": {
        "$type": "color",
        "$value": "oklch(0.8425 0.1642 171.51)",
        "$description": "sRGB #00edbe"
      },
      "success-solid": {
        "$type": "color",
        "$value": "oklch(0.775 0.157 168.2)",
        "$description": "sRGB #00d5a3"
      },
      "success-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.004 84.6)",
        "$description": "sRGB #100f0d"
      },
      "warning": {
        "$type": "color",
        "$value": "oklch(0.835 0.168 81.8)",
        "$description": "sRGB #ffbc19"
      },
      "warning-solid": {
        "$type": "color",
        "$value": "oklch(0.764 0.162 74.2)",
        "$description": "sRGB #eea000"
      },
      "warning-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.004 84.6)",
        "$description": "sRGB #100f0d"
      },
      "error": {
        "$type": "color",
        "$value": "oklch(0.681 0.208 19.2)",
        "$description": "sRGB #ff5263"
      },
      "error-solid": {
        "$type": "color",
        "$value": "oklch(0.692 0.200 17.0)",
        "$description": "sRGB #ff5a6e"
      },
      "error-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.004 84.6)",
        "$description": "sRGB #100f0d"
      },
      "info": {
        "$type": "color",
        "$value": "oklch(0.774 0.147 228.6)",
        "$description": "sRGB #1fc6ff"
      },
      "info-solid": {
        "$type": "color",
        "$value": "oklch(0.758 0.153 231.1)",
        "$description": "sRGB #00c0ff"
      },
      "info-solid-foreground": {
        "$type": "color",
        "$value": "oklch(0.169 0.004 84.6)",
        "$description": "sRGB #100f0d"
      }
    }
  }
}

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 #0069C2 in the OKLCH picker →Build a tonal scale →Check a pair

FAQ

Can bright colours really be accessible?
Yes. Contrast depends on lightness difference, not saturation. The solver holds chroma and hue and only adjusts lightness, so the colours stay lively, and the table shows each pair's measured ratio.
Which age group is this for?
It suits early readers through primary school. It makes no medical or developmental claims; it applies the standard WCAG contrast criteria with extra headroom for text.
Why a cream background?
Pure white next to saturated colour can feel harsh, especially on bright screens. A light warm tone keeps contrast high while feeling softer. The value is verified like every other pair.
What about children with colour blindness?
The success and error fills are checked under simulated protanopia, deuteranopia and tritanopia. You should still add icons or text, as WCAG 1.4.1 asks.

← All accessible palettes