Source: main.js

/**
 * File: main.js
 * Project: Dāvis Strazds Portfolio
 * Purpose: Central logic engine managing i18n orchestration, asynchronous component injection, and sensory UI feedback.
 * (Mērķis: Centrālais loģikas dzinējs, kas pārvalda i18n koordināciju, komponentu injicēšanu un sensoru UI atsauksmes.)
 * Author: Dāvis Strazds
 * Dependencies: AOS (Animations), Leaflet (Mapping), VanillaTilt (Interactive depth).
 */

/* --- GLOBAL CONFIGURATION (Globālā konfigurācija) --- */
/** 
 * @constant {string} TESTIMONIALS_API - Serverless bridge to Google Sheets. 
 * Used for data persistence without server overhead. (Serverless tilts uz Google Sheets datu saglabāšanai bez servera izmaksām.)
 */
const TESTIMONIALS_API = 'https://script.google.com/macros/s/AKfycbxUhI7wmExIN65hkF-MEBQPMIFARD5BBrgRA6WuHJyA5nzqkyogCMoUHjzNEVVGSfgiaw/exec';

/**
 * State Management for Language and UI (Stāvokļa vadība valodai un UI)
 * Centralizes application state to prevent race conditions during async loads.
 * (Centralizē aplikācijas stāvokli, lai novērstu race conditions asinhronās ielādes laikā.)
 * @namespace AppState
 */
const AppState = {
    /** @property {string} lang - Current active language locale (Pašreizējā aktīvā valodas lokāle) */
    lang: localStorage.getItem('preferredLang') || (navigator.language.startsWith('lv') ? 'lv' : 'en'),
    /** @property {boolean} isNavigating - Navigation lock state (Navigācijas bloķēšanas stāvoklis) */
    isNavigating: false
};

/** @type {AudioContext} audioCtx - Global audio context for UI synthesis (Globālais audio konteksts UI sintēzei) */
let audioCtx; 

/**
 * Programmatic Audio Engine: UI feedback synthesis to avoid large asset overhead.
 * Uses Web Audio API to generate real-time feedback, reducing page load size.
 * (Izmanto Web Audio API, lai ģenerētu reāllaika atsauksmes, samazinot lapas ielādes izmēru.)
 * @param {'success'|'error'} type - Feedback category mapped to specific frequency ramps.
 * @returns {void}
 */
function playUISound(type) {
    try {
        /* Resumed on interaction to bypass browser auto-play policies.
           (Atsākts pie interakcijas, lai apietu pārlūku automātiskās atskaņošanas politikas.) */
        if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        // Global gain normalization (Globālā skaņas līmeņa normalizācija)
        if (audioCtx.state === 'suspended') audioCtx.resume();
        
        const oscillator = audioCtx.createOscillator();
        const gainNode = audioCtx.createGain();
        oscillator.connect(gainNode);
        gainNode.connect(audioCtx.destination);

        if (type === 'success') {
            oscillator.type = 'sine'; 
            /* 880Hz (A5) to 1320Hz (E6) - Harmonic upward ramp signifying positive completion.
               (880Hz līdz 1320Hz - Augšupejoša skaņa, kas norāda uz veiksmīgu pabeigšanu.) */
            oscillator.frequency.setValueAtTime(880, audioCtx.currentTime); 
            oscillator.frequency.exponentialRampToValueAtTime(1320, audioCtx.currentTime + 0.1); 
            gainNode.gain.setValueAtTime(0.1, audioCtx.currentTime); /* Lower gain to prevent audio clipping (Zemāks gain, lai novērstu audio kropļojumus) */
            gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.4);
            oscillator.start(); oscillator.stop(audioCtx.currentTime + 0.4);
        } else if (type === 'error') {
            oscillator.type = 'sawtooth';
            /* 110Hz to 55Hz - Dissonant drop representing a system warning/error.
               (110Hz līdz 55Hz - Disonējošs kritums, kas reprezentē sistēmas kļūdu.) */
            oscillator.frequency.setValueAtTime(110, audioCtx.currentTime); 
            oscillator.frequency.linearRampToValueAtTime(55, audioCtx.currentTime + 0.2); 
            gainNode.gain.setValueAtTime(0.05, audioCtx.currentTime);
            gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.3);
            oscillator.start(); oscillator.stop(audioCtx.currentTime + 0.3);
        }
    } catch (e) { console.warn("Audio Context failed:", e); }
}

/**
 * Entry point for UI component orchestration.
 * (UI komponentu koordinācijas sākuma punkts.)
 * @listens document:DOMContentLoaded
 */
document.addEventListener('DOMContentLoaded', () => {
    initApp();
});

/**
 * Main application bootstrap engine. 
 * Orchestrates parallel asset loading and visual state initialization.
 * (Galvenais aplikācijas ielādes dzinējs. Koordinē paralēlu resursu ielādi.)
 * @async @returns {Promise<void>}
 */
async function initApp() {
    const preloader = document.getElementById('preloader');

    /* Load fragments before translation to ensure DOM nodes exist (Ielādēt fragmentus pirms tulkošanas) */
    await Promise.all([
        loadComponent('header', './header.html'),
        loadComponent('footer', './footer.html')
    ]).catch(err => console.warn("Component loading failed:", err));

    // Sync language and translate (Sinhronizēt valodu un tulkot)
    localStorage.setItem('preferredLang', AppState.lang);
    document.documentElement.lang = AppState.lang;
    translatePage();

    /* Fast UI Reveal (Ātra UI parādīšana, lai uzlabotu Speed Index) */
    if (preloader) {
        preloader.classList.add('fade-out');
    }

    // Core interactions
    initHeader();
    updateLangButtons();
    // Essential animations (Svarīgākās animācijas)
    initTypewriter();
    optimizeMediaLoading();
    initViewportScenarios(); // Start the Scenario Engine (Palaist scenāriju dzinēju)

    // Defer heavy non-critical scripts to free up main thread (Atlikt smagos skriptus)
    const deferHeavy = window.requestIdleCallback || (cb => setTimeout(cb, 200));
    deferHeavy(() => {
        initFooter();
        initScrollToTop();
        initLaboratory();
        initExcelSimulation();
        initCardEffects();
        initParallax();
        initSkillBars();
        initProjectModals();
        initLeafletMap();
        initScrollSpy();
    });

    registerServiceWorker(); // Enable PWA capabilities (Ieslēgt PWA iespējas)

    if (window.location.pathname.includes('atsauksmes.html')) {
        fetchDynamicTestimonials();
    }

    if (typeof AOS !== 'undefined') {
        AOS.init({ once: true, duration: 800 });
    }
}

/**
 * PWA Service Worker Registration: Enables offline access and caching.
 * (PWA Service Worker reģistrācija: Iespējo bezsaistes piekļuvi un kešdarbi.)
 */
function registerServiceWorker() {
    if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
            // Dinamiski nosaka ceļu: GitHub Pages apakšmape vai lokālā sakne
            const isGitHubPages = window.location.hostname.includes('github.io');
            const swPath = isGitHubPages ? '/davis-portfolio/service-worker.js' : './service-worker.js';

            navigator.serviceWorker.register(swPath).catch(err => {
                console.warn('PWA: ServiceWorker registration failed:', err);
            });
        });
    }
}

/**
 * Viewport Scenario Engine: Detects device categories and applies data attributes.
 * (Viewport scenāriju dzinējs: Nosaka ierīču kategorijas un piešķir datu atribūtus.)
 */
function initViewportScenarios() {
    const updateScenario = () => {
        const width = window.innerWidth;
        let scenario = 'pc-medium'; // Default

        if (width < 280) scenario = 'watch'; // Extreme small (Pulksteņi)
        else if (width < 360) scenario = 'phone-small';
        else if (width < 414) scenario = 'phone-medium';
        else if (width < 600) scenario = 'phone-large';
        else if (width < 768) scenario = 'tablet-small';
        else if (width < 991) scenario = 'tablet-medium';
        else if (width < 1200) scenario = 'tablet-large';
        else if (width < 1440) scenario = 'pc-small';
        else if (width < 1920) scenario = 'pc-medium';
        else if (width < 2560) scenario = 'pc-large';
        else if (width < 3840) scenario = 'projector-medium';
        else scenario = 'tv-ultra';

        document.documentElement.setAttribute('data-scenario', scenario);
        
        // Debug mode (Optional: remove in production)
        // console.log(`Active Scenario: ${scenario} (${width}px)`);
    };

    window.addEventListener('resize', updateScenario);
    updateScenario();
}

/**
 * Media Loading Optimizer: Enhances performance by applying lazy loading and async decoding.
 * (Mediju ielādes optimizētājs: Uzlabo veiktspēju, lietojot lazy loading un asinhronu dekodēšanu.)
 * Why: Reduces main thread blocking and improves First Contentful Paint.
 * (Kāpēc: Mazina galvenās pavediena bloķēšanu un uzlabo FCP rādītājus.)
 */
function optimizeMediaLoading() {
    // 1. Image Optimization (Attēlu optimizācija)
    document.querySelectorAll('img').forEach(img => {
        if (!img.hasAttribute('loading')) img.setAttribute('loading', 'lazy');
        if (!img.hasAttribute('decoding')) img.setAttribute('decoding', 'async');
    });

    // 2. Intelligent Video Loading (Inteliģenta video ielāde)
    const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
    const isLowEnd = connection && (connection.saveData || ['slow-2g', '2g', '3g'].includes(connection.effectiveType));
    const isLowRam = navigator.deviceMemory && navigator.deviceMemory < 4;

    document.querySelectorAll('video.video-background').forEach(video => {
        // Ja ir lēns internets vai maz RAM, neielādējam video vispār - paliekam pie Poster Image
        if (isLowEnd || isLowRam) {
            video.remove(); 
            return;
        }

        video.setAttribute('preload', 'metadata');
        video.addEventListener('loadedmetadata', () => video.play(), { once: true });

        // 3. Resource Management: Pause when not visible (Resursu pārvaldība: Pauzēt, kad nav redzams)
        const handleVisibility = () => {
            if (document.hidden) video.pause();
            else video.play().catch(() => {}); // Catch prevents error if user hasn't interacted yet
        };
        document.addEventListener('visibilitychange', handleVisibility);
    });
}

/**
 * Modular Component Injector: Fetches HTML fragments asynchronously.
 * Enables DRY (Don't Repeat Yourself) principle for headers and footers.
 * (Nodrošina DRY principu galvenēm un kājenēm.)
 * @async 
 * @param {string} id - Target DOM element ID for injection.
 * @param {string} file - Path to the HTML fragment.
 * @returns {Promise<void>}
 */
async function loadComponent(id, file) {
    const el = document.getElementById(id);
    if (!el) return;
    try {
        const res = await fetch(file);
        const data = await res.text();
        el.innerHTML = data;
    } catch (err) {
        console.error(`Error loading ${file}:`, err);
    }
}

/**
 * Switches application language and persists preference.
 * Uses opacity transitions to mitigate Flash of Un-translated Content (FOTC).
 * (Izmanto caurspīdības pārejas, lai mazinātu netulkotā satura pavīdēšanu.)
 * @param {'lv'|'en'} lang - Targeted language locale.
 * @returns {void}
 */
function switchLanguage(lang) {
    if (AppState.lang === lang || AppState.isNavigating) return;

    AppState.isNavigating = true;
    const wrapper = document.querySelector('.main-wrapper');
    if (wrapper) wrapper.style.opacity = '0';
    
    setTimeout(() => {
        AppState.lang = lang;
        localStorage.setItem('preferredLang', lang);
        document.documentElement.lang = lang;
        
        translatePage();
        updateLangButtons();
        initTypewriter(); 
        
        if (wrapper) wrapper.style.opacity = '1';
        playUISound('success');
        AppState.isNavigating = false;
    }, 400);
}

/**
 * Maps translation dictionary to DOM elements based on data attributes.
 * Traverses DOM and updates nodes with data-i18n attributes.
 * (Meklē DOM un atjaunina mezglus ar data-i18n atribūtiem.)
 * @returns {void}
 */
function translatePage() {
    const lang = localStorage.getItem('preferredLang') || 'lv';
    if (typeof translations === 'undefined') return;

    // Tulkojam teksta saturu un placeholderus
    document.querySelectorAll('[data-i18n]').forEach(el => {
        const key = el.getAttribute('data-i18n');
        if (!key) return;
        const translation = translations[lang] ? translations[lang][key] : null;
        
        if (translation) {
            if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
                el.placeholder = translation;
            } else {
                const icon = el.querySelector('i');
                // Preserves icons while updating text (Saglabā ikonas, atjauninot tekstu)
                if (icon && el.childNodes.length > 0) {
                    const textNode = Array.from(el.childNodes).find(node => node.nodeType === 3);
                    if (textNode) textNode.textContent = ' ' + translation; else el.innerHTML = icon.outerHTML + ' ' + translation;
                } else {
                    el.innerHTML = translation;
                }
            }
        }
    });

    document.querySelectorAll('[data-full-desc-i18n]').forEach(el => {
        const key = el.getAttribute('data-full-desc-i18n');
        const translation = translations[lang] ? translations[lang][key] : null;
        if (translation) {
            el.setAttribute('data-full-desc', translation);
        }
    });
}

/**
 * Integrates with Google Apps Script to fetch live client testimonials.
 * Fetches JSON payload and generates semantic cards dynamically.
 * (Iegūst JSON datus un dinamiski ģenerē semantiskas kartītes.)
 * @async 
 * @returns {Promise<void>}
 */
async function fetchDynamicTestimonials() {
    const container = document.getElementById('testimonials-container');
    if (!container || AppState.isNavigating) return;
    
    AppState.isNavigating = true; // Lock process (Bloķēt procesu)
    const lang = localStorage.getItem('preferredLang') || 'lv'; 

    try {
        // Pievienojam cache: 'no-cache', lai pārlūks vienmēr prasītu svaigus datus
        const response = await fetch(TESTIMONIALS_API, { method: 'GET', redirect: 'follow', cache: 'no-cache' });
        
        if (!response.ok) throw new Error("Tīkla kļūda");
        
        const text = await response.text(); // Vispirms nolasām kā tekstu, lai izvairītos no SyntaxError
        const result = JSON.parse(text);
        let reviews = result.data || [];

        AppState.isNavigating = false; // Unlock (Atbloķēt)

        if (!Array.isArray(reviews) || reviews.length === 0) {
            container.innerHTML = `<p style="text-align:center; grid-column: 1/-1; color: var(--text-muted); padding: 3rem;" data-i18n="testimonials.empty">Pašlaik atsauksmju vēl nav. Esi pirmais!</p>`;
            translatePage();
            return;
        }

        container.innerHTML = reviews.map((rev, idx) => {
            const name = rev.Name || rev.name || "Anonymous";
            const message = rev.Message || rev.message || "";
            const dateRaw = rev.Timestamp || rev.date || new Date();

            const initials = name.split(' ').map(n => n[0]).join('').toUpperCase().substring(0, 2);
            
            const revDate = new Date(dateRaw);
            const formattedDate = isNaN(revDate) ? new Date().toLocaleDateString() : revDate.toLocaleDateString(lang === 'lv' ? 'lv-LV' : 'en-US');

            return `
            <div class="testimonial-card" data-tilt data-aos="fade-up" data-aos-delay="${idx * 100}">
                <div class="card-content">
                    <i class="fas fa-quote-left"></i>
                    <p class="testimonial-text">"${message}"</p>
                    <div class="testimonial-author">
                        <div class="author-avatar">${initials}</div>
                        <h3>${name}</h3>
                        <p>${formattedDate}</p>
                        <div class="rating">
                            <i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i>
                        </div>
                    </div>
                </div>
            </div>
            `;
        }).join('');
        
        if (typeof VanillaTilt !== 'undefined') {
            VanillaTilt.init(document.querySelectorAll(".testimonial-card"), { max: 10, speed: 400 });
        }
        initCardEffects(); // Re-initialize glow for dynamic elements (Reinicializēt spīdumu dinamiskajiem elementiem)
        translatePage(); // Ensure dynamic content is translated (Nodrošināt dinamiskā satura tulkošanu)
    } catch (err) {
        console.error("Neizdevās ielādēt atsauksmes:", err);
        AppState.isNavigating = false;
    }
}

/**
 * Handles contact form submission with UI feedback and validation.
 * @param {Event} e - Form submission event.
 * @async
 * @returns {Promise<void>}
 */
async function handleFeedbackSubmit(e) {
    e.preventDefault();
    const form = e.target;
    const btn = form.querySelector('.submit-btn');
    const successMsg = document.getElementById('success-message');

    const nameInput = form.querySelector('[name="name"]');
    const emailInput = form.querySelector('[name="email"]');
    const msgInput = form.querySelector('[name="message"]');
    const gdprInput = form.querySelector('[name="gdpr"]');

    const name = nameInput.value.trim();
    const email = emailInput.value.trim();
    const message = msgInput.value.trim();

    [nameInput, emailInput, msgInput].forEach(el => el.classList.remove('input-error'));

    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    let hasError = false;

    if (!name) { nameInput.classList.add('input-error'); hasError = true; }
    if (!email || !emailRegex.test(email)) { emailInput.classList.add('input-error'); hasError = true; }
    if (!message) { msgInput.classList.add('input-error'); hasError = true; }
    
    if (gdprInput && !gdprInput.checked) {
        gdprInput.parentElement.classList.add('input-error');
        hasError = true;
    }

    if (hasError) { /* Trigger haptic sound and reset error styles (Izsaukt skaņu un atiestatīt kļūdu stilus) */
        playUISound('error');
        setTimeout(() => {
            [nameInput, emailInput, msgInput].forEach(el => el.classList.remove('input-error'));
        }, 500);
        return; 
    }

    // Noteikt sūtīšanas tipu (Atsauksme vai Kontakts)
    const isTestimonial = form.id === 'feedback-form' || window.location.pathname.includes('atsauksmes.html');
    
    const data = { 
        token: 'ManPatikGoogle', // Drošības žetons
        type: isTestimonial ? 'testimonial' : 'contact',
        name, 
        email, 
        message,
        website: "" // Honeypot pret spamu
    };
    const originalBtnHTML = btn.innerHTML;

    btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
    btn.disabled = true;

    try {
        const response = await fetch(TESTIMONIALS_API, {
            method: 'POST',
            mode: 'no-cors', // Izmantojam no-cors, lai apietu CORS preflight ierobežojumus
            cache: 'no-cache',
            body: JSON.stringify(data)
        });
        
        // 'no-cors' režīmā mēs vienmēr saņemam atbildi, ja nav tīkla kļūdas
        playUISound('success');
        successMsg.classList.add('visible');
        form.reset();
        
        setTimeout(() => {
            successMsg.classList.remove('visible');
        }, 5000);

    } catch (err) {
        console.error("Saziņas kļūda:", err);
        playUISound('error');
    } finally {
        btn.innerHTML = originalBtnHTML;
        btn.disabled = false;
    }
}

/**
 * Syncs language switcher UI buttons with the current active locale.
 * (Sinhronizē valodu slēdža UI pogas ar pašreizējo aktīvo lokāli.)
 * @returns {void}
 */
function updateLangButtons() {
    const lang = localStorage.getItem('preferredLang') || 'lv';
    document.querySelectorAll('.lang-btn').forEach(btn => {
        btn.classList.toggle('active', btn.getAttribute('onclick').includes(lang));
    });
}

/**
 * Excel Data Transformation Simulation: Visualizes the power of Java-SQL integration.
 * (Excel datu transformācijas simulācija: Vizualizē Java-SQL integrācijas jaudu.)
 */
function initExcelSimulation() {
    const btn = document.getElementById('btn-run-excel-sim');
    const out = document.getElementById('excel-sim-output');
    if (!btn) return;

    /* Illustrates complex Range-to-Object mapping (Ilustrē sarežģītu Range-to-Object kartēšanu) */
    btn.onclick = () => {
        const lang = localStorage.getItem('preferredLang') || 'lv';
        const t = translations[lang];
        playUISound('success');

        const lines = [
            t["excel.log_open"],
            t["excel.log_handshake"],
            t["excel.log_map"],
            t["excel.log_poi"],
            t["excel.log_heap"],
            t["excel.log_sql"],
            t["excel.log_impact"],
            t["excel.log_success"]
        ];

        let i = 0; out.innerHTML = "";
        const run = () => {
            if (i < lines.length) {
                out.innerHTML += lines[i++] + "<br>";
                out.scrollTop = out.scrollHeight; // Auto-scroll to latest log (Automātiska ritināšana uz jaunāko ierakstu)
                setTimeout(run, 800);
            }
        };
        run();
    };
}

/**
 * UI Utility: Scroll behavior and Navigation spies.
 * (UI palīgrīki: Ritrināšanas uzvedība un navigācijas izsekošana.)
 * Why: Enhances interactivity by dynamically tracking user focus areas.
 * (Kāpēc: Uzlabo interaktivitāti, dinamiski izsekojot lietotāja fokusa zonas.)
 */
function initScrollToTop() {
    const btn = document.createElement('button');
    btn.className = 'scroll-to-top';
    btn.innerHTML = '<i class="fas fa-chevron-up"></i>';
    document.body.appendChild(btn);

    window.addEventListener('scroll', () => {
        btn.classList.toggle('visible', window.scrollY > 500);
    });

    btn.onclick = () => window.scrollTo({ top: 0, behavior: 'smooth' });
}

/**
 * Typewriter Engine: Rotates defined professional roles.
 * (Rakstāmmašīnas dzinējs: Rotē definētās profesionālās lomas.)
 */
let typewriterTimeout;
function initTypewriter() {
    const el = document.getElementById('typewriter');
    if (!el) return;
    
    clearTimeout(typewriterTimeout);
    const lang = localStorage.getItem('preferredLang') || 'lv';
    const roles = translations[lang] ? translations[lang].hero_roles : ["AI Architect"];
    let roleIdx = 0;
    let charIdx = 0;
    let isDeleting = false;

    function type() {
        const currentRole = roles[roleIdx] || "";
        if (isDeleting) {
            el.textContent = currentRole.substring(0, charIdx - 1);
            charIdx--;
        } else {
            el.textContent = currentRole.substring(0, charIdx + 1);
            charIdx++;
        }

        let typeSpeed = isDeleting ? 50 : 150;

        if (!isDeleting && charIdx === currentRole.length) {
            typeSpeed = 2000;
            isDeleting = true;
        } else if (isDeleting && charIdx === 0) {
            isDeleting = false;
            roleIdx = (roleIdx + 1) % roles.length;
            typeSpeed = 500;
        }

        typewriterTimeout = setTimeout(type, typeSpeed);
    }
    type();
}

/**
 * ScrollSpy Implementation: Updates active navigation links based on scroll position.
 * Also dynamically updates the navbar background color theme based on section metadata.
 * (Atjaunina aktīvās saites un dinamiski maina navigācijas joslas krāsu tēmu.)
 */
function initScrollSpy() {
    const options = { threshold: 0.3, rootMargin: "-10px" };
    const navbar = document.querySelector('.navbar'); // Navbar reference for theme updates (Atsauce uz navigāciju tēmu maiņai)

    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                const id = entry.target.getAttribute('id');
                
                /* Only update links that point to specific anchors (#) on the current page to avoid stripping file-based active states.
                   (Atjaunina tikai enkura saites (#), lai neietekmētu failu bāzēto navigāciju.) */
                document.querySelectorAll('.navbar-menu a[href*="#"]').forEach(link => {
                    link.classList.toggle('active', link.getAttribute('href').includes('#' + id));
                });

                /* Update Navbar Theme based on section data attribute (Atjaunina navigācijas tēmu, balstoties uz sekcijas datiem) */
                if (navbar) {
                    const theme = entry.target.getAttribute('data-nav-theme');
                    // Remove all previous theme classes (Noņem visas iepriekšējās tēmu klases)
                    navbar.classList.forEach(className => {
                        if (className.startsWith('nav-theme-')) navbar.classList.remove(className);
                    });
                    // Add new theme class if present (Pievieno jauno tēmu, ja tāda ir definēta)
                    if (theme) navbar.classList.add(`nav-theme-${theme}`);
                }
            }
        });
    }, options);

    document.querySelectorAll('section[id]').forEach(section => observer.observe(section));
}

/**
 * Calculates and updates the top reading progress bar.
 * (Aprēķina un atjaunina augšējo lasīšanas progresa joslu.)
 * @returns {void}
 */
function updateReadingProgress() {
    const progressFill = document.getElementById('reading-progress-fill');
    if (!progressFill) return;

    /* Calculate scroll percentage (Aprēķina ritināšanas procentu) */
    const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
    const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
    const scrolled = (winScroll / height) * 100;

    progressFill.style.width = scrolled + "%";
}

/**
 * Header Logic: Handles mobile menu toggles and dynamic background scrolling effects.
 * (Galvenes loģika: Pārvalda mobilo izvēlni un dinamiskos fona ritināšanas efektus.)
 */
function initHeader() {
    const toggle = document.getElementById('mobile-menu-toggle');
    const menu = document.getElementById('nav-menu');
    if (toggle && menu) {
        toggle.addEventListener('click', () => menu.classList.toggle('active'));
        
        // Close menu when clicking links
        menu.querySelectorAll('a').forEach(link => {
            link.addEventListener('click', () => menu.classList.remove('active'));
        });
    }

    const navbar = document.querySelector('.navbar');
    window.addEventListener('scroll', () => {
        if (navbar) navbar.classList.toggle('scrolled', window.scrollY > 50);
        updateReadingProgress(); // Sync progress bar (Sinhronizē progresa joslu)
    });

    // Correctly identify the active page even if the path is the root (Pareizi identificē aktīvo lapu arī pie saknes ceļa)
    const currentPath = window.location.pathname.split('/').pop() || 'index.html';
    
    document.querySelectorAll('.navbar-menu a').forEach(link => {
        const href = link.getAttribute('href');
        if (href === currentPath || (currentPath === 'index.html' && href === './')) {
            link.classList.add('active');
        }
    });
}

/**
 * Mouse Tracking Engine: Powers the glow effect for glassmorphism cards.
 * (Peles izsekošanas dzinējs: Nodrošina spīduma efektu glassmorphism kartītēm.)
 */
function initCardEffects() {
    document.querySelectorAll('.project-card, .testimonial-card').forEach(card => {
        card.addEventListener('mousemove', e => {
            const rect = card.getBoundingClientRect();
            card.style.setProperty('--mouse-x', `${e.clientX - rect.left}px`);
            card.style.setProperty('--mouse-y', `${e.clientY - rect.top}px`);
        });
    });
}

/**
 * AI Laboratory UI: Simulates agent logic flows and code generation sequences.
 * (MI Laboratorijas UI: Simulē aģentu loģikas plūsmas un koda ģenerēšanas sekvences.)
 */
function initLaboratory() {
    const labBtn = document.getElementById('btn-analyze');
    const taskBtn = document.getElementById('btn-execute');
    const copyBtn = document.getElementById('btn-copy');

    if (labBtn) {
        labBtn.addEventListener('click', () => {
            const prompt = document.getElementById('ai-prompt').value.trim();
            const output = document.getElementById('prompt-output');
            const lang = localStorage.getItem('preferredLang') || 'lv';
            const t = translations[lang];

            if (!prompt) { output.innerHTML = t["coding.error_no_prompt"]; return; }
            playUISound('success');

            const personalities = [t["coding.p_arch"], t["coding.p_sec"], t["coding.p_ux"], t["coding.p_ds"], t["coding.p_cloud"]];
            const randomP = personalities[Math.floor(Math.random() * personalities.length)];
            const sequence = [t["coding.log_neural"], t["coding.log_agent"] + `<span style="color:var(--accent-gold)">${randomP}</span>`, t["coding.log_intent"] + `'${prompt.substring(0, 30)}...'`, t["coding.log_map"], t["coding.log_query"]]; /* Orchestrate visual delay for realism (Koordinē vizuālo aizturi reālismam) */

            let i = 0; output.innerHTML = "";
            const run = () => {
                if (i < sequence.length) {
                    output.innerHTML += sequence[i++] + "<br>";
                    output.scrollTop = output.scrollHeight;
                    setTimeout(run, 600);
                } else {
                    output.innerHTML += `> <span style="color:var(--accent-gold)">${t["coding.generated"]}</span> Risinājums sagatavots.<br>> <span class="blink">_</span>`;
                }
            };
            run();
        });
    }

    if (taskBtn) {
        taskBtn.addEventListener('click', () => {
            const topic = document.getElementById('topic').value.trim();
            const result = document.getElementById('result');
            const lang = localStorage.getItem('preferredLang') || 'lv';
            const t = translations[lang];

            if (!topic) { result.innerHTML = t["coding.error_no_input"]; return; }
            playUISound('success');

            let uzdevums = topic.includes("cikli") ? "Izveido 'for' ciklu Fibonači skaitļiem." : `Integrē '${topic}' loģiku jaunā API galapunktā.`;
            const lines = [t["coding.log_init"], t["coding.log_analyze"] + topic, t["coding.log_kb"], t["coding.log_gen"]];
            
            let i = 0; result.innerHTML = "";
            const printLines = () => {
                if (i < lines.length) {
                    result.innerHTML += lines[i++] + "<br>";
                    setTimeout(printLines, 300);
                } else {
                    result.innerHTML += `<br><span style="color:var(--accent-gold)">${t["coding.success"]}</span> ${uzdevums}<span class="blink">_</span>`;
                }
            };
            printLines();
        });
    }

    if (copyBtn) {
        copyBtn.addEventListener('click', () => {
            const output = document.getElementById('prompt-output').innerText;
            navigator.clipboard.writeText(output).then(() => alert(translations[localStorage.getItem('preferredLang') || 'lv']["coding.alert_copied"]));
        });
    }
}

/**
 * Subtle Background Parallax: Enhances depth by scaling video background on scroll.
 * (Smalks fona paralakse: Uzlabo dziļumu, mērogojot video fonu pie ritināšanas.)
 */
function initParallax() { 
    window.addEventListener('scroll', () => {
        const scroll = window.pageYOffset;
        const video = document.querySelector('.video-background');
        if (video) video.style.transform = `scale(${1 + scroll * 0.0005})`;
    });
}

/**
 * Intersection-based animation for skill visualization bars.
 * (Uz Intersection bāzēta animācija prasmju vizualizācijas joslām.)
 */
function initSkillBars() {
    const bars = document.querySelectorAll('.progress-bar-fill');
    if (bars.length > 0) {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    entry.target.style.width = entry.target.getAttribute('data-width');
                }
            });
        }, { threshold: 0.5 });
        bars.forEach(bar => observer.observe(bar));
    }

    document.querySelectorAll('.skill-card').forEach(card => {
        card.addEventListener('click', () => card.classList.toggle('active'));
    });
}

/**
 * Modal Controller: Handles project detail overlays and scroll locks.
 * (Modālā loga kontrolieris: Apstrādā projektu detaļu pārklājumus un ritināšanas bloķēšanu.)
 */
function initProjectModals() {
    const modal = document.getElementById('project-modal');
    if (!modal) return;

    const modalTitle = document.getElementById('modal-title');
    const modalDesc = document.getElementById('modal-desc');
    const modalTech = document.getElementById('modal-tech');
    const closeModalBtn = modal.querySelector('.close-modal');

    document.querySelectorAll('.project-card').forEach(card => {
        card.addEventListener('click', (e) => {
            if (e.target.closest('a')) return;
            
            const title = card.querySelector('.card-title').innerText;
            const fullDesc = card.getAttribute('data-full-desc');
            const techBadges = card.querySelector('.badges').innerHTML;

            modalTitle.innerText = title;
            modalDesc.innerHTML = fullDesc;
            modalTech.innerHTML = techBadges;

            modal.classList.add('active');
            document.body.style.overflow = 'hidden';
        });
    });

    const close = () => {
        modal.classList.remove('active');
        document.body.style.overflow = '';
    };

    closeModalBtn.onclick = close;
    modal.onclick = (e) => { if(e.target === modal) close(); };
}

/**
 * Map Integration: Renders Dark-Mode Leaflet map with custom markers.
 * (Kartes integrācija: Renderē Dark-Mode Leaflet karti ar pielāgotiem marķieriem.)
 */
function initLeafletMap() {
    const mapEl = document.getElementById('map');
    if (!mapEl || typeof L === 'undefined') return;

    const map = L.map('map', { scrollWheelZoom: false }).setView([56.8796, 24.6032], 7);
    L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
        attribution: '© OpenStreetMap contributors'
    }).addTo(map);
    
    const lang = localStorage.getItem('preferredLang') || 'lv';
    const popupText = typeof translations !== 'undefined' ? translations[lang]["contact.map_popup"] : "Dāvis Strazds";
    L.marker([56.9496, 24.1052]).addTo(map).bindPopup(popupText);
}

/**
 * Controls the visibility of the scroll-to-top utility.
 * (Kontrolē "ritināt uz augšu" rīka redzamību.)
 */
function initFooter() { 
    const year = document.getElementById('year');
    if (year) year.textContent = new Date().getFullYear(); 
}