{
  "contract_version": "gab_113_contract_v1",
  "gab_id": "GAB-113",
  "canonical_name": "MemoryHintReveal",
  "module_owner": "EdTechMemoryLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "hint_card_id",
    "question",
    "hints",
    "answer"
  ],
  "optional_fields": [
    "cta_hint_label",
    "cta_next_hint_label",
    "cta_reveal_label"
  ],
  "field_types": {
    "hint_card_id": "string — identifiant unique de la carte indice",
    "question": "string — question posée à l'élève",
    "hints": "array<{index:number, text:string}> — indices révélés progressivement, au moins 1",
    "answer": "string — réponse finale révélée après tous les indices",
    "cta_hint_label": "string — libellé du bouton CTA au premier clic",
    "cta_next_hint_label": "string — libellé du bouton CTA pour les indices suivants",
    "cta_reveal_label": "string — libellé du bouton CTA avant révélation de la réponse"
  },
  "constraints": [
    "hints doit contenir au moins 1 entrée sinon BLOCKED.",
    "Les indices sont révélés dans l'ordre croissant de leur champ index.",
    "La réponse (answer) n'est affichée qu'après que tous les indices aient été révélés.",
    "Les libellés CTA (cta_hint_label, cta_next_hint_label, cta_reveal_label) sont optionnels ; si absents le moteur utilise des valeurs par défaut."
  ],
  "blocked_conditions": [
    "hints absent ou vide",
    "question absente",
    "answer absente"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria_live_region_for_hint_reveal"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet : question affichée, bouton CTA visible, 0 indice affiché" },
    { "case": "clic 1 sur CTA", "expected": "indice 1 révélé, libellé bouton change" },
    { "case": "clic 2 sur CTA", "expected": "indice 2 révélé, libellé bouton change vers révélation" },
    { "case": "clic final sur CTA", "expected": "réponse révélée, bouton masqué" },
    { "case": "hints vide", "expected": "BLOCKED listé clairement" },
    { "case": "question absente", "expected": "BLOCKED listé clairement" },
    { "case": "answer absente", "expected": "BLOCKED listé clairement" },
    { "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" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-113",
    "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). Source HTML : INDEX-300-memorylearning-GAB-111-115-PLAYABLE.html stage data-tpl=113, handlers hntNext()."
  }
}
