<!-- SAGA2 · part 102 -->
, opacity:0.9});
  var goldMat = new THREE.LineBasicMaterial({color:0xffcc44, transparent:true, opacity:0.9});
  function hline(pts, mat, grp){
    grp.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(pts.map(function(p){
      return new THREE.Vector3(p[0],p[1],p[2]); })), mat));
  }
  function hellipse(cx,cy,cz,rx,ry,mat,grp){
    var pts=[];
    for(var i=0;i<=16;i++){ var a=(i/16)*Math.PI*2;
      pts.push(new THREE.Vector3(cx+Math.cos(a)*rx, cy+Math.sin(a)*ry, cz)); }
    hline(pts, mat, grp);
  }
  function buildHeadVariant(idx, px){
    var grp = new THREE.Group();
    var es = idx % 5;
    var jw = Math.floor(idx/5);
    // slight variations — each one different
    var eyeDX = 1.9 + es*0.4 + (idx%3)*0.1;
    var eyeSize = 1.15 + (es%2)*0.25 + (idx%4)*0.05;
    var jawW = 2.6 + jw*0.65 + (idx%3)*0.12;
    var noseL = 2.1 + (jw%2)*0.5 + (idx%5)*0.08;
    var mouthW = 1.6 + es*0.28 + (idx%4)*0.07;
    var browH = 2.1 + (idx%3)*0.15;
    // head outline — cranium
    hellipse(0, 0.5, 0, 4.2, 5.5, headMat, grp);
    hellipse(0, 1.5, -0.5, 3.8, 4.8, headMat, grp);
    // jaw — varied
    hline([[-3.8,-1,0.5],[-jawW,-3.5,0.8],[-jawW*0.5,-5,1],[0,-5.5,1.2],[jawW*0.5,-5,1],[jawW,-3.5,0.8],[3.8,-1,0.5]], headMat, grp);
    // center line
    hline([[0,5.5,3.2],[0,3,4.0],[0,0.5,4.2],[0,-2,4.3],[0,-4,4.0]], goldMat, grp);
    // DETAILED EYES — banknote style
    function detailEye(cx){
      hellipse(cx, 0.5, 3.8, eyeSize, eyeSize*0.55, headMat, grp);
      // iris rings
      for(var ir=0; ir<3; ir++){
        hellipse(cx, 0.5, 3.85, eyeSize*0.55-ir*0.18, eyeSize*0.3-ir*0.1, ir%2?goldMat:headMat, grp);
      }
      hellipse(cx, 0.5, 3.9, 0.28, 0.28, goldMat, grp);
      // upper lid fold
      hline([[cx-eyeSize*0.9,1.6,3.7],[cx,1.9,3.85],[cx+eyeSize*0.9,1.6,3.7]], goldMat, grp);
      // lashes
      for(var lh=0; lh<5; lh++){
        var lx = cx-eyeSize*0.7+lh*eyeSize*0.35;
        hline([[lx,1.3,3.75],[lx+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