Saros
A dark almanac that runs the Moon through its phases while the 223-lunation Saros cycle predicts each eclipse. The single job of the page: make why eclipses return every eighteen years something you can watch in seven seconds — with a partial already caught mid-frame.
The concept
Saros is a fictional deep-time almanac for a reader who has looked up at an eclipse and wondered how anyone knew it was coming. The Babylonians did: an eclipse repeats after 223 synodic months — 6,585 days, or 18 years, 11 days, 8 hours — because that span is also a whole number of draconic months, returning the Moon to the same node. The page is that clock, drawn. The Moon marches through its phases at the centre; a wheel of 223 lunations turns beside it with the eclipse-capable months lit in gold; a drone tuned to the beat between the two lunar periods swells as the shadow arrives.
Palette — argued from the subject
A night sky seen from the shadow side. The bright accent is reserved for light — the corona, the eclipse marks, the pointer — while text runs in a lighter slate ink so body copy clears 4.5:1 over the animated field.
Type
Techniques
- Canvas 2D for the whole celestial field — no external libraries. The Moon, the 223-mark wheel, the tide strip, and the star field are drawn each frame at a device-pixel ratio capped at 2.
- A scanline-exact terminator. The lit face of the Moon is built as a clip region, column by column, from the rule that a point is lit when
x > R·cos(2πp)waxing andx < −R·cos(2πp)waning. A radial gradient and mare mottling are painted inside that region — correct at every phase, from a hair of crescent to full. - An eclipse that branches. At full moon near a node the Earth's coppery umbra creeps across the bright disc — a lunar eclipse. At new moon near a node the disc goes dark and a gold corona flares behind the silhouette, with ragged rays near totality — a solar eclipse. The same geometry, two faces.
- The signature — a self-timing wheel. Three periods run at once: the synodic month (29.53 d, the phases), the draconic month (27.21 d, the nodes), and their product, the Saros. An eclipse fires only when a syzygy lands within about 1.5° of a node. The wheel plots all 223 lunations and lights the ones that align; the pointer walks the 18-year cycle. The clock eases itself down as an eclipse nears, so the simulation parks on the shadow instead of racing past it — slow is the point.
- WebAudio drone. A low chord — root, fifth, octave, plus a twin detuned by a fraction of a hertz — beats slowly against itself, and a low-pass filter opens as the eclipse magnitude climbs, so the shadow is something you hear arrive. It starts only on the first press of the toggle (never on load, never under reduced motion) and is muteable.
- Tides. The strip below swells to a spring tide at new and full moon and flattens to a neap at the quarters — amplitude driven by
|cos(2π·phase)|, the same syzygy that makes the eclipses.
Iteration log
The Moon was lit inside-out
The first terminator used an arc-plus-ellipse path, and it was wrong at the extremes: a new moon rendered fully bright and a waxing gibbous rendered nearly dark — the illuminated fraction was inverted through the crescent and gibbous ranges. I derived the exact per-column lit rule, validated a scanline reference across all eight canonical phases, then rebuilt drawPhase (and the wheel's hub moon) as a scanline clip. Also fixed a copy defect: the readout announced the next eclipse while one was plainly in frame — it now describes the current one.
Two kinds of shadow, and a clock that waits
Eclipses were being painted as a red bite on every syzygy, including new moons — nonsense for a solar eclipse, where the Moon is dark. Split the render: coppery umbra for lunar, annulus-clipped gold corona with rays for solar. Then the second-read detail — the day-rate now eases toward a near-stop as the Moon closes on a syzygy-at-node, so the page lingers on each eclipse and drifts through the ordinary months. Added earthshine on the dark limb and mare mottling so the disc rewards a closer look.
375px, reduced motion, and the resting frame
On a phone the Moon and the wheel had been placed side by side and collided; they now stack vertically with shrunk radii, the wake-hint is hidden, and the panel compacts — scrollWidth holds at 375 with no element crossing the edge. Under prefers-reduced-motion the loop never starts: a single settled frame renders on the partial lunar eclipse, no audio, no rAF. The loop pauses on document.hidden, resize is handled, DPR is capped at 2, and the drone is gated on the first gesture. Removed one ornament — a redundant corona ring that fought the umbra — per the Chanel rule.