<!-- SOLID CITY · part 2080 -->
,8,6),leafM);
    lf.position.set(pt[0],30.5,pt[1]); root.add(lf);
  });
  box(4,0.5,1.5,woodM,-8,28.25,0); solid(-8,0,4,1.5,28,28.8);
  box(4,0.5,1.5,woodM,8,28.25,0); solid(8,0,4,1.5,28,28.8);
  // gold obelisk at center
  var ob=new T.Mesh(new T.CylinderGeometry(0.3,1.2,8,4),gold);
  ob.position.set(0,32,0); root.add(ob); solid(0,0,2.5,2.5,28,36);
  var obCap=new T.Mesh(new T.OctahedronGeometry(0.8),goldTrim);
  obCap.position.set(0,36.5,0); root.add(obCap);
  standFloors.push({x0:-22,x1:22,z0:-22,z1:22,y:28});

  /* ============ TOWER SHAFT (28-95): stepped, with portholes ============ */
  // lower shaft: 44 -> 36 (28-55)
  box(40,27,40,glass,0,41.5,0); solid(0,0,40,40,28,55);
  box(44,1.5,44,goldTrim,0,55.5,0);
  // mid shaft: 36 -> 28 (55-78)
  box(32,23,32,glass,0,66.5,0); solid(0,0,32,32,55,78);
  box(36,1.5,36,goldTrim,0,78.5,0);
  // upper shaft: 28 (78-95)
  box(26,17,26,glass,0,86.5,0); solid(0,0,26,26,78,95);
  // portholes on the shaft (the King's portal vision)
  var pTex=portholeTex(T);
  var pLevels=[40,62,86];
  pLevels.forEach(function(py,idx){
    var r=[20.2,16.2,13.2][idx];
    // 4 faces
    [[0,-r,0],[0,r,Math.PI],[r,0,Math.PI/2],[-r,0,-Math.PI/2]].forEach(function(f){
      var pMat=new T.MeshBasicMaterial({map:pTex,transparent:true,side:T.DoubleSide});
      var pm=new T.Mesh(new T.CircleGeometry(3.2,24),pMat);
      pm.position.set(f[0],py,f[1]); pm.rotation.y=f[2];
      pm.name='porthole'; root.add(pm); portholeMeshes.push(pm);
    });
  });

  /* ============ CROWN (95-115) ============ */
  var ring=new T.Mesh(new T.TorusGeometry(14,1.8,10,32),gold);
  ring.rotation.x=Math.PI/2; ring.position.y=97; root.add(ring);
  var ring2=new T.Mesh(new T.TorusGeometry(10,1.4,10,32),goldTrim);
  ring2.rotation.x=Math.PI/2; ring2.position.y=101; root.add(ring2);
  var spire=new T.Mesh(new T.CylinderGeometry(0.5,2,14,8),gold);
  spire.position.y=108; root.add(spire);
  var beaconM=new T.MeshBasicMaterial({color:0xffe8a0});
  var beacon=new T.Mesh(new T.SphereGeometry(1.2,10,8),beaconM);
  beacon.position.y=116; root.add(beacon);
  solid(0,0,30,30,95,116);

  /* ============ ELEVATOR ============ */
  // shaft at east side (x=14, z=0), 5x5
  box(5,28,5,steel,14,14,0); solid(14,0,5,5,0,28);
  // shaft opening on west face (door)
  // cab
  var cab=new T.Mesh(new T.BoxGeometry(3.6,3.5,3.6),new T.MeshLambertMaterial({color:0xc8ccd4}));
  cab.position.set(14,1.75,0); root.add(cab);
  var cabTrim=new T.Mesh(new T.BoxGeometry(3.8,0.4,3.8),goldTrim);
  cabTrim.position.set(14,3.4,0); cab.add(cabTrim);
  elevators.push({cab:cab,x:14,z:0,floors:[0,16,28],idx:0,moving:false,t:0,from:0,to:0,toIdx:0});
  // elevator plaque
  var ep=quietMarker(T,'LIFT'); ep.position.set(11,2,3); ep.rotation.y=Math.PI/4; root.add(ep);

  /* ============ NAME PLATE ============ */
  var nm=quietMarker(T,'THE ANNEX');
  nm.position.set(0,2,26); root.add(nm);

  /* ============ userData ============ */
  root.userData={
    footprint:foot, center:{x:0,z:0}, radius:80, height:130,
    elevators:elevators, standFloors:standFloors,
    update:function(t,dt,A){
      // portholes pulse and rotate
      for(var i=0;i<portholeMeshes.length;i++){
        var pm=portholeMeshes[i];
        pm.material.opacity=0.85+0.15*Math.sin(t*2+i*0.7);
        pm.rotation.z=t*0.3+i;
      }
      // beacon pulse
      var bp=0.7+0.3*Math.sin(t*2.4); beacon.scale.setScalar(bp);
      // elevator
      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;
            var y=el.from+(el.to-el.from)*ease;
            el.cab.position.y=y+1.75;
            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){
      for(var e=0;e<elevators.length;e++){
        var el=elevators[e];
        if(el.moving)continue;
        var dx=wx-(P.x+el.x), dz=wz-(P.z+el.z);
        if(Math.abs(dx)<4&&Math.abs(dz)<4){
          var nf=(el.idx+1)%el.floors.length;
          var names=['LOBBY','FLOOR 2','ROOF'];
          return 'ELEVATOR \u2192 '+(names[nf]||('FLOOR '+(nf+1)));
        }
      }
      return null;
    },
    boardElevator:function(wx,wz){
      for(var e=0;e<elevators.length;e++){
        var el=elevators[e];
        if(el.moving)continue;
        var dx=wx-(P.x+el.x), dz=wz-(P.z+el.z);
        if(Math.abs(dx)<4&&Math.abs(dz)<4){
          el.toIdx=(el.idx+1)%el.floors.length;
          el.from=el.floors[el.idx]; el.to=el.floors[el.toIdx];
          el.t=0; el.moving=true;
          return true;
        }
      }
      return false;
    }
  };
  return root;
}
export default createAnn