# GAB-269 · ComprehensionLearningConceptBridge — « Carte mentale visuelle »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechComprehensionLearning
**Critère validé :** changer le JSON change la carte sans modifier le HTML. check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-269/
  renderer.html            ← moteur carte mentale (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` · `mindmap_id` · `title` · `summary` · `center_node` · `branches[]{id,label}`

Optionnels : `map_layout`, `reason_title`, `reason_body`, `primary_cta{label,action}`, `secondary_cta{label,action}`, `icon`, `leaves`.

## Ce qui vient du JSON vs HTML
- **JSON** : titre, nœud central, labels des 4 branches, raison pédagogique, libellés des boutons CTA.
- **HTML** : canvas SVG/div radial, positionnement des noeuds (b1..b4), lignes de connexion, layout responsive.

## Garde-fous (child_safety)
- **Anti-invention** : les branches et le nœud central viennent exclusivement de l'instance — jamais générés par le moteur.
- **BLOCKED** si `branches` vide / `center_node` absent / `title` absent.
- `map_layout` est un enum à 4 valeurs ; si absent, la valeur par défaut `radial_4branch` est utilisée.
- Pas de contenu pédagogique en dur dans le HTML.

## QA à vérifier
1. Modifier `center_node` + `branches[].label` → rendu change sans toucher au HTML (critère d'or).
2. `branches:[]` → BLOCKED propre avec message explicite.
3. `center_node` absent → BLOCKED listant le champ.
4. Instance externe injectée via `ENGINE.init(ext)` → rendu complet.
5. Responsive 375/768/1024 — canvas carte mentale sans débordement.

## Source
`INDEX-300-comprehensionlearning-GAB-266-270-PLAYABLE.html` (stage `data-tpl="269"`, handlers `mmPick`).
