<!-- SOLID-PLAYTIME · part 197 -->
roughness:0.15,metalness:0.35})
  );
  rubyHit=new T.Mesh(new T.SphereGeometry(0.7,8,6),new T.MeshBasicMaterial({visible:false}));
  grp.add(gem); grp.add(rubyHit);
  grp.position.set(sx,rubyBaseY,sz);
  Kt.scene.add(grp);
  ruby=gem;
  try{ localStorage.setItem('solid-ruby-v1',JSON.stringify({x:sx,z:sz})); }catch(e){}
  var t0=Date.now();
  setInterval(function(){
    rubyT+=0.09;
    try{
      grp.position.y=rubyBaseY+Math.sin(rubyT)*0.14;
      var base=(window.camLinked===false)?1.7:0.9;
      gem.material.emissiveIntensity=base+0.45*Math.sin(rubyT*1.4);
    }catch(e){}
  },90);
}

function boot(){
  spawnRuby();
  var cv=null;
  try{ cv=Kt.renderer.domElement; }catch(e){}
  if(!cv) return;

  function dist2(){ return Math.hypot(pA.x-pB.x,pA.y-pB.y); }

  cv.addEventListener('pointerdown',function(e){
    if(pA===null){ pA={id:e.pointerId,x:e.clientX,y:e.clientY}; downX=e.clientX; downY=e.clientY; }
    else if(pB===null&&e.pointerId!==pA.id){ pB={id:e.pointerId,x:e.clientX,y:e.clientY}; pinchD0=dist2(); pinchV0=(window.camLinked===false)?freeDist:window.KtZoom; }
    if(window.camLinked===false&&pB===null){ dragging=true; ldx=e.clientX; ldy=e.clientY; }
  });
  cv.addEventListener('pointermove',function(e){
    var upd=false;
    if(pA&&e.pointerId===pA.id){ pA.x=e.clientX; pA.y=e.clientY; upd=true; }
    if(pB&&e.pointerId===pB.id){ pB.x=e.clientX; pB.y=e.clientY; upd=true; }
    if(upd&&pA&&pB&&pinchD0>0){
      var f=dist2()/pinchD0;
      if(window.camLinked===false) freeDist=Math.max(1,Math.min(150,pinchV0/f));
      else setZoom(pinchV0*f);
    }else if(dragging&&window.camLinked===false&&pA&&e.pointerId===pA.id){
      freeYaw-=(e.clientX-ldx)*0.0052;
      freePitch=Math.max(-1.2,Math.min(1.2,freePitch-(e.clientY-ldy)*0.0052));
      ldx=e.clientX; ldy=e.clientY;
    }
  });
  function endP(e){
    if(pA&&e.pointerId===pA.id) pA=null;
    if(pB&&e.pointerId===pB.id) pB=null;
    if(!pA||!pB) pinchD0=0;
    dragging=false;
  }
  cv.addEventListener('pointerup',endP);
  cv.addEventListener('pointercancel',endP);
  cv.addEventListener('wheel',function(e){
    e.preventDefault();
    var f=Math.exp(-e.deltaY*0.0012);
    if(window.camLinked===false) freeDist=Math.max(1,Math.min(150,freeDist/f));
    else setZoom(window.KtZoom*f);
  },{passive:false});

  /* ruby tap: capture-phase pointerup beats the build tap layer */
  var rayc=new T.Raycaster(), ndc=new T.Vector2(), pd=null;
  document.addEventListener('pointerdown',function(e){ pd={x:e.clientX,y:e.clientY}; },true);
  document.addEventListener('pointerup',function(e){
    try{
      if(!pd) return;
      var moved=Math.hypot(e.clientX-pd.x,e.clientY-pd.y);
      pd=null;
      if(moved>12||!rubyHit) return;
      if(e.target&&e.target.closest&&e.target.closest('button')) return;
      ndc.x=(e.clientX/window.innerWidth)*2-1;
      ndc.y=-(e.clientY/window.innerHeight)*2+1;
      rayc.setFromCamera(ndc,Kt.camera);
      var hits=rayc.intersectObject(rubyHit,false);
      if(hits.length){
        e.stopPropagation();
        e.preventDefault();
        toggle();
      }
    }catch(err){}
  },true);

  /* free-camera driver: runs after the game's loop each frame */
  var cp=new T.Vector3();
  function frame(){
    requestAnimationFrame(frame);
    try{
      if(window.camLinked===false&&freeTgt){
        var sp=Math.sin(freePitch), cp2=Math.cos(freePitch);
        cp.set(
          freeTgt.x+freeDist*cp2*Math.sin(freeYaw),
          freeTgt.y+freeDist*sp,
          freeTgt.z+freeDist*cp2*Math.cos(freeYaw)
        );
        var gy=groundY(cp.x,cp.z)+0.5;
        if(cp.y<gy) cp.y=gy;
        Kt.camera.position.copy(cp);
        Kt.camera.lookAt(freeTgt);
      }
    }catch(e){}
  }
  requestAnimationFrame(frame);

  toast('TAP THE RUBY TO FREE THE CAMERA · PINCH TO ZOOM','#ff5566');
}
}catch(err){}
})()})(),()=>{Kt.dispose(),Y.current=null}},[e.data,L]),Ze(()=>{let I=ot.current,lt=St.current;if(!I)return;let Kt=(Yt)=>Yt.preventDefault();return I.addEventListener("touchstart",Kt,{passive:!1}),lt?.addEventListener("touchstart",Kt,{passive:!1}),()=>{I.removeEventListener("touchstart",Kt),lt?.removeEventListener("touchstart",Kt)}},[e.data,r]),Ze(()=>{let I=()=>be(),lt=()=>{if(document.hidden)be()};return window.addEventListener("pagehide",I),document.addEventListener("visibilitychange",lt),()=>{window.removeEventListener("pagehide",I),document.removeEventListener("visibilitychange",lt)}},[be]),Ze(()=>{if(Y.current?.setActive(r==="world"),r==="proclamation"){let I=Bt.current;if(I)I.currentTime=0,I.play()}},[r]),Ze(()=>{let I=(Kt)=>{let Yt=Y.current;if(!Yt||r!=="world")return;let de=Kt.key.toLowerCase();if(de==="w"||de==="arrowup")Yt.setMovement(0,1);if(de==="s"||de==="arrowdown")Yt.setMovement(0,-1);if(de==="a"||de==="arrowleft")Yt.setMovement(-1,0);if(de==="d"||de==="arrowright")Yt.setMovement(1,0);if(de==="shift")Yt.setRun(!0);if(de==="v")Yt.setVision(!0);if(de==="x")Yt.attack();if(de===" ")Yt.jump();if(de==="e")Y