An OKLCH palette forge. Pick one colour, get a tonal ramp at constant hue, and see the actual sRGB boundary it has to live inside. The two mapping strategies are shown together because the difference between them is the whole point.
Lightness runs left to right, chroma bottom to top, and the painted region is every colour a screen can actually show at this hue. The ceiling is the gamut boundary. The peak of it is the cusp: the most saturated this hue gets, and the lightness it happens at. White dots are your ramp steps after mapping; a hollow dot marks a step whose requested chroma was outside the boundary and had to be brought in.
Both rows asked for exactly the same colours. The top row bisects on chroma
with hue and lightness pinned, which is what a gamut mapper should do. The bottom row clips
each sRGB channel independently, which is what your browser does with an out-of-gamut
oklch(). When the rows differ, the bottom one has drifted off your hue.
The ramp assigned to tokens and rendered both ways, with WCAG 2.2 contrast measured on the pairs that actually occur. 4.5 is the AA floor for body text, 3.0 for large text and for a border carrying meaning.
Custom properties for both themes, plus the ramp as raw steps. Hex, because it
works everywhere; the oklch() originals are in the comment so the intent
survives.