- Import SLOTS_PER_PAGE in reward.ts; replace hardcoded 12 with it
- Import SLOTS_PER_PAGE and getForestElements in app.ts
- Zurueck zum Wald callback navigates to page containing new element
- currentForestPage updated in progress before initForestScreen
- Add saveProgress import to scene.ts
- Wire prevBtn/nextBtn onclick handlers in initForestScreen
- Persist currentForestPage to IndexedDB on every navigation
- Add fade-out/fade-in opacity transition on page changes
- Add forest__nav container with prev/next buttons and page indicator in index.html
- Navigation placed between forest scene and level map, hidden by default
- Add .forest__nav, .forest__nav-btn, .forest__nav-text CSS classes
- 44px minimum touch targets on nav buttons, pastel BEM styling
- Buttons use Quicksand font matching app design language
- Add currentForestPage: number field to Progress interface in types.ts
- Export SLOTS_PER_PAGE = 12 constant from scene.ts
- Change renderForestScene signature to accept page: number parameter
- Slice elements by page (start/end = page * SLOTS_PER_PAGE)
- Update navigation UI (forest-nav) after rendering
- Add migrateProgress entry for currentForestPage in app.ts
- Fix Progress object literals in db.test.ts and screens.ts to include new field
- levels.test.ts: change length assertion to 16, add newKeys tests for levels 7-16
- levels.test.ts: add Level 16 allKeys completeness test (all QWERTZ keys)
- words.test.ts: extend all loops from 6 to 16 levels, add validateWordList test
- companion.test.ts: fix unknown-letter test to use '@' (z now has a fallback entry)
- Add German word lists for levels 7-16 (10 words each, max 5 chars)
- All words validated against allowed keys per level
- Level 16 uses short words with period for punctuation practice
- Add 19 new fallback letter introductions (r,u,t,z,w,o,q,p,n,b,v,m,c,x,ä,ü,y,, ,.)
- Update entry count comment to 32 entries (levels 1-16)
- Add levels 7-16 covering r,u,t,z,w,o,q,p,n,b,v,m,c,x,ä,ü,y and punctuation
- Add comma and period to fingerMap (r-mid and r-ring)
- Update keyboard.ts: add ',' and '.' to bottom row in DE and CH layouts
- Add comma and period to fingerColorMap in keyboard.ts
- Full project overview with tagline and concept description
- Features, tech stack, prerequisites, getting started sections
- Available scripts table, project structure tree
- How It Works explanation of the three-phase lesson loop
- Configuration, deployment, contributing, and license sections
- Added forest__intro paragraph between title and greeting area in index.html
- Added .forest__intro CSS block with Nunito font, centered, pastel-style styling
- setPhase("practice") now shows full instruction instead of "Ueben"
- setPhase("words") now shows full instruction instead of "Woerter"
- Removed 2500ms delay and companion text flicker in runPracticePhase
- Removed 2500ms delay and companion text flicker in runWordsPhase
- src/app.ts: greeting text now renders inline markdown
- src/ui/screens.ts: letter intro text now renders inline markdown
- src/forest/reward.ts: forest comment now renders inline markdown
- All 3 sites use innerHTML with XSS-safe renderInlineMarkdown
- Escapes HTML special chars first (XSS safe)
- Converts **bold** to <strong>, *italic* to <em>
- Standalone asterisks with spaces are left unchanged
- Pure function, no DOM dependency
- Practice phase shows 'Jetzt kannst du ueben! Druecke die Taste zu dem Buchstaben, der herunterfaellt.' for 2.5s before exercise starts
- Words phase shows 'Jetzt kommen ganze Woerter! Tippe die Buchstaben nacheinander ein.' for 2.5s before exercise starts
- Both functions converted to async/await pattern matching existing discover phase
- Companion text cleared after delay before exercises begin
- Replace 'if (key === " ") continue' with a dedicated space bar step
- Shows ␣ symbol large with 'Leertaste' label underneath
- Companion text explains the symbol in child-friendly German
- Highlights and pulses the space key on the keyboard
- Child must press space bar once to confirm understanding and continue
- html/body: height 100dvh, overflow hidden
- .screen--active: height 100dvh instead of min-height 100vh
- Forest/lesson/reward/welcome: flex: 1 to fill available space
- Forest scene: flex: 1 with min-height: 0 to shrink properly
- Reduced padding and font sizes for better fit
- Continue button and title: flex-shrink: 0 to stay visible
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Click any forest element or reward image to see it large
- Smooth zoom-in animation, click anywhere to close
- Hover effect on clickable images
- Works on both forest grid and reward screen
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SUMMARY.md with all task commits and decisions
- STATE.md updated to 100% progress, phase 04 complete
- ROADMAP.md updated with plan progress
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- playCorrectSound() on correct keypress in letter and word exercises
- playRewardSound() when reward image appears
- speakText() for companion comment on reward screen
- playForestElementSound() when new forest element renders
- speakText() for companion greeting on forest screen
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 04-01-SUMMARY.md with execution results
- Update STATE.md with position, decisions, metrics
- Update ROADMAP.md with plan progress
- Mark AUDI-01 through AUDI-05 complete in REQUIREMENTS.md
- SUMMARY.md with plan results and decisions
- STATE.md updated with progress and metrics
- ROADMAP.md and REQUIREMENTS.md updated
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 04-02-SUMMARY.md with animation and error handler results
- Update STATE.md with progress, decisions, metrics
- Update ROADMAP.md with plan progress
- Mark PLSH-01 through PLSH-05 complete in REQUIREMENTS.md
- Create src/audio/sounds.ts with playCorrectSound, playRewardSound, playForestElementSound
- Create src/audio/speech.ts with speakText via Web Speech API
- Add speechEnabled field to Settings interface in types.ts
- Add speechEnabled defaults in all Settings initializers (gemini.ts, parent.ts, db.test.ts)
- All sound functions check audioEnabled, speakText checks speechEnabled
- AudioContext lazy initialization for autoplay policy compliance
- Add error overlay HTML element in index.html before script tag
- Add window error + unhandledrejection listeners in main.ts
- Add error overlay CSS styles (fixed, z-index 9999, tree icon, reload button)
- Error message: "Oh, der Wald braucht kurz eine Pause..."
- HTML section with export-btn, import-btn, reset-btn, hidden file input
- CSS styles for action buttons including danger variant for reset
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CSS radial-gradient mask for organic blending into forest scene
- Generate with light green background instead of transparency (avoids checkerboard)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SUMMARY.md for reward module and game flow wiring
- STATE.md updated with position, decisions, metrics
- ROADMAP.md updated with plan progress
- Requirements RWRD-01 through RWRD-04 marked complete
- Lesson completion now shows reward screen instead of going directly to forest
- Pre-generation starts at lesson begin (fire-and-forget)
- Stats accumulated (correct/errors/errorKeys) in progress after each lesson
- Review mode triggers every 3rd session
- Encouragement shown after 2x same level (repetition protection)
- Progress migration for older saved data without new fields
- Create src/forest/reward.ts with startPreGeneration() and initRewardScreen()
- Image pre-generation starts at lesson begin, placeholder shows while loading
- Fallback to static SVGs when rate-limited or API unavailable
- Reward screen HTML with image area, companion comment, action buttons
- CSS for reward screen with animated leaves placeholder and image appear animation
- Discover phase: companion introduces new key, key pulses, child presses once
- Practice phase: existing letter exercise with cumulative stats
- Words phase: word display with active letter highlighting
- Review mode skips discover, mixes letters/words from recent levels
- Encouragement messages for repetition protection
- Phase indicator UI (Entdecken / Ueben / Woerter)
- CSS for word display, phase indicator, discover pulse animation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 03-05-SUMMARY.md with plan execution results
- Update STATE.md, ROADMAP.md, REQUIREMENTS.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Import showParentCodePrompt and initParentScreen from ui/parent
- Register global Ctrl+Shift+E keyboard listener in initApp
- Initialize parent screen with back-to-forest callback
- Add parent screen HTML with code gate, stats overview, and settings form
- Add parent area CSS styles for stats grid, calendar dots, error badges, settings
- Create src/ui/parent.ts with showParentCodePrompt, initParentScreen, loadParentData
- Add createWordExerciseState() that splits words into letters with boundaries
- Add getCurrentWordIndex() helper for UI word tracking
- Extend TypingExerciseState with mode, words, wordBoundaries fields
- Backwards compatible: createExerciseState sets mode='letters'
- All 85 tests pass
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Tests for createWordExerciseState, getCurrentWordIndex
- Backwards compatibility test for createExerciseState mode field
- handleKeyPress test with word-mode state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SUMMARY.md with execution results
- STATE.md updated with position and decisions
- ROADMAP.md updated with plan progress
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SUMMARY.md with forest scene implementation details
- STATE.md updated with progress and decisions
- ROADMAP.md updated with plan progress
- Requirements FRST-01, FRST-02, FRST-03 marked complete
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Progress: added totalCorrect, totalErrors, errorKeyCounts, lastPlayedLevels
- New LessonPhase type: discover | practice | words
- Rate limits: 10 text / 5 image per day (was 1 each)
- Updated screens.ts with new Progress field defaults
- Updated existing tests for new rate limits and Progress shape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- renderForestScene() loads elements from IDB and renders as images
- Object URLs tracked and revoked on re-render to prevent memory leaks
- Random +-10-20px offset for natural element placement
- New element animation class applied via newElementId parameter
- Integrated into initForestScreen alongside renderLevelMap
- Static word lists for levels 1-6, 8-10 words each
- Levels 1-2 use letter combos (no real words possible with F/J/D/K)
- Levels 3-6 mix real German words with combos
- All words validated: only use learned letters, max 5 chars
- getWordsForLevel with/without replacement sampling
- All 8 tests pass
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SVG woodland background with sky gradient, clouds, sun, trees, hills, ground
- 4x3 CSS grid overlay for forest element placement
- Fade-in + scale-up animation keyframes for new elements
- Tests for wordsByLevel entries levels 1-6
- Tests for allKeys-only characters validation
- Tests for max 5 chars per word
- Tests for getWordsForLevel random selection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 plans across 3 waves covering all 17 requirements:
- Plan 01 (W1): Word lists, Progress extension, rate limits
- Plan 02 (W2): Lesson 3-phase state machine, review/repeat
- Plan 03 (W1): Forest visual scene with SVG + grid
- Plan 04 (W3): Reward screen, pre-generation, full flow wiring
- Plan 05 (W2): Parent area with stats and settings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add forest-greeting companion area in HTML with avatar + text
- Add lesson-companion area in HTML above letter area
- Wire getGreeting() call for returning users in app.ts
- Show companion avatar in lesson screen via getProgress lookup
- Fix pre-existing noUncheckedIndexedAccess errors in fallbacks.ts (Rule 3)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extend CompanionDefinition with avatarUrl field using Vite static imports
- Replace emoji-only companion cards with avatar img + onerror emoji fallback
- Add companion-card__avatar CSS (80px round) and companion-area styles (48px)
- Add vite-env.d.ts for PNG import type declarations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SUMMARY: 6 IndexedDB accessors + 9 generated assets via Gemini API
- STATE: advance to plan 4/5, 90% progress
- ROADMAP: update phase 02 plan progress
- REQUIREMENTS: mark ASST-01, ASST-02 complete
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SUMMARY.md with task commits and decisions
- STATE.md advanced to plan 4 of 5, 80% progress
- ROADMAP.md updated with plan progress
- Requirements COMP-01 through COMP-04 marked complete
- getGreeting: AI greeting with time-of-day context, falls back to static texts
- getLetterIntro: AI letter introduction with finger description, falls back to curated intros
- getForestComment: AI forest element comment, falls back to static comments
- All functions check config availability and rate limits before API calls
- System prompts enforce max 25 words, simple German, no performance praise
- Tests for getGreeting, getLetterIntro, getForestComment
- Covers API success, API failure, no config, rate-limited paths
- 12 test cases total with mocked dependencies
- Config loader: fetches/caches public/config.json with GeminiConfig interface
- generateText: Gemini REST with 3x exponential backoff retry, returns string|null
- generateImage: reference images as base64 inlineData, responseModalities: ["IMAGE"]
- Rate limiting: checkRateLimit/incrementApiCall with daily reset in Settings store
- Extended Settings type with apiCallsToday and lastApiCallDate fields
- 18 tests across config.test.ts and gemini.test.ts, all passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>