<!-- RUBY-BACKUP · part 74 -->
k(x,y);
      if(hit3){
        var tg3=resolveTarget(hit3.object);
        if(tg3&&tg3.kind==='pulley') status('pulleys are already fixed in space');
        else if(tg3) addAnchor(tg3,hit3.point.clone());
      }
      anchorArmed=false;
      return true;
    }
    // 5. unanchor
    if(unanchorArmed){
      var hit4=rayPick(x,y);
      if(hit4){ var tg4=resolveTarget(hit4.object); if(tg4&&!removeAnchor(tg4)) status('that one is not anchored'); }
      unanchorArmed=false;
      return true;
    }
    // 5b. lift stake placement
    if(liftArmed){
      var hitL=rayPick(x,y);
      if(hitL){ placeLiftStake(hitL.point.x, hitL.point.z); }
      else status('tap the ground');
      liftArmed=false;
      return true;
    }
    // 5c2. detach — tap a rope handle to remove that rig
    if(detachArmed){
      detachArmed=false;
      // find nearest rig handle
      var best=null, bd=1e9;
      for(var di=0; di<rigs.length; di++){
        var hp=rigs[di].handle.group.position;
        var dd=Math.hypot(hp.x-hitF.point.x, hp.z-hitF.point.z);
        if(dd<bd){ bd=dd; best=rigs[di]; }
      }
      if(best && bd<5){ doDetachRig(best); }
      else status('no rope near that tap');
      return;
    }
    if(unpulleyArmed){
      unpulleyArmed=false;
      var bp=null, bd2=1e9;
      for(var pi2=0; pi2<pulleys.length; pi2++){
        var pp=pulleys[pi2].group.position;
        var d2=Math.hypot(pp.x-hitF.point.x, pp.z-hitF.point.z);
        if(d2<bd2){ bd2=d2; bp=pulleys[pi2]; }
      }
      if(bp && bd2<5){
        if(bp.group.parent) bp.group.parent.remove(bp.group);
        var bi=pulleys.indexOf(bp); if(bi>=0) pulleys.splice(bi,1);
        status('pulley removed');
      } else status('no pulley near that tap');
      return;
    }
    // 5c. flatten
    if(flattenArmed){
      var hitF=rayPick(x,y);
      if(hitF){
        var n=flattenAt(hitF.point.x/0.13, hitF.point.z/0.13);
        status(n?('flattened '+n+' lift(s) — the earth settles'):('no lift here to flatten'));
      }
      flattenArmed=false;
      return true;
    }
    // 5d. lift ring pull (any time)
    if(!activeLiftPull){
      var lst=liftStakeHit(x,y);
      if(lst){ activeLiftPull={stake:lst,id:id}; return true; }
    }
    // 6. grab mode
    if(grabMode){
      if(carried){
        grabTouch={id:id,sx:x,sy:y,moved:false,carrying:true};
      }else{
        var hit5=rayPick(x,y);
        var tg5=hit5?resolveTarget(hit5.object):null;
        grabTouch={id:id,sx:x,sy:y,moved:false,carrying:false,
                   pending:tg5, point:hit5?hit5.point.clone():null};
      }
      return true;
    }
    // 7. pulley scroll menu: DISABLED — King's order, it keeps popping up
    /* Tap no longer opens the pulley menu. Use the pulley code if needed. */
  }catch(e){}
  return false;
}
function dMove(id,x,y){
  var consumed=false;
  try{
    if(activePull&&activePull.id===id){ dragHandle(activePull.rig,x,y); consumed=true; }
    if(activeLiftPull&&activeLiftPull.id===id){ dragLiftRing(activeLiftPull.stake,x,y); consumed=true; }
    if(grabTouch&&grabTouch.id===id){
      var dx=x-grabTouch.sx, dy=y-grabTouch.sy;
      if(dx*dx+dy*dy>144) grabTouch.moved=true;
      if(grabTouch.moved&&carried){ carryMoveTo(x,y); consumed=true; }
      else if(grabTouch.moved) consumed=true;
    }
  }catch(e){}
  return consumed;
}
function dUp(id){
  try{
    if(activePull&&activePull.id===id){
      var r=activePull.rig;
      if(r._deformCorner&&r.target.frame){
        try{ r.target.frame.driven[r._deformCorner]=false; }catch(e){}
        r._deformCorner=null;
      }
      activePull=null;
    }
    if(activeLiftPull&&activeLiftPull.id===id){ activeLiftPull=null; }
    if(grabTouch&&grabTouch.id===id){
      if(!grabTouch.moved){
        if(grabTouch.carrying) dropCarried();
        else if(grabTouch.pending) startCarry(grabTouch.pending,grabTouch.point);
      }
      grabTouch=null;
    }
  }catch(e){}
}
function onTS(e){
  var used=false;
  for(var i=0;i<e.changedTouches.length;i++){
    var t=e.changedTouches[i];
    if(dDown(t.identifier,t.clientX,t.clientY)) used=true;
  }
  if(used){ e.preventDefault(); e.stopPropagation(); }
}
function onTM(e){
  var used=false;
  for(var i=0;i<e.changedTouches.length;i++){
    var t=e.changedTouches[i];
    if(dMove(t.identifier,t.clientX,t.clientY)) used=true;
  }
  if(used){ e.preventDefault(); e.stopPropagation(); }
}
function onTE(e){
  for(var i=0;i<e.changedTouches.length;i++) dUp(e.changedTouches[i].identifier);
}
var mouseDown=false;
function onMD(e){
  if(e.button!==0) return;
  if(dDown('m',e.clientX,e.clientY)){ mouseDown=true; e.preventDefault(); e.stopPropagation(); }
}
function onMM(e){
  if(!mouseDown) return;
  if(dMove('m',e.clientX,e.clientY)){ e.preventDefault(); e.stopPropagation(); }
}
function onMU(e){
  if(mouseDown){ dUp('m'); mouseDown=false; }
}


/* ============================================================================
   TERRAIN LIFT — the ground itse