# GAB-228 · SmartSelectAccessibilityFit — « A11y fit non-stigmatisant »

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

## Pack (structure officielle par-GAB)
```
GAB-228/
  renderer.html            ← moteur sélecteur A11y (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` · `accessibility_fit_id` · `title` · `subtitle` · `privacy_notice` · `default_fit_key` · `fits[]{key,icon,label,description,impact}` · `primary_cta{label,action}`

Optionnels : `impact_header`, `secondary_cta{label,action}`, `fallback_text_summary`.

## Ce qui vient du JSON vs HTML
- **JSON** : titre, sous-titre, notice privacy, 7 options A11y (icône/label/description/impact), clé par défaut, libellés des CTA, action.
- **HTML** : grille 2 colonnes, zone impact, bandeau privacy, boutons CTA, slots panel, layout responsive.

## Garde-fous (child_safety / non-stigmatisation)
- **Doctrine privacy A11y** : `privacy_notice` est un champ **requis**. SmartSelect ne stocke aucune donnée médicale — préférences UI uniquement. Jamais de profilage santé.
- **Non-stigmatisation** : les labels d'options A11y sont formulés en termes de préférences d'usage, pas de diagnostics médicaux.
- **BLOCKED** si `fits` vide/absent · `accessibility_fit_id` absent · `primary_cta` absent.
- L'impact de chaque fit peut contenir du HTML limité (`<b>`), jamais de scripts injectés.

## QA à vérifier
1. Modifier un `impact` dans `fits[]` → texte impact mis à jour sans toucher au HTML (critère d'or).
2. `fits:[]` → BLOCKED propre.
3. Clic sur un fit → sélection visuelle + chip mis à jour + impact texte depuis JSON.
4. `default_fit_key` : le bon fit est pré-sélectionné au chargement.
5. CTA primaire → panel action. CTA secondaire → panel confirm.
6. Responsive 375/768/1024 : grille 1 col mobile, 2 col desktop.
7. Instance externe injectée via `ENGINE.init(ext)` → rendu change sans modifier HTML.

## Source
`INDEX-300-smartselect-GAB-226-230-PLAYABLE.html` (stage `data-tpl="228"`, handler `afPick`, objet `AF_FITS`).
