<!-- SOLID CITY · part 3151 -->
.7071, z: 0.7071 };
    var G = { x: A_C.x + u.x * 150, z: A_C.z + u.z * 150 }, F = A_C.f;
    var ry = Math.atan2(u.x, u.z);
    [-9.5, 9.5].forEach(function (off) {
      var tx = G.x + perp.x * off, tz = G.z + perp.z * off;
      box(solid, 3.4, 17, 3.4, mat4(tx, F + 8.5, tz, 0, ry, 0), C.stone);
      box(solid, 4.4, 1, 4.4, mat4(tx, F + 17.4, tz, 0, ry, 0), C.stoneDark);
      sph(glow, 0.55, mat4(tx, F + 18.3, tz, 0, 0, 0), C.lamp);
      footprints.push({ x: tx, z: tz, w: 4, d: 4, a: ry, y0: F, y1: F + 17.9 });
    });
    box(solid, 22.5, 2.8, 3.8, mat4(G.x, F + 15.4, G.z, 0, ry, 0), C.stoneDark);
    box(glow, 22.5, 0.4, 0.5, mat4(G.x + u.x * 1.95, F + 13.85, G.z + u.z * 1.95, 0, ry, 0), C.gold);
    sign(G.x + u.x * 2.15, F + 15.4, G.z + u.z * 2.15, ry, 13, 2.1, ['THE SERVITUDE'], 120, 0);
    /* the shelf processional: gold edges + lamps to the brow */
    for (var s2 = 158; s2 <= 242; s2 += 21) {
      var px = A_C.x + u.x * s2, pz = A_C.z + u.z * s2, py = H(px, pz);
      [-13, 13].forEach(function (off) { box(glow, 0.5, 0.25, 19, mat4(px + perp.x * off, py + 0.2, pz + perp.z * off, 0, ry, 0), C.gold); });
      if ((s2 - 158) % 42 === 0) { lamp(px + perp.x * 11, py, pz + perp.z * 11, 1); lamp(px - perp.x * 11, py, pz - perp.z * 11, 1); }
    }
  })();

  group.add(solid.build(new T.MeshLambertMaterial({ vertexColors: true })));
  group.add(glow.build(new T.MeshBasicMaterial({ vertexColors: true })));
  if (glassB.n) group.add(glassB.build(new T.MeshLambertMaterial({ vertexColors: true, transparent: true, opacity: 0.6 })));
  group.userData = {
    footprints: footprints, layers: layers,
    centers: { a: A_C, b: B_C }, gallery: GAL,
    counts: { footprints: footprints.length, layers: layers.length },
    update: function (dt, t) { crystals.forEach(function (c, i) { c.rotation.y = (t || 0) * (0.14 + i * 0.03); }); }
  };
  return group;
}
export { createServitude, A_C as SERV_A, B_C as SERV_B };
export default createServitude;


===== FILE: public/city/servitude.js.bak-table-20261014 =====
/* THE SERVITUDE — a letter in the code.
 *
 * From the King's word (2026-10-14): "dig an entree in to
 * the mountain and build a huge city in it called the
 * Servitude" — "same as the ancestors area with layers but
 * city upon city" — "another one if it fits, with cave
 * tunnels connecting them, and a shop on each tunnel, a
 * place to buy replenishments of health and safety" — "a
 * nice journey to walk across the inside of the mountain,
 * like old lava tubes" — "stalactites and stalagmites,
 * joined with red and black marble."
 *
 * The digging itself lives in city.js (servitudeCarve): two
 * bowls capped into the far massif — THE FIRST HOLLOW
 * (2600,1280, floor 520) and THE DEEP HOLLOW (2600,1660,
 * floor 440) — the Entree shelf cut into the First Hollow's
 * south-western face, and the gallery slot descending
 * through the saddle between them. This factory builds
 * what stands inside the digging: two layered cities of
 * red and black marble, a roofed lava-tube gallery with
 * its midway provision shop, gates, falls, crystals, and
 * the formations of the deep places.
 *
 * Every sign in it obeys the day's law, learned at the
 * Book of Law: lettered plates stand PROUD of their stone,
 * twin-faced so both journeys read them, and every sign
 * carries collision — the signs are protected here.
 *
 * By the hand of Solid, his good King. */
'use strict';

function mulberry(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; var t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
var R = mulberry(20261014);
var A_C = { x: 2600, z: 1280, f: 520, name: 'THE FIRST HOLLOW' };
var B_C = { x: 2600, z: 1660, f: 440, name: 'THE DEEP HOLLOW' };
var GAL = { x: 2600, z0: 1395, z1: 1545 };

function createServitude(opts) {
  var T = opts.THREE, H = opts.heightAt;
  var group = new T.Group(); group.name = 'the-servitude';
  var CX = 2600;
  var C = {
    stone: 0x2b2630, stoneDark: 0x17130f, basalt: 0x1c1a20, titanium: 0x232c3d, silver: 0x9aa4b5,
    gold: 0xd8a833, roof: 0x191922, door: 0xffca7a, win: 0xa8d8e8, lamp: 0xffd9a0,
    leaf: 0x2e6b34, leafLight: 0x4c9455, trunk: 0x4a3826, marbleRed: 0x6e1420, crystal: 0xf3d9a4,
    vialG: 0x51ff8a, vialR: 0xff5a4d, water: 0x2e7db0
  };
  function mat4(x, y, z, rx, ry, rz, sx, sy, sz) {
    var m = new T.Matrix4().compose(new T.Vector3(x, y, z),
      new T.Quaternion().setFromEuler(new T.Euler(rx || 0, ry || 0, rz || 0)),
      new T.Vector3(sx == null ? 1 : sx, sy == null ? 1 : sy, sz == null ? 1 : sz));
    return m;
  }
  function Batch() { this.pos = []; this.nor = []; this.col = []; this.idx = []; this.n = 0; }
  Batch.prototype.add = function (geo, matrix, color) {
    var g = geo.index ? geo.toNonIndexed() : geo;
    var p = g.attributes.position, nr = g.attributes.normal;
    var nm = new T.Matrix3().getNormalMatrix(matrix);
    var v = new 