{
  "contract_version": "gab_069_contract_v1",
  "gab_id": "GAB-069",
  "canonical_name": "StoryReadingSimpleMode",
  "module_owner": "EdTechStoryLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "reading_mode_id",
    "toggle_label",
    "text_normal",
    "text_simplified",
    "primary_cta"
  ],
  "optional_fields": [
    "tag_normal",
    "tag_simplified",
    "accessibility"
  ],
  "field_types": {
    "reading_mode_id": "string — identifiant unique de l'instance lecture",
    "toggle_label": "string — libellé du bouton bascule",
    "tag_normal": "string — étiquette mode normal (défaut : '📄 Version normale')",
    "tag_simplified": "string — étiquette mode simplifié (défaut : '✨ Version simplifiée')",
    "text_normal": "string — texte version normale (peut être dense/complexe)",
    "text_simplified": "string — texte version accessible (charge cognitive réduite)",
    "primary_cta": "object{label,action}",
    "accessibility": "object{aria_label_toggle_off, aria_label_toggle_on}"
  },
  "constraints": [
    "text_normal et text_simplified doivent traiter le même contenu pédagogique (même référent).",
    "text_simplified ne supprime pas le sens, il réduit la charge cognitive.",
    "primary_cta.label vient du JSON — jamais codé en dur dans le HTML.",
    "Le toggle est un bouton accessible (rôle button, aria-label dynamique)."
  ],
  "blocked_conditions": [
    "text_normal absent (BLOCKED)",
    "text_simplified absent (BLOCKED)",
    "primary_cta absent (BLOCKED)"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria_label_toggle_dynamique",
    "aria_pressed_state"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, toggle fonctionnel, 0 erreur" },
    { "case": "champ requis manquant (text_normal)", "expected": "BLOCKED listant le champ" },
    { "case": "champ requis manquant (text_simplified)", "expected": "BLOCKED listant le champ" },
    { "case": "champ requis manquant (primary_cta)", "expected": "BLOCKED listant le champ" },
    { "case": "instance externe injectée via init(ext)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "toggle activé", "expected": "tag + fond + texte basculent vers version simplifiée" },
    { "case": "toggle désactivé", "expected": "retour exact au texte normal + tag normal" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-069",
    "note": "Ce schema VALIDE l'instance. Le contrat pédagogique complet (input_contract/validation_logic/feedback_scoring_logic) vit dans le CORE-GAB officiel, pas ici (évite la duplication)."
  }
}
