<!-- NEW2 — TEST 2 · THE DISTRICT OF 800 · part 8 -->
eFigure(THREE, rng, { shirt: 0xd8a944, pants: 0x1c1c22 });
  const group = rig.root;
  group.visible = false;

  const king = {
    group,
    x: 0, z: 0, yaw: Math.PI, phase: 0, t: 0,
    input: { fwd: false, back: false, left: false, right: false },
    boomH: 4.2, boomD: 8.5,
    colliders: [],
    BOOM_MIN_Y: 1.4,
  };

  /* ---------- collision, measured from the standing city ---------- */
  king.buildColliders = function (cityGroup) {
    // Measure the city AS IT STANDS: refresh every world matrix
    // first, or nested pieces (a lamp's parts, a bridge's slabs)
    // report their local boxes and pile up at the origin.
    cityGroup.updateWorldMatrix(true, true);
    const box = new THREE.Box3();
    const list = [];
    cityGroup.traverse((o) => {
      if (!o.isMesh) return;
      box.setFromObject(o);
      const sx = box.max.x - box.min.x, sy = box.max.y - box.min.y, sz = box.max.z - box.min.z;
      // tall and solid: towers, houses, trees. Roads, stalls, curbs
      // and water lie below the line and never block a king — and
      // neither do the bridge decks: a deck's crown (top ~2.4) is a
      // floor to walk over, not a wall. Only solids rising past
      // step-over height (3.2) earn the right to stop him.
      if (sy > 2.2 && box.max.y > 3.2 && sx > 0.7 && sz > 0.7 && box.min.y < 1.5) {
        list.push({ minX: box.min.x, maxX: box.max.x, minZ: box.min.z, maxZ: box.max.z, top: box.max.y });
      }
    });
    king.colliders = list;
    return list.length;
  };
  function hitsCollider(x, z) {
    for (const b of king.colliders) {
      if (x > b.minX - BODY_R && x < b.maxX + BODY_R && z > b.minZ - BODY_R && z < b.maxZ + BODY_R) return b;
    }
    return null;
  }
  function inWater(x, z) {
    if (!meta.riverBand) return false; // Test 2 is only city — no water to refuse him
    const band = meta.riverBand;
    if (z <= band.zMin + 0.4 || z >= band.zMax - 0.4) return false;
    return !meta.bridges.some((bx) => Math.abs(bx - x) < 6.5);
  }

  /* Test 2's city is MERGED geometry — one mesh holds a hundred
   * buildings — so collision comes from the LIST itself: every
   * building's true footprint, box for box. */
  king.setCollidersFromList = function (buildings) {
    king.colliders = buildings.map((b) => ({
      minX: b.x - b.w / 2, maxX: b.x + b.w / 2,
      minZ: b.z - b.d / 2, maxZ: b.z + b.d / 2,
      top: b.h,
    }));
    return king.colliders.length;
  };

  /* ---------- placement + control ---------- */
  king.spawn = function (x, z, yaw) {
    king.x = x; king.z = z; king.yaw = yaw;
    group.position.set(x, 0, z);
    group.rotation.y = yaw;
    group.visible = true;
  };
  king.hide = function () { group.visible = false; };
  king.look = function (dYaw) { king.yaw += dYaw; };
  king.lift = function (dH) { king.boomH = Math.min(8, Math.max(2.2, king.boomH + dH)); };

  king.update = function (dt) {
    king.t += dt;
    const inp = king.input;
    if (inp.left) king.yaw += TURN_RATE * dt;
    if (inp.right) king.yaw -= TURN_RATE * dt;
    const fwd = (inp.fwd ? 1 : 0) - (inp.back ? 0.55 : 0);
    let moved = 0;
    if (fwd !== 0) {
      const dx = Math.sin(king.yaw) * fwd, dz = Math.cos(king.yaw) * fwd;
      const step = WALK_SPEED * dt;
      // axis-separated: slide along walls instead of sticking to them
      const nx = king.x + dx * step;
      if (!hitsCollider(nx, king.z) && !inWater(nx, king.z)) { king.x = nx; moved = step; }
      const nz = king.z + dz * step;
      if (!hitsCollider(king.x, nz) && !inWater(king.x, nz)) { king.z = nz; moved = step; }
      // the world's rim: the district apron, no farther
      const rimX = meta.district ? meta.district.w / 2 + 320 : 330;
      const rimZ = meta.district ? meta.district.d / 2 + 320 : 290;
      king.x = Math.max(-rimX, Math.min(rimX, king.x));
      king.z = Math.max(-rimZ, Math.min(rimZ, king.z));
    }
    // On a bridge his feet ride the deck's rise (a smooth crown over
    // the band's middle); everywhere else the stand layer is flat law.
    let lift = 0;
    const band = meta.riverBand;
    if (band && king.z > band.zMin && king.z < band.zMax && meta.bridges.some((bx) => Math.abs(bx - king.x) < 6.5)) {
      const b = 1 - (king.z / ((band.zMax - band.zMin) / 2)) ** 2;
      lift = 1.3 * Math.max(0, b);
    }
    group.position.set(king.x, lift, king.z);
    group.rotation.y = king.yaw;
    if (moved > 0) {
      king.phase += moved * gait.walk.phasePerUnit;
      poses.walk(rig, king.phase, 1);
    } else {
      poses.idle(rig, king.t, 0.8);
    }
    return { x: king.x, z: king.z, yaw: king.yaw };
  };

  /* ---------- the street camera: behind him, smoothed, fenced ---- */
  const _want = new THREE.Vector3(), _look = new THREE.Vector3();
  king.boom = function (camera, dt) {
    const fx = Math.sin(king.yaw), fz = Math.cos(king.yaw);
    _want.set(king.x - fx * king.boomD, king.boomH, king.z - fz * king.boomD);
    // the camera may 