<!-- RUBY · part 22 -->
(a2)*R,11);
  }
  for(var s=0;s<10;s++){
    var a=(s/10)*Math.PI*2+0.31;
    road(cx,cz,cx+Math.cos(a)*R,cz+Math.sin(a)*R,9);
  }
  // lamps (denser)
  for(var l=-8;l<=8;l++){
    if(!l)continue;
    [[cx+l*100,cz],[cx,cz+l*100]].forEach(function(p){
      var pole=new THREE.Mesh(new THREE.CylinderGeometry(1.5,1.5,44,6),MAT.dark);
      pole.position.set(p[0],22,p[1]);
      var lamp=new THREE.Mesh(new THREE.SphereGeometry(6,10,10),MAT.goldBright);
      lamp.position.set(p[0],47,p[1]);
      scene.add(pole); scene.add(lamp);
    });
  }
})();

// CITY (denser, with lit windows)
(function(){
  function block(bx,bz,rows,cols){
    for(var r=0;r<rows;r++)for(var c=0;c<cols;c++){
      var h=60+Math.random()*160, w=26+Math.random()*16;
      var b=new THREE.Mesh(new THREE.BoxGeometry(w,h,w),MAT.dark);
      b.position.set(bx+c*46,h/2,bz+r*46); scene.add(b);
      var top=new THREE.Mesh(new THREE.BoxGeometry(w+2,6,w+2),MAT.darkTop);
      top.position.set(bx+c*46,h+3,bz+r*46); scene.add(top);
      // lit windows
      if(Math.random()<0.7){
        var win=new THREE.Mesh(new THREE.PlaneGeometry(w*0.6,8),MAT.window);
        win.position.set(bx+c*46,h*0.6,bz+r*46+w/2+0.5); scene.add(win);
      }
    }
  }
  block(680,280,5,6); block(280,640,6,5); block(640,680,4,5);
  block(240,240,4,4); block(760,480,3,4); block(400,120,3,5);
})();

// PLAZA (richer)
(function(){
  var cx=500,cz=500;
  var disc=new THREE.Mesh(new THREE.CylinderGeometry(100,100,4,36),MAT.pillar);
  disc.position.set(cx,2,cz); scene.add(disc);
  var disc2=new THREE.Mesh(new THREE.CylinderGeometry(70,70,6,32),MAT.dark);
  disc2.position.set(cx,4,cz); scene.add(disc2);
  for(var i=0;i<8;i++){
    var a=(i/8)*Math.PI*2, x=cx+Math.cos(a)*72, z=cz+Math.sin(a)*72;
    var pil=new THREE.Mesh(new THREE.CylinderGeometry(6,8,80,8),MAT.pillar);
    pil.position.set(x,40,z); scene.add(pil);
    var orb=new THREE.Mesh(new THREE.SphereGeometry(10,12,12),MAT.goldBright);
    orb.position.set(x,86,z); scene.add(orb);
  }
  for(var j=0;j<8;j++){
    var a2=(j/8)*Math.PI*2+0.4, x2=cx+Math.cos(a2)*125, z2=cz+Math.sin(a2)*125;
    var pole=new THREE.Mesh(new THREE.CylinderGeometry(2.5,2.5,70,6),MAT.red);
    pole.position.set(x2,35,z2); scene.add(pole);
  }
  var ring=new THREE.Mesh(new THREE.TorusGeometry(20,3.5,8,36),MAT.cyan);
  ring.position.set(cx+150,28,cz+50); scene.add(ring);
  var ring2=new THREE.Mesh(new THREE.TorusGeometry(14,2.5,8,32),MAT.cyan);
  ring2.position.set(cx-140,22,cz-60); scene.add(ring2);
  var mon=new THREE.Mesh(new THREE.CylinderGeometry(12,18,180,8),MAT.white);
  mon.position.set(cx-50,90,cz-140); scene.add(mon);
  var cap=new THREE.Mesh(new THREE.SphereGeometry(14,12,12),MAT.goldBright);
  cap.position.set(cx-50,186,cz-140); scene.add(cap);
  var mLight=new THREE.PointLight(0xffd766,1.5,600);
  mLight.position.set(cx-50,190,cz-140); scene.add(mLight);
  [[200,-70,MAT.teal],[-170,90,MAT.blue],[100,190,MAT.gray],[-200,-140,MAT.teal]].forEach(function(p){
    var pil=new THREE.Mesh(new THREE.CylinderGeometry(8,10,60,8),p[2]);
    pil.position.set(cx+p[0],30,cz+p[1]); scene.add(pil);
    var orb=new THREE.Mesh(new THREE.SphereGeometry(9,10,10),MAT.goldBright);
    orb.position.set(cx+p[0],66,cz+p[1]); scene.add(orb);
  });
  for(var d=0;d<36;d++){
    var a3=(d/36)*Math.PI*2;
    var dot=new THREE.Mesh(new THREE.BoxGeometry(7,2,7),MAT.goldBright);
    dot.position.set(cx+Math.cos(a3)*45,6,cz+Math.sin(a3)*45); scene.add(dot);
  }
})();

// MOUNTAINS (more clusters, two tones)
(function(){
  var clusters=[[-550,-450],[750,-550],[-700,650],[850,550],[0,-900],[-250,900],[900,0],[-900,-100]];
  clusters.forEach(function(cl,ci){
    var n=7+Math.floor(Math.random()*5);
    for(var i=0;i<n;i++){
      var h=200+Math.random()*300;
      var cone=new THREE.Mesh(new THREE.ConeGeometry(100+Math.random()*80,h,6),ci%2?MAT.mountain:MAT.mountain2);
      cone.position.set(500+cl[0]+(Math.random()-0.5)*400,h/2-5,500+cl[1]+(Math.random()-0.5)*400);
      cone.rotation.y=Math.random()*Math.PI; scene.add(cone);
    }
  });
})();

// TREES (forest clusters)
(function(){
  var groves=[[-800,300],[800,800],[-400,-800],[600,-800],[-900,-500],[300,900]];
  groves.forEach(function(gv){
    var n=14+Math.floor(Math.random()*10);
    for(var i=0;i<n;i++){
      var x=500+gv[0]+(Math.random()-0.5)*300, z=500+gv[1]+(Math.random()-0.5)*300;
      var h=28+Math.random()*40;
      var trunk=new THREE.Mesh(new THREE.CylinderGeometry(2.5,3.5,h*0.3,6),MAT.trunk);
      trunk.position.set(x,h*0.15,z);
      var leaves=new THREE.Mesh(new THREE.ConeGeometry(12+Math.random()*8,h*0.85,7),Math.random()<0.5?MAT.leaf:MAT.leaf2);
      leaves.position.set(x,h*0.55,z);
      scene.add(trunk); scene.add(leaves);
    }
  });
})();

// BLIMPS (9)
var blimps=[];
(function(){
  for(var i=0;i<9;i++){
    var grp=new THREE.Group();
    var body=new THREE.Mesh(new THREE.SphereGeometry(26,14,12),MAT.gold);
    body.scale.set(1.9,1,1); grp.add(body);
    var cab=new