FireAndForgetPlayback's cleanup task had the same 2 s done.Wait timeout
as the beep cleanup. Beep is 200 ms so 2 s is generous; recording
playback is 5 s so the timeout fired mid-playback, cleanup ran
stream.Stop(), and the audio cut at ~2.2 s. Timeout is now
recording-duration + 2 s.
Stale Set() from a delayed cleanup task could short-circuit a future
PLAYBACK state; new flag per cycle avoids the cross-cycle leak. Also
log when the 2 s done.Wait timeout fires so silent PortAudio callback
faults are visible during hardware debugging.