{
  "contract_version": "gab_102_contract_v1",
  "gab_id": "GAB-102",
  "canonical_name": "MemoryFlashcardReverse",
  "module_owner": "EdTechMemoryLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "flashcard_id",
    "front_text",
    "back_text"
  ],
  "optional_fields": [
    "title",
    "front_label",
    "front_hint",
    "back_label",
    "back_hint",
    "btn_again_label",
    "btn_know_label"
  ],
  "field_types": {
    "flashcard_id": "string — identifiant unique de la carte",
    "front_text": "string — texte affiché au recto (réponse d'origine, sens inversé)",
    "front_label": "string — libellé de face recto (ex : 'Sens inverse · Réponse')",
    "front_hint": "string — texte d'invite au bas du recto (ex : '→ quelle date ? touche')",
    "back_text": "string — texte affiché au verso (question d'origine retrouvée)",
    "back_label": "string — libellé de face verso (ex : 'Question d'origine')",
    "back_hint": "string — texte d'invite au bas du verso",
    "btn_again_label": "string — libellé bouton 'à revoir'",
    "btn_know_label": "string — libellé bouton 'je sais'"
  },
  "constraints": [
    "front_text contient la RÉPONSE d'origine (sens inversé) — pas la question.",
    "back_text contient la QUESTION d'origine — ce que l'élève doit retrouver.",
    "La distinction recto=réponse / verso=question est la règle de cet archétype (différent de GAB-101).",
    "btn_again_label et btn_know_label sont purement libellés — le comportement (flip reset) est câblé dans le moteur."
  ],
  "blocked_conditions": [
    "front_text absent ou vide",
    "back_text absent ou vide",
    "flashcard_id absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria-label sur la carte (flipable au clavier)"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, carte retournable, 0 erreur" },
    { "case": "front_text absent", "expected": "BLOCKED listant le champ manquant" },
    { "case": "back_text absent", "expected": "BLOCKED listant le champ manquant" },
    { "case": "instance externe injectée via init(ext)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "clic / touche Entrée sur la carte", "expected": "flip 3D recto→verso puis verso→recto" },
    { "case": "bouton 'À revoir'", "expected": "remet la carte côté recto" },
    { "case": "bouton 'Je sais'", "expected": "remet la carte côté recto" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-102",
    "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)."
  }
}
