<!-- SOLID CITY · part 2977 -->
    var rec = { x: f.x, z: f.z };
    if (palm) {
      cyl(solid, f, 0.16, 0.24, 5.6, 6, 0, 2.8, 0, C.trunk, 0.12, 0, 0.06);
      for (var k = 0; k < 6; k++) {
        var aa = k / 6 * Math.PI * 2;
        box(solid, f, 3.6, 0.07, 0.7, Math.cos(aa) * 1.6, 5.9 - Math.abs(Math.sin(aa)) * 0.3, Math.sin(aa) * 1.6, C.leafLight, 0, -aa, 0.35);
      }
    } else {
      cyl(solid, f, 0.22, 0.34, 3.1, 6, 0, 1.55, 0, C.trunk);
      sph(solid, f, 2.6, 0, 4.6, 0, C.leaf, 1, 0.85, 1);
      sph(solid, f, 1.8, 1.4, 3.8, 0.7, C.leafLight, 1, 0.8, 1);
    }
    footprints.push({ x: f.x, z: f.z, w: 0.7, d: 0.7, a: f.a, y0: BASE, y1: BASE + 3 });
    trees.push(rec);
  }
  function buildGarden(f, r, ring2) {
    disc(solid, f, r, 0.045, C.lawn);
    if (ring2) disc(solid, f, r * 0.62, 0.06, C.lawnDeep);
    for (var k = 0; k < 9; k++) {
      var aa = R() * Math.PI * 2, rr = r * (0.35 + R() * 0.55);
      box(glow, f, 0.55, 0.3, 0.55, Math.cos(aa) * rr, 0.18, Math.sin(aa) * rr, [C.flower1, C.flower2, C.flower3][k % 3]);
    }
  }
  function buildFountain(f) {
    cyl(solid, f, 5.2, 5.6, 0.85, 18, 0, 0.43, 0, C.stone);
    cyl(solid, f, 4.5, 4.5, 0.3, 18, 0, 0.78, 0, C.pool);
    cyl(solid, f, 0.35, 0.5, 2.6, 8, 0, 1.7, 0, C.silver);
    sph(glow, f, 0.65, 0, 3.3, 0, C.gold);
    footprint(f, 10.6, 10.6, BASE, BASE + 0.9);
    return record('', 'fountain', f, '');
  }
  function buildLamp(f) {
    cyl(solid, f, 0.09, 0.13, 3.6, 6, 0, 1.8, 0, C.titanium);
    sph(glow, f, 0.32, 0, 3.8, 0, C.gold);
    footprints.push({ x: f.x, z: f.z, w: 0.3, d: 0.3, a: f.a, y0: BASE, y1: BASE + 3.6 });
  }

  /* ---------- the laying-out: bands between the roads ---------- */
  function angleDiff(a, b) { var d = Math.abs(a - b) % (Math.PI * 2); return d > Math.PI ? Math.PI * 2 - d : d; }
  /* 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. */
  [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);
  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) {
    if (angleDiff(angle, Math.PI / 2) < 0.15) return;
    var rec = buildHouse(frame(radius, angle), district, style, floors);
    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(f