# GAB-105 · MemoryMatchingPairs — « Association de paires »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechMemoryLearning
**Critère validé :** changer le JSON change les colonnes, libellés et paires sans modifier le HTML. check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-105/
  renderer.html            ← moteur association de paires (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` · `matching_id` · `items[]{pair_id, left, right}` · `col_left_label` · `col_right_label`

Optionnels : `title`, `instructions`, `status_idle`, `feedback_success`, `accessibility{keyboard_navigable, focus_visible, prefers_reduced_motion}`.

## Ce qui vient du JSON vs HTML
- **JSON** : libellés des colonnes, texte de chaque item gauche/droite, consigne, message de statut, feedback de succès.
- **HTML** : grille 2 colonnes, animations (sélection/matched/shake), logique d'appariement (pair_id), layout, fallback BLOCKED.

## Archétype — comment ça marche
Le moteur charge `items[]`, place la colonne gauche dans l'ordre naturel et **mélange** la colonne droite (shuffle). L'utilisateur clique un item gauche (sélection + armement de la colonne droite), puis un item droit. Si `L.pair_id === R.pair_id` → `matched`. Sinon → animation shake. Quand `done === items.length` → affiche `feedback_success`.

## Garde-fous
- **BLOCKED** si `items` absent/vide, `col_left_label` absent, `col_right_label` absent.
- Aucun contenu pédagogique en dur dans le HTML.
- Palette DS V2 : violet (#7B61FF) signature EdTechMemoryLearning. Aucune ombre `rgba(0,0,0,...)`.
- Un seul bloc `<script>` sans attribut.

## QA à vérifier
1. Modifier un `left`/`right` → rendu change sans toucher au HTML (critère d'or).
2. `items:[]` → BLOCKED propre.
3. `col_left_label` absent → BLOCKED propre.
4. Mauvaise paire → shake + reset sélection.
5. Toutes paires trouvées → `feedback_success` affiché.
6. `init(ext)` avec instance externe → rendu change.
7. Responsive 375/768/1024 : aucun débordement.

## Source
`INDEX-300-memorylearning-GAB-101-105-PLAYABLE.html` — stage `data-tpl="105"`, handlers `matPick` / `matArmingOn` / `matArmingOff`.

## external_refs / dependencies
Aucune dépendance externe. Polices Google Fonts (Nunito, DM Sans, JetBrains Mono) optionnelles — le renderer fonctionne avec les fonts système si non chargées.
