<!-- SAGA3 · part 31 -->
ial({color: 0xffd700, transparent: true, opacity: 0.5, side: THREE.DoubleSide}));
    disk2.rotation.x = Math.PI/2.3;
    disk2.position.set(bhX, bhY, bhZ);
    bhG.add(disk2);
    scene.add(bhG);
    window._dynamics.push(function(t){
      disk.rotation.z += 0.005;
      disk2.rotation.z -= 0.003;
    });

    /* PLANETS */
    var planetData = [
      {x: -300, y: 250, z: -300, r: 20, c: 0x4466aa},
      {x: 300, y: 200, z: -400, r: 15, c: 0xaa4422},
      {x: 200, y: 350, z: 300, r: 25, c: 0x44aa66}
    ];
    for(var p = 0; p < planetData.length; p++){
      (function(){
        var pd = planetData[p];
        var planet = new THREE.Mesh(new THREE.SphereGeometry(pd.r, 24, 18),
          new THREE.MeshStandardMaterial({color: pd.c, roughness: 0.7}));
        planet.position.set(pd.x, pd.y, pd.z);
        scene.add(planet);
        /* Ring */
        if(p !== 1){
          var ring = new THREE.Mesh(new THREE.RingGeometry(pd.r + 5, pd.r + 10, 32),
            new THREE.MeshBasicMaterial({color: 0xffffff, transparent: true, opacity: 0.3, side: THREE.DoubleSide}));
          ring.rotation.x = Math.PI/2.5;
          ring.position.copy(planet.position);
          scene.add(ring);
        }
        var ph = Math.random() * 10;
        window._dynamics.push(function(t){
          planet.rotation.y += 0.002;
          planet.position.y = pd.y + Math.sin(t * 0.3 + ph) * 5;
        });
      })();
    }

    /* NEBULA — cosmic clouds */
    for(var n = 0; n < 30; n++){
      (function(){
        var colors = [0x8800ff, 0x0044ff, 0xff0088];
        var neb = new THREE.Mesh(new THREE.SphereGeometry(20 + Math.random() * 30, 12, 10),
          new THREE.MeshBasicMaterial({color: colors[n % 3], transparent: true, opacity: 0.08, fog: false}));
        neb.position.set((Math.random()-0.5)*1000, 200 + Math.random()*200, (Math.random()-0.5)*1000);
        scene.add(neb);
        var ph2 = Math.random() * 10;
        window._dynamics.push(function(t){
          neb.material.opacity = 0.06 + Math.sin(t * 0.4 + ph2) * 0.03;
        });
      })();
    }

    /* ENERGY BEAMS — connecting districts, cosmic scale */
    var beamMat = new THREE.MeshBasicMaterial({color: 0x00ffff, transparent: true, opacity: 0.4});
    var beamPoints = [[0,0], [100,-100], [-200,200], [350,-200], [0,-250]];
    for(var b = 0; b < beamPoints.length - 1; b++){
      var x1 = beamPoints[b][0], z1 = beamPoints[b][1];
      var x2 = beamPoints[b+1][0], z2 = beamPoints[b+1][1];
      var len = Math.sqrt((x2-x1)*(x2-x1) + (z2-z1)*(z2-z1));
      var beam = new THREE.Mesh(new THREE.CylinderGeometry(1, 1, len, 8), beamMat);
      beam.position.set((x1+x2)/2, 50, (z1+z2)/2);
      beam.rotation.z = Math.PI/2;
      beam.rotation.y = Math.atan2(x2-x1, z2-z1);
      scene.add(beam);
    }
    window._dynamics.push(function(t){
      beamMat.opacity = 0.3 + Math.sin(t * 2) * 0.15;
    });

    /* FLOATING ISLANDS */
    for(var fi = 0; fi < 8; fi++){
      (function(){
        var fx = (Math.random() - 0.5) * 400;
        var fz = (Math.random() - 0.5) * 400;
        var fy = 60 + Math.random() * 40;
        var island = new THREE.Group();
        var top = new THREE.Mesh(new THREE.CylinderGeometry(12, 8, 4, 8),
          new THREE.MeshStandardMaterial({color: 0x2a4a2a, roughness: 0.9}));
        island.add(top);
        var bottom = new THREE.Mesh(new THREE.ConeGeometry(8, 12, 8),
          new THREE.MeshStandardMaterial({color: 0x555555, roughness: 0.9}));
        bottom.position.y = -8;
        bottom.rotation.x = Math.PI;
        island.add(bottom);
        /* Mini trees */
        for(var mt = 0; mt < 5; mt++){
          var mtree = new THREE.Mesh(new THREE.ConeGeometry(1.5, 4, 6),
            new THREE.MeshStandardMaterial({color: 0x0a4a0a}));
          mtree.position.set((Math.random()-0.5)*15, 4, (Math.random()-0.5)*15);
          island.add(mtree);
        }
        island.position.set(fx, fy, fz);
        scene.add(island);
        var ph3 = Math.random() * 10;
        window._dynamics.push(function(t){
          island.position.y = fy + Math.sin(t * 0.6 + ph3) * 4;
          island.rotation.y += 0.001;
        });
      })();
    }

    /* COSMIC DUST — maximum particles */
    var cosmicGeo = new THREE.BufferGeometry();
    var cosmicCount = 2000;
    var cosmicPos = new Float32Array(cosmicCount * 3);
    for(var cd = 0; cd < cosmicCount; cd++){
      cosmicPos[cd*3] = (Math.random() - 0.5) * 1200;
      cosmicPos[cd*3+1] = Math.random() * 500;
      cosmicPos[cd*3+2] = (Math.random() - 0.5) * 1200;
    }
    cosmicGeo.setAttribute('position', new THREE.BufferAttribute(cosmicPos, 3));
    var cosmicMat = new THREE.PointsMaterial({color: 0xaaaaff, size: 1, transparent: true, opacity: 0.5, fog: false});
    var cosmic = new THREE.Points(cosmicGeo, cosmicMat);
    scene.add(cosmic);
    window._dynamics.push(function(t){
      cosmic.rotation.y = t * 0.005;
    });

  }catch(e){}
}
if(typeof buildCosmic === 'function'){ try{