The dictation widget window could mistake itself for the main window: detectIsWidget() asked getCurrentWindow().label, which throws while Tauri's internals are still injecting, and the catch fell back to a URL query Tauri 2 cannot set. A window that guessed wrong rendered the whole app into 300x64 — opaque background, no pill, and no CaptureWidget to run the hide reconcile, so nothing but quitting the app could clear it. It now stamps its identity from an initialization_script, which runs before any page script and cannot race.
The pill is gone as well: the widget window is never shown. It still has to exist — getUserMedia, MediaRecorder and the transcription WebSocket all live in CaptureWidget — so it is now a hidden recorder host, and dictation records, transcribes and pastes with nothing on screen.
The tray Start/Stop item no longer infers recording from window visibility (which a permanently hidden window made meaningless, leaving Stop unreachable); it reads a dictating flag the frontend already maintains. States needing user action — Accessibility, mic denial, failed transcription — used to surface in the pill and now arrive as a toast in the main window, carrying the button that opens the relevant OS pane.
Also closes the second-launch path: the single-instance handler targeted the widget in pill mode and showed it.
Refs #1398