Field guide · how it was built
The drought, rendered
PLAYA is a fictional desiccation survey of Kestrel Flat, a dry lake that hasn't taken measurable rain in years. Its single job is to make deep time legible: to let a visitor watch a mud crust dry — contracting into polygons, curling at every rim, and whitening with salt — over seasons compressed into seconds. The audience is anyone who has stood on a cracked lakebed and wondered how long it took.
The signature
The crust is a single raw-WebGL fragment shader — no three.js, no textures. A fullscreen triangle runs an Inigo-Quilez-style Voronoi border metric: a first pass finds the nearest cell centre, a second measures the distance to the edge between it and its neighbours. That edge distance is the crack. The point field is domain-warped by value-noise fbm so the polygons read organic rather than gridded.
A single dryness uniform drives everything, grown on an exponential curve — dry = 1 − e^(−0.108 · seasons) — so early seasons crack fast and late ones asymptote, the way a real playa does. Rising dryness widens the crack mask and the curl rim, deepens the relief, and pushes the whole surface toward salt-white. Above 0.58 a second, higher-frequency Voronoi layer fades in, so fresh hairline cracks visibly propagate through the plates as the drought deepens.
The curl is the trick that sells it: using OES_standard_derivatives, the screen-space gradient of the plate-height field becomes a surface normal, lit by a low raking sun. Plate interiors stay flat and bright; rims — where the gradient is steep — catch the light and lift, while crack troughs fall into shadow. Turn up the dryness and the relief deepens, so the flat visibly becomes a tilework of shallow, upturned dishes.
Palette — argued from the salt flat
The concept's danger was contrast: a bright playa is a light background, and gold-on-tan is the collection's most repeated readability failure. So the accent (brass) drives only lines and marks; every run of text uses a dedicated dark ink (silt-ink or the stronger #3B2E14) that clears 4.5:1.
Type
Archivo at 800 sets the wordmark and the monumental PLAYA — a dense, geometric grotesque that packs into a tight, cracked-earth mass at display size, the one moment of typographic bravery. Space Mono handles every reading — seasons, days, humidity — giving the drought instrument the deadpan authority of a logged field measurement.
Techniques
Raw WebGL fragment shader for the crust (Voronoi border + fbm warp + derivative-lit curl). DOM & CSS for the whole instrument panel and layout. An inline SVG polyline sparkline for the humidity strip, shifted and redrawn in JS each half-second. No animation library — the loop is a plain rAF with a clamped delta, paused on document.hidden and when the field scrolls off-screen. DPR is capped at 2 behind a 1500px quality clamp; a WebGL-context failure drops to a static CSS crack scene.
Iteration log
-
Pass 1 · Craft
Sharpen the rims, secure the contrast
Tightened the crack anti-aliasing so polygon edges read crisp rather than rubbery. Audited every text run against the warm paper and moved body/labels onto the darker silt-ink (#5C4A2E) and ink (#3B2E14) tokens — all copy now clears 4.5:1, with brass held back for marks. Confirmed exactly one real h1 and evened the season-bar and metric baselines.
-
Pass 2 · Depth
Make the drought visibly salt and propagate
Added a global aridity whitening — past dryness 0.6 the whole crust mixes toward salt-white, so advancing a season now visibly pales the playa. Enriched the signature with the second higher-frequency Voronoi layer, so new hairline cracks propagate through the plates as it dries. Added the "Plate map" overlay as the second-read detail: it paints the ochre polygon boundaries the eye had been inferring.
-
Pass 3 · Hardening
375px, reduced motion, and one tag removed
Verified 375px headlessly — wordmark and nav sit inside the viewport, scrollWidth is exactly 375, zero offenders. Removed the redundant "Drying" corner tag below 560px where it collided with the survey caption (the Chanel-rule cut). Confirmed the reduced-motion path renders a single settled frame at dry≈0.66 with the rAF loop never started, and that focus rings, resize, and the visibility pause all hold. No console errors at any width.