    createAnomalies() {
        // Create a gravitational lens effect
        this.createGravitationalLens(14, 0.2);
        
        // Create a neutron star with pulsar beams
        this.createPulsar(-12, 0.12, 0xaaffff);
        
        // Create a wormhole
        this.createWormhole(16, 1.5);
        
        // Create a nebula
        this.createNebula(-10, 3);
        
        // Create a black hole
        this.createBlackHole(7, 0.5);
    }
    
    createGravitationalLens(radius, size) {
        const ringGeometry = new THREE.RingGeometry(size, size * 1.5, 64);
        const ringMaterial = new THREE.MeshBasicMaterial({ 
            color: 0xffffff, 
            side: THREE.DoubleSide,
            transparent: true,
            opacity: 0.2
        });
        
        const ring = new THREE.Mesh(ringGeometry, ringMaterial);
        
        const angle = Math.random() * Math.PI * 2;
        ring.position.x = radius * Math.cos(angle);
        ring.position.z = radius * Math.sin(angle);
        
        // Random orientation
        ring.rotation.x = Math.PI / 2;
        ring.rotation.y = Math.random() * Math.PI;
        
        this.galaxyGroup.add(ring);
        
        // Add a distortion effect with points
        const particleCount = 1000;
        const particles = new THREE.BufferGeometry();
        const positions = new Float32Array(particleCount * 3);
        
        for (let i = 0; i < particleCount; i++) {
            const t = Math.random() * Math.PI * 2;
            const r = size + (Math.random() * 0.5 - 0.25);
            
            positions[i * 3] = r * Math.cos(t);
            positions[i * 3 + 1] = (Math.random() - 0.5) * 0.1;
            positions[i * 3 + 2] = r * Math.sin(t);
        }
        
        particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        
        const particleMaterial = new THREE.PointsMaterial({
            color: 0xffffff,
            size: 0.02,
            transparent: true,
            opacity: 0.6,
            blending: THREE.AdditiveBlending
        });
        
        const lensParticles = new THREE.Points(particles, particleMaterial);
        ring.add(lensParticles);
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: ring,
            type: 'lens',
            radius: radius,
            angle: angle,
            orbitSpeed: 0.01,
            rotationSpeed: 0.1
        });
    }
    
    createPulsar(radius, size, color) {
        const geometry = new THREE.SphereGeometry(size, 32, 32);
        const material = new THREE.MeshBasicMaterial({ 
            color: color,
            emissive: color,
            emissiveIntensity: 2
        });
        
        const pulsar = new THREE.Mesh(geometry, material);
        
        const angle = Math.random() * Math.PI * 2;
        pulsar.position.x = radius * Math.cos(angle);
        pulsar.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(pulsar);
        
        // Create beams
        const beamGroup = new THREE.Group();
        pulsar.add(beamGroup);
        
        const beamGeometry = new THREE.CylinderGeometry(0.05, 0.2, 3, 16);
        const beamMaterial = new THREE.MeshBasicMaterial({
            color: color,
            transparent: true,
            opacity: 0.6,
            blending: THREE.AdditiveBlending
        });
        
        const beam1 = new THREE.Mesh(beamGeometry, beamMaterial);
        beam1.position.y = 1.5;
        beamGroup.add(beam1);
        
        const beam2 = new THREE.Mesh(beamGeometry, beamMaterial);
        beam2.position.y = -1.5;
        beam2.rotation.x = Math.PI;
        beamGroup.add(beam2);
        
        // Random initial rotation
        beamGroup.rotation.x = Math.random() * Math.PI;
        beamGroup.rotation.z = Math.random() * Math.PI;
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: pulsar,
            beamGroup: beamGroup,
            type: 'pulsar',
            color: color,
            radius: radius,
            angle: angle,
            orbitSpeed: 0.03,
            rotationSpeed: 0.5 + Math.random() * 2
        });
    }
    
    createWormhole(radius, size) {
        // Create a torus for the wormhole edge
        const torusGeometry = new THREE.TorusGeometry(size, size * 0.2, 32, 64);
        const torusMaterial = new THREE.MeshBasicMaterial({
            color: 0x440088,
            emissive: 0x6600aa,
            transparent: true,
            opacity: 0.8
        });
        
        const torus = new THREE.Mesh(torusGeometry, torusMaterial);
        
        const angle = Math.random() * Math.PI * 2;
        torus.position.x = radius * Math.cos(angle);
        torus.position.z = radius * Math.sin(angle);
        
        // Random orientation
        torus.rotation.x = Math.PI / 2;
        torus.rotation.y = Math.random() * Math.PI;
        
        this.galaxyGroup.add(torus);
        
        // Create the wormhole center
        const diskGeometry = new THREE.CircleGeometry(size * 0.8, 64);
        const diskMaterial = new THREE.MeshBasicMaterial({
            color: 0x110022,
            transparent: true,
            opacity: 0.6,
            side: THREE.DoubleSide
        });
        
        const disk = new THREE.Mesh(diskGeometry, diskMaterial);
        disk.rotation.x = Math.PI / 2;
        torus.add(disk);
        
        // Add swirling particles
        const particleCount = 2000;
        const particles = new THREE.BufferGeometry();
        const positions = new Float32Array(particleCount * 3);
        
        for (let i = 0; i < particleCount; i++) {
            const t = Math.random() * Math.PI * 2;
            const spiral = Math.random() * 3;
            const r = 0.1 + (size * 0.7) * Math.exp(-spiral);
            
            positions[i * 3] = r * Math.cos(t + spiral * 10);
            positions[i * 3 + 1] = (Math.random() - 0.5) * 0.1;
            positions[i * 3 + 2] = r * Math.sin(t + spiral * 10);
        }
        
        particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        
        const particleMaterial = new THREE.PointsMaterial({
            color: 0xaa55ff,
            size: 0.04,
            transparent: true,
            opacity: 0.7,
            blending: THREE.AdditiveBlending
        });
        
        const wormholeParticles = new THREE.Points(particles, particleMaterial);
        disk.add(wormholeParticles);
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: torus,
            disk: disk,
            particles: wormholeParticles,
            type: 'wormhole',
            radius: radius,
            angle: angle,
            orbitSpeed: 0.01,
            rotationSpeed: 0.1
        });
    }
    
    createNebula(radius, size) {
        const particleCount = 5000;
        const particles = new THREE.BufferGeometry();
        const positions = new Float32Array(particleCount * 3);
        const colors = new Float32Array(particleCount * 3);
        
        const angle = Math.random() * Math.PI * 2;
        const nebulaCenter = new THREE.Vector3(
            radius * Math.cos(angle),
            0,
            radius * Math.sin(angle)
        );
        
        // Create the nebula color palette
        const colorOptions = [
            new THREE.Color(0xff5566), // Red
            new THREE.Color(0x5566ff), // Blue
            new THREE.Color(0x55ff88)  // Green
        ];
        
        const primaryColor = colorOptions[Math.floor(Math.random() * colorOptions.length)];
        
        for (let i = 0; i < particleCount; i++) {
            // Create cloud-like formations
            const distance = Math.random() * size;
            const azimuth = Math.random() * Math.PI * 2;
            const elevation = Math.random() * Math.PI - Math.PI/2;
            
            // Create non-uniform distribution for more cloud-like appearance
            const distortFactor = 0.6;
            const x = nebulaCenter.x + distance * Math.cos(elevation) * Math.cos(azimuth) * (1 + Math.random() * distortFactor);
            const y = nebulaCenter.y + distance * Math.sin(elevation) * (1 + Math.random() * distortFactor);
            const z = nebulaCenter.z + distance * Math.cos(elevation) * Math.sin(azimuth) * (1 + Math.random() * distortFactor);
            
            positions[i * 3] = x;
            positions[i * 3 + 1] = y;
            positions[i * 3 + 2] = z;
            
            // Color variations
            const color = primaryColor.clone();
            const distFromCenter = Math.sqrt(
                Math.pow(x - nebulaCenter.x, 2) + 
                Math.pow(y - nebulaCenter.y, 2) + 
                Math.pow(z - nebulaCenter.z, 2)
            );
            
            // Fade color based on distance from center
            const fade = Math.max(0, 1 - distFromCenter / size);
            color.offsetHSL(Math.random() * 0.1 - 0.05, 0, 0);
            color.multiplyScalar(fade * 0.8 + 0.2);
            
            colors[i * 3] = color.r;
            colors[i * 3 + 1] = color.g;
            colors[i * 3 + 2] = color.b;
        }
        
        particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        particles.setAttribute('color', new THREE.BufferAttribute(colors, 3));
        
        const particleMaterial = new THREE.PointsMaterial({
            size: 0.1,
            vertexColors: true,
            transparent: true,
            opacity: 0.6,
            blending: THREE.AdditiveBlending
        });
        
        const nebula = new THREE.Points(particles, particleMaterial);
        this.galaxyGroup.add(nebula);
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: nebula,
            type: 'nebula',
            radius: radius,
            angle: angle,
            orbitSpeed: 0.005,
            center: nebulaCenter,
            size: size
        });
    }
    
    createBlackHole(radius, size) {
        // Create the event horizon
        const horizonGeometry = new THREE.SphereGeometry(size, 32, 32);
        const horizonMaterial = new THREE.MeshBasicMaterial({
            color: 0x000000,
            transparent: false
        });
        
        const blackHole = new THREE.Mesh(horizonGeometry, horizonMaterial);
        
        const angle = Math.random() * Math.PI * 2;
        blackHole.position.x = radius * Math.cos(angle);
        blackHole.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(blackHole);
        
        // Create the accretion disk
        const diskGeometry = new THREE.RingGeometry(size * 1.2, size * 3, 64);
        const diskMaterial = new THREE.MeshBasicMaterial({
            color: 0xff8800,
            side: THREE.DoubleSide,
            transparent: true,
            opacity: 0.7
        });
        
        const accretionDisk = new THREE.Mesh(diskGeometry, diskMaterial);
        accretionDisk.rotation.x = Math.PI / 2;
        blackHole.add(accretionDisk);
        
        // Add disk particles
        const particleCount = 3000;
        const particles = new THREE.BufferGeometry();
        const positions = new Float32Array(particleCount * 3);
        const colors = new Float32Array(particleCount * 3);
        
        for (let i = 0; i < particleCount; i++) {
            const angle = Math.random() * Math.PI * 2;
            const distance = size * 1.2 + Math.random() * (size * 1.8);
            
            positions[i * 3] = distance * Math.cos(angle);
            positions[i * 3 + 1] = (Math.random() - 0.5) * 0.1;
            positions[i * 3 + 2] = distance * Math.sin(angle);
            
            // Color gradient from yellow to red to blue
            const color = new THREE.Color();
            const ratio = (distance - size * 1.2) / (size * 1.8);
            
            if (ratio < 0.3) {
                color.setHSL(0.15, 1.0, 0.5); // Yellow-orange
            } else if (ratio < 0.6) {
                color.setHSL(0.05, 1.0, 0.5); // Red-orange
            } else {
                color.setHSL(0.65, 1.0, 0.5); // Blue
            }
            
            colors[i * 3] = color.r;
            colors[i * 3 + 1] = color.g;
            colors[i * 3 + 2] = color.b;
        }
        
        particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        particles.setAttribute('color', new THREE.BufferAttribute(colors, 3));
        
        const particleMaterial = new THREE.PointsMaterial({
            size: 0.04,
            vertexColors: true,
            transparent: true,
            opacity: 0.8,
            blending: THREE.AdditiveBlending
        });
        
        const diskParticles = new THREE.Points(particles, particleMaterial);
        accretionDisk.add(diskParticles);
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: blackHole,
            disk: accretionDisk,
            particles: diskParticles,
            type: 'blackHole',
            radius: radius,
            angle: angle,
            orbitSpeed: 0.01,
            rotationSpeed: 0.2
        });
    }/**
 * Galaxy Background Animation
 * A Three.js based animated galaxy simulation for website backgrounds
 */
class GalaxyBackground {
    constructor(containerId = 'background-container') {
        this.containerId = containerId;
        this.setup();
        this.createScene();
        this.createGalaxy();
        this.clock = new THREE.Clock();
        this.animate();
        
        // Handle window resize
        window.addEventListener('resize', () => this.onWindowResize(), false);
    }
    
    setup() {
        // Create container if it doesn't exist
        if (!document.getElementById(this.containerId)) {
            const container = document.createElement('div');
            container.id = this.containerId;
            container.style.position = 'fixed';
            container.style.top = '0';
            container.style.left = '0';
            container.style.width = '100%';
            container.style.height = '100%';
            container.style.zIndex = '-1';
            container.style.overflow = 'hidden';
            document.body.prepend(container);
        }
        
        // Setup Three.js scene, camera, and renderer
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.setClearColor(0x000011, 1);
        document.getElementById(this.containerId).appendChild(this.renderer.domElement);
        
        // Setup camera position - farther back for a larger view
        this.camera.position.set(0, 15, 30);
        this.camera.lookAt(0, 0, 0);
        
        // Container for galaxy elements
        this.galaxyGroup = new THREE.Group();
        this.scene.add(this.galaxyGroup);
        
        // Store celestial entities
        this.entities = [];
        
        // Auto rotation settings
        this.autoRotate = true;
        this.autoRotateSpeed = 0.03;
    }
    
    createScene() {
        // Add ambient light
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
        this.scene.add(ambientLight);
        
        // Add point light
        const pointLight = new THREE.PointLight(0xffffff, 1);
        pointLight.position.set(5, 5, 5);
        this.scene.add(pointLight);
    }
    
    createGalaxy() {
        this.createDustDisk();
        this.createBackgroundStars();
        this.createAsteroidBelt();
        this.createCelestialBodies();
        this.createAnomalies();
    }
    
    createDustDisk() {
        const particleCount = 30000;
        const geometry = new THREE.BufferGeometry();
        const positions = new Float32Array(particleCount * 3);
        const colors = new Float32Array(particleCount * 3);
        
        for (let i = 0; i < particleCount; i++) {
            // Create main galaxy disk with spiral arms
            let distance, theta;
            
            if (Math.random() > 0.3) {
                // Create spiral arms
                const arm = Math.floor(Math.random() * 5); // 5 spiral arms
                const armAngle = (arm / 5) * Math.PI * 2;
                const spiralFactor = 0.5 + Math.random() * 0.5;
                distance = 2 + Math.random() * 20; // Extended radius
                theta = armAngle + spiralFactor * distance * 0.1;
                
                // Add some random spread to the arms
                theta += (Math.random() - 0.5) * 0.3;
            } else {
                // Random particles for the central bulge and between arms
                distance = Math.random() * Math.random() * 20;
                theta = Math.random() * Math.PI * 2;
            }
            
            positions[i * 3] = distance * Math.cos(theta);
            positions[i * 3 + 1] = (Math.random() - 0.5) * 0.2 * (1 - Math.min(1, distance / 10));
            positions[i * 3 + 2] = distance * Math.sin(theta);
            
            // Color gradient from center to edge
            const color = new THREE.Color();
            if (distance < 5) {
                // Yellowish center
                color.setHSL(0.15, 0.8, Math.random() * 0.2 + 0.8);
            } else if (distance < 10) {
                // Blueish middle
                color.setHSL(0.6, 0.8, Math.random() * 0.2 + 0.8);
            } else {
                // Purplish outer regions
                color.setHSL(0.75, 0.8, Math.random() * 0.2 + 0.8);
            }
            
            colors[i * 3] = color.r;
            colors[i * 3 + 1] = color.g;
            colors[i * 3 + 2] = color.b;
        }
        
        geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
        
        const material = new THREE.PointsMaterial({
            size: 0.05,
            vertexColors: true,
            transparent: true,
            opacity: 0.8
        });
        
        this.dustDisk = new THREE.Points(geometry, material);
        this.galaxyGroup.add(this.dustDisk);
    }
    
    createBackgroundStars() {
        const starCount = 15000;
        const geometry = new THREE.BufferGeometry();
        const positions = new Float32Array(starCount * 3);
        const colors = new Float32Array(starCount * 3);
        
        for (let i = 0; i < starCount; i++) {
            const theta = Math.random() * Math.PI * 2;
            const phi = Math.acos(Math.random() * 2 - 1);
            const radius = 70 + Math.random() * 80;
            positions[i * 3] = radius * Math.sin(phi) * Math.cos(theta);
            positions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
            positions[i * 3 + 2] = radius * Math.cos(phi);
            
            // Add variety to star colors
            const color = new THREE.Color();
            if (Math.random() > 0.97) {
                // Red giants (few)
                color.setHSL(0.05, 1.0, 0.9);
            } else if (Math.random() > 0.95) {
                // Blue giants (some)
                color.setHSL(0.6, 1.0, 0.9);
            } else if (Math.random() > 0.90) {
                // Yellow stars 
                color.setHSL(0.15, 0.8, 0.8);
            } else {
                // White-ish stars (most common)
                const whiteness = Math.random() * 0.2 + 0.8;
                color.setRGB(whiteness, whiteness, whiteness);
            }
            
            colors[i * 3] = color.r;
            colors[i * 3 + 1] = color.g;
            colors[i * 3 + 2] = color.b;
        }
        
        geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
        
        const material = new THREE.PointsMaterial({
            size: 0.08,
            vertexColors: true,
            transparent: true,
            opacity: 0.8
        });
        
        this.backgroundStars = new THREE.Points(geometry, material);
        this.scene.add(this.backgroundStars);
    }
    
    createAsteroidBelt() {
        const asteroidCount = 400;
        const asteroidGeometry = new THREE.SphereGeometry(0.05, 8, 8);
        const materials = [
            new THREE.MeshBasicMaterial({ color: 0x8B4513 }),
            new THREE.MeshBasicMaterial({ color: 0x696969 }),
            new THREE.MeshBasicMaterial({ color: 0xA0522D })
        ];
        
        // Create two asteroid belts
        for (let belt = 0; belt < 2; belt++) {
            const beltRadius = belt === 0 ? 13 : 18;
            const beltWidth = belt === 0 ? 2 : 1.5;
            const beltHeight = belt === 0 ? 0.5 : 0.3;
            
            for (let i = 0; i < asteroidCount; i++) {
                const material = materials[Math.floor(Math.random() * materials.length)];
                const asteroid = new THREE.Mesh(asteroidGeometry, material);
                
                // Random size variation
                const scale = 0.5 + Math.random();
                asteroid.scale.set(scale, scale, scale);
                
                const angle = (i / asteroidCount) * Math.PI * 2;
                const radiusVariation = Math.random() * beltWidth;
                const radius = beltRadius + radiusVariation;
                
                asteroid.position.set(
                    radius * Math.cos(angle),
                    (Math.random() - 0.5) * beltHeight,
                    radius * Math.sin(angle)
                );
                
                this.galaxyGroup.add(asteroid);
            }
        }
    }
    
    createCelestialBodies() {
        // Create a massive central star
        this.createStar(0, 0, 0, 0.5, 0xffffff);
        
        // Create several stars scattered around the galaxy
        this.createStar(8, 0.2, 0xffdd88, 0.02);
        this.createStar(15, 0.3, 0xffaa66, 0.03);
        this.createStar(-12, 0.25, 0x66ccff, 0.01);
        this.createStar(-7, 0.22, 0xffff99, 0.015);
        
        // Create various planets in different orbits
        const planetOrbits = [3, 5, 6.5, 8, 10, 12, 15, 17, 19, 20.5];
        const planetCount = 30; // More planets!
        
        for (let i = 0; i < planetCount; i++) {
            const radius = planetOrbits[i % planetOrbits.length] * (0.9 + Math.random() * 0.2);
            const size = 0.08 + Math.random() * 0.08;
            
            // Generate a random color
            const hue = Math.random();
            const color = new THREE.Color().setHSL(hue, 0.7, 0.6);
            
            // Randomize the type of planet
            const planetType = Math.random();
            
            if (planetType < 0.4) {
                // Regular planet
                this.createPlanet(radius, size, color.getHex(), 0.05 + Math.random() * 0.15);
            } else if (planetType < 0.6) {
                // Ringed planet
                const ringColor = new THREE.Color().setHSL((hue + 0.2) % 1, 0.7, 0.6);
                this.createRingedPlanet(radius, size, color.getHex(), ringColor.getHex(), 0.04 + Math.random() * 0.12);
            } else if (planetType < 0.8) {
                // Lightning planet
                const lightningColor = 0xffffff;
                this.createLightningPlanet(radius, size, color.getHex(), lightningColor, 0.03 + Math.random() * 0.1);
            } else {
                // Create a few comets
                const cometColor = 0x87CEEB;
                this.createComet(radius, size * 0.6, cometColor, 0.2 + Math.random() * 0.3);
            }
        }
        
        // Create quasars at strategic positions
        this.createEnhancedQuasar(21, 0.18, 0x00aaff, 0.015);
        this.createEnhancedQuasar(-18, 0.16, 0xff00ff, 0.02);
        this.createEnhancedQuasar(16, 0.17, 0x00ffaa, 0.018);
    }
    
    createStar(radius, size, color, orbitSpeed = 0) {
        const geometry = new THREE.SphereGeometry(size, 32, 32);
        const material = new THREE.MeshBasicMaterial({ color: color });
        const star = new THREE.Mesh(geometry, material);
        
        // Create glow effect
        const glowGeometry = new THREE.SphereGeometry(size * 1.2, 32, 32);
        const glowMaterial = new THREE.ShaderMaterial({
            uniforms: {
                c: { type: "f", value: 0.1 },
                p: { type: "f", value: 1.2 },
                glowColor: { type: "c", value: new THREE.Color(color) }
            },
            vertexShader: `
                varying vec3 vNormal;
                void main() 
                {
                    vNormal = normalize(normalMatrix * normal);
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                }
            `,
            fragmentShader: `
                uniform vec3 glowColor;
                uniform float c;
                uniform float p;
                varying vec3 vNormal;
                void main() 
                {
                    float intensity = pow(c - dot(vNormal, vec3(0.0, 0.0, 1.0)), p);
                    gl_FragColor = vec4(glowColor, 1.0) * intensity;
                }
            `,
            side: THREE.FrontSide,
            blending: THREE.AdditiveBlending,
            transparent: true
        });
        
        const glow = new THREE.Mesh(glowGeometry, glowMaterial);
        star.add(glow);
        
        const angle = Math.random() * Math.PI * 2;
        star.position.x = radius * Math.cos(angle);
        star.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(star);
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: star,
            type: 'star',
            radius: radius,
            angle: angle,
            orbitSpeed: orbitSpeed,
            glow: glow
        });
    }
    
    createPlanet(radius, size, color, orbitSpeed) {
        const geometry = new THREE.SphereGeometry(size, 32, 32);
        const material = new THREE.MeshBasicMaterial({ color: color });
        const planet = new THREE.Mesh(geometry, material);
        
        const angle = Math.random() * Math.PI * 2;
        planet.position.x = radius * Math.cos(angle);
        planet.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(planet);
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: planet,
            type: 'planet',
            radius: radius,
            angle: angle,
            orbitSpeed: orbitSpeed
        });
    }
    
    createRingedPlanet(radius, size, color, ringColor, orbitSpeed) {
        const planetGeometry = new THREE.SphereGeometry(size, 32, 32);
        const planetMaterial = new THREE.MeshBasicMaterial({ color: color });
        const planet = new THREE.Mesh(planetGeometry, planetMaterial);
        
        const ringGeometry = new THREE.RingGeometry(size * 1.5, size * 2, 32);
        const ringMaterial = new THREE.MeshBasicMaterial({ color: ringColor, side: THREE.DoubleSide });
        const ring = new THREE.Mesh(ringGeometry, ringMaterial);
        ring.rotation.x = Math.PI / 2;
        
        const planetGroup = new THREE.Group();
        planetGroup.add(planet);
        planetGroup.add(ring);
        
        const angle = Math.random() * Math.PI * 2;
        planetGroup.position.x = radius * Math.cos(angle);
        planetGroup.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(planetGroup);
        
        this.entities.push({
            id: Date.now().toString() + Math.random(),
            object: planetGroup,
            type: 'ringedPlanet',
            ring: ring,
            radius: radius,
            angle: angle,
            orbitSpeed: orbitSpeed
        });
    }
    
    createComet(radius, size, color, orbitSpeed) {
        const geometry = new THREE.SphereGeometry(size, 32, 32);
        const material = new THREE.MeshBasicMaterial({ color: color });
        const comet = new THREE.Mesh(geometry, material);
        
        const angle = Math.random() * Math.PI * 2;
        comet.position.x = radius * Math.cos(angle);
        comet.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(comet);
        
        const cometData = {
            id: Date.now().toString() + Math.random(),
            object: comet,
            type: 'comet',
            color: color,
            radius: radius,
            angle: angle,
            orbitSpeed: orbitSpeed
        };
        
        this.entities.push(cometData);
        this.updateCometTail(cometData);
        this.updateCometGlow(cometData);
    }
    
    createLightningPlanet(radius, size, color, lightningColor, orbitSpeed) {
        const geometry = new THREE.SphereGeometry(size, 32, 32);
        const material = new THREE.MeshBasicMaterial({ color: color });
        const planet = new THREE.Mesh(geometry, material);
        
        const angle = Math.random() * Math.PI * 2;
        planet.position.x = radius * Math.cos(angle);
        planet.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(planet);
        
        const planetData = {
            id: Date.now().toString() + Math.random(),
            object: planet,
            type: 'lightningPlanet',
            lightningColor: lightningColor,
            radius: radius,
            angle: angle,
            orbitSpeed: orbitSpeed,
            lightningTimer: 0
        };
        
        this.entities.push(planetData);
        this.updateLightningPlanet(planetData, 0);
    }
    
    createEnhancedQuasar(radius, size, color, orbitSpeed) {
        const geometry = new THREE.SphereGeometry(size, 32, 32);
        const material = new THREE.MeshBasicMaterial({ 
            color: color,
            emissive: color,
            emissiveIntensity: 2
        });
        
        const quasar = new THREE.Mesh(geometry, material);
        
        const angle = Math.random() * Math.PI * 2;
        quasar.position.x = radius * Math.cos(angle);
        quasar.position.z = radius * Math.sin(angle);
        
        this.galaxyGroup.add(quasar);
        
        // Add a glow effect
        const glowGeometry = new THREE.SphereGeometry(size * 1.5, 32, 32);
        const glowMaterial = new THREE.ShaderMaterial({
            uniforms: {
                c: { type: "f", value: 0.2 },
                p: { type: "f", value: 1.4 },
                glowColor: { type: "c", value: new THREE.Color(color) }
            },
            vertexShader: `
                varying vec3 vNormal;
                void main() 
                {
                    vNormal = normalize(normalMatrix * normal);
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                }
            `,
            fragmentShader: `
                uniform vec3 glowColor;
                uniform float c;
                uniform float p;
                varying vec3 vNormal;
                void main() 
                {
                    float intensity = pow(c - dot(vNormal, vec3(0.0, 0.0, 1.0)), p);
                    gl_FragColor = vec4(glowColor, intensity);
                }
            `,
            side: THREE.FrontSide,
            blending: THREE.AdditiveBlending,
            transparent: true
        });
        
        const glow = new THREE.Mesh(glowGeometry, glowMaterial);
        quasar.add(glow);
        
        const quasarData = {
            id: Date.now().toString() + Math.random(),
            object: quasar,
            type: 'enhancedQuasar',
            color: color,
            radius: radius,
            angle: angle,
            orbitSpeed: orbitSpeed,
            jetDirection: new THREE.Vector3(
                Math.random() * 2 - 1,
                Math.random() * 2 - 1,
                Math.random() * 2 - 1
            ).normalize(),
            jetLength: 10 + Math.random() * 5,
            jetSpeed: 0.5 + Math.random() * 0.5
        };
        
        this.entities.push(quasarData);
        this.createEnhancedQuasarJet(quasarData);
    }
    
    createEnhancedQuasarJet(quasar) {
        // Create the jet container
        quasar.jetSystem = new THREE.Group();
        quasar.object.add(quasar.jetSystem);
        
        // Create the main jet beam
        const jetGeometry = new THREE.CylinderGeometry(0.1, 0.01, quasar.jetLength, 32, 20, true);
        const jetMaterial = new THREE.MeshBasicMaterial({ 
            color: quasar.color, 
            transparent: true, 
            opacity: 0.7,
            side: THREE.DoubleSide
        });
        
        quasar.jet = new THREE.Mesh(jetGeometry, jetMaterial);
        quasar.jet.position.set(0, quasar.jetLength/2, 0);
        
        // Align jet with direction
        quasar.jet.lookAt(quasar.jetDirection.clone().multiplyScalar(10));
        
        quasar.jetSystem.add(quasar.jet);
        
        // Create expanding spherical cloud at the end of the jet
        const cloudGeometry = new THREE.SphereGeometry(1, 32, 32);
        const cloudMaterial = new THREE.MeshBasicMaterial({
            color: quasar.color,
            transparent: true,
            opacity: 0.4,
            side: THREE.DoubleSide
        });
        
        quasar.cloud = new THREE.Mesh(cloudGeometry, cloudMaterial);
        quasar.cloud.position.copy(quasar.jetDirection.clone().multiplyScalar(quasar.jetLength));
        quasar.jetSystem.add(quasar.cloud);
        
        // Add particle systems for the jet
        const particleCount = 3000;
        const particleGeometry = new THREE.BufferGeometry();
        const particlePositions = new Float32Array(particleCount * 3);
        const particleSizes = new Float32Array(particleCount);
        
        for (let i = 0; i < particleCount; i++) {
            const t = Math.random(); // Position along jet
            
            if (t < 0.7) {
                // Particles along the jet beam
                const radius = 0.05 + t * 0.15;
                const theta = Math.random() * Math.PI * 2;
                const x = radius * Math.cos(theta);
                const y = t * quasar.jetLength;
                const z = radius * Math.sin(theta);
                
                const position = new THREE.Vector3(x, y, z);
                const jetVector = new THREE.Vector3(0, 1, 0);
                const rotationMatrix = new THREE.Matrix4();
                
                // Align with jet direction
                rotationMatrix.lookAt(
                    new THREE.Vector3(0, 0, 0),
                    quasar.jetDirection,
                    new THREE.Vector3(0, 1, 0)
                );
                
                position.applyMatrix4(rotationMatrix);
                
                particlePositions[i * 3] = position.x;
                particlePositions[i * 3 + 1] = position.y;
                particlePositions[i * 3 + 2] = position.z;
                particleSizes[i] = 0.02 + Math.random() * 0.03;
            } else {
                // Particles in the cloud at the end
                const phi = Math.random() * Math.PI * 2;
                const theta = Math.random() * Math.PI;
                const radius = 0.5 + Math.random() * 1.5;
                
                const x = radius * Math.sin(theta) * Math.cos(phi);
                const y = radius * Math.sin(theta) * Math.sin(phi);
                const z = radius * Math.cos(theta);
                
                const cloudPos = quasar.jetDirection.clone().multiplyScalar(quasar.jetLength);
                
                particlePositions[i * 3] = cloudPos.x + x;
                particlePositions[i * 3 + 1] = cloudPos.y + y;
                particlePositions[i * 3 + 2] = cloudPos.z + z;
                particleSizes[i] = 0.03 + Math.random() * 0.04;
            }
        }
        
        particleGeometry.setAttribute('position', new THREE.BufferAttribute(particlePositions, 3));
        particleGeometry.setAttribute('size', new THREE.BufferAttribute(particleSizes, 1));
        
        const particleMaterial = new THREE.ShaderMaterial({
            uniforms: {
                color: { value: new THREE.Color(quasar.color) },
                pointTexture: { value: this.createParticleTexture() }
            },
            vertexShader: `
                attribute float size;
                varying vec3 vColor;
                void main() {
                    vColor = vec3(1.0);
                    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
                    gl_PointSize = size * (300.0 / -mvPosition.z);
                    gl_Position = projectionMatrix * mvPosition;
                }
            `,
            fragmentShader: `
                uniform vec3 color;
                uniform sampler2D pointTexture;
                varying vec3 vColor;
                void main() {
                    gl_FragColor = vec4(color, 1.0) * texture2D(pointTexture, gl_PointCoord);
                }
            `,
            blending: THREE.AdditiveBlending,
            depthTest: true,
            depthWrite: false,
            transparent: true
        });
        
        quasar.particles = new THREE.Points(particleGeometry, particleMaterial);
        quasar.jetSystem.add(quasar.particles);
        
        // Rotation for visual effect
        quasar.jetSystem.rotation.x = Math.random() * Math.PI;
        quasar.jetSystem.rotation.z = Math.random() * Math.PI;
    }
    
    createParticleTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 64;
        canvas.height = 64;
        
        const context = canvas.getContext('2d');
        const gradient = context.createRadialGradient(32, 32, 0, 32, 32, 32);
        gradient.addColorStop(0, 'rgba(255,255,255,1)');
        gradient.addColorStop(0.3, 'rgba(255,255,255,0.8)');
        gradient.addColorStop(0.6, 'rgba(255,255,255,0.4)');
        gradient.addColorStop(1, 'rgba(255,255,255,0)');
        
        context.fillStyle = gradient;
        context.fillRect(0, 0, 64, 64);
        
        const texture = new THREE.Texture(canvas);
        texture.needsUpdate = true;
        return texture;
    }
    
    animate() {
        requestAnimationFrame(() => this.animate());
        
        const deltaTime = this.clock.getDelta();
        
        // Update various elements
        this.updateDustDisk(deltaTime);
        this.updateEntities(deltaTime);
        this.rotateBackgroundStars(deltaTime);
        
        // Auto-rotate the galaxy
        if (this.autoRotate) {
            this.galaxyGroup.rotation.y += this.autoRotateSpeed * deltaTime;
        }
        
        this.renderer.render(this.scene, this.camera);
    }
    
    updateDustDisk(deltaTime) {
        const positions = this.dustDisk.geometry.attributes.position.array;
        
        for (let i = 0; i < positions.length; i += 3) {
            const x = positions[i];
            const z = positions[i + 2];
            const distance = Math.sqrt(x * x + z * z);
            const angle = Math.atan2(z, x) + deltaTime * (1 / (distance + 0.1)) * 0.5;
            
            positions[i] = distance * Math.cos(angle);
            positions[i + 2] = distance * Math.sin(angle);
        }
        
        this.dustDisk.geometry.attributes.position.needsUpdate = true;
    }
    
    updateEntities(deltaTime) {
        this.entities.forEach(entity => {
            if (entity.type === 'planet' || entity.type === 'ringedPlanet') {
                // Update planet positions
                const radius = entity.radius;
                const angle = entity.angle + entity.orbitSpeed * deltaTime;
                entity.angle = angle;
                entity.object.position.x = radius * Math.cos(angle);
                entity.object.position.z = radius * Math.sin(angle);
                
                // Add fluid dynamics effect to dust particles near planets
                this.flowDustAroundEntity(entity.object.position, 0.5);
            } else if (entity.type === 'star') {
                // Add fluid dynamics effect to dust particles near stars
                this.flowDustAroundEntity(entity.object.position, 1);
            } else if (entity.type === 'comet') {
                this.updateComet(entity, deltaTime);
            } else if (entity.type === 'lightningPlanet') {
                this.updateLightningPlanet(entity, deltaTime);
            } else if (entity.type === 'quasar') {
                this.updateQuasar(entity, deltaTime);
            } else if (entity.type === 'enhancedQuasar') {
                this.updateEnhancedQuasar(entity, deltaTime);
            } else if (entity.type === 'lens') {
                this.updateGravitationalLens(entity, deltaTime);
            } else if (entity.type === 'pulsar') {
                this.updatePulsar(entity, deltaTime);
            } else if (entity.type === 'wormhole') {
                this.updateWormhole(entity, deltaTime);
            } else if (entity.type === 'nebula') {
                this.updateNebula(entity, deltaTime);
            } else if (entity.type === 'blackHole') {
                this.updateBlackHole(entity, deltaTime);
            }
        });
    }
    
    updateEnhancedQuasar(quasar, deltaTime) {
        // Orbit movement
        if (quasar.orbitSpeed > 0) {
            quasar.angle += quasar.orbitSpeed * deltaTime;
            quasar.object.position.x = quasar.radius * Math.cos(quasar.angle);
            quasar.object.position.z = quasar.radius * Math.sin(quasar.angle);
        }
        
        // Update the jet particles for movement
        if (quasar.particles) {
            const positions = quasar.particles.geometry.attributes.position.array;
            
            for (let i = 0; i < positions.length; i += 3) {
                // Get distance from center
                const x = positions[i];
                const y = positions[i + 1];
                const z = positions[i + 2];
                
                // Transform to local coordinates for calculation
                const localPos = new THREE.Vector3(x, y, z);
                
                // Find distance from quasar center
                const distance = localPos.length();
                
                // Check if particle is in jet or cloud
                if (distance > quasar.jetLength * 0.7) {
                    // Cloud particles - expand outward
                    localPos.normalize().multiplyScalar(distance + deltaTime * 0.1);
                    
                    // If too far from center, reset closer to center
                    if (localPos.length() > quasar.jetLength * 2) {
                        const resetPos = quasar.jetDirection.clone().multiplyScalar(quasar.jetLength * 0.8);
                        const randomOffset = new THREE.Vector3(
                            (Math.random() - 0.5) * 0.2,
                            (Math.random() - 0.5) * 0.2,
                            (Math.random() - 0.5) * 0.2
                        );
                        resetPos.add(randomOffset);
                        
                        positions[i] = resetPos.x;
                        positions[i + 1] = resetPos.y;
                        positions[i + 2] = resetPos.z;
                    } else {
                        positions[i] = localPos.x;
                        positions[i + 1] = localPos.y;
                        positions[i + 2] = localPos.z;
                    }
                } else {
                    // Jet particles - move along the jet
                    localPos.add(quasar.jetDirection.clone().multiplyScalar(deltaTime * quasar.jetSpeed));
                    
                    // If near end of jet, add some outward motion
                    const jetProgress = localPos.dot(quasar.jetDirection) / quasar.jetLength;
                    if (jetProgress > 0.7) {
                        const outwardVector = localPos.clone().sub(
                            quasar.jetDirection.clone().multiplyScalar(localPos.dot(quasar.jetDirection))
                        );
                        if (outwardVector.length() > 0) {
                            outwardVector.normalize().multiplyScalar(deltaTime * 0.1 * (jetProgress - 0.7) / 0.3);
                            localPos.add(outwardVector);
                        }
                    }
                    
                    positions[i] = localPos.x;
                    positions[i + 1] = localPos.y;
                    positions[i + 2] = localPos.z;
                }
            }
            
            quasar.particles.geometry.attributes.position.needsUpdate = true;
        }
        
        // Pulse the cloud
        if (quasar.cloud) {
            const pulseFactor = 1 + Math.sin(performance.now() * 0.001) * 0.2;
            quasar.cloud.scale.set(pulseFactor, pulseFactor, pulseFactor);
        }
        
        // Rotate the entire jet system slightly for visual interest
        quasar.jetSystem.rotation.y += deltaTime * 0.1;
    }
    
    updateGravitationalLens(lens, deltaTime) {
        // Orbit movement
        lens.angle += lens.orbitSpeed * deltaTime;
        lens.object.position.x = lens.radius * Math.cos(lens.angle);
        lens.object.position.z = lens.radius * Math.sin(lens.angle);
        
        // Rotate the lens
        lens.object.rotation.z += lens.rotationSpeed * deltaTime;
    }
    
    updatePulsar(pulsar, deltaTime) {
        // Orbit movement
        pulsar.angle += pulsar.orbitSpeed * deltaTime;
        pulsar.object.position.x = pulsar.radius * Math.cos(pulsar.angle);
        pulsar.object.position.z = pulsar.radius * Math.sin(pulsar.angle);
        
        // Rotate the beams
        pulsar.beamGroup.rotation.y += pulsar.rotationSpeed * deltaTime;
        
        // Pulse the brightness
        const material = pulsar.object.material;
        material.emissiveIntensity = 1.5 + Math.sin(performance.now() * 0.01) * 0.5;
    }
    
    updateWormhole(wormhole, deltaTime) {
        // Orbit movement
        wormhole.angle += wormhole.orbitSpeed * deltaTime;
        wormhole.object.position.x = wormhole.radius * Math.cos(wormhole.angle);
        wormhole.object.position.z = wormhole.radius * Math.sin(wormhole.angle);
        
        // Rotate the wormhole
        wormhole.object.rotation.z += wormhole.rotationSpeed * deltaTime;
        
        // Update the particles
        if (wormhole.particles) {
            const positions = wormhole.particles.geometry.attributes.position.array;
            
            for (let i = 0; i < positions.length; i += 3) {
                // Convert to polar coordinates
                let x = positions[i];
                let z = positions[i + 2];
                const r = Math.sqrt(x * x + z * z);
                let theta = Math.atan2(z, x);
                
                // Rotate faster near the center
                const angularSpeed = 0.5 * (1 / (r + 0.1));
                theta += deltaTime * angularSpeed;
                
                // Move slightly inward for spiraling effect
                const newRadius = Math.max(0.1, r - deltaTime * 0.1);
                
                // Convert back to Cartesian
                positions[i] = newRadius * Math.cos(theta);
                positions[i + 2] = newRadius * Math.sin(theta);
                
                // Reset particles that get too close to center
                if (newRadius < 0.2) {
                    const resetRadius = 0.8;
                    const resetTheta = Math.random() * Math.PI * 2;
                    positions[i] = resetRadius * Math.cos(resetTheta);
                    positions[i + 1] = (Math.random() - 0.5) * 0.1;
                    positions[i + 2] = resetRadius * Math.sin(resetTheta);
                }
            }
            
            wormhole.particles.geometry.attributes.position.needsUpdate = true;
        }
    }
    
    updateNebula(nebula, deltaTime) {
        // Orbit movement
        nebula.angle += nebula.orbitSpeed * deltaTime;
        const newX = nebula.radius * Math.cos(nebula.angle);
        const newZ = nebula.radius * Math.sin(nebula.angle);
        
        // Update the center and position
        const dx = newX - nebula.center.x;
        const dz = newZ - nebula.center.z;
        
        nebula.center.x = newX;
        nebula.center.z = newZ;
        nebula.object.position.x += dx;
        nebula.object.position.z += dz;
        
        // Slow rotation of the nebula for visual effect
        nebula.object.rotation.y += deltaTime * 0.02;
    }
    
    updateBlackHole(blackHole, deltaTime) {
        // Orbit movement
        blackHole.angle += blackHole.orbitSpeed * deltaTime;
        blackHole.object.position.x = blackHole.radius * Math.cos(blackHole.angle);
        blackHole.object.position.z = blackHole.radius * Math.sin(blackHole.angle);
        
        // Rotate the accretion disk
        blackHole.disk.rotation.z += blackHole.rotationSpeed * deltaTime;
        
        // Update disk particles
        if (blackHole.particles) {
            const positions = blackHole.particles.geometry.attributes.position.array;
            
            for (let i = 0; i < positions.length; i += 3) {
                // Convert to polar coordinates
                let x = positions[i];
                let z = positions[i + 2];
                const r = Math.sqrt(x * x + z * z);
                let theta = Math.atan2(z, x);
                
                // Different orbital speeds at different distances (Keplerian rotation)
                const angularSpeed = 0.5 * Math.pow(r, -1.5);
                theta += deltaTime * angularSpeed;
                
                // Convert back to Cartesian
                positions[i] = r * Math.cos(theta);
                positions[i + 2] = r * Math.sin(theta);
            }
            
            blackHole.particles.geometry.attributes.position.needsUpdate = true;
        }
        
        // Create a gravitational effect on nearby dust
        this.flowDustAroundEntity(blackHole.object.position, 3, true);
    }
    
    updateComet(comet, deltaTime) {
        comet.angle += comet.orbitSpeed * deltaTime;
        const x = comet.radius * Math.cos(comet.angle);
        const z = comet.radius * Math.sin(comet.angle);
        comet.object.position.set(x, 0, z);
        
        this.updateCometTail(comet);
    }
    
    updateCometTail(comet) {
        if (!comet.tail) {
            const tailGeometry = new THREE.BufferGeometry();
            const tailMaterial = new THREE.PointsMaterial({
                size: 0.05,
                color: comet.color,
                transparent: true,
                opacity: 0.6,
                blending: THREE.AdditiveBlending
            });
            
            comet.tail = new THREE.Points(tailGeometry, tailMaterial);
            this.galaxyGroup.add(comet.tail);
        }
        
        const tailLength = 2;
        const particleCount = 100;
        const positions = new Float32Array(particleCount * 3);
        
        for (let i = 0; i < particleCount; i++) {
            const t = i / particleCount;
            const x = comet.object.position.x - t * tailLength * Math.cos(comet.angle);
            const y = comet.object.position.y + (Math.random() - 0.5) * 0.1;
            const z = comet.object.position.z - t * tailLength * Math.sin(comet.angle);
            
            positions[i * 3] = x;
            positions[i * 3 + 1] = y;
            positions[i * 3 + 2] = z;
        }
        
        comet.tail.geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        comet.tail.geometry.attributes.position.needsUpdate = true;
    }
    
    updateCometGlow(comet) {
        if (!comet.glow) {
            const glowGeometry = new THREE.SphereGeometry(0.15, 32, 32);
            const glowMaterial = new THREE.ShaderMaterial({
                uniforms: {
                    c: { type: "f", value: 0.1 },
                    p: { type: "f", value: 1.2 },
                    glowColor: { type: "c", value: new THREE.Color(comet.color) }
                },
                vertexShader: `
                    varying vec3 vNormal;
                    void main() 
                    {
                        vNormal = normalize(normalMatrix * normal);
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                    }
                `,
                fragmentShader: `
                    uniform vec3 glowColor;
                    uniform float c;
                    uniform float p;
                    varying vec3 vNormal;
                    void main() 
                    {
                        float intensity = pow(c - dot(vNormal, vec3(0.0, 0.0, 1.0)), p);
                        gl_FragColor = vec4(glowColor, 1.0) * intensity;
                    }
                `,
                side: THREE.FrontSide,
                blending: THREE.AdditiveBlending,
                transparent: true
            });
            
            comet.glow = new THREE.Mesh(glowGeometry, glowMaterial);
            comet.object.add(comet.glow);
        }
    }
    
    updateLightningPlanet(planet, deltaTime) {
        if (!planet.lightningSystem) {
            planet.lightningSystem = new THREE.Group();
            planet.object.add(planet.lightningSystem);
            planet.lightningTimer = 0;
        }
        
        planet.lightningTimer -= deltaTime;
        if (planet.lightningTimer <= 0) {
            this.createLightning(planet);
            planet.lightningTimer = Math.random() * 0.5 + 0.1; // Random time between 0.1 and 0.6 seconds
        }
    }
    
    createLightning(planet) {
        const lightningGeometry = new THREE.BufferGeometry();
        const lightningMaterial = new THREE.LineBasicMaterial({ color: planet.lightningColor });
        const points = [];
        
        const startAngle = Math.random() * Math.PI * 2;
        const endAngle = startAngle + (Math.random() * Math.PI / 2 - Math.PI / 4);
        const radius = 0.15; // Slightly larger than the planet
        
        points.push(new THREE.Vector3(
            Math.cos(startAngle) * radius,
            Math.sin(startAngle) * radius,
            0
        ));
        
        for (let i = 0; i < 5; i++) {
            const t = (i + 1) / 6;
            const angle = startAngle + (endAngle - startAngle) * t;
            points.push(new THREE.Vector3(
                Math.cos(angle) * radius + (Math.random() - 0.5) * 0.05,
                Math.sin(angle) * radius + (Math.random() - 0.5) * 0.05,
                (Math.random() - 0.5) * 0.05
            ));
        }
        
        points.push(new THREE.Vector3(
            Math.cos(endAngle) * radius,
            Math.sin(endAngle) * radius,
            0
        ));
        
        lightningGeometry.setFromPoints(points);
        const lightning = new THREE.Line(lightningGeometry, lightningMaterial);
        planet.lightningSystem.add(lightning);
        
        setTimeout(() => {
            planet.lightningSystem.remove(lightning);
            lightning.geometry.dispose();
            lightning.material.dispose();
        }, 100); // Remove lightning after 100ms
    }
    
    updateQuasar(quasar, deltaTime) {
        if (!quasar.shaft) {
            const shaftGeometry = new THREE.CylinderGeometry(0.05, 0.05, 10, 32);
            const shaftMaterial = new THREE.MeshBasicMaterial({ color: quasar.color, transparent: true, opacity: 0.7 });
            
            quasar.shaft = new THREE.Mesh(shaftGeometry, shaftMaterial);
            quasar.shaft.rotation.x = Math.PI / 2;
            quasar.object.add(quasar.shaft);
            
            const particleCount = 1000;
            const particles = new THREE.BufferGeometry();
            const positions = new Float32Array(particleCount * 3);
            
            for (let i = 0; i < particleCount; i++) {
                const t = Math.random();
                const angle = Math.random() * Math.PI * 2;
                const radius = 0.05 + t * 0.05;
                positions[i * 3] = Math.cos(angle) * radius;
                positions[i * 3 + 1] = (Math.random() - 0.5) * 10;
                positions[i * 3 + 2] = Math.sin(angle) * radius;
            }
            
            particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            const particleMaterial = new THREE.PointsMaterial({ color: quasar.color, size: 0.02 });
            quasar.particles = new THREE.Points(particles, particleMaterial);
            quasar.object.add(quasar.particles);
        }
        
        quasar.shaft.rotation.z += deltaTime;
        const positions = quasar.particles.geometry.attributes.position.array;
        
        for (let i = 0; i < positions.length; i += 3) {
            positions[i + 1] += deltaTime * (Math.random() + 0.5); // Move particles along the shaft
            if (positions[i + 1] > 5) positions[i + 1] = -5; // Reset particles at the end of the shaft
        }
        
        quasar.particles.geometry.attributes.position.needsUpdate = true;
    }
    
    flowDustAroundEntity(position, radius, isBlackHole = false) {
        const positions = this.dustDisk.geometry.attributes.position.array;
        
        for (let i = 0; i < positions.length; i += 3) {
            const dustX = positions[i];
            const dustZ = positions[i + 2];
            const dx = dustX - position.x;
            const dz = dustZ - position.z;
            const distance = Math.sqrt(dx * dx + dz * dz);
            
            if (distance < radius) {
                const angle = Math.atan2(dz, dx);
                let tangentialSpeed = 0.1 * (1 - distance / radius);
                let newDistance = Math.max(distance, radius * 0.8);
                
                if (isBlackHole) {
                    // Black hole has stronger effect - spiral inward more dramatically
                    tangentialSpeed = 0.2 * (1 - distance / radius);
                    newDistance = distance * (1 - 0.01); // Slowly pull inward
                    
                    // Particles too close to black hole get "consumed"
                    if (distance < radius * 0.2) {
                        // Reset particle to random location on galaxy edge
                        const resetAngle = Math.random() * Math.PI * 2;
                        const resetRadius = 15 + Math.random() * 5;
                        positions[i] = resetRadius * Math.cos(resetAngle);
                        positions[i + 1] = (Math.random() - 0.5) * 0.2;
                        positions[i + 2] = resetRadius * Math.sin(resetAngle);
                        continue;
                    }
                }
                
                const newAngle = angle + tangentialSpeed;
                positions[i] = position.x + newDistance * Math.cos(newAngle);
                positions[i + 2] = position.z + newDistance * Math.sin(newAngle);
            }
        }
        
        this.dustDisk.geometry.attributes.position.needsUpdate = true;
    }
    
    rotateBackgroundStars(deltaTime) {
        this.backgroundStars.rotation.y += 0.01 * deltaTime;
    }
    
    onWindowResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
    }
    
    // Public methods for controlling the background
    setAutoRotate(enabled) {
        this.autoRotate = enabled;
    }
    
    setRotationSpeed(speed) {
        this.autoRotateSpeed = speed;
    }
    
    setCameraPosition(x, y, z) {
        this.camera.position.set(x, y, z);
        this.camera.lookAt(0, 0, 0);
    }
    
    setBackgroundColor(color) {
        this.renderer.setClearColor(color);
    }
    
    dispose() {
        window.removeEventListener('resize', this.onWindowResize);
        this.renderer.dispose();
        document.getElementById(this.containerId).removeChild(this.renderer.domElement);
    }
}

// Initialize the galaxy background when the page loads
document.addEventListener('DOMContentLoaded', function() {
    // Check if Three.js is loaded
    if (typeof THREE === 'undefined') {
        console.error('Three.js is required for GalaxyBackground. Please include it in your HTML.');
        
        // Create a script element to load Three.js
        const script = document.createElement('script');
        script.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js';
        script.onload = function() {
            // Initialize the galaxy background after Three.js is loaded
            window.galaxyBackground = new GalaxyBackground();
        };
        document.head.appendChild(script);
    } else {
        // If Three.js is already loaded, initialize the galaxy background
        window.galaxyBackground = new GalaxyBackground();
    }
});
