06 / 25 · field notes
How DESCENT is made
One page, ten kilometres tall. The whole site is a single continuous fall from daylight to the Challenger Deep, and every system on it answers to the scrollbar.
One scroll, 10,935 metres
The page is roughly nine viewport-heights of ocean. Scroll position becomes depth through a piecewise-linear map whose anchor points are read from the DOM itself: every encounter carries a data-depth attribute, and at layout time the script measures each section's centre and pairs it with its depth. The meter therefore always reads exactly 400 m when the jellyfish is centred, no matter the viewport. Scroll input is smoothed with an exponential-decay lerp inside one requestAnimationFrame loop, so the HUD needle and water colour settle like something moving through liquid, not a spreadsheet.
Making water out of nothing
There are no images anywhere. The water is a single fixed layer whose colour is interpolated per-frame between four palette stops — surface, twilight, midnight, hadal. Sunbeams are CSS conic-gradient wedges swaying on offset alternate timelines, squared-off with an opacity curve so they die inside the first two viewports, exactly where photosynthesis does. Marine snow is one <canvas>: ~150 particles, each with a parallax factor z, drifting upward past a sinking camera while wobbling on its own sine. devicePixelRatio is capped at 2, and the loop stops cold on document.hidden.
The fauna
All five encounters — Atolla, anglerfish, gulper eel, dumbo octopus, and the bathyscaphe Trieste — are hand-drawn inline SVG. Idle life comes from CSS keyframes on sub-groups using transform-box: fill-box: the jelly's bell squashes against its own bounding box, tentacles sway on staggered negative delays, the angler's lure flickers on deliberately uneven keyframe percentages so it never reads as a loop. Glow is filter: drop-shadow in bioluminescent aqua and pink. Fact cards slide in through an IntersectionObserver, children staggered with transition delays.
Touch — it answers in light
Every creature responds to a press with its documented behaviour: the Atolla spins its burglar-alarm pinwheel (three dashed SVG circles counter-rotating through one cubic-bezier flare), the angler's lure blooms, the gulper's tail lantern strobes, the dumbo blushes and scrambles, and the Trieste's porthole blinks O·K in Morse via a steps(1,end) opacity timeline. The snow canvas also carries a pointer lamp — a faint aqua halo that only fades in once the sun is gone, gently shoving nearby motes aside — and stretches every particle into a motion-blur streak proportional to smoothed scroll velocity, which is what makes the "return to surface" ascent feel like being winched up through rain.
Iteration passes
Pass one built the depth engine and typography; screenshots then drove the fixes: rail labels that clipped in the tape's overflow, HUD contrast at the bright surface (a .is-deep class flips the chrome from ink to pale once you pass ~600 m), and mobile spacing so the meter never collides with the cards. Pass two was the motion pass — sounding-line interstitials, parallaxed ghost numerals, the touch responses above, a pressure-gauge quiver on the HUD needle keyed to descent speed. prefers-reduced-motion collapses every animation and lets the page update directly on scroll — still, dark, and legible all the way down.