<!-- SOLID CITY · part 2933 -->
th.random()*.9});
    applyMode(mode,false); updateHud(); els.logList.innerHTML=''; log('SYS','Route simulator ready','teal');
  }
  function applyMode(next,write){
    mode=next;document.querySelectorAll('.preset').forEach(function(b){b.classList.toggle('active',b.dataset.mode===mode)});
    if(mode==='rider'){setOwner('move','human',write);setOwner('weapon','ai',write)}
    if(mode==='archer'){setOwner('move','ai',write);setOwner('weapon','human',write)}
    if(mode==='manual'){setOwner('move','human',write);setOwner('weapon','human',write)}
    releaseAt.move=releaseAt.weapon=0;updateOwners();
    if(write)log('CFG',mode==='rider'?'Human movement · AI weapons':mode==='archer'?'AI movement · Human weapons':'Human holds both','gold');
  }
  document.querySelectorAll('.preset').forEach(function(b){b.addEventListener('click',function(){applyMode(b.dataset.mode,true)})});

  function now(){return performance.now()}
  function setOwner(task,owner,write){
    if(owners[task]===owner)return;
    owners[task]=owner;if(state){state.handoffs++;els.handoffCount.textContent=state.handoffs}
    if(write!==false)log(task==='move'?'MOVE':'ARMS',owner==='human'?'Human claimed task':'AI resumed task',owner==='human'?'gold':'teal');
    updateOwners();
  }
  function claim(task){
    releaseAt[task]=0;var t0=now();setOwner(task,'human',true);var latency=Math.max(1,Math.round(now()-t0));
    (task==='move'?els.moveLatency:els.weaponLatency).textContent=latency+' ms';updateOwners();
  }
  function release(task){releaseAt[task]=now()+800;log(task==='move'?'MOVE':'ARMS','Release detected · guarded coast','');updateOwners()}
  function updateOwners(){
    [['move',els.moveOwner],['weapon',els.weaponOwner]].forEach(function(pair){var task=pair[0],el=pair[1],releasing=releaseAt[task]>now();el.className='owner '+(releasing?'release':owners[task]);el.textContent=releasing?'HUMAN → AI':owners[task].toUpperCase()});
  }
  function log(tag,text,tone){
    if(!state)return;var li=document.createElement('li');var sec=Math.floor(state.elapsed);var mm=String(Math.floor(sec/60)).padStart(2,'0'),ss=String(sec%60).padStart(2,'0');li.innerHTML='<time>'+mm+':'+ss+'</time><span><b class="'+(tone||'')+'">'+tag+'</b> · '+text+'</span>';els.logList.insertBefore(li,els.logList.firstChild);while(els.logList.children.length>24)els.logList.lastChild.remove();
  }

  function bindPad(id,nub,task){
    var pad=document.getElementById(id),active=null;
    function move(e){if(e.pointerId!==active)return;var r=pad.getBoundingClientRect(),x=(e.clientX-r.left)/r.width*2-1,y=(e.clientY-r.top)/r.height*2-1,m=Math.hypot(x,y);if(m>1){x/=m;y/=m}input[task].x=x;input[task].y=y;nub.style.left=((x*.39+.5)*100)+'%';nub.style.top=((y*.39+.5)*100)+'%';if(task==='weapon')input.firing=true}
    pad.addEventListener('pointerdown',function(e){e.preventDefault();active=e.pointerId;pad.setPointerCapture(active);if(task==='move')pointerMove=true;else pointerWeapon=true;claim(task);move(e)});
    pad.addEventListener('pointermove',move);
    function end(e){if(e.pointerId!==active)return;active=null;if(task==='move')pointerMove=false;else pointerWeapon=false;input[task]={x:task==='weapon'?1:0,y:0};input.firing=false;nub.style.left='50%';nub.style.top='50%';release(task)}
    pad.addEventListener('pointerup',end);pad.addEventListener('pointercancel',end);
  }
  bindPad('movePad',document.getElementById('moveNub'),'move');bindPad('weaponPad',document.getElementById('weaponNub'),'weapon');

  window.addEventListener('keydown',function(e){
    var k=e.key.toLowerCase();if(['w','a','s','d','arrowup','arrowdown','arrowleft','arrowright',' '].indexOf(k)>=0)e.preventDefault();
    if(keys[k])return;keys[k]=true;
    if('wasd'.indexOf(k)>=0)claim('move');if(k.indexOf('arrow')===0||k===' ')claim('weapon');
  });
  window.addEventListener('keyup',function(e){var k=e.key.toLowerCase();keys[k]=false;if('wasd'.indexOf(k)>=0&&!['w','a','s','d'].some(function(x){return keys[x]}))release('move');if((k.indexOf('arrow')===0||k===' ')&&!['arrowup','arrowdown','arrowleft','arrowright',' '].some(function(x){return keys[x]}))release('weapon')});

  function keyboardInput(){
    if(!pointerMove){var x=(keys.d?1:0)-(keys.a?1:0),y=(keys.s?1:0)-(keys.w?1:0),m=Math.hypot(x,y)||1;input.move.x=x/m;input.move.y=y/m}
    if(!pointerWeapon){var ax=(keys.arrowright?1:0)-(keys.arrowleft?1:0),ay=(keys.arrowdown?1:0)-(keys.arrowup?1:0);if(ax||ay){var am=Math.hypot(ax,ay);input.weapon.x=ax/am;input.weapon.y=ay/am}input.firing=!!keys[' ']}
  }

  function launch(){reset();state.running=true;last=performance.now();els.startCard.hidden=true;els.debrief.hidden=true;log('SYS','Route 01 launched','teal');cancelAnimationFrame(raf);raf=requestAnimationFrame(loop)}
  document.getElementById('launchBtn').addEventListener('click',launch);document.getElementById('againBtn').addEventListener('click',launch);

  function nearestThreat(){
    var best=null,bd=1e9;state.enemies.forEach(function(e)