# GAB-140 · InteractiveSliderExperiment — « Expérience à curseur »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechInteractiveLearning
**Critère validé :** changer le JSON change l'expérience (question, variable, loi) sans modifier le HTML. ✅ check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-140/
  renderer.html            ← moteur expérience à curseur (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` · `experiment_id` · `question` · `variable{label,unit,min,max,default}` · `output{label,unit,formula_type}`
Optionnels : `title`, `instruction`, `primary_cta{label,action}`.

## Ce qui vient du JSON vs HTML
- **JSON** : question pédagogique, label/unité/bornes/défaut du curseur, label de sortie, formule (`formula_type`), libellé du bouton.
- **HTML** : curseur `<input type=range>`, barre de sortie, layout, logique de calcul (`inverse_square` / `linear` / `quadratic`), fallback BLOCKED.

## Logique de calcul (`formula_type`)
| Valeur | Formule appliquée | Cas d'usage |
|---|---|---|
| `inverse_square` | `round(100 / d²)` (normalisé max 100% pour d=1) | Loi en 1/d² (intensité lumineuse) |
| `linear` | `round(d * 10)` | Loi linéaire simple |
| `quadratic` | `round(d²)` | Loi quadratique croissante |

La source hardcodée utilisait `inverse_square` pour illustrer la variation d'intensité d'une lampe avec la distance (∝ 1/d²).

## Garde-fous (child_safety)
- **Anti-contenu-dur** : aucune question, unité ou texte pédagogique dans le HTML.
- **Bornes curseur** : `variable.min/max/default` pilotent l'attribut HTML `min/max/value` — aucune borne en dur.
- **BLOCKED** si `question` absent / `variable` absent / `output` absent.
- **Formule inconnue** : fallback sur `inverse_square` (comportement sûr).

## QA à vérifier
1. Modifier `question` → rendu change sans toucher au HTML (critère d'or).
2. `question:""` absent → BLOCKED propre.
3. `variable` absent → BLOCKED propre.
4. Curseur à `d=1` → intensité 100% (inverse_square).
5. Curseur à `d=10` → intensité 1% (inverse_square).
6. Inject instance externe via `ENGINE.init(ext)` → rendu se met à jour.
7. Responsive 375/768/1024 — aucun débordement.

## Source
`INDEX-300-interactivelearning-GAB-136-140-PLAYABLE.html` (stage `data-tpl="140"`, handler `seUpdate(v)`, styles `.se-*`).
