{
  "contract_version": "gab_048_contract_v1",
  "gab_id": "GAB-048",
  "canonical_name": "StoryProblemSituation",
  "module_owner": "EdTechStoryLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "situation_id",
    "scene_text",
    "question_text",
    "cta_label",
    "hint_text"
  ],
  "optional_fields": [
    "visual_emoji",
    "question_label",
    "cta_label_done"
  ],
  "field_types": {
    "situation_id": "string — identifiant unique de l'instance",
    "visual_emoji": "string — emoji illustrant la scène (affiché dans le visuel de la carte)",
    "scene_text": "string — texte narratif décrivant le contexte du problème",
    "question_label": "string — libellé au-dessus de la question (ex: 'La question qui crée le besoin')",
    "question_text": "string — question centrale qui crée le besoin d'apprendre",
    "cta_label": "string — libellé du bouton CTA avant clic",
    "cta_label_done": "string — libellé du bouton CTA après clic (état déclenché)",
    "hint_text": "string — indice révélé après clic sur le CTA"
  },
  "constraints": [
    "scene_text doit décrire un problème concret ancré dans un contexte narratif.",
    "question_text doit créer un besoin cognitif — pas une question de restitution.",
    "hint_text révèle le sens du besoin d'apprendre, pas la réponse à la notion.",
    "cta_label est le libellé structurel du bouton — vient du JSON, jamais en dur dans le HTML."
  ],
  "blocked_conditions": [
    "scene_text absent (BLOCKED)",
    "question_text absent (BLOCKED)",
    "cta_label absent (BLOCKED)",
    "hint_text absent (BLOCKED)"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "bouton désactivé visuellement après clic (opacity + pointerEvents)"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet : scène, question, CTA actif, hint caché" },
    { "case": "champ requis manquant", "expected": "BLOCKED listant le champ absent" },
    { "case": "clic CTA", "expected": "hint révélé, bouton désactivé, libellé passe à cta_label_done" },
    { "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-048",
    "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)."
  }
}
