# Phase 4: Polish + Audio - Context **Gathered:** 2026-03-29 (assumptions mode) **Status:** Ready for planning ## Phase Boundary Visuell und auditiv angenehmes Erlebnis, bereit zum Testen mit dem Kind. Umfasst: Sound-Effekte (Web Audio API), Sprachausgabe (Web Speech API), sanfte Animationen (Blätter-Fall, Sternenstaub, Avatar-Schweben), Responsive bis 700px, globaler Error-Handler, Export/Import/Reset im Elternbereich. Keine neuen Features — rein Polish auf bestehendem Spielerlebnis. ## Implementation Decisions ### Audio System - **D-01:** Ein Modul `src/audio/sounds.ts` mit Web Audio API. Shared `AudioContext`, procedural Sounds (Oszillatoren, Noise Buffers). Exportiert: `playCorrectSound()` (800Hz, 0.1s), `playRewardSound()` (aufsteigende Tonfolge, 0.8s), `playForestElementSound()` (gefiltertes weisses Rauschen, 0.5s). Alle prüfen `audioEnabled` aus Settings Store. - **D-02:** AudioContext wird bei erster User-Interaktion erstellt/resumed (Auto-Play Policy Compliance). Lazy initialization Pattern. - **D-03:** Mute-Button als fixed-position Element in `` ausserhalb aller `
` Screens. Liest/schreibt `audioEnabled` in Settings Store. Zustand persistiert über Reload. ### Speech Synthesis - **D-04:** Optionale Sprachausgabe via `window.speechSynthesis` (Web Speech API). Deutsch, Rate 0.9, Pitch 1.1. Liest Companion-Texte vor (Begrüssung, Wald-Kommentar). Silent Fallback wenn keine deutsche Stimme verfügbar. - **D-05:** Eigene Funktion `speakText(text: string)` in `src/audio/speech.ts`. Prüft Settings-Flag (neues Feld `speechEnabled: boolean` in Settings). ### Animations - **D-06:** Fallende Buchstaben: Neue `@keyframes leaf-fall` Animation mit lateralem Sway (sinusförmig) + sanftem vertikalen Abstieg. Ersetzt bestehende `letter-float`. - **D-07:** Sternenstaub bei richtigem Tastendruck: CSS `::before`/`::after` Pseudo-Elemente auf `.falling-letter--dissolve` mit kleinen Particles die auseinanderfliegen und verblassen. Pure CSS, kein JS. - **D-08:** Companion-Avatar Float-Animation: Sanftes Auf-Ab-Schweben via `@keyframes companion-float` auf `.companion-area__avatar`. - **D-09:** Alle Animationen respektieren `prefers-reduced-motion: reduce` Media Query. ### Responsive - **D-10:** `@media (max-width: 700px)` in main.css. Keyboard-Tasten von 44px auf ~32px, Leertaste proportional. Fonts skalieren via `clamp()`. Forest-Grid reduziert auf 3×4 oder 2×6. Welcome-Cards in 2×2 statt 4×1. ### Error Handling - **D-11:** Globaler Error-Handler in `src/main.ts`: `window.addEventListener('error')` + `window.addEventListener('unhandledrejection')`. Zeigt kindgerechtes Overlay ("Oh, der Wald braucht kurz eine Pause...") mit Reload-Button. Console.error für Debugging. ### Export/Import/Reset - **D-12:** Export: `progress` + `settings` als JSON-Download. Blobs ausgeschlossen (zu gross). Funktion in `src/ui/parent.ts`. - **D-13:** Import: JSON-Datei hochladen via ``. Validiert gegen Progress + Settings Interface-Struktur. Überschreibt nach Bestätigung. - **D-14:** Reset: Alle 5 IndexedDB Stores löschen. Doppelte Bestätigung ("Wirklich alles löschen?" → "Ja, alles löschen"). Danach Reload auf Welcome-Screen. ### Claude's Discretion - Exakte Frequenzen und Hüllkurven für Belohnungs-Tonfolge und Glitzer-Sound - CSS Particle-Anzahl und Timing für Sternenstaub - Leaf-Fall Animation Kurvenparameter - Exact responsive Breakpoints innerhalb 700px - Error-Overlay Styling ## Canonical References **Downstream agents MUST read these before planning or implementing.** - `SPEC.md` section 11 — Audio-Details (Frequenzen, Dauern, Web Audio API) - `SPEC.md` section 7.2 — Animationen (sanft, langsam, keine schnellen Blitze) - `SPEC.md` section 12 — Responsive, Error-Handler - `src/styles/main.css` — Bestehende Animationen (letter-float, falling-letter--dissolve, forest-element-appear) - `src/ui/screens.ts` — Lesson screen (touch points für Audio + Animationen) - `src/forest/reward.ts` — Reward screen (touch point für Belohnungs-Sound) - `src/forest/scene.ts` — Forest scene (touch point für Waldelement-Sound) - `src/ui/parent.ts` — Parent area (Export/Import/Reset einbauen) - `src/storage/db.ts` — IndexedDB Stores (Export liest, Import schreibt, Reset löscht) - `src/types.ts` — Settings Interface (audioEnabled existiert, speechEnabled hinzufügen) - `src/main.ts` — Entry point (Error-Handler hier) - `index.html` — Mute-Button ausserhalb Screens ## Existing Code Insights ### Reusable Assets - `Settings.audioEnabled: boolean` existiert in types.ts, Parent-Screen hat Toggle, DB-Methoden fertig - `getSettings()`/`saveSettings()` in db.ts ready - Bestehende CSS Animationen: `letter-float`, `falling-letter--dissolve`, `forest-element-appear`, `companion-float` (teilweise) - `getProgress()`/`saveProgress()` für Export ready - Parent-Screen HTML/CSS existiert mit Settings-Section ### Established Patterns - Settings Store für Persistenz (audioEnabled Pattern wiederverwendbar für speechEnabled) - CSS `@keyframes` für alle Animationen - IndexedDB Promise-Wrapper Pattern in db.ts ### Integration Points - `screens.ts` Zeile ~214 (result.correct Branch) → `playCorrectSound()` - `reward.ts` initRewardScreen → `playRewardSound()` + `speakText(comment)` - `scene.ts` forest element appear → `playForestElementSound()` - `app.ts` greeting → `speakText(greeting)` - `parent.ts` → Export/Import/Reset Buttons - `main.ts` → Error-Handler - `index.html` `` → Mute-Button ## Specific Ideas No specific requirements — open to standard approaches ## Deferred Ideas None — analysis stayed within phase scope