<html><head><base href="blob:https://party.websim.ai/c777e954-6ad3-4545-beed-41039b256590">

    <title>Cosmic Crypto Constellation with New Tokens</title>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>

    <style>

        body { margin: 0; overflow: hidden; background-color: #000; }

        #info, #cryptoInfo { position: absolute; color: white; font-family: Arial; }

        #info { top: 10px; left: 10px; }

        #cryptoInfo { top: 10px; right: 10px; text-align: right; }

        #canvas-container { position: relative; width: 100%; height: 100vh; }

        canvas { position: absolute; top: 0; left: 0; }

    </style>

</head>

<body>

    <div id="canvas-container">

        <canvas id="backgroundCanvas"></canvas>

        <canvas id="particleCanvas"></canvas>

    </div>

    <div id="info"></div>

    <div id="cryptoInfo"></div>


    <script>

        // Three.js setup

        const scene = new THREE.Scene();

        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

        const renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('particleCanvas') });

        renderer.setSize(window.innerWidth, window.innerHeight);


        camera.position.z = 50;


        // Updated Crypto data

        const cryptos = [

            'BTC', 'ETH', 'ADA', 'SOL', 'DOGE', 'QQ', 'NO', 'PEPE', 'GF', 'PANDA', 

            'YAYA', 'SATOSHI', 'CAT', 'ORD', 'CLOWN', 'YY', 'JUMP', 'DONALD', 'A', 'MIMI', 

            'MIQI', 'RABBIT', 'SHEEP', 'SNAKE', 'PEACE', 'RAT', 'MONKEY', 'DRAGON', 'X', 'SEAL', 

            'COW', 'OTTER', 'ORD(', 'ORD{', 'ORD%', 'ORD<'

        ].map(name => ({ name, color: Math.random() * 0xFFFFFF }));


        // Create crypto spheres

        const cryptoSpheres = cryptos.map((crypto, index) => {

            const geometry = new THREE.SphereGeometry(1, 32, 32);

            const material = new THREE.MeshBasicMaterial({ color: crypto.color });

            const sphere = new THREE.Mesh(geometry, material);

            

            const phi = Math.acos(-1 + (2 * index) / cryptos.length);

            const theta = Math.sqrt(cryptos.length * Math.PI) * phi;

            

            const radius = 30;

            sphere.position.x = radius * Math.cos(theta) * Math.sin(phi);

            sphere.position.y = radius * Math.sin(theta) * Math.sin(phi);

            sphere.position.z = radius * Math.cos(phi);

            

            scene.add(sphere);

            return sphere;

        });


        // Create connection lines

        const lineMaterial = new THREE.LineBasicMaterial({ color: 0xFFFFFF, transparent: true, opacity: 0.3 });

        for (let i = 0; i < cryptoSpheres.length; i++) {

            for (let j = i + 1; j < cryptoSpheres.length; j++) {

                const geometry = new THREE.BufferGeometry().setFromPoints([

                    cryptoSpheres[i].position,

                    cryptoSpheres[j].position

                ]);

                const line = new THREE.Line(geometry, lineMaterial);

                scene.add(line);

            }

        }


        // Create stars

        const starGeometry = new THREE.BufferGeometry();

        const starMaterial = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.1 });


        const starVertices = [];

        for (let i = 0; i < 10000; i++) {

            const x = (Math.random() - 0.5) * 2000;

            const y = (Math.random() - 0.5) * 2000;

            const z = (Math.random() - 0.5) * 2000;

            starVertices.push(x, y, z);

        }


        starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));

        const stars = new THREE.Points(starGeometry, starMaterial);

        scene.add(stars);


        // Raycaster for interaction

        const raycaster = new THREE.Raycaster();

        const mouse = new THREE.Vector2();


        function onMouseMove(event) {

            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;

            mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;


            raycaster.setFromCamera(mouse, camera);

            const intersects = raycaster.intersectObjects(cryptoSpheres);


            if (intersects.length > 0) {

                const intersectedSphere = intersects[0].object;

                const cryptoIndex = cryptoSpheres.indexOf(intersectedSphere);

                document.getElementById('info').textContent = cryptos[cryptoIndex].name;

            } else {

                document.getElementById('info').textContent = '';

            }

        }


        window.addEventListener('mousemove', onMouseMove, false);


        // Simulate crypto price changes

        function updateCryptoPrices() {

            let infoHTML = '<h3>Crypto Prices</h3>';

            cryptos.forEach(crypto => {

                const price = (Math.random() * 10000).toFixed(2);

                const change = (Math.random() * 10 - 5).toFixed(2);

                infoHTML += `${crypto.name}: $${price} (${change}%)<br>`;

            });

            document.getElementById('cryptoInfo').innerHTML = infoHTML;

        }


        setInterval(updateCryptoPrices, 5000);

        updateCryptoPrices();


        // Merged Animation: Particle System

        const canvas = document.getElementById('backgroundCanvas');

        const ctx = canvas.getContext('2d');


        canvas.width = window.innerWidth;

        canvas.height = window.innerHeight;


        const particles = [];

        const maxParticles = 100;


        class Particle {

            constructor() {

                this.x = Math.random() * canvas.width;

                this.y = Math.random() * canvas.height;

                this.size = Math.random() * 5 + 1;

                this.speedX = Math.random() * 3 - 1.5;

                this.speedY = Math.random() * 3 - 1.5;

                this.color = `hsl(${Math.random() * 360}, 100%, 50%)`;

            }


            update() {

                this.x += this.speedX;

                this.y += this.speedY;


                if (this.size > 0.2) this.size -= 0.1;


                if (this.x < 0 || this.x > canvas.width) this.speedX *= -1;

                if (this.y < 0 || this.y > canvas.height) this.speedY *= -1;

            }


            draw() {

                ctx.fillStyle = this.color;

                ctx.beginPath();

                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);

                ctx.fill();

            }

        }


        function createParticles() {

            for (let i = 0; i < maxParticles; i++) {

                particles.push(new Particle());

            }

        }


        function animateParticles() {

            ctx.clearRect(0, 0, canvas.width, canvas.height);

            for (let i = 0; i < particles.length; i++) {

                particles[i].update();

                particles[i].draw();

                

                for (let j = i; j < particles.length; j++) {

                    const dx = particles[i].x - particles[j].x;

                    const dy = particles[i].y - particles[j].y;

                    const distance = Math.sqrt(dx * dx + dy * dy);

                    

                    if (distance < 100) {

                        ctx.beginPath();

                        ctx.strokeStyle = particles[i].color;

                        ctx.lineWidth = 0.2;

                        ctx.moveTo(particles[i].x, particles[i].y);

                        ctx.lineTo(particles[j].x, particles[j].y);

                        ctx.stroke();

                    }

                }

                

                if (particles[i].size <= 0.2) {

                    particles.splice(i, 1);

                    i--;

                }

            }

            requestAnimationFrame(animateParticles);

        }


        createParticles();

        animateParticles();


        // Combined animation function

        function animate() {

            requestAnimationFrame(animate);


            // Rotate camera around the scene

            const time = Date.now() * 0.0005;

            camera.position.x = Math.cos(time) * 50;

            camera.position.z = Math.sin(time) * 50;

            camera.lookAt(scene.position);


            // Pulsate crypto spheres

            cryptoSpheres.forEach((sphere, index) => {

                const pulseFactor = Math.sin(time * 5 + index) * 0.1 + 1;

                sphere.scale.set(pulseFactor, pulseFactor, pulseFactor);

            });


            // Rotate stars

            stars.rotation.y += 0.0002;


            renderer.render(scene, camera);

        }


        animate();


        // Responsive design

        window.addEventListener('resize', onWindowResize, false);


        function onWindowResize() {

            camera.aspect = window.innerWidth / window.innerHeight;

            camera.updateProjectionMatrix();

            renderer.setSize(window.innerWidth, window.innerHeight);

            canvas.width = window.innerWidth;

            canvas.height = window.innerHeight;

        }


        // Add data flow animation

        function animateDataFlow() {

            for (let i = 0; i < cryptoSpheres.length; i++) {

                for (let j = i + 1; j < cryptoSpheres.length; j++) {

                    const startSphere = cryptoSpheres[i];

                    const endSphere = cryptoSpheres[j];


                    const dataPacket = new THREE.Mesh(

                        new THREE.SphereGeometry(0.2, 8, 8),

                        new THREE.MeshBasicMaterial({ color: 0xFFFFFF })

                    );


                    dataPacket.position.copy(startSphere.position);

                    scene.add(dataPacket);


                    gsap.to(dataPacket.position, {

                        x: endSphere.position.x,

                        y: endSphere.position.y,

                        z: endSphere.position.z,

                        duration: 2,

                        ease: "none",

                        onComplete: () => {

                            scene.remove(dataPacket);

                        }

                    });

                }

            }

        }


        setInterval(animateDataFlow, 3000);

    </script>

</body>

</html>