The same RadarFrame is enqueued for the display consumer and handed to
DataRecorder.record_frame on the producer thread. h5py releases the GIL
during gzip compression, so any in-place mutation by the consumer (or a
future scaling/normalisation step) would tear the on-disk frame.
record_frame now copies all five numpy arrays into local snapshots
before passing them to h5py.create_dataset. Disk integrity no longer
depends on consumer behaviour.
New test test_record_frame_isolates_from_post_call_mutation asserts
that mutating every array in place after record_frame returns leaves
the HDF5 contents untouched.
Tests: GUI 93/93 (was 92), ruff clean repo-wide.