<!-- SOLID CITY · part 2133 -->
.y=1.6;root.add(basin);
  var water=new T.Mesh(new T.CylinderGeometry(11,11,0.6,24),
    new T.MeshBasicMaterial({color:0x6ab8e8,transparent:true,opacity:0.85}));
  water.position.y=2.6;water.name='fountainwater';root.add(water);
  var jet=new T.Mesh(new T.CylinderGeometry(0.8,1.6,16,8),
    new T.MeshBasicMaterial({color:0xbfe4ff,transparent:true,opacity:0.7}));
  jet.position.y=10;jet.name='fountainjet';root.add(jet);
  var obel=new T.Mesh(new T.CylinderGeometry(2,3.4,22,4),gold);
  obel.position.y=11;obel.rotation.y=Math.PI/4;root.add(obel);
  foot.push([0,0,30,30,0,24,0]);
  var dmark=quietMarker(T,'THE HYPER CITY');dmark.position.set(0,0,48);root.add(dmark);

  // ---- waterfront promenade (west edge) ----
  var prom=new T.Mesh(new T.BoxGeometry(36,1.2,380),new T.MeshLambertMaterial({color:0x3a3f47}));
  prom.position.set(-192,0.4,0);root.add(prom);
  // railing (collision so he doesn't stroll into the sea)
  var railM=new T.MeshLambertMaterial({color:0x8a94a0});
  for(var rz=-180;rz<=180;rz+=12){
    var post=new T.Mesh(new T.BoxGeometry(0.5,3,0.5),railM);
    post.position.set(-209,2.2,rz);root.add(post);
  }
  var rail=new T.Mesh(new T.BoxGeometry(0.6,0.5,372),railM);
  rail.position.set(-209,3.8,0);root.add(rail);
  foot.push([-209,0,2,372,0,4,0]);
  // piers + boats
  var boatHullM=new T.MeshLambertMaterial({color:0x5a3a28});
  var boatMastM=new T.MeshLambertMaterial({color:0x8a6a48});
  var sailM=new T.MeshLambertMaterial({color:0xe8e0d0,side:T.DoubleSide});
  [-90,30,120].forEach(function(pz){
    var pier=new T.Mesh(new T.BoxGeometry(70,1.6,10),deckM);
    pier.position.set(-244,0.2,pz);root.add(pier);
    foot.push([-244,pz,70,10,0,1.2,0]);
    for(var b=0;b<2;b++){
      var bx=-244+(b?18:-14), bz=pz+(b?6:-5);
      var hull=new T.Mesh(new T.BoxGeometry(10,3,4),boatHullM);
      hull.position.set(bx,-2.5,bz);hull.name='boat';root.add(hull);
      var mast=new T.Mesh(new T.CylinderGeometry(0.3,0.3,12,6),boatMastM);
      mast.position.set(bx,2,bz);root.add(mast);
      var sail=new T.Mesh(new T.PlaneGeometry(7,9),sailM);
      sail.position.set(bx,5,bz+0.5);root.add(sail);
    }
  });

  // animated bits
  var beaconM=null,beamM=null,fw=null,fj=null;
  root.traverse(function(m){
    if(m.name==='beacon')beaconM=m;
    if(m.name==='beam')beamM=m;
    if(m.name==='fountainwater')fw=m;
    if(m.name==='fountainjet')fj=m;
  });
  var boats=[];root.traverse(function(m){if(m.name==='boat')boats.push(m);});
  root.userData={
    footprint:foot,center:{x:0,z:0},radius:260,height:580,
    elevators:elevators, standFloors:standFloors,
    update:function(t,dt,A){
      if(beaconM){var p=0.6+0.4*Math.sin(t*2.4);beaconM.scale.setScalar(p);}
      if(beamM){beamM.material.opacity=0.2+0.12*Math.sin(t*2.4);}
      if(fw){fw.position.y=2.6+Math.sin(t*3)*0.15;}
      if(fj){fj.scale.y=1+Math.sin(t*5)*0.12;}
      for(var b=0;b<boats.length;b++){boats[b].position.y=-2.5+Math.sin(t*1.2+b*1.7)*0.5;boats[b].rotation.z=Math.sin(t*0.9+b)*0.04;}
      if(window._hyperPortholes){ for(var ph=0; ph<window._hyperPortholes.length; ph++){ var hm=window._hyperPortholes[ph]; hm.material.opacity=0.85+0.15*Math.sin(t*2+ph*0.7); hm.rotation.z=t*0.3+ph; } }
      if(window._hyperShips){ for(var sh3=0; sh3<window._hyperShips.length; sh3++){ var shp=window._hyperShips[sh3]; shp.position.y=Math.sin(t*0.8+shp.userData.ph)*0.6; shp.rotation.z=Math.sin(t*0.6+shp.userData.ph)*0.02; shp.rotation.x=Math.sin(t*0.5+shp.userData.ph)*0.015; } }
      if(window._hyperBeams){ for(var bm3=0; bm3<window._hyperBeams.length; bm3++){ window._hyperBeams[bm3].rotation.y=t*0.8; } }
      if(window._hyperBuoys){ for(var by3=0; by3<window._hyperBuoys.length; by3++){ var buo=window._hyperBuoys[by3]; if(buo.name==='buoy'){ buo.position.y=-2+Math.sin(t*1.5+buo.userData.ph)*0.5; buo.rotation.x=Math.sin(t+buo.userData.ph)*0.1; } else { buo.material.opacity=0.35+0.65*Math.abs(Math.sin(t*2+buo.userData.ph)); } } }
      if(window._hyperTrolleys){ for(var tr3=0; tr3<window._hyperTrolleys.length; tr3++){ var tro=window._hyperTrolleys[tr3]; tro.position.x=tro.userData.cx+Math.sin(t*0.25+tr3*1.7)*8; } }
      // elevators: animate cabs, carry the rider
      if(dt&&A&&A.S){
        var S=A.S;
        for(var e=0;e<elevators.length;e++){
          var el=elevators[e];
          if(el.moving){
            el.t+=dt;
            var dur=3.0, k=Math.min(1,el.t/dur);
            var ease=k<0.5?2*k*k:1-Math.pow(-2*k+2,2)/2; // easeInOut
            var y=el.from+(el.to-el.from)*ease;
            el.cab.position.y=y+1.75;
            // carry the player if inside the cab (world coords)
            var dx=S.p.x-(P.x+el.x), dz=S.p.z-(P.z+el.z);
            if(Math.abs(dx)<3&&Math.abs(dz)<3&&Math.abs(S.p.y-(P.y+y))<4){
              S.p.y=P.y+y+0.2;
            }
            if(k>=1){ el.moving=false; el.idx=el.toIdx; }
          }
        }
      }
    },
    actHere:function(wx,wz){
      // near an elevator cab? offer the ride
      for(va