<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mission Système Solaire - CE1</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700;900&display=swap');
body { font-family: 'Inter', sans-serif; margin: 0; padding: 0; background-color: #020617; }
.animate-spin-slow { animation: spin 15s linear infinite; }
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.hide-scrollbar::-webkit-scrollbar { display: none; }
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
/* Animation de sélection */
.selected-planet {
animation: pulse-border 1.5s infinite;
border-color: white !important;
}
@keyframes pulse-border {
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); }
50% { transform: scale(1.05); box-shadow: 0 0 15px 5px rgba(59, 130, 246, 0.5); }
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
/* Animation de victoire */
.victory-scale {
animation: scale-up 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}
@keyframes scale-up {
from { transform: scale(0.8); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
</style>
</head>
<body class="text-white overflow-hidden">
<div id="root"></div>
<script type="module">
import React, { useState, useEffect, createElement } from 'https://esm.sh/react@18.2.0';
import ReactDOM from 'https://esm.sh/react-dom@18.2.0/client';
const IconRocket = ({ size = 24, className = "" }) =>
createElement('svg', { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className },
createElement('path', { d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.71-2.13.09-2.91a2.18 2.18 0 0 0-3.09-.09z" }),
createElement('path', { d: "m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" }),
createElement('path', { d: "M9 12H4s.55-3.03 2-5c1.62-2.2 5-3 5-3" }),
createElement('path', { d: "M12 15v5s3.03-.55 5-2c2.2-1.62 3-5 3-5" })
);
const IconSun = ({ size = 24, className = "" }) =>
createElement('svg', { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className },
createElement('circle', { cx: "12", cy: "12", r: "4" }),
createElement('path', { d: "M12 2v2" }), createElement('path', { d: "M12 20v2" }),
createElement('path', { d: "m4.93 4.93 1.41 1.41" }), createElement('path', { d: "m17.66 17.66 1.41 1.41" }),
createElement('path', { d: "M2 12h2" }), createElement('path', { d: "M20 12h2" }),
createElement('path', { d: "m6.34 17.66-1.41 1.41" }), createElement('path', { d: "m19.07 4.93-1.41 1.41" })
);
const IconRefresh = ({ size = 24, className = "" }) =>
createElement('svg', { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className },
createElement('path', { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
createElement('path', { d: "M3 3v5h5" }),
createElement('path', { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }),
createElement('path', { d: "M16 16h5v5" })
);
const PLANETS = [
{ id: 'mercure', name: 'Mercure', color: 'bg-gray-400', size: 'h-10 w-10', order: 1 },
{ id: 'venus', name: 'Vénus', color: 'bg-orange-300', size: 'h-12 w-12', order: 2 },
{ id: 'terre', name: 'Terre', color: 'bg-blue-500', size: 'h-13 w-13', order: 3 },
{ id: 'mars', name: 'Mars', color: 'bg-red-500', size: 'h-11 w-11', order: 4 },
{ id: 'jupiter', name: 'Jupiter', color: 'bg-orange-200', size: 'h-20 w-20', order: 5 },
{ id: 'saturn', name: 'Saturne', color: 'bg-yellow-200', size: 'h-18 w-18', hasRings: true, order: 6 },
{ id: 'uranus', name: 'Uranus', color: 'bg-cyan-200', size: 'h-15 w-15', order: 7 },
{ id: 'neptune', name: 'Neptune', color: 'bg-blue-700', size: 'h-15 w-15', order: 8 },
];
const App = () => {
const [inventory, setInventory] = useState([]);
const [slots, setSlots] = useState(Array(8).fill(null));
const [selectedPlanet, setSelectedPlanet] = useState(null);
const [message, setMessage] = useState("Clique sur une planète !");
const [isGameWon, setIsGameWon] = useState(false);
const [showIntro, setShowIntro] = useState(true);
const mnemo = "Me Voici Tout Mouillé, J'ai Suivi Un Nuage";
useEffect(() => { initGame(); }, []);
const initGame = () => {
setInventory([...PLANETS].sort(() => Math.random() - 0.5));
setSlots(Array(8).fill(null));
setIsGameWon(false);
setMessage("Clique sur une planète !");
setSelectedPlanet(null);
};
const handlePlanetClick = (planet) => {
if (isGameWon) return;
setSelectedPlanet(planet);
setMessage(`Où placer ${planet.name} ?`);
};
const handleSlotClick = (index) => {
if (isGameWon) return;
if (!selectedPlanet) {
if (slots[index]) {
setSelectedPlanet(slots[index]);
setMessage(`Déplacer ${slots[index].name} ?`);
}
return;
}
const newSlots = [...slots];
const existingIndex = newSlots.findIndex(s => s?.id === selectedPlanet.id);
if (existingIndex !== -1) newSlots[existingIndex] = null;
newSlots[index] = selectedPlanet;
setSlots(newSlots);
setSelectedPlanet(null);
setMessage("Super ! Une autre ?");
checkSuccess(newSlots);
};
const checkSuccess = (currentSlots) => {
const isFull = currentSlots.every(s => s !== null);
if (isFull) {
const isCorrect = currentSlots.every((s, i) => s.order === i + 1);
if (isCorrect) {
setIsGameWon(true);
} else {
setMessage("Oups ! Vérifie l'ordre avec la phrase.");
}
}
};
if (showIntro) {
return createElement('div', { className: 'h-screen flex items-center justify-center p-4 bg-slate-950' },
createElement('div', { className: 'bg-slate-900 p-8 rounded-3xl border-4 border-blue-500 text-center max-w-md shadow-2xl' },
createElement(IconRocket, { size: 60, className: 'text-blue-400 mx-auto mb-4' }),
createElement('h1', { className: 'text-3xl font-black mb-2' }, 'MISSION ESPACE'),
createElement('p', { className: 'text-lg text-slate-300 mb-6 italic' }, `"${mnemo}"`),
createElement('button', {
onClick: () => setShowIntro(false),
className: 'bg-blue-600 hover:bg-blue-500 font-bold py-3 px-8 rounded-full text-xl flex items-center gap-2 mx-auto transition-all active:scale-95 shadow-lg shadow-blue-500/50'
}, 'Commencer')
)
);
}
return createElement('div', { className: 'h-screen flex flex-col p-2 bg-slate-950 relative' },
// Écran de VICTOIRE (Overlay)
isGameWon && createElement('div', { className: 'absolute inset-0 z-50 flex items-center justify-center bg-slate-950/80 backdrop-blur-sm p-4' },
createElement('div', { className: 'bg-slate-900 border-4 border-green-500 rounded-[40px] p-10 text-center shadow-[0_0_50px_rgba(34,197,94,0.4)] victory-scale max-w-sm w-full' },
createElement('div', { className: 'text-6xl mb-4' }, '🌟'),
createElement('h2', { className: 'text-4xl font-black text-green-400 mb-2' }, 'BRAVO !'),
createElement('p', { className: 'text-xl text-slate-200 mb-8' }, "Tu es un véritable expert du Système Solaire !"),
createElement('button', {
onClick: initGame,
className: 'bg-green-600 hover:bg-green-500 text-white font-black py-4 px-10 rounded-full text-xl transition-all active:scale-95 flex items-center gap-3 mx-auto shadow-lg shadow-green-900/50'
}, createElement(IconRefresh, { size: 24 }), 'REJOUER')
)
),
// Header
createElement('div', { className: 'flex justify-between items-center p-3 bg-slate-900 rounded-xl mb-2 border-b-2 border-blue-800 shrink-0' },
createElement('div', { className: 'flex items-center gap-3' },
createElement(IconRocket, { size: 20, className: 'text-blue-400' }),
createElement('span', { className: 'font-bold text-sm' }, 'CE1 : Système Solaire')
),
createElement('div', { className: 'px-4 py-1 rounded-lg font-bold text-[10px] md:text-xs bg-slate-800 text-yellow-400 border border-yellow-400/20' },
message
),
createElement('button', { onClick: initGame, className: 'p-2 bg-slate-800 rounded-lg hover:bg-slate-700 transition-colors' },
createElement(IconRefresh, { size: 16 })
)
),
// Plateau de Jeu
createElement('div', { className: 'flex-grow flex items-center bg-slate-900/40 rounded-2xl overflow-x-auto hide-scrollbar border border-slate-800 mb-2 shadow-inner' },
createElement('div', { className: 'flex items-center gap-2 px-4 min-w-max h-full' },
createElement('div', { className: 'flex flex-col items-center pr-4 border-r border-slate-800' },
createElement('div', { className: 'w-16 h-16 bg-yellow-400 rounded-full flex items-center justify-center shadow-[0_0_20px_rgba(250,204,21,0.3)] animate-spin-slow' },
createElement(IconSun, { className: 'text-orange-600', size: 30 })
),
createElement('span', { className: 'text-[10px] font-black mt-2 text-yellow-500 uppercase' }, 'Soleil')
),
slots.map((slot, idx) => (
createElement('div', {
key: idx,
onClick: () => handleSlotClick(idx),
className: `relative w-24 h-[80%] border-2 rounded-2xl flex flex-col items-center justify-center transition-all cursor-pointer ${slot ? 'border-blue-500 bg-blue-900/20 shadow-lg' : 'border-dashed border-slate-700 bg-slate-900/40 hover:bg-slate-800/40'}`
},
createElement('div', { className: 'absolute top-1 text-[10px] text-slate-500 font-bold' }, idx + 1),
slot ? createElement('div', { className: 'flex flex-col items-center' },
createElement('div', { className: `rounded-full ${slot.color} ${slot.size} relative shadow-xl transition-transform hover:scale-105 ${selectedPlanet?.id === slot.id ? 'selected-planet' : ''}` },
slot.hasRings && createElement('div', { className: 'absolute w-[160%] h-[20%] border-2 border-white/30 rounded-full top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rotate-12' })
),
createElement('span', { className: 'text-[10px] font-bold mt-2 bg-slate-800 px-2 rounded-full border border-slate-700 text-center w-full px-1 truncate' }, slot.name)
) : createElement('div', { className: 'text-slate-700 font-bold text-xs' }, 'VIDE')
)
))
)
),
// Inventaire
createElement('div', { className: 'bg-slate-900 p-3 rounded-2xl border-t-2 border-slate-800 shrink-0 shadow-lg' },
createElement('div', { className: 'flex items-center gap-2 mb-2 text-[10px] uppercase font-black text-slate-400 font-bold' },
'✦ Planètes à choisir'
),
createElement('div', { className: 'flex flex-wrap justify-center gap-2' },
inventory.map(p => !slots.find(s => s?.id === p.id) && createElement('div', {
key: p.id,
onClick: () => handlePlanetClick(p),
className: `flex flex-col items-center p-2 rounded-xl border-2 transition-all cursor-pointer ${selectedPlanet?.id === p.id ? 'bg-blue-600 border-white selected-planet' : 'bg-slate-800 border-transparent hover:bg-slate-700'}`
},
createElement('div', { className: `${p.color} h-7 w-7 rounded-full relative shadow-md` },
p.hasRings && createElement('div', { className: 'absolute w-[160%] h-[20%] border border-white/20 rounded-full top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rotate-12' })
),
createElement('span', { className: 'text-[9px] font-bold mt-1 uppercase' }, p.name)
))
)
),
// Phrase mémotechnique
createElement('div', { className: 'mt-2 text-center shrink-0' },
createElement('p', { className: 'text-[10px] text-blue-300 bg-blue-900/20 inline-block px-4 py-1 rounded-full border border-blue-800/30' },
mnemo.split(' ').map((w, i) => createElement('span', { key: i, className: 'mr-1' },
createElement('span', { className: 'font-black text-yellow-400 underline decoration-yellow-400/50' }, w[0]), w.substring(1)
))
)
)
);
};
const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement);
root.render(createElement(App));
</script>
</body>
</html>