Build and push server image / build-and-push (push) Successful in 40s
battery_read_percent() was called once at the very start of boot, before WiFi even connects, and that value was reused both for the manage-menu overlay and the server report. Taken right after a reset (e.g. the OTA reboot that immediately precedes it), the rail may still be settling -- plausible source of noisy jumps in reported battery level. Now there's a single read, in frame_client_run() right before report_battery(), after the photo (and manage overlay, if shown) is already on the panel -- the fetch/display work already done this cycle is the settle time, no delay to guess. The manage overlay no longer needs an early local reading at all: it shows the server's last-known value instead, added to the /frame/photo-info response it already fetches.