Two regressions surfaced after adding the Pause label in manual mode:
1. Clicking Pause restarted the cached blob from the beginning (looked
like the track played twice). speakText's onclick was still wired to
speakText itself, so each click created a fresh Audio and started
from 0. Manual play now uses the same takeOver pattern as the queued
path: while live audio owns playback, the click routes through
toggleAudioPlayback (which pauses any current audio and toggles this
one); when audio ends or errors, the original speakText handler is
restored so users can replay from cache.
2. Manual mode had no sentence highlights. The glow needs per-sentence
timing from the speech service, which only the SSE branch returns —
manual mode was using the older non-SSE streaming path. speakText now
branches on tts-1-f5 like speakTextQueued does, caches the sentences
array, and calls attachSentenceGlow. Pauses naturally pause the glow
(its tick loop checks audio.paused/ended).
Also routes the queued-audio onclick rebind through toggleAudioPlayback
for cross-message safety (was calling audio.play()/pause() directly,
which would let two queued audios play simultaneously if the user
clicked Play on a paused one while another was active).