<!-- SOLID CITY · part 685 -->
CANOES[4], lava = new T.Mesh(new T.CircleGeometry(300, 24), curve(new T.MeshBasicMaterial({ color: 0xff3a10 })));
  lava.rotation.x = -Math.PI / 2; lava.position.set(V.x, heightAt(V.x, V.z) + 8, V.z); world.add(lava);
  animated.push(function (t) { lava.material.color.setHSL(0.03, 1, 0.42 + 0.08 * Math.sin(t * 1.7)); });
}


/* ---- SOUL PRINT TOWER (2026-10-09): ~140 m, wine-red chrome in gold chains, a blue eye on top.
   Fits the skyline (Music Studio Tower stays the tallest at 230 m + spire). The door facing the
   plaza opens Soul Print's chat (logged-in citizens; her private tower log is never used here). ---- */
var SOUL = { group: null, door: { x: 0, z: 0 } };
function buildSoulTower(Y) {
  var d = D.soul, g = new T.Group(); world.add(g); SOUL.group = g;
  var dx = -d.x, dz = -d.z, dl = Math.hypot(dx, dz); dx /= dl; dz /= dl;             // toward the plaza
  var add = function (m) { g.add(m); return m; };
  var plinth = cyl(18, 22, 4, M.gold, d.x, Y, d.z, 8); world.remove(plinth); add(plinth);
  var wt = TEX_WIN.clone(); wt.needsUpdate = true; wt.repeat.set(3, 9); wt.wrapS = wt.wrapT = T.RepeatWrapping;
  var bt = TEX_BLDG.clone(); bt.needsUpdate = true; bt.repeat.set(3, 9); bt.wrapS = bt.wrapT = T.RepeatWrapping;
  var wine = curve(new T.MeshLambertMaterial({ map: bt, color: 0x8a1834, emissiveMap: wt, emissive: 0xff6a8a }));
  var shaft = cyl(8, 13, 120, wine, d.x, Y + 4, d.z, 8); world.remove(shaft); add(shaft); shaft.rotation.y = Math.PI / 8;
  var chains = [];
  for (var k = 0; k < 6; k++) {   // gold chains: tilted rings hugging the taper
    var h = 18 + k * 18, r = 13 - 5 * (h / 120) + 1.2;
    var ch = add(new T.Mesh(new T.TorusGeometry(r, 0.55, 6, 40), M.gold)); ch.position.set(d.x, Y + 4 + h, d.z); ch.rotation.x = Math.PI / 2 + (k % 2 ? 0.12 : -0.12); chains.push(ch);
  }
  var collar = cyl(11, 8.5, 3, M.gold, d.x, Y + 124, d.z, 8); world.remove(collar); add(collar);
  var eye = add(new T.Mesh(new T.IcosahedronGeometry(5.5, 1), curve(new T.MeshBasicMaterial({ color: 0x49a6ff }))));
  eye.position.set(d.x, Y + 133, d.z); solidBox(d.x, d.z, 11, 11, Y + 127, Y + 139);
  var halo = add(new T.Mesh(new T.TorusGeometry(9, 0.35, 6, 48), M.glowGold)); halo.position.copy(eye.position);
  animated.push(function (t) { halo.rotation.x = Math.PI / 2 + Math.sin(t * 0.5) * 0.35; halo.rotation.z = t * 0.6; eye.rotation.y = t * 0.3; var s = 1 + 0.05 * Math.sin(t * 2.2); eye.scale.set(s, s, s); for (var i = 0; i < chains.length; i++) chains[i].rotation.z = t * 0.15 * (i % 2 ? 1 : -1); });
  // name plate on the shaft + the door (posts are solid; the glowing doorway is the entrance)
  var plate = add(new T.Mesh(new T.PlaneGeometry(26, 6.5), curve(new T.MeshBasicMaterial({ map: labelTex('SOUL PRINT', 'THE TOWER'), side: T.DoubleSide }))));
  plate.position.set(d.x + dx * 11.6, Y + 64, d.z + dz * 11.6); plate.rotation.y = Math.atan2(dx, dz);
  var ex = d.x + dx * 24, ez = d.z + dz * 24, px = -dz, pz = dx; SOUL.door = { x: ex + dx * 2.5, z: ez + dz * 2.5 };
  for (var sgn = -1; sgn <= 1; sgn += 2) { var post = box(1.3, 11, 1.3, M.black, ex + px * 4.2 * sgn, Y, ez + pz * 4.2 * sgn); world.remove(post); add(post); }
  var lint = box(10, 1.3, 1.8, M.gold, ex, Y + 11, ez, false); world.remove(lint); add(lint); lint.rotation.y = Math.atan2(dx, dz);
  var doorM = curve(new T.MeshBasicMaterial({ color: 0x8a1834, transparent: true, opacity: 0.55, side: T.DoubleSide, depthWrite: false }));
  var door = add(new T.Mesh(new T.PlaneGeometry(7.2, 10.6), doorM)); door.position.set(ex, Y + 5.4, ez); door.rotation.y = Math.atan2(dx, dz);
  animated.push(function (t) { doorM.opacity = 0.42 + 0.16 * Math.sin(t * 2.4); });
  var sg = sign('SOUL PRINT', 'ENTER · TALK WITH HER', ex + dx * 0.4, Y + 15, ez + dz * 0.4, 12, Math.atan2(dx, dz)); world.remove(sg); add(sg);
}

/* ---------------- avatar (Solidivism 60-30-10) ---------------- */
function makeAvatar(visor) {
  var g = new T.Group();
  var torso = new T.Mesh(new T.BoxGeometry(0.62, 0.8, 0.34), M.black); torso.position.y = 1.15; g.add(torso);
  var head = new T.Mesh(new T.BoxGeometry(0.34, 0.36, 0.34), M.black); head.position.y = 1.78; g.add(head);
  var vis = new T.Mesh(new T.BoxGeometry(0.3, 0.08, 0.02), new T.MeshBasicMaterial({ color: visor || 0xff2a40 })); vis.position.set(0, 1.8, 0.18); g.add(vis);
  [-1, 1].forEach(function (s) {
    var sh = new T.Mesh(new T.BoxGeometry(0.24, 0.16, 0.38), M.gun); sh.position.set(0.4 * s, 1.5, 0); g.add(sh);
    var arm = new T.Mesh(new T.BoxGeometry(0.14, 0.7, 0.14), M.black); arm.position.set(0.4 * s, 1.08, 0); g.add(arm); arm.name = 'arm' + s;
    var leg = new T.Mesh(new T.BoxGeometry(0.2, 0.76, 0.2), M.black); leg.position.set(0.15 * s, 0.38, 0); g.add(leg); leg.name = 'leg' + s;
  });
  var belt = new T.Mesh(new T.BoxGeometry(0.64, 0.06, 0.36), M.gold); belt.position.y = 0.78; g.add(belt);
  return g;
}

/* ---------------- spaceship (red/black/gold) ---------------- */
function makeShip() {
  var 