<!-- SOLID CITY · part 2014 -->
h.PI*2,rr=r.r*(.75+(v%3)*.12);ctx.lineTo(Math.cos(a)*rr,Math.sin(a)*rr)}ctx.closePath();ctx.fill();ctx.stroke();ctx.restore()}
    for(var p of shots){ctx.strokeStyle=shipColor(p.team);ctx.lineWidth=3;ctx.beginPath();ctx.moveTo(p.x,p.y);ctx.lineTo(p.x-p.vx*.035,p.y-p.vy*.035);ctx.stroke()}
    for(var sp of sparks){ctx.globalAlpha=sp.life*4;ctx.fillStyle=shipColor(sp.color);ctx.fillRect(sp.x,sp.y,3,3)}ctx.globalAlpha=1;
    for(var s of ships){drawShip(ctx,s,focusTeam)}ctx.restore()}
  function drawShip(ctx,s,focusTeam){var c=shipColor(s.team),isSel=selected[s.team]===s.id;ctx.save();ctx.translate(s.x,s.y);ctx.rotate(s.a);if(s.disabled>0){ctx.globalAlpha=.35;ctx.rotate(s.disabled*2)}if(isSel){ctx.strokeStyle='#fff';ctx.lineWidth=2;ctx.beginPath();ctx.arc(0,0,25,0,Math.PI*2);ctx.stroke()}ctx.fillStyle=c;ctx.shadowColor=c;ctx.shadowBlur=s.team===focusTeam?12:3;ctx.beginPath();ctx.moveTo(20,0);ctx.lineTo(-12,-10);ctx.lineTo(-6,0);ctx.lineTo(-12,10);ctx.closePath();ctx.fill();ctx.shadowBlur=0;ctx.fillStyle='#e9ffff';ctx.fillRect(3,-2,8,4);ctx.restore();ctx.fillStyle='rgba(0,0,0,.75)';ctx.fillRect(s.x-23,s.y+18,46,5);ctx.fillStyle=s.hull<30?'#ff6969':'#71f0ac';ctx.fillRect(s.x-23,s.y+18,46*(s.hull/100),5);ctx.fillStyle=s.team===focusTeam?'#e8f7f4':'#718a86';ctx.font='700 10px sans-serif';ctx.textAlign='center';ctx.fillText(s.name,s.x,s.y+36);if(s.owners.movement==='HUMAN'){ctx.fillStyle='#fff';ctx.font='8px sans-serif';ctx.fillText('HUMAN HELM',s.x,s.y-23)}}
  var canvases={gold:document.getElementById('goldCanvas'),teal:document.getElementById('tealCanvas')},contexts={gold:canvases.gold.getContext('2d'),teal:canvases.teal.getContext('2d')};
  function resizeCanvas(c){var r=c.getBoundingClientRect(),d=Math.min(2,window.devicePixelRatio||1);c.width=Math.max(1,Math.round(r.width*d));c.height=Math.max(1,Math.round(r.height*d));c._w=r.width;c._h=r.height;c.getContext('2d').setTransform(d,0,0,d,0,0)}function resizeAll(){resizeCanvas(canvases.gold);resizeCanvas(canvases.teal)}
  function pointFrom(e,c){var r=c.getBoundingClientRect();return{x:(e.clientX-r.left)/r.width*W,y:(e.clientY-r.top)/r.height*H}}
  function bindCanvas(team){var c=canvases[team],down=false;c.addEventListener('pointerdown',function(e){e.preventDefault();down=true;c.setPointerCapture(e.pointerId);var p=pointFrom(e,c),a=teamShips(team).filter(function(s){return s.disabled<=0}).sort(function(x,y){return dist(p,x)-dist(p,y)}),s=a[0];if(s&&dist(p,s)<55){claim(s,['movement','navigation']);s.humanAim={x:p.x+(s.team==='gold'?100:-100),y:p.y}}else{var cur=ships.find(function(x){return x.id===selected[team]});if(cur){cur.humanAim=p;cur.task='Human vector'}}});c.addEventListener('pointermove',function(e){if(!down)return;var s=ships.find(function(x){return x.id===selected[team]});if(s){s.humanAim=pointFrom(e,c);s.task='Human vector'}});function up(){down=false}c.addEventListener('pointerup',up);c.addEventListener('pointercancel',up)}
  bindCanvas('gold');bindCanvas('teal');
  document.addEventListener('pointerdown',function(e){var b=e.target.closest('button');if(!b)return;var team=b.dataset.team;if(b.dataset.order)issueOrder(team,b.dataset.order);if(b.dataset.action){var s=ships.find(function(x){return x.id===selected[team]});if(!s){toast('Tap a '+team+' fighter first');return}if(b.dataset.action==='fire'){claim(s,['weapons']);fire(s,true)}if(b.dataset.action==='shield'){claim(s,['defense']);s.shield=Math.min(100,s.shield+24);s.task='Human shield boost';log('handoff',s.name+' human defense boost',s.id)}if(b.dataset.action==='release')release(s)}});
  document.addEventListener('pointerup',function(e){var b=e.target.closest&&e.target.closest('[data-action="fire"]');if(b){var s=ships.find(function(x){return x.id===selected[b.dataset.team]});if(s)setTimeout(function(){release(s,['weapons'])},220)}});
  document.getElementById('mode').addEventListener('change',function(){reset();if(this.value==='auto'){log('handoff','AI + AI command configuration engaged');toast('AI + AI · tap any fighter to intervene')}else log('handoff','Human + AI configuration engaged · Gold available')});
  function toast(t){var el=document.getElementById('toast');el.textContent=t;el.classList.add('show');clearTimeout(toast.t);toast.t=setTimeout(function(){el.classList.remove('show')},1500)}
  function updateUI(){for(var t of ['gold','teal']){var ready=teamShips(t).filter(function(s){return s.disabled<=0}).length;document.getElementById(t+'Health').textContent=ready+' ships combat-ready';document.getElementById(t+'Meter').style.width=progress[t]+'%';document.getElementById(t+'Progress').textContent=Math.floor(progress[t])+'%';var s=ships.find(function(x){return x.id===selected[t]}),el=document.getElementById(t+'Selected');el.innerHTML=s?'<strong>'+s.name+'</strong> · '+ownerLabel(s)+' · '+s.task:'<strong>Tap a '+(t==='gold'?'Gold':'Teal')+' fighter</strong> to '+(t==='gold'?'take its helm':'intervene')}}
  function updateStats(){document.getElementById('goldS