<!-- NEW5 — TEST 5 · THE BEND AT THE HEART · part 7 -->
.z);
        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/new5/enterw.js =====
/* enterw.js — THE WAY IN for the investigation worlds (new3-new6).
 * Ported faithfully from Test 2's proven enter.js — same figure, same
 * pads, same boom — with the ground law grown for whole worlds:
 *   - Collision comes from the world's building LIST (every kit reports
 *     its boxes), never from imagined geometry.
 *   - Feet ride the world's own ground: 0.02 on land, the deck profile
 *     (meta.deckAt) on bridges.
 *   - The water law binds kings too: open water (meta.inWater) refuses
 *     him unless a deck carries him (deckAt >= 2).
 * Contract mirrors Test 2: makeKing(THREE, pieces, meta) -> king with
 * spawn/hide/input/look/lift/update/boom/setCollidersFromList.
 */
'use strict';

const WALK_SPEED = 9;
const TURN_RATE = 2.4;
const BODY_R = 0.55;

function makeKing(THREE, pieces, meta) {
  const { makeFigure, poses, gait } = pieces;
  let seed = 777;
  const rng = () => { seed |= 0; seed = seed + 0x6D2B79F5 | 0; let t = Math.imul(seed ^ seed >>> 15, 1 | seed); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; };
  const rig = makeFigure(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,
  };
  const groundAt = (x, z) => Math.max(0.02, meta.deckAt ? meta.deckAt(x, z) : 0);
  king.setCollidersFromList = function (buildings) {
    king.colliders = buildings.filter(b => b.h > 3.2).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;
  };
  function hitsCollider(x, z) {
    for (const b of king.colliders) {
      if (