# GAB-065 · StoryCheckpoint — « Point de contrôle narratif »

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

## Pack (structure officielle par-GAB)
```
GAB-065/
  renderer.html            ← moteur checkpoint narratif (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
**StoryCheckpoint** = point de contrôle narratif d'auto-évaluation. L'élève déclare lui-même s'il a compris (CTA oui / CTA non). Pas de notation, pas de correction : c'est un signal d'intention qui permet au parcours de proposer soit la suite, soit une révision. Gabarit S · P0 · V1_CORE.

## Champs requis (instance, à plat)
`gab_id` · `checkpoint_id` · `question` · `primary_cta{label,icon,action}` · `secondary_cta{label,icon,action}` · `feedback_yes` · `feedback_no`

Optionnels : `icon`, `section_label`, `accessibility{aria_label_card,keyboard_navigable}`.

## Ce qui vient du JSON vs HTML
- **JSON** : la question, les libellés des deux boutons, leurs icônes, les deux feedbacks, l'icône du flag, le label de section.
- **HTML** : la structure carte, les couleurs DS V2 (magenta/violet), la logique de désactivation des boutons après réponse, le layout responsive.

## Garde-fous (child_safety)
- **Anti-invention** : la `question` est extraite verbatim de la source HTML playable — jamais générée.
- **Feedbacks distincts** : `feedback_yes` (mint) et `feedback_no` (gold) sont deux messages séparés, pas une variante d'un seul.
- **Désactivation post-réponse** : les deux boutons sont `disabled` après le premier clic (pas de double-réponse).
- **BLOCKED** si `question`, `primary_cta` ou `secondary_cta` absent.

## QA à vérifier
1. Modifier `question`/`feedback_yes`/`feedback_no` dans le JSON → rendu change sans toucher au HTML (critère d'or).
2. `question` absente → BLOCKED propre.
3. Clic "oui" → `feedback_yes` affiché en `var(--mint-deep)`, boutons désactivés.
4. Clic "non" → `feedback_no` affiché en `var(--gold-deep)`, boutons désactivés.
5. Responsive 375/768/1024 — boutons empilés sur mobile.
6. Instance externe `ENGINE.init({...})` → rendu mis à jour dynamiquement.

## Différences avec les autres GAB du lot
- **GAB-066 StoryNarrativeBoss** : choix multiple avec bonne/mauvaise réponse → différent de l'auto-évaluation binaire oui/non de GAB-065.
- **GAB-060** (hors lot) : question inline simple sans feedback bifurqué.

## Source
`INDEX-300-storylearning-GAB-065-069-PLAYABLE.html` (stage `data-tpl="65"`, handler `cpAnswer()`).
