310f37f29b
Reported: "the loading buffer is not the spinner, it still loads at the left of the timer." Correct — and it was our bug, not a cosmetic preference. The spinner was driven by a hand-picked event list (waiting/seeking/stalled). But a cold start from preload="none" NEVER fires `waiting`: it runs loadstart -> loadedmetadata -> loadeddata -> canplay -> playing straight through. Since the bandwidth fix, that cold start is the only stall left — so the spinner sat out the exact moment it existed for, leaving just the OS control bar's own small indicator where the play button sits, i.e. left of the timer. Now the spinner is derived from the element's real state rather than guessed from events: busy = seeking || (!paused && !ended && readyState < HAVE_FUTURE_DATA), recomputed on every relevant media event. Simulated against the real event sequences before shipping — cold start, mid-stream stall and seek all spin; paused/ended/idle never do. Also dim the frame to 72% brightness while buffering so the spinner reads instantly against a bright poster, and give it a dark backing disc. Note: the small indicator inside the native control bar belongs to the OS's own video controls and cannot be suppressed while we use them. Ours is now the loud, central one; removing the OS indicator entirely would mean custom controls. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>