Method
How Percevra computes light-aware color
Last reviewed: September 25, 2026
Percevra claims that a palette behaves differently under different light, and that the difference can be measured. This page is the evidence for that claim: the illuminants and standards behind them, the color space the math runs in, the exact formula for the separation diagnostic, the blinded study that tested whether that diagnostic matches human perception (it does not — reported in full below), and the things the model cannot see.
Every threshold, band, and white point below is read directly from the running engine rather than transcribed into prose. If we retune the model, this page changes with it.
The pipeline
One engine, one clamp. The pipeline stays in unclamped linear light from the illuminant cast through chromatic adaptation, and only encodes to sRGB at the very end. That ordering is load-bearing rather than fussy: under a correct Illuminant A about 45% of colors leave the display range at the simulate stage, and clipping is irreversible, so encoding early would mean scoring data the display had already destroyed.
Simulatescene-referred
Your palette is re-lit by the illuminant — reflected = surface × light — as a von Kries scaling in CAT16 cone space rather than a multiply in RGB primaries. That choice is deliberate: adaptation happens in cone space, and casting the light in a different basis leaves a residue the two stages can never cancel. Nothing is clamped here, so a strong lamp can push bright swatches past 1.0 and those values carry forward rather than clip. Daylight is a true no-op, so D65 never quietly restyles your colors.
Adaptstill unclamped
The stimulus is chromatically adapted back toward D65 with CAT16 at a fixed degree of adaptation D = 0.6, modelling a viewer whose eyes have partly settled into the room. Because stage one casts in the same space, this is an exact partial inverse: at D = 1 it would recover your original color precisely, so what survives here is cleanly the 40% of the cast a partly-adapted viewer still sees.
Measure and displayone clamp, at the end
The adapted color is measured in OKLab for the score, and separately encoded to sRGB for the diagnostic swatch shown on this page. Both read the same stage, so this page's swatches and numbers can never tell different stories, and the score is taken before the display encoding throws anything away. (Product preview surfaces — palette cards, the Light Profile, studios — render a separate spectral pipeline at a gentler adaptation degree; see the illuminants section below.)
Which illuminants we simulate
The illuminant names are CIE standards—we did not invent the physics, and the tables below let you check our numbers against the published ones. What differs between our two engines is how much of each standard they reproduce: the tint model matches the illuminant's white point, and the spectral model matches its full spectrum.
Scoring — tint model
The stability diagnostic uses a three-channel linear-RGB multiply. The multipliers are not chosen by eye: each one is derived from its illuminant's published CIE chromaticity at constant luminance, so the white the engine adapts to is the standard's white by construction. The two right-hand columns below are the check — the left is computed live from the running engine, the right is transcribed from the standards. They should agree to four decimal places.
Product previews no longer use this model. Palette cards, the Light Profile, mood and decision previews, and Extract render the spectral pipeline (reflectance reconstructed from each hex, integrated against the lamp's SPD, then CAT16) at a display adaptation of D = 0.85 — a settled viewer — while the diagnostic keeps its harsher D = 0.6 stress test. One preview condition also differs from its diagnostic counterpart by design: the “Blue-sky shade” stop previews a daylight-locus 10000K proxy (shade lit only by clear sky — an estimate, not a measured spectrum), because the diagnostic's CIE D75 is chromatically so close to D65 that a preview of it is visually inert. The diagnostic below still measures CIE D75.
One row does not agree, and it is worth naming. Candlelight at 1900K falls outside the sRGB gamut: reproducing it exactly needs a negative blue multiplier. Its multipliers are clamped to the gamut boundary, which is why its white lands a few ten-thousandths off. Candle is preview-only and never enters a score.
| Illuminant | Standard | Used for | Adapting white (x, y) | CIE tabulated (x, y) |
|---|---|---|---|---|
| DaylightD65 | CIE D65 | Reference | 0.3127, 0.3290 | 0.3127, 0.3290 |
| Warm2700K | CIE Illuminant A | Diagnostic | 0.4476, 0.4074 | 0.4476, 0.4074 |
| Neutral LED4000K | CIE LED-B3 | Diagnostic | 0.3756, 0.3723 | 0.3756, 0.3723 |
| Shade7500K | CIE D75 | Diagnostic | 0.2990, 0.3149 | 0.2990, 0.3149 |
| FluorescentF11 | CIE F11 (TL84) | Diagnostic | 0.3805, 0.3769 | 0.3805, 0.3769 |
| Warm daylightD50 | CIE D50 | Preview only | 0.3457, 0.3585 | 0.3457, 0.3585 |
| Candle1900K | Planckian 1900K | Preview only | 0.5368, 0.4100 | 0.5381, 0.4112 |
| Nightmoon | Non-standard | Preview only | 0.2753, 0.2879 | — |
Only 3 of these eight (A, LED-B3, Shade) feed the separation diagnostic below; D65 is the fixed reference it is measured against. A pass/warn/fail badge was formerly judged on A, F11, LED-B3 — it was retired after blinded perceptual testing (see “Does the diagnostic match what people see?” below). Candle, Night, and D50 are visualization only and never affect a number.
Light-Aware Lab — spectral model
The Light-Aware Palette Lab runs the real thing: tabulated CIE relative spectral power distributions for D65, D50, A, F11, and LED-B3, sampled from 380–780 nm at 5 nm intervals (81 samples), integrated against the CIE 1931 2° standard observer color-matching functions. Continuous color temperatures are generated from the Planckian locus or the CIE daylight locus as appropriate. The reference data is generated from colour-science 0.4.7 and committed to the repository rather than fetched at runtime, so results are reproducible.
This path can express spectral effects the tint model cannot, because it integrates a reflectance curve against a real lamp spectrum. It is still working from a reflectance recovered from your hex value, not one measured off your material.
What the math runs in, and why
OKLab / OKLCh
All perceptual distances are Euclidean in OKLab. Unlike HSL, equal numeric steps correspond to roughly equal perceived steps, and unlike CIELAB it stays well behaved for saturated blues, where CIELAB bends hue lines badly. OKLCh is the same space in polar form, so lightness, chroma, and hue readouts and the ΔE that scores them are the same measurement, not two that can disagree.
Distances are scaled ×100 so they land on the familiar ΔE range. On this scale roughly 4 units is a just-noticeable difference in context and 10 units is a comfortably distinct pair.
Linear RGB and CIE XYZ
Light mixes linearly; sRGB does not. Every simulation step is done after undoing the sRGB transfer function, then re-encoded for display. Adaptation runs in CIE XYZ, reached through the standard sRGB primaries matrix.
Whites are normalized to Y = 1, so adaptation only discounts the color of the light and never silently changes luminance.
CAT16 chromatic adaptation
The cone-response transform from CIECAM16 (Li et al., 2017), applied as a partial von Kries scaling from the illuminant's white toward D65. It is better behaved than Bradford in the blue region. The degree of adaptation is fixed at D = 0.6 — not adjustable, because it is the assumption the whole verdict rests on and a slider would let anyone tune their way to a nicer score.
The spectral appearance path in the Lab uses a full von Kries Bradford transform instead; the spectral surface path uses CAT16 at the same D.
Where other metrics are used
OKLab ΔE is the currency for lighting. Two places deliberately use something else: print-gamut and color-naming comparisons use CIEDE2000, which remains the industry reference for small-difference tolerancing, and contrast readouts use APCA alongside WCAG 2 ratios.
The emotional-character score (ECS) is a heuristic over palette statistics. It is not a CIE-defined quantity and should not be read as one.
How the separation diagnostic is computed
Every color shifts under a warm bulb. A uniform cast is physics, not a defect, so measuring absolute shift would mostly measure the lamp. What this diagnostic measures instead is whether the palette's internal structure survives: if two colors were clearly different in daylight, are they still clearly different under this light? It is a well-defined physical quantity — and, as the validation section below reports, one that turned out not to track what people perceive as a palette breaking, which is why it no longer grades anything in the product.
for each pair (i, j) in the palette:
d_base = ‖ OKLab(cᵢ) − OKLab(cⱼ) ‖ × 100 // separation at D65
skip the pair if d_base < 10 // never distinct to begin with
d_lit = ‖ OKLab(lit(cᵢ)) − OKLab(lit(cⱼ)) ‖ × 100
retention(illuminant) = min over surviving pairs of ( d_lit / d_base )
collapsed = any d_lit < 4
stability % = min( retention ) over A, LED-B3, Shade × 100
where lit() is read at two points in the pipeline:
settled = adapt(simulate(c), D = 0.6) // partly adapted viewer
first glance = simulate(c) // D = 0, unadapted worst caseWhy there are two numbers
The same formula is read at two points in the pipeline, and the honest reason is worth stating plainly: the settled number cannot fail. Once the illuminant is cast in cone space, adaptation is an exact partial inverse of it, so a viewer whose eyes have adjusted recovers almost all of the original separation. That is not a loophole in the model — it is colour constancy, and it is the correct result. But it means the settled score is a high, narrow quantity: we searched adversarially for the worst palette it can produce and could not drive it below 78%.
The first-glance figure — the unadapted stimulus, the moment you walk into the room before your eyes do any work — spans roughly 43–100 and was historically the graded number. Those grades are now retired (see the validation section below); both figures remain documented here as diagnostics. The gap between the two is still an honest reading: a palette whose numbers sit far apart is one that only holds together once the room has settled.
It is worst-case twice over: the weakest surviving pair within a light, and then the weakest light of the three. A palette fails at its weakest relationship under its worst condition, not on average, and reporting an average across lights would let a palette that collapses under a warm bulb be rescued by holding up under two others. Retention is a ratio of distances, so it is dimensionless and comparable across palettes of different overall contrast.
Inputs and thresholds
- Distinct at base
- ΔE ≥ 10 pairs closer than this are not measured
- Collapse
- ΔE < 4 roles have merged under the light
- Retention pass
- ≥ 0.7 per-illuminant status ok
- Retention warn
- ≥ 0.45 below this, or collapsed, is a fail
- Adaptation degree
- D = 0.6 settled view; first glance is D = 0
- Minimum palette
- 2 colors fewer returns no score at all
What a number means
Either percentage is the share of the palette's weakest color relationship that survives under its worst light. A first glance of 90% means the pair most at risk still holds about nine tenths of the separation it had in daylight.
Neither percentage carries a grade any more. The five stability bands (Excellent → Sensitive) that used to grade the first-glance figure were retired in September 2026 after blinded perceptual testing found the metric does not predict what people judge as a palette breaking — the section below reports that study in full. The numbers remain published here as physical diagnostics.
A worked example
This palette is run through the live engine every time the page loads, so you can reproduce the arithmetic below rather than take it on faith.
#0B3C49#137A7F#7FB8B0#E4DFD0#C46D5E
| Illuminant | Mean shift (ΔE) | Retention, settled | Retention, first glance | Status | In headline |
|---|---|---|---|---|---|
| A Incandescent | 3.8 | 93.1% | 87.6% | ok | yes |
| LED-B3 | 2.1 | 97.7% | 93.9% | ok | yes |
| Open Shade | 0.6 | 100.0% | 100.0% | ok | yes |
| F11 Fluorescent | 1.6 | 91.0% | 88.4% | ok | no |
Worst retention across A, LED-B3, Shade: 93% settled, 88% at first glance. Both are set by Illuminant A, the hardest of the three for this palette. The mean shift column describes how strong each cast is; it does not enter the retention figures.
The second score: MSS
The Material Stability Score answers a different question—absolute drift rather than preserved separation—and is used where a color has to hit a target rather than merely stay distinguishable. Per color it is 1 − max(ΔE across illuminants) / threshold, clamped to 0–1, where the threshold tightens by use case. A palette's MSS is 70% of the mean plus 30% of the worst swatch, so one fragile color cannot be averaged away.
- 14Print
- 15UI
- 16Architecture
- 17Textile
- 20Interior
- 18Default
Thresholds are in the same OKLab ΔE ×100 units. Print is tightest because a proof is judged against a target; interior is loosest because a wall is judged against its own room.
Does the diagnostic match what people see?
In September 2026 we tested it, blind. A reviewer judged palettes shown as-authored beside their simulations under real lamps — no scores, categories, or metric values visible — across two rounds (79 palettes, then a 30-palette confirmation with hidden repeats, near-miss controls, and anchors). The question each time: did the palette’s internal relationships materially change?
The result was decisive and negative: separation retention — settled or first-glance — predicts those judgments at chance level. Palettes with the lowest retention were mostly judged fine; palettes judged broken were scattered across the whole retention range. What people actually track is hue: the judged failures were overwhelmingly pale, low-chroma cool swatches flipping to warm (a pale cyan reading as peach under an incandescent lamp), a signal that per-palette retention averages are structurally blind to.
So we changed the product before changing this page’s math: the pass/warn/fail badge, the stability grades, and every public retention percentage were withdrawn, and surfaces now describe simulations (“previewed across lighting conditions”) rather than issue verdicts. A candidate replacement — a per-swatch pale-flip event defined in Cartesian opponent coordinates — is under pre-registered blinded testing now, and no verdict language returns until a metric passes it. The retention formulas above remain published because they are honest physics and useful diagnostics; they are simply not proof that a palette will look broken or fine to a person.
What the model does not capture
This is the most useful section on the page. A model is only trustworthy to the extent its edges are known, so these are stated as specifically as we can rather than hedged.
Surface finish and geometry
Every color is treated as an ideal flat matte patch. Gloss, sheen, metallic and pearlescent flake, weave, pile direction, texture, translucency, and the angle you stand at all change appearance, and none of them are inputs. A gloss and a matte mix of the same pigment score identically here and will not look identical on a wall.
Metamerism from real pigments
The product path scales three cone responses. A real lamp is a spectrum and a real pigment is a reflectance curve, so two colors that match under one light can separate under another at the same color temperature. No three-channel model can see that, however well chosen its basis. The Light-Aware Lab's spectral path narrows the gap, but it recovers a plausible reflectance from a hex value rather than measuring your actual material.
Display calibration
Results are computed and drawn in sRGB and assume a reasonably calibrated display. Panel technology, gamut, brightness, color profile, ambient light in your own room, night-shift filters, and browser color management all shift what reaches your eye before any of this math matters.
Observer variance
The spectral path uses the CIE 1931 2° standard observer — an average derived from a small mid-century panel, and not a stand-in for any individual. Color vision differs between people, with age, and across field sizes. The degree of adaptation is likewise fixed rather than fitted to a viewer or a room — one value for the diagnostic (D = 0.6) and one for product previews (D = 0.85).
Materials, scale, and surroundings
From a bare hex code the engine infers behavior; it does not know your paint's formulation, substrate, batch, or age. It also scores colors in isolation, so it cannot account for area, adjacency, shadow, inter-reflection between surfaces, or the way a color reads differently on a chip and across a whole room.
The adaptation degree is an assumption, and it decides the answer
D = 0.6 is a deliberate choice representing partial adaptation — mixed lighting, a screen in a lit room, a viewer who has adjusted but not fully. It is not a measurement, and it is the single most consequential number on this page. Sweeping D from 0 to 1 moves the median diagnostic for random palettes from roughly 69 to 99, so almost any stability claim could be manufactured by choosing a different D. We fix it and publish it precisely so the choice is visible rather than load-bearing and hidden.
A settled viewer will see less drift than the score implies
Chromatic adaptation is real and it is strong. Someone who has been in a room for a few minutes discounts most of the lamp's cast, and at D = 1 would recover your palette's separation almost exactly. The first-glance figure deliberately describes the harsher moment before that happens, so treat it as a worst case rather than a prediction of everyday experience.
Known limits of the score itself
Separately from what the physics misses, the stability metric has properties worth knowing before you quote it.
- It does not predict human judgment. Blinded testing (see the validation section above) found both retention readouts perform at chance against what reviewers perceive as a palette materially breaking under a lamp. Quote either number as a measured property of the simulation, never as evidence a palette will look stable.
- Scores are not comparable across palette sizes. More colors means more pairs, and the score reports the weakest one, so a seven-color palette is structurally harder to keep stable than a three-color palette. Median first-glance scores across random palettes fall from roughly 79 at three colors to 67 at five and 61 at seven. Compare a palette against alternatives of the same size, not against a number you remember from elsewhere in the app.
- Low-contrast palettes score perfectly by construction. Pairs closer than ΔE 10 in daylight are excluded from the measurement, so a palette of five near-identical tints has nothing to lose and returns 100%. That is the metric declining to comment, not an endorsement.
- It is silent about absolute appearance. A palette can keep all of its internal separation while every color shifts a long way from what you specified. Retention will not catch that; the mean shift figure and MSS will.
- It scores three lights, not your light. Warm 2700K, cool 4000K, and shade are stand-ins for common conditions. A low-CRI lamp, a colored wall bouncing light, or a mixed-source room is not represented.
- The settled score is close to a formality. It has a floor near 78% even for palettes built adversarially to break it, so a high settled number is weak evidence on its own. Read it as confirmation that adaptation is doing its job, and take the disagreement between it and the first-glance figure as the real signal.
Standards referenced
- CIE 15:2018 — colorimetry, standard illuminants D65, D50, A, and the F and LED series
- CIE 1931 2° standard observer color-matching functions
- CIECAM16 / CAT16 chromatic adaptation transform (Li et al., 2017)
- IEC 61966-2-1 — sRGB color space and transfer function
- OKLab / OKLCh perceptual color space (Ottosson, 2020); CSS Color 4
- CIEDE2000 color-difference formula, used for print gamut and color naming
- WCAG 2.2 contrast ratios and APCA lightness contrast, used for accessibility readouts
This page describes how the model works. For what its output can and cannot be used to claim—and why physical samples still decide consequential specifications—see Color Accuracy & Real-World Verification.
Color accuracyGuide: how colors change under lightLight-Aware Palette LabTerms of Use
