/**
 * Blog Over Theme Functions
 * 
 * Main theme JavaScript functionality
 *
 * @package Blog_Over
 */

(function () {
    'use strict';

    /**
     * Dark Mode Toggle (Top Bar Switcher)
     * 
     * PRIORITY LOGIC:
     * 1. User Preference (localStorage) - highest priority
     * 2. Theme Skin (Customizer/body class from PHP) - fallback
     * 3. Light mode - hardcoded fallback
     * 
     * User preference saved to localStorage, persists across page reloads
     * Theme Skin setting in Customizer is NEVER modified by this toggle
     * Note: Inline script in <head> applies initial class to html element to prevent FOUC
     */
    function initDarkMode() {
        var toggles = document.querySelectorAll('.blog-over-theme-toggle');
        if (!toggles.length) return;

        const STORAGE_KEY = 'blog_over_user_skin_preference';

        // Read user preference from localStorage
        const userPreference = localStorage.getItem(STORAGE_KEY);

        // Get admin default from body class (set by PHP based on Customizer Theme Skin)
        const adminDefault = document.body.classList.contains('blog-over-dark-mode') ? 'dark' : 'light';

        // Determine active skin: User preference > Admin default
        let activeSkin;
        if (userPreference && (userPreference === 'dark' || userPreference === 'light')) {
            activeSkin = userPreference;
        } else {
            activeSkin = adminDefault;
        }

        // Apply the active skin to both html and body (html is already set by inline script)
        if (activeSkin === 'dark') {
            document.documentElement.classList.add('blog-over-dark-mode');
            document.body.classList.add('blog-over-dark-mode');
        } else {
            document.documentElement.classList.remove('blog-over-dark-mode');
            document.body.classList.remove('blog-over-dark-mode');
        }

        // Update all toggle states
        var isDark = activeSkin === 'dark';
        toggles.forEach(function (toggle) {
            toggle.setAttribute('aria-pressed', isDark.toString());
            updateToggleIcon(toggle, isDark);
        });

        // Bind click to every toggle — syncs all instances
        toggles.forEach(function (toggle) {
            toggle.addEventListener('click', function () {
                var newIsDark = !document.body.classList.contains('blog-over-dark-mode');

                if (newIsDark) {
                    document.documentElement.classList.add('blog-over-dark-mode');
                    document.body.classList.add('blog-over-dark-mode');
                } else {
                    document.documentElement.classList.remove('blog-over-dark-mode');
                    document.body.classList.remove('blog-over-dark-mode');
                }

                var newSkin = newIsDark ? 'dark' : 'light';
                localStorage.setItem(STORAGE_KEY, newSkin);

                // Update ALL toggles so desktop + mobile stay in sync
                toggles.forEach(function (t) {
                    t.setAttribute('aria-pressed', newIsDark.toString());
                    updateToggleIcon(t, newIsDark);
                });
            });
        });
    }

    /**
     * Update toggle button icon/state (supports all toggle styles)
     */
    function updateToggleIcon(toggle, isDark) {
        // Pill & Labeled styles: use CSS class for thumb position
        if (toggle.classList.contains('blog-over-toggle-pill') ||
            toggle.classList.contains('blog-over-toggle-labeled')) {
            if (isDark) {
                toggle.classList.add('active');
            } else {
                toggle.classList.remove('active');
            }
            return;
        }

        // Icon style: swap moon/sun icon
        const icon = toggle.querySelector('i');
        if (icon) {
            if (isDark) {
                icon.className = 'fas fa-sun'; // Show sun icon when dark (click to go light)
            } else {
                icon.className = 'fas fa-moon'; // Show moon icon when light (click to go dark)
            }
        }
    }

    /**
     * Scroll to Top Button
     */
    function initScrollToTop() {
        const btn = document.querySelector('.blog-over-scroll-top');
        if (!btn) return;

        function toggleVisibility() {
            if (window.scrollY > 300) {
                btn.classList.add('visible');
            } else {
                btn.classList.remove('visible');
            }
        }

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

        btn.addEventListener('click', function (e) {
            e.preventDefault();
            window.scrollTo({
                top: 0,
                behavior: 'smooth'
            });
        });
    }

    /**
     * Sticky Sidebar
     */
    function initStickySidebar() {
        const sidebar = document.querySelector('.blog-over-sticky-sidebar');
        if (!sidebar) return;

        const header = document.querySelector('.blog-over-site-header');
        const headerHeight = header ? header.offsetHeight : 0;
        const offset = headerHeight + 30;

        function handleScroll() {
            const sidebarTop = sidebar.parentElement.getBoundingClientRect().top;

            if (sidebarTop < offset) {
                sidebar.style.position = 'sticky';
                sidebar.style.top = offset + 'px';
            }
        }

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

    /**
     * Smooth Anchor Links
     */
    function initSmoothScroll() {
        document.querySelectorAll('a[href^="#"]').forEach(function (anchor) {
            anchor.addEventListener('click', function (e) {
                const targetId = this.getAttribute('href');
                if (targetId === '#') return;

                const target = document.querySelector(targetId);
                if (!target) return;

                e.preventDefault();
                target.scrollIntoView({
                    behavior: 'smooth',
                    block: 'start'
                });
            });
        });
    }

    /**
     * Search Functionality
     * Handles all 3 search styles: popup, inline, slide-panel
     */
    function initSearch() {
        var searchToggles = document.querySelectorAll('.blog-over-search-toggle');
        if (!searchToggles.length) return;

        const searchModal = document.querySelector('.blog-over-search-modal');
        const searchInline = document.querySelector('.blog-over-search-inline');
        const searchPanel = document.querySelector('.blog-over-search-panel');

        function getStyleSearchElement(style) {
            if (style === 'popup') return searchModal;
            if (style === 'inline') return searchInline;
            if (style === 'slide-panel' || style === 'slide-panel-rtl') return searchPanel;
            return null;
        }

        let activeSearchElement = null;
        let activeSearchStyle = null;
        let activeToggle = null;

        function positionInlineDropdown(toggle, element) {
            var rect = toggle.getBoundingClientRect();
            var dropdownWidth = 340;
            var gap = 10;
            var topPos = rect.bottom + gap;
            var rightPos = Math.max(12, window.innerWidth - rect.right - 12);

            // Ensure dropdown doesn't go off-screen right
            if (rect.right - dropdownWidth + 12 < 0) {
                rightPos = window.innerWidth - dropdownWidth - 12;
            }

            element.style.top = topPos + 'px';
            element.style.right = rightPos + 'px';
        }

        function openSearch(toggle, style, element) {
            activeSearchElement = element;
            activeSearchStyle = style;
            activeToggle = toggle;

            // Position inline dropdown below the toggle button
            if (style === 'inline') {
                positionInlineDropdown(toggle, element);
            }

            element.setAttribute('aria-hidden', 'false');
            toggle.setAttribute('aria-expanded', 'true');
            toggle.classList.add('active');

            if (style === 'slide-panel' || style === 'slide-panel-rtl') {
                document.body.classList.add('blog-over-search-open');
            }

            const searchInput = element.querySelector('.blog-over-search-input');
            setTimeout(function () {
                if (searchInput) {
                    searchInput.focus();
                }
            }, 300);
        }

        function closeSearch() {
            if (!activeSearchElement) return;

            activeSearchElement.setAttribute('aria-hidden', 'true');

            searchToggles.forEach(function (t) {
                t.setAttribute('aria-expanded', 'false');
                t.classList.remove('active');
            });

            if (activeSearchStyle === 'slide-panel' || activeSearchStyle === 'slide-panel-rtl') {
                document.body.classList.remove('blog-over-search-open');
            }

            if (activeToggle) {
                activeToggle.focus();
            }

            activeSearchElement = null;
            activeSearchStyle = null;
            activeToggle = null;
        }

        searchToggles.forEach(function (btn) {
            btn.addEventListener('click', function (e) {
                e.preventDefault();
                e.stopPropagation();

                var style = btn.getAttribute('data-search-style') || 'popup';
                var element = getStyleSearchElement(style);

                if (!element) return;

                var isOpen = element.getAttribute('aria-hidden') === 'false';

                if (isOpen) {
                    closeSearch();
                } else {
                    if (activeSearchElement) closeSearch();
                    openSearch(btn, style, element);
                }
            });
        });

        document.querySelectorAll('.blog-over-search-close').forEach(function (btn) {
            btn.addEventListener('click', function (e) {
                e.preventDefault();
                closeSearch();
            });
        });

        document.querySelectorAll('.blog-over-search-modal-overlay, .blog-over-search-panel-overlay').forEach(function (overlay) {
            overlay.addEventListener('click', function (e) {
                e.preventDefault();
                closeSearch();
            });
        });

        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape' && activeSearchElement) {
                closeSearch();
            }
        });

        // Reposition inline dropdown on scroll/resize
        function handleScrollResize() {
            if (activeSearchStyle === 'inline' && activeSearchElement && activeToggle) {
                positionInlineDropdown(activeToggle, activeSearchElement);
            }
        }
        window.addEventListener('scroll', handleScrollResize, { passive: true });
        window.addEventListener('resize', handleScrollResize, { passive: true });

        document.addEventListener('click', function (e) {
            if (activeSearchStyle === 'inline' && activeSearchElement) {
                var isInsideToggle = false;
                searchToggles.forEach(function (t) {
                    if (t.contains(e.target)) isInsideToggle = true;
                });

                if (!activeSearchElement.contains(e.target) && !isInsideToggle) {
                    closeSearch();
                }
            }
        });

        function trapFocus(e, container) {
            if (e.key !== 'Tab') return;

            const focusableElements = container.querySelectorAll(
                'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
            );
            if (!focusableElements.length) return;

            const firstFocusable = focusableElements[0];
            const lastFocusable = focusableElements[focusableElements.length - 1];

            if (e.shiftKey) {
                if (document.activeElement === firstFocusable) {
                    lastFocusable.focus();
                    e.preventDefault();
                }
            } else {
                if (document.activeElement === lastFocusable) {
                    firstFocusable.focus();
                    e.preventDefault();
                }
            }
        }

        if (searchModal) {
            searchModal.addEventListener('keydown', function (e) { trapFocus(e, searchModal); });
        }
        if (searchPanel) {
            searchPanel.addEventListener('keydown', function (e) { trapFocus(e, searchPanel); });
        }
    }

    /**
     * Hero Slider
     * Handles slider navigation, autoplay, dots, and effects
     * Supports multiple sliders on the page (for Grid layout)
     * Exposes reinit method for Customizer live preview
     */

    // Store slider instances for cleanup
    var sliderInstances = [];

    /**
     * Destroy all slider instances (cleanup)
     */
    function destroyHeroSliders() {
        sliderInstances.forEach(function (instance) {
            if (instance.autoplayInterval) {
                clearInterval(instance.autoplayInterval);
            }
            // Remove event listeners by cloning and replacing
            if (instance.slider) {
                instance.slider.removeAttribute('data-initialized');
            }
        });
        sliderInstances = [];
    }

    /**
     * Initialize all hero sliders
     */
    function initHeroSlider() {
        const wrapper = document.querySelector('.blog-over-hero-wrapper');
        if (!wrapper) return;

        // Get all sliders on the page (main slider + slot sliders)
        const sliders = wrapper.querySelectorAll('.blog-over-hero-slider');
        if (sliders.length === 0) return;

        // Read global/fallback settings from wrapper data attributes
        const globalAutoplay = wrapper.dataset.autoplay === 'true';
        const globalSpeed = parseInt(wrapper.dataset.speed, 10) || 5000;
        const globalPauseHover = wrapper.dataset.pauseHover === 'true';
        const globalEffect = wrapper.dataset.effect || 'slide';
        const globalLoop = wrapper.dataset.loop !== 'false'; // default true

        // Initialize each slider with its own settings (or fallback to global)
        sliders.forEach(function (slider) {
            // Skip if already initialized
            if (slider.dataset.initialized === 'true') return;

            // Read per-slider settings, fallback to global
            const autoplay = slider.dataset.autoplay !== undefined ? slider.dataset.autoplay === 'true' : globalAutoplay;
            const speed = slider.dataset.speed ? parseInt(slider.dataset.speed, 10) : globalSpeed;
            const pauseHover = slider.dataset.pauseHover !== undefined ? slider.dataset.pauseHover === 'true' : globalPauseHover;
            const effect = slider.dataset.effect || globalEffect;
            const loop = slider.dataset.loop !== undefined ? slider.dataset.loop !== 'false' : globalLoop;

            initSingleSlider(slider, autoplay, speed, pauseHover, effect, loop);
            slider.dataset.initialized = 'true';
        });
    }

    /**
     * Reinitialize hero sliders (for Customizer live preview)
     */
    function reinitHeroSliders() {
        destroyHeroSliders();
        // Small delay to ensure DOM is updated
        setTimeout(function () {
            initHeroSlider();
        }, 100);
    }

    // Expose globally for Customizer
    window.novaHeroSlider = {
        init: initHeroSlider,
        destroy: destroyHeroSliders,
        reinit: reinitHeroSliders
    };

    /**
     * Initialize a single slider instance
     */
    function initSingleSlider(slider, autoplay, speed, pauseHover, effect, loop) {
        const track = slider.querySelector('.blog-over-slider-track');
        const slides = slider.querySelectorAll('.blog-over-hero-item');
        const prevBtn = slider.querySelector('.blog-over-slider-prev');
        const nextBtn = slider.querySelector('.blog-over-slider-next');
        const dotsContainer = slider.querySelector('.blog-over-slider-dots, .blog-over-slider-thumbnails');
        const dots = dotsContainer ? dotsContainer.querySelectorAll('.blog-over-slider-dot, .blog-over-slider-thumb') : [];

        if (slides.length <= 1) return;

        let currentIndex = 0;
        let autoplayInterval = null;
        let isPaused = false;

        // Store instance for cleanup
        var instance = {
            slider: slider,
            autoplayInterval: null
        };
        sliderInstances.push(instance);

        /**
         * Go to specific slide
         */
        function goToSlide(index) {
            // Handle looping vs non-looping
            if (loop) {
                // Wrap around for loop mode
                if (index < 0) index = slides.length - 1;
                if (index >= slides.length) index = 0;
            } else {
                // Clamp for non-loop mode
                if (index < 0) index = 0;
                if (index >= slides.length) index = slides.length - 1;
            }

            // Remove active class from all slides and dots
            slides.forEach(function (slide) {
                slide.classList.remove('active', 'blog-over-slide-prev', 'blog-over-slide-next', 'blog-over-slide-out');
            });
            dots.forEach(function (dot) {
                dot.classList.remove('active');
            });

            // Add active class to current slide and dot
            slides[index].classList.add('active');
            
            // Add prev and next classes for advanced CSS effects (like Coverflow)
            let prevIndex = index - 1;
            if (prevIndex < 0) prevIndex = loop ? slides.length - 1 : 0;
            if (slides[prevIndex] && prevIndex !== index) slides[prevIndex].classList.add('blog-over-slide-prev');

            let nextIndex = index + 1;
            if (nextIndex >= slides.length) nextIndex = loop ? 0 : slides.length - 1;
            if (slides[nextIndex] && nextIndex !== index) slides[nextIndex].classList.add('blog-over-slide-next');

            if (dots[index]) {
                dots[index].classList.add('active');
            }

            // Dispatch event for Pro features (Fraction, Progressbar)
            slider.dispatchEvent(new CustomEvent('blogOverSlideChanged', {
                bubbles: true,
                detail: { index: index, total: slides.length }
            }));

            // Apply effect based on setting
            if (effect === 'slide' && track) {
                // Slide effect: horizontal translate
                track.style.transform = 'translateX(-' + (index * 100) + '%)';
            } else if (effect === 'fade' || effect === 'coverflow' || effect === 'zoom') {
                // Effects that rely purely on CSS for transition
                // Track should not translate
                if (track) {
                    track.style.transform = 'translateX(0)';
                }
            }

            currentIndex = index;
        }

        /**
         * Next slide
         */
        function nextSlide() {
            goToSlide(currentIndex + 1);
        }

        /**
         * Previous slide
         */
        function prevSlide() {
            goToSlide(currentIndex - 1);
        }

        /**
         * Start autoplay
         */
        function startAutoplay() {
            if (autoplay && !autoplayInterval) {
                autoplayInterval = setInterval(function () {
                    if (!isPaused) {
                        nextSlide();
                    }
                }, speed);
                // Store in instance for cleanup
                instance.autoplayInterval = autoplayInterval;
            }
        }

        /**
         * Stop autoplay
         */
        function stopAutoplay() {
            if (autoplayInterval) {
                clearInterval(autoplayInterval);
                autoplayInterval = null;
            }
        }

        // Event listeners for arrows
        if (prevBtn) {
            prevBtn.addEventListener('click', function (e) {
                e.preventDefault();
                prevSlide();
            });
        }

        if (nextBtn) {
            nextBtn.addEventListener('click', function (e) {
                e.preventDefault();
                nextSlide();
            });
        }

        // Event listeners for dots
        dots.forEach(function (dot) {
            dot.addEventListener('click', function (e) {
                e.preventDefault();
                var index = parseInt(dot.dataset.index, 10);
                goToSlide(index);
            });
        });

        // Pause on hover
        if (pauseHover) {
            slider.addEventListener('mouseenter', function () {
                isPaused = true;
            });

            slider.addEventListener('mouseleave', function () {
                isPaused = false;
            });
        }

        // Keyboard navigation (only for focused slider)
        slider.setAttribute('tabindex', '0');
        slider.addEventListener('keydown', function (e) {
            if (e.key === 'ArrowLeft') {
                prevSlide();
            } else if (e.key === 'ArrowRight') {
                nextSlide();
            }
        });

        // Touch/swipe support
        let touchStartX = 0;
        let touchEndX = 0;

        slider.addEventListener('touchstart', function (e) {
            touchStartX = e.changedTouches[0].screenX;
        }, { passive: true });

        slider.addEventListener('touchend', function (e) {
            touchEndX = e.changedTouches[0].screenX;
            handleSwipe(touchStartX, touchEndX);
        }, { passive: true });

        // Mouse drag support (desktop) - only on track, not dots/arrows
        let mouseStartX = 0;
        let isDragging = false;
        let hasDragged = false; // Track if actual drag happened
        const dragThreshold = 10; // Minimum px to consider it a drag

        // Only attach drag to the track area
        track.style.cursor = 'grab';

        track.addEventListener('mousedown', function (e) {
            // Don't drag if clicking on dots, arrows, or links
            if (e.target.closest('.blog-over-slider-dots') ||
                e.target.closest('.blog-over-slider-arrow') ||
                e.target.closest('a')) {
                return;
            }

            isDragging = true;
            hasDragged = false;
            mouseStartX = e.screenX;
            track.style.cursor = 'grabbing';
            e.preventDefault();
        });

        track.addEventListener('mousemove', function (e) {
            if (!isDragging) return;

            // Check if we've moved enough to consider it a drag
            if (Math.abs(e.screenX - mouseStartX) > dragThreshold) {
                hasDragged = true;
            }
            e.preventDefault();
        });

        track.addEventListener('mouseup', function (e) {
            if (!isDragging) return;
            isDragging = false;
            track.style.cursor = 'grab';

            if (hasDragged) {
                handleSwipe(mouseStartX, e.screenX);
            }
        });

        track.addEventListener('mouseleave', function (e) {
            if (isDragging) {
                isDragging = false;
                track.style.cursor = 'grab';

                if (hasDragged) {
                    handleSwipe(mouseStartX, e.screenX);
                }
            }
        });

        // Prevent link clicks after dragging
        slider.addEventListener('click', function (e) {
            if (hasDragged && e.target.closest('a')) {
                e.preventDefault();
                e.stopPropagation();
                hasDragged = false;
            }
        }, true);

        function handleSwipe(startX, endX) {
            var swipeThreshold = 50;
            var diff = startX - endX;

            if (Math.abs(diff) > swipeThreshold) {
                if (diff > 0) {
                    nextSlide(); // Swipe left = next
                } else {
                    prevSlide(); // Swipe right = prev
                }
            }
        }

        // Initialize
        goToSlide(0);
        startAutoplay();
    }

    /**
     * Hide Loading Screen
     * 
     * Uses Customizer settings via data attributes:
     * - data-min-duration: Minimum time (seconds) the loader stays visible
     */
    function hideLoadingScreen() {
        const loadingScreen = document.querySelector('.blog-over-loading-screen');
        if (!loadingScreen) return;

        // Get minimum duration from data attribute (set by Customizer via header.php)
        const minDuration = parseFloat(loadingScreen.getAttribute('data-min-duration')) || 0.5;
        const minDurationMs = minDuration * 1000;

        // Calculate when page started loading (approximate)
        const pageLoadStart = performance.timing ? performance.timing.navigationStart : Date.now() - 1000;
        const elapsed = Date.now() - pageLoadStart;
        const remainingTime = Math.max(0, minDurationMs - elapsed);

        // Wait for minimum duration, then hide
        setTimeout(function () {
            loadingScreen.classList.add('loaded');

            // Remove from DOM after fade-out animation completes
            setTimeout(function () {
                if (loadingScreen.parentNode) {
                    loadingScreen.parentNode.removeChild(loadingScreen);
                }
            }, 500);
        }, remainingTime);
    }

    /**
     * Mobile Top Bar — Bottom Popup
     * 
     * On mobile (≤768px), tapping the info icon opens a fixed
     * bottom-sheet popup with social links, dark mode toggle,
     * search, and subscribe. Includes:
     *  - Overlay dismiss
     *  - Close button
     *  - ESC key close
     *  - Focus trap (Tab / Shift+Tab cycle)
     *  - Body scroll lock while open
     */
    function initTopbarToggle() {
        var toggles = document.querySelectorAll('.blog-over-topbar-toggle');
        var popups = document.querySelectorAll('.blog-over-topbar-popup');
        
        if (toggles.length === 0 || popups.length === 0) return;

        toggles.forEach(function(toggle, index) {
            // Assume 1-to-1 mapping if multiple exist, else fallback to first popup
            var popup = popups[index] ? popups[index] : popups[0];
            var closeBtn = popup.querySelector('.blog-over-topbar-popup-close');
            var overlay = popup.querySelector('.blog-over-topbar-popup-overlay');
            var panel = popup.querySelector('.blog-over-topbar-popup-panel');

            function openPopup() {
                popup.classList.add('blog-over-popup-open');
                popup.setAttribute('aria-hidden', 'false');
                toggle.setAttribute('aria-expanded', 'true');
                document.body.style.overflow = 'hidden';

                setTimeout(function () {
                    if (closeBtn) closeBtn.focus();
                }, 350);
            }

            function closePopup() {
                popup.classList.remove('blog-over-popup-open');
                popup.setAttribute('aria-hidden', 'true');
                toggle.setAttribute('aria-expanded', 'false');
                document.body.style.overflow = '';
                toggle.focus();
            }

            function isOpen() {
                return popup.classList.contains('blog-over-popup-open');
            }

            toggle.addEventListener('click', function (e) {
                e.preventDefault();
                e.stopPropagation();
                if (isOpen()) {
                    closePopup();
                } else {
                    openPopup();
                }
            });

        // Close button click
        if (closeBtn) {
            closeBtn.addEventListener('click', function (e) {
                e.preventDefault();
                closePopup();
            });
        }

        // Overlay click — close
        if (overlay) {
            overlay.addEventListener('click', function () {
                closePopup();
            });
        }

        // ESC key — close
        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape' && isOpen()) {
                closePopup();
            }
        });

        // Focus trap — cycle Tab / Shift+Tab within the popup panel
        popup.addEventListener('keydown', function (e) {
            if (e.key !== 'Tab' || !isOpen()) return;

            var focusable = Array.from(panel.querySelectorAll(
                'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
            )).filter(function(el) {
                return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
            });
            if (!focusable.length) return;

            var first = focusable[0];
            var last = focusable[focusable.length - 1];

            if (e.shiftKey) {
                // Shift+Tab: wrap from first → last
                if (document.activeElement === first) {
                    e.preventDefault();
                    last.focus();
                }
            } else {
                // Tab: wrap from last → first
                if (document.activeElement === last) {
                    e.preventDefault();
                    first.focus();
                }
            }
        });
        });
    }

    /**
     * Skip Link Handler (WordPress Accessibility Guidelines)
     * 
     * After the skip link is activated:
     * 1. Move focus to the target element
     * 2. Blur the skip link so it hides properly
     */
    function initSkipLink() {
        const skipLink = document.querySelector('.skip-link');
        if (!skipLink) return;

        skipLink.addEventListener('click', function (e) {
            const targetId = this.getAttribute('href');
            const target = document.querySelector(targetId);

            if (target) {
                e.preventDefault();

                // Make target focusable if it isn't already
                if (!target.hasAttribute('tabindex')) {
                    target.setAttribute('tabindex', '-1');
                }

                // Focus the target element
                target.focus({ preventScroll: false });

                // Scroll to target
                target.scrollIntoView({ behavior: 'smooth', block: 'start' });

                // Blur the skip link to hide it
                this.blur();
            }
        });
    }

    /**
     * Ad Banner Close / Dismiss Button
     *
     * Handles the close button on dismissable ad banners.
     * Uses event delegation so it works after Customizer partial refreshes.
     */
    function initAdBannerClose() {
        document.addEventListener('click', function (e) {
            var closeBtn = e.target.closest('.blog-over-ad-close');
            if (!closeBtn) return;

            e.preventDefault();
            var banner = closeBtn.closest('.blog-over-ad-banner');
            if (!banner) return;

            // Smooth fade-out
            banner.style.transition = 'opacity 0.4s ease, transform 0.4s ease, max-height 0.5s ease 0.2s';
            banner.style.opacity = '0';
            banner.style.transform = 'translateY(-10px)';
            banner.style.maxHeight = banner.offsetHeight + 'px';
            banner.style.overflow = 'hidden';

            // Collapse height after fade
            setTimeout(function () {
                banner.style.maxHeight = '0';
                banner.style.padding = '0';
                banner.style.margin = '0';
                banner.style.border = 'none';
            }, 50);

            // Remove from DOM
            setTimeout(function () {
                if (banner.parentNode) {
                    banner.parentNode.removeChild(banner);
                }

                // If container is now empty, hide the wrapper
                var wrappers = document.querySelectorAll('.blog-over-ad-banner-wrapper');
                wrappers.forEach(function (wrapper) {
                    if (!wrapper.querySelector('.blog-over-ad-banner')) {
                        wrapper.style.display = 'none';
                    }
                });
            }, 700);
        });
    }

    /**
     * Reading Progress Bar
     * Highlights the reading progress of a single post based on scroll depth.
     */
    function initReadingProgressBar() {
        var progressBar = document.getElementById('blog-over-reading-progress-bar');
        if (!progressBar) return;

        function updateProgress() {
            var scrollTop = window.scrollY || document.documentElement.scrollTop;
            var docHeight = Math.max(
                document.body.scrollHeight, document.documentElement.scrollHeight,
                document.body.offsetHeight, document.documentElement.offsetHeight,
                document.body.clientHeight, document.documentElement.clientHeight
            );
            var winHeight = window.innerHeight;

            var scrollable = docHeight - winHeight;
            var scrollPercent = 0;

            if (scrollable > 0) {
                scrollPercent = (scrollTop / scrollable) * 100;
            }

            if (scrollPercent > 100) scrollPercent = 100;
            if (scrollPercent < 0 || isNaN(scrollPercent)) scrollPercent = 0;

            progressBar.style.width = scrollPercent + '%';
        }

        window.addEventListener('scroll', updateProgress, { passive: true });
        // Initial call
        updateProgress();
    }

    /**
     * Initialize all functions on DOM ready
     */
    function init() {
        initDarkMode();
        initScrollToTop();
        initStickySidebar();
        initSmoothScroll();
        initSearch();
        initHeroSlider();
        initTopbarToggle();
        initSkipLink();
        initAdBannerClose();
        initReadingProgressBar();

        // MutationObserver for Customizer partial refresh
        // When Customizer updates the hero section via selective refresh,
        // we need to reinitialize the sliders
        if (typeof wp !== 'undefined' && wp.customize) {
            // In Customizer preview, watch for DOM changes to hero wrapper
            var heroObserver = new MutationObserver(function (mutations) {
                mutations.forEach(function (mutation) {
                    // Check if hero wrapper was added or modified
                    mutation.addedNodes.forEach(function (node) {
                        if (node.nodeType === 1) {
                            if (node.classList && node.classList.contains('blog-over-hero-wrapper')) {
                                // Hero section was replaced, reinit
                                setTimeout(function () {
                                    window.novaHeroSlider.reinit();
                                }, 50);
                            } else if (node.querySelector && node.querySelector('.blog-over-hero-wrapper')) {
                                // Container with hero was added
                                setTimeout(function () {
                                    window.novaHeroSlider.reinit();
                                }, 50);
                            }
                        }
                    });
                });
            });

            // Observe the body for changes
            heroObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // Hide loading screen after window fully loads (including images)
    window.addEventListener('load', function () {
        hideLoadingScreen();
    });

})();
