<!-- SOLID CITY · part 2126 -->
 root.add(b);
    foot.push([bx,62,3,1.2,0,0.9,0]);
    var pl=new T.Mesh(new T.BoxGeometry(2,1.6,2),benchM);
    pl.position.set(bx,0.8,88); root.add(pl);
    var lf=new T.Mesh(new T.SphereGeometry(1.4,8,6),leafM);
    lf.position.set(bx,2.4,88); root.add(lf);
    foot.push([bx,88,2,2,0,1.6,0]);
  });
  // west store bench + planter
  var b2=new T.Mesh(new T.BoxGeometry(3,0.5,1.2),benchM);
  b2.position.set(-70,0.6,72); root.add(b2); foot.push([-70,72,3,1.2,0,0.9,0]);
}

/* WESTERN EXPANSION — massive skyline + real harbor (2026-10-11)
 * The King's words: "stretch it the direction away from the city so we have
 * a massive sky line with a real shipping dock port harbor."
 * - West podium extension (x -470..-210)
 * - 12 more megatowers (240-400m) with portholes — a wall of towers
 * - 6 businesses (bank, shipping, law, restaurant/bar, news, architect)
 * - Real harbor: quay, 3 cargo piers, 6 gantry cranes, container stacks,
 *   2 cargo ships, harbor master (real interior), breakwater, lighthouse, buoys
 */
function westTower(T, root, foot, M, x, z, h, tp, R) {
  var g = new T.Group(); g.position.set(x, 0, z);
  var w = 20 + R() * 18, d = 20 + R() * 18;
  var mat = R() < 0.5 ? M.glassA : M.glassB;
  var hw;
  if (tp === 0) {
    var nd = new T.Mesh(new T.CylinderGeometry(w*0.28, w*0.55, h, 8), mat);
    nd.position.y = h/2; g.add(nd);
    var tip = new T.Mesh(new T.CylinderGeometry(0.8, 2.5, 26, 6), M.gold);
    tip.position.y = h+13; g.add(tip);
    hw = w*0.62;
    foot.push([x, z, w*1.24, w*1.24, 0, h+26, 0]);
  } else if (tp === 1) {
    var PHI = 1.6180339887;
    var b1 = new T.Mesh(new T.BoxGeometry(w, h*0.55, d), mat); b1.position.y = h*0.275; g.add(b1);
    var w2 = w/PHI, d2 = d/PHI;
    var b2 = new T.Mesh(new T.BoxGeometry(w2, h*0.3, d2), mat); b2.position.set(0, h*0.55+h*0.15, 0); g.add(b2);
    var b3 = new T.Mesh(new T.BoxGeometry(w2/PHI, h*0.15, d2/PHI), M.gold);
    b3.position.set(0, h*0.85+h*0.075, 0); g.add(b3);
    hw = Math.max(w, d)*0.52;
    foot.push([x, z, Math.max(w,d)*1.04, Math.max(w,d)*1.04, 0, h, 0]);
  } else if (tp === 2) {
    var seg = h/5;
    for (var k = 0; k < 5; k++) {
      var sw = w*(1-k*0.09), sd = d*(1-k*0.09);
      var sgm = new T.Mesh(new T.BoxGeometry(sw, seg, sd), mat);
      sgm.position.y = seg*(k+0.5); sgm.rotation.y = k*0.16; g.add(sgm);
    }
    hw = w*0.6;
    foot.push([x, z, w*1.2, w*1.2, 0, h, 0]);
  } else {
    var bd = new T.Mesh(new T.BoxGeometry(w, h*0.82, d), mat); bd.position.y = h*0.41; g.add(bd);
    var ring = new T.Mesh(new T.TorusGeometry(Math.max(w,d)*0.42, 1.6, 8, 24),
      new T.MeshBasicMaterial({color: 0xd8aa48}));
    ring.rotation.x = Math.PI/2; ring.position.y = h*0.86; g.add(ring);
    hw = Math.max(w,d)*0.52;
    foot.push([x, z, Math.max(w,d)*1.04, Math.max(w,d)*1.04, 0, h, 0]);
  }
  root.add(g);
  // portholes on the new tower
  if (!window._hyperPortholes) window._hyperPortholes = [];
  var pc = document.createElement('canvas'); pc.width = pc.height = 128;
  var px = pc.getContext('2d');
  var pgr = px.createRadialGradient(64,64,4,64,64,64);
  pgr.addColorStop(0,'#fff8e8'); pgr.addColorStop(0.25,'#f2c86a');
  pgr.addColorStop(0.5,'#9a6ae8'); pgr.addColorStop(0.75,'#4a6ae8'); pgr.addColorStop(1,'#1a1a3a');
  px.fillStyle = pgr; px.beginPath(); px.arc(64,64,64,0,7); px.fill();
  px.strokeStyle = '#f2c86a'; px.lineWidth = 3;
  for (var pr = 12; pr < 64; pr += 13) { px.beginPath(); px.arc(64,64,pr,0,7); px.stroke(); }
  var ptex = new T.CanvasTexture(pc); ptex.encoding = T.sRGBEncoding;
  var pmat = new T.MeshBasicMaterial({ map: ptex, transparent: true, side: T.DoubleSide });
  for (var py = 50; py < h; py += 36) {
    for (var f = 0; f < 4; f++) {
      var ang = f*Math.PI/2 + 0.3;
      var hx = x + Math.cos(ang)*hw, hz = z + Math.sin(ang)*hw;
      var hole = new T.Mesh(new T.CircleGeometry(2.8, 20), pmat);
      hole.position.set(hx, py, hz);
      hole.lookAt(hx*2-x, py, hz*2-z);
      root.add(hole);
      window._hyperPortholes.push(hole);
    }
  }
  return {x:x, z:z, h:h};
}

function buildWesternExpansion(T, root, foot, o) {
  var R = mulberry(777);
  var M = {
    glassA: o.glassA, glassB: o.glassB, gold: o.gold, steel: o.steel,
    textPlate: o.textPlate
  };

  // ---- west podium extension ----
  var podM = new T.MeshLambertMaterial({color: 0x2c313a});
  var podW = new T.Mesh(new T.BoxGeometry(260, 10, 380), podM);
  podW.position.set(-340, -5, 0); root.add(podW);
  var rimW = new T.Mesh(new T.BoxGeometry(264, 1.2, 384), M.steel);
  rimW.position.set(-340, 0.1, 0); root.add(rimW);
  foot.push([-340, 0, 264, 384, -10, 0.5, 0]);

  // ---- 12 western megatowers: a wall on the horizon ----
  var cols = [-400, -340, -280], rows = [-120, -40, 40, 120];
  var types = [0, 1, 2, 3], ti = 0;
  cols.forEach(function(cx) {
    rows.forEach(function(cz) {
      var x = cx + (R()-0.5)*18, z = cz + (R()-0.5)*18;
      var h = 250 + R()*150; // 250-400m, tall for the wall effect
      // boo