FIELD GUIDE — HOW THIS PAGE WAS BUILT
A build log for the Hadal Institute site: the concept, the palette, and the canvas machinery that turns a scrollbar into a dive to 10,935 metres. Everything on the main page is drawn in code — there is not a single image file on this site.
A deep-sea research institute pitching donors on trench science. The page's one job: take you to the bottom of the Challenger Deep and make you care. So the page is the dive — scroll position maps to depth, the water colour darkens on a physical curve, a fixed instrument rail reads out depth, pressure, temperature and sunlight, and bioluminescent life only appears once the sun is mathematically gone. Structure encodes truth: the five chapters are the five real pelagic zones, and every divider sits at a real boundary depth.
Surface teal falling to absolute black, with two kinds of light in the dark: cold biology (cyan, violet) and warm machinery (instrument amber). Amber is reserved for the Institute's hardware — the HUD, the lander, the CTA — so the eye learns the rule: blue is life, amber is us.
The rule that keeps it disciplined: the grotesk narrates, the mono measures. If a machine wouldn't print it, it isn't set in mono.
Depth mapping. Invisible sentinel elements carry data-depth at real zone boundaries (0, 200, 1,000, 4,000, 6,000, 10,935 m). The engine records their document positions and piecewise-lerps the scroll position between them — so the meter honours the science even though the chapters have different heights:
function depthAt(scroll) {
const y = scroll + H * 0.6; // reading line
for (let i = 0; i < pts.length - 1; i++) {
const a = pts[i], b = pts[i + 1];
if (y < b.y) return a.d + (b.d - a.d) * ((y - a.y) / (b.y - a.y));
}
return 10935;
}
Light that obeys physics. Water colour interpolates through eight depth-keyed RGB stops, and the HUD's sunlight readout is a real exponential decay — about 1% of light survives to 200 m, effectively zero past 1,000 m:
const lightPct = d => 100 * Math.exp(-d / 43.4);
const pressureAtm = d => 1 + d / 10.06; // one atmosphere per ~10 m
Bioluminescence. One full-viewport canvas, three particle fields, all composited with globalCompositeOperation = "lighter" so overlapping glows add like light. Marine snow parallaxes upward as you sink; plankton pulse on per-particle sine phases; siphonophores are bead-chains riding a travelling sine wave. Each field has a density function of depth, so life appears exactly where it should:
function planktonDensity(d) {
if (d < 220) return 0; // sunlit: nothing glows
if (d < 900) return (d - 220) / 680 * .85; // twilight ramp
if (d < 6000) return 1; // midnight: full bloom
return 0.55; // hadal: sparse, alive
}
Reduced motion. With prefers-reduced-motion, the animation loop is replaced by single renders on scroll: the water still darkens and the meter still reads depth (both are scroll-driven, not time-driven), but nothing pulses or drifts.