# GAB-207 · PlayEngineOptionalBranch — « Branche optionnelle in-session »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechPlayEngine
**Critère validé :** changer le JSON change le rendu sans modifier le HTML.

## Pack (structure officielle par-GAB)
```
GAB-207/
  renderer.html            ← moteur branche optionnelle (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` · `optional_branch_id` · `title` · `branches[]{branch_id, tag_label, tag_icon, title, description, duration_label, module_chip, module_icon, cta_label}` · `primary_cta{label_default, action}`

Optionnels : `subtitle`, `context_note`, `prerequisite_note`, `skip_cta{label,action}`, `skip_feedback`, `accessibility`, `child_safety`.

## Ce qui vient du JSON vs HTML
- **JSON** : titre, sous-titre, note contextuelle, contenu de chaque branche (tag, titre, description, durée, module), note prérequis, libellés des CTAs.
- **HTML** : layout de la carte, grille 2 branches, état disabled/enabled du CTA principal, fallback BLOCKED, slots panel.

## Logique moteur
1. Au chargement : CTA principal `disabled` jusqu'à sélection d'une branche.
2. Sélection branche → highlight `.selected` + `::after` checkmark + CTA activé avec `cta_label` de la branche.
3. Clic CTA principal → feedback `.panel.ok` avec branche confirmée.
4. Clic skip → feedback `.panel.skip` avec `skip_feedback`.
5. BLOCKED si `branches` absent/vide/< 2 items, `optional_branch_id` absent, `primary_cta` absent.

## Garde-fous (child_safety)
- **Validité pédagogique** : les 2 branches doivent être valides (pas de notion sautée). Le champ `prerequisite_note` documente cette garantie.
- **Retour flux garanti** : après n'importe quel choix, l'élève revient au flux principal.
- **Anti-invention** : contenu extrait uniquement du HTML source. Aucun champ inventé.
- **BLOCKED** si `branches` vide, `optional_branch_id` absent, `primary_cta` absent.

## QA à vérifier
1. Modifier `title`/`branches[].title` → rendu change sans toucher au HTML (critère d'or).
2. `branches:[]` → BLOCKED propre.
3. Sélection branche → CTA activé avec bon `cta_label`.
4. Clic skip → message `skip_feedback`.
5. Responsive 375/768/1024 — grid branches passe en 1 colonne < 560px.

## external_refs / dependencies
- **GAB-197 PathMapAlternativeRoute** : alternative de CARTE (hors session). NE PAS confondre avec GAB-207 qui vit IN-SESSION (PlayEngine garde l'état).
- **LOT** : `LOT-playengine-composite-GAB-206-210` (même lot que GAB-206, GAB-208, GAB-209, GAB-210).

## Source
`INDEX-300-playengine-composite-GAB-206-210-PLAYABLE.html` (stage `data-tpl="207"`, handler `obPick`).
