<!-- NEWWORLD · part 1 -->
===== FILE: public/newworld/engine.js =====
/* ============================================================
   ENGINE.js
   Category: CORE / RENDERING
   Purpose: Scene, camera, renderer, lights — the foundation
   Dependencies: THREE.js (CDN)
   Provides: Engine.scene, Engine.camera, Engine.renderer
   ============================================================ */

var Engine = (function(){
  'use strict';
  
  /* ----- SCENE ----- */
  var scene = new THREE.Scene();
  scene.background = new THREE.Color(0x87ceeb);  // Sky blue — light is ON
  scene.fog = new THREE.Fog(0x87ceeb, 100, 500);  // Fade distance
  
  /* ----- CAMERA ----- */
  var camera = new THREE.PerspectiveCamera(
    75,                                    // FOV: wide enough for mobile
    window.innerWidth/window.innerHeight,  // Aspect: fills screen
    0.1,                                   // Near: 0.1 units
    1000                                   // Far: 1000 units
  );
  camera.position.set(0, 10, 20);  // Start: above and behind origin
  
  /* ----- RENDERER ----- */
  var renderer = new THREE.WebGLRenderer({
    antialias: true,             // Smooth edges
    preserveDrawingBuffer: true  // REQUIRED for Eyes capture — without this, screenshots are black
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;  // Real-time shadows
  document.body.appendChild(renderer.domElement);
  
  /* ----- LIGHTS ----- */
  // Ambient: base fill so nothing is pitch black
  var ambient = new THREE.AmbientLight(0xffffff, 0.9);
  scene.add(ambient);
  
  // Sun: directional key light with shadows
  var sun = new THREE.DirectionalLight(0xffffff, 1.2);
  sun.position.set(50, 100, 50);
  sun.castShadow = true;
  scene.add(sun);
  
  /* ----- RESIZE HANDLER ----- */
  // Keeps aspect correct on rotation/resize (mobile critical)
  window.addEventListener('resize', function(){
    camera.aspect = window.innerWidth/window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  });
  
  /* ----- PUBLIC API ----- */
  return {
    scene: scene,        // Add objects here
    camera: camera,      // Control viewpoint here
    renderer: renderer   // Render calls go here
  };
})();


===== FILE: public/newworld/index.html =====
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>New World</title>
<style>
  body { margin: 0; overflow: hidden; background: #000; }
  canvas { display: block; }
  #hud { position: fixed; top: 10px; left: 10px; color: #0ff; font-family: monospace; font-size: 14px; z-index: 100; }
</style>
</head>
<body>
<div id="hud">NEW WORLD</div>
<!-- 2026-10-09 Phase 0: under-construction notice; the world stays playable behind it -->
<div id="nw-uc" role="dialog" aria-labelledby="nw-uc-t" style="position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.72);padding:20px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif">
  <div style="max-width:360px;width:100%;background:#0b0b0b;border:2px solid #c1121f;border-radius:14px;box-shadow:0 0 28px rgba(193,18,31,.45);padding:22px 20px;text-align:center;color:#eee">
    <div style="color:#e5383b;font-size:12px;letter-spacing:3px;font-weight:700">NEW WORLD</div>
    <h2 id="nw-uc-t" style="margin:8px 0 10px;font-size:22px;letter-spacing:1px;color:#fff">Under construction</h2>
    <p style="margin:0 0 18px;font-size:14px;line-height:1.5;color:#bbb">This world is still being built. You can look around, but things may change or break.</p>
    <button type="button" id="nw-uc-go" style="width:100%;padding:12px;border:0;border-radius:10px;background:#c1121f;color:#fff;font-size:16px;font-weight:700;letter-spacing:1px">Enter anyway</button>
    <a href="/" style="display:block;margin-top:12px;color:#e5383b;font-size:14px;text-decoration:none">&larr; Back to Epistles</a>
  </div>
</div>
<script>
(function(){var o=document.getElementById('nw-uc');try{if(sessionStorage.getItem('nwUcSeen')){o.remove();return;}}catch(e){}
document.getElementById('nw-uc-go').onclick=function(){try{sessionStorage.setItem('nwUcSeen','1');}catch(e){}o.remove();};})();
</script>
<button id="radio-btn" style="position:fixed;bottom:20px;right:10px;padding:12px 16px;background:#00aaaa;border:none;border-radius:8px;color:#fff;font-size:16px;z-index:9998;">&#10022; Radio</button>
<script src="/newworld/three.min.js"></script>
<script src="/newworld/engine.js"></script>
<script src="/newworld/player.js"></script>
<script src="/newworld/input.js"></script>
<script src="/newworld/world.js"></script>
<script src="/newworld/radio.js"></script>
<script src="/newworld/main.js"></script>
<script>
// Wire the HUD radio button to the Radio panel
document.getElementById('radio-btn').onclick = function(){ Radio.show(); };
</scr