# GAB-121 · ExerciseFillBlank — « Texte à trou »

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

## Pack (structure officielle par-GAB)
```
GAB-121/
  renderer.html            ← moteur texte à trou (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` · `exercise_id` · `sentence_before` · `answer` · `question`

Optionnels : `title`, `instruction`, `sentence_after`, `blank_placeholder`, `suggestions[]`, `feedback_correct`, `feedback_incorrect`, `cta_label`, `input_placeholder`.

## Ce qui vient du JSON vs HTML
- **JSON** : la phrase (avant/après le blanc), la réponse correcte, les suggestions chips, les textes de feedback (correct/incorrect), le libellé du bouton, le placeholder de l'input.
- **HTML** : le layout, la phrase avec le span blanc, le champ texte, les chips en conteneur flex, le bouton structurel, le bloc feedback.

## Archétype & comportement
- Phrase découpée en `sentence_before` + `[blanc]` + `sentence_after`.
- L'élève saisit librement dans l'input OU clique une chip suggestion (qui injecte dans l'input).
- Validation via bouton : comparaison `toLowerCase()` — insensible à la casse.
- Blank passe en `.ok` (mint) ou `.ko` (coral) selon la réponse.
- Feedback `feedback_correct` / `feedback_incorrect` : HTML autorisé (`<b>`, etc.).

## Garde-fous
- **BLOCKED** si `answer` absent, `question` absente, ou `sentence_before`+`sentence_after` tous deux absents.
- `feedback_incorrect` injecté via `innerHTML` — HTML light autorisé, pas de scripts.
- `answer` comparé en `toLowerCase()` : la casse du JSON n'affecte pas la correction côté élève.
- Les suggestions sont optionnelles : si absentes, seul le champ texte libre est affiché.

## QA à vérifier
1. Modifier `sentence_before`/`answer`/`suggestions` → rendu change sans toucher au HTML (critère d'or).
2. `answer` absent → BLOCKED propre.
3. Bonne réponse → blank `.ok` + `feedback_correct` affiché.
4. Mauvaise réponse → blank `.ko` + `feedback_incorrect` affiché.
5. Clic chip → valeur injectée dans l'input.
6. Bouton sans saisie → message "Champ vide".
7. Responsive 375/768/1024.

## Références externes (external_refs / dependencies)
- **use_when** : compléter un mot/date/formule dans une phrase — exercice NOTÉ avec correction.
- **do_not_use_when** : cloze Memory non noté (→ GAB-106), QCM (→ GAB-117), rédaction ouverte (→ GAB-125).
- **Lot** : LOT-exerciselearning-GAB-121-125 · GAB-122 (DragDropSort), GAB-123 (Matching), GAB-124 (Ordering), GAB-125 (OpenExplain).

## Source
`INDEX-300-exerciselearning-GAB-121-125-PLAYABLE.html` (stage `data-tpl="121"`, handlers `fbTry`/`fbCheck`).
