---
phase: 03-komplettes-spielerlebnis
plan: 05
type: execute
wave: 2
depends_on: [03-01]
files_modified:
  - src/ui/parent.ts
  - index.html
  - src/styles/main.css
  - src/app.ts
autonomous: true
requirements: [PRNT-01, PRNT-02, PRNT-03, PRNT-04]
must_haves:
  truths:
    - "Ctrl+Shift+E opens a code input prompt"
    - "Entering '1234' navigates to parent area screen"
    - "Parent area shows current level, completed sessions, practice days as calendar dots"
    - "Parent area shows average accuracy and most frequent error keys"
    - "Settings allow changing layout, toggling audio, changing companion, entering API key"
  artifacts:
    - path: "src/ui/parent.ts"
      provides: "initParentScreen() with stats display and settings panel"
      exports: ["initParentScreen", "showParentCodePrompt"]
    - path: "index.html"
      provides: "Parent screen HTML with stats overview and settings form"
      contains: "parent-stats"
  key_links:
    - from: "src/ui/parent.ts"
      to: "src/storage/db.ts"
      via: "getProgress, saveProgress, getSettings, saveSettings"
      pattern: "getProgress"
    - from: "src/app.ts"
      to: "src/ui/parent.ts"
      via: "showParentCodePrompt on Ctrl+Shift+E"
      pattern: "showParentCodePrompt"
---

<objective>
Build the parent area: gated access via Ctrl+Shift+E + code "1234", stats overview (level, sessions, practice days, accuracy, error keys), and settings (layout, audio, companion, API key).

Purpose: Parents can see progress and adjust settings without the child being exposed to performance metrics.
Output: Parent screen with stats and settings, access gate wired into app.ts.
</objective>

<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/03-komplettes-spielerlebnis/03-01-SUMMARY.md
@src/app.ts
@src/storage/db.ts
@src/types.ts
@src/companion/characters.ts
@index.html
@src/styles/main.css

<interfaces>
<!-- From src/types.ts (after Plan 01): -->
export interface Progress {
  id: 1;
  currentLevel: number;
  completedLevels: number[];
  totalSessions: number;
  sessionDates: string[]; // ISO date strings "YYYY-MM-DD"
  selectedCharacter: CompanionType;
  selectedLayout: KeyboardLayout;
  totalCorrect: number;
  totalErrors: number;
  errorKeyCounts: Record<string, number>;
  lastPlayedLevels: number[];
}

export interface Settings {
  id: 1;
  audioEnabled: boolean;
  apiKey: string;
  apiCallsToday: { text: number; image: number };
  lastApiCallDate: string;
}

<!-- From src/storage/db.ts (existing): -->
export function getProgress(db: IDBDatabase): Promise<Progress | null>;
export function saveProgress(db: IDBDatabase, progress: Progress): Promise<void>;
export function getSettings(db: IDBDatabase): Promise<Settings | null>;
export function saveSettings(db: IDBDatabase, settings: Settings): Promise<void>;

<!-- From src/companion/characters.ts (existing): -->
export interface CompanionDefinition { type: CompanionType; name: string; emoji: string; personality: string; avatarUrl: string; }
export const companions: CompanionDefinition[];

<!-- From src/app.ts (existing): -->
export function showScreen(name: ScreenName): void;
export function getDB(): IDBDatabase;
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Parent area HTML, CSS, and access gate</name>
  <files>index.html, src/styles/main.css, src/ui/parent.ts</files>
  <read_first>index.html, src/styles/main.css, src/types.ts, src/storage/db.ts, src/companion/characters.ts</read_first>
  <action>
    **Update index.html** — replace empty `<section id="screen-parent">` (per D-14, D-17, D-18):

    ```html
    <section id="screen-parent" class="screen">
      <div class="parent">
        <button class="parent__back-btn" id="parent-back-btn">&#x2190; Zurueck</button>
        <h1 class="parent__title">Elternbereich</h1>

        <!-- Code gate overlay -->
        <div class="parent__gate" id="parent-gate">
          <p>Bitte Code eingeben:</p>
          <input type="password" id="parent-code-input" class="parent__code-input" maxlength="4" placeholder="____" inputmode="numeric">
          <p class="parent__gate-error" id="parent-gate-error" style="display:none">Falscher Code</p>
        </div>

        <!-- Content (hidden until code entered) -->
        <div class="parent__content" id="parent-content" style="display:none">

          <section class="parent__section">
            <h2>Uebersicht</h2>
            <div class="parent__stats" id="parent-stats">
              <div class="parent__stat">
                <span class="parent__stat-label">Aktuelle Stufe</span>
                <span class="parent__stat-value" id="stat-level">-</span>
              </div>
              <div class="parent__stat">
                <span class="parent__stat-label">Einheiten</span>
                <span class="parent__stat-value" id="stat-sessions">-</span>
              </div>
              <div class="parent__stat">
                <span class="parent__stat-label">Genauigkeit</span>
                <span class="parent__stat-value" id="stat-accuracy">-</span>
              </div>
            </div>
            <div class="parent__calendar" id="parent-calendar">
              <h3>Uebungstage</h3>
              <div class="parent__calendar-dots" id="calendar-dots"></div>
            </div>
            <div class="parent__errors" id="parent-errors">
              <h3>Haeufigste Fehlertasten</h3>
              <div id="error-keys-list"></div>
            </div>
          </section>

          <section class="parent__section">
            <h2>Einstellungen</h2>
            <div class="parent__settings">
              <div class="parent__setting">
                <label>Tastatur-Layout</label>
                <select id="setting-layout">
                  <option value="de">DE (Deutschland)</option>
                  <option value="ch">CH (Schweiz)</option>
                </select>
              </div>
              <div class="parent__setting">
                <label>Audio</label>
                <label class="parent__toggle">
                  <input type="checkbox" id="setting-audio">
                  <span>An/Aus</span>
                </label>
              </div>
              <div class="parent__setting">
                <label>Begleitfigur</label>
                <select id="setting-companion"></select>
              </div>
              <div class="parent__setting">
                <label>API-Key</label>
                <input type="password" id="setting-apikey" class="parent__input" placeholder="Gemini API Key">
                <button class="parent__save-btn" id="save-apikey-btn">Speichern</button>
              </div>
            </div>
          </section>

        </div>
      </div>
    </section>
    ```

    **Add CSS to `src/styles/main.css`:**
    ```css
    /* Parent Area */
    .parent {
      max-width: 600px;
      margin: 0 auto;
      padding: 1.5rem;
    }

    .parent__back-btn {
      background: none;
      border: none;
      font-family: var(--font-heading);
      font-size: 1rem;
      color: var(--text-warm);
      cursor: pointer;
      margin-bottom: 1rem;
    }

    .parent__title {
      font-family: var(--font-heading);
      color: var(--text-dark);
      margin-bottom: 1.5rem;
    }

    .parent__gate {
      text-align: center;
      padding: 2rem;
      font-family: var(--font-body);
    }

    .parent__code-input {
      font-size: 2rem;
      text-align: center;
      width: 120px;
      padding: 0.5rem;
      border: 2px solid var(--accent-purple);
      border-radius: 8px;
      font-family: var(--font-heading);
      letter-spacing: 0.5rem;
      margin-top: 0.5rem;
    }

    .parent__gate-error {
      color: var(--accent-pink);
      margin-top: 0.5rem;
      font-size: 0.9rem;
    }

    .parent__section {
      margin-bottom: 2rem;
    }

    .parent__section h2 {
      font-family: var(--font-heading);
      color: var(--text-dark);
      border-bottom: 2px solid var(--bg-forest);
      padding-bottom: 0.5rem;
      margin-bottom: 1rem;
    }

    .parent__stats {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 1rem;
      margin-bottom: 1.5rem;
    }

    .parent__stat {
      background: var(--bg-forest);
      border-radius: 12px;
      padding: 1rem;
      text-align: center;
    }

    .parent__stat-label {
      display: block;
      font-family: var(--font-body);
      font-size: 0.85rem;
      color: var(--text-warm);
      margin-bottom: 0.25rem;
    }

    .parent__stat-value {
      display: block;
      font-family: var(--font-heading);
      font-size: 1.5rem;
      font-weight: 700;
      color: var(--text-dark);
    }

    .parent__calendar-dots {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      margin-top: 0.5rem;
    }

    .parent__calendar-dot {
      width: 12px;
      height: 12px;
      border-radius: 50%;
      background: var(--accent-green);
    }

    .parent__calendar-dot--empty {
      background: var(--bg-cream);
      border: 1px solid var(--text-light);
    }

    .parent__errors h3,
    .parent__calendar h3 {
      font-family: var(--font-heading);
      font-size: 1rem;
      color: var(--text-warm);
      margin-bottom: 0.5rem;
    }

    .parent__error-key {
      display: inline-block;
      background: var(--accent-pink);
      color: white;
      padding: 0.25rem 0.75rem;
      border-radius: 8px;
      margin: 0.25rem;
      font-family: var(--font-heading);
      font-size: 0.9rem;
    }

    .parent__settings {
      display: flex;
      flex-direction: column;
      gap: 1rem;
    }

    .parent__setting {
      display: flex;
      align-items: center;
      gap: 1rem;
    }

    .parent__setting label:first-child {
      min-width: 120px;
      font-family: var(--font-body);
      color: var(--text-warm);
    }

    .parent__setting select,
    .parent__input {
      font-family: var(--font-body);
      padding: 0.5rem;
      border: 1px solid var(--text-light);
      border-radius: 8px;
      font-size: 0.95rem;
    }

    .parent__save-btn {
      font-family: var(--font-heading);
      padding: 0.5rem 1rem;
      background: var(--accent-green);
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
    }
    ```

    **Create `src/ui/parent.ts`:**

    ```typescript
    import { getProgress, saveProgress, getSettings, saveSettings } from '../storage/db';
    import { companions } from '../companion/characters';
    import type { CompanionType, KeyboardLayout } from '../types';
    import { showScreen, getDB } from '../app';
    ```

    **`showParentCodePrompt()`** (per D-14, PRNT-01):
    - Show parent screen: `showScreen('parent')`
    - Show gate, hide content
    - Focus code input
    - On input change, if value === '1234': hide gate, show content, call `loadParentData()`
    - If value.length === 4 but wrong: show error, clear after 1.5s

    **`initParentScreen(db: IDBDatabase, onBack: () => void)`:**
    Wire back button to `onBack` callback.

    **`loadParentData()`** (per D-17, PRNT-02, PRNT-03):
    1. Get progress from IndexedDB
    2. Set `#stat-level` to `progress.currentLevel`
    3. Set `#stat-sessions` to `progress.totalSessions`
    4. Calculate accuracy: `progress.totalCorrect + progress.totalErrors > 0 ? Math.round(progress.totalCorrect / (progress.totalCorrect + progress.totalErrors) * 100) : 0`
    5. Set `#stat-accuracy` to `${accuracy}%`
    6. Render calendar dots in `#calendar-dots`:
       - Get last 30 days as date strings
       - For each day: if in `progress.sessionDates`, render green dot, else empty dot
    7. Render error keys in `#error-keys-list`:
       - Sort `progress.errorKeyCounts` by value descending
       - Show top 5 keys as colored badges: `<span class="parent__error-key">E (12x)</span>`
       - If no errors: show "Noch keine Fehler erfasst"

    **Settings (per D-18, PRNT-04):**
    1. Populate companion select from `companions` array
    2. Set current values from progress (layout, companion) and settings (audio, apiKey)
    3. On layout change: `saveProgress(db, { ...progress, selectedLayout: value })`
    4. On companion change: `saveProgress(db, { ...progress, selectedCharacter: value })`
    5. On audio toggle: `saveSettings(db, { ...settings, audioEnabled: checked })`
    6. On save API key: `saveSettings(db, { ...settings, apiKey: value })`
    7. Each save shows brief "Gespeichert!" feedback
  </action>
  <verify>
    <automated>npx tsc --noEmit && grep -c "showParentCodePrompt" src/ui/parent.ts && grep -c "parent-gate" index.html && grep -c "parent__calendar-dot" src/styles/main.css</automated>
  </verify>
  <acceptance_criteria>
    - grep "showParentCodePrompt" src/ui/parent.ts returns export
    - grep "1234" src/ui/parent.ts returns match (access code)
    - grep "parent-gate" index.html returns match (gate overlay)
    - grep "stat-level" index.html returns match (stats display)
    - grep "stat-accuracy" index.html returns match
    - grep "calendar-dots" index.html returns match
    - grep "error-keys-list" index.html returns match
    - grep "setting-layout" index.html returns match (layout setting)
    - grep "setting-companion" index.html returns match (companion setting)
    - grep "setting-apikey" index.html returns match (API key setting)
    - grep "parent__calendar-dot" src/styles/main.css returns match
    - grep "parent__error-key" src/styles/main.css returns match
    - npx tsc --noEmit exits 0
  </acceptance_criteria>
  <done>Parent area gate with code "1234", stats overview with level/sessions/accuracy/calendar-dots/error-keys, settings for layout/audio/companion/API-key. All styled and functional.</done>
</task>

<task type="auto">
  <name>Task 2: Wire parent area into app.ts</name>
  <files>src/app.ts</files>
  <read_first>src/app.ts, src/ui/parent.ts</read_first>
  <action>
    **Wire parent area access in `src/app.ts`** (per D-14, PRNT-01):

    1. Import: `import { showParentCodePrompt, initParentScreen } from './ui/parent';`

    2. In `initApp()`, after DB is opened, call:
       ```typescript
       initParentScreen(db, async () => {
         // Back from parent -> return to forest
         await initForestScreen(db, startLessonFromForest);
         showScreen('forest');
       });
       ```

    3. Replace the stub `showParentCodePrompt` reference (if Plan 04 added a stub) or add the global keydown listener:
       ```typescript
       document.addEventListener('keydown', (e) => {
         if (e.ctrlKey && e.shiftKey && e.key === 'E') {
           e.preventDefault();
           showParentCodePrompt();
         }
       });
       ```
       Add this in `initApp()` after DB setup. Ensure it's only added once.

    4. Make sure `showParentCodePrompt` properly uses the DB reference. Since `parent.ts` imports `getDB` from `app.ts`, it can access the DB.
  </action>
  <verify>
    <automated>npx tsc --noEmit && grep -c "showParentCodePrompt" src/app.ts && grep -c "initParentScreen" src/app.ts</automated>
  </verify>
  <acceptance_criteria>
    - grep "import.*showParentCodePrompt" src/app.ts returns match
    - grep "import.*initParentScreen" src/app.ts returns match
    - grep "ctrlKey.*shiftKey" src/app.ts returns match (keyboard shortcut)
    - grep "initParentScreen" src/app.ts shows it's called in initApp
    - npx tsc --noEmit exits 0
  </acceptance_criteria>
  <done>Parent area fully wired: Ctrl+Shift+E triggers code prompt, "1234" opens parent screen, back button returns to forest. Global listener registered once in initApp.</done>
</task>

</tasks>

<verification>
- `npx tsc --noEmit` — no type errors
- `npx vitest run` — all tests pass
- Parent area accessible via Ctrl+Shift+E + "1234"
- Stats show current data, settings persist changes
</verification>

<success_criteria>
1. Ctrl+Shift+E opens code input overlay on parent screen
2. Code "1234" reveals parent content, wrong code shows error
3. Overview shows: current level, total sessions, accuracy percentage
4. Calendar dots show last 30 days with green dots for practice days
5. Error keys shown as badges, sorted by frequency, top 5
6. Settings: layout change, audio toggle, companion change, API key save — all persist to IndexedDB
7. Back button returns to forest screen
</success_criteria>

<output>
After completion, create `.planning/phases/03-komplettes-spielerlebnis/03-05-SUMMARY.md`
</output>
