(function() {
    'use strict';

    if (window.vmoGeneratedSiteEffects && typeof window.vmoGeneratedSiteEffects.refresh === 'function') {
        window.vmoGeneratedSiteEffects.refresh();
        return;
    }

    const TITLE_SELECTORS = [
        'h1',
        'h2',
        'h3',
        'h4',
        'h5',
        'h6',
        '[data-vmo-title]',
        '.hero-title',
        '.section-title',
        '.title',
        '.heading',
        '.headline',
        '[class*="title"]',
        '[class*="heading"]',
        '[class*="headline"]'
    ].join(',');

    const SECTION_SELECTORS = [
        'section',
        'article',
        '[class*="hero"]',
        '[class*="showcase"]',
        '[class*="banner"]',
        '[class*="feature"]',
        '[class*="panel"]'
    ].join(',');

    const MEDIA_HINT_SELECTORS = [
        '[data-parallax]',
        '[data-vmo-parallax]',
        '[class*="media"]',
        '[class*="visual"]',
        '[class*="image"]',
        '[class*="video"]',
        'picture img',
        'img',
        'video'
    ].join(',');

    const EXCLUDED_SELECTOR = [
        'nav',
        'button',
        'label',
        'input',
        'select',
        'textarea',
        'footer',
        '.swiper-pagination',
        '.swiper-button-next',
        '.swiper-button-prev',
        '.splide__arrows',
        '.splide__pagination'
    ].join(',');

    const STYLE_ID = 'vmo-generated-site-effects-style';
    const state = {
        observer: null,
        refreshTimer: 0
    };

    function clamp(value, min, max) {
        return Math.max(min, Math.min(max, value));
    }

    function getClassText(element) {
        if (!element || !element.getAttribute) return '';
        return String(element.getAttribute('class') || '');
    }

    function hasReducedMotionPreference() {
        return !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);
    }

    function hasExcludedAncestor(element) {
        return !!(element && element.closest && element.closest(EXCLUDED_SELECTOR));
    }

    function hasBackgroundImage(element) {
        if (!element || !window.getComputedStyle) return false;
        const style = window.getComputedStyle(element);
        return !!(style && style.backgroundImage && style.backgroundImage !== 'none');
    }

    function isVisibleEnough(element) {
        if (!element || !element.getBoundingClientRect) return false;
        const rect = element.getBoundingClientRect();
        return rect.width >= 16 && rect.height >= 12;
    }

    function getTitleDepth(element) {
        const tag = String(element.tagName || '').toLowerCase();
        if (tag === 'h1') return 72;
        if (tag === 'h2') return 56;
        if (tag === 'h3') return 44;
        return 30;
    }

    function getTitleScrubAmount(element) {
        const tag = String(element.tagName || '').toLowerCase();
        if (tag === 'h1') return -10;
        if (tag === 'h2') return -8;
        if (tag === 'h3') return -6;
        return -4;
    }

    function getGsap() {
        return window.gsap;
    }

    function getScrollTrigger() {
        return window.ScrollTrigger;
    }

    function ensureStyles() {
        if (!document.head || document.getElementById(STYLE_ID)) return;

        const style = document.createElement('style');
        style.id = STYLE_ID;
        style.textContent = [
            '.vmo-motion-title {',
            '  backface-visibility: hidden;',
            '  transform-origin: 50% 100%;',
            '  will-change: transform, opacity, filter;',
            '}',
            '.vmo-parallax-target {',
            '  transform: translate3d(0, 0, 0);',
            '  will-change: transform, background-position;',
            '}',
            '.vmo-motion-scope, .vmo-root {',
            '  overflow-x: clip;',
            '}',
            '@supports not (overflow: clip) {',
            '  .vmo-motion-scope, .vmo-root { overflow-x: hidden; }',
            '}',
            '@media (prefers-reduced-motion: reduce) {',
            '  .vmo-motion-title, .vmo-parallax-target {',
            '    transition-duration: 0.01ms !important;',
            '  }',
            '}'
        ].join('\n');

        document.head.appendChild(style);
    }

    function registerPlugins() {
        const gsap = getGsap();
        const ScrollTrigger = getScrollTrigger();

        if (!gsap || !ScrollTrigger) return false;

        try {
            gsap.registerPlugin(ScrollTrigger);
        } catch (_) {}

        return true;
    }

    function isMeaningfulTitleNode(element) {
        if (!element || !element.isConnected || hasExcludedAncestor(element) || !isVisibleEnough(element)) {
            return false;
        }

        const tag = String(element.tagName || '').toLowerCase();
        if (/^(script|style|noscript)$/.test(tag)) return false;

        const text = String(element.textContent || '').replace(/\s+/g, ' ').trim();
        if (text.length < 2) return false;

        if (/^h[1-6]$/.test(tag)) return true;
        if (element.hasAttribute('data-vmo-title')) return true;

        const classText = getClassText(element);
        if (!/(title|heading|headline)/i.test(classText)) return false;

        return text.length <= 240;
    }

    function collectTitleNodes(root) {
        const scope = root && root.querySelectorAll ? root : document;
        const seen = new Set();
        const titles = [];

        scope.querySelectorAll(TITLE_SELECTORS).forEach(function(element) {
            if (seen.has(element) || !isMeaningfulTitleNode(element)) return;
            seen.add(element);
            titles.push(element);
        });

        return titles;
    }

    function isMeaningfulVisual(element) {
        if (!element || !element.isConnected || hasExcludedAncestor(element) || !isVisibleEnough(element)) {
            return false;
        }

        const tag = String(element.tagName || '').toLowerCase();
        const rect = element.getBoundingClientRect();

        if (tag === 'img' || tag === 'video') {
            return rect.width >= 120 && rect.height >= 120;
        }

        if (element.hasAttribute('data-parallax') || element.hasAttribute('data-vmo-parallax')) {
            return rect.width >= 80 && rect.height >= 80;
        }

        if (hasBackgroundImage(element)) {
            return rect.width >= 120 && rect.height >= 180;
        }

        return /(media|visual|image|video|hero|banner|showcase|panel)/i.test(getClassText(element))
            && rect.width >= 120
            && rect.height >= 120;
    }

    function getMotionTrigger(element) {
        if (!element || !element.closest) return element;

        return element.closest('section, article, [class*="hero"], [class*="showcase"], [class*="banner"], [class*="feature"], [class*="panel"]')
            || element.parentElement
            || element;
    }

    function resolveParallaxConfig(element, reducedMotion) {
        const rawMode = String(element.getAttribute('data-parallax') || '').trim().toLowerCase();
        const rawSpeed = String(element.getAttribute('data-parallax-speed') || element.getAttribute('data-vmo-parallax') || '').trim().toLowerCase();

        let mode = 'y';
        if (['x', 'y', 'rotate', 'scale'].includes(rawMode)) {
            mode = rawMode;
        }

        let speed = parseFloat(rawSpeed);
        if (!Number.isFinite(speed)) {
            if (rawSpeed === 'slow') speed = 0.16;
            else if (rawSpeed === 'fast') speed = 0.34;
            else if (rawSpeed === 'medium') speed = 0.24;
            else speed = hasBackgroundImage(element) ? 0.16 : 0.22;
        }

        speed = clamp(speed, 0.08, 0.45);
        if (reducedMotion) {
            speed = clamp(speed * 0.45, 0.05, 0.18);
        }

        return { mode, speed };
    }

    function collectParallaxCandidates(root) {
        const scope = root && root.querySelectorAll ? root : document;
        const candidates = new Set();

        scope.querySelectorAll('[data-parallax], [data-vmo-parallax]').forEach(function(element) {
            if (isMeaningfulVisual(element)) {
                candidates.add(element);
            }
        });

        scope.querySelectorAll(SECTION_SELECTORS).forEach(function(section) {
            if (candidates.size >= 18 || !section || !section.isConnected || hasExcludedAncestor(section)) {
                return;
            }

            const hintedVisual = section.querySelector(MEDIA_HINT_SELECTORS);
            if (hintedVisual && isMeaningfulVisual(hintedVisual)) {
                candidates.add(hintedVisual);
                return;
            }

            if (hasBackgroundImage(section) && isMeaningfulVisual(section)) {
                candidates.add(section);
            }
        });

        if (!candidates.size) {
            Array.from(scope.querySelectorAll('img, video'))
                .filter(isMeaningfulVisual)
                .sort(function(left, right) {
                    const leftRect = left.getBoundingClientRect();
                    const rightRect = right.getBoundingClientRect();
                    return (rightRect.width * rightRect.height) - (leftRect.width * leftRect.height);
                })
                .slice(0, 8)
                .forEach(function(element) {
                    candidates.add(element);
                });
        }

        return Array.from(candidates).slice(0, 18);
    }

    function bindTitleAnimations(root) {
        const gsap = getGsap();
        const ScrollTrigger = getScrollTrigger();
        const reducedMotion = hasReducedMotionPreference();

        if (!gsap || !ScrollTrigger) return;

        collectTitleNodes(root).forEach(function(element) {
            if (element.dataset.vmoGsapTitleReady === '1') return;

            element.dataset.vmoGsapTitleReady = '1';
            element.classList.add('vmo-motion-title');

            const travel = reducedMotion ? clamp(getTitleDepth(element) * 0.35, 10, 24) : getTitleDepth(element);
            const scrubAmount = reducedMotion ? getTitleScrubAmount(element) * 0.4 : getTitleScrubAmount(element);

            gsap.fromTo(element,
                {
                    autoAlpha: 0.01,
                    y: travel,
                    rotateX: reducedMotion ? 0 : 10,
                    filter: reducedMotion ? 'blur(0px)' : 'blur(8px)',
                    transformPerspective: 900,
                    transformOrigin: '50% 100%'
                },
                {
                    autoAlpha: 1,
                    y: 0,
                    rotateX: 0,
                    filter: 'blur(0px)',
                    duration: reducedMotion ? 0.45 : 1.05,
                    ease: 'power3.out',
                    overwrite: 'auto',
                    scrollTrigger: {
                        trigger: element,
                        start: 'top 88%',
                        toggleActions: 'play none none reverse'
                    }
                }
            );

            gsap.to(element, {
                yPercent: scrubAmount,
                ease: 'none',
                overwrite: 'auto',
                scrollTrigger: {
                    trigger: getMotionTrigger(element),
                    start: 'top bottom',
                    end: 'bottom top',
                    scrub: reducedMotion ? 0.35 : true
                }
            });
        });
    }

    function bindParallaxAnimations(root) {
        const gsap = getGsap();
        const ScrollTrigger = getScrollTrigger();
        const reducedMotion = hasReducedMotionPreference();

        if (!gsap || !ScrollTrigger) return;

        collectParallaxCandidates(root).forEach(function(element) {
            if (element.dataset.vmoGsapParallaxReady === '1') return;

            element.dataset.vmoGsapParallaxReady = '1';
            element.classList.add('vmo-parallax-target');

            const config = resolveParallaxConfig(element, reducedMotion);
            const bounds = element.getBoundingClientRect();
            const distance = clamp(
                Math.round(Math.max(window.innerHeight * config.speed, bounds.height * 0.18)),
                reducedMotion ? 12 : 24,
                reducedMotion ? 42 : 96
            );

            const fromVars = {};
            const toVars = {
                ease: 'none',
                overwrite: 'auto',
                scrollTrigger: {
                    trigger: getMotionTrigger(element),
                    start: 'top bottom',
                    end: 'bottom top',
                    scrub: reducedMotion ? 0.35 : true
                }
            };

            if (hasBackgroundImage(element)) {
                const offset = clamp(Math.round(distance * 0.65), 12, reducedMotion ? 24 : 42);
                fromVars.backgroundPosition = '50% calc(50% - ' + offset + 'px)';
                toVars.backgroundPosition = '50% calc(50% + ' + offset + 'px)';
            } else if (config.mode === 'x') {
                fromVars.x = -distance * 0.5;
                toVars.x = distance * 0.5;
            } else if (config.mode === 'rotate') {
                fromVars.rotate = -clamp(distance / 12, 1.5, reducedMotion ? 3 : 8);
                toVars.rotate = clamp(distance / 12, 1.5, reducedMotion ? 3 : 8);
            } else if (config.mode === 'scale') {
                fromVars.scale = 1;
                toVars.scale = 1 + clamp(config.speed * 0.24, 0.04, reducedMotion ? 0.07 : 0.14);
            } else {
                fromVars.y = -distance * 0.5;
                toVars.y = distance * 0.5;
            }

            gsap.fromTo(element, fromVars, toVars);
        });
    }

    function scheduleRefresh(delay) {
        window.clearTimeout(state.refreshTimer);
        state.refreshTimer = window.setTimeout(function() {
            init(false);
        }, typeof delay === 'number' ? delay : 180);
    }

    function startObserver() {
        if (state.observer || !document.body || typeof MutationObserver === 'undefined') return;

        state.observer = new MutationObserver(function(mutations) {
            for (let index = 0; index < mutations.length; index += 1) {
                if (mutations[index].addedNodes && mutations[index].addedNodes.length) {
                    scheduleRefresh(220);
                    break;
                }
            }
        });

        state.observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    function init(allowRetry) {
        if (!document.body) return;

        ensureStyles();

        if (!registerPlugins()) {
            if (allowRetry !== false) {
                scheduleRefresh(180);
            }
            return;
        }

        bindTitleAnimations(document);
        bindParallaxAnimations(document);
        startObserver();

        const ScrollTrigger = getScrollTrigger();
        if (ScrollTrigger) {
            ScrollTrigger.refresh();
        }
    }

    window.vmoGeneratedSiteEffects = {
        version: '1.0.0',
        init: function() {
            init(true);
        },
        refresh: function() {
            init(false);
        },
        scheduleRefresh: scheduleRefresh
    };

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

    window.addEventListener('load', function() {
        scheduleRefresh(80);
    });

    window.addEventListener('resize', function() {
        scheduleRefresh(180);
    });

    if (document.fonts && typeof document.fonts.ready === 'object' && typeof document.fonts.ready.then === 'function') {
        document.fonts.ready.then(function() {
            scheduleRefresh(60);
        }).catch(function() {});
    }
})();