{
  "options": {
    "title": "Enquête au laboratoire",
    "identifier": "activity_1778796923419",
    "version": "1.2",
    "description": "Mise en situation :\nUne expérience cruciale a été sabotée hier soir. La direction a besoin de toi pour identifier le coupable avant que la police n'arrive.\nTes objectifs :\nAnalyser les 3 indices trouvés sur la scène (Solide, Liquide, Gaz).\nCommander des tests au laboratoire (Masse, Volume, Tests de flamme...).\nUtiliser tes connaissances scientifiques pour identifier chaque substance.\nDésigner le coupable parmi les 3 suspects en fonction des produits qu'ils utilisent. >>>\n\nLes noms à afficher sont:\n-M. Ferland\n- Mme. Lachance\n- Dr. Oxid\n\nCahier de charges :\nTu dois créer un jeu interactif (jeu dont vous êtes le héros) à l'attention d'un élève de troisième secondaire qui vit au Québec et qui a 14 ans. Le jeu consiste à trouver le coupable d'un crime à l'aide de trois indices trouvés sur les lieux : un solide, un liquide et un gaz.\n\nTu dois créer une mise en situation et faire en sorte que l'élève puisse utiliser ses connaissances afin de résoudre le crime. Les substances retrouvées sur le lieu du crime doivent correspondre aux substances fréquemment utilisées au laboratoire à l'école. L'élève doit être amené à faire des choix et à définir les analyses à envoyer au laboratoire. Il doit analyser le rapport du labo, interpréter correctement les réactions et utiliser des documents de référence. Si ses choix ne sont pas bons, il ne pourra pas identifier le coupable et devra pouvoir revenir en arrière et demander de nouvelles analyses.\n\nIl est possible que le dihydrogène explose en présence du tison. Il ne faut pas offrir ce choix dans cette situation.\n\nAu chargement, crée des scénarios aléatoires (substances trouvées sur les lieux) et varie les quantités mesurées afin de pouvoir recommencer avec une nouvelle mise en situation.\n\nL'élève doit tirer une conclusion qui va lui permettre d'établir hors de tout doute l'identité du coupable. Crée des représentations svg lorsque c'est possible.\n\nConnaissances : \nLes élèves de troisième secondaire doivent interpréter correctement les réactions à l'aide des indicateurs. Ils doivent être en mesure d'identifier un substance à l'aide de ses propriétés physiques et chimiques caractéristiques.\n\nPropriétés chimiques caractéristiques utiisées en troisième secondaire.\na. Le dioxygène ravive le tison\nb. Le dioxyde de carbone éteint la flamme\nc. Le dihydrogène explose en présence de la flamme\n\n\nPropriétés physiques caractéristiques\na. Point de fusion\ni. Identifier une substance par son point de fusion à l’aide d’un document de\nréférence\nb. Point d’ébullition\ni. Identifier une substance par son point d’ébullition à l’aide d’un document de\nréférence\nc. Masse volumique\ni. Expliquer le concept de masse volumique\nii. Déterminer la masse volumique de différentes substances\niii. Identifier des substances liquides et solides par leur masse volumique à l’aide\nd’un document de référence.\n\n\nLes substances suggérées :\n\nGazs\n- dioxygène\n- dioxyde de carbone\n- dihydrogène\n\nSolides métalliques (recouverts de peinture afin de ne pas les reconnaitre)\n- fer\n- cuivre\n- aluminium\n\nLiquides\n- eau\n- alcool\n- glycérine\n- glycol\n- huile d'olive",
    "passingScore": false,
    "passingScoreValue": 80,
    "completionTracking": true,
    "activityInstruction": "Tu dois trouver le coupable d'un crime à l'aide de trois indices trouvés sur les lieux : un solide, un liquide et un gaz !",
    "allowMultipleAttempts": false,
    "maxAttempts": 3,
    "provideFeedback": false,
    "provideCorrectAnswer": true,
    "showFinalResult": true,
    "moodleOptimization": true,
    "embedOptimization": false,
    "activityType": "scorm",
    "predefinedType": "libre",
    "feedbackPrompt": "Rôle : Tu es un enseignant expert en pédagogie explicite. Ta mission est de guider un élève à travers un problème complexe en utilisant la technique du \"haut-parleur sur la pensée\" (think-aloud modeling).\n\nStructure de ta réponse :\nPour chaque étape de résolution, tu dois impérativement diviser ta réponse en deux sections distinctes :\n\n📢 LE HAUT-PARLEUR (Pensée interne) : Explicite ton raisonnement métacognitif en italique. Dis ce que tu vois, les pièges que tu identifies, et pourquoi tu choisis cette stratégie précise.\n\n✅ ACTION CONSEILLÉE :\nDonne une instruction claire, concise et directe sur la prochaine étape technique à réaliser.\n\nConsignes de style :\nSois très concis.\nUtilise un ton encourageant mais rigoureux.\nAvance une seule étape à la fois."
  },
  "htmlCode": "<!doctype html>\n<html lang=\"fr\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Enquête au laboratoire</title>\n  <script src=\"https://cdn.tailwindcss.com/3.4.17\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/lucide@0.263.0/dist/umd/lucide.min.js\"></script>\n  <link href=\"https://fonts.googleapis.com/css2?family=Bitter:wght@400;700&family=Source+Sans+3:wght@400;600;700&display=swap\" rel=\"stylesheet\">\n  <style>\n    :root {\n      --bg: #1a1a2e;\n      --surface: #16213e;\n      --card: #0f3460;\n      --accent: #e94560;\n      --accent2: #f5a623;\n      --text: #e8e8e8;\n      --text-muted: #a0a0b0;\n    }\n    * { box-sizing: border-box; }\n    html, body {\n      height: auto;\n      overflow: hidden;\n      margin: 0;\n      font-family: 'Source Sans 3', sans-serif;\n      background: var(--bg);\n      color: var(--text);\n    }\n    h1, h2, h3 { font-family: 'Bitter', serif; }\n    .game-container { height: auto; min-height: auto; overflow-y: auto; width: 100%; padding: 20px; }\n    .card { background: var(--surface); border: 1px solid rgba(233,69,96,0.2); border-radius: 12px; padding: 1.5rem; margin-bottom: 1rem; }\n    .btn-primary { background: var(--accent); color: #fff; padding: 0.7rem 1.5rem; border-radius: 8px; border: none; cursor: pointer; font-weight: 600; font-size: 1rem; transition: all 0.2s; }\n    .btn-primary:hover { background: #c73a52; transform: translateY(-1px); }\n    .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }\n    .btn-secondary { background: var(--card); color: var(--text); padding: 0.6rem 1.2rem; border-radius: 8px; border: 1px solid rgba(233,69,96,0.3); cursor: pointer; font-size: 0.95rem; transition: all 0.2s; }\n    .btn-secondary:hover { border-color: var(--accent); background: rgba(233,69,96,0.1); }\n    .btn-secondary.selected { border-color: var(--accent); background: rgba(233,69,96,0.2); box-shadow: 0 0 8px rgba(233,69,96,0.3); }\n    .suspect-card { background: var(--card); border-radius: 12px; padding: 1.2rem; border: 2px solid transparent; cursor: pointer; transition: all 0.3s; }\n    .suspect-card:hover { border-color: var(--accent2); }\n    .suspect-card.selected { border-color: var(--accent); box-shadow: 0 0 12px rgba(233,69,96,0.4); }\n    .evidence-badge { display: inline-flex; align-items: center; gap: 0.4rem; background: rgba(245,166,35,0.15); border: 1px solid rgba(245,166,35,0.4); border-radius: 20px; padding: 0.3rem 0.8rem; font-size: 0.85rem; color: var(--accent2); }\n    .result-correct { background: rgba(46,204,113,0.15); border: 1px solid rgba(46,204,113,0.5); border-radius: 8px; padding: 1rem; margin-top: 1rem; }\n    .result-incorrect { background: rgba(233,69,96,0.15); border: 1px solid rgba(233,69,96,0.5); border-radius: 8px; padding: 1rem; margin-top: 1rem; }\n    .fade-in { animation: fadeIn 0.4s ease; }\n    @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }\n    .ref-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }\n    .ref-table th, .ref-table td { padding: 0.5rem; border: 1px solid rgba(255,255,255,0.1); text-align: center; }\n    .ref-table th { background: rgba(233,69,96,0.2); }\n    .ref-table tr:nth-child(even) { background: rgba(255,255,255,0.03); }\n    .tooltip { position: relative; }\n    .tooltip .tip-text { display: none; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); background: #222; padding: 0.5rem; border-radius: 6px; font-size: 0.8rem; white-space: nowrap; z-index: 10; }\n    .tooltip:hover .tip-text { display: block; }\n  </style>\n</head>\n<body>\n  <div class=\"game-container\" id=\"app\"></div>\n\n  <script>\n    // ─── SCORM BOILERPLATE & FALLBACKS ─────────────────────────────────────\n    if (typeof window.activityComplete !== \"function\") {\n      window.activityComplete = function(score) {\n        console.log('[SCORM] activityComplete appelé avec le score :', score);\n      };\n    }\n    \n    if (typeof window.activityProgress !== \"function\") {\n      window.activityProgress = function(stepId) {\n        console.log('[SCORM] activityProgress enregistré pour l\\'étape :', stepId);\n      };\n    }\n    \n    window.onActivityRestore = function(stepId) {\n      if (stepId) {\n        state.phase = stepId;\n        render();\n      }\n    };\n\n    // ─── DATA ───────────────────────────────────────────────────────────────\n    const GASES = [\n      {name:\"Dioxygène\",formula:\"O₂\",test:\"Ravive le tison\",density:1.429,boiling:-183},\n      {name:\"Dioxyde de carbone\",formula:\"CO₂\",test:\"Éteint la flamme\",density:1.977,boiling:-78.5},\n      {name:\"Dihydrogène\",formula:\"H₂\",test:\"Explose en présence de la flamme\",density:0.09,boiling:-253}\n    ];\n    const SOLIDS = [\n      {name:\"Fer\",formula:\"Fe\",density:7.87,melting:1538,color:\"gris foncé\"},\n      {name:\"Cuivre\",formula:\"Cu\",density:8.96,melting:1085,color:\"orangé\"},\n      {name:\"Aluminium\",formula:\"Al\",density:2.70,melting:660,color:\"gris clair\"}\n    ];\n    const LIQUIDS = [\n      {name:\"Eau\",formula:\"H₂O\",density:1.00,boiling:100,melting:0},\n      {name:\"Alcool éthylique\",formula:\"C₂H₅OH\",density:0.789,boiling:78.4,melting:-114},\n      {name:\"Glycérine\",formula:\"C₃H₈O₃\",density:1.261,boiling:290,melting:18},\n      {name:\"Glycol\",formula:\"C₂H₆O₂\",density:1.113,boiling:197,melting:-13},\n      {name:\"Huile d'olive\",formula:\"—\",density:0.92,boiling:300,melting:-6}\n    ];\n\n    const SUSPECTS = [\n      {name:\"M. Ferland\",description:\"Technicien de laboratoire, passionné de métallurgie. Utilise régulièrement du fer et de l'aluminium pour ses expériences. Il travaille souvent avec du glycol comme antigel.\"},\n      {name:\"Mme Lachance\",description:\"Professeure de chimie remplaçante. Elle utilise du cuivre pour ses démonstrations et travaille avec de la glycérine pour ses réactions.\"},\n      {name:\"Dr. Oxid\",description:\"Chercheur invité, spécialiste des gaz. Il manipule fréquemment du dioxyde de carbone et utilise de l'alcool pour nettoyer ses instruments.\"}\n    ];\n\n    const config = { game_title: \"Enquête au laboratoire\" };\n\n    // ─── GAME STATE ─────────────────────────────────────────────────────────\n    let state = {\n      phase: \"intro\", \n      scenario: null, \n      analysesChosen: {solid:[], liquid:[], gas:[]}, \n      results: {solid:null, liquid:null, gas:null}, \n      accusation: null\n    };\n\n    const SUSPECT_PROFILES = [\n      {\n        suspect: SUSPECTS[0],\n        solids: [\"Fer\", \"Aluminium\"],\n        liquids: [\"Glycol\"],\n        gases: [\"Dioxygène\"],\n        description: \"Utilise du fer ou aluminium, du glycol, et produit de l'oxygène\"\n      },\n      {\n        suspect: SUSPECTS[1],\n        solids: [\"Cuivre\"],\n        liquids: [\"Glycérine\"],\n        gases: [\"Dioxyde de carbone\"],\n        description: \"Utilise du cuivre, de la glycérine, et du dioxyde de carbone\"\n      },\n      {\n        suspect: SUSPECTS[2],\n        solids: [\"Aluminium\"],\n        liquids: [\"Alcool éthylique\"],\n        gases: [\"Dihydrogène\"],\n        description: \"Utilise de l'aluminium, de l'alcool, et produit du dihydrogène\"\n      }\n    ];\n\n    function generateScenario(){\n      const culpritProfile = SUSPECT_PROFILES[Math.floor(Math.random() * SUSPECT_PROFILES.length)];\n      const solid = SOLIDS.find(s => culpritProfile.solids.includes(s.name));\n      const liquid = LIQUIDS.find(l => culpritProfile.liquids.includes(l.name));\n      const gas = GASES.find(g => culpritProfile.gases.includes(g.name));\n      \n      const solidMass = +(solid.density * (10 + Math.random()*20)).toFixed(1);\n      const solidVolume = +(solidMass / solid.density).toFixed(1);\n      const liquidMass = +(liquid.density * (20 + Math.random()*30)).toFixed(1);\n      const liquidVolume = +(liquidMass / liquid.density).toFixed(1);\n      \n      return {\n        gas, solid, liquid,\n        solidMass, solidVolume,\n        liquidMass, liquidVolume,\n        culprit: culpritProfile.suspect,\n        culpritProfile: culpritProfile\n      };\n    }\n\n    function init(){\n      state.scenario = generateScenario();\n      state.phase = \"intro\";\n      state.analysesChosen = {solid:[], liquid:[], gas:[]};\n      state.results = {solid:null, liquid:null, gas:null};\n      state.accusation = null;\n      window.activityProgress(\"intro\");\n      render();\n    }\n\n    // ─── RENDER ─────────────────────────────────────────────────────────────\n    function render(){\n      const app = document.getElementById('app');\n      switch(state.phase){\n        case \"intro\": app.innerHTML = renderIntro(); break;\n        case \"scene\": app.innerHTML = renderScene(); break;\n        case \"analyse_solid\": app.innerHTML = renderAnalyse(\"solid\"); break;\n        case \"result_solid\": app.innerHTML = renderResult(\"solid\"); break;\n        case \"analyse_liquid\": app.innerHTML = renderAnalyse(\"liquid\"); break;\n        case \"result_liquid\": app.innerHTML = renderResult(\"liquid\"); break;\n        case \"analyse_gas\": app.innerHTML = renderAnalyse(\"gas\"); break;\n        case \"result_gas\": app.innerHTML = renderResult(\"gas\"); break;\n        case \"reference\": app.innerHTML = renderReference(); break;\n        case \"accusation\": app.innerHTML = renderAccusation(); break;\n        case \"verdict\": app.innerHTML = renderVerdict(); break;\n      }\n      if (typeof lucide !== 'undefined') {\n        lucide.createIcons();\n      }\n      if (typeof window.requestResize === 'function') {\n        window.requestResize();\n      }\n    }\n\n    function renderIntro(){\n      return `<div class=\"max-w-3xl mx-auto p-6 fade-in\">\n        <div class=\"text-center mb-8\">\n          <div class=\"inline-block p-4 rounded-full bg-gradient-to-br from-red-900/40 to-purple-900/40 mb-4\">\n            ${svgMagnifyingGlass()}\n          </div>\n          <h1 class=\"text-3xl font-bold mb-2\">${config.game_title}</h1>\n          <p class=\"text-red-400 text-lg\">Science · 3ᵉ secondaire</p>\n        </div>\n        <div class=\"card\">\n          <h2 class=\"text-xl font-bold mb-3 text-red-300\"><i data-lucide=\"alert-triangle\" class=\"inline w-5 h-5\"></i> Mise en situation</h2>\n          <p class=\"mb-4 leading-relaxed\">Une expérience cruciale a été sabotée hier soir au laboratoire de ton école. La direction a besoin de toi pour identifier le coupable avant que la police n'arrive.</p>\n          <p class=\"mb-4 leading-relaxed font-semibold text-yellow-300\">Tu dois trouver le coupable d'un crime à l'aide de trois indices trouvés sur les lieux : un solide, un liquide et un gaz !</p>\n          <h3 class=\"font-bold mb-2\">Tes objectifs :</h3>\n          <ul class=\"list-disc list-inside space-y-1 text-sm text-gray-300 mb-4\">\n            <li>Analyser les 3 indices trouvés sur la scène (Solide, Liquide, Gaz)</li>\n            <li>Commander des tests au laboratoire</li>\n            <li>Utiliser tes connaissances scientifiques pour identifier chaque substance</li>\n            <li>Désigner le coupable parmi les 3 suspects</li>\n          </ul>\n        </div>\n        <div class=\"text-center mt-6\">\n          <button class=\"btn-primary text-lg px-8 py-3\" onclick=\"goTo('scene')\"><i data-lucide=\"search\" class=\"inline w-5 h-5 mr-2\"></i>Commencer l'enquête</button>\n        </div>\n      </div>`;\n    }\n\n    function renderScene(){\n      const s = state.scenario;\n      return `<div class=\"max-w-3xl mx-auto p-6 fade-in\">\n        <h2 class=\"text-2xl font-bold mb-4\"><i data-lucide=\"map-pin\" class=\"inline w-6 h-6 text-red-400\"></i> Scène du crime — Laboratoire</h2>\n        <p class=\"mb-6 text-gray-300\">Tu arrives sur les lieux. Trois indices ont été trouvés à proximité de l'expérience sabotée :</p>\n        <div class=\"grid gap-4 md:grid-cols-3 mb-6\">\n          <div class=\"card text-center\">\n            ${svgSolid()}\n            <h3 class=\"font-bold mt-2\">Indice #1 — Solide</h3>\n            <p class=\"text-sm text-gray-400\">Un morceau de métal recouvert de peinture noire. Impossible de l'identifier visuellement.</p>\n            <span class=\"evidence-badge mt-2\">Masse : ${s.solidMass} g</span>\n          </div>\n          <div class=\"card text-center\">\n            ${svgLiquid()}\n            <h3 class=\"font-bold mt-2\">Indice #2 — Liquide</h3>\n            <p class=\"text-sm text-gray-400\">Un liquide transparent trouvé dans un bécher sans étiquette.</p>\n            <span class=\"evidence-badge mt-2\">Volume : ${s.liquidVolume} mL</span>\n          </div>\n          <div class=\"card text-center\">\n            ${svgGas()}\n            <h3 class=\"font-bold mt-2\">Indice #3 — Gaz</h3>\n            <p class=\"text-sm text-gray-400\">Un gaz emprisonné dans une éprouvette inversée sur la cuve à eau.</p>\n            <span class=\"evidence-badge mt-2\">Incolore, inodore</span>\n          </div>\n        </div>\n        <div class=\"card\">\n          <h3 class=\"font-bold mb-3\"><i data-lucide=\"users\" class=\"inline w-5 h-5 text-yellow-400\"></i> Les suspects & leurs substances</h3>\n          <div class=\"grid gap-4 md:grid-cols-3\">\n            ${SUSPECT_PROFILES.map((profile)=>`<div class=\"p-3 rounded-lg bg-black/20 border border-gray-700\">\n              <p class=\"font-bold text-yellow-300\">${profile.suspect.name}</p>\n              <p class=\"text-xs text-gray-300 mt-2 mb-2\">${profile.suspect.description}</p>\n              <div class=\"text-xs space-y-1 bg-black/40 p-2 rounded\">\n                <p class=\"font-semibold text-cyan-400\">Substances qu'il utilise :</p>\n                <p>🧊 Métaux : ${profile.solids.join(', ')}</p>\n                <p>💧 Liquides : ${profile.liquids.join(', ')}</p>\n                <p>💨 Gaz : ${profile.gases.join(', ')}</p>\n              </div>\n            </div>`).join('')}\n          </div>\n        </div>\n        <div class=\"text-center mt-6\">\n          <button class=\"btn-primary\" onclick=\"goTo('analyse_solid')\">Analyser le premier indice (solide) <i data-lucide=\"arrow-right\" class=\"inline w-4 h-4\"></i></button>\n        </div>\n      </div>`;\n    }\n\n    function renderAnalyse(type){\n      const titles = {solid:\"Solide métallique\",liquid:\"Liquide inconnu\",gas:\"Gaz inconnu\"};\n      let options = [];\n      if(type===\"solid\"){\n        options = [\n          {id:\"mass_vol\",label:\"Mesurer la masse et le volume (masse volumique)\",icon:\"scale\"},\n          {id:\"melting\",label:\"Déterminer le point de fusion\",icon:\"thermometer\"},\n        ];\n      } else if(type===\"liquid\"){\n        options = [\n          {id:\"mass_vol\",label:\"Mesurer la masse et le volume (masse volumique)\",icon:\"scale\"},\n          {id:\"boiling\",label:\"Déterminer le point d'ébullition\",icon:\"thermometer\"},\n        ];\n      } else {\n        options = [\n          {id:\"flamme\",label:\"Approcher une flamme (allumette)\",icon:\"flame\"},\n          {id:\"tison\",label:\"Approcher un tison (bâton incandescent)\",icon:\"flame\"},\n          {id:\"chaux\",label:\"Introduire de l'eau de chaux\",icon:\"droplets\"},\n        ];\n      }\n      const chosen = state.analysesChosen[type];\n      return `<div class=\"max-w-3xl mx-auto p-6 fade-in\">\n        <h2 class=\"text-2xl font-bold mb-2\"><i data-lucide=\"flask-conical\" class=\"inline w-6 h-6 text-blue-400\"></i> Analyse — ${titles[type]}</h2>\n        <p class=\"text-gray-300 mb-4\">Quel test souhaites-tu envoyer au laboratoire?</p>\n        <div class=\"card\">\n          <p class=\"text-sm text-gray-400 mb-3\">Sélectionne un test puis clique sur « Envoyer au labo » :</p>\n          <div class=\"space-y-3\">\n            ${options.map(o=>`<button class=\"btn-secondary w-full text-left flex items-center gap-3 ${chosen.includes(o.id)?'selected':''}\" onclick=\"selectTest('${type}','${o.id}')\">\n              <i data-lucide=\"${o.icon}\" class=\"w-5 h-5 text-yellow-400\"></i> ${o.label}\n            </button>`).join('')}\n          </div>\n        </div>\n        <div class=\"mt-4 flex gap-3\">\n          <button class=\"btn-primary\" ${chosen.length===0?'disabled':''} onclick=\"sendToLab('${type}')\"><i data-lucide=\"send\" class=\"inline w-4 h-4 mr-1\"></i>Envoyer au labo</button>\n        </div>\n      </div>`;\n    }\n\n    function renderResult(type){\n      const s = state.scenario;\n      let report = \"\";\n      if(type===\"solid\"){\n        const chosen = state.analysesChosen.solid;\n        if(chosen.includes(\"mass_vol\")){\n          report += `<p><strong>Masse mesurée :</strong> <span class=\"text-yellow-300 font-bold\">${s.solidMass} g</span></p><p class=\"mt-2\"><strong>Volume mesuré (par déplacement d'eau) :</strong> <span class=\"text-yellow-300 font-bold\">${s.solidVolume} mL</span></p><p class=\"text-gray-400 text-sm mt-2\">À toi de calculer la masse volumique !</p>`;\n        }\n        if(chosen.includes(\"melting\")){\n          report += `<p class=\"mt-2\"><strong>Point de fusion mesuré :</strong> <span class=\"text-yellow-300 font-bold\">${s.solid.melting} °C</span></p>`;\n        }\n      } else if(type===\"liquid\"){\n        const chosen = state.analysesChosen.liquid;\n        if(chosen.includes(\"mass_vol\")){\n          report += `<p><strong>Masse mesurée :</strong> <span class=\"text-yellow-300 font-bold\">${s.liquidMass} g</span></p><p class=\"mt-2\"><strong>Volume mesuré :</strong> <span class=\"text-yellow-300 font-bold\">${s.liquidVolume} mL</span></p><p class=\"text-gray-400 text-sm mt-2\">À toi de calculer la masse volumique !</p>`;\n        }\n        if(chosen.includes(\"boiling\")){\n          report += `<p class=\"mt-2\"><strong>Point d'ébullition mesuré :</strong> <span class=\"text-yellow-300 font-bold\">${s.liquid.boiling} °C</span></p>`;\n        }\n      } else {\n        const chosen = state.analysesChosen.gas;\n        let obs = \"\";\n        if(chosen.includes(\"flamme\")){\n          if(s.gas.name===\"Dihydrogène\") obs = \"Le gaz <span class='text-orange-400 font-bold'>EXPLOSE avec un « pop » caractéristique</span> à la flamme !\";\n          else if(s.gas.name===\"Dioxygène\") obs = \"La flamme <span class='text-green-400 font-bold'>s'intensifie</span> et <span class='text-green-400 font-bold'>ravive au contact du gaz</span>.\";\n          else obs = \"La flamme <span class='text-red-400 font-bold'>s'éteint</span> au contact du gaz.\";\n        }\n        if(chosen.includes(\"tison\")){\n          if(s.gas.name===\"Dioxygène\") obs = \"Le tison se <span class='text-green-400 font-bold'>ravive intensément</span> au contact du gaz !\";\n          else if(s.gas.name===\"Dioxyde de carbone\") obs = \"Le tison <span class='text-red-400 font-bold'>s'éteint immédiatement</span>.\";\n          else obs = \"Le tison <span class='text-gray-400'>ne montre aucune réaction particulière</span>.\";\n        }\n        if(chosen.includes(\"chaux\")){\n          if(s.gas.name===\"Dioxyde de carbone\") obs = \"L'eau de chaux se <span class='text-yellow-300 font-bold'>trouble et devient blanche/laiteuse</span> (précipité de carbonate de calcium).\";\n          else obs = \"L'eau de chaux <span class='text-blue-400'>ne montre aucune réaction</span>.\";\n        }\n        report = `<p><strong>Observation :</strong> ${obs}</p>`;\n      }\n\n      const nextPhases = {solid:\"analyse_liquid\",liquid:\"analyse_gas\",gas:\"reference\"};\n      const nextLabels = {solid:\"Analyser le liquide\",liquid:\"Analyser le gaz\",gas:\"Consulter les documents de référence\"};\n\n      return `<div class=\"max-w-3xl mx-auto p-6 fade-in\">\n        <h2 class=\"text-2xl font-bold mb-4\"><i data-lucide=\"file-text\" class=\"inline w-6 h-6 text-green-400\"></i> Rapport du laboratoire</h2>\n        <div class=\"card\">${report}</div>\n        <p class=\"text-sm text-gray-400 mt-3\">Tu peux maintenant identifier cette substance à l'aide des documents de référence à l'étape suivante, ou demander un autre test.</p>\n        <div class=\"mt-4 flex gap-3 flex-wrap\">\n          <button class=\"btn-secondary\" onclick=\"goTo('analyse_${type}')\"><i data-lucide=\"undo\" class=\"inline w-4 h-4 mr-1\"></i>Demander un autre test</button>\n          <button class=\"btn-primary\" onclick=\"goTo('${nextPhases[type]}')\">${nextLabels[type]} <i data-lucide=\"arrow-right\" class=\"inline w-4 h-4 ml-1\"></i></button>\n        </div>\n      </div>`;\n    }\n\n    function renderReference(){\n      return `<div class=\"max-w-3xl mx-auto p-6 fade-in\">\n        <h2 class=\"text-2xl font-bold mb-4\"><i data-lucide=\"book-open\" class=\"inline w-6 h-6 text-blue-400\"></i> Documents de référence</h2>\n        <div class=\"card mb-4\">\n          <h3 class=\"font-bold text-yellow-300 mb-2\">Métaux — Propriétés physiques</h3>\n          <table class=\"ref-table\">\n            <tr><th>Métal</th><th>Masse vol. (g/mL)</th><th>Point de fusion (°C)</th></tr>\n            ${SOLIDS.map(s=>`<tr><td>${s.name}</td><td>${s.density.toFixed(2)}</td><td>${s.melting}</td></tr>`).join('')}\n          </table>\n        </div>\n        <div class=\"card mb-4\">\n          <h3 class=\"font-bold text-yellow-300 mb-2\">Liquides — Propriétés physiques</h3>\n          <table class=\"ref-table\">\n            <tr><th>Liquide</th><th>Masse vol. (g/mL)</th><th>Point d'ébullition (°C)</th></tr>\n            ${LIQUIDS.map(l=>`<tr><td>${l.name}</td><td>${l.density.toFixed(3)}</td><td>${l.boiling}</td></tr>`).join('')}\n          </table>\n        </div>\n        <div class=\"card mb-4\">\n          <h3 class=\"font-bold text-yellow-300 mb-2\">Gaz — Tests d'identification</h3>\n          <table class=\"ref-table\">\n            <tr><th>Gaz</th><th>Test</th><th>Résultat</th></tr>\n            <tr><td>Dihydrogène (H₂)</td><td>Flamme</td><td>EXPLOSE avec un « pop »</td></tr>\n            <tr><td>Dioxygène (O₂)</td><td>Tison</td><td>Ravive le tison</td></tr>\n            <tr><td>Dioxyde de carbone (CO₂)</td><td>Eau de chaux</td><td>Trouble la solution (précipité blanc)</td></tr>\n          </table>\n        </div>\n        <div class=\"text-center mt-6\">\n          <button class=\"btn-primary text-lg\" onclick=\"goTo('accusation')\"><i data-lucide=\"user-check\" class=\"inline w-5 h-5 mr-2\"></i>Désigner le coupable</button>\n        </div>\n      </div>`;\n    }\n\n    function renderAccusation(){\n      const s = state.scenario;\n      return `<div class=\"max-w-3xl mx-auto p-6 fade-in\">\n        <h2 class=\"text-2xl font-bold mb-4\"><i data-lucide=\"gavel\" class=\"inline w-6 h-6 text-red-400\"></i> Accusation finale</h2>\n        <div class=\"card mb-4\">\n          <h3 class=\"font-bold text-lg mb-3 text-cyan-400\">Substances identifiées :</h3>\n          <div class=\"bg-black/30 p-4 rounded-lg mb-4 space-y-2\">\n            <div class=\"flex justify-between items-center\"><span>🧊 Solide métallique :</span><span class=\"text-yellow-300 font-bold\">${s.solid.name}</span></div>\n            <div class=\"flex justify-between items-center\"><span>💧 Liquide :</span><span class=\"text-yellow-300 font-bold\">${s.liquid.name}</span></div>\n            <div class=\"flex justify-between items-center\"><span>💨 Gaz :</span><span class=\"text-yellow-300 font-bold\">${s.gas.name}</span></div>\n          </div>\n          <p class=\"text-sm text-gray-400 mb-3\">Compare ces trois substances avec les profils des suspects pour trouver le coupable !</p>\n          <h3 class=\"font-bold text-cyan-400 mb-3\">Profils des suspects :</h3>\n          <div class=\"space-y-2 text-xs bg-black/40 p-3 rounded\">\n            ${SUSPECT_PROFILES.map(p=>`<div class=\"pb-2 border-b border-gray-700 last:border-b-0\">\n              <p class=\"font-bold text-yellow-300\">${p.suspect.name}</p>\n              <p class=\"text-gray-300\">🧊 ${p.solids.join(', ')} | 💧 ${p.liquids.join(', ')} | 💨 ${p.gases.join(', ')}</p>\n            </div>`).join('')}\n          </div>\n        </div>\n        <h3 class=\"font-bold mb-3 text-lg\">Qui est le coupable ?</h3>\n        <div class=\"grid gap-4 md:grid-cols-3 mb-6\" id=\"suspectGrid\">\n          ${SUSPECTS.map((su,i)=>`<div class=\"suspect-card\" onclick=\"selectSuspect(${i}, this)\">\n            ${svgPerson(i)}\n            <p class=\"font-bold text-center mt-2\">${su.name}</p>\n          </div>`).join('')}\n        </div>\n        <div class=\"mt-6 mb-4\">\n          <button class=\"btn-secondary w-full\" onclick=\"toggleSuspectDetails()\"><i data-lucide=\"info\" class=\"inline w-4 h-4 mr-2\"></i>Voir les détails des suspects</button>\n          <div id=\"suspectDetails\" class=\"hidden mt-4 card\">\n            <h3 class=\"font-bold text-cyan-400 mb-3\">Profils complets des suspects :</h3>\n            <div class=\"space-y-4\">\n              ${SUSPECT_PROFILES.map(p=>`<div class=\"bg-black/40 p-4 rounded-lg border border-gray-700\">\n                <p class=\"font-bold text-lg text-yellow-300 mb-2\">${p.suspect.name}</p>\n                <p class=\"text-sm text-gray-300 mb-3\">${p.suspect.description}</p>\n                <div class=\"space-y-1 text-sm bg-black/60 p-3 rounded\">\n                  <p class=\"font-semibold text-cyan-400\">Substances utilisées :</p>\n                  <p><strong>🧊 Métaux :</strong> ${p.solids.join(', ')}</p>\n                  <p><strong>💧 Liquides :</strong> ${p.liquids.join(', ')}</p>\n                  <p><strong>💨 Gaz :</strong> ${p.gases.join(', ')}</p>\n                </div>\n              </div>`).join('')}\n            </div>\n          </div>\n        </div>\n        <div class=\"flex gap-3 flex-wrap\">\n          <button class=\"btn-secondary\" onclick=\"goTo('reference')\"><i data-lucide=\"arrow-left\" class=\"inline w-4 h-4 mr-1\"></i>Revoir les documents</button>\n          <button class=\"btn-primary\" id=\"accuseBtn\" disabled onclick=\"accuse()\"><i data-lucide=\"alert-circle\" class=\"inline w-4 h-4 mr-1\"></i>Accuser ce suspect</button>\n        </div>\n      </div>`;\n    }\n\n    function renderVerdict(){\n      const s = state.scenario;\n      const correct = state.accusation === s.culprit.name;\n      const verdictClass = correct ? \"result-correct\" : \"result-incorrect\";\n      const icon = correct ? \"check-circle\" : \"x-circle\";\n      const msg = correct \n        ? `Bravo, détective ! Tu as correctement identifié <strong>${s.culprit.name}</strong> comme le coupable !`\n        : `Ce n'est pas la bonne réponse. Le coupable était <strong>${s.culprit.name}</strong>.`;\n\n      const explanation = `<p class=\"mt-3 text-sm\">Les substances retrouvées sur la scène (${s.solid.name}, ${s.liquid.name}, ${s.gas.name}) correspondent au profil de <strong>${s.culprit.name}</strong>, qui utilise ces substances dans son travail quotidien au laboratoire.</p>`;\n\n      return `<div class=\"max-w-3xl mx-auto p-6 fade-in\">\n        <h2 class=\"text-2xl font-bold mb-4\"><i data-lucide=\"${icon}\" class=\"inline w-6 h-6 ${correct?'text-green-400':'text-red-400'}\"></i> Verdict</h2>\n        <div class=\"${verdictClass}\">\n          <p class=\"text-lg\">${msg}</p>\n          ${explanation}\n        </div>\n        <div class=\"card mt-4\">\n          <h3 class=\"font-bold mb-2\">Résumé des preuves</h3>\n          <ul class=\"space-y-1 text-sm\">\n            <li>🧊 Solide : <strong>${s.solid.name}</strong> (${s.solid.formula}) — masse volumique ${s.solid.density} g/mL</li>\n            <li>💧 Liquide : <strong>${s.liquid.name}</strong> (${s.liquid.formula}) — masse volumique ${s.liquid.density} g/mL</li>\n            <li>💨 Gaz : <strong>${s.gas.name}</strong> (${s.gas.formula}) — ${s.gas.test}</li>\n          </ul>\n        </div>\n        <div class=\"text-center mt-6\">\n          <button class=\"btn-primary text-lg\" onclick=\"newGame()\"><i data-lucide=\"refresh-cw\" class=\"inline w-5 h-5 mr-2\"></i>Nouvelle enquête (nouveau scénario)</button>\n        </div>\n      </div>`;\n    }\n\n    // ─── ACTIONS ────────────────────────────────────────────────────────────\n    function goTo(phase){ \n      state.phase = phase; \n      window.activityProgress(phase);\n      render(); \n      window.scrollTo(0,0); \n    }\n\n    function selectTest(type,id){\n      if(!state.analysesChosen[type].includes(id)) state.analysesChosen[type].push(id);\n      else state.analysesChosen[type] = state.analysesChosen[type].filter(x=>x!==id);\n      render();\n    }\n\n    function sendToLab(type){\n      if(state.analysesChosen[type].length===0) return;\n      state.phase = \"result_\"+type;\n      window.activityProgress(state.phase);\n      render();\n    }\n\n    let selectedSuspectIdx = null;\n    function selectSuspect(i, element){\n      selectedSuspectIdx = i;\n      document.querySelectorAll('.suspect-card').forEach((el)=>el.classList.remove('selected'));\n      element.classList.add('selected');\n      document.getElementById('accuseBtn').disabled = false;\n    }\n\n    function accuse(){\n      if(selectedSuspectIdx === null) return;\n      state.accusation = SUSPECTS[selectedSuspectIdx].name;\n      state.phase = \"verdict\";\n      \n      const s = state.scenario;\n      const score = (state.accusation === s.culprit.name) ? 100 : 0;\n      \n      // Appel SCORM final\n      window.activityComplete(score);\n      \n      render();\n    }\n\n    function toggleSuspectDetails(){\n      const details = document.getElementById('suspectDetails');\n      details.classList.toggle('hidden');\n      if (typeof window.requestResize === 'function') {\n        window.requestResize();\n      }\n    }\n\n    function newGame(){ \n      selectedSuspectIdx = null; \n      init(); \n    }\n\n    // ─── SVGs ───────────────────────────────────────────────────────────────\n    function svgMagnifyingGlass(){\n      return `<svg width=\"64\" height=\"64\" viewBox=\"0 0 64 64\" fill=\"none\"><circle cx=\"28\" cy=\"28\" r=\"16\" stroke=\"#e94560\" stroke-width=\"3\"/><line x1=\"40\" y1=\"40\" x2=\"56\" y2=\"56\" stroke=\"#e94560\" stroke-width=\"4\" stroke-linecap=\"round\"/><circle cx=\"28\" cy=\"28\" r=\"8\" fill=\"rgba(233,69,96,0.1)\"/></svg>`;\n    }\n    function svgSolid(){\n      return `<svg width=\"60\" height=\"60\" viewBox=\"0 0 60 60\"><rect x=\"15\" y=\"20\" width=\"30\" height=\"25\" rx=\"3\" fill=\"#444\" stroke=\"#888\" stroke-width=\"2\"/><rect x=\"15\" y=\"20\" width=\"30\" height=\"25\" rx=\"3\" fill=\"url(#pg)\"/><defs><linearGradient id=\"pg\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0%\" stop-color=\"#333\"/><stop offset=\"100%\" stop-color=\"#111\"/></linearGradient></defs><text x=\"30\" y=\"50\" text-anchor=\"middle\" fill=\"#aaa\" font-size=\"8\">peint</text></svg>`;\n    }\n    function svgLiquid(){\n      return `<svg width=\"60\" height=\"60\" viewBox=\"0 0 60 60\"><path d=\"M20 15 L20 40 Q20 50 30 50 Q40 50 40 40 L40 15 Z\" fill=\"rgba(100,180,255,0.2)\" stroke=\"#6ab4ff\" stroke-width=\"2\"/><path d=\"M22 30 Q30 27 38 30 L38 40 Q38 48 30 48 Q22 48 22 40 Z\" fill=\"rgba(100,180,255,0.4)\"/></svg>`;\n    }\n    function svgGas(){\n      return `<svg width=\"60\" height=\"60\" viewBox=\"0 0 60 60\"><ellipse cx=\"30\" cy=\"35\" rx=\"12\" ry=\"18\" fill=\"none\" stroke=\"#aaa\" stroke-width=\"2\"/><path d=\"M22 20 Q30 15 38 20\" stroke=\"#aaa\" stroke-width=\"2\" fill=\"none\"/><circle cx=\"27\" cy=\"30\" r=\"2\" fill=\"rgba(255,255,255,0.2)\"/><circle cx=\"33\" cy=\"35\" r=\"1.5\" fill=\"rgba(255,255,255,0.15)\"/><circle cx=\"30\" cy=\"42\" r=\"1\" fill=\"rgba(255,255,255,0.1)\"/></svg>`;\n    }\n    function svgPerson(i){\n      const colors = [\"#e94560\",\"#f5a623\",\"#6ab4ff\"];\n      return `<svg width=\"50\" height=\"50\" viewBox=\"0 0 50 50\" class=\"mx-auto\"><circle cx=\"25\" cy=\"18\" r=\"9\" fill=\"${colors[i]}\"/><path d=\"M12 45 Q12 32 25 32 Q38 32 38 45\" fill=\"${colors[i]}\" opacity=\"0.7\"/></svg>`;\n    }\n\n    // ─── INIT INITIAL ───────────────────────────────────────────────────────\n    init();\n\n  </script>\n\n  <script id=\"scorm-resize\">\n    function resizeLMSIframe() {\n      var wrapper = document.getElementById('app') || document.body;\n      var h = (wrapper ? wrapper.offsetHeight : document.body.scrollHeight) + 50;\n      try {\n        if (window.frameElement) {\n          window.frameElement.style.height = h + 'px';\n        }\n        if (window.parent && window.parent !== window) {\n          window.parent.postMessage({ type: 'setHeight', height: h }, '*');\n        }\n      } catch(e) {}\n    }\n    try { new ResizeObserver(resizeLMSIframe).observe(document.body); } catch(e) {}\n    window.addEventListener('load', resizeLMSIframe);\n    window.requestResize = function() {\n      setTimeout(resizeLMSIframe, 100);\n      setTimeout(resizeLMSIframe, 400);\n    };\n  </script>\n\n  </body>\n</html>",
  "validationReport": "",
  "contentMode": "full"
}