<!-- SAGA2 · part 28 -->
2 + fh*0.08;
        fpts.push([fx, fy, fz]);
      }
      fline(fpts);
    }
    // CHEEKS — diagonal lines from nose to ears (both sides)
    for(var ch=0; ch<8; ch++){
      var ct = ch/8;
      // left cheek
      fline([[-1.5-ct*2.0, 21-ct*3.0, 9.2-ct*1.0],[-2.0-ct*2.0, 20.5-ct*3.0, 8.8-ct*1.0]]);
      // right cheek
      fline([[1.5+ct*2.0, 21-ct*3.0, 9.2-ct*1.0],[2.0+ct*2.0, 20.5-ct*3.0, 8.8-ct*1.0]]);
    }
    // NOSE — bridge lines and side planes
    for(var ns=0; ns<5; ns++){
      var nx = -0.8 + ns*0.4;
      fline([[nx, 22, 9.3+Math.abs(nx)*0.3],[nx*1.1, 20, 9.5+Math.abs(nx)*0.3],[nx*1.2, 18.5, 9.6]]);
    }
    // CHIN — curved lines under mouth
    for(var cn=0; cn<4; cn++){
      var cy = 16.8 - cn*0.5;
      fline([[-2.0+cn*0.2, cy, 9.0],[0, cy-0.2, 9.4],[2.0-cn*0.2, cy, 9.0]]);
    }
    // TEMPLES — vertical fine lines
    for(var tp=0; tp<6; tp++){
      var tx = -3.8 + tp*0.25;
      fline([[tx, 24, 7.5],[tx, 22, 8.0],[tx, 20, 8.2]]);
      fline([[-tx, 24, 7.5],[-tx, 22, 8.0],[-tx, 20, 8.2]]);
    }
  })();
  */


  // MINIMAL FACE — sacred geometry (King's pick)
  (function(){
    function mline(pts, mat){ draw(pts.map(function(p){return new THREE.Vector3(p[0],p[1],p[2]);}), mat); }
    // center line
    mline([[0,28,8.5],[0,22,9.4],[0,18,9.6],[0,15,9.2]], lnGold);
    // brows — angular
    mline([[-5,24,8.5],[-2.5,23.5,9],[-1,23.2,9.1]], lnGold);
    mline([[1,23.2,9.1],[2.5,23.5,9],[5,24,8.5]], lnGold);
    mline([[-4.5,22.8,8.7],[-2.5,22.3,9.05],[-1.2,22.1,9.1]], lnGold);
    mline([[1.2,22.1,9.1],[2.5,22.3,9.05],[4.5,22.8,8.7]], lnGold);
    // lashes — 5 ticks each
    for(var lh=0; lh<5; lh++){
      var lx1 = -4.2+lh*0.7, lx2 = 4.2-lh*0.7;
      mline([[lx1,22.5,9.0],[lx1,21.9,9.0]], lnCyan);
      mline([[lx2,22.5,9.0],[lx2,21.9,9.0]], lnCyan);
    }
    // cheeks — diagonal gold
    mline([[-3.5,20,8.8],[-2,18.5,9.2]], lnGold);
    mline([[3.5,20,8.8],[2,18.5,9.2]], lnGold);
    // nose — small cyan V
    mline([[-0.6,18.3,9.5],[0,17.9,9.6],[0.6,18.3,9.5]], lnCyan);
    // mouth — gold upper, cyan lower
    mline([[-2,16.8,9.3],[-1,16.6,9.5],[0,16.7,9.6],[1,16.6,9.5],[2,16.8,9.3]], lnGold);
    mline([[-1.8,16.6,9.35],[-0.8,16.1,9.5],[0,16.0,9.55],[0.8,16.1,9.5],[1.8,16.6,9.35]], lnCyan);
    // jaw — angular cyan
    mline([[-5.5,20,7.5],[-4,17.5,8.5],[-2.5,16,9.0],[-1,15.3,9.2],[0,15.1,9.25]], lnCyan);
    mline([[0,15.1,9.25],[1,15.3,9.2],[2.5,16,9.0],[4,17.5,8.5],[5.5,20,7.5]], lnCyan);
  })();

  // lights
  var eyeL = new THREE.PointLight(0x66eeff, 1.5, 50);
  eyeL.position.set(0, 21, 10);
  avatarGrp.add(eyeL);
  avatarGrp.userData.lights = [eyeL];
  // PRESENCE — soft radial glow behind (he exists in space)
  var glowTex = (function(){
    var c = document.createElement('canvas'); c.width=c.height=128;
    var ctx = c.getContext('2d');
    var g = ctx.createRadialGradient(64,64,0,64,64,64);
    g.addColorStop(0,'rgba(80,180,220,0.35)');
    g.addColorStop(0.5,'rgba(60,140,200,0.12)');
    g.addColorStop(1,'rgba(0,0,0,0)');
    ctx.fillStyle=g; ctx.fillRect(0,0,128,128);
    return new THREE.CanvasTexture(c);
  })();
  var presence = new THREE.Mesh(new THREE.PlaneGeometry(60, 60),
    new THREE.MeshBasicMaterial({map:glowTex, transparent:true, blending:THREE.AdditiveBlending, depthWrite:false}));
  presence.position.set(0, 5, -15);
  avatarGrp.add(presence);

  scene.add(avatarGrp);
  avatarGrp.scale.set(0.55, 0.55, 0.55);
  avatarGrp.position.set(0, 0, -490);
  avatarGrp.visible = false; // hidden — King: soldiers in the way
  avatarGrp.rotation.set(0,0,0);
  scene.add(camera);
}
var weaponMode = false;
var lasers = [];
var cannonL = null, cannonR = null;
var scorchMarks = [];
var sparkles = [];
function animate(){
  requestAnimationFrame(animate);
  var dt=Math.min(clock.getDelta(),0.05), t=clock.elapsedTime;
  auroras.forEach(function(a){
    a.material.opacity=0.14+Math.sin(t*0.5+a.userData.phase)*0.08;
    a.rotation.y+=dt*0.006;
  });
  if(window._crown){
    window._crown.rotation.y+=dt*0.8;
    window._crown.position.y=300+Math.sin(t*0.8)*12;
  }
  (window._rings||[]).forEach(function(r){
    r.rotation.z+=dt*r.userData.s;
  });
  blimps.forEach(function(b){
    var u=b.userData; u.a+=dt*u.s;
    b.position.set(500+Math.cos(u.a)*u.r,u.h+Math.sin(t*0.4+u.a)*14,500+Math.sin(u.a)*u.r);
    b.rotation.y=-u.a+Math.PI/2;
  });
  heart.intensity=1.6+Math.sin(t*1.2)*0.5;
  if(avatarGrp){
    if(avatarGrp.userData.reactor){
      var rp = 1+Math.sin(t*4)*0.08;
      avatarGrp.userData.reactor.scale.set(rp,rp,rp);
    }
    // lights breathe with power
    if(avatarGrp.userData.lights){
      var lp = 2.5+Math.sin(t*4)*0.6;
      if(avatarGrp.userData.lights[1]) avatarGrp.userData.lights[1].intensity = lp+0.5;
      if(avatarGrp.userData.lights[0]) avatarGrp.userData.lights[0].intensity = 2.2+Math.sin(t*2.3)*0.4;
      // cannons blaze when firing
      var cf = weaponMode ? 2.5 : 1.2;
      if(avatarGrp.userData.lights[2]) avatarGrp.us