# Iridescent Plate

Study 11 places *Red Meridian* under a simulated coating. A band of daylight crosses the ochre disc and dark crescent. At a steeper incidence angle it moves down the plate and cools. With the angle held steady, changing the thickness changes the band’s colour in place.

| Output | Angle | Nominal thickness |
| --- | ---: | ---: |
| [Live study](./index.html) | 28° at launch | 205 nm at launch |
| [First light](./cover.png) | 28° | 205 nm |
| [Oblique](./oblique.png) | 68° | 205 nm |
| [Thicker](./thicker.png) | 28° | 267 nm |

The three stills are 1000 × 760 pixel exports of the same live canvas. The plate uses the square interior of [Iana Kochu’s original painting photograph](../../assets/red-meridian.jpg). The render crops the easel and backdrop, with a warm exposure adjustment and light falloff applied to the paint pixels. The plaster, bronze bezel and shadow are drawn around that crop.

## Optical model

The model treats the surface as air (`n₀ = 1`), one coherent dielectric film (`n₁ = 1.95`) and a semi-infinite substrate (`n₂ = 1.48`). Angle is measured from the surface normal in air. Snell’s law sets the propagation angles in film and substrate. The round-trip phase inside the film is `φ = 4π n₁ d cos(θ₁) / λ`, where `d` and vacuum wavelength `λ` are in nanometres.

For each of s and p polarization, the two interfaces supply signed Fresnel amplitude coefficients `r₀₁` and `r₁₂`. The single-layer coherent reflection amplitude is `(r₀₁ + r₁₂ exp(iφ)) / (1 + r₀₁ r₁₂ exp(iφ))`. The denominator accounts for repeated internal reflections. Unpolarized reflectance is the mean of the two squared amplitude magnitudes. At zero thickness this reduces to the air–substrate reflectance. The real, constant indices are illustrative and assume lossless, nondispersive materials. [Steven J. Byrnes, *Multilayer optical calculations*, sections 3–4](https://arxiv.org/html/1603.02720v5#S3)

The spectrum and swatch use the selected angle and nominal thickness. At 205 nm, the strongest sampled reflection shifts from 515 nm at 28° to 470 nm at 68°. At 267 nm and 28° it is at 675 nm. At 28° the zero-thickness reflectance is spectrally flat at about 3.9%.

The renderer integrates reflectance times D65 spectral power times the CIE 1931 2° colour-matching functions from 380 to 780 nm in 5 nm steps, normalizing by the Y of an ideal white reflector under D65. It converts the resulting XYZ to linear sRGB, combines it with the source paint, and clips and encodes for display. The spectral table is reused from [Hidden Colour](../hidden-colour/README.md), with CIE dataset attribution and [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) applying to the table. [CIE 1931 observer](https://cie.co.at/datatable/cie-1931-colour-matching-functions-2-degree-observer), [CIE D65](https://cie.co.at/datatable/cie-standard-illuminant-d65), [W3C colour conversion](https://www.w3.org/TR/css-color-4/#color-conversion-code)

The plate varies the local thickness around the control value, with small variations along the photographed brushwork. Variation ramps to zero at 0 nm. A shaped highlight moves down as the angle increases. Luminance gradients in the photograph carry the paint texture through the reflection. The scene blends that gloss with a separately lit paint photograph. The spatial thickness field, gloss intensity, lamp position and refractive indices are design choices. The underlying paint has no measured spectral, relief or absorption data, and the scene has no measured lighting geometry. The spectral plot is the idealized film calculation, while the full plate is an illustrative composite.

## Verification

Run the optical checks with `node --test optics.test.mjs` from this directory. The five tests cover the bare Fresnel interface at normal and oblique incidence, analytical quarter- and half-wave points, reflectance bounds over the control range and local variation, angle and thickness sensitivity, and neutral D65 integration.

With Chrome and Playwright available, serve the `kochu-studio` directory at port 4387 and run `node verify.mjs`. Set `PLAYWRIGHT_PACKAGE` to the bundled Playwright package path if it lives outside Node’s module resolution. The script checks both sliders by keyboard, all presets, the artwork and spectrum updates, touch at 390 px without horizontal overflow, disabled JavaScript, and a failed source-image load. It compares each saved PNG to the same live Chrome canvas state byte for byte. Run `node verify.mjs --capture` to regenerate the three PNGs.
