Each section/page completion previously appended a new full-viewport
(100vw x 100vh, z-index 99999) canvas with its own requestAnimationFrame
loop. Completing several sections in a row stacked multiple fullscreen
layers, each independently repainting the whole viewport at 60fps — the
real cause of click-induced slowdown (the change handler itself is ~1ms).
Now: one shared canvas, one rAF loop, particles pooled across completions.
The loop stops and the canvas is removed once no particles remain, so
there is no idle fullscreen compositing layer. Resize keeps it sized.
Verified live: 1 canvas after two back-to-back section completions,
0 canvases after the animation ends, green pills still white-on-green.