Click a loose shard on the pattern (or a ghost slot in the window) to pick it up. Click a glass swatch to glaze the selected piece. Click a piece in the window to select it. "Start crafting" fits the remaining shards one by one.
Nothing selected.
Curve: transmission T(wavelength) = exp(-alpha x) of the piece; colour bar: visible spectrum 380 to 720 nm.
Drag to orbit, wheel / pinch to zoom, right-drag to pan. Arrow keys orbit when the scene has focus.
The science
Absorption. Coloured glass is clear glass with dissolved colourants that absorb some wavelengths. Light of wavelength lambda crossing a thickness x keeps the fraction T = I/I0 = exp(-alpha(lambda) x) (Beer-Lambert law). Doubling the thickness squares T, so thick ruby glass goes nearly black while thin glass looks pale. Two stacked sheets multiply their transmissions: T = T1 T2 (ruby over blue is almost opaque).
Colour. The page integrates the transmitted spectrum with the CIE 1931 colour-matching functions (analytic multi-lobe fits) and converts to linear sRGB: RGB = sum over lambda of I0(lambda) T(lambda) cmf(lambda). The sunlight is a 5778 K black body dimmed by Rayleigh scattering along the air mass 1/sin(elevation), so a low sun is redder: the Sunlight slider sets the sun's elevation (12 to 70 degrees) and the brightness.
Mixing on the table. Each piece throws a coloured patch on the bench along the sun's direction. Where patches overlap their light adds, C = sum w_i C_i; the "average colour" readout is that weighted sum with the pieces' areas as weights.
Honest simplifications. The absorption curves are smooth MODEL curves placed where real colourants absorb (gold/selenium ruby, iron-sulphur amber, chromium green, cobalt blue), not measured data. No reflection at the glass surfaces, no scattering or texture of real hand-made glass, no flashed layers beyond a second sheet, a single distant sun, the window glow is a stylised emissive rendering and the diffuse sky behind the window is not simulated. The pattern (two roses, leaves, background) is an invented design; the layout is not a copy of any historic window.
Check. node scripts/check.mjs verifies T(2x) = T(x)^2, 5 nm against 1 nm integration, glass colours, stacking, the linearity of sum w_i C_i, and the sun's reddening with air mass. Virtual workshop only: real glass cutting and lead work need training, eye protection and cut-resistant gloves.