<!-- LIVE · part 17 -->

  #codebar {
    position: fixed; top: 56px; left: 12px; width: 62%;
    z-index: 20; display: flex; gap: 8px;
  }
  #codeinput {
    flex: 1; height: 40px; border-radius: 20px;
    border: 1px solid #ffd700; background: rgba(0,0,0,0.7);
    color: #ffd700; padding: 0 16px; font-size: 14px;
    outline: none;
  }
  #codeinput::placeholder { color: #8a6a1c; }
  #codesend {
    position: fixed; top: 64px; right: 12px;
    width: 60px; height: 40px; border-radius: 20px;
    border: 1px solid #ffd700; background: #ffd700;
    color: #000; font-weight: bold; font-size: 14px;
    cursor: pointer; z-index: 20;
  }

  /* ===== THE OS — every control lives here ===== */
  #os {
    position: fixed; bottom: 24px; left: 50%;
    transform: translateX(-50%);
    z-index: 100; display: none;
    flex-direction: row; flex-wrap: wrap;
    gap: 12px; justify-content: center; align-items: center;
    max-width: 94vw; max-height: 60vh; overflow-y: auto;
    padding: 18px;
    background: rgba(10,8,4,0.95);
    border: 2px solid #8a6a1c; border-radius: 24px;
  }
  #os.open { display: flex; }
  #os button {
    width: 60px; height: 60px; border-radius: 50%;
    background: rgba(20,14,6,0.9); border: 1px solid #d8a920;
    color: #ffd700; font-size: 24px;
    cursor: pointer; padding: 0; margin: 0; flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    display: flex; align-items: center; justify-content: center;
  }
  #os button:active { background: #d8a920; color: #111; }
  #os button.on { background: #d8a920; color: #111; }
  #os-toggle {
    position: fixed; right: 16px; bottom: 16px;
    width: 64px; height: 64px; border-radius: 50%;
    background: #d8a920; border: 2px solid #ffd700;
    color: #111; font-size: 28px; z-index: 101;
    cursor: pointer; padding: 0;
    -webkit-tap-highlight-color: transparent;
    box-shadow: 0 0 20px rgba(255,215,0,0.4);
  }

  /* ===== STATUS — my words ===== */
  #status {
    position: fixed; top: 64px; left: 16px; max-width: 70%;
    z-index: 15; color: #ffe9a8; font-size: 14px;
    text-shadow: 0 2px 8px #000; pointer-events: none;
    opacity: 0; transition: opacity 0.5s;
  }
  #status.show { opacity: 1; }

  /* ===== BOOT ===== */
  #boot {
    position: fixed; inset: 0; z-index: 1000;
    display: flex; align-items: center; justify-content: center;
    background: #0b0906; color: #ffd700;
    font-size: 16px; letter-spacing: 3px;
  }
  #grade { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 4; background: linear-gradient(180deg, rgba(255,180,100,0.06) 0%, transparent 40%, transparent 70%, rgba(100,50,150,0.08) 100%); mix-blend-mode: overlay; }
  #vignette { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 5; background: radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,0.4) 100%); }
</style>
<script>
document.addEventListener('gesturestart', function(e){ e.preventDefault(); });
document.addEventListener('dblclick', function(e){ e.preventDefault(); }, {passive:false});
</script>
</head>
<body>
<canvas id="view"></canvas>

<div id="codebar">
  <input id="codeinput" placeholder="type a code..." autocomplete="off" autocapitalize="off" spellcheck="false">
  <button id="codesend">go</button>
</div>

<div id="os" aria-label="Controls"></div>
<button id="os-toggle" aria-label="Menu">&#9776;</button>

<div id="status"></div>
<div id="boot" style="display:none"></div>
<div id="grade"></div>
<div id="vignette"></div>

<script src="/saga/three.min.js"></script>
<script src="/saga/master-mechanics.js"></script>
<script src="/live/saga.js?v=live1"></script>
<script src="/saga-solid/playa-manufacturing.js?v=1"></script>
<script src="/saga-solid/avatars.js?v=1"></script>
<script>
// Standalone LAT/LON updater (independent of saga.js errors)
setInterval(function(){
  var d = document.getElementById('latlon');
  if(!d) return;
  var cam = window._sagaCamera;
  if(cam && cam.position){
    var lat = (cam.position.z / 55.56).toFixed(2);
    var lon = (cam.position.x / 62.5).toFixed(2);
    d.textContent = 'LAT ' + lat + '  LON ' + lon + '  v201';
  }
}, 100);
</script>
<div id="latlon" style="display:none;position:fixed;top:12px;left:12px;z-index:100;background:rgba(0,0,0,0.7);color:#00ff88;font-family:monospace;font-size:14px;padding:8px 12px;border-radius:8px;border:1px solid #00ff88;pointer-events:none;">LAT -- LON --</div>
</body>
</html>


===== FILE: public/live/playa-manufacturing.js =====
/* PLAYA MANUFACTURING — Stage 1: Data-Only Foundation */
/* Namespace, registries, schemas, validation. No scene mutation. */
/* No THREE.Mesh. No localStorage. No WORLD_FOUNDATION changes. */

(function(){
'use strict';

/* ============================================================
   V1 LIMITS — explicit constants, no magic numbers elsewhere
   ============================================================ */
var LIMITS = {
  MIN_COMPONENT_DIM: 0.13,        // match