# GAB-146 · InteractiveSortLab — « Lab de tri exploratoire (B armé) »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechInteractiveLearning
**Critère validé :** changer le JSON change les tokens, catégories et feedbacks sans modifier le HTML. ✅ check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-146/
  renderer.html            ← moteur lab de tri (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` · `sort_lab_id` · `instruction` · `items[]{id,label,category_id}` · `categories[]{id,label,color_key}` · `feedback{in_progress,all_correct,partial}`

Optionnels : `title`, `hint`, `status_idle`, `status_idle_after`, `status_armed_prefix`, `primary_cta{label,action}`.

## Ce qui vient du JSON vs HTML
- **JSON** : chaque token (label + catégorie correcte), chaque zone de dépôt (id + label + couleur), les 3 messages de feedback (avec placeholders `{placed}`, `{good}`, `{total}`), le libellé du bouton CTA.
- **HTML** : moteur pattern B armé (sélection token → activation pulses → dépôt), grille responsive, styles DS V2, logique BLOCKED.

## Archétype — Pattern B armé
L'élève touche d'abord un **token** (il se surlève, les pulses s'activent sur les zones), puis touche une **catégorie**. Ce séquencement "arming" évite les faux drops sur mobile et rend l'intention explicite. L'activité est **exploratoire** : pas de scoring officiel, le feedback est progressif et non bloquant.

## Garde-fous (child_safety)
- **Anti-invention** : aucun contenu pédagogique généré. Tout le contenu provient du HTML source `INDEX-300-interactivelearning-GAB-146-150-PLAYABLE.html` (stage `data-tpl="146"`, handlers `slPick/slDrop/slFeedback`).
- **Pas de scoring officiel** : le lab ne donne pas de note. `feedback.partial` guide sans pénaliser.
- **BLOCKED** si `items` vide / `categories` vide / `feedback` absent / `instruction` absente.
- **Palette DS V2** : ombres colorées uniquement (`rgba(123,97,255,...)`, `rgba(85,56,217,...)`). Zéro `rgba(0,0,0,...)`.

## QA à vérifier
1. Modifier `items[].label` → rendu change sans toucher au HTML. ✓ critère d'or.
2. `items:[]` → BLOCKED propre avec message lisible.
3. `categories:[]` → BLOCKED propre.
4. Placer tous les tokens correctement → `feedback.all_correct` affiché.
5. Placer partiellement → `feedback.in_progress` avec compteur interpolé.
6. Placement partiel avec erreurs → `feedback.partial` avec `{good}/{total}`.
7. Responsive 375px → board en colonne, tokens wrap.

## Source
`INDEX-300-interactivelearning-GAB-146-150-PLAYABLE.html` (stage `data-tpl="146"`, fonctions JS `slPick`, `slDrop`, `slFeedback`, `slArmingOn`, `slArmingOff`).
