/**
 * VMO Animated Overlays System
 * 
 * Provides interactive, animated overlay effects for websites:
 * - Clouds, smoke, particles, ripples, sparkles, fog, etc.
 * - Mouse/touch responsive displacement
 * - Parallax scrolling effects
 * - GPU-accelerated canvas rendering
 * 
 * @package VMO_AI_Builder
 * @since 1.0.0
 */

(function() {
    'use strict';
    
    /**
     * Main Overlay Manager Class
     */
    class VMOAnimatedOverlay {
        constructor(container, config = {}) {
            this.container = typeof container === 'string' 
                ? document.querySelector(container) 
                : container;
            
            if (!this.container) {
                console.error('VMO Overlay: Container not found');
                return;
            }
            
            // Default configuration
            this.config = Object.assign({
                type: 'particles',
                speed: 0.5,
                opacity: 0.7,
                interactive: true,
                parallax: true,
                mouseInfluence: 0.3,
                touchEnabled: true,
                layers: 2,
                density: 50,
                imageUrl: null,
                autoGenerate: true,
                loop: true,
                blendMode: 'normal',
                zIndex: 10
            }, config);
            
            // State
            this.canvas = null;
            this.ctx = null;
            this.particles = [];
            this.overlayImages = [];
            this.mouse = { x: 0, y: 0, active: false };
            this.scroll = { y: 0, velocity: 0 };
            this.animationId = null;
            this.isRunning = false;
            this.lastTime = 0;
            
            // Bind methods
            this.animate = this.animate.bind(this);
            this.handleMouseMove = this.handleMouseMove.bind(this);
            this.handleMouseLeave = this.handleMouseLeave.bind(this);
            this.handleTouchMove = this.handleTouchMove.bind(this);
            this.handleScroll = this.handleScroll.bind(this);
            this.handleResize = this.handleResize.bind(this);
            
            this.init();
        }
        
        /**
         * Initialize the overlay system
         */
        init() {
            // ✅ Mobile animation throttle: reduce density and disable heavy effects on small screens
            const isMobile = window.innerWidth < 768;
            const isTablet = window.innerWidth >= 768 && window.innerWidth < 1024;
            const prefersReducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

            if (prefersReducedMotion) {
                // User prefers reduced motion — skip overlay entirely
                console.log('[VMO Overlay] Skipping: prefers-reduced-motion');
                return;
            }

            if (isMobile) {
                // On mobile: halve density, reduce layers, disable interactivity for performance
                this.config.density = Math.max(5, Math.floor(this.config.density * 0.4));
                this.config.layers = Math.min(this.config.layers, 1);
                this.config.interactive = false;
                this.config.parallax = false;
                this.config.speed = this.config.speed * 0.6;
                console.log('[VMO Overlay] Mobile throttle: density=' + this.config.density + ', layers=1, interactive=off');
            } else if (isTablet) {
                // On tablet: slight reduction
                this.config.density = Math.max(10, Math.floor(this.config.density * 0.7));
                this.config.layers = Math.min(this.config.layers, 2);
            }

            this.createCanvas();
            this.setupStyles();
            this.bindEvents();
            
            if (this.config.imageUrl) {
                this.loadOverlayImage(this.config.imageUrl);
            } else if (this.config.autoGenerate) {
                this.generateParticles();
            }
            
            this.start();
        }
        
        /**
         * Create the canvas element
         */
        createCanvas() {
            this.canvas = document.createElement('canvas');
            this.canvas.className = 'vmo-overlay-canvas';
            this.ctx = this.canvas.getContext('2d');
            
            // Set size
            this.resize();
            
            // Add to container
            this.container.appendChild(this.canvas);
        }
        
        /**
         * Setup canvas styles
         */
        setupStyles() {
            const styles = {
                position: 'absolute',
                top: '0',
                left: '0',
                width: '100%',
                height: '100%',
                pointerEvents: this.config.interactive ? 'auto' : 'none',
                zIndex: this.config.zIndex.toString(),
                opacity: this.config.opacity.toString(),
                mixBlendMode: this.config.blendMode
            };
            
            Object.assign(this.canvas.style, styles);
            
            // Ensure container has position
            const containerStyle = window.getComputedStyle(this.container);
            if (containerStyle.position === 'static') {
                this.container.style.position = 'relative';
            }
            this.container.style.overflow = 'hidden';
        }
        
        /**
         * Bind event listeners
         */
        bindEvents() {
            if (this.config.interactive) {
                this.container.addEventListener('mousemove', this.handleMouseMove, { passive: true });
                this.container.addEventListener('mouseleave', this.handleMouseLeave);
                
                if (this.config.touchEnabled) {
                    this.container.addEventListener('touchmove', this.handleTouchMove, { passive: true });
                    this.container.addEventListener('touchend', this.handleMouseLeave);
                }
            }
            
            if (this.config.parallax) {
                window.addEventListener('scroll', this.handleScroll, { passive: true });
            }
            
            window.addEventListener('resize', this.handleResize);
        }
        
        /**
         * Handle mouse movement
         */
        handleMouseMove(e) {
            const rect = this.container.getBoundingClientRect();
            this.mouse.x = e.clientX - rect.left;
            this.mouse.y = e.clientY - rect.top;
            this.mouse.active = true;
        }
        
        /**
         * Handle mouse leave
         */
        handleMouseLeave() {
            this.mouse.active = false;
        }
        
        /**
         * Handle touch movement
         */
        handleTouchMove(e) {
            if (e.touches.length > 0) {
                const rect = this.container.getBoundingClientRect();
                this.mouse.x = e.touches[0].clientX - rect.left;
                this.mouse.y = e.touches[0].clientY - rect.top;
                this.mouse.active = true;
            }
        }
        
        /**
         * Handle scroll for parallax
         */
        handleScroll() {
            const newScroll = window.pageYOffset;
            this.scroll.velocity = newScroll - this.scroll.y;
            this.scroll.y = newScroll;
        }
        
        /**
         * Handle resize
         */
        handleResize() {
            this.resize();
        }
        
        /**
         * Resize canvas
         */
        resize() {
            const rect = this.container.getBoundingClientRect();
            this.canvas.width = rect.width;
            this.canvas.height = rect.height;
        }
        
        /**
         * Load overlay image
         */
        loadOverlayImage(url) {
            const img = new Image();
            img.crossOrigin = 'anonymous';
            img.onload = () => {
                this.createImageParticles(img);
            };
            img.src = url;
        }
        
        /**
         * Create particles from loaded image
         */
        createImageParticles(img) {
            const layers = this.config.layers;
            
            for (let layer = 0; layer < layers; layer++) {
                const scale = 0.5 + (layer / layers) * 0.8;
                const speedMultiplier = 0.5 + (layer / layers) * 0.5;
                
                this.overlayImages.push({
                    image: img,
                    x: Math.random() * this.canvas.width,
                    y: Math.random() * this.canvas.height,
                    baseX: 0,
                    baseY: 0,
                    scale: scale,
                    speedX: (Math.random() - 0.5) * this.config.speed * speedMultiplier,
                    speedY: (Math.random() - 0.5) * this.config.speed * 0.3 * speedMultiplier,
                    opacity: 0.3 + (layer / layers) * 0.5,
                    layer: layer,
                    rotation: 0,
                    rotationSpeed: (Math.random() - 0.5) * 0.01
                });
            }
        }
        
        /**
         * Generate procedural particles based on type
         */
        generateParticles() {
            this.particles = [];
            
            const generators = {
                clouds: () => this.generateCloudParticles(),
                smoke: () => this.generateSmokeParticles(),
                particles: () => this.generateLightParticles(),
                sparkles: () => this.generateSparkleParticles(),
                fog: () => this.generateFogParticles(),
                ripples: () => this.generateRippleParticles(),
                bubbles: () => this.generateBubbleParticles(),
                snow: () => this.generateSnowParticles(),
                rain: () => this.generateRainParticles(),
                leaves: () => this.generateLeafParticles(),
                dust: () => this.generateDustParticles(),
                fireflies: () => this.generateFireflyParticles(),
                embers: () => this.generateEmberParticles(),
                petals: () => this.generatePetalParticles()
            };
            
            const generator = generators[this.config.type] || generators.particles;
            generator();
        }
        
        /**
         * Cloud particle generator
         */
        generateCloudParticles() {
            const count = Math.floor(this.config.density / 5);
            
            for (let i = 0; i < count; i++) {
                const layer = Math.floor(Math.random() * this.config.layers);
                const size = 100 + Math.random() * 200;
                
                this.particles.push({
                    type: 'cloud',
                    x: Math.random() * (this.canvas.width + size * 2) - size,
                    y: Math.random() * this.canvas.height * 0.6,
                    baseY: 0,
                    size: size,
                    speedX: (0.2 + Math.random() * 0.3) * this.config.speed,
                    speedY: 0,
                    opacity: 0.3 + (layer / this.config.layers) * 0.4,
                    layer: layer,
                    segments: this.generateCloudShape(),
                    wobble: Math.random() * Math.PI * 2,
                    wobbleSpeed: 0.001 + Math.random() * 0.002
                });
            }
        }
        
        /**
         * Generate cloud shape segments
         */
        generateCloudShape() {
            const segments = [];
            const count = 4 + Math.floor(Math.random() * 4);
            
            for (let i = 0; i < count; i++) {
                segments.push({
                    offsetX: (Math.random() - 0.5) * 0.8,
                    offsetY: (Math.random() - 0.5) * 0.4,
                    scale: 0.3 + Math.random() * 0.7
                });
            }
            
            return segments;
        }
        
        /**
         * Smoke particle generator
         */
        generateSmokeParticles() {
            const count = this.config.density;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'smoke',
                    x: Math.random() * this.canvas.width,
                    y: this.canvas.height + Math.random() * 100,
                    size: 20 + Math.random() * 60,
                    speedX: (Math.random() - 0.5) * this.config.speed * 0.5,
                    speedY: -(0.3 + Math.random() * 0.5) * this.config.speed,
                    opacity: 0.1 + Math.random() * 0.3,
                    rotation: Math.random() * Math.PI * 2,
                    rotationSpeed: (Math.random() - 0.5) * 0.02,
                    life: 1,
                    decay: 0.001 + Math.random() * 0.002,
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Light particle generator
         */
        generateLightParticles() {
            const count = this.config.density;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'light',
                    x: Math.random() * this.canvas.width,
                    y: Math.random() * this.canvas.height,
                    size: 2 + Math.random() * 6,
                    speedX: (Math.random() - 0.5) * this.config.speed,
                    speedY: (Math.random() - 0.5) * this.config.speed,
                    opacity: 0.3 + Math.random() * 0.7,
                    pulse: Math.random() * Math.PI * 2,
                    pulseSpeed: 0.02 + Math.random() * 0.04,
                    layer: Math.floor(Math.random() * this.config.layers),
                    color: this.getRandomParticleColor()
                });
            }
        }
        
        /**
         * Sparkle particle generator
         */
        generateSparkleParticles() {
            const count = this.config.density;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'sparkle',
                    x: Math.random() * this.canvas.width,
                    y: Math.random() * this.canvas.height,
                    size: 3 + Math.random() * 8,
                    rotation: Math.random() * Math.PI,
                    rotationSpeed: 0.05 + Math.random() * 0.1,
                    opacity: 0,
                    targetOpacity: 0.5 + Math.random() * 0.5,
                    phase: Math.random() * Math.PI * 2,
                    phaseSpeed: 0.05 + Math.random() * 0.1,
                    layer: Math.floor(Math.random() * this.config.layers),
                    color: `hsl(${40 + Math.random() * 30}, 100%, ${70 + Math.random() * 30}%)`
                });
            }
        }
        
        /**
         * Fog particle generator
         */
        generateFogParticles() {
            const count = Math.floor(this.config.density / 3);
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'fog',
                    x: Math.random() * this.canvas.width * 2 - this.canvas.width * 0.5,
                    y: this.canvas.height * 0.5 + Math.random() * this.canvas.height * 0.5,
                    size: 200 + Math.random() * 300,
                    speedX: (0.1 + Math.random() * 0.2) * this.config.speed,
                    speedY: (Math.random() - 0.5) * 0.05 * this.config.speed,
                    opacity: 0.1 + Math.random() * 0.2,
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Ripple particle generator (interactive)
         */
        generateRippleParticles() {
            this.ripples = [];
            // Ripples are generated on mouse/touch interaction
        }
        
        /**
         * Add a ripple at position
         */
        addRipple(x, y) {
            if (!this.ripples) this.ripples = [];
            
            this.ripples.push({
                x: x,
                y: y,
                radius: 0,
                maxRadius: 100 + Math.random() * 100,
                speed: 2 + Math.random() * 2,
                opacity: 0.5,
                lineWidth: 2
            });
        }
        
        /**
         * Bubble particle generator
         */
        generateBubbleParticles() {
            const count = this.config.density;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'bubble',
                    x: Math.random() * this.canvas.width,
                    y: this.canvas.height + Math.random() * 100,
                    size: 5 + Math.random() * 25,
                    speedX: (Math.random() - 0.5) * this.config.speed * 0.3,
                    speedY: -(0.5 + Math.random() * 1) * this.config.speed,
                    opacity: 0.2 + Math.random() * 0.4,
                    wobble: Math.random() * Math.PI * 2,
                    wobbleSpeed: 0.02 + Math.random() * 0.03,
                    wobbleAmount: 1 + Math.random() * 2,
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Snow particle generator
         */
        generateSnowParticles() {
            const count = this.config.density * 2;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'snow',
                    x: Math.random() * this.canvas.width,
                    y: Math.random() * this.canvas.height,
                    size: 2 + Math.random() * 6,
                    speedX: (Math.random() - 0.5) * this.config.speed * 0.5,
                    speedY: (0.5 + Math.random() * 1) * this.config.speed,
                    opacity: 0.5 + Math.random() * 0.5,
                    wobble: Math.random() * Math.PI * 2,
                    wobbleSpeed: 0.02 + Math.random() * 0.03,
                    wobbleAmount: 0.5 + Math.random() * 1,
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Rain particle generator
         */
        generateRainParticles() {
            const count = this.config.density * 3;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'rain',
                    x: Math.random() * this.canvas.width * 1.5,
                    y: -Math.random() * 100,
                    length: 10 + Math.random() * 20,
                    speedX: -2 * this.config.speed,
                    speedY: (10 + Math.random() * 10) * this.config.speed,
                    opacity: 0.2 + Math.random() * 0.4,
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Leaf particle generator
         */
        generateLeafParticles() {
            const count = Math.floor(this.config.density / 2);
            const colors = ['#c0392b', '#e74c3c', '#d35400', '#e67e22', '#f39c12', '#8B4513'];
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'leaf',
                    x: Math.random() * this.canvas.width,
                    y: -Math.random() * 100,
                    size: 8 + Math.random() * 15,
                    speedX: (Math.random() - 0.3) * this.config.speed,
                    speedY: (0.5 + Math.random() * 1) * this.config.speed,
                    rotation: Math.random() * Math.PI * 2,
                    rotationSpeed: (Math.random() - 0.5) * 0.05,
                    wobble: Math.random() * Math.PI * 2,
                    wobbleSpeed: 0.02 + Math.random() * 0.02,
                    wobbleAmount: 2 + Math.random() * 3,
                    opacity: 0.7 + Math.random() * 0.3,
                    color: colors[Math.floor(Math.random() * colors.length)],
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Dust particle generator
         */
        generateDustParticles() {
            const count = this.config.density;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'dust',
                    x: Math.random() * this.canvas.width,
                    y: Math.random() * this.canvas.height,
                    size: 1 + Math.random() * 3,
                    speedX: (Math.random() - 0.5) * this.config.speed * 0.2,
                    speedY: (Math.random() - 0.5) * this.config.speed * 0.2,
                    opacity: 0.2 + Math.random() * 0.4,
                    pulse: Math.random() * Math.PI * 2,
                    pulseSpeed: 0.01 + Math.random() * 0.02,
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Firefly particle generator
         */
        generateFireflyParticles() {
            const count = Math.floor(this.config.density / 2);
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'firefly',
                    x: Math.random() * this.canvas.width,
                    y: Math.random() * this.canvas.height,
                    size: 3 + Math.random() * 4,
                    targetX: Math.random() * this.canvas.width,
                    targetY: Math.random() * this.canvas.height,
                    speed: 0.5 + Math.random() * 1,
                    opacity: 0,
                    maxOpacity: 0.6 + Math.random() * 0.4,
                    phase: Math.random() * Math.PI * 2,
                    phaseSpeed: 0.02 + Math.random() * 0.03,
                    glowSize: 10 + Math.random() * 15,
                    layer: Math.floor(Math.random() * this.config.layers),
                    color: `hsl(${50 + Math.random() * 30}, 100%, 70%)`
                });
            }
        }
        
        /**
         * Ember particle generator
         */
        generateEmberParticles() {
            const count = this.config.density;
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'ember',
                    x: this.canvas.width * 0.3 + Math.random() * this.canvas.width * 0.4,
                    y: this.canvas.height + Math.random() * 50,
                    size: 2 + Math.random() * 4,
                    speedX: (Math.random() - 0.5) * this.config.speed,
                    speedY: -(1 + Math.random() * 2) * this.config.speed,
                    opacity: 0.7 + Math.random() * 0.3,
                    life: 1,
                    decay: 0.002 + Math.random() * 0.003,
                    wobble: Math.random() * Math.PI * 2,
                    wobbleSpeed: 0.05 + Math.random() * 0.05,
                    layer: Math.floor(Math.random() * this.config.layers),
                    color: `hsl(${20 + Math.random() * 30}, 100%, ${50 + Math.random() * 20}%)`
                });
            }
        }
        
        /**
         * Petal particle generator
         */
        generatePetalParticles() {
            const count = Math.floor(this.config.density / 2);
            const colors = ['#ffb6c1', '#ffc0cb', '#ff69b4', '#fff0f5', '#ffe4e1'];
            
            for (let i = 0; i < count; i++) {
                this.particles.push({
                    type: 'petal',
                    x: Math.random() * this.canvas.width,
                    y: -Math.random() * 100,
                    size: 6 + Math.random() * 12,
                    speedX: (Math.random() - 0.3) * this.config.speed * 0.5,
                    speedY: (0.3 + Math.random() * 0.7) * this.config.speed,
                    rotation: Math.random() * Math.PI * 2,
                    rotationSpeed: (Math.random() - 0.5) * 0.03,
                    wobble: Math.random() * Math.PI * 2,
                    wobbleSpeed: 0.015 + Math.random() * 0.015,
                    wobbleAmount: 1.5 + Math.random() * 2,
                    opacity: 0.6 + Math.random() * 0.4,
                    color: colors[Math.floor(Math.random() * colors.length)],
                    layer: Math.floor(Math.random() * this.config.layers)
                });
            }
        }
        
        /**
         * Get random particle color
         */
        getRandomParticleColor() {
            const colors = [
                'rgba(255, 255, 255, 1)',
                'rgba(200, 220, 255, 1)',
                'rgba(255, 240, 200, 1)',
                'rgba(220, 200, 255, 1)'
            ];
            return colors[Math.floor(Math.random() * colors.length)];
        }
        
        /**
         * Start animation
         */
        start() {
            if (this.isRunning) return;
            this.isRunning = true;
            this.lastTime = performance.now();
            this.animate();
        }
        
        /**
         * Stop animation
         */
        stop() {
            this.isRunning = false;
            if (this.animationId) {
                cancelAnimationFrame(this.animationId);
                this.animationId = null;
            }
        }
        
        /**
         * Main animation loop
         */
        animate(currentTime = 0) {
            if (!this.isRunning) return;
            
            const deltaTime = (currentTime - this.lastTime) / 16.67; // Normalize to 60fps
            this.lastTime = currentTime;
            
            // Clear canvas
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
            
            // Update and draw overlay images
            this.updateOverlayImages(deltaTime);
            
            // Update and draw particles
            this.updateParticles(deltaTime);
            
            // Update and draw ripples
            this.updateRipples(deltaTime);
            
            // Request next frame
            this.animationId = requestAnimationFrame(this.animate);
        }
        
        /**
         * Update overlay images
         */
        updateOverlayImages(deltaTime) {
            for (const overlay of this.overlayImages) {
                // Apply mouse influence
                if (this.mouse.active && this.config.interactive) {
                    const dx = this.mouse.x - overlay.x;
                    const dy = this.mouse.y - overlay.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const influence = Math.max(0, 1 - distance / 300) * this.config.mouseInfluence;
                    
                    overlay.x -= dx * influence * 0.02 * deltaTime;
                    overlay.y -= dy * influence * 0.02 * deltaTime;
                }
                
                // Apply parallax
                if (this.config.parallax) {
                    const parallaxFactor = 0.1 * (overlay.layer + 1);
                    overlay.y += this.scroll.velocity * parallaxFactor * 0.1;
                }
                
                // Apply base movement
                overlay.x += overlay.speedX * deltaTime;
                overlay.y += overlay.speedY * deltaTime;
                overlay.rotation += overlay.rotationSpeed * deltaTime;
                
                // Wrap around
                const w = overlay.image.width * overlay.scale;
                const h = overlay.image.height * overlay.scale;
                
                if (overlay.x > this.canvas.width + w) overlay.x = -w;
                if (overlay.x < -w) overlay.x = this.canvas.width + w;
                if (overlay.y > this.canvas.height + h) overlay.y = -h;
                if (overlay.y < -h) overlay.y = this.canvas.height + h;
                
                // Draw
                this.ctx.save();
                this.ctx.globalAlpha = overlay.opacity;
                this.ctx.translate(overlay.x, overlay.y);
                this.ctx.rotate(overlay.rotation);
                this.ctx.drawImage(
                    overlay.image,
                    -w / 2,
                    -h / 2,
                    w,
                    h
                );
                this.ctx.restore();
            }
        }
        
        /**
         * Update particles
         */
        updateParticles(deltaTime) {
            for (let i = this.particles.length - 1; i >= 0; i--) {
                const p = this.particles[i];
                
                // Apply mouse influence
                if (this.mouse.active && this.config.interactive) {
                    this.applyMouseInfluence(p, deltaTime);
                }
                
                // Apply parallax
                if (this.config.parallax) {
                    const parallaxFactor = 0.05 * (p.layer + 1);
                    p.y += this.scroll.velocity * parallaxFactor * 0.1;
                }
                
                // Update based on type
                const updaters = {
                    cloud: () => this.updateCloud(p, deltaTime),
                    smoke: () => this.updateSmoke(p, deltaTime, i),
                    light: () => this.updateLight(p, deltaTime),
                    sparkle: () => this.updateSparkle(p, deltaTime),
                    fog: () => this.updateFog(p, deltaTime),
                    bubble: () => this.updateBubble(p, deltaTime),
                    snow: () => this.updateSnow(p, deltaTime),
                    rain: () => this.updateRain(p, deltaTime),
                    leaf: () => this.updateLeaf(p, deltaTime),
                    dust: () => this.updateDust(p, deltaTime),
                    firefly: () => this.updateFirefly(p, deltaTime),
                    ember: () => this.updateEmber(p, deltaTime, i),
                    petal: () => this.updatePetal(p, deltaTime)
                };
                
                if (updaters[p.type]) {
                    updaters[p.type]();
                }
            }
            
            // Add ripples on mouse movement for ripple type
            if (this.config.type === 'ripples' && this.mouse.active) {
                if (Math.random() < 0.1) {
                    this.addRipple(this.mouse.x, this.mouse.y);
                }
            }
        }
        
        /**
         * Apply mouse influence to particle
         */
        applyMouseInfluence(p, deltaTime) {
            const dx = this.mouse.x - p.x;
            const dy = this.mouse.y - p.y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            const maxDistance = 150;
            
            if (distance < maxDistance) {
                const influence = (1 - distance / maxDistance) * this.config.mouseInfluence;
                p.x -= dx * influence * 0.05 * deltaTime;
                p.y -= dy * influence * 0.05 * deltaTime;
            }
        }
        
        /**
         * Update cloud particle
         */
        updateCloud(p, deltaTime) {
            p.x += p.speedX * deltaTime;
            p.wobble += p.wobbleSpeed * deltaTime;
            p.y += Math.sin(p.wobble) * 0.1;
            
            // Wrap around
            if (p.x > this.canvas.width + p.size) {
                p.x = -p.size;
            }
            
            // Draw cloud
            this.drawCloud(p);
        }
        
        /**
         * Draw cloud
         */
        drawCloud(p) {
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            this.ctx.fillStyle = 'white';
            
            for (const segment of p.segments) {
                const x = p.x + segment.offsetX * p.size;
                const y = p.y + segment.offsetY * p.size;
                const radius = p.size * 0.3 * segment.scale;
                
                this.ctx.beginPath();
                this.ctx.arc(x, y, radius, 0, Math.PI * 2);
                this.ctx.fill();
            }
            
            this.ctx.restore();
        }
        
        /**
         * Update smoke particle
         */
        updateSmoke(p, deltaTime, index) {
            p.x += p.speedX * deltaTime;
            p.y += p.speedY * deltaTime;
            p.rotation += p.rotationSpeed * deltaTime;
            p.life -= p.decay * deltaTime;
            p.size += 0.5 * deltaTime;
            
            if (p.life <= 0) {
                // Reset particle
                p.x = Math.random() * this.canvas.width;
                p.y = this.canvas.height + Math.random() * 50;
                p.size = 20 + Math.random() * 60;
                p.life = 1;
                p.opacity = 0.1 + Math.random() * 0.3;
            }
            
            // Draw smoke
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity * p.life;
            this.ctx.translate(p.x, p.y);
            this.ctx.rotate(p.rotation);
            
            const gradient = this.ctx.createRadialGradient(0, 0, 0, 0, 0, p.size);
            gradient.addColorStop(0, 'rgba(128, 128, 128, 0.3)');
            gradient.addColorStop(1, 'rgba(128, 128, 128, 0)');
            
            this.ctx.fillStyle = gradient;
            this.ctx.beginPath();
            this.ctx.arc(0, 0, p.size, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update light particle
         */
        updateLight(p, deltaTime) {
            p.x += p.speedX * deltaTime;
            p.y += p.speedY * deltaTime;
            p.pulse += p.pulseSpeed * deltaTime;
            
            // Wrap around
            if (p.x > this.canvas.width) p.x = 0;
            if (p.x < 0) p.x = this.canvas.width;
            if (p.y > this.canvas.height) p.y = 0;
            if (p.y < 0) p.y = this.canvas.height;
            
            // Draw
            const pulseOpacity = p.opacity * (0.5 + Math.sin(p.pulse) * 0.5);
            this.ctx.save();
            this.ctx.globalAlpha = pulseOpacity;
            
            const gradient = this.ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 2);
            gradient.addColorStop(0, p.color);
            gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
            
            this.ctx.fillStyle = gradient;
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size * 2, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update sparkle particle
         */
        updateSparkle(p, deltaTime) {
            p.rotation += p.rotationSpeed * deltaTime;
            p.phase += p.phaseSpeed * deltaTime;
            p.opacity = p.targetOpacity * Math.abs(Math.sin(p.phase));
            
            // Draw sparkle
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            this.ctx.translate(p.x, p.y);
            this.ctx.rotate(p.rotation);
            
            // Draw 4-pointed star
            this.ctx.fillStyle = p.color;
            this.ctx.beginPath();
            for (let i = 0; i < 4; i++) {
                const angle = (i / 4) * Math.PI * 2;
                const x1 = Math.cos(angle) * p.size;
                const y1 = Math.sin(angle) * p.size;
                const x2 = Math.cos(angle + Math.PI / 4) * p.size * 0.3;
                const y2 = Math.sin(angle + Math.PI / 4) * p.size * 0.3;
                
                if (i === 0) {
                    this.ctx.moveTo(x1, y1);
                } else {
                    this.ctx.lineTo(x1, y1);
                }
                this.ctx.lineTo(x2, y2);
            }
            this.ctx.closePath();
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update fog particle
         */
        updateFog(p, deltaTime) {
            p.x += p.speedX * deltaTime;
            p.y += p.speedY * deltaTime;
            
            // Wrap around
            if (p.x > this.canvas.width + p.size) {
                p.x = -p.size;
            }
            
            // Draw fog
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            
            const gradient = this.ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size);
            gradient.addColorStop(0, 'rgba(255, 255, 255, 0.3)');
            gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
            
            this.ctx.fillStyle = gradient;
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update bubble particle
         */
        updateBubble(p, deltaTime) {
            p.wobble += p.wobbleSpeed * deltaTime;
            p.x += p.speedX * deltaTime + Math.sin(p.wobble) * p.wobbleAmount;
            p.y += p.speedY * deltaTime;
            
            // Reset at top
            if (p.y < -p.size) {
                p.y = this.canvas.height + p.size;
                p.x = Math.random() * this.canvas.width;
            }
            
            // Draw bubble
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            this.ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
            this.ctx.lineWidth = 1;
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
            this.ctx.stroke();
            
            // Highlight
            this.ctx.beginPath();
            this.ctx.arc(p.x - p.size * 0.3, p.y - p.size * 0.3, p.size * 0.2, 0, Math.PI * 2);
            this.ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update snow particle
         */
        updateSnow(p, deltaTime) {
            p.wobble += p.wobbleSpeed * deltaTime;
            p.x += p.speedX * deltaTime + Math.sin(p.wobble) * p.wobbleAmount;
            p.y += p.speedY * deltaTime;
            
            // Reset at bottom
            if (p.y > this.canvas.height + p.size) {
                p.y = -p.size;
                p.x = Math.random() * this.canvas.width;
            }
            
            // Draw snowflake
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            this.ctx.fillStyle = 'white';
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update rain particle
         */
        updateRain(p, deltaTime) {
            p.x += p.speedX * deltaTime;
            p.y += p.speedY * deltaTime;
            
            // Reset at bottom
            if (p.y > this.canvas.height) {
                p.y = -p.length;
                p.x = Math.random() * this.canvas.width * 1.5;
            }
            
            // Draw rain drop
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            this.ctx.strokeStyle = 'rgba(174, 194, 224, 0.8)';
            this.ctx.lineWidth = 1;
            this.ctx.beginPath();
            this.ctx.moveTo(p.x, p.y);
            this.ctx.lineTo(p.x + p.speedX * 0.1, p.y + p.length);
            this.ctx.stroke();
            this.ctx.restore();
        }
        
        /**
         * Update leaf particle
         */
        updateLeaf(p, deltaTime) {
            p.wobble += p.wobbleSpeed * deltaTime;
            p.rotation += p.rotationSpeed * deltaTime;
            p.x += p.speedX * deltaTime + Math.sin(p.wobble) * p.wobbleAmount;
            p.y += p.speedY * deltaTime;
            
            // Reset at bottom
            if (p.y > this.canvas.height + p.size) {
                p.y = -p.size;
                p.x = Math.random() * this.canvas.width;
            }
            
            // Draw leaf
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            this.ctx.translate(p.x, p.y);
            this.ctx.rotate(p.rotation);
            this.ctx.fillStyle = p.color;
            
            // Simple leaf shape
            this.ctx.beginPath();
            this.ctx.ellipse(0, 0, p.size * 0.4, p.size, 0, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update dust particle
         */
        updateDust(p, deltaTime) {
            p.x += p.speedX * deltaTime;
            p.y += p.speedY * deltaTime;
            p.pulse += p.pulseSpeed * deltaTime;
            
            // Wrap around
            if (p.x > this.canvas.width) p.x = 0;
            if (p.x < 0) p.x = this.canvas.width;
            if (p.y > this.canvas.height) p.y = 0;
            if (p.y < 0) p.y = this.canvas.height;
            
            // Draw
            const pulseOpacity = p.opacity * (0.5 + Math.sin(p.pulse) * 0.5);
            this.ctx.save();
            this.ctx.globalAlpha = pulseOpacity;
            this.ctx.fillStyle = 'rgba(255, 248, 220, 0.8)';
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update firefly particle
         */
        updateFirefly(p, deltaTime) {
            // Move towards target
            const dx = p.targetX - p.x;
            const dy = p.targetY - p.y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            
            if (distance < 10) {
                // Pick new target
                p.targetX = Math.random() * this.canvas.width;
                p.targetY = Math.random() * this.canvas.height;
            } else {
                p.x += (dx / distance) * p.speed * deltaTime;
                p.y += (dy / distance) * p.speed * deltaTime;
            }
            
            // Pulsing glow
            p.phase += p.phaseSpeed * deltaTime;
            p.opacity = p.maxOpacity * Math.max(0, Math.sin(p.phase));
            
            // Draw firefly
            if (p.opacity > 0.1) {
                this.ctx.save();
                
                // Glow
                const gradient = this.ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.glowSize);
                gradient.addColorStop(0, p.color);
                gradient.addColorStop(1, 'rgba(255, 255, 0, 0)');
                
                this.ctx.globalAlpha = p.opacity * 0.5;
                this.ctx.fillStyle = gradient;
                this.ctx.beginPath();
                this.ctx.arc(p.x, p.y, p.glowSize, 0, Math.PI * 2);
                this.ctx.fill();
                
                // Core
                this.ctx.globalAlpha = p.opacity;
                this.ctx.fillStyle = p.color;
                this.ctx.beginPath();
                this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
                this.ctx.fill();
                
                this.ctx.restore();
            }
        }
        
        /**
         * Update ember particle
         */
        updateEmber(p, deltaTime, index) {
            p.wobble += p.wobbleSpeed * deltaTime;
            p.x += p.speedX * deltaTime + Math.sin(p.wobble) * 0.5;
            p.y += p.speedY * deltaTime;
            p.life -= p.decay * deltaTime;
            
            if (p.life <= 0) {
                // Reset
                p.x = this.canvas.width * 0.3 + Math.random() * this.canvas.width * 0.4;
                p.y = this.canvas.height + Math.random() * 50;
                p.life = 1;
            }
            
            // Draw ember
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity * p.life;
            
            // Glow
            const gradient = this.ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 3);
            gradient.addColorStop(0, p.color);
            gradient.addColorStop(1, 'rgba(255, 100, 0, 0)');
            
            this.ctx.fillStyle = gradient;
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size * 3, 0, Math.PI * 2);
            this.ctx.fill();
            
            // Core
            this.ctx.fillStyle = p.color;
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update petal particle
         */
        updatePetal(p, deltaTime) {
            p.wobble += p.wobbleSpeed * deltaTime;
            p.rotation += p.rotationSpeed * deltaTime;
            p.x += p.speedX * deltaTime + Math.sin(p.wobble) * p.wobbleAmount;
            p.y += p.speedY * deltaTime;
            
            // Reset at bottom
            if (p.y > this.canvas.height + p.size) {
                p.y = -p.size;
                p.x = Math.random() * this.canvas.width;
            }
            
            // Draw petal
            this.ctx.save();
            this.ctx.globalAlpha = p.opacity;
            this.ctx.translate(p.x, p.y);
            this.ctx.rotate(p.rotation);
            this.ctx.fillStyle = p.color;
            
            // Petal shape
            this.ctx.beginPath();
            this.ctx.ellipse(0, 0, p.size * 0.5, p.size, 0, 0, Math.PI * 2);
            this.ctx.fill();
            this.ctx.restore();
        }
        
        /**
         * Update ripples
         */
        updateRipples(deltaTime) {
            if (!this.ripples) return;
            
            for (let i = this.ripples.length - 1; i >= 0; i--) {
                const ripple = this.ripples[i];
                
                ripple.radius += ripple.speed * deltaTime;
                ripple.opacity = 1 - (ripple.radius / ripple.maxRadius);
                
                if (ripple.radius >= ripple.maxRadius) {
                    this.ripples.splice(i, 1);
                    continue;
                }
                
                // Draw ripple
                this.ctx.save();
                this.ctx.globalAlpha = ripple.opacity * 0.5;
                this.ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
                this.ctx.lineWidth = ripple.lineWidth;
                this.ctx.beginPath();
                this.ctx.arc(ripple.x, ripple.y, ripple.radius, 0, Math.PI * 2);
                this.ctx.stroke();
                this.ctx.restore();
            }
        }
        
        /**
         * Destroy the overlay
         */
        destroy() {
            this.stop();
            
            // Remove event listeners
            this.container.removeEventListener('mousemove', this.handleMouseMove);
            this.container.removeEventListener('mouseleave', this.handleMouseLeave);
            this.container.removeEventListener('touchmove', this.handleTouchMove);
            this.container.removeEventListener('touchend', this.handleMouseLeave);
            window.removeEventListener('scroll', this.handleScroll);
            window.removeEventListener('resize', this.handleResize);
            
            // Remove canvas
            if (this.canvas && this.canvas.parentNode) {
                this.canvas.parentNode.removeChild(this.canvas);
            }
            
            this.particles = [];
            this.overlayImages = [];
            this.ripples = [];
        }
    }
    
    /**
     * Auto-initialize overlays with data attributes
     */
    function initOverlays() {
        const overlayElements = document.querySelectorAll('[data-vmo-overlay]');
        
        overlayElements.forEach(element => {
            try {
                const configStr = element.getAttribute('data-vmo-overlay');
                const config = configStr ? JSON.parse(configStr) : {};
                const imageUrl = element.getAttribute('data-overlay-image');
                
                if (imageUrl) {
                    config.imageUrl = imageUrl;
                }
                
                new VMOAnimatedOverlay(element.parentElement || element, config);
            } catch (e) {
                console.error('VMO Overlay init error:', e);
            }
        });
    }
    
    // Initialize on DOM ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initOverlays);
    } else {
        initOverlays();
    }
    
    // Export to global scope
    window.VMOAnimatedOverlay = VMOAnimatedOverlay;
    
    /**
     * Helper function to add overlay to any element
     */
    window.vmoAddOverlay = function(selector, type, options = {}) {
        const element = typeof selector === 'string' 
            ? document.querySelector(selector) 
            : selector;
        
        if (!element) {
            console.error('VMO Overlay: Element not found');
            return null;
        }
        
        return new VMOAnimatedOverlay(element, Object.assign({ type }, options));
    };
    
    /**
     * Create overlay from preset
     */
    window.vmoOverlayPresets = {
        heroSky: { type: 'clouds', speed: 0.2, opacity: 0.6, layers: 3 },
        heroNight: { type: 'fireflies', speed: 0.8, opacity: 0.9, density: 30 },
        heroWinter: { type: 'snow', speed: 0.5, opacity: 0.8, density: 80 },
        heroRain: { type: 'rain', speed: 1.2, opacity: 0.6, density: 100 },
        luxurySparkle: { type: 'sparkles', speed: 1, opacity: 0.8, density: 40 },
        romantic: { type: 'petals', speed: 0.4, opacity: 0.7, density: 25 },
        atmospheric: { type: 'fog', speed: 0.15, opacity: 0.4, density: 15 },
        dramatic: { type: 'smoke', speed: 0.4, opacity: 0.5, density: 30 },
        magical: { type: 'particles', speed: 0.6, opacity: 0.7, density: 50 },
        autumn: { type: 'leaves', speed: 0.4, opacity: 0.85, density: 20 },
        campfire: { type: 'embers', speed: 0.7, opacity: 0.8, density: 40 },
        underwater: { type: 'bubbles', speed: 0.5, opacity: 0.5, density: 30 },
        interactive: { type: 'ripples', interactive: true, mouseInfluence: 0.5 }
    };
    
})();
