# GAB-046 · StoryNarrativeScene — « Scène narrative »

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

## Pack (structure officielle par-GAB)
```
GAB-046/
  renderer.html            ← moteur scène narrative (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
```

## Champs requis (instance, à plat)
`gab_id` · `scene_id` · `scene_narration` · `scene_steps[]` (au moins 1 item)

Optionnels : `title`, `scene_emoji`, `cta_label`, `cta_label_counting`, `cta_label_done`.

## Ce qui vient du JSON vs HTML
- **JSON** : narration initiale, chaque étape progressive, emoji visuel, libellés bouton (normal / avec compteur / terminé).
- **HTML** : layout carte, bandeau visuel, animation `scene-float`, logique `next()`, désactivation bouton, slots affichés.

## Archétype : progressive_reveal
La scène s'ouvre sur un paragraphe narratif initial. L'élève clique pour révéler les étapes une à une (compteur `{remaining}`). À la dernière étape, le bouton se désactive — le récit est clos. Le moteur ne recharge pas la page, il appende les paragraphes dans le DOM.

## Garde-fous (child_safety)
- **Contenu narratif uniquement** — pas de quiz noté, pas de feedback correct/incorrect.
- **BLOCKED** si `scene_narration` absent, `scene_steps` vide, ou `scene_id` absent.
- **Anti-invention** : les 3 étapes et la narration initiale sont extraites du HTML source `INDEX-300-storylearning-GAB-045-049-PLAYABLE.html` (stage `data-tpl="46"`, handler `sceneNext()`). Aucun texte inventé.
- Bouton disabled après révélation complète — l'élève ne peut pas cliquer "dans le vide".

## QA à vérifier
1. Modifier `scene_narration` → rendu change sans toucher au HTML (critère d'or).
2. `scene_steps:[]` → BLOCKED propre.
3. Clic bouton 3 fois → 3 étapes révélées, bouton `disabled` après la 3e.
4. `cta_label_counting` avec `{remaining}` → décompte visible dans le bouton.
5. `init(customInstance)` → le moteur utilise l'instance externe, pas `window.GAB_INSTANCE`.
6. Responsive 375/768/1024 → aucun débordement horizontal.

## Références externes
- `→ GAB-045` : intro complète avant la scène.
- `→ GAB-047` : si la scène est suivie d'un dialogue pédagogique avec Ketty.

## Source
`INDEX-300-storylearning-GAB-045-049-PLAYABLE.html` (stage `data-tpl="46"`, styles `.scene-*`, handler `sceneNext()` + array `SCENE_STEPS`).
