// Version 5: Pure Gaussian Noise - Infinite organic motion without looping
const staggerVisualizerEl = document.querySelector('.stagger-visualizer');
const fragment = document.createDocumentFragment();
const grid = [12, 6];
const col = grid[0];
const row = grid[1];
const numberOfElements = col * row;

// Store element data for continuous noise
const elementData = [];

for (let i = 0; i < numberOfElements; i++) {
    let div = document.createElement('div');
    div.className = 'part';
    div.dataset.index = i;
    fragment.appendChild(div);
    
    // Each element gets unique noise parameters
    elementData.push({
        element: div,
        index: i,
        // Multiple frequency layers for natural-looking noise
        freq1X: anime.utils.random(0.25, 0.75),
        freq2X: anime.utils.random(0.1, 0.25),
        freq1Y: anime.utils.random(0.2, 0.6),
        freq2Y: anime.utils.random(0.05, 0.2),
        freq1Rot: anime.utils.random(0.1, 0.4),
        freq2Rot: anime.utils.random(0.025, 0.1),
        freqScale: anime.utils.random(0.15, 0.4),
        freqOpacity: anime.utils.random(0.05, 0.25),
        // Amplitudes
        ampX: anime.utils.random(4, 12),
        ampY: anime.utils.random(4, 12),
        ampRot: anime.utils.random(20, 45),
        ampScale: anime.utils.random(0.05, 0.15),
        // Phase offsets for variation
        phase1X: Math.random() * Math.PI * 2,
        phase2X: Math.random() * Math.PI * 2,
        phase1Y: Math.random() * Math.PI * 2,
        phase2Y: Math.random() * Math.PI * 2,
        phase1Rot: Math.random() * Math.PI * 2,
        phase2Rot: Math.random() * Math.PI * 2,
        phaseScale: Math.random() * Math.PI * 2,
        phaseOpacity: Math.random() * Math.PI * 2,
        // Random drift direction preference
        driftX: anime.utils.random(-0.5, 0.5),
        driftY: anime.utils.random(-0.5, 0.5),
    });
}

staggerVisualizerEl.appendChild(fragment);

// Continuous Gaussian noise animation using requestAnimationFrame
let animationStart = Date.now();
let lastFrameTime = animationStart;

const updateNoise = () => {
    const now = Date.now();
    const elapsed = (now - animationStart) / 1000; // Convert to seconds
    lastFrameTime = now;
    
    elementData.forEach((data) => {
        // Multi-layered sine waves create smooth Gaussian-like noise
        // Layer 1: Low frequency, high amplitude (main motion)
        const noiseX1 = Math.sin(elapsed * data.freq1X + data.phase1X) * data.ampX;
        const noiseY1 = Math.sin(elapsed * data.freq1Y + data.phase1Y) * data.ampY;
        const noiseRot1 = Math.sin(elapsed * data.freq1Rot + data.phase1Rot) * data.ampRot;
        
        // Layer 2: Higher frequency, lower amplitude (detail/jitter)
        const noiseX2 = Math.sin(elapsed * data.freq2X + data.phase2X) * data.ampX * 0.4;
        const noiseY2 = Math.sin(elapsed * data.freq2Y + data.phase2Y) * data.ampY * 0.3;
        const noiseRot2 = Math.sin(elapsed * data.freq2Rot + data.phase2Rot) * data.ampRot * 0.3;
        
        // Combine layers
        const totalX = noiseX1 + noiseX2 + (data.driftX * elapsed * 0.01);
        const totalY = noiseY1 + noiseY2 + (data.driftY * elapsed * 0.01);
        const totalRot = noiseRot1 + noiseRot2;
        
        // Scale breathing
        const scale = 1 + (Math.sin(elapsed * data.freqScale + data.phaseScale) * data.ampScale);
        
        // Opacity breathing - very subtle
        const opacity = 0.7 + Math.sin(elapsed * data.freqOpacity + data.phaseOpacity) * 0.25;
        
        // Apply transforms directly to style
        data.element.style.transform = `translateX(${totalX}px) translateY(${totalY}px) rotate(${totalRot}deg) scale(${Math.max(0.3, scale)})`;
        data.element.style.opacity = opacity;
    });
    
    requestAnimationFrame(updateNoise);
};

// Start the noise animation
updateNoise();
