# GAB-133 · ExerciseTimerChallenge — « Défi chronométré »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechExerciseLearning
**Critère validé :** changer le JSON change le défi (question, durée, options, feedbacks) sans modifier le HTML. ✅ check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-133/
  renderer.html            ← moteur défi chronométré (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` · `title` · `question` · `duration` · `primary_cta{label,action}` · `options[]{text,correct:boolean}`

Optionnels : `feedback_success` (avec placeholder `{elapsed}`), `feedback_wrong`, `feedback_timeout`, `cta_restart`, `cta_running`.

## Ce qui vient du JSON vs HTML
- **JSON** : titre, question, durée du chrono, tableau d'options (texte + flag correct), libellés des feedbacks (succès/erreur/timeout), libellé du bouton de démarrage, libellé du bouton redémarrage.
- **HTML** : barre de progression animée, affichage urgence (rouge si ≤ 3s), logique chrono, layout, fallback BLOCKED.

## Logique moteur
1. `init(ext)` accepte une instance externe ou lit `window.GAB_INSTANCE`.
2. `validate()` pousse des messages contenant `BLOCKED` si `question`, `duration` ou `options` sont absents, ou si aucune option n'est `correct:true`.
3. `startTimer()` : réinitialise l'état, lance `setInterval` d'une seconde, met à jour la barre et la valeur numérique.
4. `pickOption(el)` : stoppé si chrono non démarré ou déjà verrouillé (`tLocked`). Marque l'option cliquée ok/ko, révèle la bonne réponse, affiche le feedback.
5. `timeout()` : déclenché quand `tSec <= 0`. Révèle la bonne réponse et affiche `feedback_timeout`.
6. `{elapsed}` dans `feedback_success` est substitué par le nombre de secondes réellement utilisées.

## Garde-fous (child_safety)
- Chrono non anxiogène : urgence visuelle uniquement (rouge à ≤ 3s), aucun son.
- **BLOCKED** si `options` vide / `duration` absent / `question` absente / aucune option `correct:true`.
- Options désactivées après réponse ou timeout (pas de double clic).
- `prefers-reduced-motion` : animations réduites, chrono continue de fonctionner.

## QA à vérifier
1. Modifier `question` / `duration` / `options` → rendu change sans toucher au HTML (critère d'or).
2. `options:[]` → BLOCKED propre.
3. Aucune option `correct:true` → BLOCKED.
4. Réponse correcte avant timeout → `feedback_success` avec `{elapsed}` substitué.
5. Réponse incorrecte → `feedback_wrong` + highlight bonne réponse.
6. Timeout sans réponse → `feedback_timeout` + highlight bonne réponse.
7. Bouton « Recommencer » → réinitialisation complète.
8. Responsive 375/768/1024.

## external_refs / dependencies
- Référence dans la source : `do_not_use_when` cite GAB-132 (ExerciseFormalExam) et GAB-115 (mémo avant exam).
- `use_when` : rapidité/automatisation, tables, dates clés, vocabulaire, chrono LÉGER (pas anxiogène).

## Source
`INDEX-300-exerciselearning-GAB-131-135-PLAYABLE.html` (stage `data-tpl="133"`, handlers `tchStart/tchStop/tchPick/tchTimeout/tchUpdate`).
