<!-- SOLID CITY · part 2111 -->
(12,2.7,5.2), cm);
        cb.position.set(dx, 3.4, dz); sg.add(cb);
        if ((dx+dz)%2===0) {
          var cb2 = new T.Mesh(new T.BoxGeometry(12,2.7,5.2), contCols[(Math.abs(dx*3+dz)+1)%5]);
          cb2.position.set(dx, 6.2, dz); sg.add(cb2);
        }
      }
    }
    // bridge tower
    var brM = new T.MeshLambertMaterial({color: 0xe8e8e8});
    var br = new T.Mesh(new T.BoxGeometry(10,16,14), brM);
    br.position.set(-30, 8, 0); sg.add(br);
    var brTop = new T.Mesh(new T.BoxGeometry(11,3,15), new T.MeshLambertMaterial({color: 0x2a4a6a}));
    brTop.position.set(-30, 17, 0); sg.add(brTop);
    // funnel
    var fun = new T.Mesh(new T.CylinderGeometry(2,2.5,8,10), stripeM);
    fun.position.set(-34, 20, 0); sg.add(fun);
    sg.name = 'cargoship';
    sg.userData.baseY = 0; sg.userData.ph = si*2.1;
    root.add(sg);
    solid(-640, sz, 72, 17, -7, 12);
    if (!window._hyperShips) window._hyperShips = [];
    window._hyperShips.push(sg);
  });

  // ---- HARBOR MASTER (real interior office) ----
  buildStore(T, root, foot, BM, {
    x:-500, z:100, ry:Math.PI/2, name:'HARBOR MASTER',
    fit:function(bx, sl, M){
      bx(6,1.1,2,M.counter, 0,0.55,-4); sl(0,-4,6,2,0,1.1);
      // chart wall
      bx(8,4,0.25,M.blueprint, 0,3.5,-6.7);
      bx(8.4,4.4,0.15,M.gold, 0,3.5,-6.8);
      // desks
      [[-4,0],[4,0]].forEach(function(p){
        bx(3,0.9,1.6,M.table, p[0],0.45,p[1]);
        bx(1.0,0.3,0.8,M.paper, p[0],1.05,p[1]);
        sl(p[0],p[1],3,1.6,0,1.2);
      });
      // radio desk with glowing console
      bx(4,1.0,1.4,M.register, 0,0.5,3.5);
      bx(3.6,0.7,0.2,M.glowA, 0,1.35,3.2);
      sl(0,3.5,4,1.4,0,1.7);
      // logbooks shelf
      bx(4,2.4,0.8,M.shelf, -6,1.2,4);
      for (var i=0;i<4;i++) bx(0.7,0.5,0.6,M.paper, -7.2+i*0.85,1.6,4);
      sl(-6,4,4,0.8,0,2.4);
    }
  });

  // ---- BREAKWATER ----
  var rockM = new T.MeshLambertMaterial({color: 0x3a3f45});
  for (var bz=-160; bz<=160; bz+=26) {
    var rk = new T.Mesh(new T.DodecahedronGeometry(7+((bz*13)%5+5)%5, 0), rockM);
    rk.position.set(-745 + ((bz*7)%9+9)%9 - 4, -3, bz);
    rk.rotation.set((bz%3), (bz%5), 0);
    root.add(rk);
  }

  // ---- LIGHTHOUSE ----
  var lhX = -630, lhZ = -165;
  var lhM = new T.MeshLambertMaterial({color: 0xe8e8e8});
  var redM = new T.MeshLambertMaterial({color: 0xc84a3a});
  var lht = new T.Mesh(new T.CylinderGeometry(4.5,6.5,38,12), lhM);
  lht.position.set(lhX, 19, lhZ); root.add(lht);
  for (var lsy=6; lsy<36; lsy+=10) {
    var st = new T.Mesh(new T.CylinderGeometry(4.9-(lsy/38)*2, 5.1-(lsy/38)*2, 3.4, 12), redM);
    st.position.set(lhX, lsy, lhZ); root.add(st);
  }
  var lampR = new T.Mesh(new T.CylinderGeometry(3,3,4,10), darkM);
  lampR.position.set(lhX, 40, lhZ); root.add(lampR);
  var lampB = new T.Mesh(new T.SphereGeometry(2.2,12,10), new T.MeshBasicMaterial({color: 0xffe8a0}));
  lampB.position.set(lhX, 40, lhZ); root.add(lampB);
  var beam = new T.Mesh(new T.CylinderGeometry(1.5,4,70,8,1,true),
    new T.MeshBasicMaterial({color: 0xffe8a0, transparent: true, opacity: 0.28, side: T.DoubleSide, depthWrite: false}));
  beam.position.set(lhX, 40, lhZ);
  beam.rotation.z = Math.PI/2;
  beam.name = 'lhbeam';
  root.add(beam);
  solid(lhX, lhZ, 13, 13, 0, 42);
  if (!window._hyperBeams) window._hyperBeams = [];
  window._hyperBeams.push(beam);

  // ---- BUOYS (channel markers) ----
  if (!window._hyperBuoys) window._hyperBuoys = [];
  for (var bi=0; bi<6; bi++) {
    var buX = -660 - bi*16, buZ = (bi%2 ? 95 : -95);
    var buM = new T.MeshLambertMaterial({color: bi%2 ? 0x3aa84a : 0xc84a3a});
    var buoy = new T.Mesh(new T.CylinderGeometry(1.6,2.2,4.5,8), buM);
    buoy.position.set(buX, -2, buZ); buoy.name = 'buoy';
    buoy.userData.ph = bi*1.3;
    root.add(buoy);
    var bl = new T.Mesh(new T.SphereGeometry(0.65,8,6), new T.MeshBasicMaterial({color: 0xffe8a0, transparent: true}));
    bl.position.set(buX, 0.9, buZ); bl.name = 'buoylight'; bl.userData.ph = bi*1.3;
    root.add(bl);
    window._hyperBuoys.push(buoy); window._hyperBuoys.push(bl);
  }

  // ---- FORKLIFTS ----
  var forkM = new T.MeshLambertMaterial({color: 0xe8b83a});
  [[-540,-40],[-520,30],[-550,95]].forEach(function(fp){
    box(3.2,2,2.2,forkM, fp[0],2,fp[1]);
    box(1.8,1.6,2,forkM, fp[0]-0.5,3.6,fp[1]); // cab
    box(0.4,3.4,2,steel, fp[0]+1.8,2.7,fp[1]); // mast
    box(2.2,0.25,1.6,steel, fp[0]+3,1.2,fp[1]); // forks
    // wheels
    box(0.8,0.8,0.4,darkM, fp[0]-1,1,fp[1]+1.2);
    box(0.8,0.8,0.4,darkM, fp[0]-1,1,fp[1]-1.2);
    box(0.8,0.8,0.4,darkM, fp[0]+1,1,fp[1]+1.2);
    box(0.8,0.8,0.4,darkM, fp[0]+1,1,fp[1]-1.2);
    solid(fp[0],fp[1],4.5,2.5,0,4);
  });

  // ---- PALLETS + CRATES + ROPE COILS ----
  var crateM = new T.MeshLambertMaterial({color: 0x8a6a48});
  for (var pi=0; pi<10; pi++) {
    var px3 = -560 + ((pi*37)%70), pz3 = -115 + ((pi*53)%230);
    if (Math.abs(pz3) < 20) pz3 += 40;
    box(2.2,0.3,2.2,crateM, px3,1.7,pz3);
    var ch = 1 + (pi%2);
  