Brightness is how light or dark a color appears. Color spaces expose related controls differently: HSL lightness runs from black at 0% to white at 100%, while LAB and OKLCH use a lightness axis. In HSL, 50% is normal brightness; in OKLCH, lightness is designed to correspond more closely to perceived brightness. section 7.1.2 section 7.1.4
Do not treat RGB channel values as a direct measure of perceived brightness. Human vision is more sensitive to green and less sensitive to blue, so RGB-to-grayscale conversion uses a weighted average rather than a simple channel average. section 7.2.1
Build a consistent color scale
Keep OKLCH chroma and hue fixed, then vary lightness: `oklch(0.8 0.15 350)`, `oklch(0.6 0.15 350)`, and `oklch(0.4 0.15 350)` create light, medium, and dark versions of one brand color. Unlike HSL hue rotation, OKLCH hue adjustments retain the same perceived brightness. section 7.1.4
For dark mode, simple RGB inversion can distort relative contrast and make muted colors garish. A more controlled starting point is to invert lightness while retaining hue and saturation, then reduce saturation or chroma, optionally shift hue, and test contrast against the new background. section 7.5.1 section 7.5.4
Listing 7.3 Converting RGB to grayscale using a weighted average
function rgbToGrayscale(r, g, b) {
return 0.299 * r + 0.587 * g + 0.114 * b; #1
}
Use the weighted RGB formula to see why equal channel averaging does not match apparent brightness. section 7.2.1






