The sweep read a frame per idle repaint, so it climbed at half speed on the
handheld — a platform that ticks every 2 s because a frame costs 7-11% of a
core there. Pacing it off the tick was solving the wrong problem: the gauge
should climb at a second a frame everywhere, and the repaints that takes are
worth buying, since a pack only sweeps while it is plugged in.
So the poller now buys them, and only while all three hold: the gauge is
actually sweeping (a pack sitting full on the charger is not — which is where
a forgotten handheld spends the night), the platform idles slower than a
frame, and a surface is listening. Everything else sleeps out the interval as
before. BATTERY_ANIM_S moves to the widget as the one cadence both read, and
Ui.invalidate gives a service its first channel to repaint live chrome.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>