{
  "contract_version": "gab_096_contract_v1",
  "gab_id": "GAB-096",
  "canonical_name": "VisualMiniQuizPreview",
  "module_owner": "EdTechVisualLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "quiz_preview_id",
    "question",
    "choices"
  ],
  "optional_fields": [
    "title",
    "tag_label",
    "note",
    "cta_label",
    "accessibility",
    "child_safety"
  ],
  "field_types": {
    "question": "string — question posée à l'apprenant, non notée",
    "choices": "array<{id:string, text:string, correct:boolean}> — min 2 choix",
    "tag_label": "string — libellé du badge tag (ex: 'Aperçu · non noté')",
    "note": "string — note de bas de carte (ex: 'Juste pour vérifier — ce n'est pas noté.')",
    "cta_label": "string — libellé du bouton CTA",
    "accessibility": "object{keyboard_navigable,focus_visible,aria_label_card}",
    "child_safety": "object{content_level,no_scoring,note}"
  },
  "constraints": [
    "choices : min 2 éléments, exactement 1 correct:true obligatoire.",
    "Ce gabarit est NON noté — jamais utilisé pour une évaluation officielle.",
    "cta_label : libellé du bouton vient du JSON, jamais en dur dans le HTML.",
    "tag_label : affiché dans le badge visuel du mini-quiz, configurable par instance."
  ],
  "blocked_conditions": [
    "question absente",
    "choices insuffisants (moins de 2)",
    "quiz_preview_id absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria_label_card"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, question + choix affichés, 0 erreur" },
    { "case": "champ requis manquant (question absent)", "expected": "BLOCKED listant le champ" },
    { "case": "choices < 2", "expected": "BLOCKED — choices insuffisants" },
    { "case": "clic choix correct", "expected": "choix coloré en mint (ok), feedback positif" },
    { "case": "clic choix incorrect", "expected": "choix coloré en coral (ko), bonne réponse révélée en mint" },
    { "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-096",
    "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)."
  }
}
