<!-- NEW2 — TEST 2 · THE DISTRICT OF 800 · part 7 -->
 faceToward(c.rig.root, p.dx, p.dz);
        poseGait(c.rig, c.phase, 0.95, 0.22, 1.25);
      } else if (c.kind === 'bike') {
        c.s += c.speed * dt;
        c.phase += dt * (c.speed / 0.34) * 0.55; // pedal cadence from wheel speed
        const p = c.path.at(c.s);
        c.holder.position.set(p.x, 0, p.z);
        faceToward(c.holder, p.dx, p.dz);
        c.holder.rotation.z = Math.sin(c.phase * 0.5) * 0.015;
        const spin = (c.speed / 0.34) * dt;
        c.bike.wF.rotation.x += spin;
        c.bike.wB.rotation.x += spin;
        posePedal(c.rig, c.phase);
      } else if (c.kind === 'foot') {
        const dx = c.tx - c.x, dz = c.tz - c.z;
        const dist = Math.hypot(dx, dz);
        let moving = 0;
        if (dist > 0.25) {
          const step = Math.min(dist, c.speed * dt);
          c.x += (dx / dist) * step; c.z += (dz / dist) * step;
          c.phase += dt * c.speed * 3.1;
          moving = 1;
          faceToward(c.rig.root, dx / dist, dz / dist);
        } else if ((c.wait -= dt) <= 0) {
          newTarget(c); c.wait = 0.6 + rng() * 2.2;
        }
        c.rig.root.position.set(c.x, 0, c.z);
        if (moving) poseGait(c.rig, c.phase, 0.7, 0.13, 0.95);
        else { // idle: breathe, shift weight, watch the game
          poseIdle(c.rig, c.phase * 0.25, 1); // phase ticks 4x/s; /4 = seconds
          c.phase += dt * 4;
        }
      }
    }

    /* the ball: rests at the holder's feet, then a kicked pass arcs over */
    if (game.flying) {
      const f = game.flying;
      f.k += dt / f.dur;
      if (f.k >= 1) {
        game.holder = f.to; game.flying = null; game.rest = 0.9 + rng() * 1.6;
        ball.position.set(f.to.x, 0.16, f.to.z);
      } else {
        const x = f.x0 + (f.x1 - f.x0) * f.k;
        const z = f.z0 + (f.z1 - f.z0) * f.k;
        const y = 0.16 + Math.sin(f.k * Math.PI) * f.h;
        ball.position.set(x, y, z);
        ball.rotation.x += dt * 7;
      }
    } else {
      const h = game.holder;
      ball.position.set(h.x + Math.sin(h.rig.root.rotation.y) * 0.35, 0.16,
                        h.z + Math.cos(h.rig.root.rotation.y) * 0.35);
      if ((game.rest -= dt) <= 0) {
        let to = h;
        while (to === h) to = footies[Math.floor(rng() * footies.length)];
        const d = Math.hypot(to.x - h.x, to.z - h.z);
        game.flying = {
          x0: ball.position.x, z0: ball.position.z, x1: to.x, z1: to.z,
          k: 0, dur: Math.max(0.45, d * 0.09), h: 0.5 + d * 0.08, to,
        };
        newTarget(to); // receiver shuffles to meet it
      }
    }
  }

  return { group, update };
}

/* Export both ways: page module script and bundler-style.
 * makeCitizens is the crowd whole; makeFigure, makeBike, poses and
 * gait are the same craft in pieces, for the life director to drive. */
const EXPORTS = { makeCitizens, makeFigure, makeBike, poses, gait };
if (typeof module !== 'undefined' && module.exports) module.exports = EXPORTS;
if (typeof window !== 'undefined') Object.assign(window, EXPORTS);


===== FILE: public/new2/enter.js =====
/* enter.js — THE WAY IN for the King's /new1 test.
 *
 * One figure in the city belongs to no schedule: the King's own.
 * This piece builds it from the same nerves as the citizens, walks
 * it on the stand layer under tappable control, and holds the two
 * laws of the street:
 *   - What you SEE is what stops you. Collision comes from the
 *     rendered city's own boxes — towers, houses, trees — measured,
 *     not imagined.
 *   - The river law binds kings too: the water band may be entered
 *     only on a bridge street.
 *
 * Contract: makeKing(THREE, pieces, meta) -> king
 *   pieces — citizens.js { makeFigure, poses, gait }
 *   meta   — city-layout.js meta (for the river band + bridges)
 *   king.buildColliders(cityGroup)  — measure the standing city
 *   king.spawn(x, z, yaw)           — place him, standing at his door
 *   king.group                      — add to the scene (at standY)
 *   king.input {fwd, back, left, right} — the page's pads write here
 *   king.look(dYaw) / king.lift(dH) — drag-look from the page
 *   king.update(dt)                  — walk + animate; returns pos
 *   king.boom(camera, dt)            — the street camera, behind him,
 *                                      smoothed and fenced
 */

'use strict';

function mulberry32(seed) {
  let a = seed >>> 0;
  return function () {
    a |= 0; a = (a + 0x6D2B79F5) | 0;
    let t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

const WALK_SPEED = 7;        // units per second — a king's stride among citizens
const TURN_RATE = 2.4;       // radians per second on the turn pads
const BODY_R = 0.55;         // his shoulder width against the world

function makeKing(THREE, pieces, meta) {
  const { makeFigure, poses, gait } = pieces;
  const rng = mulberry32(777);
  const rig = mak