<!-- SOLID CITY · part 2884 -->
(g, W, 1.1, 0.3, 0, TH + 0.8, hd, M.steel); box(g, W, 1.1, 0.3, 0, TH + 0.8, -hd, M.steel);
    box(g, 0.3, 1.1, D, hw, TH + 0.8, 0, M.steel); box(g, 0.3, 1.1, D, -hw, TH + 0.8, 0, M.steel);
    SF(cfg.ox - hw + 1, cfg.ox + hw - 1, cfg.oz - hd + 1, cfg.oz + hd - 1, TH);
    FP(cfg.ox, cfg.oz, W, D, TH - 1, TH + 1.2); // roof slab handled via standY; block below

    /* portholes: 6 glowing discs on upper facade */
    for (var ph = 0; ph < 6; ph++) {
      var pgeo = new T.CircleGeometry(1.6, 24);
      var pmt = new T.MeshBasicMaterial({ color: cfg.accent, transparent: true, opacity: 0.85, side: T.DoubleSide });
      var pm = new T.Mesh(pgeo, pmt);
      var pfl = 4 + (ph % 4) * 2, side4 = ph % 4;
      var pyy = pfl * FH + FH / 2;
      if (side4 === 0) { pm.position.set(-6 + (ph * 3) % 12, pyy, hd + 0.15); }
      else if (side4 === 1) { pm.position.set(-6 + (ph * 3) % 12, pyy, -hd - 0.15); pm.rotation.y = Math.PI; }
      else if (side4 === 2) { pm.position.set(hw + 0.15, pyy, -6 + (ph * 3) % 12); pm.rotation.y = Math.PI / 2; }
      else { pm.position.set(-hw - 0.15, pyy, -6 + (ph * 3) % 12); pm.rotation.y = -Math.PI / 2; }
      g.add(pm); portholes.push(pm);
    }

    /* name plaque */
    var plq = makeText(T, cfg.name, 0xd8a833); plq.position.set(0, 3, hd + 1.2); g.add(plq);
    return g;
  }

  function makeText(T, str, color) {
    /* lightweight canvas text plate */
    var cv = document.createElement('canvas'); cv.width = 512; cv.height = 64;
    var cx = cv.getContext('2d');
    cx.fillStyle = 'rgba(10,12,18,0.85)'; cx.fillRect(0, 0, 512, 64);
    cx.fillStyle = '#d8a833'; cx.font = 'bold 34px sans-serif'; cx.textAlign = 'center'; cx.textBaseline = 'middle';
    cx.fillStyle = '#' + new T.Color(color).getHexString();
    cx.fillText(str, 256, 34);
    var tx = new T.CanvasTexture(cv);
    var m = new T.Mesh(new T.PlaneGeometry(10, 1.25), new T.MeshBasicMaterial({ map: tx, transparent: true }));
    return m;
  }

  /* build all four */
  var built = TOWERS.map(buildTower);

  /* central plaza */
  var plaza = new T.Group(); root.add(plaza);
  box(plaza, 44, 0.6, 44, 0, 0.3, 0, M.steel);
  box(plaza, 3, 9, 3, 0, 4.5, 0, M.gold); // obelisk
  box(plaza, 6, 0.5, 6, 0, 0.6, 0, M.dark);
  for (var b = 0; b < 4; b++) {
    var ba = b * Math.PI / 2 + Math.PI / 4;
    box(plaza, 3, 1, 1.2, Math.cos(ba) * 14, 0.5, Math.sin(ba) * 14, M.wood);
  }
  var pq = makeText(T, 'QUADRANT CROWN', 0xd8a833); pq.position.set(0, 11, 0); plaza.add(pq);
  SF(-22, 22, -22, 22, 0.6);
  FP(0, 0, 6, 6, 0, 9.5);

  /* two walkable bridges at floor-2 level (y=12) */
  function bridge(a, b) {
    var y = FH + 4;
    var ax = a.ox, az = a.oz, bx = b.ox, bz = b.oz;
    var mx = (ax + bx) / 2, mz = (az + bz) / 2;
    var len = Math.abs(bx - ax) || Math.abs(bz - az);
    var horiz = Math.abs(bx - ax) > Math.abs(bz - az);
    var bg = new T.Group(); bg.position.set(mx, y, mz); root.add(bg);
    if (horiz) { box(bg, len - W, 0.6, 4, 0, 0, 0, M.steel); }
    else { box(bg, 4, 0.6, len - D, 0, 0, 0, M.steel); }
    /* railings */
    for (var s = -1; s <= 1; s += 2) {
      if (horiz) { box(bg, len - W, 1.1, 0.25, 0, 0.85, s * 1.9, M.gold); }
      else { box(bg, 0.25, 1.1, len - D, s * 1.9, 0.85, 0, M.gold); }
    }
    /* door gaps: bridge meets tower faces — footprints already have walls; bridge deck overlaps */
    if (horiz) { SF(mx - (len - W) / 2, mx + (len - W) / 2, mz - 2, mz + 2, y + 0.3); }
    else { SF(mx - 2, mx + 2, mz - (len - D) / 2, mz + (len - D) / 2, y + 0.3); }
    return bg;
  }
  bridge(TOWERS[0], TOWERS[1]); // command <-> intelligence (north pair)
  bridge(TOWERS[2], TOWERS[3]); // living <-> frontier (south pair)

  root.userData = {
    footprint: foot, center: { x: 0, z: 0 }, radius: 130, height: TH + 20,
    elevators: elevators, standFloors: standFloors,
    update: function (t, dt, A) {
      for (var i = 0; i < portholes.length; i++) {
        var pm = portholes[i];
        pm.material.opacity = 0.7 + 0.25 * Math.sin(t * 2 + i * 0.8);
      }
      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 ez2 = k < 0.5 ? 2 * k * k : 1 - Math.pow(-2 * k + 2, 2) / 2;
            var yy = el.from + (el.to - el.from) * ez2;
            el.cab.position.y = yy + 1.75;
            var tw = TOWERS.filter(function (x) { return x.id === el.tower; })[0];
            var dx = S.p.x - (P.x + tw.ox + el.x), dz = S.p.z - (P.z + tw.oz + el.z);
            if (Math.abs(dx) < 3 && Math.abs(dz) < 3 && Math.abs(S.p.y - (P.y + yy)) < 4) S.p.y = P.y + yy + 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