# GAB-122 · ExerciseDragDropSort — « Tri par catégories (accessible) »

**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-122/
  renderer.html            ← moteur tri par catégories (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` · `instruction` · `question` · `items[]{id,text,category}` · `zones[]{id,label,icon,css_class}`

Optionnels : `title`, `feedback_ok`, `feedback_ko`, `feedback_incomplete`, `status_idle`, `status_armed`, `status_continue`, `cta_label`, `accessibility`.

## Ce qui vient du JSON vs HTML
- **JSON** : libellés de chaque item, catégorie correcte, libellés et icônes des zones, tous les messages de feedback et de statut, libellé du bouton CTA.
- **HTML** : moteur tap-to-place (Pattern B armé), pool, zones, animation arming-active, layout responsive, validation, affichage feedback.

## Archétype : tap-to-place (Pattern B armé)
Interaction sans drag natif pour accessibilité mobile :
1. L'élève touche/clique un token dans la pool → token « sélectionné » (surligné + élévé) + zones pulsent.
2. L'élève touche/clique une zone → token déposé dans la zone.
3. Re-toucher un token sélectionné = désélection.
4. Bouton « Valider le tri » déclenche la correction.

## Garde-fous (child_safety / anti-invention)
- Contenu extrait UNIQUEMENT de la source HTML (INDEX-300, stage `data-tpl="122"`, handlers `ddsPick/ddsDrop/ddsCheck`).
- Aucun contenu pédagogique inventé : les 4 items, les 2 zones, les feedbacks sont copiés à l'identique.
- **BLOCKED** si `exercise_id` absent, `items` vide, ou `zones` vide.

## QA à vérifier
1. Modifier un `items[].text` ou `zones[].label` → rendu change sans toucher au HTML.
2. `items:[]` → BLOCKED propre.
3. `zones:[]` → BLOCKED propre.
4. Tri entièrement correct → `feedback_ok` affiché (style vert).
5. Un item mal classé → `feedback_ko` affiché (style rouge).
6. Valider sans tout placer → `feedback_incomplete`, pas de verdict final.
7. Responsive 375/768/1024 — zones en colonne unique < 560px.

## external_refs / dependencies
- Fait partie du lot `LOT-exerciselearning-GAB-121-125`.
- Même palette DS V2 que GAB-121, GAB-123, GAB-124, GAB-125 (mêmes variables CSS racine).
- Aucune dépendance externe : moteur autonome, 0 librairie.

## Source
`INDEX-300-exerciselearning-GAB-121-125-PLAYABLE.html` (stage `data-tpl="122"`, handlers `ddsPick`, `ddsDrop`, `ddsCheck`).
