diff --git a/docs/04-diktat.md b/docs/04-diktat.md
index 993943c..e330f04 100644
--- a/docs/04-diktat.md
+++ b/docs/04-diktat.md
@@ -1,129 +1,132 @@
-# 04 Diktat (Whisper im Browser)
-
-Überall dort, wo längerer Text entsteht – Notiz am Kontakt, Notizen an Lead und
-Unternehmen, Projektnotizen, Ausschreibungstext – sitzt ein Mikrofon-Knopf. Die
-Erkennung läuft **vollständig im Browser des Benutzers**.
-
-Das Backend ist daran nicht beteiligt und sieht keine Audiodaten: kein
-API-Schlüssel, keine Kosten pro Minute, kein Datenabfluss. Aufnahmen werden
-nirgends gespeichert.
-
-Die Umsetzung ist aus dem perinco CRM übernommen und technisch identisch – wer
-das eine kennt, findet sich im anderen zurecht.
-
-## Weg der Aufnahme
-
-```mermaid
-flowchart LR
- MIC(("Mikrofon")) --> MR["MediaRecorder
webm / ogg / mp4"]
- MR --> AC["AudioContext + OfflineAudioContext
16 kHz Mono PCM"]
- AC --> W["Web Worker"]
- W --> ONNX["Whisper als ONNX
WebGPU, sonst WASM"]
- ONNX --> T["Text"]
- T --> F["Formularfeld
angehaengt, nie ersetzt"]
-
- HF["Hugging-Face-CDN"] -.->|"einmalig ~300 MB"| CACHE[("Cache-Speicher
der Seite")]
- CACHE --> ONNX
-```
-
-Die Erkennung liegt im Web Worker (`src/lib/whisper.worker.ts`), damit die
-Oberfläche währenddessen nicht einfriert. Die ONNX-Laufzeit wird **mit
-ausgeliefert** (Vite bündelt die `.wasm`, rund 21 MB unter `dist/assets/`), nur
-die Modelldateien kommen beim ersten Laden vom CDN und bleiben danach im
-Cache-Speicher der Seite.
-
-## Festlegungen
-
-Es gibt bewusst nichts einzustellen (`src/lib/whisper.tsx`):
-
-| Festlegung | Wert | Warum |
-| --- | --- | --- |
-| Modell | `onnx-community/whisper-large-v3-turbo` | beste Erkennung im Deutschen, auch bei Fachbegriffen („S4 HANA"); `small` verliert genau dort, `tiny` ist unbrauchbar |
-| Genauigkeit | `q4` | `q8` liefert auf der Grafikkarte Unsinn, `fp16` blockiert den Tab, `fp32` passt nicht in einen Speicherblock |
-| Rechenweg | WebGPU, sonst WASM | automatisch; ohne Grafikbeschleunigung dauert es länger, funktioniert aber |
-| Sprache | Deutsch | fest |
-
-## Lebenszyklus des Modells
-
-```mermaid
-stateDiagram-v2
- [*] --> idle: Anmeldung
- idle --> loading: "Sprachmodell laden" oder Cache vorhanden
- loading --> ready: Worker meldet "ready"
- loading --> error: Speicher, Abbruch, 2 min ohne Regung
- ready --> idle: "Entladen"
- ready --> idle: "Sprachmodell loeschen" (Cache geleert)
- error --> loading: erneuter Versuch
-```
-
-* **Liegt das Modell im Cache, stellt es sich beim Anmelden von selbst bereit.**
- Einmal herunterladen genügt also.
-* **Ohne Cache passiert nichts von allein** – ein Download von 300 MB startet nie
- unaufgefordert.
-* Der Selbstversuch läuft genau **einmal je Seitenaufruf**: wer das Modell
- absichtlich löscht oder entlädt, will es nicht sofort wiederhaben.
-* Vor dem Download bittet die Anwendung um **dauerhaften Speicher**
- (`navigator.storage.persist`). Chrome darf ablehnen; dann funktioniert alles
- genauso, nur ohne diese Zusicherung.
-
-### Hänger werden erkannt
-
-Zwei Fristen, beide mit verwertbarer Meldung statt endlosem „Lädt …":
-
-| Frist | Wann |
-| --- | --- |
-| 120 s ohne Regung des Workers | beim Laden – meist scheitert das Anlegen der ONNX-Sitzung am Speicher |
-| max(45 s, 15 × Aufnahmedauer), höchstens 300 s | bei einer Erkennung |
-
-In beiden Fällen wird der Worker beendet; ein neuer Versuch bekommt einen
-frischen.
-
-## Bedienung
-
-*Einstellungen → Diktat* (für jede Rolle sichtbar, denn jeder richtet sein Gerät
-selbst ein):
-
-1. **Sprachmodell laden** – zeigt die tatsächliche Downloadgröße, bei Hugging
- Face erfragt (`src/lib/whisperModels.ts`), und einen Fortschrittsbalken.
-2. **Probe sprechen** – kurz etwas diktieren und den erkannten Text ansehen.
-3. **Sprachmodell löschen** – entfernt es aus diesem Browser.
-
-Danach steht in den Formularen ein Mikrofon-Knopf. Während der Aufnahme läuft
-die Zeit, daneben liegt ein Kreuz zum Verwerfen.
-
-Der Knopf zeigt drei Zustände:
-
-| Zustand | Was zu sehen ist |
-| --- | --- |
-| kein Mikrofon / kein HTTPS | gar nichts – ein toter Knopf wäre schlechter |
-| Modell fehlt | *Diktat einrichten*, führt direkt in den Reiter |
-| bereit | Mikrofon, dann laufende Zeit, dann *Erkenne …* |
-
-Erkannter Text wird **angehängt**, nie ersetzt: in den WYSIWYG-Feldern als
-eigener Absatz am Ende, in den Textfeldern hinter dem Vorhandenen. Ins DOM des
-Editors zu schreiben wäre die Alternative – dann hinge das Ergebnis aber an der
-Schreibmarke, die während der Aufnahme längst woanders stehen kann.
-
-## Dateien
-
-| Datei | Aufgabe |
-| --- | --- |
-| `src/lib/whisper.tsx` | Kontext: Zustand, Fortschritt, Cache-Erkennung, Fähigkeiten des Geräts |
-| `src/lib/whisper.worker.ts` | Pipeline, Erkennung, Fehler auch außerhalb der await-Kette |
-| `src/lib/dictation.tsx` | `useRecorder` – Mikrofon, Dauer, Abbruch |
-| `src/lib/audio.ts` | webm/ogg/mp4 → 16 kHz Mono Float32 |
-| `src/lib/whisperModels.ts` | Downloadgröße, Formatierung |
-| `src/components/ui/Dictate.tsx` | `DictateButton`, `DictateTextarea`, `appendParagraph` |
-| `src/components/settings/WhisperSettings.tsx` | der Reiter |
-
-Abhängigkeit: `@huggingface/transformers` (^3.8.1).
-
-## Störungssuche
-
-| Symptom | Ursache |
-| --- | --- |
-| Kein Mikrofon-Knopf zu sehen | kein `MediaRecorder` oder keine sichere Verbindung (HTTPS) |
-| „Kein Zugriff aufs Mikrofon" | Berechtigung im Browser verweigert |
-| Erkennung sehr langsam | keine WebGPU – der Reiter sagt es ausdrücklich |
-| Modell nach Neustart wieder weg | privates Fenster oder Speicherbeschränkung; der Reiter weist darauf hin |
-| „Der Speicher reicht … nicht" | zu wenig Arbeitsspeicher für die ONNX-Sitzung |
+# 04 Diktat (Whisper im Browser)
+
+Überall dort, wo längerer Text entsteht – Notiz am Kontakt, Notizen an Lead und
+Unternehmen, Projektnotizen, Ausschreibungstext – sitzt ein Mikrofon-Knopf. Die
+Erkennung läuft **vollständig im Browser des Benutzers**.
+
+Das Backend ist daran nicht beteiligt und sieht keine Audiodaten: kein
+API-Schlüssel, keine Kosten pro Minute, kein Datenabfluss. Aufnahmen werden
+nirgends gespeichert.
+
+Die Umsetzung ist aus dem perinco CRM übernommen und technisch identisch – wer
+das eine kennt, findet sich im anderen zurecht.
+
+## Weg der Aufnahme
+
+```mermaid
+flowchart LR
+ MIC(("Mikrofon")) --> MR["MediaRecorder
webm / ogg / mp4"]
+ MR --> AC["AudioContext + OfflineAudioContext
16 kHz Mono PCM"]
+ AC --> W["Web Worker"]
+ W --> ONNX["Whisper als ONNX
WebGPU, sonst WASM"]
+ ONNX --> T["Text"]
+ T --> F["Formularfeld
angehaengt, nie ersetzt"]
+
+ HF["Hugging-Face-CDN"] -.->|"einmalig ~300 MB"| CACHE[("Cache-Speicher
der Seite")]
+ CACHE --> ONNX
+```
+
+Die Erkennung liegt im Web Worker (`src/lib/whisper.worker.ts`), damit die
+Oberfläche währenddessen nicht einfriert. Die ONNX-Laufzeit wird **mit
+ausgeliefert** (Vite bündelt die `.wasm`, rund 21 MB unter `dist/assets/`), nur
+die Modelldateien kommen beim ersten Laden vom CDN und bleiben danach im
+Cache-Speicher der Seite.
+
+## Festlegungen
+
+Es gibt bewusst nichts einzustellen (`src/lib/whisper.tsx`):
+
+| Festlegung | Wert | Warum |
+| --- | --- | --- |
+| Modell | `onnx-community/whisper-large-v3-turbo` | beste Erkennung im Deutschen, auch bei Fachbegriffen („S4 HANA"); `small` verliert genau dort, `tiny` ist unbrauchbar |
+| Genauigkeit | `q4` | `q8` liefert auf der Grafikkarte Unsinn, `fp16` blockiert den Tab, `fp32` passt nicht in einen Speicherblock |
+| Rechenweg | WebGPU, sonst WASM | automatisch; ohne Grafikbeschleunigung dauert es länger, funktioniert aber |
+| Sprache | Deutsch | fest |
+
+## Lebenszyklus des Modells
+
+```mermaid
+stateDiagram-v2
+ [*] --> idle: Anmeldung
+ idle --> loading: Klick auf "Sprachmodell laden" / "Diktat aktivieren"
+ loading --> ready: Worker meldet "ready"
+ loading --> error: Speicher, Abbruch, 2 min ohne Regung
+ ready --> idle: "Entladen"
+ ready --> idle: "Sprachmodell loeschen" (Cache geleert)
+ error --> loading: erneuter Versuch
+```
+
+* **Es lädt nichts von selbst** – weder der Download noch das Aktivieren aus dem
+ Cache. Beides braucht einen Klick.
+* Der Grund ist gemessen, nicht vermutet: das Anlegen der ONNX-Sitzung übersetzt
+ hunderte Shader und legt dabei Zeiger und Darstellung für einige Sekunden
+ still. Lief das beim Anmelden von selbst, sah die ganze Anwendung aus, als
+ hinge sie – und zwar genau dann, wenn jemand gerade eine Lead-Kachel ziehen
+ wollte.
+* Liegt das Modell im Cache, heißt der Knopf *Diktat aktivieren* und der
+ Download entfällt.
+* Vor dem Download bittet die Anwendung um **dauerhaften Speicher**
+ (`navigator.storage.persist`). Chrome darf ablehnen; dann funktioniert alles
+ genauso, nur ohne diese Zusicherung.
+
+### Hänger werden erkannt
+
+Zwei Fristen, beide mit verwertbarer Meldung statt endlosem „Lädt …":
+
+| Frist | Wann |
+| --- | --- |
+| 120 s ohne Regung des Workers | beim Laden – meist scheitert das Anlegen der ONNX-Sitzung am Speicher |
+| max(45 s, 15 × Aufnahmedauer), höchstens 300 s | bei einer Erkennung |
+
+In beiden Fällen wird der Worker beendet; ein neuer Versuch bekommt einen
+frischen.
+
+## Bedienung
+
+*Einstellungen → Diktat* (für jede Rolle sichtbar, denn jeder richtet sein Gerät
+selbst ein):
+
+1. **Sprachmodell laden** – zeigt die tatsächliche Downloadgröße, bei Hugging
+ Face erfragt (`src/lib/whisperModels.ts`), und einen Fortschrittsbalken.
+2. **Probe sprechen** – kurz etwas diktieren und den erkannten Text ansehen.
+3. **Sprachmodell löschen** – entfernt es aus diesem Browser.
+
+Danach steht in den Formularen ein Mikrofon-Knopf. Während der Aufnahme läuft
+die Zeit, daneben liegt ein Kreuz zum Verwerfen.
+
+Der Knopf zeigt drei Zustände:
+
+| Zustand | Was zu sehen ist |
+| --- | --- |
+| kein Mikrofon / kein HTTPS | gar nichts – ein toter Knopf wäre schlechter |
+| Modell fehlt | *Diktat einrichten*, führt direkt in den Reiter |
+| bereit | Mikrofon, dann laufende Zeit, dann *Erkenne …* |
+
+Erkannter Text wird **angehängt**, nie ersetzt: in den WYSIWYG-Feldern als
+eigener Absatz am Ende, in den Textfeldern hinter dem Vorhandenen. Ins DOM des
+Editors zu schreiben wäre die Alternative – dann hinge das Ergebnis aber an der
+Schreibmarke, die während der Aufnahme längst woanders stehen kann.
+
+## Dateien
+
+| Datei | Aufgabe |
+| --- | --- |
+| `src/lib/whisper.tsx` | Kontext: Zustand, Fortschritt, Cache-Erkennung, Fähigkeiten des Geräts |
+| `src/lib/whisper.worker.ts` | Pipeline, Erkennung, Fehler auch außerhalb der await-Kette |
+| `src/lib/dictation.tsx` | `useRecorder` – Mikrofon, Dauer, Abbruch |
+| `src/lib/audio.ts` | webm/ogg/mp4 → 16 kHz Mono Float32 |
+| `src/lib/whisperModels.ts` | Downloadgröße, Formatierung |
+| `src/components/ui/Dictate.tsx` | `DictateButton`, `DictateTextarea`, `appendParagraph` |
+| `src/components/settings/WhisperSettings.tsx` | der Reiter |
+
+Abhängigkeit: `@huggingface/transformers` (^3.8.1).
+
+## Störungssuche
+
+| Symptom | Ursache |
+| --- | --- |
+| Kein Mikrofon-Knopf zu sehen | kein `MediaRecorder` oder keine sichere Verbindung (HTTPS) |
+| „Kein Zugriff aufs Mikrofon" | Berechtigung im Browser verweigert |
+| Erkennung sehr langsam | keine WebGPU – der Reiter sagt es ausdrücklich |
+| Modell nach Neustart wieder weg | privates Fenster oder Speicherbeschränkung; der Reiter weist darauf hin |
+| „Der Speicher reicht … nicht" | zu wenig Arbeitsspeicher für die ONNX-Sitzung |