# GAB-289 · WritingLearningToneAndRegister — « Ton et registre »

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

## Pack (structure officielle par-GAB)
```
GAB-289/
  renderer.html            ← moteur ton & registre (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` · `tone_register_id` · `text_ref` · `target_audience` · `expected_register` · `register_criteria`

Optionnels : `title`, `subtitle`, `register_options`, `bad_fit_examples[]{original,tag}`,
`rewrite_suggestions[]{from,to}`, `preserve_voice_policy`, `reason_why`,
`primary_cta{label,reveal}`, `secondary_cta{label,reveal}`, `use_when`, `do_not_use_when`.

## Ce qui vient du JSON vs HTML
- **JSON** : audience cible, registre attendu, libellés de la barre de registre, exemples d'écarts, reformulations, politique preserve_voice, libellé des boutons CTA.
- **HTML** : layout audience-block, barre de registre, zones detect/suggest/preserve/reason, boutons structurels, fallback BLOCKED.

## Archétype
GAB-289 est un gabarit **audience-matching + preserve_voice** : il identifie l'audience cible, active le registre attendu dans une barre de sélection, expose les écarts détectés (bad_fit_examples), propose des reformulations (rewrite_suggestions), et rappelle la règle de préservation de la voix de l'auteur. Aucun élément pédagogique n'est codé en dur dans le HTML.

## Garde-fous (child_safety)
- **Anti-invention** : tout contenu pédagogique vient de l'instance JSON. Si un champ est absent dans la source, il porte `_TODO` dans l'instance ; le HTML masque la zone silencieusement.
- **BLOCKED** si `tone_register_id`, `target_audience`, `expected_register` ou `register_criteria` sont absents.
- **Preserve voice** : `preserve_voice_policy` est extrait verbatim de la source ; jamais remplacé par un message générique.
- **Registre** : `expected_register` pilote l'état actif de la barre — le moteur normalise pour comparer sans distinction de casse/accent.

## QA à vérifier
1. Modifier `target_audience` → affichage audience-block change sans toucher au HTML (critère d'or).
2. Champ requis absent (ex : `expected_register`) → BLOCKED propre, pas de crash JS.
3. `bad_fit_examples:[]` → zone écarts masquée, pas d'erreur.
4. `rewrite_suggestions` absent → zone suggestions masquée silencieusement.
5. Bouton secondaire → texte `reveal` affiché dans le panel.
6. Responsive 375/768/1024 : barre de registre lisible, pas de débordement horizontal.

## Source
`INDEX-300-writinglearning-GAB-286-290-PLAYABLE.html` (stage `data-tpl="289"`, section `<!-- ═══════════ GAB-289 TONEANDREGISTER ═══════════ -->`).

## Chaîne Writing vague 2
GAB-286 Evidence → GAB-287 Transition → GAB-288 Rewrite → **GAB-289 Tone** → GAB-290 FinalReview
