Enoder commited on
Commit
54919a9
·
verified ·
1 Parent(s): 94aa10f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +1041 -19
index.html CHANGED
@@ -1,19 +1,1041 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Devine l'Insecte | Jeu Géographique</title>
7
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
8
+ <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">
9
+ <style>
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ :root {
17
+ --sepia: #f4f1e8;
18
+ --dark-sepia: #3d3526;
19
+ --accent-green: #4a7c59;
20
+ --accent-gold: #d4a574;
21
+ --shadow: rgba(61, 53, 38, 0.15);
22
+ --border: rgba(61, 53, 38, 0.2);
23
+ }
24
+
25
+ body {
26
+ font-family: 'Source Sans 3', sans-serif;
27
+ background: linear-gradient(135deg, #f4f1e8 0%, #e8e3d6 100%);
28
+ color: var(--dark-sepia);
29
+ overflow-x: hidden;
30
+ min-height: 100vh;
31
+ }
32
+
33
+ body::before {
34
+ content: '';
35
+ position: fixed;
36
+ top: 0;
37
+ left: 0;
38
+ width: 100%;
39
+ height: 100%;
40
+ background-image:
41
+ repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px),
42
+ repeating-linear-gradient(90deg, transparent, transparent 2px, rgba(61, 53, 38, 0.03) 2px, rgba(61, 53, 38, 0.03) 4px);
43
+ pointer-events: none;
44
+ z-index: 1;
45
+ opacity: 0.3;
46
+ }
47
+
48
+ .container {
49
+ max-width: 1400px;
50
+ margin: 0 auto;
51
+ padding: 2rem;
52
+ position: relative;
53
+ z-index: 2;
54
+ }
55
+
56
+ header {
57
+ text-align: center;
58
+ margin-bottom: 3rem;
59
+ animation: fadeInDown 1s ease;
60
+ }
61
+
62
+ h1 {
63
+ font-family: 'Crimson Pro', serif;
64
+ font-size: 3.5rem;
65
+ font-weight: 700;
66
+ color: var(--accent-green);
67
+ letter-spacing: -0.02em;
68
+ margin-bottom: 0.5rem;
69
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
70
+ }
71
+
72
+ .subtitle {
73
+ font-size: 1.1rem;
74
+ color: var(--dark-sepia);
75
+ opacity: 0.8;
76
+ font-style: italic;
77
+ }
78
+
79
+ .stats-bar {
80
+ display: flex;
81
+ justify-content: center;
82
+ gap: 2rem;
83
+ margin-top: 1rem;
84
+ font-size: 0.95rem;
85
+ color: var(--dark-sepia);
86
+ opacity: 0.7;
87
+ }
88
+
89
+ .game-container {
90
+ display: grid;
91
+ grid-template-columns: 1fr 400px;
92
+ gap: 2rem;
93
+ animation: fadeInUp 1s ease 0.2s both;
94
+ }
95
+
96
+ .map-panel {
97
+ background: white;
98
+ border-radius: 16px;
99
+ box-shadow:
100
+ 0 10px 40px var(--shadow),
101
+ inset 0 0 0 1px var(--border);
102
+ overflow: hidden;
103
+ position: relative;
104
+ }
105
+
106
+ .map-header {
107
+ background: linear-gradient(135deg, var(--accent-green) 0%, #5a8c69 100%);
108
+ color: white;
109
+ padding: 1.5rem 2rem;
110
+ font-family: 'Crimson Pro', serif;
111
+ font-size: 1.4rem;
112
+ font-weight: 600;
113
+ letter-spacing: 0.02em;
114
+ display: flex;
115
+ justify-content: space-between;
116
+ align-items: center;
117
+ }
118
+
119
+ .map-controls {
120
+ display: flex;
121
+ gap: 0.5rem;
122
+ }
123
+
124
+ .map-type-btn {
125
+ background: rgba(255, 255, 255, 0.2);
126
+ border: 2px solid rgba(255, 255, 255, 0.3);
127
+ color: white;
128
+ padding: 0.5rem 1rem;
129
+ border-radius: 6px;
130
+ font-family: 'Source Sans 3', sans-serif;
131
+ font-size: 0.85rem;
132
+ font-weight: 600;
133
+ cursor: pointer;
134
+ transition: all 0.3s ease;
135
+ }
136
+
137
+ .map-type-btn:hover {
138
+ background: rgba(255, 255, 255, 0.3);
139
+ border-color: rgba(255, 255, 255, 0.5);
140
+ }
141
+
142
+ .map-type-btn.active {
143
+ background: white;
144
+ color: var(--accent-green);
145
+ border-color: white;
146
+ }
147
+
148
+ #map {
149
+ height: 600px;
150
+ width: 100%;
151
+ background: #a8c5d9;
152
+ }
153
+
154
+ .control-panel {
155
+ background: white;
156
+ border-radius: 16px;
157
+ box-shadow:
158
+ 0 10px 40px var(--shadow),
159
+ inset 0 0 0 1px var(--border);
160
+ padding: 2rem;
161
+ display: flex;
162
+ flex-direction: column;
163
+ gap: 1.5rem;
164
+ max-height: 800px;
165
+ overflow-y: auto;
166
+ }
167
+
168
+ .score-display {
169
+ background: linear-gradient(135deg, #f8f6f0 0%, #ede9dc 100%);
170
+ padding: 1.5rem;
171
+ border-radius: 10px;
172
+ text-align: center;
173
+ border: 2px solid var(--border);
174
+ position: sticky;
175
+ top: 0;
176
+ z-index: 10;
177
+ }
178
+
179
+ .score-label {
180
+ font-family: 'Crimson Pro', serif;
181
+ font-size: 0.9rem;
182
+ color: var(--dark-sepia);
183
+ opacity: 0.7;
184
+ text-transform: uppercase;
185
+ letter-spacing: 0.1em;
186
+ margin-bottom: 0.5rem;
187
+ }
188
+
189
+ .score-value {
190
+ font-size: 2.5rem;
191
+ font-weight: 700;
192
+ color: var(--accent-green);
193
+ font-family: 'Crimson Pro', serif;
194
+ }
195
+
196
+ .answer-input-section {
197
+ display: flex;
198
+ flex-direction: column;
199
+ gap: 1rem;
200
+ }
201
+
202
+ .answer-input-section label {
203
+ font-family: 'Crimson Pro', serif;
204
+ font-size: 1.1rem;
205
+ font-weight: 600;
206
+ color: var(--accent-green);
207
+ }
208
+
209
+ .input-wrapper {
210
+ position: relative;
211
+ }
212
+
213
+ #species-input {
214
+ width: 100%;
215
+ padding: 1rem;
216
+ border: 2px solid var(--border);
217
+ border-radius: 10px;
218
+ font-family: 'Crimson Pro', serif;
219
+ font-size: 1rem;
220
+ background: var(--sepia);
221
+ color: var(--dark-sepia);
222
+ transition: all 0.3s ease;
223
+ }
224
+
225
+ #species-input:focus {
226
+ outline: none;
227
+ border-color: var(--accent-green);
228
+ background: white;
229
+ box-shadow: 0 4px 12px var(--shadow);
230
+ }
231
+
232
+ .autocomplete-dropdown {
233
+ position: absolute;
234
+ top: 100%;
235
+ left: 0;
236
+ right: 0;
237
+ background: white;
238
+ border: 2px solid var(--accent-green);
239
+ border-top: none;
240
+ border-radius: 0 0 10px 10px;
241
+ max-height: 300px;
242
+ overflow-y: auto;
243
+ z-index: 1000;
244
+ box-shadow: 0 8px 16px var(--shadow);
245
+ }
246
+
247
+ .autocomplete-item {
248
+ padding: 0.75rem 1rem;
249
+ cursor: pointer;
250
+ transition: background 0.2s ease;
251
+ border-bottom: 1px solid var(--border);
252
+ }
253
+
254
+ .autocomplete-item:last-child {
255
+ border-bottom: none;
256
+ }
257
+
258
+ .autocomplete-item:hover,
259
+ .autocomplete-item.selected {
260
+ background: var(--sepia);
261
+ }
262
+
263
+ .autocomplete-item strong {
264
+ color: var(--accent-green);
265
+ display: block;
266
+ margin-bottom: 0.25rem;
267
+ }
268
+
269
+ .autocomplete-item em {
270
+ color: var(--dark-sepia);
271
+ opacity: 0.7;
272
+ font-size: 0.9rem;
273
+ }
274
+
275
+ .submit-btn {
276
+ background: linear-gradient(135deg, var(--accent-green) 0%, #5a8c69 100%);
277
+ color: white;
278
+ border: none;
279
+ padding: 1rem 1.5rem;
280
+ border-radius: 10px;
281
+ font-family: 'Crimson Pro', serif;
282
+ font-size: 1.1rem;
283
+ font-weight: 600;
284
+ cursor: pointer;
285
+ transition: all 0.3s ease;
286
+ box-shadow: 0 4px 12px rgba(74, 124, 89, 0.3);
287
+ }
288
+
289
+ .submit-btn:hover:not(:disabled) {
290
+ transform: translateY(-2px);
291
+ box-shadow: 0 6px 20px rgba(74, 124, 89, 0.4);
292
+ }
293
+
294
+ .submit-btn:disabled {
295
+ opacity: 0.5;
296
+ cursor: not-allowed;
297
+ }
298
+
299
+ .hints-section {
300
+ border-top: 2px solid var(--border);
301
+ padding-top: 1.5rem;
302
+ }
303
+
304
+ .hint-btn {
305
+ background: linear-gradient(135deg, var(--accent-gold) 0%, #c49564 100%);
306
+ color: white;
307
+ border: none;
308
+ padding: 1rem 1.5rem;
309
+ border-radius: 10px;
310
+ font-family: 'Crimson Pro', serif;
311
+ font-size: 1.1rem;
312
+ font-weight: 600;
313
+ cursor: pointer;
314
+ width: 100%;
315
+ transition: all 0.3s ease;
316
+ box-shadow: 0 4px 12px rgba(212, 165, 116, 0.3);
317
+ }
318
+
319
+ .hint-btn:hover:not(:disabled) {
320
+ transform: translateY(-2px);
321
+ box-shadow: 0 6px 20px rgba(212, 165, 116, 0.4);
322
+ }
323
+
324
+ .hint-btn:disabled {
325
+ opacity: 0.5;
326
+ cursor: not-allowed;
327
+ }
328
+
329
+ .hints-display {
330
+ margin-top: 1rem;
331
+ display: flex;
332
+ flex-direction: column;
333
+ gap: 0.75rem;
334
+ }
335
+
336
+ .hint-item {
337
+ background: #fff9f0;
338
+ border-left: 4px solid var(--accent-gold);
339
+ padding: 1rem;
340
+ border-radius: 6px;
341
+ font-size: 0.95rem;
342
+ line-height: 1.6;
343
+ animation: slideInRight 0.4s ease;
344
+ }
345
+
346
+ .hint-label {
347
+ font-weight: 600;
348
+ color: var(--accent-green);
349
+ margin-bottom: 0.25rem;
350
+ }
351
+
352
+ .next-btn {
353
+ background: var(--accent-green);
354
+ color: white;
355
+ border: none;
356
+ padding: 1rem 1.5rem;
357
+ border-radius: 10px;
358
+ font-family: 'Crimson Pro', serif;
359
+ font-size: 1.1rem;
360
+ font-weight: 600;
361
+ cursor: pointer;
362
+ width: 100%;
363
+ transition: all 0.3s ease;
364
+ box-shadow: 0 4px 12px rgba(74, 124, 89, 0.3);
365
+ }
366
+
367
+ .next-btn:hover {
368
+ background: #5a8c69;
369
+ transform: translateY(-2px);
370
+ box-shadow: 0 6px 20px rgba(74, 124, 89, 0.4);
371
+ }
372
+
373
+ .result-message {
374
+ padding: 1.5rem;
375
+ border-radius: 10px;
376
+ text-align: center;
377
+ font-family: 'Crimson Pro', serif;
378
+ font-size: 1.2rem;
379
+ font-weight: 600;
380
+ animation: fadeIn 0.5s ease;
381
+ }
382
+
383
+ .result-message.correct {
384
+ background: rgba(74, 124, 89, 0.1);
385
+ color: var(--accent-green);
386
+ border: 2px solid var(--accent-green);
387
+ }
388
+
389
+ .result-message.incorrect {
390
+ background: rgba(197, 74, 74, 0.1);
391
+ color: #c54a4a;
392
+ border: 2px solid #c54a4a;
393
+ }
394
+
395
+ @keyframes fadeInDown {
396
+ from {
397
+ opacity: 0;
398
+ transform: translateY(-30px);
399
+ }
400
+ to {
401
+ opacity: 1;
402
+ transform: translateY(0);
403
+ }
404
+ }
405
+
406
+ @keyframes fadeInUp {
407
+ from {
408
+ opacity: 0;
409
+ transform: translateY(30px);
410
+ }
411
+ to {
412
+ opacity: 1;
413
+ transform: translateY(0);
414
+ }
415
+ }
416
+
417
+ @keyframes slideInRight {
418
+ from {
419
+ opacity: 0;
420
+ transform: translateX(-20px);
421
+ }
422
+ to {
423
+ opacity: 1;
424
+ transform: translateX(0);
425
+ }
426
+ }
427
+
428
+ @keyframes fadeIn {
429
+ from { opacity: 0; }
430
+ to { opacity: 1; }
431
+ }
432
+
433
+ @media (max-width: 1024px) {
434
+ .game-container {
435
+ grid-template-columns: 1fr;
436
+ }
437
+
438
+ h1 {
439
+ font-size: 2.5rem;
440
+ }
441
+
442
+ #map {
443
+ height: 500px;
444
+ }
445
+ }
446
+
447
+ .leaflet-control-attribution {
448
+ background: rgba(255, 255, 255, 0.8) !important;
449
+ font-size: 0.7rem !important;
450
+ }
451
+ </style>
452
+ </head>
453
+ <body>
454
+ <div class="container">
455
+ <header>
456
+ <h1>🦗 Devine l'Insecte</h1>
457
+ <p class="subtitle">Identifie l'espèce selon sa distribution géographique</p>
458
+ <div class="stats-bar">
459
+ <span>📊 <span id="total-species">22</span> espèces disponibles</span>
460
+ </div>
461
+ </header>
462
+
463
+ <div class="game-container">
464
+ <div class="map-panel">
465
+ <div class="map-header">
466
+ <span>Distribution Mondiale des Occurrences</span>
467
+ <div class="map-controls">
468
+ <button class="map-type-btn active" data-map="standard">Standard</button>
469
+ <button class="map-type-btn" data-map="dark">Sombre</button>
470
+ <button class="map-type-btn" data-map="satellite">Satellite</button>
471
+ </div>
472
+ </div>
473
+ <div id="map"></div>
474
+ </div>
475
+
476
+ <div class="control-panel">
477
+ <div class="score-display">
478
+ <div class="score-label">Score</div>
479
+ <div class="score-value" id="score">0</div>
480
+ </div>
481
+
482
+ <div id="result-container"></div>
483
+
484
+ <div class="answer-input-section">
485
+ <label for="species-input">Quelle est cette espèce ?</label>
486
+ <div class="input-wrapper">
487
+ <input
488
+ type="text"
489
+ id="species-input"
490
+ placeholder="Tapez le nom de l'espèce..."
491
+ autocomplete="off"
492
+ />
493
+ <div id="autocomplete-dropdown" class="autocomplete-dropdown" style="display: none;"></div>
494
+ </div>
495
+ <button class="submit-btn" id="submit-btn">
496
+ Valider ma réponse
497
+ </button>
498
+ </div>
499
+
500
+ <div class="hints-section">
501
+ <button class="hint-btn" id="hint-btn">
502
+ 💡 Demander un indice
503
+ </button>
504
+ <div class="hints-display" id="hints-display"></div>
505
+ </div>
506
+
507
+ <button class="next-btn" id="next-btn" style="display: none;">
508
+ Mante Suivante →
509
+ </button>
510
+ </div>
511
+ </div>
512
+ </div>
513
+
514
+ <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
515
+ <script>
516
+ // Complete species database with verified GBIF taxonKeys
517
+ const speciesData = [
518
+ {
519
+ name: "Phasma gigas",
520
+ commonName: "Phasme géant",
521
+ taxonKey: "5049821",
522
+ family: "Phasmatidae",
523
+ region: "Asie du Sud-Est",
524
+ hints: [
525
+ "Famille : Phasmatidae",
526
+ "Distribution : Asie du Sud-Est",
527
+ "Un des plus grands phasmes au monde, peut atteindre 30 cm de longueur"
528
+ ]
529
+ },
530
+ {
531
+ name: "Macromantis hyalina",
532
+ commonName: "Mante hyaline",
533
+ taxonKey: "1405821",
534
+ family: "Mantidae",
535
+ region: "Amérique du Sud",
536
+ hints: [
537
+ "Famille : Mantidae",
538
+ "Distribution : Amérique du Sud",
539
+ "Grande mante aux ailes transparentes, typique des forêts tropicales"
540
+ ]
541
+ },
542
+ {
543
+ name: "Blepharopsis mendica",
544
+ commonName: "Mante diable",
545
+ taxonKey: "1406697",
546
+ family: "Empusidae",
547
+ region: "Afrique du Nord, Moyen-Orient",
548
+ hints: [
549
+ "Famille : Empusidae",
550
+ "Distribution : Afrique du Nord et Moyen-Orient",
551
+ "Mante du désert avec des yeux spectaculaires et des motifs colorés"
552
+ ]
553
+ },
554
+ {
555
+ name: "Creobroter gemmatus",
556
+ commonName: "Mante fleur indienne",
557
+ taxonKey: "1406395",
558
+ family: "Hymenopodidae",
559
+ region: "Asie du Sud",
560
+ hints: [
561
+ "Famille : Hymenopodidae",
562
+ "Distribution : Inde, Asie du Sud",
563
+ "Petite mante colorée avec taches oculaires vertes sur les ailes"
564
+ ]
565
+ },
566
+ {
567
+ name: "Hymenopus coronatus",
568
+ commonName: "Mante orchidée",
569
+ taxonKey: "1406471",
570
+ family: "Hymenopodidae",
571
+ region: "Asie du Sud-Est",
572
+ hints: [
573
+ "Famille : Hymenopodidae",
574
+ "Distribution : Asie du Sud-Est (Malaisie, Indonésie)",
575
+ "Célèbre pour son mimétisme d'orchidée, une des plus belles mantes au monde"
576
+ ]
577
+ },
578
+ {
579
+ name: "Callibia diana",
580
+ commonName: "Mante de Diana",
581
+ taxonKey: "1404244",
582
+ family: "Nanomantidae",
583
+ region: "Afrique",
584
+ hints: [
585
+ "Famille : Nanomantidae",
586
+ "Distribution : Afrique tropicale",
587
+ "Petite mante aux motifs contrastés noir et blanc"
588
+ ]
589
+ },
590
+ {
591
+ name: "Polyspilota aeruginosa",
592
+ commonName: "Mante cuivrée",
593
+ taxonKey: "1405481",
594
+ family: "Mantidae",
595
+ region: "Afrique subsaharienne",
596
+ hints: [
597
+ "Famille : Mantidae",
598
+ "Distribution : Afrique subsaharienne",
599
+ "Coloration vert-cuivré caractéristique, espèce robuste"
600
+ ]
601
+ },
602
+ {
603
+ name: "Argema mimosae",
604
+ commonName: "Papillon lune africain",
605
+ taxonKey: "1867009",
606
+ family: "Saturniidae",
607
+ region: "Afrique australe",
608
+ hints: [
609
+ "Famille : Saturniidae",
610
+ "Distribution : Afrique australe",
611
+ "Magnifique papillon de nuit avec de longues queues sur les ailes"
612
+ ]
613
+ },
614
+ {
615
+ name: "Acontista mexicana",
616
+ commonName: "Mante mexicaine",
617
+ taxonKey: "1404204",
618
+ family: "Acontistidae",
619
+ region: "Amérique centrale",
620
+ hints: [
621
+ "Famille : Acontistidae",
622
+ "Distribution : Amérique centrale, notamment Mexique",
623
+ "Petite mante discrète vivant dans les zones arides mexicaines"
624
+ ]
625
+ },
626
+ {
627
+ name: "Prohierodula flavipennis",
628
+ commonName: "Mante à ailes jaunes",
629
+ taxonKey: "1406032",
630
+ family: "Mantidae",
631
+ region: "Asie du Sud-Est",
632
+ hints: [
633
+ "Famille : Mantidae",
634
+ "Distribution : Asie du Sud-Est",
635
+ "Ailes postérieures jaune vif, espèce de taille moyenne"
636
+ ]
637
+ },
638
+ {
639
+ name: "Armadillidium werneri",
640
+ commonName: "Cloporte de Werner",
641
+ taxonKey: "2203862",
642
+ family: "Armadillidiidae",
643
+ region: "Europe",
644
+ hints: [
645
+ "Famille : Armadillidiidae",
646
+ "Distribution : Europe",
647
+ "Petit crustacé terrestre capable de se rouler en boule"
648
+ ]
649
+ },
650
+ {
651
+ name: "Carausius morosus",
652
+ commonName: "Phasme bâton indien",
653
+ taxonKey: "1411953",
654
+ family: "Lonchodidae",
655
+ region: "Inde",
656
+ hints: [
657
+ "Famille : Lonchodidae",
658
+ "Distribution : Inde",
659
+ "Phasme très populaire en élevage, reproduction par parthénogenèse"
660
+ ]
661
+ },
662
+ {
663
+ name: "Goliathus goliatus",
664
+ commonName: "Goliath géant",
665
+ taxonKey: "1076779",
666
+ family: "Scarabaeidae",
667
+ region: "Afrique équatoriale",
668
+ hints: [
669
+ "Famille : Scarabaeidae",
670
+ "Distribution : Afrique équatoriale",
671
+ "Un des plus grands coléoptères au monde, motifs noir et blanc spectaculaires"
672
+ ]
673
+ },
674
+ {
675
+ name: "Eudicella morgani",
676
+ commonName: "Cétoine de Morgan",
677
+ taxonKey: "1082835",
678
+ family: "Scarabaeidae",
679
+ region: "Afrique centrale",
680
+ hints: [
681
+ "Famille : Scarabaeidae",
682
+ "Distribution : Afrique centrale",
683
+ "Magnifique cétoine aux couleurs métalliques et motifs contrastés"
684
+ ]
685
+ },
686
+ {
687
+ name: "Mecynorhina harrisii",
688
+ commonName: "Cétoine de Harris",
689
+ taxonKey: "1081449",
690
+ family: "Scarabaeidae",
691
+ region: "Afrique centrale",
692
+ hints: [
693
+ "Famille : Scarabaeidae",
694
+ "Distribution : Afrique centrale",
695
+ "Grande cétoine colorée avec motifs jaunes et noirs"
696
+ ]
697
+ },
698
+ {
699
+ name: "Idolomantis diabolica",
700
+ commonName: "Mante diable géante",
701
+ taxonKey: "1406692",
702
+ family: "Empusidae",
703
+ region: "Afrique de l'Est",
704
+ hints: [
705
+ "Famille : Empusidae",
706
+ "Distribution : Afrique de l'Est",
707
+ "Mante spectaculaire avec crête et coloration d'avertissement"
708
+ ]
709
+ },
710
+ {
711
+ name: "Asbolus verrucosus",
712
+ commonName: "Coléoptère cuirassé du désert",
713
+ taxonKey: "9670677",
714
+ family: "Tenebrionidae",
715
+ region: "Sud-ouest des États-Unis",
716
+ hints: [
717
+ "Famille : Tenebrionidae",
718
+ "Distribution : Sud-ouest des États-Unis, déserts",
719
+ "Coléoptère du désert avec surface rugueuse et cireuse"
720
+ ]
721
+ },
722
+ {
723
+ name: "Atta mexicana",
724
+ commonName: "Fourmi champignonniste mexicaine",
725
+ taxonKey: "5035745",
726
+ family: "Formicidae",
727
+ region: "Amérique centrale",
728
+ hints: [
729
+ "Famille : Formicidae",
730
+ "Distribution : Amérique centrale, notamment Mexique",
731
+ "Fourmi coupeuse de feuilles qui cultive des champignons"
732
+ ]
733
+ },
734
+ {
735
+ name: "Acromyrmex octospinosus",
736
+ commonName: "Fourmi champignonniste épineuse",
737
+ taxonKey: "1320686",
738
+ family: "Formicidae",
739
+ region: "Amérique centrale et du Sud",
740
+ hints: [
741
+ "Famille : Formicidae",
742
+ "Distribution : Amérique centrale et du Sud",
743
+ "Fourmi coupeuse de feuilles avec épines sur le thorax"
744
+ ]
745
+ },
746
+ {
747
+ name: "Macrophasma lyratus",
748
+ commonName: "Phasme lyre",
749
+ taxonKey: "1412429",
750
+ family: "Phasmatidae",
751
+ region: "Asie",
752
+ hints: [
753
+ "Famille : Phasmatidae",
754
+ "Distribution : Asie",
755
+ "Phasme de taille moyenne avec forme de corps distinctive"
756
+ ]
757
+ },
758
+ {
759
+ name: "Myrmecocystus",
760
+ commonName: "Fourmi pot de miel",
761
+ taxonKey: "1316742",
762
+ family: "Formicidae",
763
+ region: "Amérique du Nord",
764
+ hints: [
765
+ "Famille : Formicidae",
766
+ "Distribution : Régions arides d'Amérique du Nord",
767
+ "Fourmis avec individus spécialisés servant de réservoirs de nourriture"
768
+ ]
769
+ },
770
+ {
771
+ name: "Sphodromantis viridis",
772
+ commonName: "Mante africaine géante",
773
+ taxonKey: "1404864",
774
+ family: "Mantidae",
775
+ region: "Afrique",
776
+ hints: [
777
+ "Famille : Mantidae",
778
+ "Distribution : Afrique subsaharienne",
779
+ "Grande mante verte robuste, très populaire en terrariophilie"
780
+ ]
781
+ }
782
+ ];
783
+
784
+ // Update total species count
785
+ document.getElementById('total-species').textContent = speciesData.length;
786
+
787
+ // Game state
788
+ let currentSpecies = null;
789
+ let score = 0;
790
+ let hintsRevealed = 0;
791
+ let answered = false;
792
+ let map = null;
793
+ let tileLayer = null;
794
+ let baseLayer = null;
795
+ let selectedIndex = -1;
796
+ let filteredSpecies = [];
797
+ let currentMapType = 'standard';
798
+
799
+ // Map configurations
800
+ const mapLayers = {
801
+ standard: {
802
+ url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
803
+ attribution: '© OpenStreetMap contributors'
804
+ },
805
+ dark: {
806
+ url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',
807
+ attribution: '© OpenStreetMap contributors, © CARTO'
808
+ },
809
+ satellite: {
810
+ url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
811
+ attribution: 'Tiles © Esri'
812
+ }
813
+ };
814
+
815
+ // Initialize map
816
+ function initMap() {
817
+ map = L.map('map').setView([20, 0], 2);
818
+
819
+ baseLayer = L.tileLayer(mapLayers.standard.url, {
820
+ attribution: mapLayers.standard.attribution,
821
+ maxZoom: 18
822
+ }).addTo(map);
823
+ }
824
+
825
+ // Change map type
826
+ function changeMapType(type) {
827
+ if (baseLayer) {
828
+ map.removeLayer(baseLayer);
829
+ }
830
+
831
+ currentMapType = type;
832
+ const config = mapLayers[type];
833
+
834
+ baseLayer = L.tileLayer(config.url, {
835
+ attribution: config.attribution,
836
+ maxZoom: 18
837
+ }).addTo(map);
838
+
839
+ // Update active button
840
+ document.querySelectorAll('.map-type-btn').forEach(btn => {
841
+ btn.classList.toggle('active', btn.dataset.map === type);
842
+ });
843
+ }
844
+
845
+ // Add event listeners for map type buttons
846
+ document.querySelectorAll('.map-type-btn').forEach(btn => {
847
+ btn.addEventListener('click', () => {
848
+ changeMapType(btn.dataset.map);
849
+ });
850
+ });
851
+
852
+ // Load species occurrences on map
853
+ function loadSpeciesOnMap(taxonKey) {
854
+ if (tileLayer) {
855
+ map.removeLayer(tileLayer);
856
+ }
857
+
858
+ tileLayer = L.tileLayer(
859
+ `https://api.gbif.org/v2/map/occurrence/density/{z}/{x}/{y}@1x.png?taxonKey=${taxonKey}&bin=hex&hexPerTile=100&style=red.marker`,
860
+ {
861
+ attribution: '© GBIF',
862
+ maxZoom: 18
863
+ }
864
+ );
865
+
866
+ tileLayer.addTo(map);
867
+ }
868
+
869
+ // Autocomplete functionality
870
+ const input = document.getElementById('species-input');
871
+ const dropdown = document.getElementById('autocomplete-dropdown');
872
+
873
+ function filterSpecies(query) {
874
+ if (!query) return [];
875
+ const lowerQuery = query.toLowerCase();
876
+ return speciesData.filter(species =>
877
+ species.name.toLowerCase().includes(lowerQuery) ||
878
+ species.commonName.toLowerCase().includes(lowerQuery)
879
+ ).slice(0, 10); // Limit to 10 results
880
+ }
881
+
882
+ function showAutocomplete(species) {
883
+ if (species.length === 0) {
884
+ dropdown.style.display = 'none';
885
+ return;
886
+ }
887
+
888
+ filteredSpecies = species;
889
+ dropdown.innerHTML = species.map((s, index) => `
890
+ <div class="autocomplete-item" data-index="${index}">
891
+ <strong>${s.commonName}</strong>
892
+ <em>${s.name}</em>
893
+ </div>
894
+ `).join('');
895
+
896
+ dropdown.style.display = 'block';
897
+ selectedIndex = -1;
898
+ }
899
+
900
+ input.addEventListener('input', (e) => {
901
+ const filtered = filterSpecies(e.target.value);
902
+ showAutocomplete(filtered);
903
+ });
904
+
905
+ input.addEventListener('keydown', (e) => {
906
+ const items = dropdown.querySelectorAll('.autocomplete-item');
907
+
908
+ if (e.key === 'ArrowDown') {
909
+ e.preventDefault();
910
+ selectedIndex = Math.min(selectedIndex + 1, items.length - 1);
911
+ updateSelection(items);
912
+ } else if (e.key === 'ArrowUp') {
913
+ e.preventDefault();
914
+ selectedIndex = Math.max(selectedIndex - 1, 0);
915
+ updateSelection(items);
916
+ } else if (e.key === 'Enter') {
917
+ e.preventDefault();
918
+ if (selectedIndex >= 0 && selectedIndex < filteredSpecies.length) {
919
+ selectSpecies(filteredSpecies[selectedIndex]);
920
+ } else {
921
+ submitAnswer();
922
+ }
923
+ }
924
+ });
925
+
926
+ function updateSelection(items) {
927
+ items.forEach((item, index) => {
928
+ item.classList.toggle('selected', index === selectedIndex);
929
+ });
930
+ if (selectedIndex >= 0) {
931
+ items[selectedIndex].scrollIntoView({ block: 'nearest' });
932
+ }
933
+ }
934
+
935
+ dropdown.addEventListener('click', (e) => {
936
+ const item = e.target.closest('.autocomplete-item');
937
+ if (item) {
938
+ const index = parseInt(item.dataset.index);
939
+ selectSpecies(filteredSpecies[index]);
940
+ }
941
+ });
942
+
943
+ function selectSpecies(species) {
944
+ input.value = `${species.commonName} (${species.name})`;
945
+ dropdown.style.display = 'none';
946
+ }
947
+
948
+ document.addEventListener('click', (e) => {
949
+ if (!input.contains(e.target) && !dropdown.contains(e.target)) {
950
+ dropdown.style.display = 'none';
951
+ }
952
+ });
953
+
954
+ // Start new round
955
+ function startNewRound() {
956
+ currentSpecies = speciesData[Math.floor(Math.random() * speciesData.length)];
957
+ hintsRevealed = 0;
958
+ answered = false;
959
+
960
+ loadSpeciesOnMap(currentSpecies.taxonKey);
961
+
962
+ document.getElementById('hints-display').innerHTML = '';
963
+ document.getElementById('hint-btn').disabled = false;
964
+ document.getElementById('result-container').innerHTML = '';
965
+ document.getElementById('species-input').value = '';
966
+ document.getElementById('species-input').disabled = false;
967
+ document.getElementById('submit-btn').disabled = false;
968
+ document.getElementById('next-btn').style.display = 'none';
969
+
970
+ input.focus();
971
+ }
972
+
973
+ // Submit answer
974
+ function submitAnswer() {
975
+ if (answered || !input.value.trim()) return;
976
+
977
+ answered = true;
978
+ const userInput = input.value.toLowerCase();
979
+ const isCorrect = userInput.includes(currentSpecies.name.toLowerCase()) ||
980
+ userInput.includes(currentSpecies.commonName.toLowerCase());
981
+
982
+ document.getElementById('species-input').disabled = true;
983
+ document.getElementById('submit-btn').disabled = true;
984
+
985
+ if (isCorrect) {
986
+ const points = Math.max(3 - hintsRevealed, 1);
987
+ score += points;
988
+ document.getElementById('score').textContent = score;
989
+
990
+ document.getElementById('result-container').innerHTML = `
991
+ <div class="result-message correct">
992
+ ✓ Correct ! C'était bien ${currentSpecies.commonName}<br>
993
+ <em>${currentSpecies.name}</em><br>
994
+ +${points} point${points > 1 ? 's' : ''}
995
+ </div>
996
+ `;
997
+ } else {
998
+ document.getElementById('result-container').innerHTML = `
999
+ <div class="result-message incorrect">
1000
+ ✗ Incorrect ! C'était ${currentSpecies.commonName}<br>
1001
+ <em>${currentSpecies.name}</em>
1002
+ </div>
1003
+ `;
1004
+ }
1005
+
1006
+ document.getElementById('next-btn').style.display = 'block';
1007
+ document.getElementById('hint-btn').disabled = true;
1008
+ }
1009
+
1010
+ document.getElementById('submit-btn').addEventListener('click', submitAnswer);
1011
+
1012
+ // Handle hint request
1013
+ document.getElementById('hint-btn').addEventListener('click', () => {
1014
+ if (hintsRevealed >= currentSpecies.hints.length || answered) return;
1015
+
1016
+ const hint = currentSpecies.hints[hintsRevealed];
1017
+ const hintElement = document.createElement('div');
1018
+ hintElement.className = 'hint-item';
1019
+ hintElement.innerHTML = `
1020
+ <div class="hint-label">Indice ${hintsRevealed + 1} :</div>
1021
+ ${hint}
1022
+ `;
1023
+
1024
+ document.getElementById('hints-display').appendChild(hintElement);
1025
+ hintsRevealed++;
1026
+
1027
+ if (hintsRevealed >= currentSpecies.hints.length) {
1028
+ document.getElementById('hint-btn').disabled = true;
1029
+ document.getElementById('hint-btn').textContent = 'Tous les indices révélés';
1030
+ }
1031
+ });
1032
+
1033
+ // Handle next round
1034
+ document.getElementById('next-btn').addEventListener('click', startNewRound);
1035
+
1036
+ // Initialize game
1037
+ initMap();
1038
+ startNewRound();
1039
+ </script>
1040
+ </body>
1041
+ </html>