<!-- SAGA2 · part 25 -->
-10, 5, 10);
scene.add(fill);
var rim = new THREE.DirectionalLight(0xffffff, 0.3);
rim.position.set(0, 10, -15);
scene.add(rim);

// MATERIALS (proper PBR)
var skin = new THREE.MeshStandardMaterial({color:0xd4a574, roughness:0.6, metalness:0.0});
var eyeWhiteMat = new THREE.MeshStandardMaterial({color:0xffffff, roughness:0.15, metalness:0.0});
var irisMat = new THREE.MeshStandardMaterial({color:0x2288cc, roughness:0.3, metalness:0.0});
var pupilMat = new THREE.MeshStandardMaterial({color:0x111111, roughness:0.2, metalness:0.0});
var lipMat = new THREE.MeshStandardMaterial({color:0xbb5555, roughness:0.35, metalness:0.0});
var hairMat = new THREE.MeshStandardMaterial({color:0x332211, roughness:0.8, metalness:0.0});

var avatar = new THREE.Group();
scene.add(avatar);

function addMesh(geo, mat, x, y, z){
  var m = new THREE.Mesh(geo, mat);
  m.position.set(x, y, z);
  m.castShadow = true;
  m.receiveShadow = true;
  avatar.add(m);
  return m;
}

// HEAD (proper proportions, high-poly)
var head = addMesh(new THREE.SphereGeometry(3.0, 48, 32), skin, 0, 16, 0);
head.scale.set(0.9, 1.15, 0.95);

// JAW
var jaw = addMesh(new THREE.SphereGeometry(2.2, 32, 24), skin, 0, 14.0, 0.3);
jaw.scale.set(0.85, 0.9, 0.85);

// EYES
for(var s=-1; s<=1; s+=2){
  var ex = s*1.15;
  var scl = addMesh(new THREE.SphereGeometry(0.55, 32, 24), eyeWhiteMat, ex, 16.2, 2.45);
  scl.scale.set(1.3, 0.8, 0.6);
  var iri = addMesh(new THREE.CircleGeometry(0.28, 32), irisMat, ex, 16.2, 2.78);
  var pup = addMesh(new THREE.CircleGeometry(0.12, 24), pupilMat, ex, 16.2, 2.79);
  // Upper lid
  var lid = addMesh(new THREE.TorusGeometry(0.55, 0.08, 12, 32, Math.PI), skin, ex, 16.2, 2.55);
  lid.rotation.x = 0.2;
  // Brow
  var brow = addMesh(new THREE.SphereGeometry(0.35, 16, 12), hairMat, ex, 17.1, 2.6);
  brow.scale.set(1.8, 0.4, 0.6);
}

// NOSE
var noseBridge = addMesh(new THREE.CylinderGeometry(0.18, 0.28, 1.8, 16), skin, 0, 15.8, 2.9);
noseBridge.rotation.x = 0.1;
var noseTip = addMesh(new THREE.SphereGeometry(0.32, 24, 18), skin, 0, 14.9, 3.05);
noseTip.scale.set(1.2, 0.9, 0.9);
for(var n=-1; n<=1; n+=2){
  addMesh(new THREE.SphereGeometry(0.12, 12, 10),
    new THREE.MeshStandardMaterial({color:0x442222, roughness:0.9}), n*0.25, 14.75, 2.95);
}

// MOUTH
var upperLip = addMesh(new THREE.SphereGeometry(0.45, 24, 18), lipMat, 0, 13.9, 2.7);
upperLip.scale.set(1.8, 0.4, 0.6);
var lowerLip = addMesh(new THREE.SphereGeometry(0.45, 24, 18), lipMat, 0, 13.5, 2.65);
lowerLip.scale.set(1.6, 0.55, 0.65);

// EARS
for(var e=-1; e<=1; e+=2){
  var ear = addMesh(new THREE.SphereGeometry(0.55, 24, 18), skin, e*2.75, 16.0, 0.2);
  ear.scale.set(0.4, 1.1, 0.7);
}

// NECK
addMesh(new THREE.CylinderGeometry(0.9, 1.1, 2.0, 24), skin, 0, 12.5, 0);

// TORSO
var torso = addMesh(new THREE.CylinderGeometry(2.2, 1.6, 6.0, 32), skin, 0, 8.5, 0);
torso.scale.set(1.2, 1.0, 0.8);

// SHOULDERS + ARMS
for(var a=-1; a<=1; a+=2){
  addMesh(new THREE.SphereGeometry(0.9, 24, 18), skin, a*2.6, 11.0, 0);
  var uArm = addMesh(new THREE.CylinderGeometry(0.55, 0.45, 3.5, 20), skin, a*2.9, 8.8, 0);
  uArm.rotation.z = a*0.12;
  var fArm = addMesh(new THREE.CylinderGeometry(0.45, 0.35, 3.2, 20), skin, a*3.1, 5.8, 0.1);
  fArm.rotation.z = a*0.08;
  var hand = addMesh(new THREE.SphereGeometry(0.55, 20, 16), skin, a*3.2, 3.8, 0.2);
  hand.scale.set(0.8, 1.3, 0.5);
}

// HIPS + LEGS
var hips = addMesh(new THREE.SphereGeometry(1.8, 32, 24), skin, 0, 5.0, 0);
hips.scale.set(1.15, 0.85, 0.9);
for(var l=-1; l<=1; l+=2){
  addMesh(new THREE.CylinderGeometry(0.7, 0.55, 4.0, 20), skin, l*1.0, 2.5, 0);
  addMesh(new THREE.CylinderGeometry(0.55, 0.4, 3.8, 20), skin, l*1.0, -1.5, 0);
  var foot = addMesh(new THREE.SphereGeometry(0.55, 20, 16), skin, l*1.0, -3.6, 0.4);
  foot.scale.set(0.9, 0.6, 1.6);
}

// HAIR (simple cap)
var hair = addMesh(new THREE.SphereGeometry(3.05, 48, 32, 0, Math.PI*2, 0, Math.PI*0.45), hairMat, 0, 16.3, -0.2);

// GROUND (for shadows)
var ground = new THREE.Mesh(new THREE.PlaneGeometry(100, 100),
  new THREE.MeshStandardMaterial({color:0x111111, roughness:1.0}));
ground.rotation.x = -Math.PI/2;
ground.position.y = -4.2;
ground.receiveShadow = true;
scene.add(ground);

// ANIMATE
function animate(){
  requestAnimationFrame(animate);
  avatar.rotation.y = Math.sin(Date.now()*0.0003)*0.15; // gentle sway
  renderer.render(scene, camera);
}
animate();

// Resize
window.addEventListener('resize', function(){
  camera.aspect = window.innerWidth/window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>


===== FILE: public/saga2/buildHead.js =====
// FACE TEMPLATE 1 — v160 intaglio human head (ribbons)
// Extracted from /saga2 saga.js v160

  function buildHead(){
    function ellipse(cx,cy,cz,rx,ry,mat){
      var pts=[];
      for(var i=0;i<=24;i++){
        var a=(i/24)*Math.PI*2;
        pts.push(new THREE.Vector3(cx+Math.cos(a)*rx, cy+Math.sin(a)*ry, cz