Update human-evolution.html

D David Veksler · 1 year ago 6ade467279434e22cb9fd3685b563e2fe4d83930
Parent: 099aea0ca

1 file changed +225 −288

Diff

diff --git a/human-evolution.html b/human-evolution.html
index aadb972..647a5cc 100644
--- a/human-evolution.html
+++ b/human-evolution.html
@@ -3,7 +3,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>Human Evolution: Journey Through Time (Concise) - AWESOME Edition v3</title>
+    <title>Human Evolution: Journey Through Time (Concise) - AWESOME Edition v4 (Fossil Markers)</title>
     <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css" />
     <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
@@ -32,7 +32,7 @@
         --text-muted-color: #90909A;
         --text-heading-color: #FFFFFF;
 
-        --timeline-period-color: #FFC107;
+        --timeline-period-color: #FFC107; /* Amber for current period, also used for fossil markers */
 
         /* Typography */
         --font-primary: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
@@ -309,7 +309,6 @@
           box-shadow: 0 4px 12px rgba(var(--danger-accent-rgb), 0.5);
       }
       
-      /* Period Navigator Select Styling */
       #period-filter-select {
         background-color: var(--dark-bg);
         color: var(--text-color);
@@ -422,7 +421,7 @@
         background-color: rgba(var(--warning-accent-rgb), 0.05);
         padding: 0.5rem;
         border-radius: 4px;
-        border-top: none; /* Removed original dashed top border as it's a box now */
+        border-top: none; 
       }
       .data-limitation-note i {
         margin-right: 0.35rem;
@@ -578,6 +577,17 @@
         border-bottom: 1px solid var(--light-bg);
         padding-bottom: 0.4rem;
       }
+       .leaflet-popup-content h5 i { /* Icon styling within popup title */
+        margin-right: 0.3em;
+        color: inherit; /* Inherit color from h5, or set specifically */
+      }
+      .popup-hr { /* Styling for HR in popups */
+        margin: 0.3rem 0;
+        border-color: var(--light-bg); 
+        border-top-width: 1px;
+        opacity: 0.5;
+      }
+
       .leaflet-container a.leaflet-popup-close-button {
         color: var(--text-muted-color);
         padding: 8px 8px 0 0;
@@ -593,7 +603,7 @@
         margin-left: auto;
         margin-right: auto;
         border: 1px solid var(--light-bg);
-        border-radius: var(--border-radius-standard); /* Match other radii */
+        border-radius: var(--border-radius-standard); 
       }
       .popup-learn-more {
         color: var(--primary-accent-static);
@@ -615,7 +625,7 @@
         outline-offset: 2px;
       }
       #species-filter-list .form-check-input:focus-visible,
-      #period-filter-select:focus-visible { /* Add period filter to custom focus */
+      #period-filter-select:focus-visible {
         box-shadow: 0 0 0 2px var(--dark-bg), 0 0 0 4px var(--focus-ring-color);
       }
       .tooltip-inner {
@@ -634,67 +644,40 @@
 
       /* Responsive Adjustments */
       @media (max-width: 992px) {
-        #main-content {
-          flex-direction: column;
-        }
+        #main-content { flex-direction: column; }
         #controls-sidebar {
           width: 100%;
-          max-height: 45vh; /* Original */
+          max-height: 45vh; 
           border-right: none;
           border-bottom: 1px solid var(--light-bg);
         }
-        #map-container {
-          flex-grow: 1;
-          height: auto;
-        }
+        #map-container { flex-grow: 1; height: auto; }
       }
 
       @media (max-width: 767.98px) {
-        :root {
-            /* --sidebar-width: 100%; Already handled by .controls-sidebar in this query */
-        }
-
         header.app-header h1 { font-size: 1.3rem; }
         header.app-header h1 i { margin-right: 0.5rem; }
 
-        #controls-sidebar {
-            padding: 0.75rem;
-            gap: 0.75rem;
-            max-height: 50vh; 
-        }
-
+        #controls-sidebar { padding: 0.75rem; gap: 0.75rem; max-height: 50vh; }
         .control-card .card-header { font-size: 0.8rem; padding: 0.5rem 0.75rem; }
         .control-card .card-body { padding: 0.6rem 0.75rem; }
-
         #current-period-display { font-size: 1.1rem; }
         #timeline-value-display { font-size: 0.7rem; margin-bottom: 0.5rem; }
         #timeline-scrubber { margin: 0.5rem 0; }
         #timeline-scrubber::-webkit-slider-thumb { width: 18px; height: 18px; }
         #timeline-scrubber::-moz-range-thumb { width: 18px; height: 18px; }
-
-
-        .timeline-buttons .btn,
-        .quick-filter-buttons .btn,
-        #reset-button { padding: 0.3rem 0.75rem; font-size: 0.75rem; }
+        .timeline-buttons .btn, .quick-filter-buttons .btn, #reset-button { padding: 0.3rem 0.75rem; font-size: 0.75rem; }
         .timeline-buttons .btn i, #reset-button i { margin-right: 0.25rem; }
-
         #period-filter-select { font-size: 0.75rem; padding-top: 0.3rem; padding-bottom: 0.3rem; }
-
         #species-filter-list .form-check-label { font-size: 0.75rem; }
         #species-filter-list .form-check-input { width: 1em; height: 1em; }
         #species-filter-list .form-check-input:checked::before { font-size: 0.7em; }
         .species-color-indicator { width: 10px; height: 10px; }
-
-
-        #narrative-panel .card-body,
-        #narrative-panel .card-body p#narrative-text-element,
-        .data-limitation-note { font-size: 0.75rem; }
-
+        #narrative-panel .card-body, #narrative-panel .card-body p#narrative-text-element, .data-limitation-note { font-size: 0.75rem; }
         .legend { padding: 0.5rem 0.75rem; max-height: 150px; }
         .legend h5 { font-size: 0.8rem; }
         .legend-item { font-size: 0.7rem; }
         .legend-color-box { width: 10px; height: 10px; }
-
         .leaflet-popup-content { padding: 0.6rem 0.8rem; font-size: 0.75rem; }
         .leaflet-popup-content h5 { font-size: 1em; }
       }
@@ -703,41 +686,22 @@
         header.app-header { padding: 0 1rem; }
         header.app-header h1 { font-size: 1.15rem; }
         header.app-header h1 i { font-size: 0.9em; }
-
-
         #controls-sidebar { padding: 0.5rem; gap: 0.5rem; }
-
         .control-card .card-header { font-size: 0.75rem; padding: 0.4rem 0.6rem; }
         .control-card .card-header i { font-size: 0.85em; }
         .control-card .card-body { padding: 0.5rem 0.6rem; }
         .control-card .card-header + .card-body { padding-top: 0.75rem; }
-
-
         #current-period-display { font-size: 1rem; }
-
         .timeline-buttons { flex-wrap: wrap; gap: 0.25rem; }
-        .timeline-buttons .btn,
-        .timeline-buttons .btn-group, /* Target group directly for basis */
-        #reset-button { /* Play, Group, Reset */
-             flex-grow: 1; /* Allow them to grow */
-             flex-basis: auto; /* Reset basis or set to a meaningful min-content */
-        }
-         /* Make all three items (Play button, Speed group, Reset button) share space */
         .d-flex.justify-content-between.align-items-center.mt-2.timeline-buttons > * {
-            flex-basis: calc(33.333% - 0.2rem); /* Approx 1/3 width, accounting for gap */
-            min-width: 80px; /* Prevent them from becoming too small */
+            flex-basis: calc(33.333% - 0.2rem); 
+            min-width: 70px; /* Further reduced min-width */
         }
         .timeline-buttons .btn-group { display: flex; }
         .timeline-buttons .btn-group .btn { flex-grow: 1; }
-
-
         .quick-filter-buttons .btn { font-size: 0.7rem; padding: 0.25rem 0.5rem; }
-
         #species-filter-list { max-height: 120px; }
-        
-        #narrative-panel .card-body,
-        #narrative-panel .card-body p#narrative-text-element,
-        .data-limitation-note { font-size: 0.7rem; }
+        #narrative-panel .card-body, #narrative-panel .card-body p#narrative-text-element, .data-limitation-note { font-size: 0.7rem; }
         .data-limitation-note i { display: none; }
       }
 
@@ -803,14 +767,12 @@
             </div>
           </div>
 
-          <!-- NEW: Period Navigation Card -->
           <div class="control-card card">
               <div class="card-header"><i class="bi bi-collection-play"></i> Period Navigator</div>
               <div class="card-body">
                   <label for="period-filter-select" class="form-label visually-hidden">Select a Time Period</label>
                   <select class="form-select" id="period-filter-select" data-bs-toggle="tooltip" title="Jump to a specific period">
                       <option selected disabled value="">Select a period...</option>
-                      <!-- Options will be populated by JavaScript -->
                   </select>
               </div>
           </div>
@@ -893,6 +855,7 @@
     
         let iceSheetLayerGroup = L.layerGroup();
         let speciesGeoJsonLayerGroup = L.layerGroup().addTo(map);
+        let fossilSiteLayerGroup = L.layerGroup().addTo(map); // Layer for fossil markers
     
         let currentPeriodIndex = 0;
         let selectedSpecies = {};
@@ -917,14 +880,14 @@
             loadingScreen: null,
             controlsContentDiv: null,
             climateToggle: null,
-            periodFilterSelect: null // Added for Period Navigator
+            periodFilterSelect: null 
         };
     
         function populateDomElements() {
             const idMap = {
                 controlsContentDiv: 'controls-content',
                 climateToggle: 'climate-toggle-switch',
-                periodFilterSelect: 'period-filter-select' // Added
+                periodFilterSelect: 'period-filter-select' 
             };
             for (const key in domElements) {
                 if (key === 'playPauseIcon' || key === 'playPauseText') continue;
@@ -937,8 +900,6 @@
             if (domElements.playPauseButton) {
                 domElements.playPauseIcon = domElements.playPauseButton.querySelector('i');
                 domElements.playPauseText = domElements.playPauseButton.querySelector('span');
-                if (!domElements.playPauseIcon) console.warn("Play/Pause button icon (<i>) not found.");
-                if (!domElements.playPauseText) console.warn("Play/Pause button text (<span>) not found.");
             } else {
                 console.error("playPauseButton element not found, cannot derive icon and text elements.");
             }
@@ -952,26 +913,27 @@
                 }
 
                 const [evolutionResponse, iceSheetResponse] = await Promise.all([
-                    fetch('https://cheatsheets.davidveksler.com/evolution_data.json'),
-                    fetch('https://cheatsheets.davidveksler.com/iceSheetGeoJson.json')
+                    fetch('https://cheatsheets.davidveksler.com/evolution_data.json'), // Ensure this path is correct
+                    fetch('https://cheatsheets.davidveksler.com/iceSheetGeoJson.json') // Ensure this path is correct
                 ]);
 
-                if (!evolutionResponse.ok) {
-                    throw new Error(`HTTP error! status: ${evolutionResponse.status} for evolution data`);
-                }
-                if (!iceSheetResponse.ok) {
-                    throw new Error(`HTTP error! status: ${iceSheetResponse.status} for ice sheet data`);
-                }
+                if (!evolutionResponse.ok) throw new Error(`HTTP error! status: ${evolutionResponse.status} for evolution data`);
+                if (!iceSheetResponse.ok) throw new Error(`HTTP error! status: ${iceSheetResponse.status} for ice sheet data`);
 
                 timePeriodsData = await evolutionResponse.json();
                 fetchedIceSheetGeoJson = await iceSheetResponse.json(); 
 
-                if (!Array.isArray(timePeriodsData) || timePeriodsData.length === 0) {
-                    throw new Error("Fetched evolution data is not a valid array or is empty.");
-                }
-                if (typeof fetchedIceSheetGeoJson !== 'object' || fetchedIceSheetGeoJson === null) {
-                    throw new Error("Fetched ice sheet data is not a valid object.");
-                }
+                if (!Array.isArray(timePeriodsData) || timePeriodsData.length === 0) throw new Error("Fetched evolution data is not a valid array or is empty.");
+                if (typeof fetchedIceSheetGeoJson !== 'object' || fetchedIceSheetGeoJson === null) throw new Error("Fetched ice sheet data is not a valid object.");
+
+                // Sort timePeriodsData chronologically
+                timePeriodsData.sort((a, b) => {
+                    if (a.numericStartYear == null || b.numericStartYear == null) { 
+                        console.warn("Data integrity: Found period(s) without numericStartYear. Sorting may be affected.");
+                        return 0; 
+                    }
+                    return a.numericStartYear - b.numericStartYear;
+                });
 
                 initializeApplication();
             } catch (error) {
@@ -982,6 +944,7 @@
                      domElements.loadingScreen.innerHTML = `<div class='p-3 text-center'><i class='bi bi-exclamation-triangle-fill text-danger h1'></i><p class="text-light">Failed to load required data.<br><small>${error.message}</small></p></div>`;
                 }
             }
+            // The redundant try...catch block that was here has been removed.
         }
     
         function populatePeriodFilter() {
@@ -990,13 +953,12 @@
                 return;
             }
             domElements.periodFilterSelect.disabled = false;
-            domElements.periodFilterSelect.innerHTML = ''; // Clear existing options
+            domElements.periodFilterSelect.innerHTML = ''; 
 
             const defaultOption = document.createElement('option');
             defaultOption.textContent = 'Select a period...';
             defaultOption.value = ""; 
             defaultOption.disabled = true;
-            // defaultOption.selected = true; // Will be handled by updateUIForCurrentPeriod setting the correct index
             domElements.periodFilterSelect.appendChild(defaultOption);
 
             timePeriodsData.forEach((period, index) => {
@@ -1006,35 +968,31 @@
                 domElements.periodFilterSelect.appendChild(option);
             });
         }
-
     
         function initializeApplication() {
             if (!domElements.loadingScreen || !domElements.controlsContentDiv) {
-                console.error("Core UI elements (loadingScreen or controlsContentDiv) not found. Cannot initialize application properly.");
-                document.body.innerHTML = `<div class='p-5 text-center text-danger'><h1>Application Error</h1><p>Essential UI components are missing. Please check the HTML structure and element IDs.</p></div>`;
+                document.body.innerHTML = `<div class='p-5 text-center text-danger'><h1>Application Error</h1><p>Essential UI components are missing.</p></div>`;
                 return;
             }
 
             domElements.loadingScreen.style.display = 'none';
             domElements.controlsContentDiv.classList.remove('d-none');
 
-            Object.values(domElements).forEach(el => {
-                if (el && el.id !== 'period-filter-select' && typeof el.disabled === 'boolean') { // Don't enable period filter select here
+            Object.keys(domElements).forEach(key => {
+                const el = domElements[key];
+                if (el && el.id !== 'period-filter-select' && typeof el.disabled === 'boolean') {
                     el.disabled = false;
                 }
             });
-            if (domElements.timelineScrubber) {
-                domElements.timelineScrubber.max = timePeriodsData.length - 1;
-            }
+            if (domElements.timelineScrubber) domElements.timelineScrubber.max = timePeriodsData.length - 1;
 
             populateAllSpeciesList();
             populateSpeciesFilter();
-            populatePeriodFilter(); // Populate period filter
+            populatePeriodFilter(); 
             currentPeriodIndex = 0;
             updateSpeedButtonsActiveState(); 
             updateQuickFilterActiveState('filter-all'); 
-            updateUIForCurrentPeriod(); // This will now also set periodFilterSelect
-
+            updateUIForCurrentPeriod();
 
             const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
             tooltipTriggerList.map(function (tooltipTriggerEl) {
@@ -1045,13 +1003,11 @@
         function populateAllSpeciesList() {
             const speciesSet = new Map();
             timePeriodsData.forEach(period => {
-                if (period.species && Array.isArray(period.species)) {
-                    period.species.forEach(s => {
-                        if (s && s.name && !speciesSet.has(s.name)) { 
-                            speciesSet.set(s.name, { color: s.color || '#cccccc' }); 
-                        }
-                    });
-                }
+                (period.species || []).forEach(s => {
+                    if (s && s.name && !speciesSet.has(s.name)) { 
+                        speciesSet.set(s.name, { color: s.color || '#cccccc' }); 
+                    }
+                });
             });
             allSpeciesList = Array.from(speciesSet, ([name, data]) => ({ name, ...data }));
             allSpeciesList.sort((a, b) => a.name.localeCompare(b.name));
@@ -1060,12 +1016,11 @@
         function populateSpeciesFilter() {
             domElements.speciesFilterList.innerHTML = '';
             if (allSpeciesList.length === 0) {
-                domElements.speciesFilterList.innerHTML = '<p class="text-muted p-2 small">No species found in data.</p>'; return;
+                domElements.speciesFilterList.innerHTML = '<p class="text-muted p-2 small">No species data.</p>'; return;
             }
             allSpeciesList.forEach(s => {
                 selectedSpecies[s.name] = true; 
-                const itemDiv = document.createElement('div');
-                itemDiv.className = 'form-check';
+                const itemDiv = document.createElement('div'); itemDiv.className = 'form-check';
                 const input = document.createElement('input');
                 input.type = 'checkbox'; input.className = 'form-check-input';
                 input.id = `filter-${s.name.replace(/\W/g, '_')}`; input.value = s.name; input.checked = true;
@@ -1075,47 +1030,33 @@
                     updateQuickFilterActiveState(null); 
                 });
                 const colorIndicator = document.createElement('span');
-                colorIndicator.className = 'species-color-indicator';
-                colorIndicator.style.backgroundColor = s.color;
-    
+                colorIndicator.className = 'species-color-indicator'; colorIndicator.style.backgroundColor = s.color;
                 const label = document.createElement('label');
-                label.className = 'form-check-label'; label.htmlFor = input.id;
-                label.textContent = s.name;
-    
-                itemDiv.appendChild(input);
-                itemDiv.appendChild(colorIndicator); 
-                itemDiv.appendChild(label);
+                label.className = 'form-check-label'; label.htmlFor = input.id; label.textContent = s.name;
+                itemDiv.appendChild(input); itemDiv.appendChild(colorIndicator); itemDiv.appendChild(label);
                 domElements.speciesFilterList.appendChild(itemDiv);
             });
         }
     
         function updateUIForCurrentPeriod() {
-            speciesGeoJsonLayerGroup.clearLayers(); 
+            speciesGeoJsonLayerGroup.clearLayers();
+            fossilSiteLayerGroup.clearLayers(); 
     
             if (!timePeriodsData || timePeriodsData.length === 0 || currentPeriodIndex < 0 || currentPeriodIndex >= timePeriodsData.length) {
                 if(domElements.currentPeriodDisplay) domElements.currentPeriodDisplay.textContent = `Timeline End`;
-                if(domElements.timelineValueDisplay) domElements.timelineValueDisplay.textContent = "(Drag scrubber or Reset)";
-                if(domElements.narrativeTextElement) {
-                    domElements.narrativeTextElement.style.color = 'var(--text-color)';
-                    domElements.narrativeTextElement.textContent = "End of timeline data.";
-                }
-                if(domElements.legendItemsContainer) domElements.legendItemsContainer.innerHTML = '<small class="text-muted">No active period.</small>';
-                if(domElements.periodFilterSelect) domElements.periodFilterSelect.value = ""; // Select placeholder
+                if(domElements.timelineValueDisplay) domElements.timelineValueDisplay.textContent = "(Drag or Reset)";
+                if(domElements.narrativeTextElement) domElements.narrativeTextElement.textContent = "End of timeline.";
+                if(domElements.legendItemsContainer) domElements.legendItemsContainer.innerHTML = '<small class="text-muted">No period.</small>';
+                if(domElements.periodFilterSelect) domElements.periodFilterSelect.value = ""; 
                 return;
             }
     
             const period = timePeriodsData[currentPeriodIndex];
-            if(domElements.currentPeriodDisplay) domElements.currentPeriodDisplay.textContent = period.periodName || "Unknown Period";
+            if(domElements.currentPeriodDisplay) domElements.currentPeriodDisplay.textContent = period.periodName || "Unknown";
             if(domElements.timelineValueDisplay) domElements.timelineValueDisplay.textContent = period.timeRange || `Period ${currentPeriodIndex + 1}`;
             if (domElements.timelineScrubber) domElements.timelineScrubber.value = currentPeriodIndex;
-            if (domElements.periodFilterSelect) { // Set period filter select
-                 domElements.periodFilterSelect.value = currentPeriodIndex;
-            }
-            
-            if(domElements.narrativeTextElement) {
-                domElements.narrativeTextElement.style.color = 'var(--text-color)';
-                domElements.narrativeTextElement.innerHTML = period.narrative || "No narrative available for this period.";
-            }
+            if (domElements.periodFilterSelect) domElements.periodFilterSelect.value = currentPeriodIndex;
+            if(domElements.narrativeTextElement) domElements.narrativeTextElement.innerHTML = period.narrative || "No narrative.";
     
             let speciesInCurrentPeriod = period.species || [];
             let visibleSpeciesInLegend = [];
@@ -1124,51 +1065,54 @@
                 if (s && s.name && selectedSpecies[s.name]) {
                     visibleSpeciesInLegend.push(s); 
     
-                    // ENHANCED POPUP CONTENT
-                    let learnMoreLink = s.learnMoreUrl ? `<p class="mb-1 mt-1 small"><a href="${s.learnMoreUrl}" target="_blank" rel="noopener noreferrer" class="popup-learn-more">Learn More <i class="bi bi-box-arrow-up-right"></i></a></p>` : '';
                     let speciesImage = s.imageUrl ? `<img src="${s.imageUrl}" alt="${s.name}" class="img-fluid rounded mb-2 popup-species-image">` : '';
-
-                    let popupContent = `<h5>${s.name}</h5>
-                                        ${speciesImage}
-                                        <p class="mb-1 small"><strong>Timeline:</strong> ${s.timeline || 'N/A'}</p>
-                                        <p class="mb-0 small">${s.notes || 'No specific notes.'}</p>
-                                        ${learnMoreLink}`;
+                    let learnMoreLink = s.learnMoreUrl ? `<p class="mb-1 mt-1 small"><a href="${s.learnMoreUrl}" target="_blank" rel="noopener noreferrer" class="popup-learn-more">Learn More <i class="bi bi-box-arrow-up-right"></i></a></p>` : '';
+                    let speciesRangePopupContent = `<h5>${s.name}</h5>${speciesImage}<p class="mb-1 small"><strong>Timeline:</strong> ${s.timeline||'N/A'}</p><p class="mb-0 small">${s.notes||'No notes.'}</p>${learnMoreLink}`;
     
                     if (s.estimatedRangeGeoJson && Object.keys(s.estimatedRangeGeoJson).length > 0) {
                         try {
-                            L.geoJSON(s.estimatedRangeGeoJson, {
-                                style: { 
-                                    fillColor: s.color || '#888888',
-                                    weight: 1.5, 
-                                    opacity: 1,
-                                    color: 'rgba(255,255,255,0.3)', 
-                                    fillOpacity: 0.55,
-                                }
-                            }).bindPopup(popupContent).addTo(speciesGeoJsonLayerGroup);
+                            L.geoJSON(s.estimatedRangeGeoJson, { style: { fillColor: s.color||'#888', weight:1.5, opacity:1, color:'rgba(255,255,255,0.3)', fillOpacity:0.55 }})
+                             .bindPopup(speciesRangePopupContent).addTo(speciesGeoJsonLayerGroup);
                         } catch (e) { console.warn("Error drawing range for", s.name, e); }
                     }
     
                     if (s.migrationPaths && Array.isArray(s.migrationPaths)) {
                         s.migrationPaths.forEach(path => {
                             if (path && Object.keys(path).length > 0) {
-                               try {
-                                    L.geoJSON(path, {
-                                        style: { 
-                                            color: s.migrationColor || s.color || '#888888',
-                                            weight: 3, 
-                                            opacity: 0.75,
-                                            dashArray: '8, 6', 
-                                            lineCap: 'round' 
-                                        }
-                                    }).bindPopup(popupContent).addTo(speciesGeoJsonLayerGroup);
-                                } catch (e) { console.warn("Error drawing migration for", s.name, e); }
+                               try { L.geoJSON(path, { style: { color:s.migrationColor||s.color||'#888', weight:3, opacity:0.75, dashArray:'8, 6', lineCap:'round' }})
+                                     .bindPopup(speciesRangePopupContent).addTo(speciesGeoJsonLayerGroup); } catch (e) { console.warn("Error drawing migration for", s.name, e); }
+                            }
+                        });
+                    }
+
+                    // Plot Fossil Site Markers
+                    if (s.locations && Array.isArray(s.locations)) {
+                        s.locations.forEach(loc => {
+                            if (loc.latitude != null && loc.longitude != null) {
+                                const markerCertainty = loc.certainty || 0.7;
+                                const markerOptions = {
+                                    radius: 5,
+                                    fillColor: "var(--timeline-period-color)", // Amber
+                                    color: s.color || "var(--light-bg)",      
+                                    weight: 1.5,                              
+                                    opacity: 1,
+                                    fillOpacity: 0.6 + (markerCertainty * 0.3)
+                                };
+                                let fossilPopupContent = `<h5><i class="bi bi-compass"></i> ${loc.siteName}</h5>
+                                                          <p class="mb-1 small">${loc.details}</p>
+                                                          <hr class="popup-hr">
+                                                          <p class="mb-0 small"><strong>Found:</strong> ${s.name}</p>
+                                                          ${loc.certainty ? `<p class="mb-0 small"><strong>Discovery Certainty:</strong> ${(markerCertainty * 100).toFixed(0)}%</p>` : ''}`;
+                                L.circleMarker([loc.latitude, loc.longitude], markerOptions)
+                                    .bindPopup(fossilPopupContent)
+                                    .addTo(fossilSiteLayerGroup);
                             }
                         });
                     }
                 }
             });
             updateLegend(visibleSpeciesInLegend);
-            updateClimateOverlay(period.timeRange);
+            updateClimateOverlay(period);
         }
     
         function updateLegend(visibleSpecies) {
@@ -1192,49 +1136,84 @@
             if (!rangeString) return { start: null, end: null };
             const cleaned = rangeString.toLowerCase().replace(/c\.|ago|years|million|kya|mya/g, '').trim();
             const parts = cleaned.split(/\s*-\s*|\s+to\s+/);
-    
             function parsePart(part) {
-                part = part.trim();
-                let num = parseFloat(part.replace(/,/g, '')); 
-                if (rangeString.toLowerCase().includes("million") || rangeString.toLowerCase().includes("mya")) {
-                    num *= 1000000;
-                } else if (rangeString.toLowerCase().includes("kya")) {
-                    num *= 1000;
-                }
+                part = part.trim(); let num = parseFloat(part.replace(/,/g, '')); 
+                if (rangeString.toLowerCase().includes("million") || rangeString.toLowerCase().includes("mya")) num *= 1000000;
+                else if (rangeString.toLowerCase().includes("kya")) num *= 1000;
                 return isNaN(num) ? null : -Math.abs(num); 
             }
-    
             let startYear = parsePart(parts[0]);
             let endYear = parts.length > 1 ? parsePart(parts[1]) : startYear;
-    
-            if (startYear && endYear === null) endYear = startYear;
-            if (endYear && startYear === null) startYear = endYear;
-    
-            if (startYear && endYear && startYear > endYear) {
-                [startYear, endYear] = [endYear, startYear];
-            }
+            if (startYear && endYear === null) endYear = startYear; if (endYear && startYear === null) startYear = endYear;
+            if (startYear && endYear && startYear > endYear) [startYear, endYear] = [endYear, startYear];
             return { start: startYear, end: endYear };
         }
     
-        function updateClimateOverlay(periodTimeRange) {
+        function updateClimateOverlay(period) { // Accepts the full period object
             iceSheetLayerGroup.clearLayers();
-            if (domElements.climateToggle && domElements.climateToggle.checked && periodTimeRange && fetchedIceSheetGeoJson) {
-                const { start, end } = parseYearFromRange(periodTimeRange);
-                const lgmStart = -26500; 
-                const lgmEnd = -19000;  
-    
-                if (start && end && Math.max(start, lgmStart) <= Math.min(end, lgmEnd)) {
+            // --- DEBUGGING START ---
+            console.log("Attempting to update climate overlay.");
+            if (domElements.climateToggle) {
+                console.log("Climate Toggle Exists. Checked:", domElements.climateToggle.checked);
+            } else {
+                console.log("Climate Toggle DOM element NOT FOUND.");
+                // Fallback or early exit if essential controls are missing
+                return;
+            }
+
+            if (period) {
+                console.log("Current Period:", period.periodName, 
+                            "Numeric Start:", period.numericStartYear, 
+                            "Numeric End:", period.numericEndYear);
+            } else {
+                console.log("Current Period object is null or undefined.");
+            }
+
+            if (!fetchedIceSheetGeoJson) {
+                console.log("fetchedIceSheetGeoJson is null or not loaded.");
+            }
+            // --- DEBUGGING END ---
+
+            if (domElements.climateToggle.checked && period &&
+                period.numericStartYear != null && period.numericEndYear != null && // Ensure numeric years are present
+                fetchedIceSheetGeoJson) {
+
+                const currentPeriodStart = period.numericStartYear;
+                const currentPeriodEnd = period.numericEndYear;
+
+                const lgmStart = -26500; // Last Glacial Maximum start ~26,500 years ago
+                const lgmEnd = -19000;   // Last Glacial Maximum end ~19,000 years ago
+
+                // --- DEBUGGING START ---
+                console.log(`Checking LGM overlap: Period (${currentPeriodStart} to ${currentPeriodEnd}) vs LGM (${lgmStart} to ${lgmEnd})`);
+                // --- DEBUGGING END ---
+                
+                // Check for overlap: The LGM period must overlap with the current hominin period
+                const isOverlap = Math.max(currentPeriodStart, lgmStart) <= Math.min(currentPeriodEnd, lgmEnd);
+
+                // --- DEBUGGING START ---
+                console.log("Is LGM overlapping with current period?", isOverlap);
+                // --- DEBUGGING END ---
+
+                if (isOverlap) {
+                    // --- DEBUGGING START ---
+                    console.log("Overlap with LGM detected. Adding ice sheets to layer group.");
+                    let sheetsAddedCount = 0;
+                    // --- DEBUGGING END ---
                     Object.values(fetchedIceSheetGeoJson).forEach(sheet => {
-                        if (sheet && sheet.type && sheet.coordinates) { 
-                           try {
+                        if (sheet && sheet.type && sheet.coordinates) {
+                            try {
                                 L.geoJSON(sheet, {
-                                    style: { 
-                                        color: 'rgba(173, 216, 230, 0.5)', 
-                                        fillColor: '#A2D1E6', 
+                                    style: {
+                                        color: 'rgba(173,216,230,0.5)',
+                                        fillColor: '#A2D1E6',
                                         fillOpacity: 0.35,
                                         weight: 1
                                     }
                                 }).addTo(iceSheetLayerGroup);
+                                // --- DEBUGGING START ---
+                                sheetsAddedCount++;
+                                // --- DEBUGGING END ---
                             } catch (e) {
                                 console.warn("Error drawing ice sheet GeoJSON feature:", e, sheet);
                             }
@@ -1242,27 +1221,40 @@
                             console.warn("Invalid GeoJSON feature structure in ice sheet data:", sheet);
                         }
                     });
+                    // --- DEBUGGING START ---
+                    console.log(sheetsAddedCount + " ice sheet features processed.");
+                    // --- DEBUGGING END ---
                 }
+            } else {
+                // --- DEBUGGING START ---
+                let conditionsNotMetReason = "Conditions for displaying ice sheets not met:";
+                if (!domElements.climateToggle.checked) conditionsNotMetReason += " Toggle not checked.";
+                if (!period) conditionsNotMetReason += " Period undefined.";
+                else if (period.numericStartYear == null || period.numericEndYear == null) conditionsNotMetReason += " Numeric years missing in period.";
+                if (!fetchedIceSheetGeoJson) conditionsNotMetReason += " Ice sheet data not fetched.";
+                console.log(conditionsNotMetReason);
+                // --- DEBUGGING END ---
             }
-            if (domElements.climateToggle) { 
-                if (!map.hasLayer(iceSheetLayerGroup) && domElements.climateToggle.checked && iceSheetLayerGroup.getLayers().length > 0) {
+
+            // Add or remove the layer group from the map based on its content and toggle state
+            if (domElements.climateToggle.checked && iceSheetLayerGroup.getLayers().length > 0) {
+                if (!map.hasLayer(iceSheetLayerGroup)) {
                     map.addLayer(iceSheetLayerGroup);
-                } else if (map.hasLayer(iceSheetLayerGroup) && (!domElements.climateToggle.checked || iceSheetLayerGroup.getLayers().length === 0)) {
+                    console.log("iceSheetLayerGroup added to map.");
+                }
+            } else {
+                if (map.hasLayer(iceSheetLayerGroup)) {
                     map.removeLayer(iceSheetLayerGroup);
+                    console.log("iceSheetLayerGroup removed from map.");
                 }
             }
         }
     
         function animationLoop(timestamp) {
             if (!isPlaying) return;
-    
             if (timestamp - lastFrameTime >= (baseAnimationInterval / playbackSpeed)) {
-                lastFrameTime = timestamp;
-                currentPeriodIndex++;
-                if (currentPeriodIndex >= timePeriodsData.length) {
-                    currentPeriodIndex = timePeriodsData.length - 1; 
-                    pauseAnimation();
-                }
+                lastFrameTime = timestamp; currentPeriodIndex++;
+                if (currentPeriodIndex >= timePeriodsData.length) { currentPeriodIndex = timePeriodsData.length - 1; pauseAnimation(); }
                 updateUIForCurrentPeriod();
             }
             animationFrameId = requestAnimationFrame(animationLoop);
@@ -1274,9 +1266,7 @@
             if (domElements.playPauseIcon) domElements.playPauseIcon.className = 'bi bi-pause-fill';
             if (domElements.playPauseText) domElements.playPauseText.textContent = "Pause";
             lastFrameTime = performance.now();
-            if (currentPeriodIndex >= timePeriodsData.length - 1 && timePeriodsData.length > 0) {
-                currentPeriodIndex = 0;
-            }
+            if (currentPeriodIndex >= timePeriodsData.length - 1 && timePeriodsData.length > 0) currentPeriodIndex = 0;
             updateUIForCurrentPeriod(); 
             animationFrameId = requestAnimationFrame(animationLoop);
         }
@@ -1285,132 +1275,79 @@
             isPlaying = false;
             if (domElements.playPauseIcon) domElements.playPauseIcon.className = 'bi bi-play-fill';
             if (domElements.playPauseText) domElements.playPauseText.textContent = "Play";
-            if (animationFrameId) {
-                cancelAnimationFrame(animationFrameId);
-            }
+            if (animationFrameId) cancelAnimationFrame(animationFrameId);
         }
     
-        function togglePlayPause() {
-            if (isPlaying) {
-                pauseAnimation();
-            } else {
-                playAnimation();
-            }
-        }
+        function togglePlayPause() { if (isPlaying) pauseAnimation(); else playAnimation(); }
     
         function resetAnimation() {
-            pauseAnimation();
-            currentPeriodIndex = 0;
+            pauseAnimation(); currentPeriodIndex = 0;
             if (domElements.timelineScrubber) domElements.timelineScrubber.value = 0;
-            // periodFilterSelect will be updated by updateUIForCurrentPeriod
-            playbackSpeed = 1;
-            updateSpeedButtonsActiveState();
+            playbackSpeed = 1; updateSpeedButtonsActiveState();
             if (allSpeciesList && allSpeciesList.length > 0) {
-                 Object.keys(selectedSpecies).forEach(sName => {
-                    selectedSpecies[sName] = true;
-                });
-                 document.querySelectorAll('#species-filter-list input[type="checkbox"]').forEach(cb => {
-                    cb.checked = true;
-                });
+                 Object.keys(selectedSpecies).forEach(sName => { selectedSpecies[sName] = true; });
+                 document.querySelectorAll('#species-filter-list input[type="checkbox"]').forEach(cb => { cb.checked = true; });
             }
             updateQuickFilterActiveState('filter-all'); 
-            updateUIForCurrentPeriod(); // This will sync periodFilterSelect
+            updateUIForCurrentPeriod(); 
         }
     
         function updateSpeedButtonsActiveState() {
             document.querySelectorAll('.speed-btn').forEach(btn => {
-                btn.classList.remove('active');
-                btn.classList.add('btn-outline-light'); 
-                if (parseInt(btn.dataset.speed) === playbackSpeed) {
-                    btn.classList.add('active');
-                    btn.classList.remove('btn-outline-light'); 
-                }
+                btn.classList.remove('active'); btn.classList.add('btn-outline-light'); 
+                if (parseInt(btn.dataset.speed) === playbackSpeed) { btn.classList.add('active'); btn.classList.remove('btn-outline-light'); }
             });
         }
 
         function updateQuickFilterActiveState(activeButtonId) {
             document.querySelectorAll('.quick-filter-buttons .btn').forEach(btn => {
-                btn.classList.remove('active');
-                btn.classList.add('btn-outline-light'); 
+                btn.classList.remove('active'); btn.classList.add('btn-outline-light'); 
             });
             if (activeButtonId) {
                 const activeButton = document.getElementById(activeButtonId);
-                if (activeButton) {
-                    activeButton.classList.add('active');
-                    activeButton.classList.remove('btn-outline-light'); 
-                }
+                if (activeButton) { activeButton.classList.add('active'); activeButton.classList.remove('btn-outline-light'); }
             }
         }
     
         function addEventListeners() {
-            if (!domElements.timelineScrubber || !domElements.playPauseButton || !domElements.resetButton) { 
-                console.error("Cannot add event listeners: Core DOM elements for controls not found.");
-                return;
-            }
+            if (!domElements.timelineScrubber || !domElements.playPauseButton || !domElements.resetButton) return;
             domElements.timelineScrubber.addEventListener('input', (event) => {
-                currentPeriodIndex = parseInt(event.target.value);
-                pauseAnimation();
-                updateUIForCurrentPeriod();
+                currentPeriodIndex = parseInt(event.target.value); pauseAnimation(); updateUIForCurrentPeriod();
             });
             domElements.playPauseButton.addEventListener('click', togglePlayPause);
             domElements.resetButton.addEventListener('click', resetAnimation);
     
             document.querySelectorAll('.speed-btn').forEach(button => {
-                button.addEventListener('click', () => {
-                    playbackSpeed = parseInt(button.dataset.speed);
-                    updateSpeedButtonsActiveState();
-                });
-            });
-            const filterAllBtn = document.getElementById('filter-all');
-            if(filterAllBtn) filterAllBtn.addEventListener('click', () => {
-                allSpeciesList.forEach(s => selectedSpecies[s.name] = true);
-                document.querySelectorAll('#species-filter-list input[type="checkbox"]').forEach(cb => cb.checked = true);
-                updateUIForCurrentPeriod();
-                updateQuickFilterActiveState('filter-all');
+                button.addEventListener('click', () => { playbackSpeed = parseInt(button.dataset.speed); updateSpeedButtonsActiveState(); });
             });
-            const filterNoneBtn = document.getElementById('filter-none');
-            if(filterNoneBtn) filterNoneBtn.addEventListener('click', () => {
-                allSpeciesList.forEach(s => selectedSpecies[s.name] = false);
-                document.querySelectorAll('#species-filter-list input[type="checkbox"]').forEach(cb => cb.checked = false);
-                updateUIForCurrentPeriod();
-                updateQuickFilterActiveState('filter-none');
-            });
-            const filterHomoBtn = document.getElementById('filter-homo');
-            if(filterHomoBtn) filterHomoBtn.addEventListener('click', () => {
-                allSpeciesList.forEach(s => {
-                    const isHomo = s.name.toLowerCase().includes('homo');
-                    selectedSpecies[s.name] = isHomo;
-                    const cb = document.getElementById(`filter-${s.name.replace(/\W/g, '_')}`);
-                    if(cb) cb.checked = isHomo;
+            ['filter-all', 'filter-none', 'filter-homo'].forEach(id => {
+                const btn = document.getElementById(id);
+                if (btn) btn.addEventListener('click', () => {
+                    if (id === 'filter-all') allSpeciesList.forEach(s => selectedSpecies[s.name] = true);
+                    else if (id === 'filter-none') allSpeciesList.forEach(s => selectedSpecies[s.name] = false);
+                    else if (id === 'filter-homo') allSpeciesList.forEach(s => selectedSpecies[s.name] = s.name.toLowerCase().includes('homo'));
+                    
+                    document.querySelectorAll('#species-filter-list input[type="checkbox"]').forEach(cb => {
+                        cb.checked = selectedSpecies[cb.value];
+                    });
+                    updateUIForCurrentPeriod(); updateQuickFilterActiveState(id);
                 });
-                updateUIForCurrentPeriod();
-                updateQuickFilterActiveState('filter-homo');
             });
 
-            if(domElements.climateToggle) { 
-                domElements.climateToggle.addEventListener('change', () => {
-                    if (timePeriodsData.length > 0 && fetchedIceSheetGeoJson) { 
-                         updateUIForCurrentPeriod(); 
-                    }
-                });
-            }
+            if(domElements.climateToggle) domElements.climateToggle.addEventListener('change', () => {
+                if (timePeriodsData.length > 0 && fetchedIceSheetGeoJson) updateUIForCurrentPeriod(); 
+            });
 
-            if (domElements.periodFilterSelect) { // Event listener for Period Navigator
-                domElements.periodFilterSelect.addEventListener('change', (event) => {
-                    const selectedIndex = parseInt(event.target.value);
-                    if (!isNaN(selectedIndex) && selectedIndex >= 0 && selectedIndex < timePeriodsData.length) {
-                        currentPeriodIndex = selectedIndex;
-                        pauseAnimation(); 
-                        updateUIForCurrentPeriod();
-                    }
-                });
-            }
+            if (domElements.periodFilterSelect) domElements.periodFilterSelect.addEventListener('change', (event) => {
+                const selectedIndex = parseInt(event.target.value);
+                if (!isNaN(selectedIndex) && selectedIndex >= 0 && selectedIndex < timePeriodsData.length) {
+                    currentPeriodIndex = selectedIndex; pauseAnimation(); updateUIForCurrentPeriod();
+                }
+            });
         }
     
         document.addEventListener('DOMContentLoaded', () => {
-            populateDomElements(); 
-            addEventListeners();   
-            fetchAllRequiredData();
+            populateDomElements(); addEventListeners(); fetchAllRequiredData();
         });
         </script>
   </body>