<!-- SOLID CITY · part 2959 -->
e heart of the city is glass, so whoever
     * stands here sees the terrace city turning below; a stone
     * rim carries the Family Ring; and the keel is ringed in
     * gold at the five road radii, so from the terrace the twin
     * reads in the sky exactly as the roads read on the ground. */
    var cf = frame(0, 0);
    disc(glassB, cf, 100, -0.03, C.glass);
    glassB.add(new T.RingGeometry(100, 470, 64), localMatrix(cf, 0, -0.03, 0, -Math.PI / 2, 0, 0), C.glass);
    solid.add(new T.RingGeometry(470, 545, 64), localMatrix(cf, 0, -0.04, 0, -Math.PI / 2, 0, 0), C.stoneDark);
    solid.add(new T.CylinderGeometry(545, 552, 7, 64, 1, true), localMatrix(cf, 0, -3.5, 0, 0, 0, 0), C.stoneDark);
    glow.add(new T.TorusGeometry(545, 0.3, 6, 72), localMatrix(cf, 0, -0.05, 0, Math.PI / 2, 0, 0), C.gold);
    [130, 210, 290, 370, 450].forEach(function (rr) {
      glow.add(new T.TorusGeometry(rr, 0.22, 5, 64), localMatrix(cf, 0, -7.15, 0, Math.PI / 2, 0, 0), C.gold);
    });
    cyl(solid, cf, 3.2, 4.2, 6.8, 12, 0, -3.6, 0, C.titanium);
    /* RAIN POOLS (the King's "All", 2026-10-14): shallow
     * shining pools in the gardens of the glass city, where
     * the Crown's rain gathers and is seen. */
    var poolSpots = [[170, 5.45, 5.5], [250, 1.5, 6], [330, 0.02, 6.5], [410, 2.72, 7], [492, 2.28, 6.5], [330, 5.52, 5.5]];
    poolSpots.forEach(function (ps) {
      var pf = frame(ps[0], ps[1]);
      cyl(solid, pf, ps[2], ps[2] + 0.5, 0.24, 20, 0, 0.02, 0, C.stone);
      cyl(solid, pf, ps[2] - 0.7, ps[2] - 0.7, 0.1, 20, 0, 0.2, 0, C.pool);
    });
    group.userDataPools = poolSpots.length;
  }
  /* radial walks — pale stone laid over the terrace, passing
   * under the ring roads at every crossing, so the whole city
   * can be walked from the flame to the rim. In the sky twin
   * the glass floor itself is the walk; only the processional's
   * gold inlay carries over. */
  if (!SKY) [0, Math.PI, Math.PI * 1.5].forEach(function (a) {
    var f = frame(275, a);
    box(solid, f, 5, 0.05, 505, 0, 0.025, 0, C.conc);
  });
  var proc = frame(275, Math.PI / 2);
  if (!SKY) box(solid, proc, 7, 0.05, 505, 0, 0.026, 0, C.stone);
  box(glow, proc, 0.5, 0.06, 505, -3.4, 0.03, 0, C.gold);
  box(glow, proc, 0.5, 0.06, 505, 3.4, 0.03, 0, C.gold);
  function lampAt(radius, angle, tangentOff) {
    var f = frame(radius, angle);
    f.x += f.tx * tangentOff; f.z += f.tz * tangentOff;
    buildLamp(f);
  }
  [150, 230, 310, 390, 470].forEach(function (rr) { lampAt(rr, Math.PI / 2, -5.2); lampAt(rr, Math.PI / 2, 5.2); });

  var DISTRICTS = {
    hearth: 'THE FIRST HEARTH', voyagers: "THE VOYAGERS' RING", chiefs: "THE CHIEFS' RING",
    unifiers: "THE UNIFIERS' RING", builders: "THE BUILDERS' RING", family: 'THE FAMILY RING'
  };
  var houseNo = 0;
  function house(radius, angle, district, style, floors, sizeF) {
    if (angleDiff(angle, Math.PI / 2) < 0.15) return;
    var rec = buildHouse(frame(radius, angle), district, style, floors, sizeF);
    rec.name = district + ' HOUSE ' + (++houseNo);
  }
  function pavilion(radius, angle, district, big) {
    var rec = buildPavilion(frame(radius, angle), district, big);
    rec.name = district + ' PAVILION'; rec.district = district;
  }

  /* THE FIRST HEARTH — gardens and quiet around the flame */
  buildGarden(frame(64, 1.9), 15, true);
  buildGarden(frame(88, 2.8), 12, false);
  var fh = buildFountain(frame(70, 0.7)); fh.name = 'THE FIRST HEARTH FOUNTAIN'; fh.district = DISTRICTS.hearth;
  pavilion(80, 3.6, DISTRICTS.hearth, false);
  house(82, 5.3, DISTRICTS.hearth, 1, 1);

  /* THE VOYAGERS' RING (r 170, between the first two roads) */
  [0.25, 1.15, 2.75, 3.65, 5.15].forEach(function (a, i) { house(170, a, DISTRICTS.voyagers, i, i === 2 ? 2 : 1); });
  pavilion(170, 4.55, DISTRICTS.voyagers, false);
  buildGarden(frame(170, 2.05), 16, true);
  buildGarden(frame(170, 5.9), 14, false);

  /* THE CHIEFS' RING (r 250) */
  [0.05, 0.95, 2.25, 3.15, 5.45].forEach(function (a, i) { house(250, a, DISTRICTS.chiefs, i + 1, i === 3 ? 2 : 1); });
  var mg = buildGrand(frame(250, 4.25), DISTRICTS.chiefs, 'mansion', "THE FLAMEKEEPER'S MANSION");
  pavilion(250, 5.95, DISTRICTS.chiefs, true);
  buildGarden(frame(250, 1.55), 17, true);

  /* THE UNIFIERS' RING (r 330) */
  [0.45, 2.85, 3.95, 5.0, 5.95].forEach(function (a, i) { house(330, a, DISTRICTS.unifiers, i + 2, i === 1 ? 2 : 1); });
  var hg1 = buildGrand(frame(330, 1.95), DISTRICTS.unifiers, 'hotel', "THE CHIEFS' HOUSE HOTEL");
  pavilion(330, 4.5, DISTRICTS.unifiers, false);
  buildGarden(frame(330, 0.0), 17, true);
  buildGarden(frame(330, 5.55), 15, false);

  /* THE BUILDERS' RING (r 410) */
  [0.15, 1.0, 2.1, 3.3, 4.15, 5.25, 6.05].forEach(function (a, i) { house(410, a, DISTRICTS.builders, i, i === 4 ? 2 : 1); });
  var mg2 = buildGrand(frame(410, 5.9), DISTRICTS.builders, 'mansion', "THE BUILDERS' MANSION");
  pavilion(410, 4.7, DISTRICTS.builders, true);
  buildGarden(frame(410, 2.75), 18, 