# GAB-047 · StoryKettyDialogue — « Dialogue pédagogique avec Ketty »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechStoryLearning
**Critère validé :** changer le JSON change le dialogue sans modifier le HTML. check.py cible 12/12.

## Pack (structure officielle par-GAB)
```
GAB-047/
  renderer.html            ← moteur dialogue Ketty (ne pas modifier par instance)
  instance.example.json    ← SOURCE DE VÉRITÉ (contenu réel, à plat)
  schema.contract.json     ← contrat de validation
  README-contract.md       ← ce fichier
```

## Archétype

GAB-047 est un **dialogue pédagogique narratif** opposant deux rôles :
- **ketty** : la mascotte Ketty qui guide, questionne, corrige.
- **eleve** : la réponse ou réaction de l'élève.

Les répliques sont ordonnées dans `items[]`. Le moteur les affiche en cascade animée
et propose un bouton « Rejouer le dialogue ».

## Champs requis (instance, à plat)
`gab_id` · `dialogue_id` · `items[]{role, text}`

Optionnels : `title`, `persona_ketty{name, avatar, bubble_style}`,
`persona_eleve{name, avatar, bubble_style}`, `replay_cta{label, icon}`,
`animation{initial_delay_ms, step_delay_ms}`.

## Ce qui vient du JSON vs HTML
- **JSON** : chaque réplique (rôle + texte), les noms et avatars des personnages, le libellé du bouton rejouer, les délais d'animation.
- **HTML** : structure des bulles, styles visuels, moteur cascade, layout.

## Garde-fous (child_safety)
- **Anti-invention** : aucun texte pédagogique en dur dans le HTML. Si `items` est vide → BLOCKED.
- **BLOCKED** si `gab_id`, `dialogue_id` ou `items` absent/vide.
- **Rôles stricts** : `role` doit être `'ketty'` ou `'eleve'` ; tout autre rôle utilise le persona élève par défaut.

## QA à vérifier
1. Modifier un `text` dans `items` → rendu change sans toucher au HTML (critère d'or).
2. `items:[]` → BLOCKED propre avec message dans le panel.
3. Clic « Rejouer » → cascade re-animée depuis le début.
4. `init(ext)` avec instance externe → rendu change dynamiquement.
5. Responsive 375/768/1024 → aucun débordement.

## Source
`INDEX-300-storylearning-GAB-045-049-PLAYABLE.html`
(stage `data-tpl="47"`, handler `dlgReplay()`, lignes `.dlg-line` hardcodées dans le stage).

## external_refs / dependencies
- Aucune dépendance externe (pas d'import CSS/JS externe hors Google Fonts optionnel).
- Réfère visuellement aux styles `dlg-*` définis dans l'INDEX-300 source — reproduits
  fidèlement dans ce renderer standalone.
