/* ===================================================
   ANIMATION SYSTEM — Scroll Reveal + Hero Entrance
   =================================================== */
// Prevent browser from restoring scroll position on reload
if ('scrollRestoration' in history) {
    history.scrollRestoration = 'manual';
}
window.scrollTo(0, 0);

const appText = window.AppText || {};

/* ===================================================
   COUNTDOWN TIMER — Early Bird
   =================================================== */
(() => {
    const timer = document.getElementById('countdownTimer');
    if (!timer) return;

    const banner = document.getElementById('countdownBanner');
    const target = new Date(timer.dataset.target).getTime();

    const digitEls = {
        dTens: timer.querySelector('[data-tens="d"]'),
        dOnes: timer.querySelector('[data-ones="d"]'),
        hTens: timer.querySelector('[data-tens="h"]'),
        hOnes: timer.querySelector('[data-ones="h"]'),
        mTens: timer.querySelector('[data-tens="m"]'),
        mOnes: timer.querySelector('[data-ones="m"]'),
        sTens: timer.querySelector('[data-tens="s"]'),
        sOnes: timer.querySelector('[data-ones="s"]'),
    };

    function setDigit(el, value) {
        if (!el) return;
        const v = String(value);
        if (el.textContent !== v) {
            el.textContent = v;
            el.classList.remove('pop');
            void el.offsetWidth; // reflow
            el.classList.add('pop');
        }
    }

    function tick() {
        const now = Date.now();
        let diff = Math.max(0, target - now);

        if (diff <= 0) {
            clearInterval(intervalId);
            if (banner) banner.classList.add('is-expired');
            Object.values(digitEls).forEach(el => { if (el) el.textContent = '0'; });
            return;
        }

        const totalSec = Math.floor(diff / 1000);
        const d = Math.floor(totalSec / 86400);
        const h = Math.floor((totalSec % 86400) / 3600);
        const m = Math.floor((totalSec % 3600) / 60);
        const s = totalSec % 60;

        setDigit(digitEls.dTens, Math.floor(d / 10));
        setDigit(digitEls.dOnes, d % 10);
        setDigit(digitEls.hTens, Math.floor(h / 10));
        setDigit(digitEls.hOnes, h % 10);
        setDigit(digitEls.mTens, Math.floor(m / 10));
        setDigit(digitEls.mOnes, m % 10);
        setDigit(digitEls.sTens, Math.floor(s / 10));
        setDigit(digitEls.sOnes, s % 10);
    }

    tick();
    const intervalId = setInterval(tick, 1000);
})();

(() => {
    // Trigger hero entrance animations after page load
    window.addEventListener('load', () => {
        document.body.classList.add('is-loaded');
    });

    // Intersection Observer for scroll-triggered animations
    const revealElements = document.querySelectorAll('.fade-up, .fade-left, .fade-right, .scale-in');

    if (revealElements.length) {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    entry.target.classList.add('visible');
                    observer.unobserve(entry.target);
                }
            });
        }, {
            threshold: 0.12,
            rootMargin: '0px 0px -40px 0px'
        });

        revealElements.forEach(el => observer.observe(el));
    }
})();

const toggle = document.getElementById('menu-toggle');
const menu = document.getElementById('nav-menu');
const navbar = document.querySelector('.navbar');

const backToTop = document.getElementById('backToTop');

const updateNavbarState = () => {
    if (!navbar) {
        return;
    }

    navbar.classList.toggle('is-scrolled', window.scrollY > 24);

    if (backToTop) {
        backToTop.classList.toggle('is-visible', window.scrollY > 400);
    }
};

updateNavbarState();

window.addEventListener('scroll', updateNavbarState, { passive: true });

if (backToTop) {
    backToTop.addEventListener('click', () => {
        window.scrollTo({ top: 0, behavior: 'smooth' });
    });
}

if (toggle && menu) {
    toggle.addEventListener('click', () => {
        const isOpen = menu.classList.toggle('active');
        toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');

        if (navbar) {
            navbar.classList.toggle('is-menu-open', isOpen);
        }
    });
}

/* ===================================================
   DROPDOWN -- Race menu click toggle
   =================================================== */
(() => {
    const dropdownItems = document.querySelectorAll('.nav-item--dropdown');

    dropdownItems.forEach(item => {
        const toggleLink = item.querySelector('.nav-dropdown-toggle');
        if (!toggleLink) return;

        toggleLink.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();

            // Close other open dropdowns
            dropdownItems.forEach(other => {
                if (other !== item) other.classList.remove('is-open');
            });

            item.classList.toggle('is-open');
        });
    });

    // Close dropdown when clicking outside
    document.addEventListener('click', (e) => {
        if (!e.target.closest('.nav-item--dropdown')) {
            dropdownItems.forEach(item => item.classList.remove('is-open'));
        }
    });
})();

const cpGroups = document.querySelectorAll('.cp-tabs');

cpGroups.forEach(group => {
    const buttons = group.querySelectorAll('button');

    buttons.forEach(button => {
        button.addEventListener('click', event => {
            buttons.forEach(item => item.classList.remove('active'));
            event.currentTarget.classList.add('active');
        });
    });
});

/* ===================================================
   ACCORDION -- Race Rules page
   =================================================== */
(() => {
    const accordions = document.querySelectorAll('.accordion');
    if (!accordions.length) return;

    accordions.forEach(acc => {
        const toggle = acc.querySelector('.accordion__toggle');
        const body = acc.querySelector('.accordion__body');
        if (!toggle || !body) return;

        toggle.addEventListener('click', () => {
            const isOpen = acc.classList.contains('is-open');

            // Close all others first
            accordions.forEach(other => {
                if (other !== acc && other.classList.contains('is-open')) {
                    other.classList.remove('is-open');
                    const otherBody = other.querySelector('.accordion__body');
                    if (otherBody) otherBody.style.maxHeight = null;
                    other.querySelector('.accordion__toggle')
                         .setAttribute('aria-expanded', 'false');
                }
            });

            // Toggle current
            if (isOpen) {
                acc.classList.remove('is-open');
                body.style.maxHeight = null;
                toggle.setAttribute('aria-expanded', 'false');
            } else {
                acc.classList.add('is-open');
                body.style.maxHeight = body.scrollHeight + 48 + 'px';
                toggle.setAttribute('aria-expanded', 'true');
            }
        });
    });
})();

/* ===================================================
   RACE RESULTS -- Tabs, Search, Filters
   =================================================== */
(() => {
    const table = document.getElementById('resultsTable');
    if (!table) return;

    const rows = Array.from(table.querySelectorAll('tbody tr'));
    const searchInput = document.getElementById('resultSearch');
    const filterCat = document.getElementById('filterCategory');
    const filterGender = document.getElementById('filterGender');
    const filterStatus = document.getElementById('filterStatus');
    const resetBtn = document.getElementById('resetFilters');
    const totalEl = document.getElementById('resultsTotal');

    // Tab switching
    const tabs = document.querySelectorAll('.results-tab');
    tabs.forEach(tab => {
        tab.addEventListener('click', () => {
            tabs.forEach(t => t.classList.remove('is-active'));
            tab.classList.add('is-active');
        });
    });

    function applyFilters() {
        const q = (searchInput ? searchInput.value : '').toLowerCase().trim();
        const cat = filterCat ? filterCat.value : '';
        const gender = filterGender ? filterGender.value : '';
        const status = filterStatus ? filterStatus.value : '';
        let count = 0;

        rows.forEach(row => {
            const name = (row.children[2] ? row.children[2].textContent : '').toLowerCase();
            const raceNo = (row.children[1] ? row.children[1].textContent : '').toLowerCase();
            const rCat = row.dataset.cat || '';
            const rGender = row.dataset.gender || '';
            const rStatus = row.dataset.status || '';

            const matchSearch = !q || name.includes(q) || raceNo.includes(q);
            const matchCat = !cat || rCat === cat;
            const matchGender = !gender || rGender === gender;
            const matchStatus = !status || rStatus === status;

            if (matchSearch && matchCat && matchGender && matchStatus) {
                row.style.display = '';
                count++;
            } else {
                row.style.display = 'none';
            }
        });

        if (totalEl) {
            const totalPrefix = appText.resultsTotalPrefix || 'Total:';
            const totalWord = appText.resultsTotalWord || 'results';
            totalEl.innerHTML = totalPrefix + ' <strong>' + count + '</strong> ' + totalWord;
        }
    }

    if (searchInput) searchInput.addEventListener('input', applyFilters);
    if (filterCat) filterCat.addEventListener('change', applyFilters);
    if (filterGender) filterGender.addEventListener('change', applyFilters);
    if (filterStatus) filterStatus.addEventListener('change', applyFilters);

    if (resetBtn) {
        resetBtn.addEventListener('click', () => {
            if (searchInput) searchInput.value = '';
            if (filterCat) filterCat.value = '';
            if (filterGender) filterGender.value = '';
            if (filterStatus) filterStatus.value = '';
            applyFilters();
        });
    }
})();

/* ===================================================
   CONTACT FORM -- Submit handler
   =================================================== */
(() => {
    const form = document.getElementById('contactForm');
    if (!form) return;

    form.addEventListener('submit', (e) => {
        e.preventDefault();

        // Basic validation
        const required = form.querySelectorAll('[required]');
        let valid = true;
        required.forEach(input => {
            if (!input.value.trim()) {
                input.style.borderColor = 'var(--accent-deep)';
                valid = false;
            } else {
                input.style.borderColor = '';
            }
        });

        if (!valid) return;

        const btn = document.getElementById('contactSubmitBtn');
        if (btn) {
            btn.disabled = true;
            btn.textContent = appText.contactSending || 'Sending...';
        }

        setTimeout(() => {
            form.style.display = 'none';
            const title = form.parentElement.querySelector('.contact-form__title');
            const desc = form.parentElement.querySelector('.contact-form__desc');
            if (title) title.style.display = 'none';
            if (desc) desc.style.display = 'none';

            const success = document.getElementById('contactSuccess');
            if (success) success.hidden = false;
        }, 1000);
    });

    // Clear error on input
    form.addEventListener('input', (e) => {
        e.target.style.borderColor = '';
    });
})();

/* ===============================================
   REGISTRATION FORM -- Multi-step & Validation
   =============================================== */
(() => {
    const form = document.getElementById('regForm');
    if (!form) return;

    const steps = form.querySelectorAll('.reg-fieldset');
    const progressSteps = document.querySelectorAll('.reg-step');
    let currentStep = 1;

    const goToStep = (n) => {
        steps.forEach(fs => {
            fs.classList.remove('reg-fieldset--active');
            fs.style.animation = 'none';
        });

        progressSteps.forEach(ps => {
            const s = parseInt(ps.dataset.step, 10);
            ps.classList.remove('active', 'done');
            if (s < n) ps.classList.add('done');
            if (s === n) ps.classList.add('active');
        });

        const target = form.querySelector(`.reg-fieldset[data-step="${n}"]`);
        if (target) {
            target.classList.add('reg-fieldset--active');
            void target.offsetWidth;
            target.style.animation = '';
        }

        currentStep = n;
        window.scrollTo({ top: 0, behavior: 'smooth' });
    };

    const showError = (id, msg) => {
        const el = document.getElementById(id + '-error');
        const input = document.getElementById(id);
        if (el) {
            el.textContent = msg;
            el.classList.add('is-visible');
        }
        if (input) input.classList.add('is-invalid');
    };

    const clearErrors = (fieldset) => {
        fieldset.querySelectorAll('.reg-error').forEach(el => {
            el.textContent = '';
            el.classList.remove('is-visible');
        });
        fieldset.querySelectorAll('.is-invalid').forEach(el => {
            el.classList.remove('is-invalid');
        });
    };

    const validateStep = (n) => {
        const fs = form.querySelector(`.reg-fieldset[data-step="${n}"]`);
        if (!fs) return true;

        clearErrors(fs);
        let valid = true;

        const requiredInputs = fs.querySelectorAll('[required]');
        requiredInputs.forEach(input => {
            if (input.type === 'checkbox') {
                if (!input.checked) {
                    showError(input.id, appText.regAgreeTerms || 'You must agree to the terms');
                    valid = false;
                }
                return;
            }

            const val = input.value.trim();
            if (!val) {
                showError(input.id, appText.regRequired || 'This field is required');
                valid = false;
                return;
            }

            if (input.type === 'email' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)) {
                showError(input.id, appText.regInvalidEmail || 'Enter a valid email address');
                valid = false;
            }
        });

        return valid;
    };

    // Clear error on input
    form.addEventListener('input', (e) => {
        const el = e.target;
        if (el.classList.contains('is-invalid')) {
            el.classList.remove('is-invalid');
            const errEl = document.getElementById(el.id + '-error');
            if (errEl) {
                errEl.textContent = '';
                errEl.classList.remove('is-visible');
            }
        }
    });

    // Next / Prev buttons
    form.addEventListener('click', (e) => {
        const btn = e.target.closest('[data-next]');
        const btnPrev = e.target.closest('[data-prev]');

        if (btn) {
            const next = parseInt(btn.dataset.next, 10);
            if (validateStep(currentStep)) {
                goToStep(next);
            }
        }

        if (btnPrev) {
            goToStep(parseInt(btnPrev.dataset.prev, 10));
        }
    });

    // Form submit
    form.addEventListener('submit', (e) => {
        e.preventDefault();

        if (!validateStep(currentStep)) return;

        const submitBtn = document.getElementById('submitBtn');
        if (submitBtn) {
            submitBtn.disabled = true;
            submitBtn.textContent = appText.regSubmitting || 'Submitting...';
        }

        setTimeout(() => {
            form.style.display = 'none';
            document.querySelector('.reg-progress').style.display = 'none';

            const success = document.getElementById('regSuccess');
            if (success) {
                success.hidden = false;
            }
        }, 1200);
    });

    /* --- Participant Type Pricing Update --- */
    const participantSelect = document.getElementById('participantType');
    const summaryFee = document.getElementById('summaryFee');
    const summaryTotal = document.getElementById('summaryTotal');

    if (participantSelect && summaryFee && summaryTotal) {
        const prices = {
            umum: 'IDR 175.000',
            pelajar: 'IDR 140.000'
        };

        participantSelect.addEventListener('change', () => {
            const selected = participantSelect.value;
            const price = prices[selected] || prices.umum;
            
            summaryFee.textContent = price;
            summaryTotal.textContent = price + ',-';
        });
    }
})();

/* ===================================================
   MERCHANDISE MODAL -- Image preview
   =================================================== */
(() => {
    const modal = document.getElementById('merchModal');
    if (!modal) return;

    const image = document.getElementById('merchModalImg');
    const caption = document.getElementById('merchModalCaption');
    const closeBtn = modal.querySelector('[data-merch-close]');
    const triggers = document.querySelectorAll('[data-merch-src]');
    let activeTrigger = null;

    const openModal = (trigger) => {
        const src = trigger.dataset.merchSrc;
        const title = trigger.dataset.merchTitle || '';

        if (!src || !image) return;

        activeTrigger = trigger;
        image.src = src;
        image.alt = title;

        if (caption) {
            caption.textContent = title;
        }

        modal.hidden = false;
        document.body.classList.add('is-merch-modal-open');

        if (closeBtn) {
            closeBtn.focus({ preventScroll: true });
        }
    };

    const closeModal = () => {
        modal.hidden = true;
        document.body.classList.remove('is-merch-modal-open');

        if (image) {
            image.src = '';
            image.alt = '';
        }

        if (caption) {
            caption.textContent = '';
        }

        if (activeTrigger) {
            activeTrigger.focus({ preventScroll: true });
        }
    };

    triggers.forEach(trigger => {
        trigger.addEventListener('click', () => openModal(trigger));
    });

    modal.addEventListener('click', (event) => {
        if (event.target === modal || event.target.closest('[data-merch-close]')) {
            closeModal();
        }
    });

    document.addEventListener('keydown', (event) => {
        if (!modal.hidden && event.key === 'Escape') {
            closeModal();
        }
    });
})();

function openJersey(src){

    document.getElementById(
        'jerseyModal'
    ).style.display = 'flex';

    document.getElementById(
        'jerseyPreview'
    ).src = src;
}

function closeJersey(){

    document.getElementById(
        'jerseyModal'
    ).style.display = 'none';
}


/* ===================================================
   MAP — Leaflet + GPX + Elevation Chart (3-state UGM style)
   =================================================== */
const mapEl = document.getElementById('map');
if (mapEl) {
    const map = L.map('map', {
        zoomControl: true,
        attributionControl: true
    });

    map.setView([-6.5650, 107.4475], 13);

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
        maxZoom: 18
    }).addTo(map);

    let routePoints  = [];
    let elevationData = [];
    let chart = null;
    let chartCreated = false;
    let currentGPXLayer = null;

    /* Moving marker on map */
    const movingMarker = L.circleMarker([0, 0], {
        radius: 8,
        color: '#f39818',
        fillColor: '#f39818',
        fillOpacity: 1,
        weight: 3,
        zIndexOffset: 1000
    }).addTo(map);

    /* Route line style — crimson to match UK Trail Run theme */
    const routeLineStyle = {
        color: '#bf1732',
        weight: 4,
        opacity: 0.92,
        lineCap: 'round',
        lineJoin: 'round'
    };

    /* Load GPX file dynamically */
    function loadGPX(gpxFile) {
        /* Remove previous GPX layer if exists */
        if (currentGPXLayer) {
            map.removeLayer(currentGPXLayer);
            currentGPXLayer = null;
        }

        /* Show loading overlay */
        const overlay = document.getElementById('mapLoadingOverlay');
        if (overlay) overlay.classList.remove('is-hidden');

        /* Clear elevation chart state */
        if (chart) {
            chart.destroy();
            chart = null;
        }
        chartCreated = false;

        /* Load GPX */
        const gpxLayer = new L.GPX(gpxFile, {
            async: true,
            polyline_options: routeLineStyle,
            marker_options: {
                startIconUrl: null,
                endIconUrl:   null,
                shadowUrl:    null,
                wptIconUrls:  { '': null }
            }
        })
        .on('loaded', function (e) {
            /* Hide loading overlay */
            if (overlay) overlay.classList.add('is-hidden');

            map.fitBounds(e.target.getBounds(), { padding: [24, 24] });

            const layers = e.target._layers;
            for (let id in layers) {
                if (layers[id]._latlngs) {
                    routePoints = layers[id]._latlngs;
                    processElevation();
                    break;
                }
            }
        })
        .on('error', function () {
            if (overlay) {
                overlay.querySelector('span').textContent = 'Failed to load route';
            }
        })
        .addTo(map);

        currentGPXLayer = gpxLayer;
    }

    /* Load initial route (7K is the default active tab) */
    loadGPX('route7k.gpx');

    /* Process GPX elevation data & populate stats */
    function processElevation() {
        let totalDist = 0;
        let elevGain  = 0;
        let maxElev   = -Infinity;
        let maxGrade  = -Infinity;
        let minGrade  = Infinity;
        elevationData = [];

        for (let i = 0; i < routePoints.length; i++) {
            const pt  = routePoints[i];
            const ele = pt.meta ? (pt.meta.ele || 0) : 0;

            if (i > 0) {
                const segDist = map.distance(routePoints[i - 1], pt); // meters
                totalDist += segDist / 1000;

                const prevEle = routePoints[i - 1].meta ? (routePoints[i - 1].meta.ele || 0) : 0;
                const diff = ele - prevEle;
                if (diff > 0) elevGain += diff;

                /* Grade (%) = rise / run × 100 */
                if (segDist > 1) {
                    const grade = (diff / segDist) * 100;
                    if (grade > maxGrade) maxGrade = grade;
                    if (grade < minGrade) minGrade = grade;
                }
            }

            if (ele > maxElev) maxElev = ele;

            elevationData.push({
                x:   Number(totalDist.toFixed(2)),
                y:   Number(ele.toFixed(0)),
                lat: pt.lat,
                lng: pt.lng
            });
        }

        /* Downsample for smoother chart */
        elevationData = elevationData.filter((_, i) => i % 2 === 0);

        /* Populate stats bar */
        const setEl = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; };

        setEl('infoDistance',  totalDist.toFixed(1) + ' KM');
        setEl('infoElevGain', Math.round(elevGain) + 'M');
        setEl('infoMaxGrade', (maxGrade === -Infinity ? '—' : maxGrade.toFixed(1)) + '%');
        setEl('infoMinGrade', (minGrade === Infinity  ? '—' : minGrade.toFixed(1)) + '%');

        /* Set initial marker */
        if (elevationData.length) {
            movingMarker.setLatLng([elevationData[0].lat, elevationData[0].lng]);
        }

        /* If elevation panel is already expanded, recreate chart immediately */
        var wr = document.getElementById('raceMapWrapper');
        if (wr && wr.classList.contains('is-expanded') && !chartCreated && elevationData.length) {
            setTimeout(createChart, 50);
            chartCreated = true;
        }
    }

    /* Store loadGPX globally for category tabs to use */
    window.mapState = {
        loadGPX: loadGPX
    };

    /* ---- 3-STATE INTERACTION ---- */
    const wrapper     = document.getElementById('raceMapWrapper');
    const hoverOverlay = document.getElementById('mapHoverOverlay');
    const elevPanel   = document.getElementById('raceElevPanel');
    const closeBtn    = document.getElementById('mapCloseBtn');

    /* State 2 → State 3: Click overlay to show elevation */
    if (hoverOverlay) {
        hoverOverlay.addEventListener('click', function () {
            if (!wrapper) return;
            wrapper.classList.add('is-expanded');

            /* Show elevation panel + close button */
            if (elevPanel) elevPanel.style.display = '';
            if (closeBtn) closeBtn.style.display = '';

            /* Create chart only once, after panel is visible */
            if (!chartCreated && elevationData.length) {
                setTimeout(createChart, 50); // slight delay for layout
                chartCreated = true;
            }

            /* Invalidate map size (panel change shifts layout) */
            setTimeout(() => map.invalidateSize(), 100);
        });
    }

    /* State 3 → State 1: Click close to hide elevation */
    if (closeBtn) {
        closeBtn.addEventListener('click', function (e) {
            e.stopPropagation();
            if (!wrapper) return;
            wrapper.classList.remove('is-expanded');

            if (elevPanel) elevPanel.style.display = 'none';
            closeBtn.style.display = 'none';

            setTimeout(() => map.invalidateSize(), 100);
        });
    }

    /* Build Chart.js elevation chart (yellow/gold on dark) */
    function createChart() {
        const canvas = document.getElementById('elevationChart');
        if (!canvas) return;
        const ctx = canvas.getContext('2d');

        chart = new Chart(ctx, {
            type: 'line',
            data: {
                datasets: [{
                    label: 'Elevation',
                    data: elevationData,
                    borderColor: '#e8b848',
                    backgroundColor: (context) => {
                        const ch = context.chart;
                        const { ctx: c, chartArea } = ch;
                        if (!chartArea) return 'rgba(232,184,72,0.2)';
                        const gradient = c.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
                        gradient.addColorStop(0, 'rgba(232,184,72,0.45)');
                        gradient.addColorStop(1, 'rgba(232,184,72,0.03)');
                        return gradient;
                    },
                    fill: true,
                    borderWidth: 2,
                    pointRadius: 0,
                    tension: 0.35
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                devicePixelRatio: 2,
                parsing: false,
                animation: false,
                events: ['mousemove', 'touchmove', 'touchstart', 'mouseout'],
                plugins: {
                    legend: { display: false },
                    tooltip: { enabled: false }
                },
                scales: {
                    x: {
                        type: 'linear',
                        min: 0,
                        max: elevationData.length ? elevationData[elevationData.length - 1].x : 10,
                        ticks: { color: 'rgba(0,0,0,0.6)', font: { size: 9 }, maxTicksLimit: 8 },
                        grid:  { color: 'rgba(0,0,0,0.1)' },
                        title: { display: false }
                    },
                    y: {
                        ticks: { color: 'rgba(0,0,0,0.6)', font: { size: 9 } },
                        grid:  { color: 'rgba(0,0,0,0.1)' },
                        title: { display: false }
                    }
                },
                interaction: {
                    mode: 'index',
                    intersect: false,
                    axis: 'x'
                },
                onHover: (event, elements) => {
                    if (elements.length) {
                        const index = elements[0].index;
                        const pt = elevationData[index];
                        if (!pt) return;

                        movingMarker.setLatLng([pt.lat, pt.lng]);
                        map.panTo([pt.lat, pt.lng], { animate: true, duration: 0.2 });
                    }
                }
            }
        });
    }
}


/* ===================================================
   RACE CATEGORY TABS — Switch 7K / 9K
   =================================================== */
(function () {
    const tabs = document.querySelectorAll('.race-cat-tab');
    if (!tabs.length) return;

    /* Category data with GPX files and route information */
    const catData = {
        '7k': { 
            title: '7K TRAIL RUN', 
            subtitle: 'INDIVIDUAL', 
            gpxFile: 'route7k.gpx',
            flagOff: 'SATURDAY, 06:00 WIB', 
            flagOffId: 'SABTU, 06:00 WIB', 
            cutOff: '2 HOURS', 
            cutOffId: '2 JAM' 
        },
        '9k': { 
            title: '9K TRAIL RUN', 
            subtitle: 'INDIVIDUAL', 
            gpxFile: 'route9k.gpx',
            flagOff: 'SATURDAY, 05:00 WIB', 
            flagOffId: 'SABTU, 05:00 WIB', 
            cutOff: '3 HOURS', 
            cutOffId: '3 JAM' 
        }
    };

    tabs.forEach(function (tab) {
        tab.addEventListener('click', function () {
            /* Toggle active state */
            tabs.forEach(function (t) { t.classList.remove('is-active'); });
            tab.classList.add('is-active');

            const cat = tab.getAttribute('data-cat');
            const data = catData[cat];
            if (!data) return;

            /* Update header title */
            const titleEl = document.getElementById('raceCatTitle');
            const subEl   = document.getElementById('raceCatSubtitle');
            if (titleEl) titleEl.textContent = data.title;
            if (subEl)   subEl.textContent   = data.subtitle;

            /* Load corresponding GPX file */
            if (window.mapState && window.mapState.loadGPX) {
                window.mapState.loadGPX(data.gpxFile);
            }
        });
    });
})();
