{
  "contract_version": "gab_051_contract_v1",
  "gab_id": "GAB-051",
  "canonical_name": "StoryRevealMoment",
  "module_owner": "EdTechStoryLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "reveal_id",
    "curtain_cta",
    "reveal_label",
    "reveal_body",
    "highlight_word"
  ],
  "optional_fields": [
    "title",
    "curtain_icon",
    "replay_label",
    "accessibility",
    "child_safety"
  ],
  "field_types": {
    "reveal_id": "string — identifiant unique de l'instance",
    "curtain_cta": "string — libellé affiché sur le rideau, invite à cliquer",
    "curtain_icon": "string — emoji affiché au-dessus du libellé rideau (défaut '✨')",
    "reveal_label": "string — tag mono affiché au-dessus du texte révélé",
    "reveal_body": "string — texte complet de l'idée clé révélée",
    "highlight_word": "string — mot exact (sous-chaîne de reveal_body) mis en valeur en doré",
    "replay_label": "string — libellé du bouton 're-cacher' (défaut 'Re-cacher')",
    "accessibility": "object{aria_curtain_label:string, aria_replay_label:string}",
    "child_safety": "object{content_type:string, sensitive:boolean}"
  },
  "constraints": [
    "highlight_word doit être une sous-chaîne exacte de reveal_body — sinon aucun mot ne s'affiche en doré.",
    "reveal_body ne doit pas dépasser ~200 caractères pour rester lisible sur mobile.",
    "curtain_cta court (< 60 chars) — s'affiche en une ligne sur le rideau.",
    "Le HTML (layout, animation particules, couleurs) ne change pas entre instances."
  ],
  "blocked_conditions": [
    "reveal_body absent (BLOCKED)",
    "highlight_word absent (BLOCKED)",
    "curtain_cta absent (BLOCKED)",
    "reveal_label absent (BLOCKED)",
    "reveal_id absent (BLOCKED)"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria-label sur rideau et bouton replay"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rideau affiché, tap → lift + particules + reveal, Re-cacher reset" },
    { "case": "champ requis manquant (ex: reveal_body absent)", "expected": "BLOCKED listé dans le panneau d'erreur" },
    { "case": "highlight_word absent", "expected": "BLOCKED — aucun mot doré" },
    { "case": "instance externe injectée via init(ext)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal, reveal_body lisible" },
    { "case": "prefers-reduced-motion actif", "expected": "animations réduites, rideau saute sans transition longue" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-051",
    "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)."
  }
}
