Insecte / index.html
Enoder's picture
Update index.html
54919a9 verified
Raw History Blame Contribute Delete
35.1 kB
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Devine l'Insecte | Jeu Géographique</title> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> <link href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=Source+Sans+3:wght@300;400;600&display=swap" rel="stylesheet"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --sepia: #f4f1e8; --dark-sepia: #3d3526; --accent-green: #4a7c59; --accent-gold: #d4a574; --shadow: rgba(61, 53, 38, 0.15); --border: rgba(61, 53, 38, 0.2); } body { font-family: 'Source Sans 3', sans-serif; background: linear-gradient(135deg, #f4f1e8 0%, #e8e3d6 100%); color: var(--dark-sepia); overflow-x: hidden; min-height: 100vh; } body::before { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-image: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px), repeating-linear-gradient(90deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px); pointer-events: none; z-index: 1; opacity: 0.3; } .container { max-width: 1400px; margin: 0 auto; padding: 2rem; position: relative; z-index: 2; } header { text-align: center; margin-bottom: 3rem; animation: fadeInDown 1s ease; } h1 { font-family: 'Crimson Pro', serif; font-size: 3.5rem; font-weight: 700; color: var(--accent-green); letter-spacing: -0.02em; margin-bottom: 0.5rem; text-shadow: 2px 2px 4px rgba(0,0,0,0.1); } .subtitle { font-size: 1.1rem; color: var(--dark-sepia); opacity: 0.8; font-style: italic; } .stats-bar { display: flex; justify-content: center; gap: 2rem; margin-top: 1rem; font-size: 0.95rem; color: var(--dark-sepia); opacity: 0.7; } .game-container { display: grid; grid-template-columns: 1fr 400px; gap: 2rem; animation: fadeInUp 1s ease 0.2s both; } .map-panel { background: white; border-radius: 16px; box-shadow: 0 10px 40px var(--shadow), inset 0 0 0 1px var(--border); overflow: hidden; position: relative; } .map-header { background: linear-gradient(135deg, var(--accent-green) 0%, #5a8c69 100%); color: white; padding: 1.5rem 2rem; font-family: 'Crimson Pro', serif; font-size: 1.4rem; font-weight: 600; letter-spacing: 0.02em; display: flex; justify-content: space-between; align-items: center; } .map-controls { display: flex; gap: 0.5rem; } .map-type-btn { background: rgba(255, 255, 255, 0.2); border: 2px solid rgba(255, 255, 255, 0.3); color: white; padding: 0.5rem 1rem; border-radius: 6px; font-family: 'Source Sans 3', sans-serif; font-size: 0.85rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; } .map-type-btn:hover { background: rgba(255, 255, 255, 0.3); border-color: rgba(255, 255, 255, 0.5); } .map-type-btn.active { background: white; color: var(--accent-green); border-color: white; } #map { height: 600px; width: 100%; background: #a8c5d9; } .control-panel { background: white; border-radius: 16px; box-shadow: 0 10px 40px var(--shadow), inset 0 0 0 1px var(--border); padding: 2rem; display: flex; flex-direction: column; gap: 1.5rem; max-height: 800px; overflow-y: auto; } .score-display { background: linear-gradient(135deg, #f8f6f0 0%, #ede9dc 100%); padding: 1.5rem; border-radius: 10px; text-align: center; border: 2px solid var(--border); position: sticky; top: 0; z-index: 10; } .score-label { font-family: 'Crimson Pro', serif; font-size: 0.9rem; color: var(--dark-sepia); opacity: 0.7; text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.5rem; } .score-value { font-size: 2.5rem; font-weight: 700; color: var(--accent-green); font-family: 'Crimson Pro', serif; } .answer-input-section { display: flex; flex-direction: column; gap: 1rem; } .answer-input-section label { font-family: 'Crimson Pro', serif; font-size: 1.1rem; font-weight: 600; color: var(--accent-green); } .input-wrapper { position: relative; } #species-input { width: 100%; padding: 1rem; border: 2px solid var(--border); border-radius: 10px; font-family: 'Crimson Pro', serif; font-size: 1rem; background: var(--sepia); color: var(--dark-sepia); transition: all 0.3s ease; } #species-input:focus { outline: none; border-color: var(--accent-green); background: white; box-shadow: 0 4px 12px var(--shadow); } .autocomplete-dropdown { position: absolute; top: 100%; left: 0; right: 0; background: white; border: 2px solid var(--accent-green); border-top: none; border-radius: 0 0 10px 10px; max-height: 300px; overflow-y: auto; z-index: 1000; box-shadow: 0 8px 16px var(--shadow); } .autocomplete-item { padding: 0.75rem 1rem; cursor: pointer; transition: background 0.2s ease; border-bottom: 1px solid var(--border); } .autocomplete-item:last-child { border-bottom: none; } .autocomplete-item:hover, .autocomplete-item.selected { background: var(--sepia); } .autocomplete-item strong { color: var(--accent-green); display: block; margin-bottom: 0.25rem; } .autocomplete-item em { color: var(--dark-sepia); opacity: 0.7; font-size: 0.9rem; } .submit-btn { background: linear-gradient(135deg, var(--accent-green) 0%, #5a8c69 100%); color: white; border: none; padding: 1rem 1.5rem; border-radius: 10px; font-family: 'Crimson Pro', serif; font-size: 1.1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(74, 124, 89, 0.3); } .submit-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(74, 124, 89, 0.4); } .submit-btn:disabled { opacity: 0.5; cursor: not-allowed; } .hints-section { border-top: 2px solid var(--border); padding-top: 1.5rem; } .hint-btn { background: linear-gradient(135deg, var(--accent-gold) 0%, #c49564 100%); color: white; border: none; padding: 1rem 1.5rem; border-radius: 10px; font-family: 'Crimson Pro', serif; font-size: 1.1rem; font-weight: 600; cursor: pointer; width: 100%; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(212, 165, 116, 0.3); } .hint-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(212, 165, 116, 0.4); } .hint-btn:disabled { opacity: 0.5; cursor: not-allowed; } .hints-display { margin-top: 1rem; display: flex; flex-direction: column; gap: 0.75rem; } .hint-item { background: #fff9f0; border-left: 4px solid var(--accent-gold); padding: 1rem; border-radius: 6px; font-size: 0.95rem; line-height: 1.6; animation: slideInRight 0.4s ease; } .hint-label { font-weight: 600; color: var(--accent-green); margin-bottom: 0.25rem; } .next-btn { background: var(--accent-green); color: white; border: none; padding: 1rem 1.5rem; border-radius: 10px; font-family: 'Crimson Pro', serif; font-size: 1.1rem; font-weight: 600; cursor: pointer; width: 100%; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(74, 124, 89, 0.3); } .next-btn:hover { background: #5a8c69; transform: translateY(-2px); box-shadow: 0 6px 20px rgba(74, 124, 89, 0.4); } .result-message { padding: 1.5rem; border-radius: 10px; text-align: center; font-family: 'Crimson Pro', serif; font-size: 1.2rem; font-weight: 600; animation: fadeIn 0.5s ease; } .result-message.correct { background: rgba(74, 124, 89, 0.1); color: var(--accent-green); border: 2px solid var(--accent-green); } .result-message.incorrect { background: rgba(197, 74, 74, 0.1); color: #c54a4a; border: 2px solid #c54a4a; } @keyframes fadeInDown { from { opacity: 0; transform: translateY(-30px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideInRight { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @media (max-width: 1024px) { .game-container { grid-template-columns: 1fr; } h1 { font-size: 2.5rem; } #map { height: 500px; } } .leaflet-control-attribution { background: rgba(255, 255, 255, 0.8) !important; font-size: 0.7rem !important; } </style> </head> <body> <div class="container"> <header> <h1>🦗 Devine l'Insecte</h1> <p class="subtitle">Identifie l'espèce selon sa distribution géographique</p> <div class="stats-bar"> <span>📊 <span id="total-species">22</span> espèces disponibles</span> </div> </header> <div class="game-container"> <div class="map-panel"> <div class="map-header"> <span>Distribution Mondiale des Occurrences</span> <div class="map-controls"> <button class="map-type-btn active" data-map="standard">Standard</button> <button class="map-type-btn" data-map="dark">Sombre</button> <button class="map-type-btn" data-map="satellite">Satellite</button> </div> </div> <div id="map"></div> </div> <div class="control-panel"> <div class="score-display"> <div class="score-label">Score</div> <div class="score-value" id="score">0</div> </div> <div id="result-container"></div> <div class="answer-input-section"> <label for="species-input">Quelle est cette espèce ?</label> <div class="input-wrapper"> <input type="text" id="species-input" placeholder="Tapez le nom de l'espèce..." autocomplete="off" /> <div id="autocomplete-dropdown" class="autocomplete-dropdown" style="display: none;"></div> </div> <button class="submit-btn" id="submit-btn"> Valider ma réponse </button> </div> <div class="hints-section"> <button class="hint-btn" id="hint-btn"> 💡 Demander un indice </button> <div class="hints-display" id="hints-display"></div> </div> <button class="next-btn" id="next-btn" style="display: none;"> Mante Suivante → </button> </div> </div> </div> <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <script> // Complete species database with verified GBIF taxonKeys const speciesData = [ { name: "Phasma gigas", commonName: "Phasme géant", taxonKey: "5049821", family: "Phasmatidae", region: "Asie du Sud-Est", hints: [ "Famille : Phasmatidae", "Distribution : Asie du Sud-Est", "Un des plus grands phasmes au monde, peut atteindre 30 cm de longueur" ] }, { name: "Macromantis hyalina", commonName: "Mante hyaline", taxonKey: "1405821", family: "Mantidae", region: "Amérique du Sud", hints: [ "Famille : Mantidae", "Distribution : Amérique du Sud", "Grande mante aux ailes transparentes, typique des forêts tropicales" ] }, { name: "Blepharopsis mendica", commonName: "Mante diable", taxonKey: "1406697", family: "Empusidae", region: "Afrique du Nord, Moyen-Orient", hints: [ "Famille : Empusidae", "Distribution : Afrique du Nord et Moyen-Orient", "Mante du désert avec des yeux spectaculaires et des motifs colorés" ] }, { name: "Creobroter gemmatus", commonName: "Mante fleur indienne", taxonKey: "1406395", family: "Hymenopodidae", region: "Asie du Sud", hints: [ "Famille : Hymenopodidae", "Distribution : Inde, Asie du Sud", "Petite mante colorée avec taches oculaires vertes sur les ailes" ] }, { name: "Hymenopus coronatus", commonName: "Mante orchidée", taxonKey: "1406471", family: "Hymenopodidae", region: "Asie du Sud-Est", hints: [ "Famille : Hymenopodidae", "Distribution : Asie du Sud-Est (Malaisie, Indonésie)", "Célèbre pour son mimétisme d'orchidée, une des plus belles mantes au monde" ] }, { name: "Callibia diana", commonName: "Mante de Diana", taxonKey: "1404244", family: "Nanomantidae", region: "Afrique", hints: [ "Famille : Nanomantidae", "Distribution : Afrique tropicale", "Petite mante aux motifs contrastés noir et blanc" ] }, { name: "Polyspilota aeruginosa", commonName: "Mante cuivrée", taxonKey: "1405481", family: "Mantidae", region: "Afrique subsaharienne", hints: [ "Famille : Mantidae", "Distribution : Afrique subsaharienne", "Coloration vert-cuivré caractéristique, espèce robuste" ] }, { name: "Argema mimosae", commonName: "Papillon lune africain", taxonKey: "1867009", family: "Saturniidae", region: "Afrique australe", hints: [ "Famille : Saturniidae", "Distribution : Afrique australe", "Magnifique papillon de nuit avec de longues queues sur les ailes" ] }, { name: "Acontista mexicana", commonName: "Mante mexicaine", taxonKey: "1404204", family: "Acontistidae", region: "Amérique centrale", hints: [ "Famille : Acontistidae", "Distribution : Amérique centrale, notamment Mexique", "Petite mante discrète vivant dans les zones arides mexicaines" ] }, { name: "Prohierodula flavipennis", commonName: "Mante à ailes jaunes", taxonKey: "1406032", family: "Mantidae", region: "Asie du Sud-Est", hints: [ "Famille : Mantidae", "Distribution : Asie du Sud-Est", "Ailes postérieures jaune vif, espèce de taille moyenne" ] }, { name: "Armadillidium werneri", commonName: "Cloporte de Werner", taxonKey: "2203862", family: "Armadillidiidae", region: "Europe", hints: [ "Famille : Armadillidiidae", "Distribution : Europe", "Petit crustacé terrestre capable de se rouler en boule" ] }, { name: "Carausius morosus", commonName: "Phasme bâton indien", taxonKey: "1411953", family: "Lonchodidae", region: "Inde", hints: [ "Famille : Lonchodidae", "Distribution : Inde", "Phasme très populaire en élevage, reproduction par parthénogenèse" ] }, { name: "Goliathus goliatus", commonName: "Goliath géant", taxonKey: "1076779", family: "Scarabaeidae", region: "Afrique équatoriale", hints: [ "Famille : Scarabaeidae", "Distribution : Afrique équatoriale", "Un des plus grands coléoptères au monde, motifs noir et blanc spectaculaires" ] }, { name: "Eudicella morgani", commonName: "Cétoine de Morgan", taxonKey: "1082835", family: "Scarabaeidae", region: "Afrique centrale", hints: [ "Famille : Scarabaeidae", "Distribution : Afrique centrale", "Magnifique cétoine aux couleurs métalliques et motifs contrastés" ] }, { name: "Mecynorhina harrisii", commonName: "Cétoine de Harris", taxonKey: "1081449", family: "Scarabaeidae", region: "Afrique centrale", hints: [ "Famille : Scarabaeidae", "Distribution : Afrique centrale", "Grande cétoine colorée avec motifs jaunes et noirs" ] }, { name: "Idolomantis diabolica", commonName: "Mante diable géante", taxonKey: "1406692", family: "Empusidae", region: "Afrique de l'Est", hints: [ "Famille : Empusidae", "Distribution : Afrique de l'Est", "Mante spectaculaire avec crête et coloration d'avertissement" ] }, { name: "Asbolus verrucosus", commonName: "Coléoptère cuirassé du désert", taxonKey: "9670677", family: "Tenebrionidae", region: "Sud-ouest des États-Unis", hints: [ "Famille : Tenebrionidae", "Distribution : Sud-ouest des États-Unis, déserts", "Coléoptère du désert avec surface rugueuse et cireuse" ] }, { name: "Atta mexicana", commonName: "Fourmi champignonniste mexicaine", taxonKey: "5035745", family: "Formicidae", region: "Amérique centrale", hints: [ "Famille : Formicidae", "Distribution : Amérique centrale, notamment Mexique", "Fourmi coupeuse de feuilles qui cultive des champignons" ] }, { name: "Acromyrmex octospinosus", commonName: "Fourmi champignonniste épineuse", taxonKey: "1320686", family: "Formicidae", region: "Amérique centrale et du Sud", hints: [ "Famille : Formicidae", "Distribution : Amérique centrale et du Sud", "Fourmi coupeuse de feuilles avec épines sur le thorax" ] }, { name: "Macrophasma lyratus", commonName: "Phasme lyre", taxonKey: "1412429", family: "Phasmatidae", region: "Asie", hints: [ "Famille : Phasmatidae", "Distribution : Asie", "Phasme de taille moyenne avec forme de corps distinctive" ] }, { name: "Myrmecocystus", commonName: "Fourmi pot de miel", taxonKey: "1316742", family: "Formicidae", region: "Amérique du Nord", hints: [ "Famille : Formicidae", "Distribution : Régions arides d'Amérique du Nord", "Fourmis avec individus spécialisés servant de réservoirs de nourriture" ] }, { name: "Sphodromantis viridis", commonName: "Mante africaine géante", taxonKey: "1404864", family: "Mantidae", region: "Afrique", hints: [ "Famille : Mantidae", "Distribution : Afrique subsaharienne", "Grande mante verte robuste, très populaire en terrariophilie" ] } ]; // Update total species count document.getElementById('total-species').textContent = speciesData.length; // Game state let currentSpecies = null; let score = 0; let hintsRevealed = 0; let answered = false; let map = null; let tileLayer = null; let baseLayer = null; let selectedIndex = -1; let filteredSpecies = []; let currentMapType = 'standard'; // Map configurations const mapLayers = { standard: { url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: '© OpenStreetMap contributors' }, dark: { url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', attribution: '© OpenStreetMap contributors, © CARTO' }, satellite: { url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attribution: 'Tiles © Esri' } }; // Initialize map function initMap() { map = L.map('map').setView([20, 0], 2); baseLayer = L.tileLayer(mapLayers.standard.url, { attribution: mapLayers.standard.attribution, maxZoom: 18 }).addTo(map); } // Change map type function changeMapType(type) { if (baseLayer) { map.removeLayer(baseLayer); } currentMapType = type; const config = mapLayers[type]; baseLayer = L.tileLayer(config.url, { attribution: config.attribution, maxZoom: 18 }).addTo(map); // Update active button document.querySelectorAll('.map-type-btn').forEach(btn => { btn.classList.toggle('active', btn.dataset.map === type); }); } // Add event listeners for map type buttons document.querySelectorAll('.map-type-btn').forEach(btn => { btn.addEventListener('click', () => { changeMapType(btn.dataset.map); }); }); // Load species occurrences on map function loadSpeciesOnMap(taxonKey) { if (tileLayer) { map.removeLayer(tileLayer); } tileLayer = L.tileLayer( `https://api.gbif.org/v2/map/occurrence/density/{z}/{x}/{y}@1x.png?taxonKey=${taxonKey}&bin=hex&hexPerTile=100&style=red.marker`, { attribution: '© GBIF', maxZoom: 18 } ); tileLayer.addTo(map); } // Autocomplete functionality const input = document.getElementById('species-input'); const dropdown = document.getElementById('autocomplete-dropdown'); function filterSpecies(query) { if (!query) return []; const lowerQuery = query.toLowerCase(); return speciesData.filter(species => species.name.toLowerCase().includes(lowerQuery) || species.commonName.toLowerCase().includes(lowerQuery) ).slice(0, 10); // Limit to 10 results } function showAutocomplete(species) { if (species.length === 0) { dropdown.style.display = 'none'; return; } filteredSpecies = species; dropdown.innerHTML = species.map((s, index) => ` <div class="autocomplete-item" data-index="${index}"> <strong>${s.commonName}</strong> <em>${s.name}</em> </div> `).join(''); dropdown.style.display = 'block'; selectedIndex = -1; } input.addEventListener('input', (e) => { const filtered = filterSpecies(e.target.value); showAutocomplete(filtered); }); input.addEventListener('keydown', (e) => { const items = dropdown.querySelectorAll('.autocomplete-item'); if (e.key === 'ArrowDown') { e.preventDefault(); selectedIndex = Math.min(selectedIndex + 1, items.length - 1); updateSelection(items); } else if (e.key === 'ArrowUp') { e.preventDefault(); selectedIndex = Math.max(selectedIndex - 1, 0); updateSelection(items); } else if (e.key === 'Enter') { e.preventDefault(); if (selectedIndex >= 0 && selectedIndex < filteredSpecies.length) { selectSpecies(filteredSpecies[selectedIndex]); } else { submitAnswer(); } } }); function updateSelection(items) { items.forEach((item, index) => { item.classList.toggle('selected', index === selectedIndex); }); if (selectedIndex >= 0) { items[selectedIndex].scrollIntoView({ block: 'nearest' }); } } dropdown.addEventListener('click', (e) => { const item = e.target.closest('.autocomplete-item'); if (item) { const index = parseInt(item.dataset.index); selectSpecies(filteredSpecies[index]); } }); function selectSpecies(species) { input.value = `${species.commonName} (${species.name})`; dropdown.style.display = 'none'; } document.addEventListener('click', (e) => { if (!input.contains(e.target) && !dropdown.contains(e.target)) { dropdown.style.display = 'none'; } }); // Start new round function startNewRound() { currentSpecies = speciesData[Math.floor(Math.random() * speciesData.length)]; hintsRevealed = 0; answered = false; loadSpeciesOnMap(currentSpecies.taxonKey); document.getElementById('hints-display').innerHTML = ''; document.getElementById('hint-btn').disabled = false; document.getElementById('result-container').innerHTML = ''; document.getElementById('species-input').value = ''; document.getElementById('species-input').disabled = false; document.getElementById('submit-btn').disabled = false; document.getElementById('next-btn').style.display = 'none'; input.focus(); } // Submit answer function submitAnswer() { if (answered || !input.value.trim()) return; answered = true; const userInput = input.value.toLowerCase(); const isCorrect = userInput.includes(currentSpecies.name.toLowerCase()) || userInput.includes(currentSpecies.commonName.toLowerCase()); document.getElementById('species-input').disabled = true; document.getElementById('submit-btn').disabled = true; if (isCorrect) { const points = Math.max(3 - hintsRevealed, 1); score += points; document.getElementById('score').textContent = score; document.getElementById('result-container').innerHTML = ` <div class="result-message correct"> ✓ Correct ! C'était bien ${currentSpecies.commonName}<br> <em>${currentSpecies.name}</em><br> +${points} point${points > 1 ? 's' : ''} </div> `; } else { document.getElementById('result-container').innerHTML = ` <div class="result-message incorrect"> ✗ Incorrect ! C'était ${currentSpecies.commonName}<br> <em>${currentSpecies.name}</em> </div> `; } document.getElementById('next-btn').style.display = 'block'; document.getElementById('hint-btn').disabled = true; } document.getElementById('submit-btn').addEventListener('click', submitAnswer); // Handle hint request document.getElementById('hint-btn').addEventListener('click', () => { if (hintsRevealed >= currentSpecies.hints.length || answered) return; const hint = currentSpecies.hints[hintsRevealed]; const hintElement = document.createElement('div'); hintElement.className = 'hint-item'; hintElement.innerHTML = ` <div class="hint-label">Indice ${hintsRevealed + 1} :</div> ${hint} `; document.getElementById('hints-display').appendChild(hintElement); hintsRevealed++; if (hintsRevealed >= currentSpecies.hints.length) { document.getElementById('hint-btn').disabled = true; document.getElementById('hint-btn').textContent = 'Tous les indices révélés'; } }); // Handle next round document.getElementById('next-btn').addEventListener('click', startNewRound); // Initialize game initMap(); startNewRound(); </script> </body> </html>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Devine l'Insecte | Jeu Géographique</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=Source+Sans+3:wght@300;400;600&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--sepia: #f4f1e8;
--dark-sepia: #3d3526;
--accent-green: #4a7c59;
--accent-gold: #d4a574;
--shadow: rgba(61, 53, 38, 0.15);
--border: rgba(61, 53, 38, 0.2);
}
body {
font-family: 'Source Sans 3', sans-serif;
background: linear-gradient(135deg, #f4f1e8 0%, #e8e3d6 100%);
color: var(--dark-sepia);
overflow-x: hidden;
min-height: 100vh;
}
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px),
repeating-linear-gradient(90deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px);
pointer-events: none;
z-index: 1;
opacity: 0.3;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 2rem;
position: relative;
z-index: 2;
}
header {
text-align: center;
margin-bottom: 3rem;
animation: fadeInDown 1s ease;
}
h1 {
font-family: 'Crimson Pro', serif;
font-size: 3.5rem;
font-weight: 700;
color: var(--accent-green);
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
}
.subtitle {
font-size: 1.1rem;
color: var(--dark-sepia);
opacity: 0.8;
font-style: italic;
}
.stats-bar {
display: flex;
justify-content: center;
gap: 2rem;
margin-top: 1rem;
font-size: 0.95rem;
color: var(--dark-sepia);
opacity: 0.7;
}
.game-container {
display: grid;
grid-template-columns: 1fr 400px;
gap: 2rem;
animation: fadeInUp 1s ease 0.2s both;
}
.map-panel {
background: white;
border-radius: 16px;
box-shadow:
0 10px 40px var(--shadow),