{
  "contract_version": "gab_018_contract_v1",
  "gab_id": "GAB-018",
  "canonical_name": "SessionNavigationControls",
  "module_owner": "EdTechPlayEngine",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "nav_id",
    "context_step_label",
    "context_module_label",
    "continue_cta"
  ],
  "optional_fields": [
    "back_cta",
    "retry_cta",
    "skip_cta",
    "quit_cta",
    "nav_note"
  ],
  "field_types": {
    "context_step_label": "string — ex: 'Étape 3 / 7 — Quiz de validation'",
    "context_module_label": "string — ex: 'ExerciseLearning · étape optionnelle'",
    "continue_cta": "object{label,icon,enabled:boolean,feedback}",
    "back_cta": "object{label,icon,enabled:boolean,feedback}",
    "retry_cta": "object{label,icon,enabled:boolean,feedback}",
    "skip_cta": "object{label,icon,enabled:boolean,feedback}",
    "quit_cta": "object{label,enabled:boolean,feedback}",
    "nav_note": "string — note contextuelle affichée sous la barre"
  },
  "constraints": [
    "continue_cta est le seul bouton obligatoire (primary CTA de la barre).",
    "Boutons optionnels (back/retry/skip/quit) : si absent du JSON, le bouton n'est pas rendu.",
    "enabled:false masque le bouton sans casser le layout.",
    "feedback : texte affiché dans la zone de sortie au clic — jamais en dur dans le HTML.",
    "skip_cta : doit être absent ou enabled:false si l'étape n'est pas optionnelle.",
    "retry_cta : doit être absent ou enabled:false avant toute tentative.",
    "quit_cta : déclenche GAB-016 dans un flow réel ; ici rendu comme texte de feedback."
  ],
  "blocked_conditions": [
    "continue_cta absent",
    "context_step_label absent",
    "context_module_label absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria-labels sur les boutons icône seul (quit)"
  ],
  "qa_cases": [
    { "case": "instance conforme complète", "expected": "5 boutons rendus, feedback au clic" },
    { "case": "champ requis manquant (continue_cta)", "expected": "BLOCKED listant le champ" },
    { "case": "skip_cta absent", "expected": "bouton 'Passer' non rendu, les autres intacts" },
    { "case": "retry_cta enabled:false", "expected": "bouton masqué sans décalage layout" },
    { "case": "instance externe injectée via init(ext)", "expected": "rendu change sans modifier le HTML" },
    { "case": "responsive 375px", "expected": "barre en colonne, aucun débordement horizontal" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-018",
    "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).",
    "external_refs": {
      "dependencies": [
        "GAB-016 (SessionExitConfirm) — déclenché par quit_cta dans un flow réel",
        "GAB-017 (SessionSkipStepConfirm) — déclenché par skip_cta dans un flow réel"
      ]
    }
  }
}
