# GAB-389 · MediaLearningMediaAnnotation — « Annoter un média »

**Archétype / renderer_key :** `annotation_media` (cartographie) · **module :** EdTechMediaLearning
**Critère validé :** changer le JSON change les couches, zones et annotations sans modifier le HTML. ✅ check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-389/
  renderer.html            ← moteur annotation média (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` · `annotation_id` · `media_scene{alt,background_hint?}` · `layers[]{layer_id,label,icon?,message_on,message_off}` · `anchors[]{anchor_id,layer_id,annotation_text,position{top?,left?,right?,bottom?,width,height}}` · `text_fallback`

Optionnels : `title`, `accessibility`, `child_safety`.

## Ce qui vient du JSON vs HTML
- **JSON** : toutes les couches activables, leurs messages on/off, chaque zone ancrée et son texte d'annotation, le texte de fallback accessible, le titre.
- **HTML** : moteur toggleLayer/clickAnchor, layout scene, boutons chips, rendu panel, accessibilité clavier.

## Archétype pédagogique
Annotation média à couches contrôlées. L'apprenant active/désactive des couches (ex : villes, géographie) qui révèlent des zones ancrées précises sur un média. Cliquer une zone affiche l'annotation correspondante. Le fallback texte garantit l'accessibilité sans visuel.

## Garde-fous (child_safety)
- **Édition contrôlée** : aucune zone clickable sans activation de la couche parente — pas d'édition libre.
- **Fallback texte obligatoire** : `text_fallback` est un champ requis, jamais optionnel.
- **Anti-invention** : seul le contenu extrait du HTML source est présent. Aucun contenu pédagogique inventé.
- **BLOCKED** si `layers` vide / `anchors` vide / `text_fallback` absent / `media_scene` absent.

## QA à vérifier
1. Modifier `annotation_text` dans un anchor → rendu change sans toucher au HTML.
2. `layers:[]` → BLOCKED propre.
3. `anchors:[]` → BLOCKED propre.
4. `text_fallback` absent → BLOCKED propre.
5. Activer une couche → zone correspondante apparaît, message_on affiché.
6. Désactiver → zone masquée, message_off affiché.
7. Cliquer zone → annotation_text affiché, zone marquée found.
8. Bouton fallback → text_fallback affiché.
9. Navigation clavier sur zones ancrées (Enter/Space).
10. Responsive 375/768/1024.

## external_refs / dependencies
- **do_not_use_when** : asset généré IA sans validation → GAB-388. Annotation sans ancrage précis → préférer un autre gabarit. Édition non contrôlée → hors scope.
- **use_when** : annoter un média avec ancrage précis, activer/désactiver des couches, fournir un fallback texte accessible.

## Source
`INDEX-300-medialearning-GAB-386-390-PLAYABLE.html` (stage `data-tpl="389"`, handlers `d389Layer`, `d389Click`, `d389Text`).
