Dictation in the Clip AI chat input, mirroring Claude's interaction. A mic
button sits in both composers (compact popover + agent view); tapping it swaps
the text row for a live waveform, a pulsing record dot, and an elapsed timer,
with cancel (discard) and confirm (insert) controls. Transcription uses the
Web Speech API; the waveform is driven by a Web Audio AnalyserNode reading
live mic amplitude (lib/use-dictation.ts). The transcript appends to whatever
you'd already typed, so you can dictate mid-draft. The mic is hidden where the
browser has no speech recognition; a blocked mic surfaces a toast.
The mic permission is requested once via getUserMedia before starting
recognition (rather than both at once), which avoids Chrome rejecting the
competing request with "not-allowed"; a non-secure (plain-http) origin now
reports that it needs https instead of failing opaquely.