<!-- SOLID CITY · part 2461 -->
up, 0, 1.7, 2, 1.8, 3.4, 1.8);
  mesh(CYL, MAT.stoneDark, group, 0, 3.36, 2, 2.15, 0.14, 2.15);
  mesh(CYL, MAT.gold, group, 0, 0.5, 2, 1.86, 0.1, 1.86);
  // the barn at x[-16,-2] z[9,13] — walls, gabled (unlandable) roof, door
  mesh(BOX, MAT.wood, group, -9, 1.3, 8.8, 14.4, 2.6, 0.35);
  mesh(BOX, MAT.wood, group, -9, 1.3, 13.2, 14.4, 2.6, 0.35);
  mesh(BOX, MAT.wood, group, -16.2, 1.3, 11, 0.35, 2.6, 4.9);
  mesh(BOX, MAT.wood, group, -1.8, 1.3, 11, 0.35, 2.6, 4.9);
  mesh(BOX, MAT.woodDark, group, -9, 2.6, 11, 14.4, 0.25, 4.9);
  var roofL = mesh(BOX, MAT.roof, group, -9, 3.95, 9.85, 15.2, 0.16, 3.6); roofL.rotation.x = 0.96;
  var roofR = mesh(BOX, MAT.roof, group, -9, 3.95, 12.15, 15.2, 0.16, 3.6); roofR.rotation.x = -0.96;
  mesh(BOX, MAT.dark, group, -4, 1.05, 8.6, 1.7, 2.1, 0.1);
  // the snag pole at (-10,-8)
  mesh(CYL, MAT.bark, group, -10, 1.55, -8, 0.3, 3.1, 0.3);
  mesh(CYL, MAT.woodDark, group, -10, 3.12, -8, 0.62, 0.06, 0.62);
  // the park shelter at (-7.5,-7) — flat roof: one more lawful landing
  [[-9.0, -8.1], [-6.0, -8.1], [-9.0, -5.9], [-6.0, -5.9]].forEach(function (p) {
    mesh(BOX, MAT.woodDark, group, p[0], 1.25, p[1], 0.18, 2.5, 0.18);
  });
  mesh(BOX, MAT.wood, group, -7.5, 2.53, -7, 3.9, 0.1, 3.0);
  mesh(BOX, MAT.gold, group, -7.5, 2.6, -7, 3.9, 0.03, 3.0);

  /* ---------------- observation deck, bench & the grove sign ---------- */
  mesh(BOX, MAT.woodDark, group, -3.5, 0.15, -10.5, 3.4, 0.3, 2.4);
  mesh(BOX, MAT.wood, group, -3.5, 0.34, -10.5, 3.5, 0.08, 2.5);
  mesh(BOX, MAT.wood, group, -3.5, 0.62, -10.9, 1.9, 0.09, 0.42);
  mesh(BOX, MAT.woodDark, group, -4.2, 0.42, -10.9, 0.09, 0.35, 0.4);
  mesh(BOX, MAT.woodDark, group, -2.8, 0.42, -10.9, 0.09, 0.35, 0.4);
  mesh(BOX, MAT.wood, group, -3.5, 0.95, -11.18, 1.9, 0.5, 0.07);
  function signTexture() {
    var c = document.createElement('canvas'); c.width = 1024; c.height = 320;
    var g = c.getContext('2d');
    g.fillStyle = '#221d16'; g.fillRect(0, 0, 1024, 320);
    g.strokeStyle = '#d8a833'; g.lineWidth = 10; g.strokeRect(18, 18, 988, 284);
    g.fillStyle = '#e8c36a'; g.font = 'bold 96px Georgia, serif'; g.textAlign = 'center';
    g.fillText('LOST WINGS GROVE', 512, 140);
    g.fillStyle = '#e9e2cf'; g.font = '44px Georgia, serif';
    g.fillText('Carolina Parakeet  ·  Dodo', 512, 216);
    g.fillStyle = '#9aa4b5'; g.font = '34px Georgia, serif';
    g.fillText('two birds the world lost — watch them quietly', 512, 272);
    var t = new THREE.CanvasTexture(c); return t;
  }
  var sign = new THREE.Group(); sign.position.set(-1.0, 0, -13.8); sign.rotation.y = 0.5;
  mesh(BOX, MAT.woodDark, sign, -1.5, 1.1, 0, 0.16, 2.2, 0.16);
  mesh(BOX, MAT.woodDark, sign, 1.5, 1.1, 0, 0.16, 2.2, 0.16);
  var board = new THREE.Mesh(new THREE.BoxGeometry(3.9, 1.25, 0.08),
    [MAT.woodDark, MAT.woodDark, MAT.woodDark, MAT.woodDark,
     new THREE.MeshLambertMaterial({ map: signTexture() }), MAT.woodDark]);
  board.position.y = 1.75; sign.add(board);
  group.add(sign);

  /* ---------------- the birds ------------------------------------------ */
  var pk = new Eng.BirdEntity('carolina-parakeet', world, { seed: 20261012 });
  var dd = new Eng.BirdEntity('dodo', world, { seed: 20261013 });
  Eng.buildDetailHi(pk); Eng.buildDetailHi(dd);
  pk.placeOnSurface(world.surfaceById('branch-1'), -2.2);
  dd.placeOnGround(world.spotById('forage-patch'));
  group.add(pk.group); group.add(dd.group);
  var birds = [pk, dd];

  // soft blob shadows
  var shadowMat = new THREE.MeshBasicMaterial({ color: 0x000000, transparent: true, opacity: 0.30, depthWrite: false });
  var shadowGeo = new THREE.CircleGeometry(0.5, 14);
  var shadows = birds.map(function () {
    var s = new THREE.Mesh(shadowGeo, shadowMat.clone()); s.rotation.x = -Math.PI / 2; group.add(s); return s;
  });
  function shadowY(x, z) {
    var best = 0.05;
    world.obstacles.forEach(function (o) {
      if (world.distToObstacle({ x: x, z: z }, o) <= 0.01) best = Math.max(best, o.topY + 0.04);
    });
    return best;
  }

  /* ---------------- per-frame update (called by the placer) ------------ */
  var lensZoom = 1;
  function update(t, dt, A) {
    var gp = group.position;
    var pp = A.S.p;
    var ctx = { playerPos: V3(pp.x - gp.x, (pp.y || 0) - gp.y, pp.z - gp.z) };
    for (var i = 0; i < birds.length; i++) {
      birds[i].update(dt, ctx);
      var b = birds[i], bp = b.group.position;
      var sh = shadows[i];
      sh.position.set(bp.x, shadowY(bp.x, bp.z), bp.z);
      var hgt = Math.max(0, bp.y);
      var sc = (b.species.id === 'dodo' ? 1.5 : 0.62) * Math.max(0.35, 1 - hgt * 0.06);
      sh.scale.set(sc, sc, sc);
      sh.material.opacity = 0.30 * Math.max(0.3, 1 - hgt * 0.09);
      // LOD by effective distance from the city camera (zoom-aware)
      var cw = A.camera.position, og = A.origin || { x: 0, z: 0 };
      var dx = (cw.x + og.x) - (gp.x + bp.x), dz = (cw.z + og.z) - (gp.z + bp.z);
      var dy = cw.y - (gp.y + bp.y);
     