<!-- SOLID CITY · part 3104 -->
(solid, W + 1.2 * s, 0.5 * s, D + 1.2 * s, L(0, Hh + 0.25 * s, 0), C.stoneDark);
    if (floors > 1) box(solid, W * 0.7, 0.4 * s, D * 0.7, L(0, Hh + 0.7 * s, 0), C.roof);
    box(glow, 1.3 * s, 2.3 * s, 0.18, L(0, 1.15 * s, -D / 2 - 0.06), C.door);
    box(solid, W * 0.66, 0.22 * s, 2.6 * s, L(0, 0.11 * s, -D / 2 - 1.6 * s), C.stoneDark);
    [-1, 1].forEach(function (sgn) { box(glow, 1.1 * s, 1 * s, 0.14, L(sgn * W * 0.3, 1.9 * s, -D / 2 - 0.05), C.win); });
    if (floors > 1) [-1, 1].forEach(function (sgn) { box(glow, 1.1 * s, 1 * s, 0.14, L(sgn * W * 0.28, Hh - 1.1 * s, -D / 2 - 0.05), C.win); });
    footprints.push({ x: fr.x, z: fr.z, w: W + 0.6, d: D + 3.4 * s, a: Math.atan2(fr.tx, fr.tz), y0: y, y1: y + Hh + 1 });
    return M;
  }
  function stall(fr, y, tint) {
    function L(lx, ly, lz) { return mat4(fr.x + fr.tx * lx + fr.rx * lz, y + ly, fr.z + fr.tz * lx + fr.rz * lz, 0, Math.atan2(fr.tx, fr.tz), 0); }
    box(solid, 3.4, 1.05, 1.1, L(0, 0.52, 0), C.stoneDark);
    [-1.5, 1.5].forEach(function (lx) { box(solid, 0.14, 2.5, 0.14, L(lx, 1.25, -0.4), C.trunk); });
    box(solid, 4.1, 0.14, 2.2, L(0, 2.55, 0.1), tint);
    for (var i = 0; i < 3; i++) sph(glow, 0.3, L(-1 + i, 1.25, 0), i % 2 ? C.vialG : C.lamp);
    footprints.push({ x: fr.x, z: fr.z, w: 4, d: 2.4, a: Math.atan2(fr.tx, fr.tz), y0: y, y1: y + 2.2 });
  }
  /* formations of the deep: stalactites above, stalagmites below */
  function formation(x, y, z, s, hang) {
    if (hang) cone(solid, 0.9 * s, 3.8 * s, 7, mat4(x, y - 1.9 * s, z, Math.PI, 0, 0), C.basalt);
    else cone(solid, 1.0 * s, 3.0 * s, 7, mat4(x, y + 1.5 * s, z, 0, 0, 0), C.basalt);
    cone(solid, 0.5 * s, 1.8 * s, 6, mat4(x + 0.8 * s, hang ? y - 0.9 * s : y + 0.9 * s, z + 0.4 * s, hang ? Math.PI : 0, 0, 0), C.marbleRed);
  }
  var layers = [];   // {cx, cz, rIn, rOut, y} standable ring terraces
  var crystals = [];

  function contourR(cx, cz, a, yTarget) {
    for (var r = 138; r < 212; r += 3) { if (H(cx + Math.cos(a) * r, cz + Math.sin(a) * r) > yTarget) return r; }
    return 212;
  }
  function buildCity(Cc, big) {
    var F = Cc.f, cx = Cc.x, cz = Cc.z;
    marbleDisc(cx, F, cz, 32, marbleBlack, 4);
    cyl(glow, 32.6, 32.6, 0.18, 40, mat4(cx, F + 0.3, cz, 0, 0, 0), C.gold);
    cyl(solid, 47, 47, 0.14, 44, mat4(cx, F + 0.07, cz, 0, 0, 0), C.stoneDark);   // ring road
    /* the lava cloth hung on the hollow's wall (Plate I) —
     * and when the image has been rayscanned, the skirt is
     * BAKED OUT OF THE IMAGE ITSELF: folded concave and
     * convex, crystallized, and given collision, so the
     * folded wall is a wall in law as well as in looks */
    if (lavaTex) {
      var hiG = opts.texTier !== 'lo';
      var skirtGeo = new T.CylinderGeometry(149.5, 141.2, 58, hiG ? 168 : 80, hiG ? 12 : 6, true);
      if (HEIGHT) displace(skirtGeo, 12, 2, 1.0);
      var skirt = new T.Mesh(skirtGeo, lavaMat(12, 2, T.BackSide, !!HEIGHT));
      skirt.position.set(cx, F + 21, cz); skirt.name = 'lava-skirt'; skirt.frustumCulled = false; group.add(skirt);
      if (HEIGHT) for (var sa = 0; sa < Math.PI * 2; sa += Math.PI / 18) {
        footprints.push({ x: cx + Math.cos(sa) * 146.5, z: cz + Math.sin(sa) * 146.5, w: 26.5, d: 8, a: -sa, y0: F, y1: F + 46 });
      }
    }
    /* the plaza crystal — standing cluster for the Deep,
     * hanging heart for the First (added by caller) */
    var skipA = Cc === A_C ? [Math.PI / 2] : [-Math.PI / 2];       // the gallery mouth sector
    var skipB = Cc === A_C ? [2.36] : [];                          // the Entree sector
    function clear(a) {
      for (var i = 0; i < skipA.length; i++) { var d = Math.abs(((a - skipA[i] + Math.PI * 3) % (Math.PI * 2)) - Math.PI); if (d < 0.42) return false; }
      for (var j = 0; j < skipB.length; j++) { var d2 = Math.abs(((a - skipB[j] + Math.PI * 3) % (Math.PI * 2)) - Math.PI); if (d2 < 0.34) return false; }
      return true;
    }
    var nH = 0;
    for (var hi = 0; hi < 14 && nH < 10; hi++) {
      var ha = hi / 14 * Math.PI * 2 + 0.22;
      if (!clear(ha)) continue;
      var hr = 62 + (hi % 3) * 22;
      house(frameOf(hr, ha, cx, cz), F, 1 + (hi % 2) * 0.2, hi % 3 === 0 ? 2 : 1); nH++;
    }
    /* the grand house of the hollow */
    var ga = Cc === A_C ? 5.5 : 0.85;
    var gf = frameOf(98, ga, cx, cz);
    (function () {
      function L(lx, ly, lz) { return mat4(gf.x + gf.tx * lx + gf.rx * lz, F + ly, gf.z + gf.tz * lx + gf.rz * lz, 0, Math.atan2(gf.tx, gf.tz), 0); }
      box(solid, 24, 11, 13, L(0, 5.5, 0), C.stone);
      box(solid, 26, 0.8, 15, L(0, 11.4, 0), C.stoneDark);
      box(solid, 16, 5, 10, L(0, 13.5, 0), C.stone);
      box(solid, 17.5, 0.7, 11.5, L(0, 16.3, 0), C.roof);
      box(glow, 2.6, 4.6, 0.2, L(0, 2.3, -6.6), C.door);
      for (var wI = -3; wI <= 3; wI++) { if (wI) box(glow, 1.4, 1.6, 0.16, L(wI * 3.1, 7.6, -6.58), C.win); }
      box(glow, 20, 0.5, 0.3, L(0, 10.6, -6.7), C.gold);
      footprints.push({ x: gf.x, z: gf.z, w