Mantis_game / index.html
Enoder's picture
Update index.html
c259992 verified
Raw History Blame Contribute Delete
51.8 kB
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Devine la Mante | 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 la Mante</h1> <p class="subtitle">Identifie l'espèce selon sa distribution géographique</p> <div class="stats-bar"> <span>📊 <span id="total-species">60</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: "Mantis religiosa", commonName: "Mante religieuse", taxonKey: "6258028", family: "Mantidae", region: "Europe, Asie, introduite Amérique du Nord", hints: [ "Famille : Mantidae", "Distribution : Europe, Asie, introduite en Amérique du Nord", "L'espèce de mante la plus commune et répandue en Europe, posture de prière caractéristique" ] }, { 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: "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: "Choeradodis rhombicollis", commonName: "Mante feuille rhomboïde", taxonKey: "1405204", family: "Mantidae", region: "Amérique centrale et du Sud", hints: [ "Famille : Mantidae", "Distribution : Amérique centrale et du Sud", "Mimétisme exceptionnel de feuille avec prothorax élargi en forme de bouclier" ] }, { name: "Choeradodis servillei", commonName: "Mante feuille de Serville", taxonKey: "1405196", family: "Mantidae", region: "Amérique du Sud", hints: [ "Famille : Mantidae", "Distribution : Amérique du Sud tropicale", "Espèce arboricole imitant parfaitement une feuille verte" ] }, { name: "Rhombodera basalis", commonName: "Mante bouclier géante", taxonKey: "6725789", family: "Mantidae", region: "Asie du Sud-Est", hints: [ "Famille : Mantidae", "Distribution : Asie du Sud-Est", "Grande mante robuste, très populaire en terrariophilie" ] }, { name: "Toxodera servillei", commonName: "Mante brindille", taxonKey: "1406838", family: "Toxoderidae", region: "Asie du Sud-Est", hints: [ "Famille : Toxoderidae", "Distribution : Asie du Sud-Est", "Apparence extrêmement élancée imitant une brindille" ] }, { 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: "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: "Ameles spallanzania", commonName: "Amèle de Spallanzani", taxonKey: "5048707", family: "Amelidae", region: "Méditerranée", hints: [ "Famille : Amelidae", "Distribution : Bassin méditerranéen", "Petite mante, femelles souvent aptères (sans ailes fonctionnelles)" ] }, { name: "Ameles decolor", commonName: "Amèle décolorée", taxonKey: "5048690", family: "Amelidae", region: "Méditerranée", hints: [ "Famille : Amelidae", "Distribution : Europe du Sud et Afrique du Nord", "Petite espèce cryptique, coloration variable selon le substrat" ] }, { name: "Hierodula pulchripennis", commonName: "Mante à belles ailes", taxonKey: "1405884", family: "Mantidae", region: "Asie du Sud-Est", hints: [ "Famille : Mantidae", "Distribution : Asie du Sud-Est", "Grande mante verte avec motifs délicats sur les ailes" ] }, { name: "Callibia diana", commonName: "Mante de Diana", taxonKey: "1404245", family: "Nanomantidae", region: "Afrique", hints: [ "Famille : Nanomantidae", "Distribution : Afrique tropicale", "Petite mante aux motifs contrastés noir et blanc" ] }, { name: "Brunneria borealis", commonName: "Mante-bâton", taxonKey: "5048768", family: "Mantidae", region: "Amérique du Nord", hints: [ "Famille : Mantidae", "Distribution : Sud des États-Unis", "Corps extrêmement élancé, reproduction par parthénogenèse (pas de mâles)" ] }, { name: "Popa spurca", commonName: "Mante écorce africaine", taxonKey: "8821604", family: "Liturgusidae", region: "Afrique", hints: [ "Famille : Liturgusidae", "Distribution : Afrique subsaharienne", "Mimétisme d'écorce exceptionnel, corps aplati et rugueux" ] }, { name: "Pseudocreobotra wahlbergii", commonName: "Mante fleur épineuse", taxonKey: "1406642", family: "Hymenopodidae", region: "Afrique", hints: [ "Famille : Hymenopodidae", "Distribution : Afrique australe", "Motifs en spirale sur les ailes, abdomen en forme de feuille épineuse" ] }, { 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: "Helvia cardinalis", commonName: "Mante cardinale", taxonKey: "5048799", family: "Hymenopodidae", region: "Amérique du Sud", hints: [ "Famille : Hymenopodidae", "Distribution : Amérique du Sud", "Coloration rouge distinctive, espèce rare en captivité" ] }, { name: "Tenodera sinensis", commonName: "Mante chinoise", taxonKey: "5887934", family: "Mantidae", region: "Asie, introduite Amérique du Nord", hints: [ "Famille : Mantidae", "Distribution : Asie de l'Est, introduite en Amérique du Nord", "Une des plus grandes mantes, très robuste et vorace" ] }, { name: "Tenodera angustipennis", commonName: "Mante à ailes étroites", taxonKey: "4293587", family: "Mantidae", region: "Asie de l'Est", hints: [ "Famille : Mantidae", "Distribution : Asie de l'Est (Japon, Chine, Corée)", "Grande mante proche de T. sinensis mais avec des ailes plus fines" ] }, { name: "Heterochaeta orientalis", commonName: "Mante orientale hétéroclite", taxonKey: "5048674", family: "Mantidae", region: "Afrique de l'Est", hints: [ "Famille : Mantidae", "Distribution : Afrique de l'Est", "Espèce de taille moyenne avec coloration variable" ] }, { name: "Rhombodera kirbyi", commonName: "Mante bouclier de Kirby", taxonKey: "6725792", family: "Mantidae", region: "Asie du Sud-Est", hints: [ "Famille : Mantidae", "Distribution : Asie du Sud-Est", "Grande mante similaire à R. basalis, très populaire en élevage" ] }, { name: "Orthodera ministralis", commonName: "Mante australienne du jardin", taxonKey: "1405115", family: "Mantidae", region: "Australie", hints: [ "Famille : Mantidae", "Distribution : Australie", "Mante commune dans les jardins australiens, verte ou brune" ] }, { name: "Empusa pennata", commonName: "Empuse commune", taxonKey: "5048815", family: "Empusidae", region: "Méditerranée", hints: [ "Famille : Empusidae", "Distribution : Bassin méditerranéen", "Antennes plumeuses, silhouette très élancée avec crête sur la tête" ] }, { name: "Empusa fasciata", commonName: "Empuse fascié", taxonKey: "5048805", family: "Empusidae", region: "Méditerranée orientale", hints: [ "Famille : Empusidae", "Distribution : Méditerranée orientale, Moyen-Orient", "Proche d'E. pennata, corps élancé avec bandes caractéristiques" ] }, { name: "Sphodromantis lineola", commonName: "Mante africaine à ligne", taxonKey: "1404875", family: "Mantidae", region: "Afrique", hints: [ "Famille : Mantidae", "Distribution : Afrique centrale et occidentale", "Grande mante verte avec bande blanche sur les ailes antérieures" ] }, { name: "Theopropus elegans", commonName: "Mante orchidée élégante", taxonKey: "1406531", family: "Hymenopodidae", region: "Asie du Sud-Est", hints: [ "Famille : Hymenopodidae", "Distribution : Asie du Sud-Est", "Lobes abdominaux en forme de pétales, mimétisme floral" ] }, { name: "Chlidonoptera lestoni", commonName: "Mante de Leston", taxonKey: "1406371", family: "Hymenopodidae", region: "Afrique", hints: [ "Famille : Hymenopodidae", "Distribution : Afrique centrale", "Espèce rare avec dimorphisme sexuel prononcé" ] }, { name: "Theopompa sp.", commonName: "Mante Theopompa", taxonKey: "1406967", family: "Hymenopodidae", region: "Asie", hints: [ "Famille : Hymenopodidae", "Distribution : Asie", "Genre avec plusieurs espèces difficiles à distinguer" ] }, { name: "Metallyticus splendidus", commonName: "Mante métallique", taxonKey: "1406791", family: "Metallyticidae", region: "Asie du Sud-Est", hints: [ "Famille : Metallyticidae", "Distribution : Asie du Sud-Est", "Petite mante aux reflets métalliques bleu-vert, aspect iridescent unique" ] }, { name: "Archimantis sp.", commonName: "Mante australienne", taxonKey: "5430805", family: "Mantidae", region: "Australie", hints: [ "Famille : Mantidae", "Distribution : Australie", "Genre endémique australien de grandes mantes" ] }, { name: "Titanodula sp.", commonName: "Mante titan", taxonKey: "11149550", family: "Mantidae", region: "Asie", hints: [ "Famille : Mantidae", "Distribution : Asie", "Grande mante du genre récemment décrit" ] }, { name: "Sibylla pretiosa", commonName: "Mante cryptique", taxonKey: "5048867", family: "Sibyllidae", region: "Afrique australe", hints: [ "Famille : Sibyllidae", "Distribution : Afrique australe", "Camouflage exceptionnel imitant écorce ou brindilles" ] }, { name: "Zoolea lobipes", commonName: "Mante à pattes lobées", taxonKey: "1404596", family: "Mantidae", region: "Afrique", hints: [ "Famille : Mantidae", "Distribution : Afrique", "Pattes avec expansions en forme de lobes, espèce inhabituelle" ] }, { name: "Ceratocrania macra", commonName: "Mante à cornes", taxonKey: "1405086", family: "Nanomantidae", region: "Afrique", hints: [ "Famille : Nanomantidae", "Distribution : Afrique", "Petite mante avec protubérances en forme de cornes" ] }, { name: "Parablepharis kuhli", commonName: "Mante de Kuhl", taxonKey: "1406461", family: "Hymenopodidae", region: "Asie du Sud-Est", hints: [ "Famille : Hymenopodidae", "Distribution : Asie du Sud-Est", "Mimétisme de feuille, lobes foliaires sur les pattes" ] }, { name: "Phyllocrania paradoxa", commonName: "Mante feuille morte", taxonKey: "1406423", family: "Hymenopodidae", region: "Afrique", hints: [ "Famille : Hymenopodidae", "Distribution : Afrique subsaharienne (Madagascar)", "Mimétisme exceptionnel de feuille morte desséchée" ] }, { name: "Idolomorpha madagascariensis", commonName: "Mante de Madagascar", taxonKey: "1406706", family: "Empusidae", region: "Madagascar", hints: [ "Famille : Empusidae", "Distribution : Madagascar (endémique)", "Espèce élancée endémique de la Grande Île" ] }, { name: "Hierodula membranacea", commonName: "Mante asiatique géante", taxonKey: "1406012", family: "Mantidae", region: "Asie", hints: [ "Famille : Mantidae", "Distribution : Asie du Sud et Sud-Est", "Grande mante verte très populaire en terrariophilie" ] }, { name: "Prohierodula picta", commonName: "Mante peinte", taxonKey: "1406039", family: "Mantidae", region: "Asie du Sud-Est", hints: [ "Famille : Mantidae", "Distribution : Asie du Sud-Est", "Motifs colorés sur le corps, espèce de taille moyenne" ] }, { name: "Sphodromantis aurea", commonName: "Mante africaine dorée", taxonKey: "1404852", family: "Mantidae", region: "Afrique", hints: [ "Famille : Mantidae", "Distribution : Afrique (Ghana principalement)", "Grande mante robuste, souvent avec taches dorées" ] }, { name: "Eremiaphila sp.", commonName: "Mante du désert", taxonKey: "1404075", family: "Eremiaphilidae", region: "Afrique du Nord, Moyen-Orient", hints: [ "Famille : Eremiaphilidae", "Distribution : Déserts d'Afrique du Nord et du Moyen-Orient", "Mantes terrestres adaptées aux environnements désertiques" ] }, { name: "Iris polystictica", commonName: "Mante Iris à points", taxonKey: "1404286", family: "Tarachodidae", region: "Méditerranée", hints: [ "Famille : Tarachodidae", "Distribution : Méditerranée orientale", "Proche d'I. oratoria, avec plusieurs ocelles sur les ailes" ] }, { name: "Rivetina baetica", commonName: "Mante ibérique", taxonKey: "7204677", family: "Rivetinidae", region: "Péninsule ibérique", hints: [ "Famille : Rivetinidae", "Distribution : Péninsule ibérique et Afrique du Nord", "Petite mante vivant au sol dans la végétation basse" ] }, { name: "Rivetina balcanica", commonName: "Mante balkanique", taxonKey: "4514096", family: "Rivetinidae", region: "Balkans", hints: [ "Famille : Rivetinidae", "Distribution : Péninsule balkanique", "Petite espèce discrète proche de R. baetica" ] }, { name: "Perlamantis allibertii", commonName: "Mante d'Allibert", taxonKey: "1403589", family: "Mantidae", region: "Afrique", hints: [ "Famille : Mantidae", "Distribution : Afrique de l'Ouest", "Espèce de taille moyenne, peu commune en élevage" ] }, { name: "Macromantis ovalifolia", commonName: "Mante à feuilles ovales", taxonKey: "1405820", family: "Mantidae", region: "Amérique du Sud", hints: [ "Famille : Mantidae", "Distribution : Amérique du Sud", "Grande mante aux ailes larges et ovales" ] }, { name: "Miomantis paykulli", commonName: "Mante égyptienne", taxonKey: "5048540", family: "Mantidae", region: "Afrique, introduite", hints: [ "Famille : Mantidae", "Distribution : Afrique, introduite dans plusieurs régions", "Petite mante très adaptable, peut vivre en zones urbaines" ] }, { name: "Miomantis caffra", commonName: "Mante du Cap", taxonKey: "5048515", family: "Mantidae", region: "Afrique australe", hints: [ "Famille : Mantidae", "Distribution : Afrique australe", "Petite mante commune en Afrique du Sud" ] }, { name: "Stagmomantis carolina", commonName: "Mante de Caroline", taxonKey: "1404940", family: "Mantidae", region: "Amérique du Nord", hints: [ "Famille : Mantidae", "Distribution : États-Unis (sud-est)", "Espèce commune aux États-Unis, très adaptable" ] }, { name: "Stagmomantis californica", commonName: "Mante de Californie", taxonKey: "1404928", family: "Mantidae", region: "Amérique du Nord", hints: [ "Famille : Mantidae", "Distribution : Ouest des États-Unis (Californie)", "Espèce endémique de l'ouest américain" ] }, { name: "Paratoxodera sp.", commonName: "Mante brindille géante", taxonKey: "1406849", family: "Toxoderidae", region: "Asie du Sud-Est", hints: [ "Famille : Toxoderidae", "Distribution : Asie du Sud-Est", "Une des plus longues mantes au monde, apparence de brindille extrême" ] }, { name: "Mantis octospilota", commonName: "Mante à huit taches", taxonKey: "6258044", family: "Mantidae", region: "Europe du Sud", hints: [ "Famille : Mantidae", "Distribution : Europe du Sud", "Proche de M. religiosa, avec taches caractéristiques" ] }, { name: "Tisma freyi", commonName: "Mante de Frey", taxonKey: "1404829", family: "Mantidae", region: "Amérique du Sud", hints: [ "Famille : Mantidae", "Distribution : Amérique du Sud", "Espèce rare, peu documentée" ] }, { name: "Pnigomantis medioconstricta", commonName: "Mante à constriction", taxonKey: "1404986", family: "Mantidae", region: "Afrique", hints: [ "Famille : Mantidae", "Distribution : Afrique", "Abdomen avec constriction médiane caractéristique" ] }, { name: "Tamolanica tamolana", commonName: "Mante de Tamolana", taxonKey: "1405781", family: "Mantidae", region: "Madagascar", hints: [ "Famille : Mantidae", "Distribution : Madagascar (endémique)", "Espèce endémique de Madagascar, peu connue" ] }, { name: "Deroplatys desiccata", commonName: "Mante feuille morte géante", taxonKey: "1405421", family: "Deroplatyidae", region: "Asie du Sud-Est", hints: [ "Famille : Deroplatyidae", "Distribution : Asie du Sud-Est", "Grande mante avec mimétisme de feuille morte, apparence très plate" ] } ]; // 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 la Mante | 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),