DOWNPOUR is a wet-weather reader: heavy rain falls across the whole page, an umbrella rides your cursor, and only the dry cone beneath it keeps the copy crisp. Its single job is to make reading an act of shelter — you keep the words dry, or the storm takes them back.
Wave 4 is second person: the page is inert until you drive it. Here the whole surface is out in the rain — headline, dispatches, the small print. The only power source is your hand. Move the umbrella over a line and it sharpens; leave it exposed and the backdrop-blur closes over it, and it beads, blurs, and runs. Stop moving and nothing rescues itself. The reader isn't a spectator to the weather; the reader is the shelter.
Cold sky, warm shelter, one red object you control. Following the collection's ink/line rule, the bright accent is reserved for a mark — the canopy — never for small text; all body ink is the warm dry-white, which sits at roughly 10:1 on the storm.
Fraunces at its 144 optical size sets the headline, leads, and dispatch titles — a high-contrast old-style serif with soft, almost damp terminals, which is exactly the right voice for a page about whether ink keeps its edge. Inter carries the body, labels, nav, and fine print: a neutral grotesque that keeps the wayfinding quiet so the serif and the weather do the talking.
The temptation is to render the copy twice (a crisp layer and a wet layer) and cross-fade them. That ghosts and duplicates the DOM. Instead the words exist once, as real crisp HTML. A single fixed .rainGlass element sits above them with backdrop-filter: blur() saturate() brightness(), so it blurs whatever text is painted behind it — no second copy, no ghosting, fully selectable and accessible.
The umbrella is a hole in that glass. A radial-gradient mask-image centred on your cursor punches the glass away — transparent 55% → #000 92% of the shelter radius — so inside the dry cone there is no glass, no blur, and the original crisp text simply shows through. The same ellipse maths drives three things from one source: the CSS mask, the canvas rain clip, and the wetAlphaAt(x,y) probe used to test it.
The rain is a canvas 2-D field of ~1,100 wind-sheared streaks in three parallax layers (DPR capped at 2, paused on document.hidden). The ambient rain is clipped out of the shelter ellipse, so nothing falls on the words you're reading, while the umbrella — an eight-rib scalloped canopy that leans into your cursor velocity — is drawn on top and sheds a curtain of drips off its eight rim tips, in front of everything. A rare lightning bolt raises a screen-blend flash and briefly thins the blur, so for half a second the whole page almost surfaces.
Fallbacks. The blur only exists once JS adds a body.weather class. With JavaScript off, or under prefers-reduced-motion, that class is never added: the glass stays display:none, the cursor stays visible, and every line renders fully crisp and readable.
Enlarged the shelter ellipse (0.90 → 0.95 × canopy radius) for a comfortable reading window and centred the mask on the cursor, so pointing is reading. Parked the umbrella over the headline on load, so the crisp words "over the words" are legible the instant the page opens — the design documents itself. Locked the ink/line split: warm dry-white for all body copy, rain-grey confined to hairlines and secondary labels, brolly-red only on the canopy.
Raised the rain to a genuine downpour — density up ~40% to ~1,140 streaks with a heavier near layer. Gave the canopy a velocity-driven lean and impact sparkles where streaks strike the dome. Pulled the rim drips out of the shelter clip so the "eight thin ropes" the copy promises actually sheet off the ribs as a visible curtain in front. Added the rare lightning that thins the blur as a second-read detail.
Caught a real fallback bug: the backdrop blur was applied unconditionally in CSS, so a no-JS visitor would have been left with permanently-blurred, unreadable text and no umbrella to move it. Gated the entire rain-glass and the hidden cursor behind the JS-only body.weather class, so no-JS and reduced-motion both render fully crisp. Verified 375 / 768 / 1440 with no horizontal overflow and the wordmark and headline inside the viewport; removed dead code (an unused shelter test). Chanel rule applied.
Every pass ran the same headless check (puppeteer-core + the system Chrome, on an isolated static server): the real cursor is moved over the headline and two dispatches, then away, and the shelter state is read at each word's coordinates. 23 of 23 assertions passed.