<!-- SOLID CITY · part 2455 -->
paration
      b.pose.tailBase = -0.2;
      b.pose.foldTarget = 0.45;                      // wings begin to open
      if (b.phaseT > 0.30) {
        b.setPhase('push');
        b.releaseSurface(); b.spotId = null;
        var dir = V3(Math.sin(destHeading), 0, Math.cos(destHeading));
        b.heading = destHeading;
        b.vel.copy(dir.multiplyScalar(2.3)); b.vel.y = 2.5;
        b.speed = 3.2;
      }
    } else if (b.phase === 'push') {
      b.pose.bodyPitch = -0.10;
      b.pose.foldTarget = 1; b.pose.flapActive = true; b.pose.flapAmp = 1.15;
      b.pose.legMode = 'tucked';
      b.group.position.addScaledVector(b.vel, dt);
      b.vel.y -= 3.2 * dt;                            // gravity bites during deployment
      b.pitch = 0.25;
      if (b.phaseT > 0.24 && b.anim.fold > 0.75) { b.setPhase(null); b.setState('FLIGHT'); }
    }
  }
  function flightEnter(b) {
    b.intentSurfaceId = (b.dest && b.dest.kind === 'surface') ? b.dest.surface.id : null;
    b.glideT = 0; b.encT = 0;
    b.pose.flapRateMul = 1; b.pose.flapAmp = 1;
  }
  function flightUpdate(b, dt, ctx) {
    var F = b.species.flight, w = b.world;
    var dp = destPoint(b);
    if (!dp) { b.dest = { kind: 'surface', surface: w.surfaceById('branch-1') }; dp = destPoint(b); }
    b.intentSurfaceId = (b.dest.kind === 'surface') ? b.dest.surface.id : null;
    // energy
    b.needs.energy = clamp(b.needs.energy - 0.010 * dt, 0, 1);
    // --- obstacle evaluation BEFORE contact (Part IV + Architect's rule)
    b.encT -= dt;
    if (b.encT <= 0) {
      b.encT = 0.12;
      var enc = w.projectEncounter(b, 0.9);
      if (enc && (b.time > (b.encounterCooldown[enc.obstacle.id] || 0))) {
        b.encounterCooldown[enc.obstacle.id] = b.time + 3.0;
        var decision = w.evaluateResponse(b, enc, dp);
        b.decisions.push({ t: b.time, obstacle: enc.obstacle.id, action: decision.action, scores: { avoid: +decision.scores.avoid.toFixed(2), land: +decision.scores.land.toFixed(2), retreat: +decision.scores.retreat.toFixed(2) }, reason: decision.reason });
        if (decision.action === 'AVOID' && decision.corridor) {
          b.viaPoints = [decision.corridor.via];
        } else if (decision.action === 'LAND' && decision.surface) {
          b.journeyDest = b.dest;                    // remember the real goal
          b.dest = { kind: 'surface', surface: decision.surface };
          b.viaPoints = [];
        } else if (decision.action === 'RETREAT') {
          var rd = w.retreatDestination(b, enc.obstacle);
          if (rd) { b.dest = rd.kind === 'surface' ? { kind: 'surface', surface: rd.surface } : { kind: 'ground', spot: rd.spot }; b.journeyDest = b.dest; }
          b.viaPoints = [];
        }
        dp = destPoint(b);
      }
    }
    // --- steering: via points first, then an aim point on the route at
    // profile height (aiming at a near point gives real climb/descent
    // paths — and real glides — instead of a 25m laser line)
    var distDest = Math.sqrt(Math.pow(dp.x - b.group.position.x, 2) + Math.pow(dp.z - b.group.position.z, 2));
    var target = dp;
    if (b.viaPoints.length) {
      target = b.viaPoints[0];
      if (b.group.position.distanceTo(target) < 1.4) b.viaPoints.shift();
    } else if (distDest > 0.5) {
      var profY = distDest > 8 ? Math.max(dp.y + 1.3, 3.4) : dp.y;
      var ahead = Math.min(distDest, 9);
      target = V3(
        b.group.position.x + (dp.x - b.group.position.x) / distDest * ahead,
        profY,
        b.group.position.z + (dp.z - b.group.position.z) / distDest * ahead);
    }
    // glide management: parakeet flight is flap-glide (bounding) — bursts
    // of wingbeats alternate with brief glides whenever the bird is not
    // climbing to, or finally approaching, its target
    if (b.boutT == null) { b.boutT = 0.55; b.boutGlide = false; }
    b.boutT -= dt;
    if (b.boutT <= 0) {
      b.boutGlide = !b.boutGlide && b.rng() < 0.85;
      b.boutT = b.boutGlide ? (0.5 + b.rng() * 0.6) : (0.45 + b.rng() * 0.45);
    }
    var wantGlide = b.boutGlide && distDest > 4.5 && b.group.position.y > dp.y - 0.25 && !b.viaPoints.length;
    b.energyDemand = wantGlide ? 0 : 0.6;
    var dist = b.loco.steerFlight(dt, target, { forceGlide: wantGlide, minAlt: 1.6 });
    b.flapMode = wantGlide ? 'glide' : 'flap';
    b.pose.foldTarget = 1;
    b.pose.flapActive = !wantGlide;
    b.pose.glide = wantGlide;
    b.pose.legMode = 'tucked';
    b.pose.tailPitch = -b.pitch * 0.5;
    b.pose.tailBase = -0.05;
    b.pose.headYaw = 0; b.pose.headPitch = 0.05;
    // --- landing trigger
    var trigger = (b.dest.kind === 'surface') ? 5.2 : 6.5;
    if (!b.viaPoints.length && distDest < trigger && Math.abs(b.group.position.y - dp.y) < 3.4) {
      if (b.dest.kind === 'surface') b.setState(b.dest.surface.kind === 'branch' ? 'LAND_BRANCH' : 'LAND_SURFACE');
      else b.setState('LAND_GROUND');
    }
    // safety: never sink through the world
    if (b.group.position.y < 0.35) { b