# GAB-012 · SessionEmptyState — « Session vide ou mal configurée »

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

## Pack (structure officielle par-GAB)
```
GAB-012/
  renderer.html            ← moteur état vide (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
```

## Archétype
`SessionEmptyState` est un écran d'état informatif affiché quand une session PlayEngine ne contient
aucun contenu configurable ou est en cours de préparation. Il évite le spinner infini : l'apprenant
sait exactement où il en est et peut agir via les CTAs.

## Champs requis (instance, à plat)
`gab_id` · `session_empty_id` · `title` · `body` · `primary_cta{label,action}`

Optionnels : `icon`, `subtitle`, `secondary_cta{label,action}`, `feedback_text`.

## Ce qui vient du JSON vs HTML
- **JSON** : icône, titre, sous-titre, corps de texte, libellé et action des deux CTAs, texte feedback post-clic.
- **HTML** : layout centré, zone icône, zone actions, logique BLOCKED, slots panel, footer.

## Garde-fous (child_safety)
- **BLOCKED** si `title`, `body` ou `primary_cta` absents : le moteur affiche un panel d'erreur rouge et masque le rendu partiel.
- **Pas de spinner infini** : l'état vide est toujours un état terminal ou temporaire connu — ne pas mélanger avec un état de chargement (→ GAB-001).
- **secondary_cta optionnel** : si absent du JSON, seul le bouton primaire est rendu, sans erreur.

## QA à vérifier
1. Modifier `title`/`body`/`primary_cta.label` → rendu change sans toucher au HTML.
2. `primary_cta` absent → BLOCKED propre, aucun bouton rendu.
3. `secondary_cta` absent → un seul bouton visible, pas d'erreur.
4. Clic sur CTA primaire → `feedback_text` affiché.
5. Responsive 375/768/1024 — boutons empilés sur mobile.

## Quand utiliser / ne pas utiliser
| ✅ use_when | ⛔ do_not_use_when |
|---|---|
| Session sans contenu configuré | Chargement en cours (→ GAB-001) |
| Brouillon non publié | Erreur provider (→ GAB-011) |
| Éviter le spinner infini | Accès verrouillé (→ GAB-010) |

## external_refs / dependencies
Ce GAB fait partie du lot `LOT-playengine-GAB-011-015`. Les GAB voisins référencés dans les
`do_not_use_when` sont :
- **GAB-001** : état de chargement (spinner)
- **GAB-010** : accès verrouillé
- **GAB-011** : erreur provider (SessionProviderErrorBoundary)

Ces GABs sont dans le même lot ou dans des lots PlayEngine antérieurs. Pas de dépendance directe
à un module externe.

## Source
`INDEX-300-playengine-GAB-011-015-PLAYABLE.html` (stage `data-tpl="12"`, handler `emptyAction()`).
