{
  "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\" style=\"margin: 0; padding: 0; height: auto; min-height: auto;\">\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\"></script>\n    <script src=\"https://unpkg.com/react@18/umd/react.production.min.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@18/umd/react-dom.production.min.js\"></script>\n    <script src=\"https://unpkg.com/@babel/standalone/babel.min.js\"></script>\n    <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap\" rel=\"stylesheet\">\n    <style>\n        body { font-family: 'Inter', sans-serif; background-color: #f1f5f9; color: #1e293b; }\n        .glass-panel { background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); }\n        .fade-in { animation: fadeIn 0.4s ease-in-out; }\n        @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }\n    </style>\n    <script>\n        // Fallbacks SCORM abstraits (écrasés par le LMS si présent)\n        if (typeof window.activityComplete !== \"function\") {\n            window.activityComplete = function(score) {\n                console.log('[SCORM] activityComplete fallback. Score envoyé :', score);\n            };\n        }\n        if (typeof window.activityProgress !== \"function\") {\n            window.activityProgress = function(stepId) {\n                console.log('[SCORM] activityProgress fallback. Étape :', stepId);\n            };\n        }\n        if (typeof window.requestResize !== \"function\") {\n            window.requestResize = function() {};\n        }\n    </script>\n</head>\n<body style=\"margin: 0; padding: 0; height: auto; min-height: auto; overflow-x: hidden; overflow-y: hidden;\">\n    \n    <div id=\"scorm-main-wrapper\" style=\"padding: 20px; width: 100%;\">\n        <div id=\"root\"></div>\n    </div>\n\n    <script type=\"text/babel\">\n        const { useState, useEffect, useRef } = React;\n\n        // --- DONNÉES DE BASE ---\n        const SUSPECTS_BASE = [\n            { id: 'ferland', name: 'M. Ferland', role: 'Technicien en métallurgie' },\n            { id: 'lachance', name: 'Mme. Lachance', role: 'Biologiste' },\n            { id: 'oxid', name: 'Dr. Oxid', role: 'Chercheur en énergie' }\n        ];\n\n        const SUBSTANCES = {\n            solids: [\n                { name: 'Fer', density: 7.87 },\n                { name: 'Cuivre', density: 8.96 },\n                { name: 'Aluminium', density: 2.70 }\n            ],\n            liquids: [\n                { name: 'Eau', boil: 100, density: 1.00 },\n                { name: 'Alcool', boil: 78, density: 0.79 },\n                { name: 'Glycérine', boil: 290, density: 1.26 },\n                { name: 'Glycol', boil: 197, density: 1.11 },\n                { name: 'Huile d\\'olive', boil: 300, density: 0.92 }\n            ],\n            gases: [\n                { \n                    name: 'Dioxygène', \n                    tests: [\n                        { name: 'Test du tison incandescent', result: 'Le tison s\\'est rallumé brillamment.' },\n                        { name: 'Test de la flamme', result: 'La flamme a continué de brûler normalement.' },\n                        { name: 'Test de l\\'eau de chaux', result: 'L\\'eau de chaux est restée limpide.' }\n                    ]\n                },\n                { \n                    name: 'Dioxyde de carbone', \n                    tests: [\n                        { name: 'Test du tison incandescent', result: 'Le tison s\\'est éteint.' },\n                        { name: 'Test de la flamme', result: 'La flamme s\\'est éteinte instantanément.' },\n                        { name: 'Test de l\\'eau de chaux', result: 'L\\'eau de chaux s\\'est brouillée (devenue laiteuse).' }\n                    ]\n                },\n                { \n                    name: 'Dihydrogène', \n                    tests: [\n                        { name: 'Test du tison incandescent', result: 'Test non effectué (risque d\\'explosion imprévisible).' },\n                        { name: 'Test de la flamme', result: 'Une petite explosion (pop) s\\'est produite.' },\n                        { name: 'Test de l\\'eau de chaux', result: 'L\\'eau de chaux est restée limpide.' }\n                    ]\n                }\n            ]\n        };\n\n        // --- COMPOSANTS SVG ---\n        const IconCheck = () => <svg className=\"w-6 h-6 text-green-600 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M5 13l4 4L19 7\"></path></svg>;\n        const IconX = () => <svg className=\"w-6 h-6 text-red-600 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path></svg>;\n        const IconBook = () => <svg className=\"w-5 h-5 mr-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253\"></path></svg>;\n        \n        const SvgSolid = () => (\n            <svg viewBox=\"0 0 100 100\" className=\"w-24 h-24 mx-auto mb-4 drop-shadow-lg\">\n                <rect x=\"25\" y=\"25\" width=\"50\" height=\"50\" rx=\"5\" fill=\"#334155\" stroke=\"#0f172a\" strokeWidth=\"4\" />\n                <path d=\"M25 25 L40 10 L90 10 L90 60 L75 75\" fill=\"#475569\" stroke=\"#0f172a\" strokeWidth=\"3\" opacity=\"0.8\"/>\n                <path d=\"M25 25 L40 10 L90 10 L75 25 Z\" fill=\"#64748b\" stroke=\"#0f172a\" strokeWidth=\"3\" />\n                <text x=\"40\" y=\"55\" fontSize=\"30\" fill=\"white\" fontWeight=\"bold\">?</text>\n            </svg>\n        );\n\n        const SvgLiquid = () => (\n            <svg viewBox=\"0 0 100 100\" className=\"w-24 h-24 mx-auto mb-4 drop-shadow-lg\">\n                <path d=\"M35 20 L35 40 L20 80 A 10 10 0 0 0 30 95 L70 95 A 10 10 0 0 0 80 80 L65 40 L65 20 Z\" fill=\"#e2e8f0\" stroke=\"#475569\" strokeWidth=\"4\"/>\n                <path d=\"M25 70 L20 80 A 10 10 0 0 0 30 95 L70 95 A 10 10 0 0 0 80 80 L75 70 Z\" fill=\"#38bdf8\" opacity=\"0.8\"/>\n                <line x1=\"30\" y1=\"20\" x2=\"70\" y2=\"20\" stroke=\"#475569\" strokeWidth=\"4\"/>\n            </svg>\n        );\n\n        const SvgGas = () => (\n            <svg viewBox=\"0 0 100 100\" className=\"w-24 h-24 mx-auto mb-4 drop-shadow-lg\">\n                <rect x=\"40\" y=\"10\" width=\"20\" height=\"80\" rx=\"10\" fill=\"#f8fafc\" stroke=\"#475569\" strokeWidth=\"4\"/>\n                <circle cx=\"50\" cy=\"80\" r=\"4\" fill=\"#94a3b8\" />\n                <circle cx=\"45\" cy=\"65\" r=\"3\" fill=\"#94a3b8\" />\n                <circle cx=\"55\" cy=\"50\" r=\"5\" fill=\"#94a3b8\" />\n                <circle cx=\"48\" cy=\"35\" r=\"3\" fill=\"#94a3b8\" />\n                <rect x=\"38\" y=\"8\" width=\"24\" height=\"6\" fill=\"#ef4444\" />\n            </svg>\n        );\n\n        const SvgFlame = () => (\n            <svg viewBox=\"0 0 100 100\" className=\"w-16 h-16 mx-auto drop-shadow-md mb-2\">\n                <path d=\"M50 10 Q30 40 30 70 A 20 20 0 0 0 70 70 Q70 40 50 10 Z\" fill=\"#ef4444\"/>\n                <path d=\"M50 30 Q40 55 40 70 A 10 10 0 0 0 60 70 Q60 55 50 30 Z\" fill=\"#fbbf24\"/>\n            </svg>\n        );\n\n        const SvgThermometer = () => (\n            <svg viewBox=\"0 0 100 100\" className=\"w-16 h-16 mx-auto drop-shadow-md mb-2\">\n                <rect x=\"42\" y=\"10\" width=\"16\" height=\"65\" rx=\"8\" fill=\"#f1f5f9\" stroke=\"#475569\" strokeWidth=\"3\"/>\n                <circle cx=\"50\" cy=\"80\" r=\"14\" fill=\"#ef4444\" stroke=\"#475569\" strokeWidth=\"3\"/>\n                <rect x=\"47\" y=\"30\" width=\"6\" height=\"45\" fill=\"#ef4444\"/>\n                <line x1=\"58\" y1=\"20\" x2=\"65\" y2=\"20\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <line x1=\"58\" y1=\"35\" x2=\"65\" y2=\"35\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <line x1=\"58\" y1=\"50\" x2=\"65\" y2=\"50\" stroke=\"#475569\" strokeWidth=\"2\"/>\n            </svg>\n        );\n\n        const SvgScale = ({ mass, itemType = 'solid' }) => (\n            <svg viewBox=\"0 0 100 100\" className=\"w-24 h-24 mx-auto drop-shadow-md\">\n                <rect x=\"15\" y=\"60\" width=\"70\" height=\"25\" rx=\"4\" fill=\"#cbd5e1\" stroke=\"#475569\" strokeWidth=\"3\"/>\n                <rect x=\"25\" y=\"65\" width=\"50\" height=\"15\" fill=\"#f8fafc\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <ellipse cx=\"50\" cy=\"55\" rx=\"35\" ry=\"8\" fill=\"#94a3b8\" stroke=\"#475569\" strokeWidth=\"3\"/>\n                <text x=\"50\" y=\"76\" fontSize=\"11\" textAnchor=\"middle\" fill=\"#0f172a\" fontFamily=\"monospace\" fontWeight=\"bold\">{mass}g</text>\n                \n                {itemType === 'solid' && (\n                    <rect x=\"40\" y=\"35\" width=\"20\" height=\"20\" rx=\"3\" fill=\"#334155\" stroke=\"#0f172a\" strokeWidth=\"3\"/>\n                )}\n                {itemType === 'liquid' && (\n                    <g transform=\"translate(15, -8) scale(0.7)\">\n                        <path d=\"M30 90 L70 90 L65 85 L65 10 L35 10 L35 85 Z\" fill=\"#f1f5f9\" stroke=\"#475569\" strokeWidth=\"3\"/>\n                        <rect x=\"36\" y=\"40\" width=\"28\" height=\"45\" fill=\"#38bdf8\" opacity=\"0.6\"/>\n                        <line x1=\"35\" y1=\"20\" x2=\"42\" y2=\"20\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                        <line x1=\"35\" y1=\"30\" x2=\"45\" y2=\"30\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                        <line x1=\"35\" y1=\"40\" x2=\"42\" y2=\"40\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                        <line x1=\"35\" y1=\"50\" x2=\"45\" y2=\"50\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                        <line x1=\"35\" y1=\"60\" x2=\"42\" y2=\"60\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                        <line x1=\"35\" y1=\"70\" x2=\"45\" y2=\"70\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                    </g>\n                )}\n            </svg>\n        );\n\n        const SvgCylinder = ({ volume }) => (\n            <svg viewBox=\"0 0 100 100\" className=\"w-24 h-24 mx-auto drop-shadow-md\">\n                <path d=\"M30 90 L70 90 L65 85 L65 10 L35 10 L35 85 Z\" fill=\"#f1f5f9\" stroke=\"#475569\" strokeWidth=\"3\"/>\n                <rect x=\"36\" y=\"40\" width=\"28\" height=\"45\" fill=\"#38bdf8\" opacity=\"0.6\"/>\n                <line x1=\"35\" y1=\"20\" x2=\"42\" y2=\"20\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <line x1=\"35\" y1=\"30\" x2=\"45\" y2=\"30\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <line x1=\"35\" y1=\"40\" x2=\"42\" y2=\"40\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <line x1=\"35\" y1=\"50\" x2=\"45\" y2=\"50\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <line x1=\"35\" y1=\"60\" x2=\"42\" y2=\"60\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <line x1=\"35\" y1=\"70\" x2=\"45\" y2=\"70\" stroke=\"#475569\" strokeWidth=\"2\"/>\n                <rect x=\"42\" y=\"72\" width=\"16\" height=\"16\" rx=\"2\" fill=\"#334155\" stroke=\"#0f172a\" strokeWidth=\"2\"/>\n            </svg>\n        );\n\n        // --- APPLICATION PRINCIPALE ---\n        function App() {\n            const [gameState, setGameState] = useState('intro'); // intro, q1, q2, q3, q4, q5, outro\n            const [score, setScore] = useState(0);\n            const [scenario, setScenario] = useState(null);\n            \n            // État des questions\n            const [hasAnswered, setHasAnswered] = useState(false);\n            const [selectedOption, setSelectedOption] = useState(null);\n            const [showRefModal, setShowRefModal] = useState(false);\n\n            // Nouveaux états pour l'interactivité des étapes 1, 2 et 3\n            const [q1Tests, setQ1Tests] = useState([]);\n            const [revealedMeasurements, setRevealedMeasurements] = useState({ mass: false, volume: false });\n            const [q3Tests, setQ3Tests] = useState([]);\n\n            // Ref pour le scroll automatique\n            const nextButtonRef = useRef(null);\n\n            useEffect(() => {\n                initGame();\n\n                // RESTAURATION DE PROGRESSION SCORM\n                window.onActivityRestore = function(stepId) {\n                    if (stepId) {\n                        setGameState(stepId);\n                        if (window.requestResize) window.requestResize();\n                    }\n                };\n            }, []);\n\n            // Auto-scroll vers le bouton suivant quand l'élève répond\n            useEffect(() => {\n                if (hasAnswered && nextButtonRef.current) {\n                    setTimeout(() => {\n                        nextButtonRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' });\n                        if (window.requestResize) window.requestResize();\n                    }, 150);\n                }\n            }, [hasAnswered]);\n\n            const initGame = () => {\n                // Création aléatoire du scénario\n                const shuffledSolids = [...SUBSTANCES.solids].sort(() => Math.random() - 0.5);\n                const shuffledLiquids = [...SUBSTANCES.liquids].sort(() => Math.random() - 0.5).slice(0, 3);\n                const shuffledGases = [...SUBSTANCES.gases].sort(() => Math.random() - 0.5);\n\n                const suspectsAssigned = SUSPECTS_BASE.map((s, i) => ({\n                    ...s,\n                    uses: {\n                        solid: shuffledSolids[i],\n                        liquid: shuffledLiquids[i],\n                        gas: shuffledGases[i]\n                    }\n                }));\n\n                const culpritIndex = Math.floor(Math.random() * 3);\n                const culprit = suspectsAssigned[culpritIndex];\n\n                // Génération de mesures aléatoires pour le solide du coupable\n                const volume = (Math.floor(Math.random() * 4) + 1) * 10; // 10, 20, 30, 40\n                const mass = parseFloat((culprit.uses.solid.density * volume).toFixed(1));\n\n                // Génération de mesures aléatoires pour le liquide du coupable\n                const liquidVolume = (Math.floor(Math.random() * 4) + 2) * 10; // 20, 30, 40, 50 ml\n                const liquidMass = parseFloat((culprit.uses.liquid.density * liquidVolume).toFixed(1));\n\n                setScenario({\n                    suspects: suspectsAssigned,\n                    culprit: culprit,\n                    measurements: { volume, mass, liquidVolume, liquidMass }\n                });\n                \n                if (window.requestResize) window.requestResize();\n            };\n\n            const handleAnswer = (option, correctAnswer) => {\n                if (hasAnswered) return;\n                setSelectedOption(option);\n                setHasAnswered(true);\n                if (option === correctAnswer) {\n                    setScore(prev => prev + 1);\n                }\n                if (window.requestResize) window.requestResize();\n            };\n\n            const nextStep = (nextState) => {\n                setGameState(nextState);\n                setHasAnswered(false);\n                setSelectedOption(null);\n                setQ1Tests([]);\n                setRevealedMeasurements({ mass: false, volume: false });\n                setQ3Tests([]);\n                window.scrollTo({ top: 0, behavior: 'smooth' });\n                \n                // SUIVI DE PROGRESSION SCORM\n                window.activityProgress(nextState);\n                \n                if (window.requestResize) window.requestResize();\n            };\n\n            const terminerActivite = () => {\n                nextStep('outro');\n                \n                // CALCUL ET ENVOI DU RÉSULTAT FINAL SCORM\n                // La variable score (0 à 5) est évaluée sur un pourcentage de 100.\n                const finalScore = Math.round((score / 5) * 100);\n                window.activityComplete(finalScore);\n                \n                if (window.requestResize) window.requestResize();\n            };\n\n            if (!scenario) return <div className=\"text-center mt-20\">Chargement du laboratoire...</div>;\n\n            // --- VUES ---\n            const renderHeader = (title) => (\n                <div className=\"flex justify-between items-center mb-6 pb-4 border-b border-slate-200\">\n                    <h2 className=\"text-2xl font-bold text-slate-800\">{title}</h2>\n                    <div className=\"text-lg font-semibold bg-blue-100 text-blue-800 px-4 py-1 rounded-full\">\n                        Score : {score} / 5\n                    </div>\n                </div>\n            );\n\n            const renderFeedback = (correctAnswer, explanation) => {\n                if (!hasAnswered) return null;\n                const isCorrect = selectedOption === correctAnswer;\n                return (\n                    <div className={`mt-6 p-5 rounded-xl flex items-start gap-4 fade-in shadow-sm ${isCorrect ? 'bg-green-50 border-2 border-green-200' : 'bg-red-50 border-2 border-red-200'}`}>\n                        <div className=\"mt-1\">{isCorrect ? <IconCheck /> : <IconX />}</div>\n                        <div>\n                            <h4 className={`text-lg font-bold ${isCorrect ? 'text-green-800' : 'text-red-800'}`}>\n                                {isCorrect ? 'Excellente déduction !' : 'Oups, ce n\\'est pas tout à fait ça.'}\n                            </h4>\n                            <p className=\"text-slate-800 mt-2 font-medium\">{explanation}</p>\n                        </div>\n                    </div>\n                );\n            };\n\n            return (\n                <div className=\"w-full p-4 md:p-8 flex flex-col items-center pb-24\">\n                    \n                    {/* Bouton Modal Référence */}\n                    {gameState !== 'intro' && gameState !== 'outro' && (\n                        <button \n                            onClick={() => { setShowRefModal(true); if (window.requestResize) window.requestResize(); }}\n                            className=\"fixed top-4 right-4 md:top-8 md:right-8 bg-blue-600 text-white px-4 py-2 rounded-lg shadow-lg hover:bg-blue-700 transition flex items-center z-10\"\n                        >\n                            <IconBook /> Document de référence\n                        </button>\n                    )}\n\n                    <div className=\"w-full max-w-3xl glass-panel rounded-2xl shadow-xl p-6 md:p-10 border border-slate-200 relative\">\n                        \n                        {/* INTRO */}\n                        {gameState === 'intro' && (\n                            <div className=\"text-center fade-in\">\n                                <h1 className=\"text-4xl font-extrabold text-slate-900 mb-6\">Enquête au laboratoire 🔬</h1>\n                                <p className=\"text-lg text-slate-600 mb-4 text-left\">\n                                    Une expérience cruciale a été sabotée hier soir. La direction du centre de recherche a besoin de toi pour identifier le coupable avant que la police n'arrive !\n                                </p>\n                                <div className=\"bg-slate-100 p-6 rounded-lg text-left mb-8 border border-slate-200\">\n                                    <h3 className=\"font-bold text-lg mb-2\">Ta mission :</h3>\n                                    <p className=\"mb-2\">Tu dois trouver le coupable à l'aide de trois indices trouvés sur les lieux : <strong>un solide, un liquide et un gaz</strong>.</p>\n                                    <ul className=\"list-disc pl-5 space-y-1\">\n                                        <li>Analyse les indices.</li>\n                                        <li>Consulte le document de référence.</li>\n                                        <li>Identifie chaque substance.</li>\n                                        <li>Démasque le coupable parmi les suspects !</li>\n                                    </ul>\n                                </div>\n                                <button \n                                    onClick={() => nextStep('q1')}\n                                    className=\"bg-blue-600 text-white font-bold text-xl px-8 py-5 rounded-xl hover:bg-blue-700 hover:scale-105 transition-all shadow-lg\"\n                                >\n                                    Commencer l'enquête\n                                </button>\n                            </div>\n                        )}\n\n                        {/* Q1: Analyse du solide */}\n                        {gameState === 'q1' && (\n                            <div className=\"fade-in\">\n                                {renderHeader('Étape 1 : L\\'indice solide')}\n                                <SvgSolid />\n                                <p className=\"text-lg mb-6\">\n                                    Indice #1 : Un mystérieux cube de métal recouvert d'une peinture noire opaque a été retrouvé. Clique sur les analyses ci-dessous pour les commander au laboratoire. Attention, choisis bien ton approche !\n                                </p>\n                                <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-4\">\n                                    {['Le point d\\'ébullition', 'Le test de la flamme', 'La masse volumique'].map(opt => {\n                                        const isTested = q1Tests.includes(opt);\n                                        return (\n                                            <div \n                                                key={opt}\n                                                onClick={() => {\n                                                    if (isTested) return;\n                                                    if (!q1Tests.includes(opt)) {\n                                                        setQ1Tests(prev => [...prev, opt]);\n                                                        if (window.requestResize) window.requestResize();\n                                                    }\n                                                    if (!hasAnswered) {\n                                                        setHasAnswered(true);\n                                                        setSelectedOption(opt);\n                                                        if (opt === 'La masse volumique') setScore(prev => prev + 1);\n                                                    }\n                                                }}\n                                                className={`border-2 rounded-xl p-4 transition ${\n                                                    isTested \n                                                        ? opt === 'La masse volumique' ? 'bg-green-50 border-green-300' : 'bg-red-50 border-red-300'\n                                                        : 'bg-white border-slate-300 hover:border-blue-500 hover:bg-blue-50 cursor-pointer shadow-sm hover:shadow'\n                                                }`}\n                                            >\n                                                {!isTested ? (\n                                                    <div className=\"font-bold text-center py-4 flex flex-col items-center justify-center h-full text-blue-800\">\n                                                        <span className=\"text-2xl mb-2\">🔬</span>\n                                                        Commander :<br/>{opt}\n                                                    </div>\n                                                ) : (\n                                                    <div className=\"flex flex-col items-center animate-[fadeIn_0.3s_ease-in-out]\">\n                                                        <div className=\"font-bold mb-2 text-slate-800 text-center border-b pb-1 w-full\">{opt}</div>\n                                                        {opt === 'Le point d\\'ébullition' && <><SvgThermometer /><p className=\"text-sm mt-3 text-red-700 text-center font-medium\">Échec : Impossible de faire bouillir ce solide, la température est trop élevée !</p></>}\n                                                        {opt === 'Le test de la flamme' && <><SvgFlame /><p className=\"text-sm mt-3 text-red-700 text-center font-medium\">Échec : Le métal chauffe mais aucune couleur caractéristique n'apparaît.</p></>}\n                                                        {opt === 'La masse volumique' && <><div className=\"mt-2 mb-2\"><IconCheck /></div><p className=\"text-sm mt-1 text-green-800 text-center font-bold\">Excellente idée ! La masse volumique permet d'identifier le métal.</p></>}\n                                                    </div>\n                                                )}\n                                            </div>\n                                        );\n                                    })}\n                                </div>\n                                \n                                {renderFeedback(\n                                    'La masse volumique', \n                                    `La détermination de la masse volumique est la bonne approche. Les autres tests sont inefficaces ou impossibles sur ce cube métallique.`\n                                )}\n                                \n                                {hasAnswered && (\n                                    <button ref={nextButtonRef} onClick={() => nextStep('q2')} className=\"mt-8 w-full bg-blue-600 text-white py-4 rounded-xl font-bold text-lg hover:bg-blue-700 transition shadow-lg flex justify-center items-center gap-2\">\n                                        Effectuer les mesures <span>→</span>\n                                    </button>\n                                )}\n                            </div>\n                        )}\n\n                        {/* Q2: Identification du solide */}\n                        {gameState === 'q2' && (\n                            <div className=\"fade-in\">\n                                {renderHeader('Étape 2 : Identification du solide')}\n                                \n                                <p className=\"text-lg mb-6\">\n                                    Pour identifier ce métal, le laboratoire va procéder à la détermination de sa masse volumique. Clique sur les <strong>deux instruments</strong> pour procéder aux mesures :\n                                </p>\n\n                                <div className=\"flex flex-col md:flex-row justify-center gap-4 mb-6\">\n                                    <button\n                                        onClick={() => { setRevealedMeasurements(prev => ({...prev, mass: true})); if (window.requestResize) window.requestResize(); }}\n                                        className={`flex-1 p-4 rounded-xl border-2 transition ${revealedMeasurements.mass ? 'bg-slate-50 border-slate-300 cursor-default' : 'bg-white border-blue-300 hover:border-blue-500 hover:bg-blue-50 shadow-sm'}`}\n                                    >\n                                        {revealedMeasurements.mass ? (\n                                            <div className=\"animate-[fadeIn_0.3s_ease-in-out] flex flex-col items-center\">\n                                                <SvgScale mass={scenario.measurements.mass} />\n                                                <div className=\"mt-4 font-bold text-lg text-slate-800 bg-white p-2 rounded shadow-sm border inline-block\">Masse = {scenario.measurements.mass} g</div>\n                                            </div>\n                                        ) : (\n                                            <div className=\"font-bold text-blue-700 h-full flex flex-col items-center justify-center py-6\">\n                                                <span className=\"text-4xl mb-3\">⚖️</span>\n                                                Peser le solide\n                                            </div>\n                                        )}\n                                    </button>\n                                    <button\n                                        onClick={() => { setRevealedMeasurements(prev => ({...prev, volume: true})); if (window.requestResize) window.requestResize(); }}\n                                        className={`flex-1 p-4 rounded-xl border-2 transition ${revealedMeasurements.volume ? 'bg-slate-50 border-slate-300 cursor-default' : 'bg-white border-blue-300 hover:border-blue-500 hover:bg-blue-50 shadow-sm'}`}\n                                    >\n                                        {revealedMeasurements.volume ? (\n                                            <div className=\"animate-[fadeIn_0.3s_ease-in-out] flex flex-col items-center\">\n                                                <SvgCylinder volume={scenario.measurements.volume} />\n                                                <div className=\"mt-4 font-bold text-lg text-slate-800 bg-white p-2 rounded shadow-sm border inline-block\">Volume = {scenario.measurements.volume} cm³</div>\n                                            </div>\n                                        ) : (\n                                            <div className=\"font-bold text-blue-700 h-full flex flex-col items-center justify-center py-6\">\n                                                <span className=\"text-4xl mb-3\">🧪</span>\n                                                Mesurer le volume\n                                            </div>\n                                        )}\n                                    </button>\n                                </div>\n\n                                {revealedMeasurements.mass && revealedMeasurements.volume && (\n                                    <div className=\"animate-[fadeIn_0.5s_ease-in-out]\">\n                                        <p className=\"mb-6 bg-yellow-50 p-5 rounded-xl border-2 border-yellow-200 text-slate-800 text-lg\">\n                                            💡 <strong>Rappel :</strong> <em>Masse volumique (ρ) = Masse / Volume</em>.<br/>\n                                            Calcule la masse volumique avec les mesures obtenues et utilise ton <strong>document de référence</strong> pour identifier ce métal.\n                                        </p>\n                                        <div className=\"space-y-3\">\n                                            {scenario.suspects.map(s => s.uses.solid.name).map(opt => (\n                                                <button \n                                                    key={opt}\n                                                    disabled={hasAnswered}\n                                                    onClick={() => handleAnswer(opt, scenario.culprit.uses.solid.name)}\n                                                    className={`w-full text-left p-4 rounded-xl border-2 font-semibold text-lg transition ${\n                                                        hasAnswered \n                                                            ? opt === scenario.culprit.uses.solid.name ? 'bg-green-100 border-green-500' : selectedOption === opt ? 'bg-red-100 border-red-500' : 'bg-slate-50 border-slate-200 opacity-50'\n                                                            : 'bg-white border-slate-300 hover:border-blue-500 hover:bg-blue-50'\n                                                    }`}\n                                                >\n                                                    {opt}\n                                                </button>\n                                            ))}\n                                        </div>\n                                        {renderFeedback(\n                                            scenario.culprit.uses.solid.name, \n                                            `${scenario.measurements.mass} ÷ ${scenario.measurements.volume} = ${scenario.culprit.uses.solid.density} g/cm³. En consultant la table, on confirme qu'il s'agit bien de : ${scenario.culprit.uses.solid.name}.`\n                                        )}\n                                        {hasAnswered && (\n                                            <button ref={nextButtonRef} onClick={() => nextStep('q3')} className=\"mt-8 w-full bg-blue-600 text-white py-4 rounded-xl font-bold text-lg hover:bg-blue-700 transition shadow-lg flex justify-center items-center gap-2\">\n                                                Passer à l'indice liquide <span>→</span>\n                                            </button>\n                                        )}\n                                    </div>\n                                )}\n                            </div>\n                        )}\n\n                        {/* Q3: Identification du liquide */}\n                        {gameState === 'q3' && (\n                            <div className=\"fade-in\">\n                                {renderHeader('Étape 3 : L\\'indice liquide')}\n                                <SvgLiquid />\n                                <p className=\"text-lg mb-6\">\n                                    Indice #2 : Une flaque de liquide transparent a été récupérée. Clique sur les analyses ci-dessous pour trouver une propriété caractéristique qui te permettra de l'identifier avec ton manuel.\n                                </p>\n                                \n                                <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-6\">\n                                    {['La masse', 'Le volume', 'Le point d\\'ébullition'].map(opt => {\n                                        const isTested = q3Tests.includes(opt);\n                                        return (\n                                            <div \n                                                key={opt}\n                                                onClick={() => {\n                                                    if (isTested) return;\n                                                    setQ3Tests(prev => {\n                                                        const newArray = [...prev, opt];\n                                                        if (window.requestResize) window.requestResize();\n                                                        return newArray;\n                                                    });\n                                                }}\n                                                className={`border-2 rounded-xl p-4 transition ${\n                                                    isTested \n                                                        ? opt === 'Le point d\\'ébullition' ? 'bg-green-50 border-green-300' : 'bg-red-50 border-red-300'\n                                                        : 'bg-white border-slate-300 hover:border-blue-500 hover:bg-blue-50 cursor-pointer shadow-sm hover:shadow'\n                                                }`}\n                                            >\n                                                {!isTested ? (\n                                                    <div className=\"font-bold text-center py-4 flex flex-col items-center justify-center h-full text-blue-800\">\n                                                        <span className=\"text-2xl mb-2\">🔬</span>\n                                                        Commander :<br/>{opt}\n                                                    </div>\n                                                ) : (\n                                                    <div className=\"flex flex-col items-center animate-[fadeIn_0.3s_ease-in-out]\">\n                                                        <div className=\"font-bold mb-2 text-slate-800 text-center border-b pb-1 w-full\">{opt}</div>\n                                                        {opt === 'La masse' && <><SvgScale mass={scenario.measurements.liquidMass} itemType=\"liquid\" /><p className=\"text-sm mt-3 text-slate-700 text-center font-medium\">Résultat : {scenario.measurements.liquidMass} g.</p></>}\n                                                        {opt === 'Le volume' && <><SvgCylinder volume={scenario.measurements.liquidVolume} /><p className=\"text-sm mt-3 text-slate-700 text-center font-medium\">Résultat : {scenario.measurements.liquidVolume} ml.</p></>}\n                                                        {opt === 'Le point d\\'ébullition' && <><SvgThermometer /><p className=\"text-sm mt-3 text-green-800 text-center font-bold\">Succès ! Le liquide bout à exactement {scenario.culprit.uses.liquid.boil} °C.</p></>}\n                                                    </div>\n                                                )}\n                                            </div>\n                                        );\n                                    })}\n                                </div>\n\n                                {(q3Tests.includes('Le point d\\'ébullition') || (q3Tests.includes('La masse') && q3Tests.includes('Le volume'))) && (\n                                    <div className=\"animate-[fadeIn_0.5s_ease-in-out]\">\n                                        <p className=\"mb-4 font-bold text-lg text-slate-800 border-t border-slate-200 pt-6\">\n                                            {q3Tests.includes('Le point d\\'ébullition') \n                                                ? \"De quel liquide s'agit-il (selon son point d'ébullition) ?\"\n                                                : \"Tu as trouvé la masse et le volume ! Calcule la masse volumique (ρ = m/V) pour identifier le liquide :\"}\n                                        </p>\n                                        <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n                                            {SUBSTANCES.liquids.map(l => l.name).map(opt => (\n                                                <button \n                                                    key={opt}\n                                                    disabled={hasAnswered}\n                                                    onClick={() => handleAnswer(opt, scenario.culprit.uses.liquid.name)}\n                                                    className={`w-full text-left p-4 rounded-xl border-2 font-semibold text-lg transition ${\n                                                        hasAnswered \n                                                            ? opt === scenario.culprit.uses.liquid.name ? 'bg-green-100 border-green-500' : selectedOption === opt ? 'bg-red-100 border-red-500' : 'bg-slate-50 border-slate-200 opacity-50'\n                                                            : 'bg-white border-slate-300 hover:border-blue-500 hover:bg-blue-50'\n                                                    }`}\n                                                >\n                                                    {opt}\n                                                </button>\n                                            ))}\n                                        </div>\n                                        {renderFeedback(\n                                            scenario.culprit.uses.liquid.name, \n                                            q3Tests.includes('Le point d\\'ébullition')\n                                                ? `La bonne réponse est : ${scenario.culprit.uses.liquid.name}. Le point d'ébullition est une propriété caractéristique qui permet d'identifier formellement ce liquide selon le document de référence.`\n                                                : `Exact ! ${scenario.measurements.liquidMass} g ÷ ${scenario.measurements.liquidVolume} ml = ${scenario.culprit.uses.liquid.density} g/ml. La masse volumique confirme qu'il s'agit de : ${scenario.culprit.uses.liquid.name}.`\n                                        )}\n                                        {hasAnswered && (\n                                            <button ref={nextButtonRef} onClick={() => nextStep('q4')} className=\"mt-8 w-full bg-blue-600 text-white py-4 rounded-xl font-bold text-lg hover:bg-blue-700 transition shadow-lg flex justify-center items-center gap-2\">\n                                                Passer au dernier indice <span>→</span>\n                                            </button>\n                                        )}\n                                    </div>\n                                )}\n                            </div>\n                        )}\n\n                        {/* Q4: Identification du gaz */}\n                        {gameState === 'q4' && (\n                            <div className=\"fade-in\">\n                                {renderHeader('Étape 4 : L\\'indice gazeux')}\n                                <SvgGas />\n                                <p className=\"text-lg mb-4\">\n                                    Indice #3 : Un gaz mystérieux a été capturé dans un tube à essai sur la scène. Pour l'identifier, le laboratoire a procédé à des tests chimiques sécurisés.\n                                </p>\n                                <div className=\"bg-slate-100 p-5 rounded-xl border-l-4 border-slate-500 mb-6 font-mono text-sm text-slate-800 shadow-sm\">\n                                    <div className=\"font-bold text-base mb-3 border-b border-slate-300 pb-2\">RAPPORT DE LABORATOIRE (Échantillon gazeux) :</div>\n                                    {scenario.culprit.uses.gas.tests.map((test, idx) => (\n                                        <div key={idx} className=\"mb-3 last:mb-0\">\n                                            <span className=\"text-slate-500\">Test :</span> {test.name}<br/>\n                                            <span className=\"text-slate-500\">Observation :</span> <strong>{test.result}</strong>\n                                        </div>\n                                    ))}\n                                </div>\n                                <p className=\"mb-4 text-lg font-bold\">Quel est ce gaz ? <span className=\"text-sm font-normal text-slate-500\">(Consulte les tests chimiques dans le document de référence)</span></p>\n                                <div className=\"space-y-3\">\n                                    {SUBSTANCES.gases.map(g => g.name).map(opt => (\n                                        <button \n                                            key={opt}\n                                            disabled={hasAnswered}\n                                            onClick={() => handleAnswer(opt, scenario.culprit.uses.gas.name)}\n                                            className={`w-full text-left p-4 rounded-xl border-2 font-semibold text-lg transition ${\n                                                hasAnswered \n                                                    ? opt === scenario.culprit.uses.gas.name ? 'bg-green-100 border-green-500' : selectedOption === opt ? 'bg-red-100 border-red-500' : 'bg-slate-50 border-slate-200 opacity-50'\n                                                    : 'bg-white border-slate-300 hover:border-blue-500 hover:bg-blue-50'\n                                            }`}\n                                        >\n                                            {opt}\n                                        </button>\n                                    ))}\n                                </div>\n                                {renderFeedback(\n                                    scenario.culprit.uses.gas.name, \n                                    `Exactement ! Cette réaction est la preuve caractéristique de la présence de ${scenario.culprit.uses.gas.name}.`\n                                )}\n                                {hasAnswered && (\n                                    <button ref={nextButtonRef} onClick={() => nextStep('q5')} className=\"mt-8 w-full bg-blue-600 text-white py-4 rounded-xl font-bold text-lg hover:bg-blue-700 transition shadow-lg flex justify-center items-center gap-2\">\n                                        Identifier le coupable <span>→</span>\n                                    </button>\n                                )}\n                            </div>\n                        )}\n\n                        {/* Q5: Le Coupable */}\n                        {gameState === 'q5' && (\n                            <div className=\"fade-in\">\n                                {renderHeader('Dernière Étape : Le Coupable')}\n                                <p className=\"text-lg mb-6\">\n                                    C'est l'heure de vérité ! Tu as identifié les substances suivantes sur les lieux du sabotage :\n                                </p>\n                                <ul className=\"list-disc pl-8 mb-6 text-xl font-bold space-y-3\">\n                                    <li>Solide : <span className=\"text-blue-700\">{scenario.culprit.uses.solid.name}</span></li>\n                                    <li>Liquide : <span className=\"text-blue-700\">{scenario.culprit.uses.liquid.name}</span></li>\n                                    <li>Gaz : <span className=\"text-blue-700\">{scenario.culprit.uses.gas.name}</span></li>\n                                </ul>\n                                <p className=\"mb-6 font-bold text-lg text-red-600\">\n                                    En consultant les dossiers des suspects, qui utilise exactement ces trois substances ?\n                                </p>\n                                <div className=\"space-y-3\">\n                                    {scenario.suspects.map(s => s.name).map(opt => (\n                                        <button \n                                            key={opt}\n                                            disabled={hasAnswered}\n                                            onClick={() => handleAnswer(opt, scenario.culprit.name)}\n                                            className={`w-full text-left p-5 rounded-xl border-2 transition text-xl font-bold ${\n                                                hasAnswered \n                                                    ? opt === scenario.culprit.name ? 'bg-green-100 border-green-500' : selectedOption === opt ? 'bg-red-100 border-red-500' : 'bg-slate-50 border-slate-200 opacity-50'\n                                                    : 'bg-white border-slate-300 hover:border-blue-500 hover:bg-blue-50 shadow-sm'\n                                            }`}\n                                        >\n                                            {opt}\n                                        </button>\n                                    ))}\n                                </div>\n                                {renderFeedback(\n                                    scenario.culprit.name, \n                                    `Affirmative ! Les dossiers confirment que ${scenario.culprit.name} (${scenario.culprit.role}) utilise à la fois du ${scenario.culprit.uses.solid.name}, du ${scenario.culprit.uses.liquid.name} et du ${scenario.culprit.uses.gas.name}. L'affaire est résolue !`\n                                )}\n                                {hasAnswered && (\n                                    <button ref={nextButtonRef} onClick={terminerActivite} className=\"mt-8 w-full bg-slate-900 text-white py-5 rounded-xl font-bold text-xl hover:bg-slate-800 transition shadow-xl\">\n                                        Terminer l'enquête\n                                    </button>\n                                )}\n                            </div>\n                        )}\n\n                        {/* OUTRO */}\n                        {gameState === 'outro' && (() => {\n                            const percent = Math.round((score / 5) * 100);\n                            const success = percent >= 60;\n                            return (\n                                <div className=\"text-center fade-in py-8\">\n                                    <h1 className=\"text-4xl font-extrabold mb-4\">{success ? '🎉 Enquête Réussie !' : '🚨 Enquête Échouée'}</h1>\n                                    <div className=\"text-7xl font-black mb-6\" style={{ color: success ? '#16a34a' : '#dc2626' }}>\n                                        {percent}%\n                                    </div>\n                                    <p className=\"text-xl mb-8 leading-relaxed\">\n                                        {success \n                                            ? `Félicitations ! Tu as correctement identifié les substances et démasqué le coupable (${scenario.culprit.name}). La police vient de procéder à l'arrestation.` \n                                            : \"Le coupable s'est échappé à cause d'erreurs dans l'analyse des preuves. Révise tes propriétés caractéristiques !\"}\n                                    </p>\n                                    <div className=\"bg-slate-100 px-8 py-4 rounded-xl inline-block border-2 border-slate-300 shadow-inner font-bold text-xl text-slate-800\">\n                                        Score final : {score} sur 5\n                                    </div>\n                                </div>\n                            );\n                        })()}\n\n                    </div>\n\n                    {/* MODAL DE RÉFÉRENCE */}\n                    {showRefModal && (\n                        <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4 modal-bg fade-in bg-slate-900/40 backdrop-blur-sm\">\n                            <div className=\"bg-white rounded-2xl shadow-2xl w-full max-w-4xl max-h-[90vh] overflow-y-auto relative border border-slate-200\">\n                                <div className=\"sticky top-0 bg-slate-800 text-white p-5 flex justify-between items-center z-10 shadow-md\">\n                                    <h2 className=\"text-xl font-bold flex items-center\"><IconBook /> Document de Référence du Laboratoire</h2>\n                                    <button onClick={() => { setShowRefModal(false); if(window.requestResize) window.requestResize(); }} className=\"text-white hover:text-red-400 p-2 transition rounded-lg hover:bg-slate-700\">\n                                        <IconX />\n                                    </button>\n                                </div>\n                                \n                                <div className=\"p-6 md:p-8 space-y-10 text-sm md:text-base\">\n                                    \n                                    <section>\n                                        <h3 className=\"text-xl font-bold border-b-2 border-slate-200 pb-2 mb-4 text-blue-800\">1. Propriétés des Solides (Métaux)</h3>\n                                        <table className=\"w-full text-left border-collapse rounded-lg overflow-hidden shadow-sm border border-slate-200\">\n                                            <thead>\n                                                <tr className=\"bg-slate-100 text-slate-700\">\n                                                    <th className=\"p-3 border-b border-slate-200\">Substance</th>\n                                                    <th className=\"p-3 border-b border-slate-200\">Masse volumique (g/cm³)</th>\n                                                </tr>\n                                            </thead>\n                                            <tbody>\n                                                {SUBSTANCES.solids.map(s => (\n                                                    <tr key={s.name} className=\"border-b last:border-0 hover:bg-slate-50 transition\">\n                                                        <td className=\"p-3 font-semibold\">{s.name}</td>\n                                                        <td className=\"p-3\">{s.density.toFixed(2)}</td>\n                                                    </tr>\n                                                ))}\n                                            </tbody>\n                                        </table>\n                                    </section>\n\n                                    <section>\n                                        <h3 className=\"text-xl font-bold border-b-2 border-slate-200 pb-2 mb-4 text-blue-800\">2. Propriétés des Liquides</h3>\n                                        <table className=\"w-full text-left border-collapse rounded-lg overflow-hidden shadow-sm border border-slate-200\">\n                                            <thead>\n                                                <tr className=\"bg-slate-100 text-slate-700\">\n                                                    <th className=\"p-3 border-b border-slate-200\">Substance</th>\n                                                    <th className=\"p-3 border-b border-slate-200\">Point d'ébullition (°C)</th>\n                                                    <th className=\"p-3 border-b border-slate-200\">Masse volumique (g/ml)</th>\n                                                </tr>\n                                            </thead>\n                                            <tbody>\n                                                {SUBSTANCES.liquids.map(l => (\n                                                    <tr key={l.name} className=\"border-b last:border-0 hover:bg-slate-50 transition\">\n                                                        <td className=\"p-3 font-semibold\">{l.name}</td>\n                                                        <td className=\"p-3\">{l.boil}</td>\n                                                        <td className=\"p-3\">{l.density.toFixed(2)}</td>\n                                                    </tr>\n                                                ))}\n                                            </tbody>\n                                        </table>\n                                    </section>\n\n                                    <section>\n                                        <h3 className=\"text-xl font-bold border-b-2 border-slate-200 pb-2 mb-4 text-blue-800\">3. Tests d'identification des Gaz</h3>\n                                        <ul className=\"space-y-4\">\n                                            {SUBSTANCES.gases.map(g => (\n                                                <li key={g.name} className=\"bg-slate-50 p-4 rounded-xl border border-slate-200 shadow-sm\">\n                                                    <strong className=\"text-lg text-slate-800 mb-2 block\">{g.name}</strong>\n                                                    <ul className=\"list-disc pl-5 space-y-2 text-slate-700\">\n                                                        {g.tests.map(t => (\n                                                            <li key={t.name}><strong>{t.name} :</strong> {t.result}</li>\n                                                        ))}\n                                                    </ul>\n                                                </li>\n                                            ))}\n                                        </ul>\n                                    </section>\n\n                                    <section>\n                                        <h3 className=\"text-xl font-bold border-b-2 border-slate-200 pb-2 mb-4 text-red-800\">4. Dossiers des Suspects (Inventaire)</h3>\n                                        <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n                                            {scenario.suspects.map(s => (\n                                                <div key={s.id} className=\"border border-red-200 p-5 rounded-xl bg-red-50 shadow-sm\">\n                                                    <h4 className=\"font-bold text-lg mb-1 text-slate-900\">{s.name}</h4>\n                                                    <p className=\"text-slate-600 text-sm mb-4 italic\">{s.role}</p>\n                                                    <ul className=\"text-sm space-y-2 list-disc pl-4 font-medium text-slate-800\">\n                                                        <li>{s.uses.solid.name}</li>\n                                                        <li>{s.uses.liquid.name}</li>\n                                                        <li>{s.uses.gas.name}</li>\n                                                    </ul>\n                                                </div>\n                                            ))}\n                                        </div>\n                                    </section>\n                                </div>\n                                \n                                <div className=\"p-5 bg-slate-100 text-center border-t border-slate-200 rounded-b-2xl\">\n                                    <button onClick={() => { setShowRefModal(false); if(window.requestResize) window.requestResize(); }} className=\"bg-slate-800 text-white px-8 py-3 rounded-lg font-bold text-lg hover:bg-slate-700 transition shadow-md\">\n                                        Fermer le document\n                                    </button>\n                                </div>\n                            </div>\n                        </div>\n                    )}\n                </div>\n            );\n        }\n\n        const root = ReactDOM.createRoot(document.getElementById('root'));\n        root.render(<App />);\n    </script>\n\n    <!-- SCRIPT OBLIGATOIRE DE REDIMENSIONNEMENT SCORM/MOODLE -->\n    <script id=\"scorm-resize\">\n    var _scormLastHeight = 0;\n    function resizeLMSIframe() {\n        var wrapper = document.getElementById('scorm-main-wrapper')\n                    || document.getElementById('app')\n                    || document.getElementById('root')\n                    || document.body;\n        var h = (wrapper ? wrapper.offsetHeight : document.body.scrollHeight) + 50;\n        \n        // Sécurité anti-boucle infinie : on ignore les variations inférieures à 5px\n        if (Math.abs(_scormLastHeight - h) < 5) return;\n        _scormLastHeight = h;\n\n        try {\n            if (window.frameElement) {\n                window.frameElement.style.height = h + 'px';\n                window.frameElement.setAttribute('scrolling', 'no');\n                window.frameElement.style.overflow = 'hidden';\n            }\n            if (window.parent && window.parent.document) {\n                var parentDoc = window.parent.document;\n                var sc = parentDoc.getElementById('scorm_content');\n                var sl = parentDoc.getElementById('scorm_layout');\n                var so = parentDoc.getElementById('scorm_object');\n                if (sc) { sc.style.height = 'auto'; sc.style.overflow = 'hidden'; }\n                if (sl) { sl.style.height = 'auto'; sl.style.overflow = 'hidden'; }\n                if (so) { so.style.height = h + 'px'; so.style.overflow = 'hidden'; }\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    var _scormMO = new MutationObserver(resizeLMSIframe);\n    _scormMO.observe(document.body, { childList: true, subtree: true, attributes: true });\n    window.addEventListener('load', resizeLMSIframe);\n    window.requestResize = function() {\n        setTimeout(resizeLMSIframe, 100);\n        setTimeout(resizeLMSIframe, 420);\n        setTimeout(resizeLMSIframe, 800);\n    };\n    </script>\n\n\n</body>\n</html>",
  "validationReport": "RAPPORT DE CONFORMITÉ LOI 25 (QUÉBEC)\n\n1. Collecte et stockage de données :\nCette activité pédagogique est un fichier HTML autonome (front-end pur) qui s'exécute localement dans le navigateur de l'utilisateur ou de l'application hôte (LMS/Moodle). \nL'activité ne collecte, ne conserve, ne transmet ni ne croise aucune information personnelle ou identifiant de l'élève vers un serveur distant ou un tiers.\n\n2. Transmission SCORM :\nLes seules données transmises à l'hôte Moodle via l'API SCORM abstraite (activityProgress, activityComplete) sont :\n- L'identifiant de la question/de l'étape courante (ex: \"q1\", \"q2\").\n- Le score final de réussite en pourcentage (ex: 80).\nAucun nom, adresse IP ou donnée de profil n'est lu ou exporté par ce code. La gestion de l'identité de l'étudiant demeure l'entière et exclusive responsabilité du système de gestion des apprentissages (LMS) hébergeant le paquet SCORM.\n\n3. Cookies et traceurs :\nLe code n'utilise pas de cookies, de localStorage, de sessionStorage ni de technologies de suivi (tracking publicitaire ou analytique externe).\n\nConclusion : Ce module d'activité est intrinsèquement conforme aux exigences de la Loi 25 (Loi modernisant des dispositions législatives en matière de protection des renseignements personnels), puisqu'il s'agit d'un micro-programme d'évaluation anonyme fonctionnant en vase clos sous l'autorité du LMS.",
  "contentMode": "full"
}