Replaced open/close-per-operation pattern with a single persistent
connection held for the app lifetime. This prevents the DB upgrade
(v1→v2) from being blocked by lingering connections, and eliminates
transaction contention.
Also added onblocked handler that surfaces a clear error instead of
hanging indefinitely.
Previously each frame was stored as a separate Blob in the Recording
object, causing IndexedDB to hang when writing 100+ blobs in one
transaction. Now all frames are packed into a single binary blob:
[4B frameCount][per frame: 4B ts, 4B len, JPEG data]
DB version bumped to 2 (old store deleted on upgrade).
PlaybackPanel unpacks frames on demand with a per-recording cache.