# GAB-321 · ResearchLearningIntro — « Intro de recherche »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechResearchLearning
**Critère validé :** changer le JSON change l'intro sans modifier le HTML. ✅ check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-321/
  renderer.html            ← moteur intro de recherche (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` · `research_intro_id` · `doc_kind` · `doc_title` · `doc_body` · `primary_cta{label,action}` · `contract_items[]{icon,label,detail}`

Optionnels : `secondary_cta{label,action}`, `contract_success_message`, `anti_plagiarism_message`.

## Ce qui vient du JSON vs HTML
- **JSON** : sujet (doc_title), catégorie (doc_kind), corps (doc_body), libellé des boutons, items du contrat, messages de feedback.
- **HTML** : layout doc-paper, animation apparition contrat, boutons structurels, panneaux ok/warn, layout.

## Garde-fous (child_safety)
- **BLOCKED** si `contract_items` vide/absent, `primary_cta` absent, ou `research_intro_id` absent.
- **Anti-plagiarism_message** : affiché uniquement sur clic secondary_cta, jamais en dur.
- **contract_success_message** : affiché en panel ok après activation du contrat.
- Le bouton secondary_cta est masqué si non fourni dans l'instance.

## QA à vérifier
1. Modifier `doc_title`/`contract_items` → rendu change sans toucher au HTML (critère d'or).
2. `contract_items:[]` → BLOCKED propre.
3. `primary_cta` absent → BLOCKED propre.
4. Clic primary_cta → items s'animent + panel ok + bouton désactivé.
5. Clic secondary_cta → panel warn anti-plagiat.
6. Responsive 375/768/1024 — aucun débordement.

## Source
`INDEX-300-researchlearning-GAB-321-325-PLAYABLE.html` (stage `data-tpl="321"`, handlers `d321Start`, `d321Plagiat`).
