<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Reverse Big Bang Simulation - 2025</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.128/examples/js/controls/OrbitControls.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js"></script>
    <style>
        body {
            margin: 0;
            background: linear-gradient(180deg, #0d1b2a, #1b263b); /* Cosmic gradient */
            font-family: 'Arial', sans-serif;
            overflow: hidden;
        }
        canvas { display: block; }
        
        /* Control Panel Styling */
        .control-panel {
            position: fixed;
            top: 15px;
            left: 15px;
            z-index: 10;
            background: rgba(27, 38, 59, 0.9); /* Dark blue semi-transparent */
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
        }
        .control-panel label {
            color: #e0e1dd; /* Light gray */
            font-size: 14px;
            display: block;
            margin-bottom: 5px;
        }
        .control-panel input[type="range"] {
            width: 200px;
            accent-color: #00d4ff; /* Cyan accent */
        }
        .control-panel input[type="color"] {
            width: 50px;
            height: 30px;
            border: none;
            cursor: pointer;
        }
        .control-panel button {
            width: 100px;
            padding: 8px;
            margin: 5px 0;
            background: #415a77; /* Muted blue */
            color: #e0e1dd;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background 0.3s;
        }
        .control-panel button:hover {
            background: #778da9; /* Lighter blue on hover */
        }
        .control-panel span {
            color: #00d4ff; /* Cyan text */
            margin-left: 10px;
        }

        /* Timeline Styling */
        #timeline {
            position: fixed;
            bottom: 15px;
            left: 15px;
            color: #e0e1dd;
            font-size: 16px;
            z-index: 10;
            background: rgba(27, 38, 59, 0.7);
            padding: 5px 10px;
            border-radius: 5px;
        }

        /* Data Tooltip */
        .tooltip {
            position: absolute;
            background: rgba(0, 212, 255, 0.9);
            color: #0d1b2a;
            padding: 5px 10px;
            border-radius: 5px;
            font-size: 12px;
            pointer-events: none;
            z-index: 20;
            display: none;
        }
    </style>
</head>
<body>
    <div class="control-panel">
        <label for="timeSlider">Time Reversal Speed:</label>
        <input type="range" id="timeSlider" min="1" max="10" value="5" step="1">
        <span id="speedLabel">Speed: 5</span>

        <label for="particleColor">Particle Color:</label>
        <input type="color" id="particleColor" value="#00d4ff"> <!-- Cyan default -->

        <label for="particleSize">Particle Size:</label>
        <input type="range" id="particleSize" min="0.1" max="1" value="0.2" step="0.1">
        <span id="sizeLabel">Size: 0.2</span>

        <button id="pauseBtn">Pause</button>
        <button id="resetBtn">Reset</button>
        <button id="toggleSound">Mute Sound</button>
    </div>

    <div id="timeline">Epoch: Big Bang</div>
    <div class="tooltip" id="dataTooltip"></div>

    <script>
        // Scene Setup
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.05;

        // Lighting
        const ambientLight = new THREE.AmbientLight(0xe0e1dd, 0.4); // Soft white
        scene.add(ambientLight);
        const pointLight = new THREE.PointLight(0xffffff, 1.5, 100);
        pointLight.position.set(10, 10, 10);
        scene.add(pointLight);

        // Singularity (Big Bang Origin)
        const sphereGeometry = new THREE.SphereGeometry(1, 64, 64);
        const sphereMaterial = new THREE.MeshPhysicalMaterial({
            color: 0xff1a1a, // Bright red
            emissive: 0xff1a1a,
            emissiveIntensity: 1.5,
            metalness: 0.2,
            roughness: 0.5
        });
        const bigBangSphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        scene.add(bigBangSphere);

        // Particle System
        const particleCount = 15000; // Increased for more detail
        const particleGeometry = new THREE.BufferGeometry();
        const particles = new Float32Array(particleCount * 3);
        const velocities = new Float32Array(particleCount * 3);
        for (let i = 0; i < particleCount * 3; i += 3) {
            const radius = Math.random() * 100;
            const theta = Math.random() * Math.PI * 2;
            const phi = Math.acos(2 * Math.random() - 1);
            particles[i] = radius * Math.sin(phi) * Math.cos(theta);
            particles[i + 1] = radius * Math.sin(phi) * Math.sin(theta);
            particles[i + 2] = radius * Math.cos(phi);
            velocities[i] = -particles[i] * 0.001; // Initial inward velocity
            velocities[i + 1] = -particles[i + 1] * 0.001;
            velocities[i + 2] = -particles[i + 2] * 0.001;
        }
        particleGeometry.setAttribute('position', new THREE.BufferAttribute(particles, 3));
        const particleMaterial = new THREE.PointsMaterial({
            color: 0x00d4ff, // Cyan
            size: 0.2,
            transparent: true,
            opacity: 0.8
        });
        const particleSystem = new THREE.Points(particleGeometry, particleMaterial);
        scene.add(particleSystem);

        camera.position.z = 50;

        // Control Variables
        let scale = 1;
        let contractionRate = 0.05;
        let simulationRunning = true;
        let soundOn = true;

        // DOM Elements
        const timeSlider = document.getElementById("timeSlider");
        const speedLabel = document.getElementById("speedLabel");
        const particleColorPicker = document.getElementById("particleColor");
        const particleSizeSlider = document.getElementById("particleSize");
        const sizeLabel = document.getElementById("sizeLabel");
        const pauseBtn = document.getElementById("pauseBtn");
        const resetBtn = document.getElementById("resetBtn");
        const toggleSoundBtn = document.getElementById("toggleSound");
        const timelineDiv = document.getElementById("timeline");
        const tooltip = document.getElementById("dataTooltip");

        // Controls
        timeSlider.addEventListener("input", () => {
            contractionRate = timeSlider.value * 0.01;
            speedLabel.innerText = `Speed: ${timeSlider.value}`;
        });

        particleColorPicker.addEventListener("input", () => {
            particleMaterial.color.set(particleColorPicker.value);
        });

        particleSizeSlider.addEventListener("input", () => {
            particleMaterial.size = parseFloat(particleSizeSlider.value);
            sizeLabel.innerText = `Size: ${particleSizeSlider.value}`;
        });

        pauseBtn.addEventListener("click", () => {
            simulationRunning = !simulationRunning;
            pauseBtn.innerText = simulationRunning ? "Pause" : "Resume";
        });

        resetBtn.addEventListener("click", () => {
            scale = 1;
            contractionRate = 0.05;
            for (let i = 0; i < particleCount * 3; i += 3) {
                const radius = Math.random() * 100;
                const theta = Math.random() * Math.PI * 2;
                const phi = Math.acos(2 * Math.random() - 1);
                particles[i] = radius * Math.sin(phi) * Math.cos(theta);
                particles[i + 1] = radius * Math.sin(phi) * Math.sin(theta);
                particles[i + 2] = radius * Math.cos(phi);
                velocities[i] = -particles[i] * 0.001;
                velocities[i + 1] = -particles[i + 1] * 0.001;
                velocities[i + 2] = -particles[i + 2] * 0.001;
            }
            particleGeometry.attributes.position.needsUpdate = true;
            simulationRunning = true;
            pauseBtn.innerText = "Pause";
        });

        toggleSoundBtn.addEventListener("click", () => {
            soundOn = !soundOn;
            toggleSoundBtn.innerText = soundOn ? "Mute Sound" : "Unmute Sound";
            soundOn ? sound.play() : sound.pause();
        });

        // Sound
        const sound = new Howl({
            src: ['https://www.soundjay.com/buttons/beep-01a.mp3'], // Placeholder sound
            volume: 0.3,
            loop: true,
        });
        sound.play();

        // Timeline Events
        const events = [
            { time: 0, label: "Big Bang", desc: "The universe begins." },
            { time: 0.1, label: "Cosmic Inflation", desc: "Rapid expansion occurs." },
            { time: 0.5, label: "First Stars", desc: "Stars begin to form." },
            { time: 1, label: "Galaxies Form", desc: "Galaxies take shape." },
            { time: 2, label: "CMB Radiation", desc: "Cosmic background radiation emerges." },
            { time: 3, label: "Mature Universe", desc: "Universe stabilizes." },
        ];

        function updateTimeline(time) {
            let eventLabel = "Epoch: ";
            events.forEach(event => {
                if (time >= event.time) eventLabel = `Epoch: ${event.label}`;
            });
            timelineDiv.innerText = eventLabel;
        }

        // Clickable Data Points
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();

        window.addEventListener('mousemove', (event) => {
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObject(bigBangSphere);
            if (intersects.length > 0) {
                tooltip.style.display = 'block';
                tooltip.style.left = `${event.clientX + 10}px`;
                tooltip.style.top = `${event.clientY + 10}px`;
                tooltip.innerText = `Singularity\nScale: ${scale.toFixed(2)}`;
            } else {
                tooltip.style.display = 'none';
            }
        });

        window.addEventListener('click', (event) => {
            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObject(bigBangSphere);
            if (intersects.length > 0) {
                alert(`Singularity Data:\nScale: ${scale.toFixed(2)}\nTime: ${(3 - scale).toFixed(2)} units`);
            }
        });

        // Animation Loop
        function animate() {
            requestAnimationFrame(animate);

            if (simulationRunning) {
                scale -= contractionRate;
                if (scale < 0.1) scale = 0.1;
                bigBangSphere.scale.set(scale, scale, scale);

                const positions = particleGeometry.attributes.position.array;
                for (let i = 0; i < particleCount * 3; i += 3) {
                    positions[i] += velocities[i];
                    positions[i + 1] += velocities[i + 1];
                    positions[i + 2] += velocities[i + 2];
                    const dist = Math.sqrt(positions[i] ** 2 + positions[i + 1] ** 2 + positions[i + 2] ** 2);
                    if (dist < 1) {
                        velocities[i] = velocities[i + 1] = velocities[i + 2] = 0; // Stop at singularity
                    }
                }
                particleGeometry.attributes.position.needsUpdate = true;

                updateTimeline(3 - scale); // Reverse timeline
                controls.update();
                renderer.render(scene, camera);
            }
        }

        animate();

        // Resize Handling
        window.addEventListener('resize', () => {
            renderer.setSize(window.innerWidth, window.innerHeight);
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
        });
    </script>
</body>
</html>