<!-- SOLID CITY · part 2105 -->
Mesh(new T.CylinderGeometry(rad-1, rad-1, 1, 16), floorM);
    slab.position.y = f2y2-0.5; g.add(slab);
    standFloors.push({ x0: o.x-rad, x1: o.x+rad, z0: o.z-rad, z1: o.z+rad, y: f2y2, cyl: true, cx: o.x, cz: o.z, r: rad-1 });
    for (j = 0; j < 6; j++) {
      var ra = (j/6)*Math.PI*2;
      var rx = Math.cos(ra)*22, rz = Math.sin(ra)*22;
      box(8, 3, 0.4, partM, rx, f2y2+1.5, rz, -ra);
      solid(rx, rz, 8, 1, f2y2, f2y2+3);
      box(3, 1, 1.5, deskM, Math.cos(ra)*26, f2y2+0.5, Math.sin(ra)*26);
    }

    // OBSERVATORY (glass curtain, 360°)
    var oslab = new T.Mesh(new T.CylinderGeometry(rad-1, rad-1, 1, 16), floorM);
    oslab.position.y = obsY-0.5; g.add(oslab);
    standFloors.push({ x0: o.x-rad, x1: o.x+rad, z0: o.z-rad, z1: o.z+rad, y: obsY, cyl: true, cx: o.x, cz: o.z, r: rad-1 });
    var curtain = new T.Mesh(new T.CylinderGeometry(rad-0.5, rad-0.5, 8, 16, 1, true),
      new T.MeshLambertMaterial({ color: 0x9fc4e8, transparent: true, opacity: 0.35, side: T.DoubleSide }));
    curtain.position.y = obsY+4; g.add(curtain);
    box(6, 1, 6, gold, 0, obsY+0.5, 0); solid(0, 0, 6, 6, obsY, obsY+1);
    var plq3 = new T.Mesh(new T.PlaneGeometry(10,2.5),
      new T.MeshBasicMaterial({ map: textPlate(T, 'THE OBSERVATORY'), side: T.DoubleSide }));
    plq3.position.set(0, obsY+6, 0); g.add(plq3);
  }

  // ---- PORTHOLES: mounted by caller on upper facades ----
  g.userData.portholes = portholes;
  g.userData.portTex = portTex;
  root.add(g);
  return g;
}
// Add glowing porthole discs to a facade (call after podium/tower built)
function addPortholes(T, parent, portTex, list) {
  // list: [{x,y,z,ry,r}]
  var mat = new T.MeshBasicMaterial({ map: portTex, transparent: true, side: T.DoubleSide });
  list.forEach(function(p){
    var m = new T.Mesh(new T.CircleGeometry(p.r||3.5, 24), mat);
    m.position.set(p.x, p.y, p.z); m.rotation.y = p.ry||0;
    m.name = 'porthole'; parent.add(m);
  });
}

/* RETAIL ROW — REAL STORES (2026-10-11, the King's "i wanted to make real stores")
 * 12 storefronts with fitted interiors: glass front, gold sign, walk-in door,
 * shelves/counters/tables per trade. Collision solid on all sides, door gaps walkable.
 * Design law: science grown into beautiful art — proportioned, lit, composed.
 */
function buildStore(T, root, foot, M, o) {
  var W=18, D=14, H=7, t=0.6, doorW=4.2;
  var ry=o.ry||0;
  var g=new T.Group(); g.position.set(o.x,0,o.z); g.rotation.y=ry;
  function box(w,h,d,mat,x,y,z){
    var m=new T.Mesh(new T.BoxGeometry(w,h,d),mat);
    m.position.set(x,y,z); g.add(m); return m;
  }
  function solid(lx,lz,w,d,y0,y1){
    var c=Math.cos(ry), s=Math.sin(ry);
    foot.push([o.x+lx*c+lz*s, o.z-lx*s+lz*c, w, d, y0, y1, ry]);
  }
  // shell
  box(W,0.5,D,M.floor, 0,0.25,0);
  box(W,0.5,D,M.ceil, 0,H+0.25,0);
  box(W,H,t,M.wall, 0,H/2,-D/2); solid(0,-D/2,W,t,0,H);
  box(t,H,D,M.wall, -W/2,H/2,0); solid(-W/2,0,t,D,0,H);
  box(t,H,D,M.wall, W/2,H/2,0); solid(W/2,0,t,D,0,H);
  var segW=(W-doorW)/2;
  box(segW,H,t,M.glass, -(doorW/2+segW/2),H/2,D/2); solid(-(doorW/2+segW/2),D/2,segW,t,0,H);
  box(segW,H,t,M.glass, (doorW/2+segW/2),H/2,D/2); solid((doorW/2+segW/2),D/2,segW,t,0,H);
  box(doorW,1.4,t,M.glass, 0,H-0.7,D/2);
  box(0.5,H,t+0.35,M.gold, -doorW/2,H/2,D/2);
  box(0.5,H,t+0.35,M.gold, doorW/2,H/2,D/2);
  box(doorW+0.6,0.5,t+0.35,M.gold, 0,H-0.25,D/2);
  // sign (gold letters)
  var sign=new T.Mesh(new T.PlaneGeometry(13,3.2),
    new T.MeshBasicMaterial({map:M.sign(o.name)}));
  sign.position.set(0,H+2.4,D/2+0.5); g.add(sign);
  // awning
  var awn=box(W*0.92,0.22,3.6,M.awn, 0,H-1.4,D/2+1.9); awn.rotation.x=0.28;
  // ceiling light strips
  [-4.5,4.5].forEach(function(lx){ box(3.2,0.14,1.1,M.strip, lx,H-0.12,0); });
  // trade fit-out
  o.fit(box, solid, M);
  root.add(g);
  return g;
}
// ---- fixture kit (shared) ----
function fxShelf(box,solid,M,x,z,w,prods){
  var d=1.1;
  box(w,2.6,0.18,M.shelf, x,1.3,z-d/2);
  [0.7,1.45,2.2].forEach(function(sy){
    box(w,0.12,d,M.shelf, x,sy,z);
    var n=Math.max(2,Math.floor(w/1.6));
    for(var i=0;i<n;i++){
      var px=x-w/2+0.8+i*(w-1.6)/(n-1);
      box(1.1,0.55,0.85,prods[(i+((x*7)|0))%prods.length], px,sy+0.34,z);
    }
  });
  solid(x,z,w,d,0,2.6);
}
function fxCounter(box,solid,M,x,z,w){
  box(w,1.1,1.6,M.counter, x,0.55,z);
  box(w+0.3,0.14,1.9,M.gold, x,1.16,z);
  box(0.9,0.5,0.7,M.register, x+w/2-1.2,1.45,z); // register
  solid(x,z,w,1.6,0,1.2);
}
function buildRetailRow(T, root, foot, o) {
  var R=o.R;
  // materials
  var M={
    gold:o.gold,
    wall:new T.MeshLambertMaterial({color:0x2e3238}),
    floor:new T.MeshLambertMaterial({color:0x3d4149}),
    ceil:new T.MeshLambertMaterial({color:0x22262c}),
    glass:new T.MeshLambertMaterial({color:0x9fc4e8,transparent:true,opacity:0.4}),
    awn:new T.MeshLambertMaterial({color:0x8a2a3a}),
    strip:new T.MeshBasicMaterial({color:0xffe8c0}),
    shelf:new T.MeshLambertMaterial({color:0x5a4028}),
    counter:new T.MeshLambert