{
  "contract_version": "gab_354_contract_v1",
  "gab_id": "GAB-354",
  "canonical_name": "MotivationLearningChallengeChoice",
  "module_owner": "EdTechMotivationLearning",
  "renderer_key": "choice_select",
  "required_fields": [
    "gab_id",
    "challenge_choice_id",
    "intro_label",
    "choices",
    "decline_label",
    "decline_feedback"
  ],
  "optional_fields": [
    "initial_state",
    "accessibility",
    "child_safety"
  ],
  "field_types": {
    "challenge_choice_id": "string — identifiant unique de cet écran de choix",
    "intro_label": "string — texte introductif affiché au-dessus des choix",
    "choices": "array<{key:enum['easy','mid','hard'], icon:string, label:string, color_token:string, feedback:string, is_recommended?:boolean}> — min 2, max 5",
    "decline_label": "string — libellé du bouton de refus",
    "decline_feedback": "string — message affiché si l'élève refuse le défi",
    "initial_state": "string — état initial du badge d'état (ex: 'recommended')",
    "accessibility": "object{keyboard_navigable:boolean, focus_visible:boolean, prefers_reduced_motion:boolean}",
    "child_safety": "object{right_to_decline:boolean, no_judgment_on_decline:boolean, partial_success_valued:boolean, reward_transparent:boolean}"
  },
  "constraints": [
    "choices doit contenir au moins 2 entrées.",
    "Chaque choice.key doit être unique dans le tableau.",
    "choice.feedback doit mentionner explicitement la récompense ou le risque (transparence).",
    "decline_label et decline_feedback sont obligatoires — le droit de refus est non négociable.",
    "child_safety.right_to_decline = true obligatoire : l'élève ne doit jamais être contraint.",
    "Aucune récompense ne doit être cachée (reward_transparent:true)."
  ],
  "blocked_conditions": [
    "choices absent ou vide",
    "decline_label absent",
    "decline_feedback absent",
    "intro_label absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria_role_listbox_or_group"
  ],
  "qa_cases": [
    { "case": "instance conforme (3 choix)", "expected": "rendu complet, 3 cartes cliquables, bouton decline visible" },
    { "case": "champ requis manquant (choices vide)", "expected": "BLOCKED mentionnant choices" },
    { "case": "decline_label absent", "expected": "BLOCKED mentionnant decline_label" },
    { "case": "clic sur un choix", "expected": "outline violet sur la carte, panel ok avec le feedback du choice" },
    { "case": "clic sur decline", "expected": "panel note avec decline_feedback, état 'declined'" },
    { "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, cartes empilées sur mobile" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-354",
    "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."
  }
}
