prototype: complete the prefers-reduced-motion coverage (#366)
Dust, confetti, and card shake were already skipped; now the strobing 11 LED, the VU flicker jitter, and the LED/eleven-number transitions go still too — states change instantly instead of animating. A mid-session toggle of the OS setting reloads the page (it's stateless) so the new preference applies everywhere.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+14
−3
prototypes/space-lever.html+14 −3
diff --git a/prototypes/space-lever.html b/prototypes/space-lever.html| index c4c8da9..6a11085 100644 |
| --- a/prototypes/space-lever.html |
| +++ b/prototypes/space-lever.html |
| @@ -79,6 +79,13 @@ |
| .led.on-r { background: var(--led-r); box-shadow: 0 0 8px color-mix(in srgb, var(--led-r) 70%, transparent); } |
| @keyframes led-fury { 0%, 100% { opacity: 1; } 50% { opacity: .25; } } |
| .led.fury { animation: led-fury .14s linear infinite; } |
| + /* Reduced motion: no strobe, no colour/scale transitions — states still |
| + change, they just change instantly. (The dust, confetti, shake, and VU |
| + flicker are skipped in the script under the same query.) */ |
| + @media (prefers-reduced-motion: reduce) { |
| + .led.fury { animation: none; } |
| + .led, .num.eleven { transition: none; } |
| + } |
| /* The fader: a recessed slot, ticks above it, numbers below, and the cap. */ |
| .fader { position: relative; height: 46px; margin: 0 2px; touch-action: none; cursor: grab; } |
| @@ -420,10 +427,11 @@ function paint() { |
| nums[10].classList.toggle("hit", past); |
| // VU: lit up to the current notch, with a one-LED flicker while the signal's |
| - // hot so it reads as a live meter, not a progress bar. At eleven: all of it, |
| - // and the last LED strobes. |
| + // hot so it reads as a live meter, not a progress bar (steady under reduced |
| + // motion). At eleven: all of it, and the last LED strobes. |
| const hot = levelNow(); |
| - const lit = past ? 11 : Math.round(value) + (hot > 0.4 && Math.random() < 0.35 ? (Math.random() < 0.5 ? -1 : 0) : 0); |
| + const flicker = !reduced && hot > 0.4 && Math.random() < 0.35 ? (Math.random() < 0.5 ? -1 : 0) : 0; |
| + const lit = past ? 11 : Math.round(value) + flicker; |
| leds.forEach((led, i) => { |
| const on = i < lit; |
| led.className = "led" + (on ? " on-" + led.dataset.c : "") + |
| @@ -561,6 +569,9 @@ bind("kick", "kick", (v) => v.toFixed(2)); bind("motes", "motes"); bind("build", |
| addEventListener("resize", initDust); |
| matchMedia("(prefers-color-scheme: dark)").addEventListener("change", initDust); |
| +// `reduced` is read once at load; if the OS setting flips mid-session, reload — |
| +// the page is stateless, and a fresh boot honours the new preference everywhere. |
| +matchMedia("(prefers-reduced-motion: reduce)").addEventListener("change", () => location.reload()); |
| initDust(); |
| rafId = requestAnimationFrame(tick); |
| </script> |