<!-- SAGA2 · part 77 -->
+0.08,1.6,3.7]], headMat, grp);
      }
    }
    detailEye(-eyeDX); detailEye(eyeDX);
    // brows — varied height
    hline([[-eyeDX-1.6,browH,3.6],[-eyeDX,browH+0.25,3.8],[-eyeDX+1.6,browH,3.6]], goldMat, grp);
    hline([[eyeDX-1.6,browH,3.6],[eyeDX,browH+0.25,3.8],[eyeDX+1.6,browH,3.6]], goldMat, grp);
    // nose — bridge + tip + nostrils
    hline([[0,0.8,4.1],[0.12,-0.8,4.25],[0,-noseL+0.8,4.35]], headMat, grp);
    hline([[-0.45,-noseL+0.6,4.25],[0,-noseL+0.4,4.4],[0.45,-noseL+0.6,4.25]], headMat, grp);
    hellipse(-0.55, -noseL+0.5, 4.2, 0.28, 0.18, headMat, grp);
    hellipse(0.55, -noseL+0.5, 4.2, 0.28, 0.18, headMat, grp);
    // mouth — upper/lower lip with detail
    hline([[-mouthW,-3.1,4.0],[-mouthW*0.5,-3.3,4.2],[0,-3.2,4.35],[mouthW*0.5,-3.3,4.2],[mouthW,-3.1,4.0]], goldMat, grp);
    hline([[-mouthW*0.85,-3.15,4.05],[-mouthW*0.4,-3.7,4.2],[0,-3.8,4.3],[mouthW*0.4,-3.7,4.2],[mouthW*0.85,-3.15,4.05]], headMat, grp);
    hline([[0,-3.2,4.35],[0,-3.8,4.3]], goldMat, grp);
    // cheekbones
    hline([[-2.8,-0.5,3.9],[-2.0,-1.2,4.1],[-1.2,-1.8,4.2]], goldMat, grp);
    hline([[2.8,-0.5,3.9],[2.0,-1.2,4.1],[1.2,-1.8,4.2]], goldMat, grp);
    // chin
    hline([[-1.0,-4.8,3.9],[-0.4,-5.3,4.0],[0.4,-5.3,4.0],[1.0,-4.8,3.9]], headMat, grp);
    grp.position.set(px, 12, -60);
    scene.add(grp);
    return grp;
  }
  // BLACKOUT — 25 heads disabled
  //for(var i=0; i<25; i++){
  //  buildHeadVariant(i, (i-12)*14);
  //}
})();

var avatarGrp2 = avatarGrp.clone();
avatarGrp2.position.set(-12, 0, -490);
avatarGrp2.visible = false; // hidden
avatarGrp2.rotation.set(0,0,0);
scene.add(avatarGrp2);
[avatarGrp, avatarGrp2].forEach(function(g){
  g.traverse(function(o){
    if(o.material){
      o.material.transparent = true;
      o.material.opacity = (o.material.opacity || 1) * 0.35;
    }
  });
});
animate();
var camMode = 8;
var camAngles = [
  [[0,12,6],[0,12,0]],    // 0 first-person (human)
  [[0,8,45],[0,5,0]],     // 1 full body front
  [[45,8,0],[0,5,0]],     // 2 full body side
  [[0,8,-45],[0,5,0]],    // 3 full body back
  [[0,60,5],[0,0,0]],     // 4 top-down
  [[0,12,15],[0,12,0]],   // 5 close-up face
  [[0,2,20],[0,12,0]],    // 6 low hero angle
  [[0,30,25],[0,5,0]],    // 7 high angle
  [[0,15,80],[0,10,0]],   // 8 wide establishing
  [[-20,8,20],[0,8,0]],   // 9 three-quarter
  [[20,3,10],[0,10,0]],   // 10 dramatic low side
  [[0,12,-20],[0,12,0]]   // 11 behind head
];

var sentinelGrp = null;
function buildSentinel(){
  if(sentinelGrp) return;
  sentinelGrp = new THREE.Group();
  sentinelGrp.position.set(0, 15, -30);
  scene.add(sentinelGrp);
  var sCyan = new THREE.LineBasicMaterial({color:0x44ffaa, transparent:true, opacity:0.7, blending:THREE.AdditiveBlending});
  var sGold = new THREE.LineBasicMaterial({color:0xffd700, transparent:true, opacity:0.9, blending:THREE.AdditiveBlending});
  function sdraw(pts, mat){
    for(var w=0; w<8; w++){
      var ox=(Math.random()-0.5)*0.3, oy=(Math.random()-0.5)*0.3;
      var ptw = pts.map(function(p){ return new THREE.Vector3(p.x+ox, p.y+oy, p.z); });
      sentinelGrp.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(ptw), mat));
    }
  }
  // CORE — sphere of contour lines
  for(var i=0; i<16; i++){
    var pts=[], lat = -1.2+i*0.15;
    for(var j=0;j<=24;j++){ var an=j/24*Math.PI*2;
      var r = 4*Math.cos(lat);
      pts.push(new THREE.Vector3(Math.cos(an)*r, Math.sin(lat)*4, Math.sin(an)*r));
    }
    sdraw(pts, i%4===0?sGold:sCyan);
  }
  // ORBIT RINGS — 3 gyroscope rings
  [[0,0,0],[Math.PI/3,0,0],[0,0,Math.PI/3]].forEach(function(rot, idx){
    var pts=[];
    for(var j=0;j<=40;j++){ var an=j/40*Math.PI*2;
      var x = Math.cos(an)*7, y = Math.sin(an)*7, z = 0;
      // rotate
      var x2 = x, y2 = y*Math.cos(rot[0])-z*Math.sin(rot[0]), z2 = y*Math.sin(rot[0])+z*Math.cos(rot[0]);
      pts.push(new THREE.Vector3(x2, y2, z2));
    }
    sdraw(pts, idx===0?sGold:sCyan);
  });
  // SINGLE EYE — central
  var eye = new THREE.Mesh(new THREE.SphereGeometry(0.8, 12, 12),
    new THREE.MeshBasicMaterial({color:0x44ffaa}));
  eye.position.set(0, 0, 3.5);
  sentinelGrp.add(eye);
}


var scoutGrp = null;
function buildScout(){
  if(scoutGrp) return;
  scoutGrp = new THREE.Group();
  scoutGrp.position.set(0, 0, -50);
  scoutGrp.scale.set(0.5, 0.5, 0.5);
  scene.add(scoutGrp);
  var eGreen = new THREE.LineBasicMaterial({color:0x44ff88, transparent:true, opacity:0.7, blending:THREE.AdditiveBlending});
  var eSilver = new THREE.LineBasicMaterial({color:0xcccccc, transparent:true, opacity:0.9, blending:THREE.AdditiveBlending});
  var eDim = new THREE.LineBasicMaterial({color:0x226644, transparent:true, opacity:0.5, blending:THREE.AdditiveBlending});
  function edraw(pts, mat){
    for(var w=0; w<8; w++){
      var ox=(Math.random()-0.5)*0.25, oy=(Math.random()-0.5)*0.25;
      var ptw = pts.map(function(p){ return new THREE.Vector3(p.x+ox, p.y+oy, p.z); });
      scoutGrp.add(new THREE.Line(new THREE.Buff