I = V/R.THE CLOCK
One requestAnimationFrame loop. Each frame it takes the real elapsed time, clamps it
(dt ≤ 64 ms) so a backgrounded tab cannot fast-forward, then advances the state.
THE STATE
A plain object: stage index, phase, particles, samples, lever angle, brightness. Every visible thing is a function of it. Nothing animates itself.
THE RENDER
The whole SVG is rebuilt as a string and assigned to innerHTML once per frame. No diffing, no
retained element references, no stale attributes.
THE LIFECYCLE
IntersectionObserver pauses it off-screen, ResizeObserver re-runs the layout pass,
a data-theme mutation re-reads the colours, and prefers-reduced-motion renders a still frame.