<!-- SAGA2 · part 58 -->
ER.camera);
Object.freeze(MASTER.animation);
Object.freeze(MASTER.blocks);
Object.freeze(MASTER.pickup);
Object.freeze(MASTER.inventory);
Object.freeze(MASTER.deploying);
Object.freeze(MASTER.undo);
Object.freeze(MASTER.touch);
Object.freeze(MASTER.ui);
Object.freeze(MASTER.sound);
Object.freeze(MASTER.physics);

// Export for server and client
if(typeof module !== 'undefined' && module.exports){
  module.exports = MASTER;
}
if(typeof window !== 'undefined'){
  window.MASTER_MECHANICS = MASTER;
}

})();


/* deletefreeze1 — THE KING'S SOLE OVERRIDE
 * The only code that can unfreeze the mastered mechanics.
 * By the King's word alone. No other code, no other hand.
 */
(function(){
  if(typeof window !== 'undefined'){
    window.deletefreeze1 = function(){
      // The King speaks — the freeze is lifted
      console.log('The King has spoken. The freeze is lifted.');
      // Return the unfrozen mechanics for modification
      var m = window.MASTER_MECHANICS;
      // Create a mutable copy (the frozen original remains as record)
      var unfrozen = JSON.parse(JSON.stringify(m));
      window.MASTER_MECHANICS_LIVE = unfrozen;
      return unfrozen;
    };
  }
  if(typeof module !== 'undefined' && module.exports){
    module.exports.deletefreeze1 = function(){
      var m = module.exports;
      var unfrozen = JSON.parse(JSON.stringify(m));
      return unfrozen;
    };
  }
})();


===== FILE: public/saga2/people.html =====
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>People I Know — 4 Faces</title>
<style>
  body { margin:0; background:#000; overflow:hidden; font-family:sans-serif; }
  #ui { position:fixed; top:10px; left:10px; color:#0cc; z-index:10; }
  #labels { position:fixed; top:60px; left:10px; color:#ffcc44; z-index:10; font-size:18px; }
  button { background:#ffcc44; border:none; padding:12px 20px; font-size:16px; margin:5px; border-radius:8px; min-height:48px; }
</style>
<script src="/saga2/three.min.js"></script>
</head>
<body>
<div id="ui">
  <div>People I Know — 4 faces</div>
  <button onclick="toggleCarousel()" id="carouselBtn">Slide View</button>
</div>
<div id="labels">The King • The Elder • The Warrior • The Youth</div>
<div id="carousel" style="position:fixed; bottom:20px; left:0; right:0; text-align:center; z-index:20; display:none;">
  <button onclick="prevFace()" style="font-size:32px; padding:20px 30px;">◀</button>
  <span id="faceNum" style="color:#ffcc44; font-size:24px; margin:0 20px;">1 / 4</span>
  <button onclick="nextFace()" style="font-size:32px; padding:20px 30px;">▶</button>
</div>
<script src="/saga2/head-king.js"></script>
<script>var headKing = window.__builtHead;</script>
<script src="/saga2/head-elder.js"></script>
<script>var headElder = window.__builtHead;</script>
<script src="/saga2/head-warrior.js"></script>
<script>var headWarrior = window.__builtHead;</script>
<script src="/saga2/head-youth.js"></script>
<script>var headYouth = window.__builtHead;</script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, innerWidth/innerHeight, 0.1, 2000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

var heads = [
  {g: headKing, name: "The King", x: -45},
  {g: headElder, name: "The Elder", x: -15},
  {g: headWarrior, name: "The Warrior", x: 15},
  {g: headYouth, name: "The Youth", x: 45},
];
heads.forEach(function(h) {
  // Reset position (v160 head is at 0,14,120, move to grid)
  h.g.position.set(h.x, 0, 0);
  // Youth: rounder
  if(h.name === "The Youth") h.g.scale.set(1.15, 0.9, 1.0);
  scene.add(h.g);
});

camera.position.set(0, 14, 100);
camera.lookAt(0, 14, 0);

var carouselMode = false, currentFace = 0;
function toggleCarousel() {
  carouselMode = !carouselMode;
  document.getElementById('carousel').style.display = carouselMode ? 'block' : 'none';
  document.getElementById('carouselBtn').textContent = carouselMode ? 'Grid View' : 'Slide View';
  if(carouselMode) showFace(0);
  else { camera.position.set(0,14,100); camera.lookAt(0,14,0); }
}
function showFace(i) {
  currentFace = ((i % 4) + 4) % 4;
  var x = heads[currentFace].x;
  camera.position.set(x, 14, 50);
  camera.lookAt(x, 14, 0);
  document.getElementById('faceNum').textContent = (currentFace+1) + ' / 4 — ' + heads[currentFace].name;
}
function nextFace(){ showFace(currentFace+1); }
function prevFace(){ showFace(currentFace-1); }
var touchX=0;
document.addEventListener('touchstart', function(e){ touchX=e.touches[0].clientX; }, {passive:true});
document.addEventListener('touchend', function(e){
  if(!carouselMode) return;
  var dx=e.changedTouches[0].clientX-touchX;
  if(dx<-50) nextFace(); else if(dx>50) prevFace();
}, {passive:true});

function animate(){ requestAnimationFrame(animate); renderer.render(scene,camera); }
animate();
</script>
</body>
</html>


===== FILE: public/sag