# GAB-053 · StoryCharacterExplains — « Un personnage explique »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechStoryLearning
**Critère validé :** changer le JSON change l'avatar, le discours et les tags sans modifier le HTML. check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-053/
  renderer.html            ← moteur personnage (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

**StoryCharacterExplains** : un personnage historique ou fictif de l'épisode prend la parole à la première personne pour rendre une notion abstraite concrète et incarnée. Le discours direct + les tags thématiques créent l'ancrage émotionnel et pédagogique.

Complexité source : **S · P0** (simple, priorité maximale dans EdTechStoryLearning).

## Champs requis (instance, à plat)
`gab_id` · `screen_id` · `character_name` · `character_role` · `speech` · `items[]{label}`

Optionnels : `title`, `character_avatar_emoji`, `persona{src?,alt?,emoji?}`, `illustration{src,alt}`, `primary_cta{label,action}`.

## Ce qui vient du JSON vs HTML
- **JSON** : nom du personnage, rôle contextuel, emoji avatar, discours verbatim, tags thématiques, libellé du bouton CTA.
- **HTML** : layout card (tête + discours + tags), couleurs gold/coral (signature personnage), bouton structurel, fallback BLOCKED.

## Garde-fous (anti-invention)
- Le contenu extrait vient UNIQUEMENT du `data-tpl="53"` dans `INDEX-300-storylearning-GAB-050-054-PLAYABLE.html`.
- Champs `persona` et `illustration` absents du source HTML → portent `_TODO` dans l'instance, jamais inventés.
- **BLOCKED** si `speech`, `items`, `character_name`, `character_role` ou `screen_id` sont absents.
- `primary_cta.label` vient du JSON, jamais hardcodé dans le HTML.

## _TODO / contenus manquants
- `persona` : illustration/avatar riche du personnage non présente dans le source HTML (au-delà de l'emoji).
- `illustration` : image de contexte de scène non présente dans le source HTML.

## QA à vérifier
1. Modifier `speech` → rendu change sans toucher au HTML (critère d'or).
2. `items:[]` → BLOCKED propre.
3. `speech` absent → BLOCKED propre.
4. Injection via `ENGINE.init({...})` → rendu change (mode externe).
5. Responsive 375/768/1024 — avatar + tags sans débordement.

## External refs / dependencies
- **GAB-047** (`StoryKettyExplains`) : similaire mais réservé à la mascotte Ketty IA — ne pas utiliser GAB-053 pour Ketty.
- **GAB-052** (`StoryMiniLesson`) : leçon neutre structurée sans point de vue personnage — préférer si pas de discours direct.
- **GAB-046** (`StoryNarration`) : narration sans personnage incarné.

## Source
`INDEX-300-storylearning-GAB-050-054-PLAYABLE.html` (stage `data-tpl="53"`, section `.char-card`).
