<!-- SOLID CITY · part 2443 -->
; });
  p.querySelector('#lw-tab0').addEventListener('click', function () { selectBird(0); });
  p.querySelector('#lw-tab1').addEventListener('click', function () { selectBird(1); });
  p.querySelector('#lw-zin').addEventListener('click', function () { setZoom(L.targetZoom * 1.4); });
  p.querySelector('#lw-zout').addEventListener('click', function () { setZoom(L.targetZoom / 1.4); });
  p.querySelector('#lw-track').addEventListener('click', function (e) { L.track = !L.track; e.target.textContent = L.track ? '◎ TRACK: ON' : '◎ TRACK: OFF'; e.target.classList.toggle('act', L.track); });
  p.querySelector('#lw-cap').addEventListener('click', capture);
  p.querySelector('#lw-photos').addEventListener('click', showGallery);
  L.zoomSlider.addEventListener('input', function () { setZoom(parseFloat(L.zoomSlider.value)); });
  L.canvas.addEventListener('wheel', function (e) { e.preventDefault(); setZoom(L.targetZoom * (e.deltaY < 0 ? 1.15 : 0.87)); }, { passive: false });
  // pinch zoom on the scope (its own surface — movement controls untouched)
  var pointers = {}, pinchD = 0;
  L.canvas.addEventListener('pointerdown', function (e) { pointers[e.pointerId] = { x: e.clientX, y: e.clientY }; });
  L.canvas.addEventListener('pointermove', function (e) {
    if (!pointers[e.pointerId]) return;
    pointers[e.pointerId] = { x: e.clientX, y: e.clientY };
    var ks = Object.keys(pointers);
    if (ks.length === 2) {
      var a = pointers[ks[0]], b = pointers[ks[1]], d = Math.hypot(a.x - b.x, a.y - b.y);
      if (pinchD > 0) setZoom(L.targetZoom * (d / pinchD));
      pinchD = d; e.preventDefault();
    }
  });
  ['pointerup', 'pointercancel'].forEach(function (ev) { L.canvas.addEventListener(ev, function (e) { delete pointers[e.pointerId]; if (Object.keys(pointers).length < 2) pinchD = 0; }); });

  var g = el('div'); g.id = 'lw-gallery';
  g.innerHTML = '<div style="display:flex;justify-content:space-between;align-items:center;max-width:520px;margin:0 auto 12px"><b>FIELD PHOTOS — Lost Wings Grove</b><button class="lw-btn" id="lw-gclose">✕ CLOSE</button></div><div id="lw-glist"></div>';
  document.body.appendChild(g); L.gallery = g;
  g.querySelector('#lw-gclose').addEventListener('click', function () { g.classList.remove('on'); });
}
function selectBird(i) {
  L.sel = i;
  L.panel.querySelector('#lw-tab0').classList.toggle('act', i === 0);
  L.panel.querySelector('#lw-tab1').classList.toggle('act', i === 1);
}
function setZoom(z) {
  L.targetZoom = Math.max(1, Math.min(20, z));
  if (L.zoomSlider) L.zoomSlider.value = L.targetZoom;
}
function openPanel(on) {
  buildLens();
  M.panelOpen = on;
  L.panel.classList.toggle('on', on);
  if (on && !L.renderer) {
    L.renderer = new A.T.WebGLRenderer({ canvas: L.canvas, antialias: true, preserveDrawingBuffer: false });
    L.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
    L.scopeCam = new A.T.PerspectiveCamera(60, 1, 0.1, 60000);
  }
  if (!on && M.group) M.group.userData.setLens(1);
}
function birdRenderPos(bird, out) { return bird.group.getWorldPosition(out); }
var _v = null, _q = null;
function renderScope() {
  if (!L.renderer || !M.group) return;
  var T = A.T, cam = A.camera;
  if (!_v) { _v = new T.Vector3(); _q = new T.Quaternion(); }
  L.scopeCam.position.copy(cam.position);
  L.scopeCam.position.y = cam.position.y;
  var baseFov = cam.fov || 62;
  L.scopeCam.fov = 2 * Math.atan(Math.tan(baseFov * Math.PI / 360) / L.zoom) * 180 / Math.PI;
  L.scopeCam.aspect = 1; L.scopeCam.near = cam.near; L.scopeCam.far = Math.max(cam.far, 60000);
  var birds = M.group.userData.birds, bird = birds[L.sel];
  if (L.track && bird) {
    birdRenderPos(bird, _v);
    var m = new T.Matrix4().lookAt(L.scopeCam.position, _v, new T.Vector3(0, 1, 0));
    _q.setFromRotationMatrix(m);
    var cur = cam.quaternion.clone();
    if (!L.trackQ) L.trackQ = cur;
    // ease toward the bird; gentle, never a lock (manual zoom/framing stays live)
    var ang = L.trackQ.angleTo(_q), step = Math.min(ang, 1.0 * 0.033);
    if (ang > 1e-5) { L.trackQ = L.trackQ.clone(); L.trackQ.rotateTowards ? L.trackQ.rotateTowards(_q, step) : L.trackQ.slerp(_q, step / ang); }
    L.scopeCam.quaternion.copy(L.trackQ);
  } else {
    L.trackQ = null;
    L.scopeCam.quaternion.copy(cam.quaternion);
  }
  L.scopeCam.updateProjectionMatrix();
  var wpx = L.canvas.clientWidth || 420;
  L.renderer.setSize(wpx, wpx, false);
  L.renderer.render(A.scene, L.scopeCam);
}
function refreshPanel() {
  if (!M.group) return;
  var E = Eng(); if (!E) return;
  var bird = M.group.userData.birds[L.sel], d = E.Observation.describe(bird);
  L.panel.querySelector('#lw-name').textContent = bird.species.commonName;
  L.panel.querySelector('#lw-state').textContent = d.stateLabel;
  L.panel.querySelector('#lw-desc').textContent = d.text;
  L.panel.querySelector('#lw-ev').textContent = 'Coloration: ' + (bird.species.coloration ? bird.species.coloration.display : '') + ' · silent — no re