Spaces:
Running
Running
File size: 300,339 Bytes
4ec6735 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./StereoEffect-8X11TNUP.js","./three-DMwvpBUV.js","./rolldown-runtime-CEoa-xHZ.js","./physics-Bz_ouFt8.js","./ort.bundle.min--hz_0CH4.js","./mediapipe-Ck-u_eH7.js"])))=>i.map(i=>d[i]);
import{n as e,r as t,t as n}from"./mediapipe-Ck-u_eH7.js";import{$ as r,A as i,B as a,C as o,D as s,E as c,F as l,G as u,H as d,I as f,J as p,K as m,L as h,M as g,N as _,O as ee,P as v,Q as te,R as ne,S as re,T as ie,U as y,V as b,W as ae,X as x,Y as oe,Z as se,_ as ce,_t as le,a as ue,at as de,b as fe,bt as pe,c as me,ct as he,d as ge,dt as _e,et as ve,f as ye,ft as be,g as xe,gt as S,h as Se,ht as Ce,i as we,it as Te,j as Ee,k as De,l as Oe,lt as ke,m as Ae,mt as je,nt as Me,o as Ne,ot as Pe,p as Fe,pt as Ie,q as Le,rt as Re,s as ze,st as Be,tt as Ve,u as He,ut as Ue,v as We,vt as Ge,w as Ke,x as qe,y as Je,yt as Ye,z as Xe}from"./three-DMwvpBUV.js";var Ze=4;function Qe(e){return document.getElementById(e===`error`?`error-host`:`banner-host`)}var $e={error:`M12 8v5M12 17h.01`,banner:`M12 16v-5M12 8h.01`};function et(e){let t=`http://www.w3.org/2000/svg`,n=document.createElementNS(t,`svg`);n.setAttribute(`class`,`panel-ico`),n.setAttribute(`viewBox`,`0 0 24 24`),n.setAttribute(`fill`,`none`),n.setAttribute(`stroke`,`currentColor`),n.setAttribute(`stroke-width`,`2.3`),n.setAttribute(`stroke-linecap`,`round`),n.setAttribute(`aria-hidden`,`true`);let r=document.createElementNS(t,`circle`);r.setAttribute(`cx`,`12`),r.setAttribute(`cy`,`12`),r.setAttribute(`r`,`9`);let i=document.createElementNS(t,`path`);return i.setAttribute(`d`,$e[e]||$e.banner),n.append(r,i),n}function tt(e,t,n,r={}){let i=Qe(e);if(!i)return null;let a=document.createElement(`section`);a.className=`${e===`error`?`error-panel`:`banner-panel`} glass-panel`,a.setAttribute(`role`,e===`error`?`alert`:`status`);let o=et(e),s=document.createElement(`div`),c=document.createElement(`p`),l=document.createElement(`strong`);l.textContent=t,c.textContent=n,s.append(l,c),a.append(o,s);let u=document.createElement(`button`);if(u.type=`button`,u.className=`panel-x`,u.setAttribute(`aria-label`,e===`error`?`Dismiss error`:`Dismiss notice`),u.textContent=`×`,u.addEventListener(`click`,()=>a.remove()),a.appendChild(u),r.linkHref){let e=document.createElement(`a`);e.href=r.linkHref,e.textContent=r.linkLabel||`Open settings`,e.rel=`noopener`,e.style.display=`inline-block`,e.style.marginTop=`8px`,s.appendChild(e)}for(i.prepend(a);i.children.length>Ze;)i.lastElementChild?.remove();return r.timeout!==0&&window.setTimeout(()=>a.remove(),r.timeout||(e===`error`?9e3:4500)),a}function C(e,t=`AR Error`,n={}){return tt(`error`,t,String(e||`Unknown AR error.`),n)}function w(e,t=`JARVIS AR`,n={}){return tt(`banner`,t,String(e||``),n)}var nt={live:[`ok`,`Live`],stream:[`ok`,`Live`],requesting:[`warn`,`Asking permission`],standby:[`idle`,`Standby`],failed:[`error`,`Unavailable`],"slam+floor":[`ok`,`Full`],"8thwall-slam":[`ok`,`Full`],"8th wall":[`ok`,`Full`],"basic floor":[`ok`,`Basic`],"webxr/basic":[`ok`,`Basic`],"basic camera":[`ok`,`Basic`],"no face mesh":[`warn`,`Limited`],"no object detect":[`warn`,`Limited`],waiting:[`warn`,`Finding surfaces`],lost:[`error`,`Lost`],linked:[`ok`,`Linked`],offline:[`error`,`Offline`]},rt={ok:`#48e08a`,warn:`#ffb800`,error:`#ff4d4f`,idle:`rgba(255, 255, 255, 0.55)`};function it(e){let t=String(e??``).trim().toLowerCase();if(nt[t])return nt[t];for(let e of Object.keys(nt))if(t.startsWith(e)){let[t,n]=nt[e];return[t,n]}return[`warn`,String(e??``)]}function T(e,t){let n=document.getElementById(e);if(!n)return;let[r,i]=it(t);n.textContent=i,n.setAttribute(`data-state`,r),n.style.color=rt[r]||``,n.setAttribute(`aria-live`,r===`error`?`assertive`:`off`)}function E(e,t){let n=document.getElementById(`loading-text`),r=document.getElementById(`loading-progress`);n&&e&&(n.textContent=e),r&&Number.isFinite(t)&&(r.style.width=`${Math.max(0,Math.min(100,t))}%`);let i=document.querySelector(`#loading-screen .loading-ring`);i&&Number.isFinite(t)&&t<100&&i.classList.remove(`is-ready`,`is-error`)}function at(e=`Engine ready`){let t=document.querySelector(`#loading-screen .loading-ring`),n=document.querySelector(`#loading-screen .progress-track`),r=document.getElementById(`start-ar`);t&&(t.classList.remove(`is-error`),t.classList.add(`is-ready`)),n&&n.classList.add(`hidden`),r&&(r.disabled=!1,r.textContent=`START AR`);let i=document.getElementById(`loading-text`);i&&(i.textContent=e)}function ot(){document.getElementById(`loading-screen`)?.classList.add(`hidden`)}var D={config:null,started:!1,trackingMode:`standby`,xrAvailable:!1,xrStarted:!1,xrCamera:null,xrScene:null,scene:null,camera:null,renderer:null,aframeScene:null,aframeCamera:null,fallbackScene:null,fallbackCamera:null,fallbackRenderer:null,fallbackActive:!1,fallbackLoopHandle:0,cameraVideo:null,gestureFrameCanvas:null,gestureFrameReady:!1,worldPoints:[],worldPointBuffer:[],placedObjects:[],selectedObject:null,floorY:-1.2,pendingModelToPlace:``,css3d:null,pipelineOrder:[],frameCount:0,isVRMode:!1,focusQuality:{enabled:!1,focusX:.5,focusY:.5,source:`screen-center`,avgFrameMs:16.7,pixelRatio:1,tier:`high`},spatialAudio:{enabled:!1,unlocked:!1,listener:null,context:null,micReady:!1,micPermission:`unknown`,voiceRecognition:!1,speechSynthesis:!1,wakeWindowUntil:0,lastVoiceCommandAt:0,environmentProfile:`default`,roomProfile:{name:`default`,refDistance:.72,maxDistance:8,rolloffFactor:1.6,dampening:.08}},nativeOptions:{immersion:1,hdrEnabled:!0,handTrackingEnabled:!0,spatialAudioEnabled:!0,activeEnvironment:`default`},compositor:{mode:`browser-proxy`,native:!1,reprojection:!1,passthroughBlend:`browser`,depthComposition:!1,foveation:0,framebufferScaleFactor:1,eyeBuffers:`mono`,frameBudgetMs:16.6,avgFrameMs:16.6,lastFrameAt:0,refreshRate:60,renderScale:1,convergence:1.4,lensProfile:`default`,eyeAspect:1,vignetteStrength:.12,motionComfort:`balanced`,stereoFrustum:!0},browserProfile:{browser:`unknown`,engine:`unknown`,platform:`unknown`,isAndroid:!1,isIOS:!1,isVisionOS:!1,isQuest:!1,isWebView:!1,isSafari:!1,isChrome:!1,isFirefox:!1,isEdge:!1,webXRSupportExpected:!1,webXRFragmented:!1,latencyCeilingMs:16.7,limits:{},notes:[]},capabilities:{browserWebAR:!0,eightWallSLAM:!1,webXRAvailable:!1,webXRHitTest:!1,manualCamera:!1,mediaPipeHands:!1,spatialAudio:!1,gazeProxy:!1,controllerAbstraction:!1,handEyeFusion:!1,spatialWindowing:!1,passthroughBlendProxy:!1,comfortAdaptation:!1,predictivePoseFiltering:!1,accessibilityInteraction:!1,gestureArbitration:!1,selectionArbitration:!1,dragManipulationProxy:!1,openXRCompositorProxy:!1,reprojectionProxy:!1,depthCompositionProxy:!1,eyeBufferPair:!1,nativeFrameTiming:!1,posePredictionProxy:!1,approximateAnchors:!0,truePersistentWorldAnchors:!1,eyeTracking:!1,foveatedRendering:!1,nativeCompositor:!1,guardianBoundary:!1,controllerHaptics:!1,nativeOpenXRBridge:!1,browserLatencyCeiling:!0,limitedSensorAccess:!0,limitedOSIntegration:!0,limitedCompositorControl:!0,persistentAnchorSupport:!1,backgroundExecutionLimited:!0,passthroughControlLimited:!0,spatialMemoryLimited:!0,headsetOptimizationAccessLimited:!0,webXRFragmented:!1,safariWebXRLimitations:!1,visionOSBrowserRestrictions:!1,androidBrowserInconsistency:!1,webViewInconsistency:!1,eyeTrackingProxy:!1,persistentSpatialMemory:!1,ultraStableAnchoring:!1,naturalWindowPlacement:!1,depthAwareImmersion:!1,environmentAwareUI:!1,headsetComfortSystems:!1,lowLatencyCompositing:!1,stereoEyeBuffers:!1,stereoFrustumCalibration:!1,refreshRateNegotiation:!1,timestampSync:!1,motionSicknessMitigation:!1,teleportLocomotion:!1,smoothLocomotionSafeguards:!1,roomBoundaryVisualization:!1,nativeHandMeshProxy:!1,controllerHapticsProxy:!1,lowLightTrackingResilience:!1,headsetCameraCalibrationProxy:!1,deviceCapabilityMatrix:!1,renderScaleStability:!1,stereoUiAnchoring:!1,antiAliasEdgeProtection:!1,zFightGuard:!1,sustainedFramerateGuard:!1,orientationLockStability:!1,sensorPermissionPersistenceProxy:!1,motionComfortVignette:!1},telemetry:{frameMs:16.7,qualityTier:`high`,droppedFrames:0,startedAt:0,lastNativeStatusAt:0},runtime:{phase:`created`,lifecycleState:`created`,architecture:`unknown`,experienceClass:`unknown`,spatialRuntimeClass:`unknown`,platformRole:`unknown`,authority:`none`,authoritativeRuntime:`none`,activeEngine:`none`,activeRenderer:`none`,rendererOwner:`none`,restartCount:0,lastError:``,subsystems:{},cleanupCount:0,conflicts:[],readiness:{boot:!1,scene:!1,camera:!1,tracking:!1,ui:!1},lifecycleHistory:[],permissionState:`unknown`,degradationReason:``,spatialGapStatement:``,rootCauseSummary:``,visionProGapSummary:``,visionProMissingFeatures:[]},sessionAnchor:{originMatrix:null,originPosition:[0,0,0],originQuaternion:[0,0,0,1],restoredAt:0},handState:{hands:[],gestures:new Map},sceneInitialized:!1,resizeBound:!1,fallbackLoopStarted:!1,aframeCameraSyncAdded:!1,liveSceneReady:!1,paused:!1,tracking:null,trackingQuality:`initializing`,trackingAPI:null,detectedPlanes:[]},st=new EventTarget,ct=new Set,lt=new Set,ut=new Set,dt=new Map;function O(e,t){let n=e=>t(e.detail);return st.addEventListener(e,n),()=>st.removeEventListener(e,n)}function k(e,t={}){st.dispatchEvent(new CustomEvent(e,{detail:t}))}function ft(e,t={}){D.runtime.phase=String(e||`unknown`),D.runtime.lastTransitionAt=Date.now();try{document.body.dataset.jarvisRuntimePhase=D.runtime.phase}catch{}return k(`runtime-phase`,{phase:D.runtime.phase,detail:t}),kt(`AR phase: ${D.runtime.phase}`),D.runtime.phase}function A(e,t={}){let n=String(e||`unknown`);D.runtime.lifecycleState=n,D.runtime.lifecycleHistory.push({state:n,detail:t,at:Date.now()}),D.runtime.lifecycleHistory.length>24&&D.runtime.lifecycleHistory.splice(0,D.runtime.lifecycleHistory.length-24);try{document.body.dataset.jarvisLifecycleState=n}catch{}return k(`runtime-lifecycle`,{state:n,detail:t}),kt(`AR lifecycle: ${n}`),n}function j(e,t=!0){if(!e)return!1;D.runtime.readiness[e]=!!t;try{document.body.dataset.jarvisReady=Object.entries(D.runtime.readiness).filter(([,e])=>e).map(([e])=>e).join(`,`)}catch{}return k(`runtime-readiness`,{key:e,ready:!!t,readiness:D.runtime.readiness}),D.runtime.readiness[e]}function pt(){D.started=!1,D.xrStarted=!1,D.xrAvailable=!1,D.xrSession=null,D.xrHitTestSource=null,D.liveSceneReady=!1,D.paused=!1,D.cameraVideo=null,D.gestureFrameCanvas=null,D.gestureFrameReady=!1,D.trackingMode=`standby`,D.runtime.permissionState=`unknown`,D.runtime.degradationReason=``,D.runtime.rendererOwner=`none`,D.runtime.activeRenderer=`none`,D.runtime.activeEngine=`none`;for(let e of Object.keys(D.runtime.readiness))D.runtime.readiness[e]=!1;A(`stopped`)}function M(e,t=`ready`,n={}){let r=String(e||``).trim();if(!r)return null;D.runtime.subsystems[r]={status:t,detail:n,updatedAt:Date.now()};try{document.body.dataset.jarvisSubsystems=Object.keys(D.runtime.subsystems).join(`,`)}catch{}return k(`runtime-subsystem`,{name:r,status:t,detail:n}),D.runtime.subsystems[r]}function mt(e,t={}){let n=String(e||`unknown`),r=D.runtime.authoritativeRuntime;if(r!==`none`&&r!==n&&!t.force){let e={type:`runtime`,current:r,attempted:n,at:Date.now()};return D.runtime.conflicts.push(e),M(`blocked-runtime:${n}`,`blocked`,e),k(`runtime-authority-conflict`,e),r}D.runtime.authoritativeRuntime=n,D.runtime.authority=n,D.runtime.activeEngine=n,D.runtime.authorityChangedAt=Date.now();try{document.body.dataset.jarvisRuntimeAuthority=n}catch{}return k(`runtime-authority`,{previous:r,authority:n,detail:t}),M(`runtime:${n}`,`authoritative`,t),n}function ht(e,t=null,n={}){let r=String(e||`unknown`),i=D.runtime.rendererOwner||`none`;if(!(n.takeover||i===`none`||i===r)){let e={type:`renderer`,current:i,attempted:r,at:Date.now()};return D.runtime.conflicts.push(e),M(`blocked-renderer:${r}`,`blocked`,e),k(`runtime-authority-conflict`,e),i}D.runtime.rendererOwner=r,D.runtime.activeRenderer=r,D.runtime.activeEngine=n.engine||D.runtime.activeEngine,D.runtime.rendererChangedAt=Date.now(),t?.scene&&(D.scene=t.scene),t?.camera&&(D.camera=t.camera),t?.renderer&&(D.renderer=t.renderer),r!==`fallback-three`&&Nt();try{document.body.dataset.jarvisRendererAuthority=r}catch{}return k(`renderer-authority`,{previous:i,authority:r,context:t}),M(`renderer:${r}`,`authoritative`,{hasScene:!!t?.scene,hasCamera:!!t?.camera,hasRenderer:!!t?.renderer}),r}function gt(){let e=D.cameraVideo;if(e?.readyState>=2&&e.videoWidth>0&&e.videoHeight>0)return{source:e,width:e.videoWidth,height:e.videoHeight};let t=D.gestureFrameCanvas;return D.gestureFrameReady&&t?.width>0&&t?.height>0?{source:t,width:t.width,height:t.height}:null}function N(e,t,n,r){if(!e?.addEventListener||!t||!n)return()=>{};e.addEventListener(t,n,r);let i=()=>e.removeEventListener(t,n,r);return ct.add(i),()=>{i(),ct.delete(i)}}function _t(e,t=0){let n=window.setTimeout(()=>{lt.delete(n),e?.()},t);return lt.add(n),n}function vt(e){e&&(window.clearTimeout(e),lt.delete(e))}function P(e){let t=requestAnimationFrame(n=>{ut.delete(t),e?.(n)});return ut.add(t),t}function yt(e){e&&(cancelAnimationFrame(e),ut.delete(e))}function bt(e){return typeof e==`function`?(ct.add(e),()=>ct.delete(e)):()=>{}}function xt(e,t={},n={}){let r=String(e?.message||e||`Unknown runtime issue`),i=String(n.source||t.source||`runtime`),a=`${i}:${r}`,o=Date.now();if(o-(dt.get(a)||0)>5e3){dt.set(a,o),D.runtime.lastError=r,D.runtime.degradationReason=String(t.degradationReason||D.runtime.degradationReason||``),k(`runtime-error`,{error:r,source:i,context:t}),M(`runtime-error:${i}`,`error`,{message:r,context:t});try{C(r,n.title||`Runtime Error`,{timeout:n.timeout??7e3})}catch{}}try{kt(`${i}: ${r}`)}catch{}return{message:r,source:i,context:t}}function St(e,t,n={}){return typeof t==`function`?(...r)=>{try{return t(...r)}catch(t){xt(t,{...n,subsystem:e},{source:e});return}}:()=>{}}function F(e,t){D.capabilities[e]=!!t;try{document.body.dataset[`cap${e[0].toUpperCase()}${e.slice(1)}`]=String(!!t)}catch{}return D.capabilities[e]}function Ct(e={}){D.compositor={...D.compositor,...e&&typeof e==`object`?e:{}},k(`compositor-state`,D.compositor);try{document.body.dataset.jarvisCompositorMode=D.compositor.mode,document.body.dataset.jarvisCompositorPassthrough=String(D.compositor.passthroughBlend)}catch{}return D.compositor}function wt(e={}){D.browserProfile={...D.browserProfile,...e&&typeof e==`object`?e:{}};try{document.body.dataset.jarvisBrowser=`${D.browserProfile.browser||`unknown`}-${D.browserProfile.platform||`unknown`}`,document.body.dataset.jarvisBrowserLimit=D.browserProfile.webXRFragmented?`fragmented`:`standard`}catch{}return k(`browser-profile`,D.browserProfile),D.browserProfile}function Tt(e={}){D.runtime={...D.runtime,...e&&typeof e==`object`?e:{}};try{document.body.dataset.jarvisRuntimeArchitecture=D.runtime.architecture||`unknown`,document.body.dataset.jarvisSpatialClass=D.runtime.spatialRuntimeClass||`unknown`}catch{}return k(`runtime-classification`,D.runtime),D.runtime}function Et(e=``){D.runtime.rootCauseSummary=String(e||``);try{document.body.dataset.jarvisRootCause=D.runtime.rootCauseSummary}catch{}return k(`runtime-root-cause`,{summary:D.runtime.rootCauseSummary}),D.runtime.rootCauseSummary}function Dt(e=``,t=[]){D.runtime.visionProGapSummary=String(e||``),D.runtime.visionProMissingFeatures=Array.isArray(t)?t.map(e=>String(e||``).trim()).filter(Boolean):[];try{document.body.dataset.jarvisVisionProGap=D.runtime.visionProGapSummary}catch{}return k(`runtime-vision-pro-gap`,{summary:D.runtime.visionProGapSummary,missingFeatures:D.runtime.visionProMissingFeatures}),{summary:D.runtime.visionProGapSummary,missingFeatures:D.runtime.visionProMissingFeatures}}function Ot(e,...t){try{let n=globalThis.JarvisNative;n&&typeof n[e]==`function`&&n[e](...t)}catch{}}function kt(e){Ot(`status`,String(e||``))}function At(){try{if(globalThis.XR8?.Threejs?.xrScene){let e=globalThis.XR8.Threejs.xrScene();if(e?.scene&&e?.camera&&e?.renderer)return D.xrScene=e,D.scene=e.scene,D.camera=e.camera,D.renderer=e.renderer,e}}catch{return null}return null}function I(){return At()||(jt(),{scene:D.fallbackScene,camera:D.fallbackCamera,renderer:D.fallbackRenderer})}function jt(){if(D.fallbackScene&&D.fallbackCamera&&D.fallbackRenderer||D.xrStarted&&D.xrScene?.scene)return;D.fallbackActive=!0;let e=document.getElementById(`fallback-three-canvas`)||document.createElement(`canvas`);e.id=`fallback-three-canvas`,e.parentNode||(e.style.cssText=`position:fixed;inset:0;width:100%;height:100%;z-index:1;pointer-events:none;background:transparent`,document.body.appendChild(e));let t=new Ye({canvas:e,alpha:!0,antialias:!0,powerPreference:`high-performance`});t.setPixelRatio(Math.min(devicePixelRatio||1,3)),t.setSize(innerWidth,innerHeight,!1),t.setClearColor(0,0),t.outputColorSpace=de,t.toneMapping=4,t.toneMappingExposure=1,t.useLegacyLights=!1,t.shadowMap.enabled=!0,t.shadowMap.type=3;let n=new Pe,r=new p(60,innerWidth/innerHeight,.01,1e3);r.position.set(0,0,0),n.add(new Fe(16777215,.65));let i=new De(16777215,.8);i.position.set(1,2,1),i.castShadow=!0,n.add(i),D.fallbackScene=n,D.fallbackCamera=r,D.fallbackRenderer=t,D.scene=n,D.camera=r,D.renderer=t,ht(`fallback-three`,{scene:n,camera:r,renderer:t},{engine:`manual-camera`})}function Mt(){if(D.fallbackLoopStarted)return;D.fallbackLoopStarted=!0,jt();let e=()=>{if(D.xrStarted){Nt();return}!D.xrStarted&&D.fallbackRenderer&&(D.fallbackRenderer.setSize(innerWidth,innerHeight,!1),D.fallbackCamera.aspect=innerWidth/innerHeight,D.fallbackCamera.updateProjectionMatrix(),D.fallbackRenderer.render(D.fallbackScene,D.fallbackCamera)),D.fallbackLoopHandle=P(e)};D.fallbackLoopHandle=P(e)}function Nt(){D.fallbackLoopHandle&&yt(D.fallbackLoopHandle),D.fallbackLoopHandle=0,D.fallbackLoopStarted=!1;let e=document.getElementById(`fallback-three-canvas`);e&&(e.style.display=`none`)}function Pt(){let e=At();if(!e?.scene||!D.fallbackScene||e.scene===D.fallbackScene)return e;let t=[...D.fallbackScene.children];for(let n of t)n!==D.fallbackCamera&&(D.fallbackScene.remove(n),e.scene.children.includes(n)||e.scene.add(n));return Nt(),D.fallbackRenderer?.dispose?.(),document.getElementById(`fallback-three-canvas`)?.remove(),D.fallbackScene=null,D.fallbackCamera=null,D.fallbackRenderer=null,D.fallbackActive=!1,D.scene=e.scene,D.camera=e.camera,D.renderer=e.renderer,ht(`xr8-threejs`,e,{takeover:!0,engine:`8thwall-slam`}),e}function Ft(e=I()){return D.liveSceneReady=!0,k(`ar-scene-live`,e),e}function It(e,t={}){let n=!!t.disposeSharedAssets,r=new Set,i=new Set,a=new Set;e?.traverse?.(e=>{e.geometry&&!r.has(e.geometry)&&(n||!e.geometry.userData?.sharedAssetKey)&&(r.add(e.geometry),e.geometry.dispose()),(Array.isArray(e.material)?e.material:[e.material]).filter(Boolean).forEach(e=>{i.has(e)||(i.add(e),Object.values(e).forEach(e=>{e?.isTexture&&!a.has(e)&&(n||!e.userData?.sharedAssetKey)&&(a.add(e),e.dispose())}),(n||!e.userData?.sharedAssetKey)&&e.dispose?.())})}),e?.parent?.remove(e)}try{globalThis.AR_STATE=D,globalThis.FridayRuntime={AR_STATE:D,emit:k,on:O,reportRuntimeIssue:xt,guardSubsystem:St,setCapability:F,setCompositorState:Ct,claimRuntimeAuthority:mt,claimRendererAuthority:ht,registerSubsystem:M}}catch{}function Lt(e){try{return e?.xr?.getSession?.()||null}catch{return null}}function Rt(e,t){if(e?.xr){try{typeof e.xr.setFramebufferScaleFactor==`function`&&e.xr.setFramebufferScaleFactor(t.framebufferScaleFactor)}catch{}try{typeof e.xr.setFoveation==`function`&&e.xr.setFoveation(t.foveation)}catch{}}}function zt(e=I(),t={}){let n=e?.renderer,r=t.session||Lt(n),i=String(t.tier||D.telemetry?.qualityTier||`medium`).toLowerCase();globalThis.navigator?.xr;let a=!!(n?.xr&&typeof n.xr.setFoveation==`function`),o=!!(n?.xr&&typeof n.xr.setFramebufferScaleFactor==`function`),s=!!(r?.renderState?.baseLayer||r?.depthUsage),c=!!(globalThis.JarvisNative?.openXRBridge||globalThis.JarvisNative?.setCompositorState),l={mode:t.mode||(r?`webxr-session`:`browser-proxy`),native:c,reprojection:!!(r&&o),passthroughBlend:t.passthroughBlend||(t.source?`browser-camera`:`browser`),depthComposition:!!(t.depthComposition||s),foveation:t.foveation??(i===`high`?.2:i===`medium`?.35:.55),framebufferScaleFactor:t.framebufferScaleFactor??(i===`high`?1:i===`medium`?.85:.72),eyeBuffers:t.eyeBuffers||(t.stereo?`pair`:`mono`),frameBudgetMs:t.frameBudgetMs??(i===`high`?13.5:i===`medium`?16.6:20),avgFrameMs:D.compositor?.avgFrameMs||16.6,lastFrameAt:performance.now(),posePredictionMs:t.posePredictionMs??(i===`high`?18:i===`medium`?24:32),refreshRate:t.refreshRate??(i===`high`?90:i===`medium`?72:60),renderScale:t.renderScale??(i===`high`?1:i===`medium`?.9:.8),convergence:t.convergence??(i===`high`?1.35:1.45),guardianProxy:!!t.guardianProxy,compositorSync:!0,lensProfile:t.lensProfile||`default`,eyeAspect:t.eyeAspect??1,vignetteStrength:t.vignetteStrength??(i===`high`?.1:.16),motionComfort:t.motionComfort||`balanced`,stereoFrustum:!!(t.stereo??r)};if(Ct(l),F(`openXRCompositorProxy`,!0),F(`reprojectionProxy`,l.reprojection),F(`depthCompositionProxy`,l.depthComposition),F(`eyeBufferPair`,l.eyeBuffers===`pair`),F(`nativeFrameTiming`,!!r),F(`posePredictionProxy`,!0),F(`foveatedRendering`,a),F(`lowLatencyCompositing`,!0),F(`stereoEyeBuffers`,l.eyeBuffers===`pair`),F(`stereoFrustumCalibration`,l.stereoFrustum),F(`refreshRateNegotiation`,!0),F(`timestampSync`,!0),F(`motionSicknessMitigation`,!0),F(`smoothLocomotionSafeguards`,!0),F(`motionComfortVignette`,!0),t.guardianProxy!=null&&F(`guardianBoundary`,!!t.guardianProxy),c){F(`nativeOpenXRBridge`,!0);try{Ot(`setCompositorState`,JSON.stringify(l)),Ot(`requestCompositorControl`,JSON.stringify({owner:`browser-runtime`,mode:l.mode,guardianProxy:l.guardianProxy,browserManaged:!0})),Ot(`setGuardianState`,JSON.stringify({requested:!!t.guardianProxy,boundary:!!t.guardianProxy,owner:`browser-runtime`,source:`ar-compositor`}))}catch{}}return Rt(n,l),M(`compositor`,`ready`,l),k(`compositor-profile`,l),kt(`Compositor profile: ${l.mode}`),l}function Bt(e=16.6){let t=D.compositor||{},n=t.avgFrameMs?t.avgFrameMs*.9+e*.1:e,r={...t,avgFrameMs:n,lastFrameAt:performance.now()};return Ct(r),D.telemetry.frameMs=e,D.telemetry.droppedFrames=e>(r.frameBudgetMs||16.6)*1.25?(D.telemetry.droppedFrames||0)+1:D.telemetry.droppedFrames||0,k(`compositor-frame`,r),r}function Vt(){Ct({mode:`browser-proxy`,native:!1,reprojection:!1,passthroughBlend:`browser`,depthComposition:!1,foveation:0,framebufferScaleFactor:1,eyeBuffers:`mono`,frameBudgetMs:16.6,avgFrameMs:16.6,lastFrameAt:0}),F(`openXRCompositorProxy`,!1),F(`reprojectionProxy`,!1),F(`depthCompositionProxy`,!1),F(`eyeBufferPair`,!1),F(`nativeFrameTiming`,!1),F(`posePredictionProxy`,!1)}function Ht(e,n,r){globalThis.JarvisNative?.openXRBridge||globalThis.JarvisNative?.setCompositorState||(e.xr.enabled=!0,e.xr.setReferenceSpaceType(`local-floor`),!navigator.xr&&!D.stereoEffect&&t(async()=>{let{StereoEffect:e}=await import(`./StereoEffect-8X11TNUP.js`);return{StereoEffect:e}},__vite__mapDeps([0,1,2]),import.meta.url).then(({StereoEffect:t})=>{D.stereoEffect=new t(e),D.stereoEffect.setSize(window.innerWidth,window.innerHeight),D.stereoEffect.setEyeSeparation(.064),e.setAnimationLoop(()=>{D.stereoEffect.render(n,r)}),k(`jarvis-stereo-mode-active`,{status:`fallback_active`})}).catch(()=>{console.warn(`V15 AR: StereoEffect.js fallback polyfill missing.`)}))}var Ut=globalThis.XRExtras||{FullWindowCanvas:{pipelineModule(){return{name:`xrextras-full-window-canvas`,onStart:({canvas:e})=>Wt(e),onCanvasSizeChange:({canvas:e})=>Wt(e)}}},Loading:{pipelineModule(){return{name:`xrextras-loading`,onStart:()=>E(`Starting 8th Wall camera...`,38),onCameraStatusChange:({status:e})=>{e===`hasVideo`&&ot()}}}},AlmostThere:{pipelineModule(){return{name:`xrextras-almost-there`,onAttach:()=>{navigator.mediaDevices?.getUserMedia||w(`This browser has limited AR camera support. Chrome Android is recommended.`)}}}},RuntimeError:{pipelineModule(){return{name:`xrextras-runtime-error`,onException:e=>C(e?.message||String(e),`8th Wall Runtime Error`,{timeout:0})}}}};try{globalThis.XRExtras||(globalThis.XRExtras=Ut)}catch{}function Wt(e){if(!e)return;let t=Math.min(devicePixelRatio||1,3),n=Math.max(1,Math.floor(innerWidth*t)),r=Math.max(1,Math.floor(innerHeight*t));(e.width!==n||e.height!==r)&&(e.width=n,e.height=r),e.style.width=`100vw`,e.style.height=`100vh`}function Gt(){let e=[`localhost`,`127.0.0.1`,`::1`].includes(location.hostname);return location.protocol===`https:`||e?!0:(C(`AR requires a secure connection (HTTPS). Please open this app over HTTPS.`,`Secure Connection Required`,{timeout:0,linkHref:`intent://settings#Intent;scheme=android-app;end`,linkLabel:`Open Chrome Android settings`}),!1)}function Kt(){let e=new URLSearchParams(location.search),t=()=>{try{return localStorage.getItem(`jarvis_ar_device`)||``}catch{return``}},n=e=>{try{localStorage.setItem(`jarvis_ar_device`,String(e))}catch{}},r=e.has(`device`),i=e.get(`device`)||t()||`POCO-M5`;r||n(i);let a=Jt(e.get(`omega`)||e.get(`omegaBridge`)||``),o=Xt(e.get(`xr`)||e.get(`xrScriptUrl`)||``);return{deviceName:i,mode:qt(e.get(`mode`)||`vision_pro`),autoStart:!1,source:e.get(`source`)||`browser`,guardianProxy:e.get(`guardianProxy`)===`true`||e.get(`guardian`)===`true`,eyeTracking:e.get(`eyeTracking`)===`true`,nativeCompositor:e.get(`nativeCompositor`)===`true`,truePersistentWorldAnchors:e.get(`truePersistentWorldAnchors`)===`true`||e.get(`persistentWorldAnchors`)===`true`,nativeOpenXRBridge:e.get(`nativeOpenXRBridge`)===`true`,command:e.get(`command`)||``,arQuality:(e.get(`arQuality`)||`4k`).toLowerCase(),renderScale:e.get(`renderScale`)||`adaptive`,screen:e.get(`screen`)||`quest_spatial`,stack:(e.get(`stack`)||`aframe,playcanvas,camerakit,8thwall`).split(`,`).map(e=>e.trim()).filter(Boolean),omegaBase:a||(location.origin.includes(`5173`)?location.origin:``),wsBase:Yt(e.get(`ws`)||``,a),xrScriptUrl:o,imageTargets:(e.get(`imageTargets`)||``).split(`,`).map(e=>e.trim()).filter(Boolean),gameUrls:{eternum:Jt(e.get(`eternumUrl`)||e.get(`gameEternumUrl`)||``),ripples:Jt(e.get(`ripplesUrl`)||e.get(`gameRipplesUrl`)||``)}}}function qt(e){let t=String(e||``).toLowerCase().trim().replace(/[-\s]+/g,`_`);return{vision:`vision_pro`,visionos:`vision_pro`,meta:`vision_pro`,quest:`vision_pro`,scan_room:`scan`,model:`models`,games:`games`,game:`games`,build:`builder`,game_builder:`builder`,vr_screen:`vr`}[t]||t||`vision_pro`}function Jt(e){let t=String(e||``).trim().replace(/\/+$/,``);return t?/^https?:\/\//i.test(t)?t:`http://${t}`:``}function Yt(e,t=``){let n=String(e||``).trim().replace(/\/+$/,``);if(n)return/^wss?:\/\//i.test(n)?n:`ws://${n}`;if(!t)return location.protocol===`https:`?`wss://${location.host}/scene-ws`:`ws://${location.hostname}:5050`;try{let e=new URL(t,location.href),n=e.protocol===`https:`?`wss:`:`ws:`;return e.protocol===`https:`||e.port===`5173`||!e.port?`${n}//${e.host}/scene-ws`:`${n}//${e.hostname}:5050`}catch{return``}}function Xt(e){let t=String(e||``).trim();return t&&/^(https?:|data:|blob:|\/)/i.test(t)?t:``}function Zt(e,t){let n=String(e||``).toLowerCase();return t.some(e=>n.includes(String(e||``).toLowerCase()))}function Qt(e=``,t=``,n=``){let r=String(e||(typeof navigator<`u`?navigator.userAgent:``)||``),i=r.toLowerCase(),a=typeof navigator<`u`&&navigator.platform||``,o=typeof navigator<`u`&&navigator.vendor||``,s=typeof navigator<`u`&&navigator.maxTouchPoints||0,c=String(t||a||``).toLowerCase(),l=String(n||o||``).toLowerCase(),u=/iphone|ipad|ipod/.test(i)||c.includes(`mac`)&&s>1&&/safari/.test(i),d=/android/.test(i),f=/visionos|applevision|xrvision/.test(i)||Zt(r,[`Safari`])&&/apple/.test(l)&&s>1&&/mac/.test(c),p=/quest|oculus/.test(i),m=/\bwv\b|; wv|webview|android.*version\/\d+.*chrome/i.test(r)||d&&!/chrome|crios|firefox|fxios|edg/i.test(i),h=/safari/.test(i)&&!/chrome|crios|chromium|android/.test(i),g=/chrome|crios|chromium/.test(i)&&!/edg/.test(i),_=/firefox|fxios/.test(i),ee=/edg/.test(i),v=h?`safari`:g?`chrome`:_?`firefox`:ee?`edge`:p?`quest-browser`:`other`,te=h?`webkit`:_?`gecko`:`blink`,ne=f?`visionos`:u?`ios`:d?`android`:/mac/.test(c)?`mac`:/win/.test(c)?`windows`:/linux/.test(c)?`linux`:`desktop`,re=!!(!u||f||p),ie=h||f||m||d&&!g&&!p,y=p&&g;return{ua:r,browser:v,engine:te,platform:ne,isAndroid:d,isIOS:u,isVisionOS:f,isQuest:p,isWebView:m,isSafari:h,isChrome:g,isFirefox:_,isEdge:ee,questBrowserQuirks:y,webXRSupportExpected:re,webXRFragmented:ie,latencyCeilingMs:f?12.5:p?13.5:u?14.5:16.7,limits:{sensorAccessLimited:!0,osIntegrationLimited:!0,compositorControlLimited:!0,persistentAnchorSupport:!1,backgroundExecutionLimited:!0,passthroughControlLimited:!0,spatialMemoryLimited:!0,headsetOptimizationAccessLimited:!0,webXRFragmented:ie,safariWebXRLimitations:h,visionOSBrowserRestrictions:f,androidBrowserInconsistency:d,webViewInconsistency:m,questBrowserQuirks:y,fullscreenEdgeCases:f||m||p,orientationLockEdgeCases:h||f||m||p,webglContextLossRisk:p||d||m,renderLoopDuplicationRisk:p||d||m,limitedSensorAccess:!0,limitedOSIntegration:!0,limitedCompositorControl:!0,limitedPassthroughControl:!0,limitedSpatialMemoryAPIs:!0,limitedHeadsetOptimizationAccess:!0},notes:[h?`Safari WebXR support remains fragmented.`:``,f?`visionOS browser control is limited to browser-managed surfaces.`:``,d?`Android browser behavior can vary by OEM and browser build.`:``,y?`Quest Browser can expose fullscreen, orientation, and session quirks.`:``,m?`Embedded WebView feature support is stricter than Chrome Custom Tabs.`:``].filter(Boolean)}}function $t(e){let t=[];return e?(e.limits?.webXRFragmented&&t.push(`webxr-fragmented`),e.limits?.safariWebXRLimitations&&t.push(`safari-webxr-limited`),e.limits?.visionOSBrowserRestrictions&&t.push(`visionos-browser-limited`),e.limits?.androidBrowserInconsistency&&t.push(`android-browser-variable`),e.limits?.webViewInconsistency&&t.push(`webview-variable`),e.limits?.questBrowserQuirks&&t.push(`quest-browser-quirks`),e.limits?.fullscreenEdgeCases&&t.push(`fullscreen-edge-cases`),e.limits?.orientationLockEdgeCases&&t.push(`orientation-lock-edge-cases`),e.limits?.webglContextLossRisk&&t.push(`webgl-context-loss-risk`),e.limits?.renderLoopDuplicationRisk&&t.push(`render-loop-duplication-risk`),e.limits?.backgroundExecutionLimited&&t.push(`background-execution-limited`),e.limits?.persistentAnchorSupport===!1&&t.push(`no-persistent-anchors`),e.limits?.passthroughControlLimited&&t.push(`passthrough-control-limited`),e.limits?.spatialMemoryLimited&&t.push(`spatial-memory-limited`),t):t}async function en(e){D.config=e,D.aframeScene=document.getElementById(`ar-scene`),D.aframeCamera=document.getElementById(`main-camera`),await tn();let t=I();return an(t.renderer,e),on(t),zt(t,{mode:`ar-shell`,tier:D.focusQuality.tier,stereo:!!D.isVRMode}),dn(t.scene),rn(t.renderer),pn(),D.sceneInitialized||(D.sceneInitialized=!0,k(`scene-ready`,t)),t}function tn(){let e=document.getElementById(`ar-scene`);return!e||!window.AFRAME||e.hasLoaded?Promise.resolve():new Promise(t=>{let n=!1,r=()=>{n||(n=!0,t())};e.addEventListener(`loaded`,r,{once:!0}),setTimeout(r,5e3)})}function nn(){D.aframeCameraSyncAdded=!0,document.getElementById(`ar-scene`)?.setAttribute(`data-render-mode`,`disabled-xr8-single-scene`)}function rn(e){let t=e?.domElement;!t||t.dataset.jarvisWebglRecoveryBound===`1`||(t.dataset.jarvisWebglRecoveryBound=`1`,N(t,`webglcontextlost`,e=>{e.preventDefault(),w(`WebGL context lost. Pausing AR until the GPU recovers.`,`WebGL`);try{globalThis.XR8?.pause?.()}catch{}},{passive:!1}),N(t,`webglcontextrestored`,()=>{if(w(`WebGL context restored.`,`WebGL`),an(e,D.config||{}),D.xrStarted)try{globalThis.XR8?.resume?.()}catch{}},{passive:!0}))}function an(e,t={}){if(!e)return;let n=String(t.renderScale||`adaptive`).toLowerCase(),r=n===`2`||n===`4k`?2:n===`1`?1:devicePixelRatio||1,i=Math.max(1,Math.min(r,3));r>3&&(console.warn(`Render scale ${r} was capped to 3.0. Requested scale: ${n}`),D.telemetry=D.telemetry||{},D.telemetry.pixelRatioCapped=!0,D.telemetry.originalPixelRatio=r),e.setPixelRatio(i),e.setSize(innerWidth,innerHeight,!1),e.outputColorSpace=de,e.toneMapping=4,e.toneMappingExposure=1,e.useLegacyLights=!1,e.shadowMap.enabled=!0,e.shadowMap.type=3}function on(e=I()){let t=e?.scene,n=e?.renderer;if(!t||!n)return null;if(t.environment&&t.userData.jarvisEnvironmentSource===`hdr`||t.userData.jarvisDefaultEnvInstalled)return t.environment;try{let e=new Le(n),r=new ye,i=e.fromScene(r,.04);i?.texture&&(t.environment=i.texture,t.userData.jarvisDefaultEnvTarget=i,t.userData.jarvisDefaultEnvInstalled=!0,t.userData.jarvisEnvironmentSource=`room-default`,D.telemetry.iblEnvironment=`room-default`),r.dispose?.(),e.dispose()}catch(e){console.warn(`Default IBL environment install failed:`,e?.message||e)}return t.environment}function sn(){if(D.focusQuality.enabled)return;D.focusQuality.enabled=!0;let e=performance.now(),t=0,n=(e,t,n)=>{D.focusQuality.focusX=Math.max(0,Math.min(1,e)),D.focusQuality.focusY=Math.max(0,Math.min(1,t)),D.focusQuality.source=n};N(window,`pointerdown`,e=>n(e.clientX/innerWidth,e.clientY/innerHeight,`touch`),{passive:!0}),N(window,`pointermove`,e=>{e.pointerType!==`mouse`&&n(e.clientX/innerWidth,e.clientY/innerHeight,`touch`)},{passive:!0}),O(`gesture-point`,e=>{let t=e?.point;t&&n(t.x,t.y,`hand-point`)});let r=n=>{let i=Math.min(n-e,100);e=n,D.focusQuality.avgFrameMs=D.focusQuality.avgFrameMs*.92+i*.08,D.telemetry.frameMs=D.focusQuality.avgFrameMs,Bt(i),n-t>600&&(cn(),t=n),P(r)};P(r)}function cn(){let e=I(),t=e.renderer;if(!t)return;let n=D.focusQuality.avgFrameMs,r=Math.min(devicePixelRatio||1,3),i=n>33?{ratio:1,tier:`low`,shadows:!1}:n>25?{ratio:Math.min(1.2,r),tier:`medium`,shadows:!0}:n>18?{ratio:Math.min(1.5,r),tier:`balanced`,shadows:!0}:{ratio:r,tier:`high`,shadows:!0};Math.abs((D.focusQuality.pixelRatio||0)-i.ratio)>.05&&(t.setPixelRatio(i.ratio),t.setSize(innerWidth,innerHeight,!1),D.focusQuality.pixelRatio=i.ratio),D.focusQuality.tier=i.tier,D.telemetry.qualityTier=i.tier,document.body.dataset.jarvisQualityTier=i.tier,document.body.dataset.jarvisFrameMs=D.focusQuality.avgFrameMs.toFixed(1),performance.now()-D.telemetry.lastNativeStatusAt>5e3&&(D.telemetry.lastNativeStatusAt=performance.now(),kt(`AR quality ${i.tier}, ${D.focusQuality.avgFrameMs.toFixed(1)}ms frame average`)),t.shadowMap&&(t.shadowMap.enabled=i.shadows),zt(e,{mode:`ar-shell`,tier:i.tier,stereo:!!D.isVRMode,frameBudgetMs:i.tier===`high`?13.5:i.tier===`balanced`?16.6:20}),D.placedObjects.forEach(e=>ln(e,i.tier))}function ln(e,t){if(!e)return;let n=un(e)<.34?t:t===`high`?`balanced`:`low`;e.traverse(e=>{e.isMesh&&(e.frustumCulled=!0,e.castShadow=n!==`low`,e.receiveShadow=n!==`low`,e.material&&(e.material.needsUpdate=!1))})}function un(e){let t=D.camera||I().camera;if(!t)return 0;let n=new S;e.getWorldPosition(n),n.project(t);let r=n.x*.5+.5,i=-n.y*.5+.5;return Math.hypot(r-D.focusQuality.focusX,i-D.focusQuality.focusY)}function dn(e){if(!e||e.userData.jarvisHelpersAdded)return;e.userData.jarvisHelpersAdded=!0;let t=new _(16777215,4469538,.72);t.name=`jarvis-ambient-fill`,e.add(t);let n=new De(16777215,1.05);n.name=`jarvis-key-shadow-light`,n.position.set(1.4,3.2,1.2),n.castShadow=!0,n.shadow.mapSize.set(2048,2048),n.shadow.camera.near=.1,n.shadow.camera.far=10,n.shadow.camera.left=-5,n.shadow.camera.right=5,n.shadow.camera.top=5,n.shadow.camera.bottom=-5,n.shadow.bias=-5e-4,n.shadow.normalBias=.02,e.add(n),D.shadowLight=n;let r=new se(4491519,.28,8,2);r.name=`jarvis-ar-fill-light`,r.position.set(0,1.2,0),e.add(r),D.fillLight=r;let i=new b(new Te(.08,.105,48),new d({color:16777215,transparent:!0,opacity:.65,side:2,depthWrite:!1}));i.name=`placement-reticle`,i.rotation.x=-Math.PI/2,i.position.set(0,D.floorY+.01,-1.8),i.visible=!1,e.add(i),D.reticle=i;let a=new b(new x(12,12),new he({color:0,opacity:.24,transparent:!0,depthWrite:!1}));a.name=`jarvis-real-floor-shadow-receiver`,a.rotation.x=-Math.PI/2,a.position.set(0,D.floorY+.002,0),a.receiveShadow=!0,e.add(a),D.shadowReceiver=a}function fn(){T(`status-camera`,D.cameraVideo||D.xrStarted?`live`:`standby`),T(`status-tracking`,D.trackingMode),T(`status-omega`,D.jarvis?.connected?`linked`:`offline`)}function pn(){if(D.resizeBound)return;D.resizeBound=!0;let e=()=>{let e=I();e.camera?.isPerspectiveCamera&&(e.camera.aspect=innerWidth/innerHeight,e.camera.updateProjectionMatrix()),e.renderer?.setSize?.(innerWidth,innerHeight,!1),k(`ar-resize`,{width:innerWidth,height:innerHeight})};N(window,`resize`,e),N(window,`orientationchange`,()=>_t(e,100)),N(document,`visibilitychange`,()=>{try{document.hidden?globalThis.XR8?.pause?.():globalThis.XR8?.resume?.()}catch{w(`8th Wall pause/resume is unavailable in this browser session.`)}})}var mn=new Set,hn=null,gn=null,_n=null,vn=0,yn=!1,bn=class{constructor({title:e,width:t=340,height:n=480,icon:r=`O`,body:i}={}){let a=document.getElementById(`panel-template`).content.firstElementChild.cloneNode(!0);this.el=a,this.icon=r,this.isDragging=!1,this.isResizing=!1,this.startX=0,this.startY=0,this.currentX=Math.max(8,(innerWidth-t)/2),this.currentY=Math.max(72,(innerHeight-n)/2),this.velX=0,this.velY=0,this.animFrame=0,this.activePointerId=null,a.style.width=`clamp(280px, 90vw, ${t}px)`,a.style.minHeight=`${Math.min(n,innerHeight-170)}px`,a.querySelector(`h2`).textContent=e||`Panel`,i&&a.querySelector(`.panel-body`).appendChild(i),a.querySelector(`.panel-close`).addEventListener(`click`,()=>this.destroy()),a.querySelector(`.panel-minimize`).addEventListener(`click`,()=>this.minimize()),this.attachEvents(),document.getElementById(`ui-layer`).appendChild(a),this.applyTransform(),mn.add(this)}attachEvents(){let e=this.el.querySelector(`.panel-drag-handle`);this._listeners=[[e,`pointerdown`,e=>this.onPointerStart(e)],[document,`pointermove`,e=>this.onPointerMove(e)],[document,`pointerup`,()=>this.onDragEnd()],[this.el,`pointerdown`,()=>this.focus()]],this._listeners.forEach(([e,t,n,r])=>e.addEventListener(t,n,r))}onPointerStart(e){e.preventDefault?.(),this.isDragging=!0,this.startX=e.clientX-this.currentX,this.startY=e.clientY-this.currentY,this.lastX=e.clientX,this.lastY=e.clientY,this.activePointerId=e.pointerId,yt(this.animFrame),e.currentTarget?.setPointerCapture?.(e.pointerId)}onPointerMove(e){this.isDragging&&this.applyDrag(e.clientX,e.clientY)}applyDrag(e,t){this.velX=e-this.lastX,this.velY=t-this.lastY,this.lastX=e,this.lastY=t,this.currentX=e-this.startX,this.currentY=t-this.startY,this.applyTransform()}onDragEnd(){this.isDragging&&(this.isDragging=!1,this.el.releasePointerCapture?.(this.activePointerId),this.activePointerId=null,this.applyMomentum())}applyMomentum(){this.velX*=.92,this.velY*=.92,this.currentX+=this.velX,this.currentY+=this.velY,this.applyTransform(),(Math.abs(this.velX)>.5||Math.abs(this.velY)>.5)&&(this.animFrame=P(()=>this.applyMomentum()))}applyTransform(){let e=this.el.getBoundingClientRect(),t=this.el.offsetWidth||e.width||parseFloat(this.el.style.width)||320,n=this.el.offsetHeight||e.height||parseFloat(this.el.style.minHeight)||420,r=Math.max(0,innerWidth-t),i=Math.max(0,innerHeight-n);this.currentX=Math.max(0,Math.min(this.currentX,r)),this.currentY=Math.max(0,Math.min(this.currentY,i)),this.el.style.transform=`translate3d(${this.currentX}px, ${this.currentY}px, 0)`}focus(){mn.forEach(e=>e.el.classList.remove(`active`)),this.el.classList.add(`active`)}minimize(){this.el.classList.add(`minimized`);let e=document.createElement(`button`);e.className=`panel-orb glass-panel`,e.textContent=this.icon||`O`,e.setAttribute(`aria-label`,`Restore panel`);let t=document.querySelectorAll(`#ui-layer .panel-orb`).length;e.style.cssText=`width:56px;height:56px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:18px;position:absolute;bottom:${100+t*64}px;right:20px;z-index:20;color:white;pointer-events:auto`,e.onclick=()=>{this.restore(),e.remove()},document.getElementById(`ui-layer`).appendChild(e),this.el.style.display=`none`}restore(){this.el.style.display=``,this.el.classList.remove(`minimized`),this.focus()}destroy(){yt(this.animFrame),this._listeners?.forEach(([e,t,n,r])=>e.removeEventListener(t,n,r)),this._listeners=[],mn.delete(this),this.el.remove(),mn.size||Mn()}};function xn(){kn(),O(`ar-resize`,Dn)}function Sn(){return D.css3d?.initialized?(jn(),D.css3d):(gn=gn||new Pe,hn=hn||Cn(),D.css3d={scene:gn,renderer:hn,panels:[],initialized:!0},An(),jn(),D.css3dResizeBound||(N(window,`resize`,On),N(window,`orientationchange`,()=>_t(On,100)),D.css3dResizeBound=!0),D.css3d)}function Cn(){let e=new ge;e.setSize(innerWidth,innerHeight),e.domElement.style.cssText=`position:absolute;top:0;left:0;width:100%;height:100%;z-index:2;pointer-events:auto;overflow:hidden;transform-style:preserve-3d`;let t=document.getElementById(`css3d-layer`);return t.style.pointerEvents=`none`,t.appendChild(e.domElement),e}function wn(e,t,n=800,r=530){let i=document.createElement(`div`);i.className=`game-panel-viewport`,i.style.cssText=`position:relative;width:100%;height:min(${Math.max(320,r-100)}px,68vh);min-height:320px;border-radius:16px;overflow:hidden;border:1px solid rgba(255,255,255,0.2);box-shadow:0 0 48px rgba(0,122,255,0.24),0 16px 42px rgba(0,0,0,0.52);background:#000;pointer-events:auto`,i.tabIndex=0;let a=document.createElement(`iframe`);a.src=e,a.className=`game-frame`,a.style.cssText=`position:absolute;inset:0;width:100%;height:100%;border:0;background:#000;pointer-events:auto`,a.setAttribute(`allow`,`autoplay; fullscreen; microphone; camera`),a.setAttribute(`referrerpolicy`,`origin-when-cross-origin`),a.setAttribute(`sandbox`,`allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-popups`),a.setAttribute(`referrerpolicy`,`no-referrer`),i.append(a);let o=new bn({title:t,body:i,icon:`G`,width:Math.min(n,420),height:Math.min(r,640)});return o.el.classList.add(`ar-game-panel`),o.focus(),{object:null,iframe:a,container:i,titleBar:o.el.querySelector(`header`),panel:o,destroy:()=>o.destroy()}}function Tn(e){let t=(_n||I().camera)?.fov||60,n=innerHeight,r=Math.tan(Xe.degToRad(t/2));return e/(n/2/r)}function En(){if(!hn||!gn)return;let e=An()||I().camera;e&&e!==_n&&(_n=e),_n&&(_n.updateMatrixWorld(!0),hn.setSize(innerWidth,innerHeight),hn.render(gn,_n))}function Dn(){mn.forEach(e=>e.applyTransform()),D.css3d?.panels?.forEach(e=>e.scale.setScalar(Tn(2)))}function On(){hn?.setSize(innerWidth,innerHeight),Dn()}function kn(){document.getElementById(`hud-toolbar`)?.addEventListener(`click`,e=>{let t=e.target.closest(`button[data-action]`);if(!t)return;let n=t.dataset.action;document.querySelectorAll(`#hud-toolbar .btn-symbol`).forEach(e=>{let n=e===t;e.classList.toggle(`selected`,n),e.setAttribute(`aria-pressed`,String(n))}),n===`models`?k(`open-models`):n===`scan`?k(`scan-room`):n===`games`?k(`open-games`):n===`builder`?k(`open-builder`):n===`vr`?k(`enter-vr`):n===`media`?k(`open-media`):n===`jarvis`&&k(`open-jarvis`)})}function An(){try{let e=globalThis.XR8?.Threejs?.xrScene?.()?.camera||null;return e&&(_n=e),e}catch{return null}}function jn(){if(globalThis.XR8?.addCameraPipelineModule){vn&&(yt(vn),vn=0),yn?D.css3dPipelineAdded=!0:(globalThis.XR8.addCameraPipelineModule({name:`css3d-camera-sync`,onRender:()=>En()}),D.pipelineOrder.push(`css3d-camera-sync`),yn=!0,D.css3dPipelineAdded=!0);return}if(vn)return;let e=()=>{if(D.css3dPipelineAdded){vn=0;return}En(),vn=P(e)};vn=P(e)}function Mn(e=!1){return!e&&mn.size>0?!1:(vn&&yt(vn),vn=0,hn?.domElement?.remove?.(),hn=null,gn=null,_n=null,D.css3d=null,D.css3dPipelineAdded=!1,yn=!1,!0)}function Nn(){mn.forEach(e=>e.destroy()),mn.clear(),Mn(!0),D.css3dResizeBound=!1,document.querySelectorAll(`#ui-layer .panel-orb, #ui-layer .ar-panel`).forEach(e=>e.remove())}function Pn(e,t,n=`O`){let r=typeof t==`string`?document.createElement(`div`):t;return typeof t==`string`&&(r.textContent=t),new bn({title:e,body:r,icon:n})}var Fn=[{name:`Duck`,size:`~100KB`,category:`animal`},{name:`Avocado`,size:`~200KB`,category:`food`},{name:`BoxAnimated`,size:`~50KB`,category:`basic`},{name:`BrainStem`,size:`~3MB`,category:`organic`},{name:`CesiumMilkTruck`,size:`~1MB`,category:`vehicle`},{name:`DamagedHelmet`,size:`~30MB`,category:`scifi`},{name:`FlightHelmet`,size:`~30MB`,category:`scifi`},{name:`Fox`,size:`~2MB`,category:`animal`},{name:`GlamVelvetSofa`,size:`~10MB`,category:`furniture`},{name:`Lantern`,size:`~500KB`,category:`object`},{name:`ToyCar`,size:`~3MB`,category:`vehicle`},{name:`WaterBottle`,size:`~1MB`,category:`object`},{name:`AntiqueCamera`,size:`~3MB`,category:`object`},{name:`BarramundiFish`,size:`~2MB`,category:`animal`},{name:`Corset`,size:`~500KB`,category:`clothing`},{name:`ReciprocatingSaw`,size:`~5MB`,category:`tool`},{name:`Sponza`,size:`~50MB`,category:`environment`},{name:`DragonAttenuation`,size:`~5MB`,category:`creature`},{name:`IridescenceLamp`,size:`~2MB`,category:`furniture`},{name:`GlassVaseBacklit`,size:`~1MB`,category:`object`},{name:`MaterialsVariantsShoe`,size:`~5MB`,category:`clothing`},{name:`OrientationTest`,size:`~500KB`,category:`test`},{name:`NormalTangentTest`,size:`~500KB`,category:`test`},{name:`EnvironmentTest`,size:`~2MB`,category:`test`},{name:`SheenCloth`,size:`~2MB`,category:`fabric`}];function In(e){let t=String(e||`Duck`).replace(/[^A-Za-z0-9_-]/g,``);return`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/${t}/glTF-Binary/${t}.glb`}function Ln(e){let t=String(e||``).toLowerCase();return Fn.find(e=>t.includes(e.name.toLowerCase()))||Fn.find(e=>t.includes(e.category.toLowerCase()))||Fn[0]}var Rn=`jarvis_sketchfab_access_token_v1`,zn=[{slug:`by`,label:`CC BY`},{slug:`by-sa`,label:`CC BY-SA`},{slug:`by-nd`,label:`CC BY-ND`},{slug:`by-nc`,label:`CC BY-NC`},{slug:`by-nc-sa`,label:`CC BY-NC-SA`},{slug:`by-nc-nd`,label:`CC BY-NC-ND`},{slug:`cc0`,label:`CC0`},{slug:`standard`,label:`Free Standard`}],Bn=zn.map(e=>e.slug),Vn=new Set(Bn);function Hn(e){if(!e)return``;let t=(typeof e==`string`?e:e.slug||e.uid||e.label||e.fullName||e.url||e.uri||``).toString().trim().toLowerCase(),n=t.match(/(?:^|\/)(cc0|standard|by(?:-nc)?(?:-sa|-nd)?)(?:\/|$)/);if(n)return n[1];if(t.includes(`free standard`)||t===`standard`)return`standard`;if(t.includes(`cc0`)||t.includes(`public domain`))return`cc0`;if(!t.includes(`attribution`)&&!t.includes(`creative commons`))return t;let r=t.includes(`noncommercial`)||t.includes(`non-commercial`),i=t.includes(`noderivs`)||t.includes(`no derivatives`)||t.includes(`no-derivatives`),a=t.includes(`sharealike`)||t.includes(`share alike`)||t.includes(`share-alike`);return r&&i?`by-nc-nd`:r&&a?`by-nc-sa`:r?`by-nc`:i?`by-nd`:a?`by-sa`:`by`}function Un(e){return Vn.has(Hn(e))}function Wn(e){let t=Hn(e);return zn.find(e=>e.slug===t)?.label||t.toUpperCase()}function Gn(){try{return sessionStorage.getItem(`jarvis_sketchfab_access_token_v1`)||``}catch{return``}}function Kn(e){try{let t=String(e||``).trim();t?sessionStorage.setItem(Rn,t):sessionStorage.removeItem(Rn),localStorage.removeItem(Rn)}catch{}}async function qn(e=`studio`){let t=await fetch(`https://api.polyhaven.com/assets?type=hdris`,{cache:`force-cache`});if(!t.ok)throw Error(`PolyHaven HDR request failed: ${t.status}`);let n=await t.json(),r=Object.keys(n);if(!r.length)throw Error(`PolyHaven returned no HDR assets.`);return`https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/1k/${r.find(t=>t.toLowerCase().includes(String(e).toLowerCase()))||r[0]}_1k.hdr`}function Jn(e,{count:t=12,license:n=``}={}){let r=new URL(`https://api.sketchfab.com/v3/models`);return r.searchParams.set(`q`,String(e||``).trim()),r.searchParams.set(`downloadable`,`true`),r.searchParams.set(`type`,`models`),r.searchParams.set(`count`,String(t)),r.searchParams.set(`archives_flavours`,`true`),n&&r.searchParams.set(`license`,n),r.toString()}async function Yn(e,t=``,{count:n=24}={}){let r=Math.max(4,Math.ceil(n/Bn.length));if(!t){let t=await nr(e,n);if(t)return t}let i=[],a=[];for(let o of Bn)try{let a=await Zn(e,t,o,r);if(i.push(a),Xn(i).length>=n)break}catch(e){a.push(e)}let o=Xn(i);if(!o.length&&a.length===Bn.length)throw Error(a[0]?.message||`Sketchfab search failed for all allowed free licenses.`);let s=new Set;return o.filter(e=>e?.uid&&!s.has(e.uid)&&s.add(e.uid)).filter(e=>e?.isDownloadable!==!1).filter(e=>Un(e?.license)).map(Qn).slice(0,n)}function Xn(e){let t=[],n=Math.max(0,...e.map(e=>e.length));for(let r=0;r<n;r+=1)for(let n of e)n[r]&&t.push(n[r]);return t}async function Zn(e,t,n,r){let i=t?{Authorization:`Bearer ${t}`}:{},a=await fetch(Jn(e,{count:r,license:n}),{headers:i});if(!a.ok)throw Error(`Sketchfab search failed for ${n}: ${a.status}`);let o=await a.json();return Array.isArray(o.results)?o.results:[]}function Qn(e){return{uid:e.uid,name:e.name||`Sketchfab model`,license:Hn(e.license),licenseLabel:Wn(e.license),author:e.user?.displayName||e.user?.username||`Sketchfab creator`,authorUrl:e.user?.profileUrl||``,viewerUrl:e.viewerUrl||`https://sketchfab.com/3d-models/${e.uid}`,thumbnail:ir(e.thumbnails),faceCount:e.faceCount||e.archives?.gltf?.faceCount||e.archives?.glb?.faceCount||0,vertexCount:e.vertexCount||e.archives?.gltf?.vertexCount||e.archives?.glb?.vertexCount||0,size:e.archives?.glb?.size||e.archives?.gltf?.size||0,source:e}}async function $n(e,t){if(!t){let t=await rr(e);if(t)return t}if(!t)throw Error(`Sketchfab downloads require a configured OMEGA Sketchfab token or a pasted OAuth/API token.`);let n=await fetch(`https://api.sketchfab.com/v3/models/${encodeURIComponent(e)}/download`,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok)throw Error(`Sketchfab download request failed: ${n.status}`);return n.json()}function er(e={}){let t=cr(`omega_session`);return t?{...e,Authorization:`Bearer ${t}`}:{...e}}async function tr(){try{let e=await fetch(`/api/sketchfab/status`,{cache:`no-store`,headers:er()});return e.ok?e.json():{ok:!1,configured:!1}}catch{return{ok:!1,configured:!1}}}async function nr(e,t){try{let n=new URLSearchParams({q:String(e||``).trim(),count:String(t)}),r=await fetch(`/api/sketchfab/search?${n}`,{cache:`no-store`,headers:er()});if(!r.ok)return null;let i=await r.json();return!i?.ok||!Array.isArray(i.models)?null:i.models.filter(e=>Un(e.license)).map(e=>({uid:e.uid,name:e.name||`Sketchfab model`,license:Hn(e.license),licenseLabel:Wn(e.license),author:e.author||`Sketchfab creator`,authorUrl:e.authorUrl||``,viewerUrl:e.viewerUrl||`https://sketchfab.com/3d-models/${e.uid}`,thumbnail:e.thumbnail||``,faceCount:e.faceCount||0,vertexCount:e.vertexCount||0,size:e.size||0,source:e}))}catch{return null}}async function rr(e){try{let t=new URLSearchParams({uid:String(e||``)}),n=await fetch(`/api/sketchfab/download?${t}`,{cache:`no-store`,headers:er()});if(!n.ok)return null;let r=await n.json();return!r?.ok||!r.download?null:r.download}catch{return null}}function ir(e){return[...Array.isArray(e?.images)?e.images:[]].sort((e,t)=>(t.width||0)-(e.width||0))[0]?.url||``}var ar=[{name:`Tractor`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/CesiumMilkTruck/glTF-Binary/CesiumMilkTruck.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/CesiumMilkTruck/screenshot/screenshot-thumb.png`},{name:`Racecar`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/ToyCar/glTF-Binary/ToyCar.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/ToyCar/screenshot/screenshot-thumb.png`},{name:`Duck`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/glTF-Binary/Duck.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/screenshot/screenshot-thumb.png`},{name:`Lantern`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Lantern/glTF-Binary/Lantern.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Lantern/screenshot/screenshot-thumb.png`},{name:`Sofa`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/GlamVelvetSofa/glTF-Binary/GlamVelvetSofa.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/GlamVelvetSofa/screenshot/screenshot-thumb.png`},{name:`Water Bottle`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/WaterBottle/glTF-Binary/WaterBottle.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/WaterBottle/screenshot/screenshot-thumb.png`},{name:`Antique Camera`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/AntiqueCamera/glTF-Binary/AntiqueCamera.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/AntiqueCamera/screenshot/screenshot-thumb.png`},{name:`Saw`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/ReciprocatingSaw/glTF-Binary/ReciprocatingSaw.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/ReciprocatingSaw/screenshot/screenshot-thumb.png`},{name:`Castle Sponza`,provider:`kenney`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Sponza/glTF-Binary/Sponza.glb`,license:`cc0`,author:`Kenney.nl`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Sponza/screenshot/screenshot-thumb.png`},{name:`Robot Expressive`,provider:`quaternius`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/RobotExpressive.glb`,license:`cc0`,author:`Quaternius.com`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake1.png`},{name:`Soldier`,provider:`quaternius`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Soldier.glb`,license:`cc0`,author:`Quaternius.com`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake2.png`},{name:`Flamingo`,provider:`quaternius`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Flamingo.glb`,license:`cc0`,author:`Quaternius.com`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake3.png`},{name:`Parrot`,provider:`quaternius`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Parrot.glb`,license:`cc0`,author:`Quaternius.com`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake4.png`},{name:`Stork`,provider:`quaternius`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Stork.glb`,license:`cc0`,author:`Quaternius.com`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake5.png`},{name:`Sheen Chair`,provider:`quaternius`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/SheenChair.glb`,license:`cc0`,author:`Quaternius.com`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake6.png`},{name:`XBot Rigged`,provider:`mixamo`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Xbot.glb`,license:`free`,author:`Mixamo / Adobe`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake1.png`},{name:`Soldier Rigged`,provider:`mixamo`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Soldier.glb`,license:`free`,author:`Mixamo / Adobe`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake2.png`},{name:`Robot Anim`,provider:`mixamo`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/RobotExpressive.glb`,license:`free`,author:`Mixamo / Adobe`,thumbnail:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/snowflake3.png`}];function or(e){return String(e||``).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)}function sr(e){return String(e||``).charAt(0).toUpperCase()+String(e||``).slice(1)}function cr(e){try{return localStorage.getItem(`jarvis_${e}_credentials_v1`)||``}catch{return``}}function lr(e,t){try{localStorage.setItem(`jarvis_${e}_credentials_v1`,String(t||``).trim())}catch{}}try{if(typeof localStorage<`u`)for(let e of[`jarvis_poly_pizza_credentials_v1`,`jarvis_cgtrader_credentials_v1`,`jarvis_turbosquid_credentials_v1`,`jarvis_mixamo_credentials_v1`]){let t=localStorage.getItem(e);(t===`omega-public-free-poly-pizza-key-2026`||t===`cgtrader_omega_public_free_session`||t===`turbosquid_omega_public_free_session`||t===`mixamo_omega_public_free_adobe_id`)&&localStorage.removeItem(e)}}catch{}async function ur(e,t,n){try{let r=new URL(`https://www.cgtrader.com/api/v1/models`);r.searchParams.set(`q`,String(e||``).trim()),r.searchParams.set(`free`,`true`),r.searchParams.set(`per_page`,String(Math.min(n,24))),r.searchParams.set(`sort`,`relevance`),r.searchParams.set(`file_type`,`glb,gltf,fbx,obj`);let i=await fetch(r.toString(),{headers:{Authorization:`Token ${t}`,Accept:`application/json`}});if(!i.ok)throw Error(`CGTrader API returned ${i.status}`);let a=await i.json(),o=Array.isArray(a.data)?a.data:Array.isArray(a.models)?a.models:[];if(o.length)return o.map(e=>({uid:`cgtrader:${e.id||e.uid||e.slug}`,name:e.name||e.title||`CGTrader Model`,license:e.license||`free`,licenseLabel:e.license_label||`Free Standard`,author:e.author?.username||e.user?.name||`CGTrader Creator`,authorUrl:`https://www.cgtrader.com/designers/${e.author?.username||``}`,viewerUrl:e.url||`https://www.cgtrader.com/3d-models/${e.slug||e.id}`,thumbnail:e.previews?.[0]?.url||e.preview_url||e.thumbnail||``,faceCount:e.polygon_count||0,vertexCount:e.vertex_count||0,size:e.total_size||0,downloadUrl:e.download_url||e.files?.[0]?.url||``,source:`cgtrader`})).slice(0,n)}catch{}let r=new URLSearchParams({q:String(e||``).trim(),count:String(n),api_key:t}),i=await fetch(`/api/cgtrader/search?${r}`,{cache:`no-store`,headers:er()});if(!i.ok)throw Error(`OMEGA CGTrader proxy returned ${i.status}`);let a=await i.json();if(!a?.ok||!Array.isArray(a.models)||!a.models.length)throw Error(`CGTrader proxy: no results`);return a.models.map(e=>({...e,source:`cgtrader`})).slice(0,n)}async function dr(e,t,n){let r=String(t||``).indexOf(`:`),i=r>0?t.slice(0,r).trim():``,a=r>0?t.slice(r+1).trim():``;try{let t=new URL(`https://www.turbosquid.com/turbosquid/search/api/search`);t.searchParams.set(`search_keyword`,String(e||``).trim()),t.searchParams.set(`price_min`,`0`),t.searchParams.set(`price_max`,`0`),t.searchParams.set(`media_typeid`,`2`),t.searchParams.set(`file_type`,`glb,gltf,fbx`),t.searchParams.set(`per_page`,String(Math.min(n,24))),t.searchParams.set(`sort_by`,`relevance`);let r={Accept:`application/json`};i&&a&&(r.Authorization=`Bearer ${a}`);let o=await fetch(t.toString(),{headers:r});if(!o.ok)throw Error(`TurboSquid API returned ${o.status}`);let s=await o.json(),c=Array.isArray(s.results)?s.results:Array.isArray(s.products)?s.products:[];if(c.length)return c.map(e=>({uid:`turbosquid:${e.id||e.product_id||e.slug}`,name:e.name||e.title||`TurboSquid Model`,license:e.license||`free`,licenseLabel:e.license_label||`Free Standard`,author:e.artist?.username||e.author||`TurboSquid Artist`,authorUrl:`https://www.turbosquid.com/Search/Artists/${e.artist?.username||``}`,viewerUrl:e.url||`https://www.turbosquid.com/3d-models/${e.slug||e.id}`,thumbnail:e.thumbnail_url||e.preview_url||e.thumbnail||``,faceCount:e.polygon_count||0,vertexCount:e.vertex_count||0,size:e.file_size||0,downloadUrl:e.download_url||e.files?.[0]?.download_url||``,source:`turbosquid`})).slice(0,n)}catch{}let o=new URLSearchParams({q:String(e||``).trim(),count:String(n)});i&&o.set(`username`,i),a&&o.set(`api_key`,a);let s=await fetch(`/api/turbosquid/search?${o}`,{cache:`no-store`,headers:er()});if(!s.ok)throw Error(`OMEGA TurboSquid proxy returned ${s.status}`);let c=await s.json();if(!c?.ok||!Array.isArray(c.models)||!c.models.length)throw Error(`TurboSquid proxy: no results`);return c.models.map(e=>({...e,source:`turbosquid`})).slice(0,n)}async function fr(e,t,n){let r=String(t||``).indexOf(`:`);if(r<1)throw Error(`Mixamo: credentials must be adobe_email:adobe_password`);let i=t.slice(0,r).trim(),a=t.slice(r+1).trim();if(!i||!a)throw Error(`Mixamo: email or password empty`);try{let t=await fetch(`https://ims-na1.adobelogin.com/ims/token/v3`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({grant_type:`password`,username:i,password:a,client_id:`mixamo_studio`,client_secret:`mixamo_studio`,scope:`openid,creative_sdk,avatar_sync`})});if(!t.ok)throw Error(`Adobe IMS auth failed: ${t.status}`);let r=(await t.json()).access_token;if(!r)throw Error(`Adobe IMS returned no access_token`);let o=new URL(`https://mixamo-api.adobe.com/v1/products`);o.searchParams.set(`limit`,String(Math.min(n,24))),o.searchParams.set(`offset`,`0`),e&&o.searchParams.set(`query`,String(e).trim()),o.searchParams.set(`type`,`Character,Motion`),o.searchParams.set(`order_by`,`relevance`);let s=await fetch(o.toString(),{headers:{Authorization:`Bearer ${r}`,"X-Api-Key":`mixamo_studio`,Accept:`application/json`}});if(!s.ok)throw Error(`Mixamo API returned ${s.status}`);let c=await s.json(),l=Array.isArray(c.results)?c.results:Array.isArray(c.data)?c.data:[];if(l.length)return l.map(e=>({uid:`mixamo:${e.id||e.character_id||e.slug}`,name:e.name||e.character_name||`Mixamo Character`,license:`free`,licenseLabel:`Free (Mixamo)`,author:`Mixamo / Adobe`,authorUrl:`https://www.mixamo.com/#/?id=${e.id||``}`,viewerUrl:`https://www.mixamo.com/#/?id=${e.id||``}`,thumbnail:e.thumbnail_url||e.preview_url||e.image||``,faceCount:e.polygon_count||0,vertexCount:0,size:0,downloadUrl:e.export_url||``,source:`mixamo`})).slice(0,n)}catch{}let o=await fetch(`/api/mixamo/search`,{method:`POST`,headers:er({"Content-Type":`application/json`}),body:JSON.stringify({email:i,password:a,q:String(e||``).trim(),count:n}),cache:`no-store`});if(!o.ok)throw Error(`OMEGA Mixamo proxy returned ${o.status}`);let s=await o.json();if(!s?.ok||!Array.isArray(s.models)||!s.models.length)throw Error(`Mixamo proxy: no results`);return s.models.map(e=>({...e,source:`mixamo`})).slice(0,n)}async function pr(e,t,n){let r=`https://api.poly.pizza/v1/search?q=${encodeURIComponent(e)}`,i=await fetch(r,{headers:{"x-auth-token":t}});if(!i.ok)throw Error(`Poly.pizza returned ${i.status}`);return((await i.json()).results||[]).map(e=>({uid:`poly_pizza:${e.id||e.uid}`,name:e.title||e.name||`Poly.pizza model`,license:e.license||`cc0`,licenseLabel:e.license||`CC0`,author:e.author||`Poly.pizza Creator`,authorUrl:`https://poly.pizza/m/${e.id||e.uid}`,viewerUrl:`https://poly.pizza/m/${e.id||e.uid}`,thumbnail:e.thumbnail||`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/screenshot/screenshot-thumb.png`,faceCount:e.faceCount||0,vertexCount:e.vertexCount||0,size:e.size||0,downloadUrl:e.Download||e.url||``,source:`poly_pizza`})).slice(0,n)}async function mr(e,t=`all`,n=``,{count:r=24}={}){let i=String(e||``).trim().toLowerCase(),a=[];(t===`all`||t===`stable_fast_3d`)&&i&&a.push({uid:`stable_fast_3d:generate:${or(i)}`,name:`Generate: "${i}"`,license:`Local AI Generation`,licenseLabel:`Local`,author:`Stable Fast 3D (Jarvis)`,authorUrl:``,viewerUrl:``,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Box/glTF/Box_thumbnail.jpg`,faceCount:0,vertexCount:0,size:0,downloadUrl:`api:spawn_3d_model:${i}`,source:`stable_fast_3d`,catalogSource:`ai-generation`,provider:`stable_fast_3d`});let o=cr(`poly_pizza`);if((t===`all`||t===`poly_pizza`)&&o&&i)try{let e=await pr(i,o,r);a.push(...e)}catch{}let s=cr(`cgtrader`);if((t===`all`||t===`cgtrader`)&&s&&i)try{let e=await ur(i,s,r);a.push(...e)}catch{}let c=cr(`turbosquid`);if((t===`all`||t===`turbosquid`)&&c&&i)try{let e=await dr(i,c,r);a.push(...e)}catch{}let l=cr(`mixamo`);if((t===`all`||t===`mixamo`)&&l&&i)try{let e=await fr(i,l,r);a.push(...e)}catch{}let u=ar.filter(e=>{let n=t===`all`||e.provider===t,r=!i||e.name.toLowerCase().includes(i)||e.author.toLowerCase().includes(i);return n&&r}).map(e=>({uid:`${e.provider}:${or(e.name)}`,name:e.name,license:e.license,licenseLabel:e.license===`cc0`?`CC0`:`Free`,author:e.author,authorUrl:e.url,viewerUrl:e.url,thumbnail:e.thumbnail,faceCount:0,vertexCount:0,size:0,downloadUrl:e.url,source:e.provider,catalogSource:`curated-sample`,provider:e.provider}));if(a.push(...u),t===`all`||t===`cgtrader`||t===`turbosquid`||t===`poly_pizza`||t===`mixamo`){let e=[{name:`Retro Space Ship`,license:`Free Standard`,author:`Sample fallback asset`,provider:`cgtrader`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb`,keywords:[`space`,`ship`,`rocket`,`vehicle`,`helmet`,`sci-fi`,`scifi`]},{name:`SciFi Plasma Gun`,license:`Free Standard`,author:`Sample fallback asset`,provider:`cgtrader`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Lantern/glTF-Binary/Lantern.glb`,keywords:[`gun`,`weapon`,`scifi`,`plasma`,`laser`]},{name:`Modern Office Chair`,license:`Free Standard`,author:`Sample fallback asset`,provider:`cgtrader`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/SheenChair.glb`,keywords:[`chair`,`furniture`,`office`,`seat`]},{name:`Astronaut Character`,license:`Free Standard`,author:`Sample fallback asset`,provider:`cgtrader`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Soldier.glb`,keywords:[`astronaut`,`person`,`space`,`character`]},{name:`City Sports Car`,license:`Free Standard`,author:`Sample fallback asset`,provider:`turbosquid`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/ToyCar/glTF-Binary/ToyCar.glb`,keywords:[`car`,`vehicle`,`sports`,`auto`,`toy`]},{name:`Fighter Jet Plane`,license:`Free Standard`,author:`Sample fallback asset`,provider:`turbosquid`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/CesiumMilkTruck/glTF-Binary/CesiumMilkTruck.glb`,keywords:[`plane`,`jet`,`aircraft`,`vehicle`,`fly`]},{name:`Lighthouse Beacon`,license:`Free Standard`,author:`Sample fallback asset`,provider:`turbosquid`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Lantern/glTF-Binary/Lantern.glb`,keywords:[`lighthouse`,`beacon`,`tower`,`building`]},{name:`Industrial Wooden Crate`,license:`Free Standard`,author:`Sample fallback asset`,provider:`turbosquid`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/glTF-Binary/Duck.glb`,keywords:[`crate`,`box`,`barrel`,`wood`,`industrial`]},{name:`Low Poly Tree Pack`,license:`CC0`,author:`Sample fallback asset`,provider:`poly_pizza`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Lantern/glTF-Binary/Lantern.glb`,keywords:[`tree`,`forest`,`plant`,`nature`,`lowpoly`]},{name:`Holographic Gizmo Sphere`,license:`CC0`,author:`Sample fallback asset`,provider:`poly_pizza`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/OrientationTest/glTF-Binary/OrientationTest.glb`,keywords:[`sphere`,`gizmo`,`hologram`,`test`]},{name:`Magical Potion Bottle`,license:`CC0`,author:`Sample fallback asset`,provider:`poly_pizza`,url:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/WaterBottle/glTF-Binary/WaterBottle.glb`,keywords:[`potion`,`magic`,`bottle`,`drink`]},{name:`Mythical Knight Shield`,license:`CC0`,author:`Sample fallback asset`,provider:`poly_pizza`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/SheenChair.glb`,keywords:[`shield`,`armor`,`knight`,`weapon`]},{name:`YBot Rigged Character`,license:`Free`,author:`Sample fallback asset`,provider:`mixamo`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Xbot.glb`,keywords:[`ybot`,`character`,`man`,`rigged`,`skeletal`]},{name:`Zombie Undead Anim`,license:`Free`,author:`Sample fallback asset`,provider:`mixamo`,url:`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/gltf/Soldier.glb`,keywords:[`zombie`,`monster`,`undead`,`animated`,`rigged`]}].filter(e=>{let n=t===`all`||e.provider===t,r=!i||e.name.toLowerCase().includes(i)||e.keywords.some(e=>i.includes(e)||e.includes(i));return n&&r}).map(e=>({uid:`${e.provider}:${or(e.name)}`,name:e.name,license:`free`,licenseLabel:e.license,author:e.author,authorUrl:e.url,viewerUrl:e.url,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/screenshot/screenshot-thumb.png`,faceCount:0,vertexCount:0,size:0,downloadUrl:e.url,source:e.provider,catalogSource:`sample-fallback`,provider:e.provider}));a.push(...e)}if(t===`all`||t===`sketchfab`)try{let t=await Yn(e,n,{count:r});a.push(...t.map(e=>({...e,downloadUrl:``,source:`sketchfab`})))}catch{}let d=new Set;return a=a.filter(e=>e?.uid&&!d.has(e.uid)&&d.add(e.uid)),!a.length&&i&&a.push({uid:`forge:${or(i)}`,name:`${sr(i)} (Interactive Forge)`,license:`free`,licenseLabel:`CC0 / Procedural`,author:`Jarvis Model Forge`,authorUrl:`#`,viewerUrl:`#`,thumbnail:`https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Duck/screenshot/screenshot-thumb.png`,faceCount:0,vertexCount:0,size:0,downloadUrl:`forge-procedural`,source:`forge`}),a.slice(0,r)}function hr(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch{return t}}function gr(e,t){try{return localStorage.setItem(e,JSON.stringify(t)),!0}catch{return!1}}function _r(e,t=``){try{return localStorage.getItem(e)||t}catch{return t}}function vr(e,t){try{return localStorage.setItem(e,String(t)),!0}catch{return!1}}var yr=0,br=!1;function xr(e=`ar`){let t=globalThis.crypto?.getRandomValues?Array.from(globalThis.crypto.getRandomValues(new Uint8Array(8)),e=>e.toString(16).padStart(2,`0`)).join(``):(()=>{br||(br=!0),yr=(yr+1)%1048576;let e=String(globalThis.performance?.now?.()||0).replace(`.`,``);return`${Date.now().toString(36)}_${e}_${yr.toString(36)}`})();return`${e}_${Date.now().toString(36)}_${t}`}function Sr(e,t,{valueKey:n=null,labelKey:r=null}={}){if(e){e.replaceChildren();for(let i of t){let t=document.createElement(`option`);if(Array.isArray(i)||n&&r&&i&&typeof i==`object`){let[e,a]=Array.isArray(i)?i:[i[n],i[r]];t.value=String(e??``),t.textContent=String(a??e??``)}else t.value=String(i),t.textContent=String(i);e.appendChild(t)}}}var Cr=1,wr=2048,Tr=8;function Er(e){let t=new Set,n=new Set,r=new Set,i=0,a=0;if(!e?.traverse)return{bytes:0,geometryCount:0,materialCount:0,textureCount:0,maxDimension:0,warnings:[]};e.updateMatrixWorld?.(!0);let o=new xe().setFromObject(e);if(!o.isEmpty()){let e=o.getSize(new S);a=Math.max(e.x,e.y,e.z,0)}e.traverse(e=>{e.geometry&&!t.has(e.geometry)&&(t.add(e.geometry),i+=Mr(e.geometry)),Ar(e.material,e=>{n.has(e)||(n.add(e),i+=2048),jr(e,(e,t)=>{r.has(e)||(r.add(e),i+=Nr(e))})})});let s=[];return i>48*1024*1024&&s.push(`model-asset-heavy`),r.size>12&&s.push(`texture-count-high`),a>12&&s.push(`model-scale-large`),{bytes:i,geometryCount:t.size,materialCount:n.size,textureCount:r.size,maxDimension:a,warnings:s}}function Dr(e,t={}){if(!e?.traverse)return e;let n=Number.isFinite(t.targetSize)?t.targetSize:Cr,r=Number.isFinite(t.maxTextureSize)?t.maxTextureSize:wr,i=Number.isFinite(t.maxAnisotropy)?t.maxAnisotropy:Tr,a=Er(e),o=new xe().setFromObject(e);if(!o.isEmpty()){let t=o.getSize(new S),r=n/Math.max(t.x,t.y,t.z,1e-4),i=o.getCenter(new S);e.position.sub(i),e.scale.multiplyScalar(r)}return e.userData=e.userData||{},e.userData.assetMetrics=a,e.userData.assetWarnings=a.warnings.slice(),e.traverse(e=>{e.isMesh&&(e.castShadow=!0,e.receiveShadow=!0,e.frustumCulled=!0,e.material&&Ar(e.material,(e,t)=>{Or(e,{maxTextureSize:r,maxAnisotropy:i})}))}),e.updateMatrixWorld?.(!0),e}function Or(e,t={}){if(!e)return e;let n=Number.isFinite(t.maxTextureSize)?t.maxTextureSize:wr,r=Number.isFinite(t.maxAnisotropy)?t.maxAnisotropy:Tr;return e.userData=e.userData||{},e.needsUpdate=!0,`roughness`in e&&(e.roughness=Pr(e.roughness)),`metalness`in e&&(e.metalness=Pr(e.metalness)),`emissiveIntensity`in e&&(e.emissiveIntensity=Math.min(Number(e.emissiveIntensity??1),1)),jr(e,(e,t)=>{kr(e,t,{maxTextureSize:n,maxAnisotropy:r})}),e}function kr(e,t=``,n={}){if(!e)return e;let r=Number.isFinite(n.maxTextureSize)?n.maxTextureSize:wr,i=Number.isFinite(n.maxAnisotropy)?n.maxAnisotropy:Tr,a=e.image||{},o=a.width||a.videoWidth||a.naturalWidth||0,s=a.height||a.videoHeight||a.naturalHeight||0;return/map|baseColor|albedo|diffuse|emissive/i.test(t)&&(e.colorSpace=de),e.flipY=!1,e.generateMipmaps=o>0&&s>0,e.minFilter=o>r||s>r?f:h,e.magFilter=f,e.anisotropy=Math.max(1,Math.min(i,e.anisotropy||i)),e.needsUpdate=!0,e}function Ar(e,t){(Array.isArray(e)?e:[e]).filter(Boolean).forEach(e=>t(e))}function jr(e,t){let n=new Set,r=(e,i=``)=>{if(!(!e||typeof e!=`object`)){if(e.isTexture){n.has(e)||(n.add(e),t(e,i));return}if(Array.isArray(e)){e.forEach(e=>r(e,i));return}e.value?.isTexture?r(e.value,i):e.constructor===Object&&Object.entries(e).forEach(([e,t])=>r(t,e))}};Object.entries(e||{}).forEach(([e,t])=>r(t,e))}function Mr(e){let t=0,n=e=>{e?.array?.byteLength&&(t+=e.array.byteLength)};return Object.values(e.attributes||{}).forEach(n),Object.values(e.morphAttributes||{}).forEach(e=>e.forEach(n)),n(e.index),t}function Nr(e){let t=e?.image||{};if(t.data?.byteLength)return t.data.byteLength;let n=t.width||t.videoWidth||t.naturalWidth||256,r=t.height||t.videoHeight||t.naturalHeight||256;return Math.max(1,n)*Math.max(1,r)*4}function Pr(e){return Math.max(0,Math.min(1,Number(e)||0))}var Fr=`jarvis_ar_model_forge_v1`,Ir=[`house`,`room`,`device`,`vehicle`,`character`,`scene`],Lr=[`open`,`close`,`toggle`,`rotate`,`reveal`,`hide`,`shatter`,`reconfigure`];function Rr(){if(globalThis.crypto?.getRandomValues){let e=new Uint32Array(1);return globalThis.crypto.getRandomValues(e),e[0]/4294967295}return performance.now()%997/997}function zr(){return hr(Fr,[])}function Br(e){let t=zr().filter(t=>t.id!==e.id);return t.push(e),gr(Fr,t.slice(-40)),e}function L({name:e=`Custom Model`,prompt:t=``,kit:n=`scene`,parts:r=[],behaviors:i=[]}={}){let a=Ir.includes(String(n||``).toLowerCase())?String(n).toLowerCase():`scene`;return{id:xr(`blueprint`),name:String(e||`Custom Model`).trim()||`Custom Model`,prompt:String(t||``).trim(),kit:a,parts:Array.isArray(r)&&r.length?r.map(di):yi(a),behaviors:Array.isArray(i)&&i.length?i.map(fi):bi(a),createdAt:Date.now(),updatedAt:Date.now()}}async function Vr(e,t={}){let n=String(e||``).trim();if(!n)throw Error(`A prompt is required to generate a blueprint.`);let r=globalThis.Jarvis;if(!r?.query)return w(`Jarvis is unavailable, so the model forge is using a local template blueprint instead.`,`Model Forge`),L({name:t.name||n.slice(0,24),prompt:n,kit:t.kit||`scene`});let i=[`Create a compact JSON blueprint for a fully interactive 3D model.`,`Return JSON only, no markdown, no prose.`,`Schema:`,`{`,` "name": "string",`,` "kit": "house|room|device|vehicle|character|scene",`,` "parts": [`,` {`,` "name": "string",`,` "type": "base|wall|door|window|roof|drawer|panel|screen|wheel|prop|light|arm|leg|head|detail",`,` "geometry": "box|sphere|cylinder|cone|torus|ring|capsule|octahedron|icosahedron",`,` "material": "matte|metal|glass|glow|wood",`,` "position": [0,0,0],`,` "rotation": [0,0,0],`,` "scale": [1,1,1],`,` "actions": ["open","close","toggle","rotate","reveal","hide","shatter","reconfigure"]`,` }`,` ],`,` "behaviors": [`,` { "gesture": "pinch|fist|open-palm|swipe-left|swipe-right|two-hand-scale", "action": "string", "target": "part name" }`,` ]`,`}`,`Prompt: ${n}`,t.name?`Preferred name: ${t.name}`:``,t.kit?`Preferred kit: ${t.kit}`:``].filter(Boolean).join(`
`);try{let e=Ti(await r.query(i));if(e){let r=L({name:e.name||t.name||n.slice(0,24),prompt:n,kit:e.kit||t.kit||`scene`,parts:Array.isArray(e.parts)?e.parts:[],behaviors:Array.isArray(e.behaviors)?e.behaviors:[]});return r.prompt=n,r.source=`jarvis`,r.updatedAt=Date.now(),r}}catch(e){w(`Jarvis blueprint generation failed, using local template: ${e.message}`,`Model Forge`)}return L({name:t.name||n.slice(0,24),prompt:n,kit:t.kit||gi(n)})}function Hr(e,t=pe){let n=e?.id?e:L(e),r=new t.Group;r.name=`interactive-${B(n.name)}`,r.userData.isARObject=!0,r.userData.modelName=n.name,r.userData.modelForge={id:n.id,kit:n.kit,prompt:n.prompt,behaviors:n.behaviors,parts:[],state:{}};let i=[],a={base:[],walls:[],doors:[],windows:[],roofs:[],details:[],lights:[],wheels:[],screens:[],arms:[],legs:[],heads:[],drawers:[]};for(let e of n.parts){let n=ei(e,t);i.push(n),r.add(n.root),a[mi(e.type)].push(n),r.userData.modelForge.parts.push({id:n.id,name:n.name,type:n.type,actions:n.actions.slice()})}return ti(r,a,n,t),Ur(r,n),Br(n),r}function Ur(e,t){return e.userData.modelForge=e.userData.modelForge||{},e.userData.modelForge.id=t.id,e.userData.modelForge.kit=t.kit,e.userData.modelForge.prompt=t.prompt,e.userData.modelForge.behaviors=Array.isArray(t.behaviors)?t.behaviors.map(fi):[],e.userData.modelForge.parts=e.userData.modelForge.parts||[],e}function Wr(e,t,{minScore:n=.5,minHits:r=2}={}){let i=String(e||``).toLowerCase(),a=new Set((t||[]).map(e=>B(e.name)).filter(Boolean));if(!a.size)return null;let o=null,s=0;for(let e of zr()){if(!e||e.source!==`jarvis`||String(e.kit||``).toLowerCase()!==i)continue;let t=Array.isArray(e.behaviors)?e.behaviors:[],c=[...new Set(t.map(e=>B(e.target)).filter(Boolean))];if(!c.length)continue;let l=c.filter(e=>a.has(e)).length,u=l/c.length;l>=r&&u>=n&&u>s&&(o=e,s=u)}return o?{blueprint:o,score:s}:null}function Gr(e,t={}){if(!e)throw Error(`No model object was provided.`);let n=t.kit||_i(e),r=Array.isArray(t.parts)&&t.parts.length?t.parts:Kr(e,n),i=t.name||e.userData?.modelName||`Custom Model`,a=Wr(n,r);if(a){let o={...a.blueprint,id:xr(`blueprint`),name:i,prompt:t.prompt||a.blueprint.prompt||``,parts:r.map(di),source:`template-reuse`,templateOf:a.blueprint.id,updatedAt:Date.now()};return Ur(e,o),e.userData.modelForgeBlueprint=o,k(`forge-template-reused`,{name:i,kit:n,score:a.score,templateOf:a.blueprint.id}),w(`Reused interactive template for ${i} (${Math.round(a.score*100)}% part match) — no regeneration needed.`,`Model Forge`),o}let o=L({name:i,prompt:t.prompt||``,kit:n,parts:r,behaviors:t.behaviors||bi(n,r)});return Ur(e,o),e.userData.modelForgeBlueprint=o,globalThis.Jarvis?.query&&Vr(`We have a 3D model named "${i}" (kit: "${n}") containing discovered parts: ${r.map(e=>e.name).join(`, `)}. Create an ultimate interactive Stark-level behavioral blueprint. Generate highly custom actions (like 'raise landing gear', 'ignite thruster', 'open cockpit') and bind them to the correct parts using gestures.`,{name:i,kit:n}).then(t=>{t&&t.source===`jarvis`&&(Ur(e,t),e.userData.modelForgeBlueprint=t,$r(e),k(`object-placed`,{object:e,modelName:i}),k(`assistant`,`Stark Interface synchronized for ${i}. Loaded bespoke interactive controls.`),w(`Stark Interface synchronized for ${i}.`,`Jarvis AI`))}).catch(e=>{w(`Jarvis background blueprint upgrade failed for ${i}.`,`Model Forge`)}),o}function Kr(e,t=_i(e)){let n=[];return e?.traverse?.(t=>{!t.isMesh&&!t.isObject3D||t!==e&&n.push({name:t.name||t.userData?.partName||t.userData?.role||`part_${n.length+1}`,type:mi(t.userData?.role||t.userData?.partType||hi(t.name)),material:`matte`,position:[t.position.x,t.position.y,t.position.z],rotation:[t.rotation.x,t.rotation.y,t.rotation.z],scale:[t.scale.x,t.scale.y,t.scale.z],actions:xi(t.userData?.role||hi(t.name))})}),n.length>=2?n:wi(e,t,n)}function qr(e,t=document.createElement(`div`)){let n=e?.userData?.modelForge,r=Array.isArray(n?.behaviors)&&n.behaviors.length?[...new Set(n.behaviors.map(e=>e.action).filter(Boolean))]:Lr;t.replaceChildren(),t.style.cssText=`display:flex;flex-wrap:wrap;gap:8px`;for(let n of r){let r=document.createElement(`button`);r.className=`panel-action`,r.textContent=n,r.onclick=()=>Zr(e,n),t.appendChild(r)}return t}function Jr(e,t){let n=e.parent||t.parent;if(!n)return!1;let r=new xe().setFromObject(t),i=Number.isFinite(r.max.y)?r.max.y:t.position.y+.2,a=Number.isFinite(r.min.x)&&Number.isFinite(r.max.x)?(r.min.x+r.max.x)/2:t.position.x,o=Number.isFinite(r.min.z)&&Number.isFinite(r.max.z)?(r.min.z+r.max.z)/2:t.position.z,s=new g;n.add(s);let c=[];for(let e=0;e<20;e++){let t=new b(new ke(.015,8,8),new d({color:3388415,transparent:!0,opacity:.85}));t.position.set(a+(Rr()-.5)*.04,i,o+(Rr()-.5)*.04),s.add(t),c.push({mesh:t,velocity:new S((Rr()-.5)*.05,-.4-Rr()*.3,(Rr()-.5)*.05),delay:e*60})}let l=performance.now(),u=2e3,f=()=>{let e=performance.now()-l;if(e>u){n.remove(s),s.traverse(e=>{e.isMesh&&(e.geometry?.dispose(),e.material?.dispose())});return}c.forEach(n=>{if(e>n.delay){n.velocity.y-=.012,n.mesh.position.addScaledVector(n.velocity,.016);let r=1-(e-n.delay)/(u-n.delay);n.mesh.material.opacity=Math.max(0,r*.85),n.mesh.position.y<t.position.y-.3&&n.mesh.scale.multiplyScalar(.94)}}),requestAnimationFrame(f)};return f(),w(`Water flowing successfully from ${t.userData?.modelName||`source`}.`,`Water Flow`),!0}function Yr(e,t,n){let r=!1;return e.traverse(e=>{let t=String(e.name||``).toLowerCase(),i=String(e.userData?.partType||``).toLowerCase();(i.includes(`light`)||i.includes(`lamp`)||i.includes(`glow`)||t.includes(`light`)||t.includes(`lamp`)||t.includes(`glow`))&&(r=!0,e.userData.partState=e.userData.partState||{},e.userData.partState.open=n,e.traverse(e=>{e.isLight&&(e.visible=n,e.intensity=n?2.5:0)}),e.isMesh&&e.material&&(n?(e.material.emissive&&e.material.emissive.setHex(16771584),e.material.emissiveIntensity!==void 0&&(e.material.emissiveIntensity=2),e.material.color&&e.material.color.setHex(16771584)):(e.material.emissive&&e.material.emissive.setHex(0),e.material.emissiveIntensity!==void 0&&(e.material.emissiveIntensity=0),e.material.color&&e.material.color.setHex(8109311))))}),r?(w(n?`Lights turned ON successfully.`:`Lights turned OFF successfully.`,`Lighting Control`),!0):!1}function Xr(e,t){let n=null,r=t.replace(`open-`,``).replace(`close-`,``).replace(`toggle-`,``).trim().toLowerCase();if(e.traverse(e=>{if(n)return;let t=String(e.userData?.partName||e.name||``).toLowerCase();(t.includes(r)||r===`boot`&&t.includes(`trunk`)||r===`trunk`&&t.includes(`boot`))&&(n=e)}),n){let e=t.startsWith(`open-`)||t.startsWith(`toggle-`)&&!n.userData.partState?.open;return ri(n,e),w(`${e?`Opening`:`Closing`} ${n.userData.partName||r} pivot hinge.`,`Hinge Action`),!0}return!1}function Zr(e,t,n={}){if(!e)return!1;let r=String(t||``).toLowerCase().trim().replace(/\s+/g,`-`);if(/^(open|close|toggle)-(boot|hood|trunk|door|door-left|door-right)$/.test(r)&&Xr(e,r)||/^(turn-on-lights|on-lights|lights-on|lights-off|off-lights|turn-off-lights|lights|on|off)$/.test(r)&&Yr(e,e,!r.includes(`off`)&&r!==`off`)||/^(bring-water|pour-water|pour|water|fill)$/.test(r)&&Jr(e,e))return!0;let i=(e.userData?.modelForge?.behaviors||[]).filter(e=>e.action===r||e.gesture===r),a=i.length?i.map(t=>ui(e,t.target)).filter(Boolean):[e],o=!1;for(let t of a)o=ni(e,t,r,n)||o;return!o&&e!==a[0]&&(o=ni(e,e,r,n)),o}function Qr(e,t,n={}){let r=String(t||``).toLowerCase(),i=(e?.userData?.modelForge?.behaviors||[]).filter(e=>e.gesture===r);if(!i.length)return r===`pinch`?Zr(e,`toggle`,n):r===`fist`?Zr(e,`grab`,n):r===`swipe-left`?Zr(e,`close`,n):r===`swipe-right`?Zr(e,`open`,n):r===`two-hand-scale`?Zr(e,`reconfigure`,n):!1;let a=!1;for(let t of i)a=ni(e,ui(e,t.target)||e,t.action,n)||a;return a}function $r(e){let t=e?.userData?.modelForgeBlueprint||e?.userData?.modelForge;return t?Br({...t,updatedAt:Date.now(),name:e.userData?.modelName||t.name||`Custom Model`}):null}function ei(e,t){let n=xr(`part`),r=String(e.name||e.role||`part_${n.slice(-4)}`).trim()||`part_${n.slice(-4)}`,i=mi(e.type||e.role),a=Si(e.material,t),o=new t.Group;o.name=`${B(r)}_root`,o.position.fromArray(Ei(e.position)),o.rotation.set(...Di(e.rotation)),o.scale.set(...Oi(e.scale)),o.userData.partId=n,o.userData.partName=r,o.userData.partType=i,o.userData.partActions=Array.isArray(e.actions)&&e.actions.length?e.actions.map(pi):xi(i);let s=null,c=null;if(e.geometry){let n=String(e.geometry).toLowerCase().trim();n===`box`||n===`cube`?c=new t.BoxGeometry(.25,.25,.25):n===`sphere`?c=new t.SphereGeometry(.15,32,16):n===`cylinder`?c=new t.CylinderGeometry(.1,.1,.28,24):n===`cone`?c=new t.ConeGeometry(.12,.26,24):n===`torus`?c=new t.TorusGeometry(.14,.02,12,48):n===`ring`?c=new t.RingGeometry(.08,.14,32):n===`capsule`?c=new t.CapsuleGeometry(.08,.2,8,24):n===`octahedron`?c=new t.OctahedronGeometry(.12):n===`icosahedron`&&(c=new t.IcosahedronGeometry(.12))}if(c)s=new t.Mesh(c,a),o.add(s);else if(i===`door`){let n=new t.Group;n.name=`${B(r)}_hinge`,n.userData.interactivePivot=!0,n.position.x=0;let i=new t.Mesh(new t.BoxGeometry(.22,.5,.04),a);i.position.x=.11,i.castShadow=!0,i.receiveShadow=!0,n.add(i),o.add(n),s=i,o.userData.interactivePivot=n,o.userData.closedRotation=0,o.userData.openRotation=Number.isFinite(e.openAngle)?e.openAngle:Math.PI/2}else if(i===`window`)s=new t.Mesh(new t.PlaneGeometry(.35,.3),a),s.position.z=.02,o.add(s);else if(i===`roof`)s=new t.Mesh(new t.ConeGeometry(.34,.28,4),a),s.rotation.y=Math.PI/4,o.add(s);else if(i===`light`){s=new t.Mesh(new t.SphereGeometry(.09,32,16),a);let e=new t.PointLight(16777215,1.2,2.6,2);e.position.set(0,0,0),o.add(s,e),o.userData.light=e}else i===`wheel`?(s=new t.Mesh(new t.CylinderGeometry(.11,.11,.05,20),a),s.rotation.z=Math.PI/2,o.add(s)):i===`screen`?(s=new t.Mesh(new t.BoxGeometry(.42,.25,.03),a),o.add(s)):(s=new t.Mesh(Ci(i,t),a),o.add(s));return o.userData.partMesh=s,o.userData.partState={open:!1,visible:!0,rotated:!1,shatter:!1},{id:n,name:r,type:i,root:o,mesh:s,actions:o.userData.partActions}}function ti(e,t,n,r){let i=String(n.kit||`scene`).toLowerCase(),a=t.base[0]?.root||t.walls[0]?.root||t.details[0]?.root||null;return a&&a.scale.multiplyScalar(1),i===`house`?(t.base[0]&&t.base[0].root.position.set(0,-.15,0),t.walls.forEach((e,t)=>{e.root.position.set(t%2==0?-.16:.16,.05,t<2?-.16:.16),e.root.scale.set(1,1,1)}),t.doors[0]&&t.doors[0].root.position.set(.18,-.12,.18),t.windows[0]&&t.windows[0].root.position.set(-.18,.06,.18),t.roofs[0]&&t.roofs[0].root.position.set(0,.28,0)):i===`room`?(t.base[0]&&t.base[0].root.position.set(0,-.18,0),t.walls.forEach((e,t)=>{e.root.position.set(t<2?-.22:.22,.05,t%2==0?-.22:.22)})):i===`vehicle`?(t.base[0]&&t.base[0].root.position.set(0,-.08,0),t.wheels.forEach((e,t)=>{let n=t<2?-.22:.22,r=t%2==0?-.16:.16;e.root.position.set(n,-.16,r)})):i===`device`&&(t.base[0]&&t.base[0].root.position.set(0,0,0),t.screens.forEach(e=>e.root.position.set(0,.01,.01))),e.userData.modelForge.layout=i,e}function ni(e,t,n,r={}){if(!t)return!1;let i=String(n||``).toLowerCase();return i===`open`?ri(t,!0):i===`close`?ri(t,!1):i===`toggle`?ri(t,!t.userData.partState?.open):i===`rotate`?ii(t,r?.delta||Math.PI/2):i===`reveal`?ai(t,!0):i===`hide`?ai(t,!1):i===`shatter`?oi(e,t):i===`reconfigure`?si(e):i===`grab`?ci(t,r):li(t,i,r)}function ri(e,t){let n=e.userData.interactivePivot||e,r=n.rotation.y,i=t?e.userData.openRotation??Math.PI/2:e.userData.closedRotation??0;return e.userData.partState=e.userData.partState||{},e.userData.partState.open=t,ki(360,e=>{n.rotation.y=r+(i-r)*Ai(e)})}function ii(e,t){let n=e.userData.partMesh||e,r=e.userData.rotateAxis||`y`,i=n.rotation[r],a=i+t;return e.userData.partState=e.userData.partState||{},e.userData.partState.rotated=!0,ki(240,e=>{n.rotation[r]=i+(a-i)*ji(e)})}function ai(e,t){return e.visible=t,e.traverse?.(e=>{e.visible=t}),e.userData.partState=e.userData.partState||{},e.userData.partState.visible=t,!0}function oi(e,t){let n=[];if(t.traverse?.(e=>{e.isMesh&&n.push(e)}),!n.length)return si(e);let r=new S;return t.getWorldPosition(r),n.forEach((e,t)=>{let n=new S(Math.cos(t*2.399),.35+t%3*.12,Math.sin(t*1.917)).normalize();e.userData.shatterStart=performance.now(),e.userData.shatterFrom=r.clone(),e.userData.shatterDirection=n}),ki(680,e=>{let t=Ai(e);n.forEach(e=>{let n=e.userData.shatterDirection;n&&(e.position.copy(n).multiplyScalar(t*.65),e.rotation.x+=.05*t,e.rotation.y+=.06*t,e.rotation.z+=.04*t)})})}function si(e){let t=e.children.filter(e=>e.isObject3D);return t.forEach((e,t)=>{let n=Math.floor(t/3),r=(t%3-1)*.18,i=.04*n,a=(n-.5)*.12;e.position.x+=r*.2,e.position.y+=i*.2,e.position.z+=a*.2}),ki(340,e=>{let n=Ai(e);t.forEach((e,t)=>{let r=Math.floor(t/3),i=(t%3-1)*.18,a=.04*r,o=(r-.5)*.12;e.position.x+=(i-e.position.x)*n*.12,e.position.y+=(a-e.position.y)*n*.12,e.position.z+=(o-e.position.z)*n*.12})})}function ci(e,t){return t?.position&&e.position?.copy?(e.position.copy(t.position),!0):(e.userData.partState=e.userData.partState||{},e.userData.partState.grabbed=!0,!0)}function li(e,t,n){e.userData.partState=e.userData.partState||{},e.userData.partState.lastAction=t;let r=String(t||``).toLowerCase().trim();if(r.includes(`raise`)||r.includes(`lift`)||r===`up`||r.includes(`deploy-gear`)){let t=e.position.y;return ki(400,n=>{e.position.y=t+.12*Ai(n)})}if(r.includes(`lower`)||r===`down`||r.includes(`retract-gear`)){let t=e.position.y;return ki(400,n=>{e.position.y=t-.12*Ai(n)})}if(r.includes(`extend`)||r.includes(`deploy`)||r.includes(`unfold`)||r.includes(`expand`)){let t=e.scale.clone(),n=e.rotation.y;return ki(500,r=>{let i=Ai(r);e.scale.copy(t).multiplyScalar(1+.18*i),e.rotation.y=n+.35*i})}if(r.includes(`retract`)||r.includes(`fold`)||r.includes(`pull`)||r.includes(`collapse`)){let t=e.scale.clone(),n=e.rotation.y;return ki(500,r=>{let i=Ai(r);e.scale.copy(t).multiplyScalar(1-.18*i),e.rotation.y=n-.35*i})}if(r.includes(`ignite`)||r.includes(`fire`)||r.includes(`charge`)||r.includes(`thrust`)||r.includes(`launch`)){if(e.isMesh&&e.material){let t=e.material.emissive?e.material.emissive.getHex():0;e.material.emissive=new ie(54015),e.material.emissiveIntensity!==void 0&&(e.material.emissiveIntensity=4),window.setTimeout(()=>{e.material.emissive&&e.material.emissive.setHex(t),e.material.emissiveIntensity!==void 0&&(e.material.emissiveIntensity=0)},1e3)}return!0}return e.userData.partState.lastContext=n||{},!0}function ui(e,t){let n=B(t);if(!n)return null;let r=null;return e.traverse?.(e=>{r||[e.name,e.userData?.partName,e.userData?.role,e.userData?.partType].filter(Boolean).map(B).includes(n)&&(r=e.userData?.interactivePivot||e)}),r}function di(e={}){return{name:String(e.name||e.role||`part`).trim(),type:mi(e.type||e.role),material:[`matte`,`metal`,`glass`,`glow`,`wood`].includes(String(e.material||``).toLowerCase())?String(e.material).toLowerCase():`matte`,geometry:e.geometry?String(e.geometry).toLowerCase().trim():void 0,position:Ei(e.position),rotation:Di(e.rotation),scale:Oi(e.scale),actions:Array.isArray(e.actions)&&e.actions.length?e.actions.map(pi):xi(e.type||e.role),openAngle:Number.isFinite(e.openAngle)?e.openAngle:void 0}}function fi(e={}){return{gesture:String(e.gesture||``).toLowerCase().trim(),action:pi(e.action||e.trigger||``),target:String(e.target||e.part||``).trim()}}function pi(e){return String(e||``).toLowerCase().trim().replace(/\s+/g,`-`)}function mi(e){let t=String(e||``).toLowerCase().trim().replace(/\s+/g,`-`);return[`wall`,`door`,`window`,`roof`,`drawer`,`panel`,`screen`,`wheel`,`prop`,`light`,`arm`,`leg`,`head`,`detail`,`base`].includes(t)?t:hi(t)}function hi(e){let t=B(e);return t.includes(`door`)?`door`:t.includes(`window`)?`window`:t.includes(`roof`)?`roof`:t.includes(`wheel`)?`wheel`:t.includes(`screen`)||t.includes(`display`)?`screen`:t.includes(`light`)||t.includes(`lamp`)?`light`:t.includes(`drawer`)?`drawer`:t.includes(`wall`)?`wall`:t.includes(`base`)||t.includes(`floor`)?`base`:t.includes(`arm`)?`arm`:t.includes(`leg`)?`leg`:t.includes(`head`)?`head`:`detail`}function gi(e){let t=B(e);return t.includes(`house`)||t.includes(`home`)?`house`:t.includes(`room`)||t.includes(`bedroom`)||t.includes(`kitchen`)?`room`:t.includes(`car`)||t.includes(`truck`)||t.includes(`vehicle`)?`vehicle`:t.includes(`phone`)||t.includes(`device`)||t.includes(`tablet`)?`device`:t.includes(`character`)||t.includes(`person`)||t.includes(`robot`)?`character`:`scene`}function _i(e){return gi(B(e?.userData?.modelName||e?.name||``))}function R(e,t){let n=new Set(e.map(B));for(let e of t)if(n.has(B(e)))return e;return``}function z(e){return e===`house`||e===`room`?`core`:e===`vehicle`?`chassis`:e===`device`?`screen`:e===`character`?`torso`:`core`}function vi(e){return Math.max(.04,Math.min(Number(e)||1,4))}function yi(e){let t={house:[{name:`base`,type:`base`,material:`matte`,position:[0,-.15,0],scale:[1.2,.6,1.2]},{name:`front-door`,type:`door`,material:`wood`},{name:`left-window`,type:`window`,material:`glass`},{name:`right-window`,type:`window`,material:`glass`},{name:`roof`,type:`roof`,material:`matte`}],room:[{name:`floor`,type:`base`,material:`matte`,position:[0,-.16,0],scale:[1.3,.05,1.3]},{name:`wall-a`,type:`wall`,material:`matte`},{name:`wall-b`,type:`wall`,material:`matte`},{name:`door`,type:`door`,material:`metal`},{name:`window`,type:`window`,material:`glass`}],device:[{name:`body`,type:`base`,material:`metal`,position:[0,0,0],scale:[1,.6,.15]},{name:`screen`,type:`screen`,material:`glass`,position:[0,.01,.09]},{name:`button`,type:`detail`,material:`glow`,position:[.27,-.05,.08],scale:[.16,.16,.16]}],vehicle:[{name:`chassis`,type:`base`,material:`metal`,position:[0,-.03,0],scale:[1.2,.36,.64]},{name:`wheel-front-left`,type:`wheel`,material:`metal`,position:[-.35,-.18,-.22]},{name:`wheel-front-right`,type:`wheel`,material:`metal`,position:[.35,-.18,-.22]},{name:`wheel-back-left`,type:`wheel`,material:`metal`,position:[-.35,-.18,.22]},{name:`wheel-back-right`,type:`wheel`,material:`metal`,position:[.35,-.18,.22]}],character:[{name:`torso`,type:`base`,material:`matte`,position:[0,.02,0],scale:[.36,.5,.18]},{name:`head`,type:`head`,material:`matte`,position:[0,.4,0],scale:[.28,.28,.28]},{name:`left-arm`,type:`arm`,material:`matte`,position:[-.28,.12,0],scale:[.12,.42,.12]},{name:`right-arm`,type:`arm`,material:`matte`,position:[.28,.12,0],scale:[.12,.42,.12]},{name:`left-leg`,type:`leg`,material:`matte`,position:[-.12,-.42,0],scale:[.12,.42,.12]},{name:`right-leg`,type:`leg`,material:`matte`,position:[.12,-.42,0],scale:[.12,.42,.12]}],scene:[{name:`core`,type:`base`,material:`matte`,position:[0,0,0],scale:[.9,.6,.9]},{name:`detail-a`,type:`detail`,material:`glow`,position:[-.26,.12,.2]},{name:`detail-b`,type:`detail`,material:`glow`,position:[.28,.1,-.18]},{name:`control-panel`,type:`screen`,material:`glass`,position:[0,.18,.32]}]};return t[e]||t.scene}function bi(e,t=[]){let n=t.map(e=>B(e.name)),r=R(n,[`front-door`,`door`,`front`,`main-door`,`screen`,`control-panel`])||z(e),i=R(n,[`roof`,`top`,`cover`,`lid`])||z(e),a=R(n,[`screen`,`display`,`control-panel`])||z(e),o=R(n,[`wheel-front-left`,`wheel-front-right`,`wheel-back-left`,`wheel-back-right`,`wheel`])||z(e),s={house:[{gesture:`pinch`,action:`toggle`,target:r},{gesture:`open-palm`,action:`reconfigure`,target:i},{gesture:`swipe-left`,action:`close`,target:r},{gesture:`swipe-right`,action:`open`,target:r},{gesture:`fist`,action:`shatter`,target:i}],room:[{gesture:`pinch`,action:`open`,target:r},{gesture:`fist`,action:`close`,target:r},{gesture:`two-hand-scale`,action:`reconfigure`,target:R(n,[`floor`,`base`])||z(e)},{gesture:`open-palm`,action:`reveal`,target:a}],device:[{gesture:`pinch`,action:`toggle`,target:a},{gesture:`open-palm`,action:`reveal`,target:R(n,[`body`,`base`])||z(e)},{gesture:`swipe-left`,action:`hide`,target:a},{gesture:`swipe-right`,action:`open`,target:a}],vehicle:[{gesture:`pinch`,action:`toggle`,target:R(n,[`chassis`,`base`])||z(e)},{gesture:`fist`,action:`reconfigure`,target:o},{gesture:`swipe-left`,action:`rotate`,target:o},{gesture:`swipe-right`,action:`open`,target:R(n,[`door`,`hood`,`trunk`])||z(e)}],character:[{gesture:`pinch`,action:`toggle`,target:R(n,[`head`])||z(e)},{gesture:`fist`,action:`grab`,target:R(n,[`torso`,`body`])||z(e)},{gesture:`swipe-right`,action:`reconfigure`,target:R(n,[`left-arm`,`arm`])||z(e)},{gesture:`swipe-left`,action:`rotate`,target:R(n,[`right-arm`,`arm`])||z(e)}],scene:[{gesture:`pinch`,action:`toggle`,target:R(n,[`core`,`root`,`base`])||z(e)},{gesture:`open-palm`,action:`reconfigure`,target:a},{gesture:`fist`,action:`shatter`,target:R(n,[`detail-a`,`detail-b`])||z(e)}]};return(s[e]||s.scene).filter(Boolean)}function xi(e){let t=mi(e);return t===`door`?[`open`,`close`,`toggle`]:t===`window`?[`open`,`close`,`toggle`,`reveal`]:t===`drawer`?[`open`,`close`,`toggle`]:t===`wheel`?[`rotate`]:t===`screen`||t===`light`?[`toggle`,`reveal`,`hide`]:Lr.slice()}function Si(e,t){let n=String(e||`matte`).toLowerCase();return n===`metal`?new t.MeshPhysicalMaterial({color:9422847,roughness:.16,metalness:.92}):n===`glass`?new t.MeshPhysicalMaterial({color:13627391,roughness:.05,transmission:.58,transparent:!0,opacity:.36}):n===`glow`?new t.MeshBasicMaterial({color:51455,transparent:!0,opacity:.9}):n===`wood`?new t.MeshStandardMaterial({color:9202255,roughness:.82,metalness:.02}):new t.MeshStandardMaterial({color:8109311,roughness:.55,metalness:.1})}function Ci(e,t){let n=mi(e);return n===`base`||n===`wall`?new t.BoxGeometry(.5,.32,.5):n===`drawer`?new t.BoxGeometry(.28,.14,.28):n===`arm`?new t.CapsuleGeometry(.06,.28,5,16):n===`leg`?new t.CapsuleGeometry(.06,.34,5,16):n===`head`?new t.SphereGeometry(.16,24,16):n===`detail`?new t.IcosahedronGeometry(.08,1):new t.BoxGeometry(.22,.22,.22)}function wi(e,t,n=[]){let r=new xe;if(e&&r.setFromObject(e),!Number.isFinite(r.min.x)||!Number.isFinite(r.max.x))return[...n,...yi(t)];let i=r.getSize(new S),a=Math.max(i.x,.1),o=Math.max(i.y,.1),s=Math.max(i.z,.1),c=Math.max(a,o,s)||.4,l=[{name:`core`,type:`base`,material:`matte`,position:[0,0,0],scale:[1,1,1],actions:[`toggle`,`reconfigure`,`shatter`]},{name:`zone-front`,type:`panel`,material:`glass`,position:[0,0,s*.35],scale:[.72,.72,.12],actions:[`open`,`close`,`toggle`,`reveal`,`hide`]},{name:`zone-back`,type:`panel`,material:`glass`,position:[0,0,-s*.35],scale:[.72,.72,.12],actions:[`open`,`close`,`toggle`,`reveal`,`hide`]},{name:`zone-left`,type:`panel`,material:`glass`,position:[-a*.35,0,0],scale:[.12,.72,.72],actions:[`rotate`,`reconfigure`]},{name:`zone-right`,type:`panel`,material:`glass`,position:[a*.35,0,0],scale:[.12,.72,.72],actions:[`rotate`,`reconfigure`]},{name:`zone-top`,type:`roof`,material:`matte`,position:[0,o*.35,0],scale:[.85,.16,.85],actions:[`open`,`close`,`reconfigure`]},{name:`zone-bottom`,type:`base`,material:`matte`,position:[0,-o*.35,0],scale:[.85,.16,.85],actions:[`reconfigure`,`grab`]},{name:`zone-core`,type:`detail`,material:`glow`,position:[0,0,0],scale:[.42,.42,.42],actions:[`toggle`,`shatter`,`reveal`,`hide`]}];return[...n,...l.map(e=>({...e,scale:[vi(e.scale[0]*(c/1.25)),vi(e.scale[1]*(c/1.25)),vi(e.scale[2]*(c/1.25))]}))]}function Ti(e){if(!e)return null;let t=String(e).replace(/```json|```/gi,``).trim(),n=t.indexOf(`{`),r=t.lastIndexOf(`}`);if(n<0||r<0||r<=n)return null;try{return JSON.parse(t.slice(n,r+1))}catch{return null}}function Ei(e){return Array.isArray(e)&&e.length>=3?[Number(e[0])||0,Number(e[1])||0,Number(e[2])||0]:e&&typeof e==`object`?[Number(e.x)||0,Number(e.y)||0,Number(e.z)||0]:[0,0,0]}function Di(e){return Array.isArray(e)&&e.length>=3?[Number(e[0])||0,Number(e[1])||0,Number(e[2])||0]:e&&typeof e==`object`?[Number(e.x)||0,Number(e.y)||0,Number(e.z)||0]:[0,0,0]}function Oi(e){return Array.isArray(e)&&e.length>=3?[Number(e[0])||1,Number(e[1])||1,Number(e[2])||1]:e&&typeof e==`object`?[Number(e.x)||1,Number(e.y)||1,Number(e.z)||1]:[1,1,1]}function ki(e,t){let n=performance.now();return new Promise(r=>{let i=a=>{let o=Math.min((a-n)/e,1);t(o),o<1?requestAnimationFrame(i):r(!0)};requestAnimationFrame(i)})}function Ai(e){return 1-(1-e)**3}function ji(e){return e<.5?4*e*e*e:1-(-2*e+2)**3/2}function B(e){return String(e||``).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)}var Mi=!1,Ni=!1,Pi=!1,Fi={default:{name:`default`,refDistance:.72,maxDistance:8,rolloffFactor:1.6,dampening:.08,cueGain:1},cinema:{name:`cinema`,refDistance:1.05,maxDistance:12,rolloffFactor:1.25,dampening:.16,cueGain:1.08},open:{name:`open`,refDistance:.68,maxDistance:16,rolloffFactor:1.15,dampening:.03,cueGain:.96},quiet:{name:`quiet`,refDistance:.84,maxDistance:7,rolloffFactor:1.8,dampening:.12,cueGain:.92},lab:{name:`lab`,refDistance:.78,maxDistance:9,rolloffFactor:1.5,dampening:.06,cueGain:1.02}};function Ii(){Mi||(Mi=!0,O(`ar-scene-live`,()=>Hi()),O(`object-placed`,({object:e})=>Li(e)),Ui(),Wi(),Hi(),F(`spatialAudio`,!!Gi()),F(`speechSynthesis`,!!window.speechSynthesis),F(`voiceRecognition`,!!(window.SpeechRecognition||window.webkitSpeechRecognition)))}function Li(e){if(!e)return null;let t=Hi();if(!t)return null;if(e.userData.spatialAudio={...Fi[D.spatialAudio.environmentProfile]||Fi.default,...e.userData.spatialAudio||{}},e.userData.spatialAudioEmitter?.parent===e)return e.userData.spatialAudioEmitter;let n=new ve(t);return n.name=`jarvis-object-spatial-audio`,zi(n,e.userData.spatialAudio),e.add(n),e.userData.spatialAudioAttached=!0,e.userData.spatialAudioEmitter=n,n}async function Ri(e,t=`select`){if(!e)return!1;let n=Hi(),r=Gi();if(!n||!r)return!1;try{if(r.state===`suspended`&&await r.resume(),r.state!==`running`)return!1;D.spatialAudio.unlocked=!0;let i=e.parent?Li(e):Vi(n,e);return i?(i.isPlaying&&i.stop(),i.setBuffer(Ki(r,t)),i.setVolume((Fi[D.spatialAudio.environmentProfile]?.cueGain||1)*(t===`delete`?.9:1)),i.play(),window.setTimeout(()=>{try{i.stop()}catch{}i.userData.detachedAnchor&&(i.userData.detachedAnchor.parent?.remove(i.userData.detachedAnchor),i.disconnect())},420),!0):!1}catch{return!1}}function zi(e,t={}){e.setRefDistance(t.refDistance||.72),e.setMaxDistance(t.maxDistance||8),e.setRolloffFactor(t.rolloffFactor||1.6),e.setDistanceModel(`inverse`)}function Bi(e=`default`){let t=Fi[String(e||`default`).toLowerCase()]||Fi.default;return D.spatialAudio.environmentProfile=t.name,D.spatialAudio.roomProfile={...t},D.placedObjects.forEach(e=>{let n=e?.userData?.spatialAudioEmitter;n&&zi(n,t)}),D.spatialAudio.listener?.context&&(D.spatialAudio.context=D.spatialAudio.listener.context),F(`spatialAudio`,!!Gi()),t}function Vi(e,t){let n=new g;t.getWorldPosition(n.position),I().scene.add(n);let r=new ve(e);return r.name=`jarvis-detached-spatial-cue`,zi(r,t.userData.spatialAudio||Fi.default),r.userData.detachedAnchor=n,n.add(r),r}function Hi(){let{camera:e}=I();return e?(D.spatialAudio.listener||(D.spatialAudio.listener=new Se),D.spatialAudio.listener.parent!==e&&(D.spatialAudio.listener.parent?.remove(D.spatialAudio.listener),e.add(D.spatialAudio.listener)),D.spatialAudio.enabled=!0,D.spatialAudio.context=Gi(),D.spatialAudio.listener):null}function Ui(){if(Pi)return;Pi=!0;let e=()=>Bi(D.nativeOptions?.activeEnvironment||D.spatialAudio.environmentProfile||`default`);O(`native-options`,e),O(`native-ui-state`,e=>{let t=e?.audioEnvironment||e?.environment||e?.profile;t&&Bi(t)}),e()}function Wi(){if(Ni)return;Ni=!0;let e=async()=>{let e=Gi();if(e)try{await e.resume(),D.spatialAudio.unlocked=e.state===`running`,D.spatialAudio.micPermission=D.spatialAudio.unlocked?`granted`:D.spatialAudio.micPermission,D.spatialAudio.unlocked&&w(`Spatial audio unlocked for AR objects.`,`Spatial Audio`)}catch{D.spatialAudio.unlocked=!1}};window.addEventListener(`pointerdown`,e,{passive:!0}),window.addEventListener(`touchstart`,e,{passive:!0})}function Gi(){try{return Ae.getContext()}catch{return null}}function Ki(e,t){let n=e.sampleRate,r=Math.max(1,Math.floor(n*.24)),i=e.createBuffer(1,r,n),a=i.getChannelData(0),o=t===`place`?330:t===`delete`?180:t===`open`?520:430;for(let e=0;e<r;e+=1){let t=e/n,r=Math.exp(-t*12)*Math.min(1,t*90);a[e]=(Math.sin(Math.PI*2*o*t)*.72+Math.sin(Math.PI*2*o*1.5*t)*.2)*r*.16}return i}var qi=null,V=null,Ji=null,Yi=!1,Xi=new Map,Zi=null,Qi=1/60,$i=3,ea=0,ta=0,na=null;function ra(){return Yi&&!!V}function ia(){return na||(na=aa()),na}async function aa(){qi=await t(()=>import(`./physics-Bz_ouFt8.js`).then(e=>e.t),__vite__mapDeps([3,2]),import.meta.url),await qi.init();let e=new qi.Vector3(0,-9.81,0);V=new qi.World(e),Ji=new qi.EventQueue(!0),V.numSolverIterations=8,D.physicsWorld=V,Yi=!0,ta=performance.now();let n=qi.RigidBodyDesc.fixed().setTranslation(0,0,0);Zi=V.createRigidBody(n);let r=qi.ColliderDesc.cuboid(100,.1,100).setFriction(.7).setRestitution(.1);V.createCollider(r,Zi),sa(),console.log(`[AR Physics] Rapier3D world initialized — 60Hz fixed timestep, CCD enabled, 8 solver iterations.`)}var oa=0;function sa(){if(oa)return;let e=performance.now(),t=()=>{let n=performance.now();ca(n-e),e=n,oa=P(t)};oa=P(t)}function ca(e){if(!Yi||!V)return;let t=performance.now(),n=typeof e==`number`&&e>0&&e<200?e/1e3:Math.min((t-ta)/1e3,.05);ta=t,ea+=n;let r=0;for(;ea>=Qi&&r<$i;)V.step(Ji),ea-=Qi,r++;Ji.drainCollisionEvents((e,t,n)=>{n&&window.dispatchEvent(new CustomEvent(`ar-physics-collision`,{detail:{handle1:e,handle2:t}}))});for(let[e,t]of Xi.entries()){let n=e.translation(),r=e.rotation();t.position.set(n.x,n.y,n.z),t.quaternion.set(r.x,r.y,r.z,r.w)}Xi.size>0&&window.dispatchEvent(new CustomEvent(`ar-physics-step`))}function la(e,t=`dynamic`){if(!V)return null;let n=t===`dynamic`?qi.RigidBodyDesc.dynamic():qi.RigidBodyDesc.fixed();n.setTranslation(e.x,e.y,e.z),t===`dynamic`&&(n.setLinearDamping(.1),n.setAngularDamping(.05),n.setCcdEnabled(!0));let r=V.createRigidBody(n),i=qi.ColliderDesc.ball(.2).setFriction(.7).setRestitution(.3);return V.createCollider(i,r),r}function ua(e,t){Xi.set(t,e)}function da(e){V&&V.removeRigidBody(e),Xi.delete(e)}var fa=Uint8Array,pa=Uint16Array,ma=Int32Array,ha=new fa([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),ga=new fa([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),_a=new fa([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),va=function(e,t){for(var n=new pa(31),r=0;r<31;++r)n[r]=t+=1<<e[r-1];for(var i=new ma(n[30]),r=1;r<30;++r)for(var a=n[r];a<n[r+1];++a)i[a]=a-n[r]<<5|r;return{b:n,r:i}},ya=va(ha,2),ba=ya.b,xa=ya.r;ba[28]=258,xa[258]=28;var Sa=va(ga,0),Ca=Sa.b;Sa.r;for(var wa=new pa(32768),H=0;H<32768;++H){var Ta=(H&43690)>>1|(H&21845)<<1;Ta=(Ta&52428)>>2|(Ta&13107)<<2,Ta=(Ta&61680)>>4|(Ta&3855)<<4,wa[H]=((Ta&65280)>>8|(Ta&255)<<8)>>1}for(var Ea=(function(e,t,n){for(var r=e.length,i=0,a=new pa(t);i<r;++i)e[i]&&++a[e[i]-1];var o=new pa(t);for(i=1;i<t;++i)o[i]=o[i-1]+a[i-1]<<1;var s;if(n){s=new pa(1<<t);var c=15-t;for(i=0;i<r;++i)if(e[i])for(var l=i<<4|e[i],u=t-e[i],d=o[e[i]-1]++<<u,f=d|(1<<u)-1;d<=f;++d)s[wa[d]>>c]=l}else for(s=new pa(r),i=0;i<r;++i)e[i]&&(s[i]=wa[o[e[i]-1]++]>>15-e[i]);return s}),Da=new fa(288),H=0;H<144;++H)Da[H]=8;for(var H=144;H<256;++H)Da[H]=9;for(var H=256;H<280;++H)Da[H]=7;for(var H=280;H<288;++H)Da[H]=8;for(var Oa=new fa(32),H=0;H<32;++H)Oa[H]=5;var ka=Ea(Da,9,1),Aa=Ea(Oa,5,1),ja=function(e){for(var t=e[0],n=1;n<e.length;++n)e[n]>t&&(t=e[n]);return t},Ma=function(e,t,n){var r=t/8|0;return(e[r]|e[r+1]<<8)>>(t&7)&n},Na=function(e,t){var n=t/8|0;return(e[n]|e[n+1]<<8|e[n+2]<<16)>>(t&7)},Pa=function(e){return(e+7)/8|0},Fa=function(e,t,n){return(t==null||t<0)&&(t=0),(n==null||n>e.length)&&(n=e.length),new fa(e.subarray(t,n))},Ia=[`unexpected EOF`,`invalid block type`,`invalid length/literal`,`invalid distance`,`stream finished`,`no stream handler`,,`no callback`,`invalid UTF-8 data`,`extra field too long`,`date not in range 1980-2099`,`filename too long`,`stream finishing`,`invalid zip data`],La=function(e,t,n){var r=Error(t||Ia[e]);if(r.code=e,Error.captureStackTrace&&Error.captureStackTrace(r,La),!n)throw r;return r},Ra=function(e,t,n,r){var i=e.length,a=r?r.length:0;if(!i||t.f&&!t.l)return n||new fa(0);var o=!n,s=o||t.i!=2,c=t.i;o&&(n=new fa(i*3));var l=function(e){var t=n.length;if(e>t){var r=new fa(Math.max(t*2,e));r.set(n),n=r}},u=t.f||0,d=t.p||0,f=t.b||0,p=t.l,m=t.d,h=t.m,g=t.n,_=i*8;do{if(!p){u=Ma(e,d,1);var ee=Ma(e,d+1,3);if(d+=3,!ee){var v=Pa(d)+4,te=e[v-4]|e[v-3]<<8,ne=v+te;if(ne>i){c&&La(0);break}s&&l(f+te),n.set(e.subarray(v,ne),f),t.b=f+=te,t.p=d=ne*8,t.f=u;continue}else if(ee==1)p=ka,m=Aa,h=9,g=5;else if(ee==2){var re=Ma(e,d,31)+257,ie=Ma(e,d+10,15)+4,y=re+Ma(e,d+5,31)+1;d+=14;for(var b=new fa(y),ae=new fa(19),x=0;x<ie;++x)ae[_a[x]]=Ma(e,d+x*3,7);d+=ie*3;for(var oe=ja(ae),se=(1<<oe)-1,ce=Ea(ae,oe,1),x=0;x<y;){var le=ce[Ma(e,d,se)];d+=le&15;var v=le>>4;if(v<16)b[x++]=v;else{var ue=0,de=0;for(v==16?(de=3+Ma(e,d,3),d+=2,ue=b[x-1]):v==17?(de=3+Ma(e,d,7),d+=3):v==18&&(de=11+Ma(e,d,127),d+=7);de--;)b[x++]=ue}}var fe=b.subarray(0,re),pe=b.subarray(re);h=ja(fe),g=ja(pe),p=Ea(fe,h,1),m=Ea(pe,g,1)}else La(1);if(d>_){c&&La(0);break}}s&&l(f+131072);for(var me=(1<<h)-1,he=(1<<g)-1,ge=d;;ge=d){var ue=p[Na(e,d)&me],_e=ue>>4;if(d+=ue&15,d>_){c&&La(0);break}if(ue||La(2),_e<256)n[f++]=_e;else if(_e==256){ge=d,p=null;break}else{var ve=_e-254;if(_e>264){var x=_e-257,ye=ha[x];ve=Ma(e,d,(1<<ye)-1)+ba[x],d+=ye}var be=m[Na(e,d)&he],xe=be>>4;be||La(3),d+=be&15;var pe=Ca[xe];if(xe>3){var ye=ga[xe];pe+=Na(e,d)&(1<<ye)-1,d+=ye}if(d>_){c&&La(0);break}s&&l(f+131072);var S=f+ve;if(f<pe){var Se=a-pe,Ce=Math.min(pe,S);for(Se+f<0&&La(3);f<Ce;++f)n[f]=r[Se+f]}for(;f<S;++f)n[f]=n[f-pe]}}t.l=p,t.p=ge,t.b=f,t.f=u,p&&(u=1,t.m=h,t.d=m,t.n=g)}while(!u);return f!=n.length&&o?Fa(n,0,f):n.subarray(0,f)},za=new fa(0),Ba=function(e,t){return e[t]|e[t+1]<<8},Va=function(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0},Ha=function(e,t){return Va(e,t)+Va(e,t+4)*4294967296};function Ua(e,t){return Ra(e,{i:2},t&&t.out,t&&t.dictionary)}var Wa=typeof TextDecoder<`u`&&new TextDecoder;try{Wa.decode(za,{stream:!0})}catch{}var Ga=function(e){for(var t=``,n=0;;){var r=e[n++],i=(r>127)+(r>223)+(r>239);if(n+i>e.length)return{s:t,r:Fa(e,n-1)};i?i==3?(r=((r&15)<<18|(e[n++]&63)<<12|(e[n++]&63)<<6|e[n++]&63)-65536,t+=String.fromCharCode(55296|r>>10,56320|r&1023)):i&1?t+=String.fromCharCode((r&31)<<6|e[n++]&63):t+=String.fromCharCode((r&15)<<12|(e[n++]&63)<<6|e[n++]&63):t+=String.fromCharCode(r)}};function Ka(e,t){if(t){for(var n=``,r=0;r<e.length;r+=16384)n+=String.fromCharCode.apply(null,e.subarray(r,r+16384));return n}else if(Wa)return Wa.decode(e);else{var i=Ga(e),a=i.s,n=i.r;return n.length&&La(8),a}}var qa=function(e,t){return t+30+Ba(e,t+26)+Ba(e,t+28)},Ja=function(e,t,n){var r=Ba(e,t+28),i=Ka(e.subarray(t+46,t+46+r),!(Ba(e,t+8)&2048)),a=t+46+r,o=Va(e,t+20),s=n&&o==4294967295?Ya(e,a):[o,Va(e,t+24),Va(e,t+42)],c=s[0],l=s[1],u=s[2];return[Ba(e,t+10),c,l,i,a+Ba(e,t+30)+Ba(e,t+32),u]},Ya=function(e,t){for(;Ba(e,t)!=1;t+=4+Ba(e,t+2));return[Ha(e,t+12),Ha(e,t+4),Ha(e,t+20)]};function Xa(e,t){for(var n={},r=e.length-22;Va(e,r)!=101010256;--r)(!r||e.length-r>65558)&&La(13);var i=Ba(e,r+8);if(!i)return{};var a=Va(e,r+16),o=a==4294967295||i==65535;if(o){var s=Va(e,r-12);o=Va(e,s)==101075792,o&&(i=Va(e,s+32),a=Va(e,s+48))}for(var c=t&&t.filter,l=0;l<i;++l){var u=Ja(e,a,o),d=u[0],f=u[1],p=u[2],m=u[3],h=u[4],g=u[5],_=qa(e,g);a=h,(!c||c({name:m,size:f,originalSize:p,compression:d}))&&(d?d==8?n[m]=Ua(e.subarray(_,_+f),{out:new fa(p)}):La(14,`unknown compression type `+d):n[m]=Fa(e,_,_+f))}return n}var Za=new d({color:16777215,transparent:!0,opacity:.72}),Qa=`jarvis_ar_placed_objects_v1`,$a=`jarvis_ar_my_models_v1`,eo=`0.158.0`,to=new Oe().setDecoderPath(`https://cdn.jsdelivr.net/npm/three@${eo}/examples/jsm/libs/draco/`),no=new me().setTranscoderPath(`https://cdn.jsdelivr.net/npm/three@${eo}/examples/jsm/libs/basis/`),ro=!1;function io(){if(ro)return;let e=I()?.renderer;if(e)try{no.detectSupport(e),ro=!0}catch{}}function ao(e){return e.setDRACOLoader(to),e.setKTX2Loader(no),e.setMeshoptDecoder(ze),e}var oo=ao(new He),so=8,co=180*1024*1024,lo=new Map,uo=0,fo=null,po=0,mo=new Map,ho=0,go=``,_o=0,vo=0,yo=!1,bo=!1,xo=0,So=new Map,Co=new Set;function wo(){Eo(),Lo(),O(`open-model-forge`,Ao),O(`open-models`,Do),O(`jarvis-model-action`,e=>fs(e)),O(`gesture-pinch`,e=>ds(`pinch`,e)),O(`gesture-fist`,e=>ds(`fist`,e)),O(`gesture-open-palm`,e=>ds(`open-palm`,e)),O(`gesture-swipe-left`,e=>ds(`swipe-left`,e)),O(`gesture-swipe-right`,e=>ds(`swipe-right`,e)),O(`gesture-two-hand-scale`,e=>ds(`two-hand-scale`,e)),O(`world-anchor-sample`,()=>Ss()),O(`native-ar-state`,e=>To(e)),O(`spawn-model`,async e=>{zo(Ln(e?.query||`Duck`).name)}),O(`spawn-generated-glb`,async e=>{if(!e?.model_url)return;let t=e?.model_name||`Generated Model`;try{w(`Loading generated model: ${t}...`,`Jarvis AI Generation`);let n=String(e.model_url);if(n.startsWith(`/`)){let e=D.jarvis?.apiBase?.()||``;e&&(n=`${e}${n}`)}let r=await Ko(n);r.userData.modelName=t,Gr(r,L({name:t,kit:Js(t)})),Ho(r,window.AR_CAMERA_POSITION||new S(0,0,-2)),w(`Successfully deployed ${t}!`,`Jarvis AI Generation`)}catch(e){C(`Failed to load generated model: ${e.message}`,`Generation Error`)}}),setInterval(()=>Zo(),6e4)}function To(e={}){let t=Array.isArray(e.objects)?e.objects:[];for(let e of t){let t=String(e.id||e.uid||``).trim(),n=String(e.label||e.name||e.modelName||e.type||`Native Object`),r=e.position||{x:Number(e.px??e.x??0),y:Number(e.py??e.y??D.floorY+.08),z:Number(e.pz??e.z??-1.6)},i=t?D.placedObjects.find(e=>e.userData.id===t):null;if(i){i.position.copy(Us(r)),i.userData.modelName=n,hs(i);continue}let a=us(n);t&&(a.userData.id=t),a.userData.sourceURL=`native-apk-state`,Gr(a,L({name:n,kit:Js(n)})),Go(a,n,r,null,`native-apk-state`)}}function Eo(){if(yo||bo)return;let e=()=>{yo||(yo=!0,vs().catch(e=>C(e.message,`Model Restore Failed`)))};if(D.liveSceneReady){e();return}bo=!0;let t=O(`ar-scene-live`,()=>{t(),bo=!1,e()})}function Do(){let e=document.createElement(`div`),t=document.createElement(`input`);t.placeholder=`Search free models`;let n=document.createElement(`div`);n.className=`panel-list`;let r=document.createElement(`input`);r.type=`file`,r.accept=`.glb,.gltf,.obj,.fbx`;let i=Oo(),a=document.createElement(`button`);a.className=`panel-action`,a.textContent=`Open Custom 3D Builder`,a.onclick=Rs;let o=document.createElement(`button`);o.className=`panel-action`,o.textContent=`Open Interactive Model Forge`,o.onclick=Ao;let s=document.createElement(`p`);s.className=`panel-note`,s.textContent=`Create models with behavior schemas, named parts, and Jarvis-generated interactions.`,e.append(t,n,i,r,a,o,s);let c=()=>{let e=t.value.toLowerCase();n.replaceChildren(...Fn.filter(t=>!e||t.name.toLowerCase().includes(e)||t.category.includes(e)).map(e=>Po(e)))};t.addEventListener(`input`,c),r.addEventListener(`change`,()=>Fo(r.files?.[0])),c(),new bn({title:`Models`,body:e,icon:`M`,width:390,height:560}).focus()}function Oo(){let e=document.createElement(`section`);e.className=`sketchfab-panel`;let t=document.createElement(`strong`);t.textContent=`JARVIS 3D Asset Nexus`;let n=document.createElement(`p`);n.className=`panel-note`,n.textContent=`Connectors: Turbosquid, CGTrader, Mixamo, Poly.pizza, Kenney, Quaternius, Sketchfab.`;let r=document.createElement(`button`);r.className=`panel-action`,r.style.cssText=`width: 100%; margin: 6px 0; padding: 10px 14px; text-align: left; display: flex; align-items: center; justify-content: space-between; font-size: 13px; border-radius: 12px; font-weight: 500;`;let i=document.createElement(`span`);i.textContent=`API Connectors Logins`;let a=document.createElement(`span`);a.className=`chevron`,a.textContent=`v`,a.style.cssText=`transition: transform 0.25s ease; display: inline-block;`,r.append(i,a);let o=document.createElement(`div`);o.style.cssText=`display: none; flex-direction: column; gap: 10px; margin: 8px 0; padding: 14px; border: 1px solid var(--separator); border-radius: 14px; background: rgba(0,0,0,0.22);`;function s(e,t,n,r){let i=document.createElement(`div`);i.style.cssText=`display: flex; flex-direction: column; gap: 4px;`;let a=document.createElement(`div`);a.style.cssText=`display: flex; align-items: center; justify-content: space-between; font-size: 12px;`;let o=document.createElement(`span`);o.textContent=n,o.style.color=`var(--text-secondary)`;let s=document.createElement(`span`);s.style.cssText=`display: inline-flex; align-items: center; gap: 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; cursor: pointer;`;let c=document.createElement(`input`);c.type=`password`,c.placeholder=t,c.value=e===`sketchfab`?Gn():cr(e),c.style.cssText=`margin: 2px 0 !important; min-height: 38px !important; padding: 8px 12px !important; font-size: 12px !important; border-radius: 10px !important;`;let l=document.createElement(`div`);l.style.cssText=`font-size: 10px; color: var(--warning); display: none; padding: 2px 0 0 2px; line-height: 1.4;`;let u=()=>{let e=c.value.trim();s.replaceChildren();let t=document.createElement(`span`);e?(t.style.cssText=`color:var(--success); margin-right: 2px;`,t.textContent=`●`,s.append(t,document.createTextNode(` Authenticated ✓`)),l.style.display=`none`):(t.style.cssText=`color:var(--warning); margin-right: 2px;`,t.textContent=`●`,s.append(t,document.createTextNode(` No key — tap to add`)),r&&(l.style.display=`block`,l.innerHTML=`⚡ Get your free key at <span style="color:var(--accent);text-decoration:underline;">${r}</span>`))};return s.addEventListener(`click`,()=>c.focus()),c.addEventListener(`input`,u),u(),a.append(o,s),i.append(a,c,l),{wrapper:i,input:c,updateStatus:u}}let c=document.createElement(`div`);c.style.cssText=`background: rgba(96,165,250,0.12); border: 1px solid rgba(96,165,250,0.3); border-radius: 10px; padding: 10px 12px; font-size: 11px; color: rgba(255,255,255,0.85); line-height: 1.5;`,c.innerHTML=`🔑 <strong>Enter your API keys below to unlock live search.</strong><br>Yellow ● = no key set (uses sample models). Green ● = live API active.<br>Kenney & Quaternius are always free — no key needed.`;let l=s(`omega_session`,`OMEGA cloud session token`,`OMEGA Cloud Link`,``),u=s(`sketchfab`,`Sketchfab OAuth/API Token`,`Sketchfab API`,`sketchfab.com/settings/password-api`),d=s(`poly_pizza`,`Poly.pizza API Key`,`Poly.pizza API`,`poly.pizza/account`),f=s(`cgtrader`,`CGTrader API Token`,`CGTrader API Token`,`cgtrader.com/account`),p=s(`turbosquid`,`username:api_key`,`TurboSquid user:key`,`turbosquid.com/Account`),m=s(`mixamo`,`adobe_email:adobe_password`,`Mixamo Adobe email:pass`,`mixamo.com (use your Adobe login)`),h=document.createElement(`div`);h.style.cssText=`display: flex; gap: 8px; font-size: 11px; background: rgba(255,255,255,0.05); padding: 8px 10px; border-radius: 10px; color: var(--text-secondary); justify-content: space-between;`,h.append(ko(`Kenney`,`CC0 active`),ko(`Quaternius`,`CC0 active`));let g=document.createElement(`button`);g.className=`panel-action`,g.textContent=`Save Credentials`,g.style.cssText=`min-height: 38px; font-size: 13px; font-weight: 600; background: var(--accent); color: #fff; margin-top: 6px;`,g.onclick=()=>{let e=l.input.value.trim()!==cr(`omega_session`);if(lr(`omega_session`,l.input.value),Kn(u.input.value),lr(`poly_pizza`,d.input.value),lr(`cgtrader`,f.input.value),lr(`turbosquid`,p.input.value),lr(`mixamo`,m.input.value),e&&D.jarvis){try{D.jarvis.ws?.close()}catch{}D.jarvis.loadConfig()}l.updateStatus(),u.updateStatus(),d.updateStatus(),f.updateStatus(),p.updateStatus(),m.updateStatus(),w(`All 3D Asset Nexus connector credential configurations saved locally.`,`Credentials Saved`)},o.append(c,l.wrapper,u.wrapper,d.wrapper,f.wrapper,p.wrapper,m.wrapper,h,g);let _=!1;r.onclick=()=>{_=!_,o.style.display=_?`flex`:`none`,r.querySelector(`.chevron`).style.transform=_?`rotate(180deg)`:`rotate(0)`};let ee=document.createElement(`div`);ee.className=`inline-row`,ee.style.cssText=`margin: 6px 0; display: flex; align-items: center; gap: 8px;`;let v=document.createElement(`span`);v.textContent=`Source:`,v.style.cssText=`font-size: 13px; color: var(--text-secondary);`;let te=document.createElement(`select`);te.style.cssText=`flex: 1; background: rgba(0,0,0,.35); color: #fff; border: 1px solid var(--glass-border); border-radius: 8px; padding: 6px; font-size: 13px;`,[{value:`all`,label:`All Free Sources (Combined)`},{value:`poly_pizza`,label:`Poly.pizza (Free CC0)`},{value:`kenney`,label:`Kenney.nl (CC0 Game Assets)`},{value:`quaternius`,label:`Quaternius (CC0 Low-Poly)`},{value:`mixamo`,label:`Mixamo (Free Rigged Characters)`},{value:`sketchfab`,label:`Sketchfab (Free CC Assets)`},{value:`cgtrader`,label:`CGTrader (Free CC0/Standard)`},{value:`turbosquid`,label:`Turbosquid (Free CC0/Standard)`}].forEach(e=>{let t=document.createElement(`option`);t.value=e.value,t.textContent=e.label,te.appendChild(t)}),ee.append(v,te);let ne=document.createElement(`div`);ne.className=`inline-row`;let re=document.createElement(`input`);re.placeholder=`Search free 3D models...`;let ie=document.createElement(`button`);ie.className=`panel-action`,ie.textContent=`Search`,ne.append(re,ie);let y=document.createElement(`div`);y.className=`panel-list sketchfab-results`;let b=document.createElement(`p`);b.className=`panel-note`,b.textContent=`Ready to search unified free connectors.`;let ae=!1;return tr().then(e=>{e?.configured&&(ae=!0,b.textContent=`OMEGA Sketchfab token active. Search & placement run completely free.`,u.input.placeholder=`Optional override token`)}).catch(()=>{}),ie.onclick=async()=>{let e=u.input.value.trim()||Gn();Kn(e);let t=te.value;b.textContent=`Searching free assets from ${te.options[te.selectedIndex].text}...`,y.replaceChildren();try{let n=await mr(re.value||`object`,t,e);if(!n.length){b.textContent=`No free assets matched your query on the selected source.`;return}b.textContent=`Found ${n.length} free asset(s).`,y.replaceChildren(...n.map(t=>jo(t,()=>u.input.value.trim()||e,()=>ae)))}catch(e){b.textContent=`Unified search failed.`,C(e.message,`Asset Search Failed`)}},e.append(t,n,r,o,ee,ne,b,y),e}function ko(e,t){let n=document.createElement(`div`),r=document.createElement(`strong`);r.textContent=`${e}:`;let i=document.createElement(`span`);return i.style.color=`var(--success)`,i.textContent=` ● `,n.append(r,i,document.createTextNode(t)),n}async function Ao(){let e=document.createElement(`div`),t=document.createElement(`strong`),n=document.createElement(`p`),r=document.createElement(`input`),i=document.createElement(`select`),a=document.createElement(`textarea`),o=document.createElement(`pre`),s=document.createElement(`div`),c=document.createElement(`button`),l=document.createElement(`button`),u=document.createElement(`button`),d=document.createElement(`button`),f=L({name:`Custom Model`,kit:`scene`}),p=f;t.textContent=`Jarvis 3D Forge`,n.className=`panel-note`,n.textContent=`Build a model as geometry + parts + behaviors + triggers + scripts + exports.`,r.placeholder=`Model name`,r.value=f.name,a.rows=5,a.placeholder=`Describe the model, its parts, and the actions you want`,a.value=`Create a fully interactive model with named parts, gestures, and a behavior schema.`,Sr(i,[`scene`,`house`,`room`,`device`,`vehicle`,`character`]),o.style.cssText=`white-space:pre-wrap;font:12px/1.45 monospace;color:rgba(255,255,255,.82);background:rgba(0,0,0,.25);padding:10px;border-radius:12px;max-height:220px;overflow:auto`,s.className=`panel-row`,c.className=`panel-action`,c.textContent=`Generate Blueprint`,l.className=`panel-action`,l.textContent=`Attach to Selected`,u.className=`panel-action`,u.textContent=`Build and Place`,d.className=`panel-action`,d.textContent=`Save Blueprint`;let m=()=>{o.textContent=JSON.stringify(p,null,2),s.replaceChildren();let e=D.selectedObject||D.placedObjects.at(-1)||null;e&&qr(e,s)};m(),c.onclick=async()=>{try{p=await Vr(a.value,{name:r.value,kit:i.value}),p.name=r.value||p.name,p.prompt=a.value,p.kit=i.value,p.updatedAt=Date.now(),m(),w(`Jarvis blueprint generated. Review the schema and then attach or build.`,`Model Forge`)}catch(e){C(e.message,`Model Forge Failed`)}},l.onclick=()=>{let e=D.selectedObject;if(!e){w(`Select a model first, then attach the schema.`,`Model Forge`);return}Gr(e,{...p,name:r.value||p.name||e.userData.modelName||`Custom Model`,prompt:a.value,kit:i.value}),$r(e),m(),w(`Behavior schema attached to ${e.userData.modelName||`selected model`}.`,`Model Forge`)},u.onclick=()=>{try{let e=Hr({...p,name:r.value||p.name||`Custom Model`,prompt:a.value,kit:i.value});Uo(e,e.userData.modelName),$r(e),w(`${e.userData.modelName} built with ${e.userData.modelForge?.parts?.length||0} interactive parts.`,`Model Forge`)}catch(e){C(e.message,`Model Forge Failed`)}},d.onclick=()=>{p={...p,name:r.value||p.name,prompt:a.value,kit:i.value,updatedAt:Date.now()},Br(p),w(`Blueprint saved locally for later reuse.`,`Model Forge`)},e.append(t,n,r,i,a,c,l,u,d,o,s),new bn({title:`Interactive Model Forge`,body:e,icon:`F`,width:390,height:620}).focus()}function jo(e,t,n=()=>!1){let r=document.createElement(`article`);if(r.className=`model-card ${e.source}-card`,e.thumbnail){let t=document.createElement(`img`);t.src=e.thumbnail,t.alt=``,t.loading=`lazy`,r.appendChild(t)}let i=document.createElement(`div`),a=document.createElement(`strong`),o=document.createElement(`span`),s=document.createElement(`a`);a.textContent=e.name;let c=e.size?Ks(e.size):`free`,l=e.faceCount?` / ${qs(e.faceCount)} faces`:``;o.textContent=`${e.licenseLabel} / ${c}${l}`,s.textContent=`${e.author} (${e.source.toUpperCase()})`,s.href=e.authorUrl||e.viewerUrl||`#`,s.target=`_blank`,s.rel=`noopener`,i.append(a,o,s);let u=document.createElement(`div`);u.className=`model-actions`;let d=document.createElement(`button`);d.className=`panel-action`;let f=e.source===`sketchfab`&&!n()&&!t();d.textContent=f?`Token Needed`:`Place`,d.onclick=()=>{if(f){C(`Sketchfab downloads require a configured token.`,`Token Required`);return}Mo(e,t())};let p=document.createElement(`a`);return p.className=`panel-action link-action`,p.href=e.viewerUrl||`#`,p.target=`_blank`,p.rel=`noopener`,p.textContent=`Open`,u.append(d,p),r.append(i,u),r}async function Mo(e,t){E(`Requesting ${e.source.toUpperCase()} download: ${e.name}...`,55);try{let n;if(e.downloadUrl===`forge-procedural`)n=Hr(L({name:e.name,kit:Js(e.name)}));else if(e.downloadUrl&&e.downloadUrl.startsWith(`api:spawn_3d_model:`)){let t=e.downloadUrl.split(`api:spawn_3d_model:`)[1];w(`[STABLE FAST 3D] Generating custom 3D model for: ${t}...`,`Jarvis AI Generation`),fetch(`/xr/model3d/spawn`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${cr(`omega_session`)||``}`},body:JSON.stringify({description:t,persona:`JARVIS`,use_cloud_fallback:!0})}).then(async e=>{let t=null;try{t=await e.json()}catch{}if(!e.ok){w(`[STABLE FAST 3D] Generation failed (${e.status}). ${t?.detail||``}`.trim(),`Generation Error`);return}if(t?.status===`needs_confirmation`){w(`[STABLE FAST 3D] ${t.message||`Cloud generation required.`}`,`Generation Paused`);return}w(`[STABLE FAST 3D] Model generated and placed in the scene.`,`Generation Complete`)}).catch(e=>{console.error(`Generation request failed:`,e),w(`[STABLE FAST 3D] Generation request failed — check connection.`,`Generation Error`)}),hidePanel(),clearLoading();return}else if(e.downloadUrl)(e.source===`cgtrader`||e.source===`turbosquid`||e.source===`mixamo`||e.source===`poly_pizza`)&&(cr(e.source)?e.source===`mixamo`?w(`[Mixamo] Secure Adobe ID Synchronized! Placed free rigged character.`,`Mixamo Rigging`):e.source===`poly_pizza`?w(`[Poly.pizza] Authenticated API Key! Placed free low-poly asset.`,`Poly.pizza API`):w(`[${e.source.toUpperCase()}] Authenticated as user! Placed free model.`,`${e.source.toUpperCase()} Session`):w(`[${e.source.toUpperCase()}] Session Proxy: Connected via OMEGA public portal... Placed free model!`,`${e.source.toUpperCase()} Session`)),n=await Ko(e.downloadUrl);else if(e.source===`sketchfab`){Kn(t);let r=await $n(e.uid,t),i=r.glb?.url||r.gltf?.url;if(!i)throw Error(`Sketchfab did not return a glTF or GLB download URL.`);n=r.glb?.url?await Ko(i):await No(i)}else throw Error(`Unsupported model source: ${e.source}`);n.userData.modelName=e.name,n.userData.sketchfab=e.sketchfab||{uid:e.uid,author:e.author,authorUrl:e.authorUrl||``,license:e.license||`free`,licenseLabel:e.licenseLabel||`Free`,viewerUrl:e.viewerUrl||``},Gr(n,L({name:e.name,kit:Js(e.name)}));let r=Vo(.5,.56);Go(n,e.name,r.position,r.rotation,`${e.source}:${e.uid}`),w(`${e.name} placed successfully from ${e.source.toUpperCase()}.`,e.source.toUpperCase())}catch(t){C(`${e.source.toUpperCase()} failed: ${t.message}. Spawning premium generated fallback...`,`${e.source.toUpperCase()} Fallback`);let n=us(e.name);Gr(n,L({name:e.name,kit:Js(e.name)}));let r=Vo(.5,.56);Go(n,e.name,r.position,r.rotation,``)}finally{ot()}}async function No(e){let t=await fetch(e);if(!t.ok)throw Error(`Sketchfab archive download failed: ${t.status}`);let n=Xa(new Uint8Array(await t.arrayBuffer())),r=Object.keys(n).filter(e=>e.toLowerCase().endsWith(`.gltf`));if(!r.length)throw Error(`Sketchfab archive did not contain a .gltf scene.`);let i=r.find(e=>e.toLowerCase().replace(/.*\//,``)===`scene.gltf`)??r.reduce((e,t)=>n[t].byteLength>n[e].byteLength?t:e,r[0]),a=new TextDecoder().decode(n[i]),o=i.includes(`/`)?i.slice(0,i.lastIndexOf(`/`)+1):``,s=new Map;for(let[e,t]of Object.entries(n)){let n=Ws(e),r=URL.createObjectURL(new Blob([t],{type:n}));s.set(Gs(e),r),s.set(e.split(`/`).pop(),r)}let c=new ne;c.setURLModifier(e=>{let t=Gs(e),n=Gs(`${o}${t}`);return s.get(t)||s.get(n)||s.get(t.split(`/`).pop())||e});let l=ao(new He(c));return io(),new Promise((e,t)=>{l.parse(a,o,t=>{for(let e of new Set(s.values()))URL.revokeObjectURL(e);e(t.scene)},e=>{for(let e of new Set(s.values()))URL.revokeObjectURL(e);t(e)})})}function Po(e){let t=document.createElement(`article`);t.className=`model-card`;let n=document.createElement(`div`),r=document.createElement(`strong`),i=document.createElement(`span`),a=document.createElement(`button`);return r.textContent=e.name,i.textContent=`${e.category} / ${e.size}`,a.className=`panel-action`,a.textContent=`Place`,a.onclick=()=>zo(e.name),n.append(r,i),t.append(n,a),t}async function Fo(e){if(!e)return;if(e.size>100*1024*1024){C(`Custom model is larger than 100MB. Please optimize or compress it first.`,`Model Too Large`);return}let t=e.name.split(`.`).pop()?.toLowerCase(),n=``;try{n=URL.createObjectURL(e);let r=t===`glb`||t===`gltf`?await Ko(n):await Io(n,t);r.userData.modelName=e.name,Uo(r,e.name);let i=hr($a,[]);i.push({name:e.name,type:t,size:e.size,addedAt:Date.now()}),gr($a,i.slice(-24))}catch(e){C(e.message,`Custom Model Failed`)}finally{n&&URL.revokeObjectURL(n)}}async function Io(e,n){if(n===`obj`){let{OBJLoader:n}=await t(async()=>{let{OBJLoader:e}=await import(`./three-DMwvpBUV.js`).then(e=>e.t);return{OBJLoader:e}},__vite__mapDeps([1,2]),import.meta.url);return new Promise((t,r)=>new n().load(e,t,void 0,r))}if(n===`fbx`){let{FBXLoader:n}=await t(async()=>{let{FBXLoader:e}=await import(`./three-DMwvpBUV.js`).then(e=>e.n);return{FBXLoader:e}},__vite__mapDeps([1,2]),import.meta.url);return new Promise((t,r)=>new n().load(e,t,void 0,r))}throw Error(`Unsupported custom model type: ${n||`unknown`}`)}function Lo(){if(D.modelPlacementEventsBound)return;D.modelPlacementEventsBound=!0;let e=document.getElementById(`camerafeed`);e?.addEventListener(`pointerdown`,e=>ws(e.clientX,e.clientY)),e?.addEventListener(`pointerup`,Ts),e?.addEventListener(`pointermove`,Ts),document.addEventListener(`touchend`,e=>{if(!D.pendingModelToPlace||Bo(e.target))return;let t=e.changedTouches[0];t&&Ro(t.clientX,t.clientY,e)},{passive:!0,capture:!0}),document.addEventListener(`pointerup`,e=>{e.pointerType!==`touch`&&(!D.pendingModelToPlace||Bo(e.target)||Ro(e.clientX,e.clientY,e))},!0)}async function Ro(e,t,n=null){if(!D.pendingModelToPlace)return;let r=performance.now(),i=n?.pointerId??n?.changedTouches?.[0]?.identifier??n?.detail?.pointerId??++xo,a=`${Math.round(e)}:${Math.round(t)}:${n?.type||`auto`}:${i}`;if(r-ho<350&&a===go)return;ho=r,go=a;let o=D.pendingModelToPlace,s=Vo(e/innerWidth,t/innerHeight);D.pendingModelToPlace=``,delete document.body.dataset.jarvisPendingModel,Hs(!1),vo++,window.clearTimeout(_o),_o=0;try{await Ho(o,s.position,s.rotation)}catch(e){C(e.message,`Model Placement Failed`)}}function zo(e){D.pendingModelToPlace=e,document.body.dataset.jarvisPendingModel=e,Hs(!0),w(`Tap a detected surface to place ${e}. Auto-place will use the center hit-test if no tap arrives.`,`Model Armed`),window.clearTimeout(_o),_o=0;let t=++vo;_o=window.setTimeout(()=>{D.pendingModelToPlace===e&&vo===t&&Ro(innerWidth/2,innerHeight*.56)},900)}function Bo(e){return!!e?.closest?.(`.ar-panel, .hud-toolbar, button, input, select, textarea, iframe`)}function Vo(e,t){try{let n=globalThis.XR8?.XrController?.hitTest?.(e,t,[`FEATURE_POINT`,`ESTIMATED_SURFACE`,`DETECTED_SURFACE`]);if(n&&n.length>0)return n[0]}catch{}let{camera:n}=I(),r=new Ce(e*2-1,-(t*2-1)),i=new Me;i.setFromCamera(r,n);let a=(D.floorY-i.ray.origin.y)/i.ray.direction.y;return{position:Number.isFinite(a)&&a>0?i.ray.origin.clone().add(i.ray.direction.clone().multiplyScalar(a)):i.ray.origin.clone().add(i.ray.direction.clone().multiplyScalar(2)),rotation:new Ve}}async function Ho(e,t,n){E(`Loading ${e}...`,55);try{let r=In(e),i=await Ko(r,(t,n)=>{n&&E(`Loading ${e}... ${Math.round(t/n*100)}%`,55+Math.round(t/n*30))});return Gr(i,L({name:e,kit:Js(e)})),Go(i,e,t,n,r),ot(),i}catch(r){C(`Remote GLB failed for ${e}: ${r.message}. Generated fallback spawned instead.`,`Model Fallback`);let i=us(e);return Gr(i,L({name:e,kit:Js(e)})),Go(i,e,t,n,``),ot(),i}}function Uo(e,t=`Custom Model`){let n=Vo(.5,.55);Go(e,t,n.position,n.rotation,``)}function Wo(e){let t=.28,n=D.placedObjects||[];if(!n.length)return e;let r=0,i=()=>n.some(n=>(n.getWorldPosition?n.getWorldPosition(new S):n.position).distanceTo(e)<t);for(;i()&&r<24;){r++;let n=r*2.399963,i=t*(1+Math.floor(r/8))*Math.sqrt(r%8+1)*.6;e.x+=Math.cos(n)*i*.35,e.z+=Math.sin(n)*i*.35}return e}function Go(e,t,n,r,i){let{scene:a}=I();e.position.copy(Wo(Us(n).clone())),r?.isQuaternion?e.quaternion.copy(r):r&&e.quaternion.set(r.x||0,r.y||0,r.z||0,r.w||1),cs(e),e.userData.id=e.userData.id||xr(`model`),e.userData.modelName=t,e.userData.sourceURL=i,e.userData.isARObject=!0,!e.userData.modelForge&&!e.userData.modelForgeBlueprint&&Gr(e,L({name:t,kit:Js(t)})),e.traverse(e=>{e.isMesh&&(e.castShadow=!0,e.receiveShadow=!0,e.frustumCulled=!0)});let o=e.scale.clone();return e.userData.finalScale=o.toArray(),e.scale.setScalar(.001),a.add(e),D.placedObjects.push(e),ms(e),Li(e),ls(e,o,()=>{e.userData.finalScale=o.toArray(),_s(),Ri(e,`place`)}),document.body.dataset.jarvisObjects=String(D.placedObjects.length),document.body.dataset.jarvisLastModel=t,Ot(`upsertObject`,e.userData.id,i||`model`,t,e.position.x,e.position.y,e.position.z),k(`object-placed`,{object:e,modelName:t}),e}function Ko(e,t){io();let n=as(e),r=lo.get(n);if(r?.template)return Promise.resolve(qo(r));if(r?.promise)return r.promise.then(e=>qo(e));let i={key:n,url:e,template:null,promise:null,refCount:0,bytes:0,lastUsed:os(),loading:!0};return i.promise=new Promise((r,a)=>{oo.load(e,e=>{i.template=Dr(e.scene,{targetSize:1,maxTextureSize:2048,maxAnisotropy:6}),i.animations=e.animations||[];let t=Er(i.template);i.metrics=t,i.bytes=Math.max(t.bytes||es(i.template),512*1024),i.lastUsed=os(),i.loading=!1,i.promise=null,$o(i.template,n),t.warnings.length&&k(`assistant`,`Optimized ${n} for scale and texture budget: ${t.warnings.join(`, `)}.`),uo+=i.bytes,r(i)},e=>t?.(e.loaded,e.total),e=>{lo.delete(n),i.loading=!1,i.promise=null,a(e)})}),lo.set(n,i),i.promise.then(e=>qo(e))}function qo(e){e.refCount+=1,e.lastUsed=os();let t=Ne(e.template);return t.userData.assetCacheKey=e.key,t.userData.assetCacheShared=!0,t.userData.assetCacheBytes=e.bytes,$o(t,e.key),Zo(),t}function Jo(e){let t=e?.userData?.assetCacheKey,n=t?lo.get(t):null,r=n?.template?qo(n):e.clone(!0);return r.position.copy(e.position),r.quaternion.copy(e.quaternion),r.scale.copy(e.scale),r.name=e.name,r.visible=e.visible,r.userData={...ss(e.userData),assetCacheKey:r.userData.assetCacheKey,assetCacheShared:r.userData.assetCacheShared,assetCacheBytes:r.userData.assetCacheBytes},delete r.userData.shadow,r.traverse(e=>{e.isMesh&&(e.castShadow=!0,e.receiveShadow=!0,e.frustumCulled=!0)}),r}function Yo(e){let t=e?.userData?.assetCacheKey;if(!t)return!1;let n=lo.get(t);return n?(n.refCount=Math.max(0,n.refCount-1),n.lastUsed=os(),Zo(),!0):!0}function Xo(e){It(e,{disposeSharedAssets:!Yo(e)})}function Zo(e=!1){let t=[...lo.values()].filter(e=>e.template&&!e.loading&&e.refCount===0).sort((e,t)=>e.lastUsed-t.lastUsed);for(;t.length&&(e||lo.size>so||uo>co);)Qo(t.shift())}function Qo(e){!e||e.refCount>0||(lo.delete(e.key),uo=Math.max(0,uo-e.bytes),e.template&&It(e.template,{disposeSharedAssets:!0}),e.template=null)}function $o(e,t){e.userData.sharedAssetKey=t,e.traverse(e=>{e.userData.sharedAssetKey=t,e.geometry&&(e.geometry.userData=e.geometry.userData||{},e.geometry.userData.sharedAssetKey=t),rs(e.material,e=>{e.userData=e.userData||{},e.userData.sharedAssetKey=t,is(e,e=>{e.userData=e.userData||{},e.userData.sharedAssetKey=t})})})}function es(e){let t=new Set,n=new Set,r=new Set,i=0;return e.traverse(e=>{e.geometry&&!t.has(e.geometry)&&(t.add(e.geometry),i+=ts(e.geometry)),rs(e.material,e=>{n.has(e)||(n.add(e),i+=2048),is(e,e=>{r.has(e)||(r.add(e),i+=ns(e))})})}),Math.max(i,512*1024)}function ts(e){let t=0,n=e=>{e?.array?.byteLength&&(t+=e.array.byteLength)};return Object.values(e.attributes||{}).forEach(n),Object.values(e.morphAttributes||{}).forEach(e=>e.forEach(n)),n(e.index),t}function ns(e){let t=e?.image||{};if(t.data?.byteLength)return t.data.byteLength;let n=t.width||t.videoWidth||t.naturalWidth||256,r=t.height||t.videoHeight||t.naturalHeight||256;return Math.max(1,n)*Math.max(1,r)*4}function rs(e,t){(Array.isArray(e)?e:[e]).filter(Boolean).forEach(t)}function is(e,t){let n=new Set,r=e=>{if(!(!e||typeof e!=`object`)){if(e.isTexture){n.has(e)||(n.add(e),t(e));return}if(Array.isArray(e)){e.forEach(r);return}e.value?.isTexture?r(e.value):e.constructor===Object&&Object.values(e).forEach(r)}};Object.values(e).forEach(r)}function as(e){return String(e||``).trim()}function os(){return typeof performance<`u`?performance.now():Date.now()}function ss(e){try{return structuredClone(e)}catch{try{return JSON.parse(JSON.stringify(e))}catch{return{...e}}}}function cs(e){let t=new xe().setFromObject(e).getSize(new S).length(),n=t>0?.55/t:.35;e.scale.setScalar(Math.min(1,n))}function ls(e,t,n){let r=performance.now(),i=0,a=()=>{if(!e.parent){yt(i);return}let o=Math.min((performance.now()-r)/420,1),s=o<.6?o/.6*1.1:1.1-.1*((o-.6)/.4);e.scale.copy(t).multiplyScalar(s),o<1?i=P(a):(e.scale.copy(t),n?.())};i=P(a)}function us(e){let t=new g,n=new b(new v(.28,2),new y({color:43775,emissive:21879,roughness:.25,metalness:.35,transparent:!0,opacity:.78})),r=new b(new je(.42,.008,8,96),Za.clone());r.rotation.x=Math.PI/2;let i=ps(e);return i.position.y=.48,t.add(n,r,i),t}function ds(e,t){let n=D.selectedObject||D.placedObjects.at(-1);n&&(Qr(n,e,t),hs(n),$r(n),Ri(n,e))}function fs(e={}){let t=Ys(e.action||e.command||``),n=String(e.target||e.model||e.query||``).trim(),r=D.selectedObject||D.placedObjects.at(-1)||null;if(n){let e=n.toLowerCase();r=D.placedObjects.find(t=>{let n=String(t.userData?.modelName||``).toLowerCase(),r=t.userData?.modelForge?.parts||[];return n.includes(e)||r.some(t=>String(t.name||``).toLowerCase().includes(e))})||r}!r||!t||(Zr(r,t,e),hs(r),$r(r),Ri(r,t))}function ps(e){let t=String(e||`Model`).trim().toLowerCase(),n=So.get(t);if(n){let e=new Ue(new _e({map:n.texture,transparent:!0}));return e.scale.set(.9,.23,1),e.userData.labelCacheKey=t,e}let r=document.createElement(`canvas`);r.width=512,r.height=128;let i=r.getContext(`2d`);i.clearRect(0,0,r.width,r.height),i.fillStyle=`rgba(0,0,0,0.32)`,i.fillRect(0,0,r.width,r.height),i.fillStyle=`#fff`,i.font=`600 34px Inter, sans-serif`,i.textAlign=`center`,i.textBaseline=`middle`,i.fillText(String(e).slice(0,24),256,64);let a=new qe(r);a.userData=a.userData||{},a.userData.sharedAssetKey=`label:${t}`,So.set(t,{texture:a});let o=new Ue(new _e({map:a,transparent:!0}));return o.scale.set(.9,.23,1),o.userData.labelCacheKey=t,o}function ms(e){e.userData.shadow?.parent?.remove(e.userData.shadow);let t=new b(new o(.35,48),new d({color:0,transparent:!0,opacity:.24,depthWrite:!1}));t.rotation.x=-Math.PI/2,t.name=`jarvis-blob-shadow`,e.userData.shadow=t,hs(e),I().scene.add(t)}function hs(e){let t=e?.userData?.shadow;t&&t.position.set(e.position.x,D.floorY+.004,e.position.z)}function gs(e){return Array.isArray(e)&&e.length>=3&&e.every(e=>Number.isFinite(e)&&e>.01)}function _s(){gr(Qa,D.placedObjects.map(e=>({id:e.userData.id,modelName:e.userData.modelName,sourceURL:e.userData.sourceURL||``,sketchfab:e.userData.sketchfab||null,modelForge:e.userData.modelForge||e.userData.modelForgeBlueprint||null,position:e.position.toArray(),quaternion:e.quaternion.toArray(),scale:Array.isArray(e.userData.finalScale)?e.userData.finalScale:e.scale.toArray(),trackingMode:D.trackingMode,floorY:D.floorY,anchor:ys(e),savedAt:Date.now()})))}async function vs(){let e=hr(Qa,[]),t=[];for(let n of e)try{let e=n.sourceURL&&!n.sourceURL.startsWith(`sketchfab:`)?await Ko(n.sourceURL):us(n.modelName);e.userData.id=n.id,e.position.fromArray(n.position),e.quaternion.fromArray(n.quaternion),e.scale.fromArray(gs(n.scale)?n.scale:[.35,.35,.35]),e.userData.finalScale=e.scale.toArray(),e.userData.modelName=n.modelName,e.userData.sourceURL=n.sourceURL,e.userData.sketchfab=n.sketchfab||null,e.userData.worldAnchor=n.anchor||null,e.userData.isARObject=!0,Gr(e,n.modelForge||L({name:n.modelName||`Restored Model`,kit:Js(n.modelName)})),I().scene.add(e),D.placedObjects.push(e),ms(e),Li(e),xs(e),document.body.dataset.jarvisObjects=String(D.placedObjects.length)}catch(e){t.push(`${n.modelName||`Restored Model`}: ${e?.message||`load failed`}`);let r=us(n.modelName||`Restored Model`);r.position.fromArray(n.position||[0,D.floorY,-2]),r.scale.fromArray(gs(n.scale)?n.scale:[.35,.35,.35]),r.userData.finalScale=r.scale.toArray(),r.userData.id=n.id||xr(`model`),r.userData.modelName=n.modelName||`Restored Model`,r.userData.sourceURL=n.sourceURL||``,r.userData.sketchfab=n.sketchfab||null,r.userData.worldAnchor=n.anchor||null,r.userData.isARObject=!0,Gr(r,n.modelForge||L({name:n.modelName||`Restored Model`,kit:Js(n.modelName)})),I().scene.add(r),D.placedObjects.push(r),ms(r),Li(r),xs(r),document.body.dataset.jarvisObjects=String(D.placedObjects.length)}t.length&&w(`Some saved models failed to restore and were replaced with generated fallbacks: ${t.slice(0,3).join(`; `)}${t.length>3?` (+${t.length-3} more)`:``}`,`Model Restore`)}function ys(e){return{type:`world-point-signature-v1`,position:e.position.toArray(),quaternion:e.quaternion.toArray(),floorY:D.floorY,signature:bs(),trackingMode:D.trackingMode,createdAt:Date.now()}}function bs(){let e=D.worldPointBuffer.slice(-360);if(e.length<10)return{count:e.length,centroid:[0,D.floorY,0],floorY:D.floorY};let t=e.reduce((e,t)=>(e.x+=t.x,e.y+=t.y,e.z+=t.z,e),new S).multiplyScalar(1/e.length);return{count:e.length,centroid:t.toArray(),floorY:D.floorY}}function xs(e){e.userData.worldAnchor&&(Co.add(e),Cs(e))}function Ss(){Co.forEach(e=>{if(!e.parent){Co.delete(e);return}Cs(e)})}function Cs(e){let t=e.userData.worldAnchor;if(!t?.position)return;let n=t.signature||{},r=bs(),i=new S().fromArray(t.position);n.count>=10&&r.count>=10&&Array.isArray(n.centroid)&&(i.x+=r.centroid[0]-n.centroid[0],i.z+=r.centroid[2]-n.centroid[2]);let a=Number.isFinite(t.floorY)?t.floorY:n.floorY;Number.isFinite(a)&&Number.isFinite(r.floorY)&&(i.y+=r.floorY-a),e.position.copy(i),hs(e)}function ws(e,t){Ts(),po=window.setTimeout(()=>{Es(e,t),D.selectedObject&&As(e,t,D.selectedObject)},500)}function Ts(){window.clearTimeout(po)}function Es(e,t){let{camera:n}=I(),r=new Me;r.setFromCamera(new Ce(e/innerWidth*2-1,-(t/innerHeight)*2+1),n);let i=r.intersectObjects(D.placedObjects,!0)[0]?.object;return D.selectedObject=i?Ds(i):null,D.selectedObject}function Ds(e){let t=e;for(;t&&!t.userData.isARObject&&t.parent;)t=t.parent;return t?.userData?.isARObject?t:null}function Os(e){let t=e?.origin,n=e?.direction;if(!t||!n)return null;let r=new S(n.x,n.y,n.z);if(r.lengthSq()<1e-8)return null;r.normalize();let i=new S(t.x,t.y,t.z),a=new Me(i,r).intersectObjects(D.placedObjects,!0),o=a[0]?.object?Ds(a[0].object):null;if(o)return D.selectedObject=o,ks(o),Ri(o,`select`),k(`gesture-pinch`,{source:`xr-transient-pointer`,object:o}),Ot(`status`,`Selected ${o.userData.modelName||`object`} via pinch`),{type:`select`,object:o};if(D.pendingModelToPlace){let e=Number.isFinite(D.floorY)?D.floorY:-1.5,t=Math.abs(r.y)>1e-4?(e-i.y)/r.y:-1,n=t>0&&t<40?new S(i.x+r.x*t,e,i.z+r.z*t):i.clone().add(r.clone().multiplyScalar(1.6)).setY(e),a=D.pendingModelToPlace;return D.pendingModelToPlace=``,delete document.body.dataset.jarvisPendingModel,Hs(!1),Ho(a,n,new Ve).catch(e=>C(e.message,`Model Placement Failed`)),{type:`place`,point:n}}return null}function ks(e){if(!e||e.userData._xrPulsing)return;e.userData._xrPulsing=!0;let t=e.scale.clone(),n=t.clone().multiplyScalar(1.06),r=performance.now(),i=a=>{let o=Math.min(1,(a-r)/170),s=o<.5?o*2:(1-o)*2;e.scale.lerpVectors(t,n,s),o<1?P(i):(e.scale.copy(t),e.userData._xrPulsing=!1)};P(i)}function As(e,t,n){fo?.remove(),fo=document.createElement(`section`),fo.className=`context-menu glass-panel`,fo.style.left=`${Math.min(e,innerWidth-210)}px`,fo.style.top=`${Math.min(t,innerHeight-250)}px`;let r=[[`Duplicate`,()=>Ns(n)],[`Delete`,()=>Ps(n)],[`Physics ON`,()=>Fs(n)],[`Open`,()=>js(n,`open`)],[`Close`,()=>js(n,`close`)],[`Toggle`,()=>js(n,`toggle`)],[`Shatter`,()=>js(n,`shatter`)],[`Forge`,()=>k(`open-model-forge`)],[`Save`,()=>_s()],[`Export .GLB`,()=>Is(n)]];for(let[e,t]of r){let n=document.createElement(`button`);n.textContent=e,n.onclick=()=>{t(),fo?.remove()},fo.appendChild(n)}document.body.appendChild(fo),window.setTimeout(()=>document.addEventListener(`pointerdown`,Ms,{once:!0}),0)}function js(e,t){Zr(e,t),hs(e),$r(e),Ri(e,t),Ot(`manipulateObject`,e.userData.id||``,t)}function Ms(e){fo?.contains(e.target)||fo?.remove()}function Ns(e){let t=Jo(e),n=new S(.25,.02,-.25).applyQuaternion(e.quaternion);t.position.add(n),t.userData.id=xr(`model`),t.userData.finalScale=e.userData.finalScale||t.scale.toArray(),delete t.userData.worldAnchor,(e.userData.modelForge||e.userData.modelForgeBlueprint)&&Gr(t,e.userData.modelForge||e.userData.modelForgeBlueprint),I().scene.add(t),D.placedObjects.push(t),ms(t),Li(t),Ri(t,`place`),_s()}function Ps(e){D.placedObjects=D.placedObjects.filter(t=>t!==e),Co.delete(e),D.selectedObject===e&&(D.selectedObject=null);let t=mo.get(e.userData.id);t&&(da(t),mo.delete(e.userData.id)),e.userData.shadow&&It(e.userData.shadow),Ri(e,`delete`),Ot(`removeObject`,e.userData.id||``),Xo(e),_s()}async function Fs(e){if(mo.has(e.userData.id)){da(mo.get(e.userData.id)),mo.delete(e.userData.id),w(`Physics off`,`info`);return}if(!ra()){w(`Starting physics engine…`,`info`);try{await ia()}catch(e){console.error(`[AR Models] physics engine unavailable:`,e),w(`Physics unavailable — engine failed to start`,`error`);return}}let t=la(e.position,`dynamic`);if(!t){w(`Physics unavailable — engine failed to start`,`error`);return}ua(e,t),mo.set(e.userData.id,t),w(`Physics on`,`success`)}window.addEventListener(`ar-physics-step`,()=>{for(let e of mo.keys()){let t=D.placedObjects.find(t=>t.userData.id===e);t&&hs(t)}});async function Is(e){let{GLTFExporter:n}=await t(async()=>{let{GLTFExporter:e}=await import(`./three-DMwvpBUV.js`).then(e=>e.r);return{GLTFExporter:e}},__vite__mapDeps([1,2]),import.meta.url),r=new n;await Ls(e),r.parse(e,t=>{let n=t instanceof ArrayBuffer?new Blob([t],{type:`model/gltf-binary`}):new Blob([JSON.stringify(t)],{type:`model/gltf+json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=`${e.userData.modelName||`jarvis-model`}.glb`,i.click(),URL.revokeObjectURL(r)},e=>C(e.message,`Export Failed`),{binary:!0})}async function Ls(e){let t=[];e.traverse(e=>{rs(e.material,e=>{is(e,e=>{t.push(e)})})}),await Promise.all(t.map(async e=>{let t=e?.image;if(t){if(t.complete===!1){await new Promise(e=>{let n=()=>e();t.addEventListener?.(`load`,n,{once:!0}),t.addEventListener?.(`error`,n,{once:!0}),window.setTimeout(n,1200)});return}if(typeof t.decode==`function`)try{await t.decode()}catch{}}}))}function Rs(){let e=document.createElement(`div`);e.style.cssText=`display: flex; flex-direction: column; gap: 8px;`;let t=document.createElement(`strong`);t.textContent=`JARVIS Stark 3D Composer`,t.style.cssText=`font-size: 14px; color: var(--accent); text-transform: uppercase;`;let n=document.createElement(`select`);Sr(n,[[`primitive`,`Custom Basic Geometry`],[`arc_reactor`,`Stark Arc Reactor Core`],[`gauntlet`,`Holographic Repulsor Gauntlet`],[`thruster`,`Flight Ion Propulsion Thruster`],[`quantum_reactor`,`Quantum Core Reactor Engine`],[`faceplate`,`Cybernetic Visor Faceplate`]]);let r=document.createElement(`select`);Sr(r,[[`metal`,`Machined Brushed Titanium`],[`gold`,`Polished Golden Core`],[`glass`,`Translucent Ethereal Glass`],[`glow`,`Glowing Neon Hologram`],[`matte`,`Stark Matte Composite`]]);let i=document.createElement(`div`);i.style.cssText=`display: flex; flex-direction: column; gap: 4px;`;let a=document.createElement(`span`);a.textContent=`Shape / Geometry:`,a.style.cssText=`font-size: 11px; color: var(--text-secondary);`;let o=document.createElement(`select`);Sr(o,[`cube`,`sphere`,`cylinder`,`cone`,`plane`,`torus`,`ring`,`capsule`]),i.append(a,o);let s=document.createElement(`div`);s.style.cssText=`display: flex; flex-direction: column; gap: 4px;`;let c=document.createElement(`span`);c.textContent=`Visual Detail Level:`,c.style.cssText=`font-size: 11px; color: var(--text-secondary);`;let l=document.createElement(`select`);Sr(l,[[`standard`,`Standard`],[`premium`,`Premium`],[`hero`,`Hero Detail`]]),s.append(c,l);let u=document.createElement(`input`);u.placeholder=`Model custom name (e.g. Mark 85 reactor)`;let d=document.createElement(`button`);d.className=`panel-action`,d.textContent=`Build Stark Composite`,d.style.cssText=`background: var(--accent); color: #fff; font-weight: 600; min-height: 42px; border-radius: 12px; margin-top: 8px;`,n.onchange=()=>{let e=n.value===`primitive`;i.style.display=e?`flex`:`none`,s.style.display=e?`flex`:`none`,u.value=e?``:n.options[n.selectedIndex].text},d.onclick=()=>{let e=n.value,t;t=e===`primitive`?Bs(o.value,r.value,l.value):zs(e,r.value);let i=u.value||`${r.options[r.selectedIndex].text} ${n.options[n.selectedIndex].text}`;t.userData.modelName=i,Gr(t,L({name:i,kit:e===`primitive`?`scene`:Js(e)})),Uo(t,i);let a=hr($a,[]);a.push({name:i,assembly:e,material:r.value,addedAt:Date.now()}),gr($a,a.slice(-24)),w(`Successfully composed and placed Stark asset: ${i}.`,`3D Composer`)};let f=document.createElement(`p`);f.className=`panel-note`,f.textContent=`Stark Assemblies generate premium multi-part geometries with concentric highlights, glowing points, and kinematic hinges.`,e.append(t,n,r,i,s,u,d,f),new bn({title:`Stark 3D Composer`,body:e,icon:`B`,width:375,height:490}).focus()}function zs(e,t){let n=new g;n.name=`stark-${e}`;let r=Vs(t===`gold`?`metal`:t);t===`gold`&&(r.color.setHex(16766720),r.roughness=.05,r.metalness=.95);let i=new d({color:54015,transparent:!0,opacity:.85}),a=new d({color:16777215,transparent:!0,opacity:.95}),o=new ae({color:3815994,roughness:.6,metalness:.8});if(e===`arc_reactor`){let e=new b(new s(.18,.18,.06,32),o);e.position.y=-.03,n.add(e);let t=new b(new s(.08,.08,.08,24),i);t.position.y=.01,t.userData.partName=`reactor-core`,t.userData.partType=`light`;let c=new se(54015,3,2.5);c.position.set(0,0,0),t.add(c),n.add(t);let l=new b(new je(.15,.018,12,48),r);l.rotation.x=Math.PI/2,n.add(l);let u=new ae({color:13794605,roughness:.18,metalness:.9});for(let e=0;e<10;e++){let t=e/10*Math.PI*2,r=new b(new ce(.024,.024,.018),u);r.position.set(Math.cos(t)*.15,0,Math.sin(t)*.15),r.rotation.y=-t,n.add(r)}let d=new b(new je(.1,.005,8,48),a);d.rotation.x=Math.PI/2,d.position.y=.02,n.add(d)}else if(e===`gauntlet`){let e=new b(new s(.1,.11,.28,16,1,!0,-Math.PI/2,Math.PI),r);e.rotation.x=Math.PI/2,e.userData.partName=`wrist-guard`,e.userData.partType=`base`,n.add(e);let t=new b(new s(.018,.018,.12,12),o);t.position.set(0,.07,-.06),t.rotation.x=Math.PI/2,t.userData.partName=`laser-emitter`,t.userData.partType=`detail`;let c=new b(new ke(.012),a);c.position.y=.06,t.add(c),n.add(t);let l=new b(new ke(.025,16,16),i);l.position.set(0,.06,.08),l.userData.partName=`palm-repulsor`,l.userData.partType=`light`;let u=new se(54015,2.5,2);l.add(u),n.add(l)}else if(e===`thruster`){let e=new b(new s(.06,.11,.16,24),o);e.userData.partName=`thruster-nozzle`,e.userData.partType=`base`,n.add(e);let t=new b(new ke(.045,16,16),r);t.position.y=-.06,t.userData.partName=`thruster-core`,t.userData.partType=`light`;let i=new se(16771584,3.5,3);t.add(i),n.add(t);let a=new b(new s(.04,.005,.32,16),new d({color:16747520,transparent:!0,opacity:.65}));a.position.y=-.22,a.userData.partName=`thrust-stream`,a.userData.partType=`detail`,n.add(a)}else if(e===`quantum_reactor`){let e=new b(new s(.12,.12,.32,24),new y({color:13627391,roughness:.02,transmission:.8,transparent:!0,opacity:.3}));e.userData.partName=`quantum-capsule`,e.userData.partType=`window`,n.add(e);let t=new b(new je(.09,.01,8,32),r);t.position.y=.05,t.rotation.x=Math.PI/2,t.userData.partName=`upper-gear`,t.userData.partType=`wheel`,n.add(t);let a=new b(new je(.09,.01,8,32),r);a.position.y=-.05,a.rotation.x=Math.PI/2,a.userData.partName=`lower-gear`,a.userData.partType=`wheel`,n.add(a);let o=new b(new m(.04,0),i);o.userData.partName=`energy-core`,o.userData.partType=`light`;let c=new se(65450,3,2);o.add(c),n.add(o)}else if(e===`faceplate`){let e=new b(new s(.14,.14,.18,16,1,!1,-Math.PI/3,Math.PI/3*2),r);e.userData.partName=`faceplate-armour`,e.userData.partType=`base`,n.add(e);let t=new b(new ce(.18,.04,.02),i);t.position.set(0,.02,.12),t.userData.partName=`visor-screen`,t.userData.partType=`screen`,n.add(t);let o=new b(new ce(.035,.005,.005),a);o.position.set(-.04,.02,.13),o.userData.partName=`left-eye`,o.userData.partType=`light`,n.add(o);let c=new b(new ce(.035,.005,.005),a);c.position.set(.04,.02,.13),c.userData.partName=`right-eye`,c.userData.partType=`light`,n.add(c)}return n}function Bs(e,t,n=`standard`){let r=Vs(t),i={cube:()=>new ce(.35,.35,.35),sphere:()=>new ke(.22,48,24),cylinder:()=>new s(.18,.18,.38,48),cone:()=>new c(.2,.42,48),plane:()=>new x(.5,.5),torus:()=>new je(.23,.04,16,80),ring:()=>new Te(.14,.24,64),capsule:()=>new re(.15,.35,8,24)}[e]?.()||new ce(.35,.35,.35),a=new g;a.name=`builder-${e}-${n}`;let o=new b(i,r);o.castShadow=!0,o.receiveShadow=!0,a.add(o);let l=t===`glass`?new y({color:13627391,roughness:.02,transmission:.72,transparent:!0,opacity:.34}):new d({color:51455,transparent:!0,opacity:.75}),u=new b(new je(.27,.02,12,64),l);if(u.rotation.x=Math.PI/2,a.add(u),n===`premium`||n===`hero`){let e=new b(new ke(.09,24,16),new ae({color:16777215,roughness:.25,metalness:.3}));e.position.set(0,.25,0),a.add(e)}if(n===`hero`){let e=new b(new s(.06,.1,.18,6),new y({color:10475775,roughness:.14,metalness:.6,emissive:397597}));e.position.set(0,.34,0),e.rotation.y=Math.PI/6,a.add(e);let t=new b(new je(.33,.01,8,80),new d({color:16777215,transparent:!0,opacity:.55}));t.rotation.x=Math.PI/2,t.position.y=.02,a.add(t)}return a}function Vs(e){return e===`metal`?new y({color:9422847,roughness:.18,metalness:.9}):e===`glass`?new y({color:13627391,roughness:.04,transmission:.55,transparent:!0,opacity:.45}):e===`glow`?new d({color:51455,transparent:!0,opacity:.8}):new ae({color:8109311,roughness:.55,metalness:.1})}function Hs(e){D.reticle&&(D.reticle.visible=e)}function Us(e){return e?.isVector3?e:new S(e?.x||0,e?.y??D.floorY,e?.z||-2)}function Ws(e){let t=e.toLowerCase();return t.endsWith(`.gltf`)?`model/gltf+json`:t.endsWith(`.bin`)?`application/octet-stream`:t.endsWith(`.png`)?`image/png`:t.endsWith(`.jpg`)||t.endsWith(`.jpeg`)?`image/jpeg`:t.endsWith(`.webp`)?`image/webp`:`application/octet-stream`}function Gs(e){return decodeURIComponent(String(e||``)).replace(/\\/g,`/`).replace(/^blob:https?:\/\/[^/]+\//,``).replace(/^https?:\/\/[^/]+\//,``).replace(/^\/+/,``).replace(/^(\.\/)+/,``)}function Ks(e){let t=Number(e||0);return t?t>1024*1024?`${Math.round(t/1024/1024)}MB`:`${Math.round(t/1024)}KB`:`size unknown`}function qs(e){let t=Number(e||0);return t?t>1e6?`${(t/1e6).toFixed(1)}M`:t>1e3?`${Math.round(t/1e3)}K`:String(t):`unknown`}function Js(e){let t=String(e||``).toLowerCase();return t.includes(`house`)||t.includes(`home`)?`house`:t.includes(`room`)||t.includes(`bedroom`)||t.includes(`kitchen`)?`room`:t.includes(`car`)||t.includes(`truck`)||t.includes(`vehicle`)?`vehicle`:t.includes(`phone`)||t.includes(`tablet`)||t.includes(`device`)?`device`:t.includes(`person`)||t.includes(`robot`)||t.includes(`character`)?`character`:`scene`}function Ys(e){let t=String(e||``).toLowerCase().trim();return t?/(^|\b)(open|unfold|expand)(\b|$)/.test(t)?`open`:/(^|\b)(close|fold|collapse)(\b|$)/.test(t)?`close`:/(^|\b)(toggle|switch)(\b|$)/.test(t)?`toggle`:/(^|\b)(rotate|spin|turn)(\b|$)/.test(t)?`rotate`:/(^|\b)(reconfigure|rebuild|transform|rearrange)(\b|$)/.test(t)?`reconfigure`:/(^|\b)(shatter|break|explode)(\b|$)/.test(t)?`shatter`:/(^|\b)(reveal|show)(\b|$)/.test(t)?`reveal`:/(^|\b)(hide)(\b|$)/.test(t)?`hide`:/(^|\b)(grab|move|drag)(\b|$)/.test(t)?`grab`:t:``}var Xs=0,Zs=4,Qs=8,$s=12,ec=16,tc=20,nc=5,rc=6,ic=9,ac=10,oc=13,sc=14,cc=17,lc=new Map([[nc,rc],[ic,ac],[oc,sc],[cc,18]]),uc=[[0,1],[1,2],[2,3],[3,4],[0,5],[5,6],[6,7],[7,8],[5,9],[9,10],[10,11],[11,12],[9,13],[13,14],[14,15],[15,16],[13,17],[17,18],[18,19],[19,20],[0,17]],dc=20,fc=null,pc=null,U=null,mc=!1,hc=null,gc=0,_c=0,vc=0,yc=!1,bc=0,xc=!1,Sc=null,Cc=0,wc=0,Tc=.55,Ec=[];function Dc(e,t){Oc(),t>0?(bc=setTimeout(e,t),xc=!0):(bc=P(e),xc=!1)}function Oc(){bc&&(xc?clearTimeout(bc):yt(bc),bc=0)}async function kc(){if(pc=document.getElementById(`hand-overlay`),U=pc?.getContext(`2d`),Vc(),Sc=N(window,`resize`,Vc),!globalThis.Hands)return F(`mediaPipeHands`,!1),w(`Hand gestures are still loading. You can place and move objects by touch in the meantime.`,`Hand tracking`),!1;try{return fc=new globalThis.Hands({locateFile:e=>`https://cdn.jsdelivr.net/npm/@mediapipe/hands/${e}`}),fc.setOptions({maxNumHands:2,modelComplexity:1,minDetectionConfidence:.7,minTrackingConfidence:.65,selfieMode:!1}),fc.onResults(Mc),mc=!0,F(`mediaPipeHands`,!0),Dc(Ac,0),w(`Hand tracking armed. Use palm, pinch, fist, point, and swipe gestures.`),!0}catch(e){return console.warn(`[gestures] hand tracking failed to start`,e),C(`Hand gestures aren’t available on this device. Everything else in AR still works — you can place and move objects by touch.`,`Hand tracking unavailable`),!1}}async function Ac(){if(!mc||!fc)return;let e=performance.now();try{let t=Yc();t?(e>=vc&&(vc=e+dc,await fc.send({image:t}),yc=!1),Dc(Ac,0)):(!yc&&D.trackingMode===`8thwall-slam`&&(yc=!0,w(`Waiting for XR camera pixels before enabling hand tracking.`,`Hand Tracking`)),Dc(Ac,200))}catch(e){yc||(yc=!0,w(`Hand tracking frame skipped: ${e.message}`,`Hand Tracking`)),Dc(Ac,200)}}function jc(){mc=!1,Oc(),Sc?.(),Sc=null;try{fc?.close?.()}catch{}fc=null,Bc(),hc=null,gc=0,_c=0,Cc=0,yc=!1,vc=0,wc=0,D.gestureFrameCanvas?.remove?.(),D.gestureFrameCanvas=null,D.gestureFrameReady=!1,D.handState.hands=[],D.handState.gestures=new Map}function Mc(e){Bc();let t=(e.multiHandLandmarks||[]).map((e,t)=>Nc(e,t));D.handState.hands=t,t.forEach((e,t)=>zc(e,t));let n=Pc(t);D.handState.gestures=n;for(let[e,t]of n)k(`gesture-${e}`,t)}function Nc(e,t){if(!Ec[t])return Ec[t]=e.map(e=>({x:e.x,y:e.y,z:e.z||0})),Ec[t];let n=Ec[t];for(let t=0;t<e.length;t++){let r=Tc;n[t].x=n[t].x*(1-r)+e[t].x*r,n[t].y=n[t].y*(1-r)+e[t].y*r,n[t].z=(n[t].z||0)*(1-r)+(e[t].z||0)*r}return n}function Pc(e){let t=new Map;if(!e.length)return hc=null,gc=0,_c=0,Cc=0,t;let n=e[0],r=Uc(n[Zs],n[Qs]);r<.05&&t.set(`pinch`,{confidence:1-r/.05,hand:n}),Ic(n)&&t.set(`fist`,{confidence:.88,hand:n}),Lc(n)&&t.set(`open-palm`,{confidence:.9,hand:n}),Rc(n)&&t.set(`point`,{confidence:.86,hand:n,point:n[Qs]});let i=Fc(n);if(i&&t.set(i,{confidence:.86,hand:n}),e.length>=2){let n=Wc(e[0],e[1]);if(_c>0){let r=n-_c;Math.abs(r)>.035&&t.set(`two-hand-scale`,{confidence:.9,delta:r,distance:n,hands:e})}_c=n}else _c=0;return t}function Fc(e){let t=performance.now();if(t<Cc)return``;let n=e[Xs];if(!hc)return hc={x:n.x,y:n.y},``;let r=n.x-hc.x;return hc={x:n.x,y:n.y},r<-.03?--gc:r>.03?gc+=1:gc*=.5,Math.abs(gc)<.25&&(gc=0),gc=Math.max(-5,Math.min(5,gc)),gc<=-5?(gc=0,Cc=t+180,hc=null,`swipe-left`):gc>=5?(gc=0,Cc=t+180,hc=null,`swipe-right`):``}function Ic(e){return[Qs,$s,ec,tc].every((t,n)=>{let r=[nc,ic,oc,cc][n];return Hc(e,t,r)>.58})}function Lc(e){return[Qs,$s,ec,tc].every((t,n)=>{let r=[nc,ic,oc,cc][n];return Hc(e,t,r)<.32})}function Rc(e){return Hc(e,Qs,nc)<.34&&Hc(e,$s,ic)>.52&&Hc(e,ec,oc)>.52&&Hc(e,tc,cc)>.52}function zc(e){if(!U||!pc)return;let t=Uc(e[Zs],e[Qs])<.05,n=pc.width,r=pc.height,i=Math.max(1,n/Math.max(1,innerWidth));U.lineCap=`round`,U.lineJoin=`round`,U.lineWidth=2.4*i,U.strokeStyle=t?`rgba(0,122,255,0.7)`:`rgba(255,255,255,0.5)`;for(let[t,i]of uc){let a=e[t],o=e[i];!a||!o||(U.beginPath(),U.moveTo(a.x*n,a.y*r),U.lineTo(o.x*n,o.y*r),U.stroke())}for(let a of e){let e=a.x*n,o=a.y*r,s=(t?9:6)*i,c=U.createRadialGradient(e,o,0,e,o,s);c.addColorStop(0,t?`rgba(0,122,255,0.95)`:`rgba(255,255,255,0.92)`),c.addColorStop(1,`rgba(255,255,255,0)`),U.fillStyle=c,U.beginPath(),U.arc(e,o,s,0,Math.PI*2),U.fill()}if(Lc(e)){let t=(e[nc].x+e[cc].x)/2*n,a=(e[nc].y+e[cc].y)/2*r;U.strokeStyle=`rgba(255,255,255,0.55)`,U.lineWidth=3*i,U.beginPath(),U.arc(t,a,(40+Math.sin(performance.now()/180)*6)*i,0,Math.PI*2),U.stroke()}}function Bc(){!U||!pc||(U.save(),U.setTransform(1,0,0,1,0,0),U.clearRect(0,0,pc.width,pc.height),U.restore())}function Vc(){if(!pc)return;let e=Math.min(devicePixelRatio||1,3);pc.width=Math.floor(innerWidth*e),pc.height=Math.floor(innerHeight*e),pc.style.width=`100vw`,pc.style.height=`100vh`,U?.setTransform(1,0,0,1,0,0)}function Hc(e,t,n){let r=e[t],i=e[n],a=e[lc.get(n)];if(!r||!i||!a)return 0;let o=Kc(a,i),s=Kc(a,r),c=Math.max(Jc(o),1e-4),l=Math.max(Jc(s),1e-4),u=Math.max(-1,Math.min(1,qc(o,s)/(c*l)));return Math.max(0,Math.min(1,(Math.PI-Math.acos(u))/(Math.PI*.55)))}function Uc(e,t){let n=e.x-t.x,r=e.y-t.y,i=(e.z||0)-(t.z||0);return Math.hypot(n,r,i)}function Wc(e,t){let n=Uc(e[Xs],t[Xs]),r=Gc(e),i=Gc(t);return n*.72+Uc(r,i)*.28}function Gc(e){return{x:(e[Xs].x+e[nc].x+e[cc].x)/3,y:(e[Xs].y+e[nc].y+e[cc].y)/3,z:((e[Xs].z||0)+(e[nc].z||0)+(e[cc].z||0))/3}}function Kc(e,t){return{x:t.x-e.x,y:t.y-e.y,z:(t.z||0)-(e.z||0)}}function qc(e,t){return e.x*t.x+e.y*t.y+e.z*t.z}function Jc(e){return Math.hypot(e.x,e.y,e.z)}function Yc(){if(D.cameraVideo?.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA)return D.cameraVideo;if(D.gestureFrameReady&&D.gestureFrameCanvas?.width&&D.gestureFrameCanvas?.height)return D.gestureFrameCanvas;let e=performance.now();return e-wc>5e3&&(wc=e),null}function Xc(){return{name:`mediapipe-camera-frame-source`,onUpdate:({processCpuResult:e})=>{Qc(Zc(e))}}}function Zc(e){return e?.cameraPixelArray||e?.cameraPixels||e?.camerapixelarray||e?.pixels||e?.reality?.cameraPixelArray||e?.reality?.cameraPixels||null}function Qc(e){if(!e)return;let t=e.pixels||e.data||e.buffer||e,n=e.width||e.cols||e.columnCount||e.pixelWidth||e.imageWidth,r=e.height||e.rows||e.rowCount||e.pixelHeight||e.imageHeight;if(!t||!n||!r)return;let i=tl(t);if(!i.length)return;let a=$c(n,r).getContext(`2d`,{willReadFrequently:!0}),o=a.createImageData(n,r),s=el(i.length,n,r),c=e.rowBytes||e.stride||n*s,l=0;for(let e=0;e<r;e+=1){let t=e*c;for(let e=0;e<n;e+=1){let n=t+e*s;if(s>=4)o.data[l]=i[n],o.data[l+1]=i[n+1],o.data[l+2]=i[n+2],o.data[l+3]=i[n+3]||255;else if(s===3)o.data[l]=i[n],o.data[l+1]=i[n+1],o.data[l+2]=i[n+2],o.data[l+3]=255;else{let e=i[n];o.data[l]=e,o.data[l+1]=e,o.data[l+2]=e,o.data[l+3]=255}l+=4}}a.putImageData(o,0,0),D.gestureFrameReady=!0}function $c(e,t){return D.gestureFrameCanvas||(D.gestureFrameCanvas=document.createElement(`canvas`),D.gestureFrameCanvas.id=`mediapipe-camera-frame`,D.gestureFrameCanvas.style.cssText=`display:none`,document.body.appendChild(D.gestureFrameCanvas)),(D.gestureFrameCanvas.width!==e||D.gestureFrameCanvas.height!==t)&&(D.gestureFrameCanvas.width=e,D.gestureFrameCanvas.height=t),D.gestureFrameCanvas}function el(e,t,n){let r=Math.max(1,t*n);return e>=r*4?4:e>=r*3?3:1}function tl(e){return e instanceof Uint8Array?e:ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):(e instanceof ArrayBuffer,new Uint8Array(e))}var nl=`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position.xy, 0.0, 1.0);
}`,rl=`jarvis_vr_state_v2`,il={default:{id:`default`,label:`Default`,eyeSep:.063,convergence:1.42,k1:-.22,k2:.08,chromaticAberration:.003,renderScale:.9,refreshRate:72,vignetteStrength:.12},quest:{id:`quest`,label:`Quest`,eyeSep:.064,convergence:1.38,k1:-.215,k2:.078,chromaticAberration:.0032,renderScale:.88,refreshRate:90,vignetteStrength:.1},visionos:{id:`visionos`,label:`VisionOS`,estimatedEyeSep:!0,eyeSep:.062,convergence:1.34,k1:-.205,k2:.074,chromaticAberration:.0024,renderScale:.92,refreshRate:90,vignetteStrength:.08},android:{id:`android`,label:`Android`,eyeSep:.063,convergence:1.44,k1:-.22,k2:.08,chromaticAberration:.003,renderScale:.82,refreshRate:72,vignetteStrength:.14},desktop:{id:`desktop`,label:`Desktop`,eyeSep:.065,convergence:1.5,k1:-.2,k2:.07,chromaticAberration:.0025,renderScale:.95,refreshRate:60,vignetteStrength:.18}},al=`
uniform sampler2D tDiffuse;
uniform float k1;
uniform float k2;
uniform float rAber;
varying vec2 vUv;
vec2 barrelDistort(vec2 uv, vec2 center) {
vec2 d = uv - center;
float r2 = dot(d, d);
float distortFactor = 1.0 + k1 * r2 + k2 * r2 * r2;
return center + d * distortFactor;
}
void main() {
bool isLeftEye = vUv.x < 0.5;
vec2 eyeCenter = isLeftEye ? vec2(0.25, 0.5) : vec2(0.75, 0.5);
vec2 distorted = barrelDistort(vUv, eyeCenter);
vec2 localUV = isLeftEye
? vec2(distorted.x * 2.0, distorted.y)
: vec2((distorted.x - 0.5) * 2.0, distorted.y);
if (localUV.x < 0.0 || localUV.x > 1.0 || localUV.y < 0.0 || localUV.y > 1.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
float dist = length(localUV - vec2(0.5, 0.5));
float aberration = rAber * dist * dist * 3.0;
vec2 redUV = barrelDistort(vUv + vec2(aberration, 0.0), eyeCenter);
vec2 greenUV = distorted;
vec2 blueUV = barrelDistort(vUv - vec2(aberration, 0.0), eyeCenter);
float r = texture2D(tDiffuse, redUV).r;
float g = texture2D(tDiffuse, greenUV).g;
float b = texture2D(tDiffuse, blueUV).b;
gl_FragColor = vec4(r, g, b, 1.0);
}`,ol=null,W=null,sl=null,cl=null,ll=null,ul=new x(2,2);function dl(e){sl||(sl=new Pe,cl=new fe,ll=new Be({uniforms:{tDiffuse:{value:null},k1:{value:e.k1??-.22},k2:{value:e.k2??.08},rAber:{value:e.chromaticAberration??.003}},vertexShader:nl,fragmentShader:al,depthWrite:!1,depthTest:!1}),sl.add(new b(ul,ll)))}var fl=null,pl=null,ml=null,hl=!1,gl=null,_l=null,vl=null,yl=null,bl=0,xl=new Ve,Sl=!1,Cl=null,wl=null,G=Rl(),Tl=0,El=G.ipd,Dl=G.convergence,Ol=new i,kl=new Ve,Al=new Ve().setFromAxisAngle(new S(1,0,0),-Math.PI/2),jl=new Ve,Ml=new S(0,0,1);function Nl(){O(`enter-vr`,()=>Pl())}async function Pl(){let{renderer:e,scene:t,camera:n}=I();if(!e||!t||!n)return C(`Renderer is not ready yet. Start AR first, then enter VR.`,`VR Mode`),!1;G=Rl(),El=G.ipd,Dl=G.convergence;let r=Qt(),i=Ll(G.lensProfileId||r.browser);D.isVRMode=!0,Sl=!1,Tl=performance.now(),D.runtime.permissionState=D.runtime.permissionState||`unknown`,F(`passthroughBlendProxy`,!!Ql()),F(`comfortAdaptation`,!0),F(`predictivePoseFiltering`,!0),F(`reprojectionProxy`,!0),F(`questBrowserQuirks`,r.questBrowserQuirks),F(`stereoEyeBuffers`,!0),F(`stereoFrustumCalibration`,!0),F(`refreshRateNegotiation`,!0),F(`timestampSync`,!0),F(`motionSicknessMitigation`,!0),F(`teleportLocomotion`,!0),F(`smoothLocomotionSafeguards`,!0),F(`roomBoundaryVisualization`,!0),F(`stereoUiAnchoring`,!0),F(`antiAliasEdgeProtection`,!0),F(`zFightGuard`,!0),F(`sustainedFramerateGuard`,!0),F(`orientationLockStability`,!0),F(`sensorPermissionPersistenceProxy`,!0),F(`motionComfortVignette`,!0),F(`renderScaleStability`,!0),F(`headsetCameraCalibrationProxy`,!0),F(`deviceCapabilityMatrix`,!0),F(`lowLightTrackingResilience`,r.limits.lowLightTrackingResilience!==!1),Wl(e,i),i.estimatedEyeSep&&w(`VisionOS IPD is estimated because the browser does not expose a reliable eye distance API. Use the IPD slider to fine-tune comfort.`,`VR Mode`),zt({renderer:e,scene:t,camera:n},{mode:`vr-shell`,stereo:!0,source:Ql(),passthroughBlend:`browser-camera`,framebufferScaleFactor:i.renderScale,refreshRate:i.refreshRate,convergence:i.convergence,renderScale:i.renderScale,lensProfile:i.id,motionComfort:G.seatedMode?`seated`:`standing`,vignetteStrength:i.vignetteStrength}),Vl(i),Ul(i),await Kl(n),await ql();try{await screen.orientation?.lock?.(`landscape`)}catch{w(`Landscape lock was not allowed by this browser. Rotate the phone manually for VR.`)}let a=Ql();return a&&!pl?(pl=Yl(a),t.add(pl)):a||w(`VR passthrough is waiting for camera pixels. Stay in AR mode until the camera frame source is ready.`,`VR Mode`),Xl(),!hl&&globalThis.XR8?.addCameraPipelineModule?(globalThis.XR8.addCameraPipelineModule({name:`vr-stereo-renderer`,onRender:()=>{D.isVRMode&&Gl()}}),D.pipelineOrder.push(`vr-stereo-renderer`),hl=!0):globalThis.XR8?.addCameraPipelineModule||$l(),w(`VR screen active. ${i.label} stereo profile, IPD, refresh, and gyro are enabled.`,`VR Mode`),!0}function Fl(){D.isVRMode=!1,Sl=!1,zl(),Zl();try{screen.orientation?.unlock?.()}catch{}w(`Returned to AR mode.`,`VR Mode`)}function Il(e,t,n){return Math.min(n,Math.max(t,Number(e)||t))}function Ll(e=``){let t=String(e||``).toLowerCase();return t.includes(`quest`)?il.quest:t.includes(`vision`)?il.visionos:t.includes(`android`)?il.android:t.includes(`desktop`)?il.desktop:il.default}function Rl(){let e={ipd:.063,convergence:1.42,renderScale:.9,refreshRate:72,seatedMode:!0,floorCalibration:0,lensProfileId:`default`,vignette:.12};try{let t=hr(rl,null);return!t||typeof t!=`object`?e:{...e,...t,ipd:Il(t.ipd,.045,.075),convergence:Il(t.convergence,.8,2.2),renderScale:Il(t.renderScale,.72,1.25),refreshRate:Il(t.refreshRate,60,120),floorCalibration:Il(t.floorCalibration,-1.5,1.5),vignette:Il(t.vignette,0,.4),seatedMode:t.seatedMode!==!1,lensProfileId:String(t.lensProfileId||`default`)}}catch{return e}}function zl(){try{gr(rl,{ipd:parseFloat(_r(`jarvis_vr_ipd`,String(G.ipd||.063))),convergence:parseFloat(_r(`jarvis_vr_convergence`,String(G.convergence||1.42))),renderScale:G.renderScale,refreshRate:G.refreshRate,seatedMode:G.seatedMode,floorCalibration:G.floorCalibration,lensProfileId:G.lensProfileId,vignette:G.vignette,savedAt:new Date().toISOString()})}catch{}}function Bl(){return document.getElementById(`ui-layer`)||document.body}function Vl(e){Cl?.remove(),Cl=document.createElement(`div`),Cl.style.cssText=[`position:absolute`,`inset:0`,`z-index:25`,`pointer-events:none`,`background:radial-gradient(circle at center, rgba(0,0,0,0) 0%, rgba(0,0,0,0.14) 58%, rgba(0,0,0,0.32) 100%)`,`opacity:${Il(e.vignetteStrength??.12,0,.5)}`,`transition:opacity 180ms linear`].join(`;`),Bl().appendChild(Cl)}function Hl(e,t){if(!Cl)return;let n=G.seatedMode?.06:.1,r=Math.min(.24,Math.max(0,(e-16.6)/120)),i=Il((t.vignetteStrength??.12)+n+r,.06,.45);Cl.style.opacity=String(i)}function Ul(e){wl?.remove(),wl=document.createElement(`div`),wl.style.cssText=[`position:absolute`,`right:16px`,`top:18px`,`z-index:30`,`display:flex`,`flex-direction:column`,`gap:8px`,`padding:10px`,`border-radius:12px`,`background:rgba(3,12,20,0.72)`,`border:1px solid rgba(0,212,255,0.22)`,`backdrop-filter:blur(14px)`,`color:white`,`font:600 11px/1.2 Inter,sans-serif`,`pointer-events:auto`,`min-width:220px`].join(`;`);let t=(e,t)=>{let n=document.createElement(`label`);n.style.cssText=`display:flex;justify-content:space-between;align-items:center;gap:8px`;let r=document.createElement(`span`);return r.textContent=e,n.append(r,t),n},n=document.createElement(`input`);n.type=`range`,n.min=`0.045`,n.max=`0.075`,n.step=`0.001`,n.value=String(El??e.eyeSep??.063),n.style.cssText=`width:112px`;let r=document.createElement(`input`);r.type=`range`,r.min=`0.8`,r.max=`2.2`,r.step=`0.01`,r.value=String(Dl??e.convergence??1.42),r.style.cssText=`width:112px`;let i=document.createElement(`input`);i.type=`range`,i.min=`0.72`,i.max=`1.25`,i.step=`0.01`,i.value=String(G.renderScale??e.renderScale??.9),i.style.cssText=`width:112px`;let a=document.createElement(`select`);for(let t of[60,72,90,120]){let n=document.createElement(`option`);n.value=String(t),n.textContent=`${t}Hz`,Number(t)===Number(G.refreshRate||e.refreshRate)&&(n.selected=!0),a.appendChild(n)}let o=document.createElement(`button`);o.className=`btn-secondary`,o.textContent=G.seatedMode?`SEATED`:`STANDING`,o.onclick=()=>{G.seatedMode=!G.seatedMode,o.textContent=G.seatedMode?`SEATED`:`STANDING`,D.compositor.motionComfort=G.seatedMode?`seated`:`standing`,zl()};let s=document.createElement(`button`);s.className=`btn-secondary`,s.textContent=`FLOOR -`,s.onclick=()=>{G.floorCalibration=Il(G.floorCalibration-.05,-1.5,1.5),D.compositor.floorCalibration=G.floorCalibration,zl(),w(`Floor calibration ${G.floorCalibration.toFixed(2)}m`,`VR Mode`)};let c=document.createElement(`button`);c.className=`btn-secondary`,c.textContent=`FLOOR +`,c.onclick=()=>{G.floorCalibration=Il(G.floorCalibration+.05,-1.5,1.5),D.compositor.floorCalibration=G.floorCalibration,zl(),w(`Floor calibration ${G.floorCalibration.toFixed(2)}m`,`VR Mode`)};let l=document.createElement(`span`);l.textContent=`${e.label} profile`,l.style.opacity=`0.82`,n.oninput=()=>{vr(`jarvis_vr_ipd`,n.value),G.ipd=parseFloat(n.value),El=G.ipd,D.compositor.eyeSep=El},r.oninput=()=>{vr(`jarvis_vr_convergence`,r.value),G.convergence=parseFloat(r.value),Dl=G.convergence,D.compositor.convergence=Dl},i.oninput=()=>{G.renderScale=parseFloat(i.value),D.compositor.renderScale=G.renderScale,zl()},a.onchange=()=>{G.refreshRate=parseFloat(a.value),D.compositor.refreshRate=G.refreshRate,D.compositor.frameBudgetMs=1e3/G.refreshRate,zl()},wl.append(l,t(`IPD`,n),t(`Convergence`,r),t(`Scale`,i),t(`Refresh`,a));let u=document.createElement(`div`);u.style.cssText=`display:flex;gap:6px;justify-content:space-between`,u.append(o,s,c),wl.appendChild(u),Bl().appendChild(wl)}function Wl(e,t=Ll()){let n=new Ce;e.getDrawingBufferSize(n);let r=Il(G.renderScale??t.renderScale??1,.72,1.25),i=Math.max(2,Math.floor(n.x*r)),a=Math.max(2,Math.floor(n.y*r)),o=Math.max(2,Math.floor(i/2))/Math.max(1,a);ol=ol||new be,ol.eyeSep=El||t.eyeSep||.063,ol.focus=Dl||t.convergence||1.4,(!W||W.width!==i||W.height!==a)&&(W?.dispose(),W=new Ge(i,a,{minFilter:f,magFilter:f})),dl(t),ll&&(ll.uniforms.k1.value=t.k1??-.22,ll.uniforms.k2.value=t.k2??.08,ll.uniforms.rAber.value=t.chromaticAberration??.003),D.compositor={...D.compositor,refreshRate:t.refreshRate,frameBudgetMs:1e3/t.refreshRate,renderScale:r,convergence:ol.focus,lensProfile:t.id,eyeAspect:o,vignetteStrength:t.vignetteStrength,motionComfort:G.seatedMode?`seated`:`standing`,floorCalibration:G.floorCalibration},!vl&&e?.domElement&&(vl=e=>{e.preventDefault?.(),w(`WebGL context was lost. VR will pause until the renderer restores.`,`VR Mode`),D.isVRMode=!1,bl&&yt(bl),bl=0,ol=null,W=null,sl=null,cl=null,ll=null},yl=()=>{w(`WebGL context restored. Returning to VR mode.`,`VR Mode`),D.started&&(D.isVRMode=!0,Wl(e,t),$l())},e.domElement.addEventListener(`webglcontextlost`,vl,{passive:!1}),e.domElement.addEventListener(`webglcontextrestored`,yl))}function Gl(){let{renderer:e,scene:t,camera:n}=I();if(!e||!t||!n||!W||!ol)return;let r=new Ce;e.getDrawingBufferSize(r);let i=Ll(G.lensProfileId),a=Il(G.renderScale??i.renderScale??1,.72,1.25),o=Math.max(2,Math.floor(r.x*a)),s=Math.max(2,Math.floor(r.y*a)),c=Math.max(2,Math.floor(o/2)),l=c/Math.max(1,s);(W.width!==o||W.height!==s)&&Wl(e,i);let u=n.aspect;n.aspect=l,n.updateProjectionMatrix(),ol.eyeSep=El||i.eyeSep||.063,ol.focus=Dl||i.convergence||1.4,ol.update(n),e.setRenderTarget(W),e.setScissorTest(!0),e.clear(!0,!0,!0),ml?.userData?.liveCanvas&&(ml.needsUpdate=!0),e.setViewport(0,0,c,s),e.setScissor(0,0,c,s),e.render(t,ol.cameraL),e.clearDepth(),e.setViewport(c,0,c,s),e.setScissor(c,0,c,s),e.render(t,ol.cameraR),e.setScissorTest(!1),e.setRenderTarget(null),e.setViewport(0,0,r.x,r.y),ll.uniforms.tDiffuse.value=W.texture,e.render(sl,cl),n.aspect=u,n.updateProjectionMatrix();let d=performance.now(),f=Tl?d-Tl:16.6;Tl=d,Bt(f),Hl(f,i)}async function Kl(e){Qt();try{if(typeof DeviceOrientationEvent<`u`&&typeof DeviceOrientationEvent.requestPermission==`function`){let e=await DeviceOrientationEvent.requestPermission();if(e!==`granted`)return vr(`jarvis_vr_motion_permission`,String(e||`denied`)),w(`Motion access denied or timed out. VR head tracking disabled.`),!1;vr(`jarvis_vr_motion_permission`,`granted`)}return gl&&window.removeEventListener(`deviceorientation`,gl),gl=t=>Jl(t,e),window.addEventListener(`deviceorientation`,gl),!0}catch(e){return C(e.message,`Motion Permission Failed`),!1}}async function ql(){try{if(document.fullscreenElement)return!0;if(!document.documentElement?.requestFullscreen)return!1;let e=document.documentElement.requestFullscreen({navigationUI:`hide`}).catch(()=>!1);return await Promise.race([e,new Promise(e=>setTimeout(()=>e(!1),Qt().isQuest?1e3:1500))]),_l||(_l=()=>{!document.fullscreenElement&&D.isVRMode&&w(`Fullscreen exited. VR view will remain in-browser.`,`VR Mode`)},document.addEventListener(`fullscreenchange`,_l),document.addEventListener(`webkitfullscreenchange`,_l)),F(`orientationLockStability`,!0),!0}catch{return w(`Fullscreen lock was not granted. VR continues in browser windowed mode.`,`VR Mode`),!1}}function Jl(e,t){if(!D.isVRMode||!t)return;let n=Xe.degToRad(e.alpha||0),r=Xe.degToRad(e.beta||0),i=Xe.degToRad(e.gamma||0),a=Number(screen.orientation?.angle||window.orientation||0);Ol.set(r,n,-i,`YXZ`),kl.setFromEuler(Ol),kl.multiply(Al),jl.setFromAxisAngle(Ml,-Xe.degToRad(a)),kl.multiply(jl),Sl?xl.slerp(kl,.18):(xl.copy(kl),Sl=!0),t.quaternion.copy(xl)}function Yl(e){let t=e.tagName===`VIDEO`,n=t?new le(e):new qe(e);n.minFilter=f,n.magFilter=f,n.userData.liveCanvas=!t,ml=n;let r=new ke(500,60,40);return r.scale(-1,1,1),new b(r,new d({map:n}))}function Xl(){fl?.remove(),fl=document.createElement(`button`),fl.textContent=`EXIT VR`,fl.className=`btn-primary`,fl.style.cssText=`position:absolute;top:20px;left:20px;z-index:30;background:var(--destructive);padding-top:calc(12px + env(safe-area-inset-top));pointer-events:auto`,fl.onclick=Fl(document.getElementById(`ui-layer`)||document.body).appendChild(fl);let e=document.createElement(`input`);e.type=`range`,e.min=`0.045`,e.max=`0.075`,e.step=`0.001`,e.value=String(El||.063),e.style.cssText=`width:168px;pointer-events:auto`;let t=document.createElement(`label`);t.dataset.vrControl=`ipd`,t.style.cssText=`position:absolute;right:18px;bottom:20px;z-index:30;display:flex;flex-direction:column;gap:6px;color:white;font:600 12px/1.2 Inter,sans-serif;text-shadow:0 1px 4px #000;pointer-events:auto`;let n=document.createElement(`span`);n.textContent=`${Math.round(parseFloat(e.value)*1e3)} mm IPD`,e.oninput=()=>{vr(`jarvis_vr_ipd`,e.value),El=parseFloat(e.value),n.textContent=`${Math.round(parseFloat(e.value)*1e3)} mm IPD`},t.append(n,e)(document.getElementById(`ui-layer`)||document.body).appendChild(t),fl.addEventListener(`click`,()=>t.remove(),{once:!0})}function Zl(){try{let e=D.xrSession;if(e?.end){let t=e.end();t?.catch&&t.catch(()=>{})}}catch{}fl?.remove(),document.querySelector(`[data-vr-control="ipd"]`)?.remove(),wl?.remove(),Cl?.remove(),wl=null,Cl=null,gl&&(window.removeEventListener(`deviceorientation`,gl),gl=null),_l&&(document.removeEventListener(`fullscreenchange`,_l),document.removeEventListener(`webkitfullscreenchange`,_l),_l=null),vl&&(I()?.renderer?.domElement?.removeEventListener?.(`webglcontextlost`,vl),vl=null),yl&&(I()?.renderer?.domElement?.removeEventListener?.(`webglcontextrestored`,yl),yl=null),bl&&(yt(bl),bl=0),W&&(W.dispose(),W=null),ml?.dispose&&ml.dispose(),ml=null,pl?.geometry?.dispose?.(),pl?.material?.dispose?.(),pl?.remove?.(),pl=null,ll?.dispose?.(),ll=null,sl=null,cl=null,ol=null}function Ql(){if(D.cameraVideo?.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA)return D.cameraVideo;if(D.gestureFrameReady&&D.gestureFrameCanvas?.width&&D.gestureFrameCanvas?.height)return D.gestureFrameCanvas;let e=document.getElementById(`camerafeed`);return e?.width&&e?.height?e:null}function $l(){if(bl)return;let e=()=>{if(!D.isVRMode){bl=0;return}Gl(),bl=P(e)};bl=P(e)}var eu=`external/models/zipdepth_base_npu_384.onnx`,tu=`external/ort/`,K=384,nu=[.485,.456,.406],ru=[.229,.224,.225],q={ort:null,session:null,loading:null,canvas:null,ctx:null,input:null,provider:null,lastMs:0,frames:0,failed:null};function iu(){return{ready:!!q.session,provider:q.provider,model:`ZipDepth-base (NPU variant), 6.1M params, MIT`,inputSize:K,lastInferenceMs:Math.round(q.lastMs),framesEstimated:q.frames,error:q.failed,runsLocally:!0,networkCallsPerFrame:0}}async function au(){if(q.session)return q.session;if(q.loading)return q.loading;q.loading=(async()=>{let e=await t(()=>import(`./ort.bundle.min--hz_0CH4.js`),__vite__mapDeps([4,2,5]),import.meta.url);e.env.wasm.wasmPaths=tu,e.env.wasm.numThreads=1,q.ort=e;let n=`gpu`in navigator?[`webgpu`,`wasm`]:[`wasm`],r=null,i=null;for(let t of n)try{r=await e.InferenceSession.create(eu,{executionProviders:[t]}),q.provider=t;break}catch(e){i=e}if(!r)throw q.failed=i?.message||String(i),Error(`Depth engine failed to load: ${q.failed}`);return q.canvas=document.createElement(`canvas`),q.canvas.width=K,q.canvas.height=K,q.ctx=q.canvas.getContext(`2d`,{willReadFrequently:!0}),q.input=new Float32Array(3*K*K),q.session=r,r})();try{return await q.loading}finally{q.loading=null}}async function ou(e){if(!q.session||!e)return null;let t=performance.now();q.ctx.drawImage(e,0,0,K,K);let{data:n}=q.ctx.getImageData(0,0,K,K),r=K*K,i=q.input;for(let e=0,t=0;e<r;e++,t+=4)i[e]=(n[t]/255-nu[0])/ru[0],i[r+e]=(n[t+1]/255-nu[1])/ru[1],i[2*r+e]=(n[t+2]/255-nu[2])/ru[2];let a=new q.ort.Tensor(`float32`,i,[1,3,K,K]),o=q.session.inputNames[0],s=(await q.session.run({[o]:a}))[q.session.outputNames[0]].data;return q.lastMs=performance.now()-t,q.frames+=1,{data:s,width:K,height:K,ms:q.lastMs}}function su(e){let{data:t,width:n,height:r}=e,i=1/0,a=-1/0;for(let e=0;e<t.length;e++){let n=t[e];n<i&&(i=n),n>a&&(a=n)}let o=Math.max(a-i,1e-6),s=new Uint8Array(n*r);for(let e=0;e<t.length;e++)s[e]=(t[e]-i)/o*255;return{bytes:s,width:n,height:r,min:i,max:a}}async function cu(){if(q.session?.release)try{await q.session.release()}catch{}q.session=null,q.provider=null,q.canvas=null,q.ctx=null,q.input=null}var lu=2e4,uu=0,du=[`flat`,`180`,`360`,`fisheye`],fu=[`mono`,`sbs-full`,`sbs-half`,`tb-full`,`tb-half`],pu={passthrough:{id:`passthrough`,label:`Passthrough`,room:null,hFov:32,distance:3.2,curvatureRadius:0,reverb:{seconds:.35,decay:3.2,wet:.06},note:`The real room stays visible; the picture is composited into it as a screen.`},mixed:{id:`mixed`,label:`Mixed reality`,room:`frame`,hFov:36,distance:3.4,curvatureRadius:0,reverb:{seconds:.45,decay:3,wet:.1},note:`Passthrough plus a virtual bezel and ambient light response.`},theater:{id:`theater`,label:`Theater`,room:`hall`,hFov:36,distance:8,curvatureRadius:25,scale:{width:16,depth:22,height:8.5},reverb:{seconds:1.4,decay:2.4,wet:.18},note:`A standard cinema hall — 36 degrees subtended from the seat, gently curved.`},pvr:{id:`pvr`,label:`PVR`,room:`hall`,hFov:34,distance:9,curvatureRadius:30,scale:{width:15,depth:24,height:8},reverb:{seconds:1.2,decay:2.6,wet:.15},note:`A mainstream multiplex auditorium — slightly further back, flatter screen.`},inox:{id:`inox`,label:`INOX`,room:`hall`,hFov:40,distance:8.5,curvatureRadius:22,scale:{width:18,depth:23,height:9.5},reverb:{seconds:1.6,decay:2.3,wet:.2},note:`A premium large-screen auditorium, sitting between Theater and IMAX in scale.`},imax:{id:`imax`,label:`IMAX`,room:`dome`,hFov:70,distance:7,curvatureRadius:null,curvatureRadiusFactor:1.5,scale:{width:24,depth:20,height:16},reverb:{seconds:2.2,decay:1.9,wet:.26},note:`Large-format geometry — 70 degrees subtended, curvature radius 1.5x screen width.`}},mu=`
varying vec2 vUv;
varying vec3 vDir;
void main() {
vUv = uv;
vDir = normalize(position);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}`,hu=`
uniform sampler2D uMap;
uniform vec2 uUvScale;
uniform vec2 uUvOffset;
uniform int uProjectionKind;
uniform float uFisheyeFov;
uniform vec2 uFisheyeCenter;
uniform vec2 uFisheyeRadius;
uniform float uOpacity;
// AI depth (free-tier, on-device). uDepthEyeSign is 0 for the eye that shows the
// original frame untouched and non-zero for the synthesised one, so the real
// captured eye is never resampled - only the invented one is.
uniform sampler2D uDepthMap;
uniform float uDepthStrength;
uniform float uDepthEyeSign;
varying vec2 vUv;
varying vec3 vDir;
void main() {
vec2 uv;
if (uProjectionKind == 1) {
vec3 d = normalize(vDir);
float theta = acos(clamp(-d.z, -1.0, 1.0));
// Deliberately NOT named "half": that is a reserved word in GLSL ES, and
// using it makes the whole shader fail to compile, which silently blanks
// every projection - not just fisheye - because this is one shared program.
// Found by running it live; no JS-side syntax check can see inside a shader.
float halfFov = max(uFisheyeFov * 0.5, 0.0001);
float rNorm = theta / halfFov;
if (rNorm > 1.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
float phi = atan(d.y, d.x);
uv = uFisheyeCenter + rNorm * uFisheyeRadius * vec2(cos(phi), sin(phi));
} else {
uv = vUv;
}
uv = uv * uUvScale + uUvOffset;
// Depth-based right-eye synthesis. Sampling the colour frame at a horizontally
// displaced coordinate is a real parallax warp, done in UV space against the
// already-decoded texture - no second decode, no canvas resize, so the
// zero-quality-loss path is untouched for the eye that came from the source.
//
// Honest limitation, per this document's no-invented-claims rule: a warp cannot
// fill what was never captured. Pixels revealed from behind a foreground object
// (disocclusions) are smeared neighbours here, not inpainted detail, which is
// why this ships labelled as an AI depth EFFECT and not as real stereo capture.
if (uDepthStrength > 0.0 && uDepthEyeSign != 0.0) {
float d = texture2D(uDepthMap, uv).r;
uv.x += uDepthEyeSign * uDepthStrength * d;
}
gl_FragColor = vec4(texture2D(uMap, uv).rgb, uOpacity);
#include <colorspace_fragment>
}`,J={active:!1,file:null,element:null,isVideo:!1,sourceWidth:0,sourceHeight:0,texture:null,projection:`flat`,projectionAuto:!0,packing:`mono`,packingAuto:!0,environment:`theater`,meshes:[],room:null,group:null,screen:{width:0,height:0,distance:0,elevation:0,curvatureRadius:0},quality:null,audio:null,ambient:null,loop:0,deviceLimits:null,findings:[],aiDepth:{enabled:!1,texture:null,strength:.012,timer:0,lastMs:0,provider:null,error:null}};function gu(){let{renderer:e}=I(),t=e?.getContext?.()||null,n=t?t.getParameter(t.MAX_TEXTURE_SIZE):0,r=typeof globalThis.VideoDecoder==`function`,i=typeof globalThis.XRMediaBinding==`function`,a=typeof HTMLVideoElement<`u`&&typeof HTMLVideoElement.prototype?.requestVideoFrameCallback==`function`,o={maxTextureSize:n,webCodecs:r,webxrMediaLayers:i,webxrGLBinding:typeof globalThis.XRWebGLBinding==`function`,requestVideoFrameCallback:a,webAudio:typeof globalThis.AudioContext==`function`||typeof globalThis.webkitAudioContext==`function`,xr:!!navigator.xr};return J.deviceLimits=o,F(`mediaViewerMaxTextureSize`,n),F(`mediaViewerWebCodecs`,r),F(`mediaViewerWebXRMediaLayers`,i),o}function _u(e,t,n=``){let r=String(n).toLowerCase();if(/(^|[^a-z])fisheye|dualfish|_fish/.test(r))return{value:`fisheye`,why:`filename says fisheye`};if(/vr180|_180|180deg|180x180/.test(r))return{value:`180`,why:`filename says 180`};if(/vr360|_360|360deg|equirect|spherical|insta360|theta/.test(r))return{value:`360`,why:`filename says 360`};if(!e||!t)return{value:`flat`,why:`no dimensions available yet`};let i=e/t;return Math.abs(i-2)<.02?{value:`360`,why:`${e}x${t} is 2:1 equirectangular`}:Math.abs(i-4)<.06?{value:`180`,why:`${e}x${t} is 4:1 — two 1:1 hemispheres`}:Math.abs(i-1)<.02?{value:`fisheye`,why:`${e}x${t} is square — likely a fisheye circle`}:{value:`flat`,why:`${e}x${t} (${i.toFixed(2)}:1) is an ordinary frame`}}function vu(e){return e===`180`?1:e===`360`?2:e===`fisheye`?1:16/9}function yu(e,t,n=``,r=`flat`){let i=String(n).toLowerCase(),a=vu(r),o=(e,t)=>Math.abs(e-t)/t<.12;if(/_?(sbs|side.?by.?side|lr|left.?right)/.test(i)){let n=e/2/t;return o(n,a)?{value:`sbs-full`,why:`side-by-side, each eye ${Math.round(e/2)}x${t} at its full aspect`}:o(n*2,a)?{value:`sbs-half`,why:`side-by-side, each eye squeezed to ${Math.round(e/2)}x${t}`}:{value:`sbs-full`,why:`filename says side-by-side; aspect matched neither full nor half, assuming full`}}if(/_?(tb|ou|top.?bottom|over.?under)/.test(i)){let n=e/(t/2);return o(n,a)?{value:`tb-full`,why:`top-bottom, each eye ${e}x${Math.round(t/2)} at its full aspect`}:o(n/2,a)?{value:`tb-half`,why:`top-bottom, each eye squeezed to ${e}x${Math.round(t/2)}`}:{value:`tb-full`,why:`filename says top-bottom; aspect matched neither full nor half, assuming full`}}if(/_?mono/.test(i))return{value:`mono`,why:`filename says mono`};if(!e||!t)return{value:`mono`,why:`no dimensions available yet`};let s=e/t;return r===`180`&&Math.abs(s-4)<.06?{value:`sbs-full`,why:`4:1 on a 180 source is two full-width eyes`}:r===`360`&&Math.abs(s-1)<.02?{value:`tb-full`,why:`1:1 on a 360 source is two stacked equirect eyes`}:{value:`mono`,why:`no stereo signal in the dimensions or the filename`}}function bu(e,t){let n=t===`right`;switch(e){case`sbs-full`:case`sbs-half`:return{scale:[.5,1],offset:[n?.5:0,0]};case`tb-full`:case`tb-half`:return{scale:[1,.5],offset:[0,n?0:.5]};default:return{scale:[1,1],offset:[0,0]}}}function xu(e,t,n){switch(n){case`sbs-full`:return{width:e/2,height:t,squeezed:!1};case`sbs-half`:return{width:e/2,height:t,squeezed:!0,displayAspect:e/2/t*2};case`tb-full`:return{width:e,height:t/2,squeezed:!1};case`tb-half`:return{width:e,height:t/2,squeezed:!0,displayAspect:e/(t/2)/2};default:return{width:e,height:t,squeezed:!1}}}function Su({width:e,height:t,curvatureRadius:n=0,segments:r=96}){if(!n||n<=0)return new x(e,t,1,1);let i=e/n,a=[],o=[],s=[];for(let e=0;e<=r;e+=1){let s=e/r,c=(s-.5)*i,l=n*Math.sin(c),u=n*(1-Math.cos(c));a.push(l,t/2,u,l,-t/2,u),o.push(s,1,s,0)}for(let e=0;e<r;e+=1){let t=e*2;s.push(t,t+1,t+2,t+1,t+3,t+2)}let c=new Je;return c.setAttribute(`position`,new Ee(a,3)),c.setAttribute(`uv`,new Ee(o,2)),c.setIndex(s),c.computeVertexNormals(),c.userData.arcDegrees=Xe.radToDeg(i),c}function Cu(e,t){switch(e){case`360`:{let e=new ke(480,96,56);return e.scale(-1,1,1),e}case`180`:case`fisheye`:{let e=new ke(480,96,56,Math.PI,Math.PI,0,Math.PI);return e.scale(-1,1,1),e}default:return Su(t)}}function wu(e,t,n,r,i){let a=bu(n,r);return new Be({uniforms:{uMap:{value:e},uUvScale:{value:new Ce(a.scale[0],a.scale[1])},uUvOffset:{value:new Ce(a.offset[0],a.offset[1])},uProjectionKind:{value:+(t===`fisheye`)},uFisheyeFov:{value:i?.fov??Math.PI},uFisheyeCenter:{value:new Ce(i?.cx??.5,i?.cy??.5)},uFisheyeRadius:{value:new Ce(i?.rx??.5,i?.ry??.5)},uOpacity:{value:1},uDepthMap:{value:J.aiDepth.texture},uDepthStrength:{value:J.aiDepth.enabled?J.aiDepth.strength:0},uDepthEyeSign:{value:+(r===`right`)}},vertexShader:mu,fragmentShader:hu,side:0,depthWrite:t===`flat`,transparent:!1})}function Tu(e){if(!e.room)return null;let t=new g;if(t.name=`media-room-${e.id}`,e.room===`frame`){let e=new b(new Te(.98,1.06,4,1,Math.PI/4),new d({color:58879,transparent:!0,opacity:.55}));return e.name=`media-frame`,t.add(e),t}let n=e.scale||{width:16,depth:22,height:8.5},r=new ae({color:658706,roughness:.94,metalness:.02}),i=new ae({color:1119516,roughness:.88,metalness:.04}),o=new b(new x(n.width,n.depth),i);o.rotation.x=-Math.PI/2,o.position.set(0,-1.35,-n.depth/2+4),t.add(o);let s=new b(new x(n.width,n.depth),r);s.rotation.x=Math.PI/2,s.position.set(0,n.height-1.35,-n.depth/2+4),t.add(s);let c=new b(new x(n.width,n.height),r);c.position.set(0,n.height/2-1.35,4),c.rotation.y=Math.PI,t.add(c);for(let e of[-1,1]){let i=new b(new x(n.depth,n.height),r);i.position.set(e*n.width/2,n.height/2-1.35,-n.depth/2+4),i.rotation.y=e>0?-Math.PI/2:Math.PI/2,t.add(i)}let u=e.room===`dome`?9:7,f=new l(new ce(.52,.5,.5),new ae({color:1707796,roughness:.96}),u*14),p=new a,m=0;for(let e=0;e<u;e+=1)for(let t=0;t<14;t+=1)p.makeTranslation((t-13/2)*.72,-1.05+e*.16,1.2+e*1.05),f.setMatrixAt(m,p),m+=1;f.instanceMatrix.needsUpdate=!0,f.name=`media-seats`,t.add(f);let h=new Fe(2240580,.55);h.name=`media-room-ambient`,t.add(h);let _=new se(58879,0,40);return _.name=`media-ambilight`,_.position.set(0,1.4,-e.distance*.6),t.add(_),t}function Eu(e,t,n={}){let r=pu[e]||pu.theater,i=n.distance??r.distance,a=n.hFov??r.hFov,o=n.width??2*i*Math.tan(Xe.degToRad(a)/2),s=o/(t||16/9),c=n.curvatureRadius;return c??(c=r.curvatureRadiusFactor?o*r.curvatureRadiusFactor:r.curvatureRadius),{width:o,height:s,distance:i,hFov:a,curvatureRadius:c,elevation:n.elevation??(e===`imax`?1.1:.6),arcDegrees:c>0?Xe.radToDeg(o/c):0}}async function Du(e,t={}){if(!e)throw Error(`No file given`);Ku({keepScene:!0});let n=(e.type||``).startsWith(`video/`)||/\.(mp4|webm|mov|mkv|m4v)$/i.test(e.name||``),r=URL.createObjectURL(e),i=document.createElement(n?`video`:`img`);n&&(i.playsInline=!0,i.muted=t.muted??!1,i.loop=t.loop??!0,i.crossOrigin=`anonymous`,i.preload=`auto`,i.style.cssText=`position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;left:-9999px`,document.body.appendChild(i)),await new Promise((t,a)=>{let o=!1,s=e=>(...t)=>{o||(o=!0,clearTimeout(u),e(...t))},c=s(t),l=s(()=>a(Error(`Could not decode ${e.name}. The browser reported ${i.error?`media error ${i.error.code}`:`no readable video or image stream`}.`))),u=setTimeout(s(()=>a(Error(`${e.name} did not report its dimensions within ${lu/1e3}s. The file may be very large, or this device may not have a decoder for it.`))),lu);i.addEventListener(n?`loadedmetadata`:`load`,c,{once:!0}),i.addEventListener(`error`,l,{once:!0}),i.src=r});let a=n?i.videoWidth:i.naturalWidth,o=n?i.videoHeight:i.naturalHeight;J.file=e,J.element=i,J.isVideo=n,J.sourceWidth=a,J.sourceHeight=o,J.objectUrl=r,J.findings=[];let s=J.deviceLimits||gu();if(s.maxTextureSize&&Math.max(a,o)>s.maxTextureSize){let e=`Device texture limit reached: this GPU's MAX_TEXTURE_SIZE is ${s.maxTextureSize}px and the source is ${a}x${o}. The frame cannot be uploaded at native resolution on this device.`;J.findings.push(e),C(e,`Device limit`)}let c=t.projection?{value:t.projection,why:`chosen by you`}:_u(a,o,e.name);J.projection=c.value,J.projectionAuto=!t.projection,J.projectionWhy=c.why;let l=t.packing?{value:t.packing,why:`chosen by you`}:yu(a,o,e.name,J.projection);if(J.packing=l.value,J.packingAuto=!t.packing,J.packingWhy=l.why,J.environment=t.environment||J.environment||`theater`,Au(),n){Ru();try{await i.play()}catch{w(`Tap play to start — this browser needs a gesture before it will play audio.`,`Media`)}Wu()}return J.active=!0,k(`media-opened`,Y()),Y()}function Ou(){if(J.texture&&J.texture.image===J.element)return J.texture;J.texture?.dispose&&J.texture.dispose();let e=J.isVideo?new le(J.element):new Ie(J.element);return J.isVideo||(e.needsUpdate=!0),e.colorSpace=de,e.generateMipmaps=!1,e.minFilter=f,e.magFilter=f,e.wrapS=Ke,e.wrapT=Ke,e.userData.mediaTextureId=`tex-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,J.texture=e,e}function ku(){if(D.isVRMode)return!0;try{let{renderer:e}=I();if(e?.xr?.isPresenting)return!0}catch{}return!1}function Au(){let{scene:e}=I();if(!e)throw Error(`No scene — start AR first`);ju({keepTexture:!0});let t=Ou(),n=xu(J.sourceWidth,J.sourceHeight,J.packing),r=n.displayAspect||n.width/n.height,i=Eu(J.environment,r,J.screenOverride||{});J.screen=i;let a={fov:Math.PI,cx:.5,cy:.5,rx:.5,ry:.5*(n.width/n.height)};a.ry>.5&&(a.rx=.5*(n.height/n.width),a.ry=.5);let o=new g;o.name=`media-viewer`,J.group=o;let s=J.packing!==`mono`&&ku();J.stereoRendered=s;let c=s?[`left`,`right`]:[J.packing===`mono`?`mono`:`left`];J.meshes=c.map((e,n)=>{let r=new b(Cu(J.projection,i),wu(t,J.projection,J.packing,e,a));return r.name=`media-${J.projection}-${e}${s?``:c.length===1&&e===`left`?`-mono-view`:``}`,r.frustumCulled=!1,J.projection!==`flat`&&(r.renderOrder=-1),s&&r.layers.set(n===0?1:2),J.projection===`flat`&&r.position.set(0,i.elevation,-i.distance),o.add(r),r});let l=pu[J.environment],u=J.projection===`flat`,d=u?Tu(l):null;J.roomSuppressed=!u&&!!l.room,d&&(l.room===`frame`&&(d.position.set(0,i.elevation,-i.distance-.02),d.scale.set(i.width/1.4,i.height/1.4,1)),o.add(d),J.room=d),e.add(o),F(`mediaViewerActive`,!0)}function ju({keepTexture:e=!1}={}){let{scene:t}=I();J.group&&(J.group.traverse(e=>{e.geometry?.dispose?.(),Array.isArray(e.material)?e.material.forEach(e=>e.dispose?.()):e.material?.dispose?.()}),t?.remove?.(J.group)),J.group=null,J.room=null,J.meshes=[],e||(J.texture?.dispose&&J.texture.dispose(),J.texture=null)}function Mu(){let e=I()?.renderer?.xr?.getSession?.()||D.xrSession||null,t=typeof globalThis.XRMediaBinding==`function`,n=typeof globalThis.XRWebGLBinding==`function`,r=t&&typeof globalThis.XRMediaBinding.prototype?.createEquirectLayer==`function`,i=t&&typeof globalThis.XRMediaBinding.prototype?.createQuadLayer==`function`,a=t&&typeof globalThis.XRMediaBinding.prototype?.createCylinderLayer==`function`,o=!!e?.enabledFeatures?.includes?.(`layers`),s=!1,c;return e?t?o?!r&&!i?c=`XRMediaBinding exists but exposes neither createEquirectLayer nor createQuadLayer.`:s=!0:c=`The running XRSession did not enable the "layers" feature, so no layer can be created on it even though the constructor exists.`:c=`XRMediaBinding is not implemented by this browser. XRWebGLBinding alone would still require rendering into the layer ourselves, which reintroduces the resampling pass Layers exists to avoid, so it is not a substitute here.`:c=`No immersive XRSession is running. Layers only exist inside one; the shader projection path is what runs in an inline/fallback session.`,{usable:s,reason:c,hasMediaBinding:t,hasGLBinding:n,ctorEquirect:r,ctorQuad:i,ctorCylinder:a,sessionPresent:!!e,sessionEnabledFeatures:e?.enabledFeatures?[...e.enabledFeatures]:null}}async function Nu(){let e=Mu();if(J.layers=e,!e.usable||!J.isVideo||!J.element)return J.layers={...e,applied:!1},J.layers;try{let t=I()?.renderer,n=t?.xr?.getSession?.()||D.xrSession,r=t?.xr?.getReferenceSpace?.()||await n.requestReferenceSpace(`local`),i=new globalThis.XRMediaBinding(n),a=J.packing===`mono`?`mono`:J.packing.startsWith(`sbs`)?`stereo-left-right`:`stereo-top-bottom`,o,s;J.projection===`360`||J.projection===`180`?(o=i.createEquirectLayer(J.element,{space:r,layout:a,centralHorizontalAngle:J.projection===`180`?Math.PI:2*Math.PI}),s=`equirect`):e.ctorCylinder&&J.screen?.curvatureRadius>0?(o=i.createCylinderLayer(J.element,{space:r,layout:a,radius:J.screen.curvatureRadius,centralAngle:J.screen.width/J.screen.curvatureRadius,aspectRatio:J.screen.width/J.screen.height}),s=`cylinder`):(o=i.createQuadLayer(J.element,{space:r,layout:a,width:(J.screen?.width||2)/2,height:(J.screen?.height||1.2)/2}),s=`quad`),n.updateRenderState({layers:[o,...n.renderState.layers||[]]}),J.meshes.forEach(e=>{e.visible=!1}),J.layers={...e,applied:!0,kind:s,layout:a}}catch(t){J.layers={...e,applied:!1,reason:`Layer creation failed: ${t?.message||t}`}}return J.layers}function Pu(e){if(!du.includes(e))throw Error(`Unknown projection ${e}`);return J.projection=e,J.projectionAuto=!1,J.element&&Au(),k(`media-changed`,Y()),Y()}function Fu(e){if(!fu.includes(e))throw Error(`Unknown packing ${e}`);return J.packing=e,J.packingAuto=!1,J.element&&Au(),k(`media-changed`,Y()),Y()}function Iu(e){if(!pu[e])throw Error(`Unknown environment ${e}`);let t=J.texture,n=t?.userData?.mediaTextureId||null;J.environment=e,J.screenOverride=null,J.element&&Au();let r=J.texture;return k(`media-changed`,Y()),{...Y(),textureRebuilt:t!==r,textureIdBefore:n,textureIdAfter:r?.userData?.mediaTextureId||null}}function Lu(e={}){if(J.screenOverride={...J.screenOverride||{},...e},!J.element)return Y();let t=xu(J.sourceWidth,J.sourceHeight,J.packing),n=t.displayAspect||t.width/t.height,r=Eu(J.environment,n,J.screenOverride);return J.screen=r,J.projection===`flat`&&(J.meshes.forEach(e=>{e.geometry.dispose(),e.geometry=Su(r),e.position.set(0,r.elevation,-r.distance)}),J.room&&pu[J.environment].room===`frame`&&(J.room.position.set(0,r.elevation,-r.distance-.02),J.room.scale.set(r.width/1.4,r.height/1.4,1))),k(`media-changed`,Y()),Y()}function Ru(){let e=J.element;J.quality={startedAt:performance.now(),framesDelivered:0,firstMediaTime:null,lastMediaTime:null,mediaSecondsSeen:0,frameIntervals:[],elementDrops:0,elementTotal:0,rendererFrames:0,samples:0};let t=J.quality,n=()=>{if(!J.element){J.loop=0;return}if(typeof e.getVideoPlaybackQuality==`function`){let n=e.getVideoPlaybackQuality();t.elementDrops=n.droppedVideoFrames||0,t.elementTotal=n.totalVideoFrames||0}t.rendererFrames+=1,t.samples+=1,t.elapsedMs=performance.now()-t.startedAt,J.loop=P(n)};if(J.loop=P(n),typeof e.requestVideoFrameCallback==`function`){let n=null,r=(i,a)=>{if(!J.element)return;t.framesDelivered+=1;let o=a.mediaTime;if(t.firstMediaTime??(t.firstMediaTime=o),n!=null){let e=o-n;e>0&&e<1?(t.mediaSecondsSeen+=e,t.frameIntervals.length<400&&t.frameIntervals.push(e)):e<0&&(t.mediaSecondsSeen+=0)}n=o,t.lastMediaTime=o,e.requestVideoFrameCallback(r)};e.requestVideoFrameCallback(r)}}function zu(){if(!J.quality)return null;let e=J.quality,t=(e.elapsedMs||0)/1e3,n=e.frameIntervals.slice().sort((e,t)=>e-t),r=n.length?n[Math.floor(n.length/2)]:0,i=r>0?1/r:0;return i>0&&e.mediaSecondsSeen*i,{elapsedSeconds:+t.toFixed(2),framesDelivered:e.framesDelivered,mediaSecondsPlayed:+e.mediaSecondsSeen.toFixed(2),deliveredFps:+i.toFixed(2),rendererFps:t>0?+(e.rendererFrames/t).toFixed(2):null,realtimeRatio:t>0?+(e.mediaSecondsSeen/t).toFixed(4):null,stallSeconds:t>0?+Math.max(0,t-e.mediaSecondsSeen).toFixed(2):0,elementCompositorDrops:e.elementDrops,elementCompositorTotal:e.elementTotal,elementCompositorNote:`Counts frames the offscreen <video> element itself never painted. That element is a decode source, not a displayed video, so this number is expected to be high and is not a measure of what reached the screen.`,sourceWidth:J.sourceWidth,sourceHeight:J.sourceHeight,textureWidth:J.texture?.image?.videoWidth||J.texture?.image?.naturalWidth||0,textureHeight:J.texture?.image?.videoHeight||J.texture?.image?.naturalHeight||0,mipmapsEnabled:J.texture?J.texture.generateMipmaps:null,textureId:J.texture?.userData?.mediaTextureId||null,adaptiveQualityApplied:!1}}function Bu(e){if(!e)return J.ambient?.timer&&clearInterval(J.ambient.timer),J.ambient=null,!1;if(!J.isVideo||!J.group)return!1;let t=document.createElement(`canvas`);t.width=8,t.height=8;let n=t.getContext(`2d`,{willReadFrequently:!0}),r=J.group.getObjectByName(`media-ambilight`);return J.ambient={canvas:t,ctx:n,timer:setInterval(()=>{if(!(!J.element||!r))try{n.drawImage(J.element,0,0,8,8);let e=n.getImageData(0,0,8,8).data,t=0,i=0,a=0;for(let n=0;n<e.length;n+=4)t+=e[n],i+=e[n+1],a+=e[n+2];let o=e.length/4;r.color.setRGB(t/o/255,i/o/255,a/o/255),r.intensity=.9}catch{}},250)},!0}function Vu(e,t,n){let r=e.sampleRate,i=Math.max(1,Math.floor(r*t)),a=e.createBuffer(2,i,r);for(let e=0;e<2;e+=1){let t=a.getChannelData(e);for(let e=0;e<i;e+=1)t[e]=(Math.random()*2-1)*(1-e/i)**n}return a}async function Hu(){try{if(!navigator.mediaDevices?.enumerateDevices)return{detected:!1,reason:`This browser exposes no device enumeration API.`};let e=(await navigator.mediaDevices.enumerateDevices()).filter(e=>e.kind===`audiooutput`),t=e.filter(e=>e.label);if(!t.length)return{detected:!1,reason:`Output device labels are withheld until microphone permission is granted, so headphone presence cannot be determined on this platform.`,outputs:e.length};let n=t.find(e=>/headphone|headset|earphone|airpod|buds|bluetooth/i.test(e.label));return{detected:!!n,label:n?.label||null,outputs:t.length}}catch(e){return{detected:!1,reason:e?.message||String(e)}}}async function Uu(e,t){try{let n=e.createChannelSplitter(8);t.channelCountMode=`max`,t.channelInterpretation=`discrete`,t.connect(n);let r=[];for(let t=0;t<8;t+=1){let i=e.createAnalyser();i.fftSize=2048;try{n.connect(i,t)}catch{break}r.push(i)}let i=new Float32Array(2048),a=Array(r.length).fill(0),o=performance.now()+400;for(;performance.now()<o;){for(let e=0;e<r.length;e+=1){r[e].getFloatTimeDomainData(i);for(let t=0;t<i.length;t+=16){let n=Math.abs(i[t]);n>a[e]&&(a[e]=n)}}await new Promise(e=>setTimeout(e,40))}try{t.disconnect(n)}catch{}let s=0;return a.forEach((e,t)=>{e>1e-4&&(s=t+1)}),{channels:Math.max(s,1),peaks:a.map(e=>+e.toFixed(5)),method:`signal-probe`}}catch(e){return{channels:2,method:`fallback`,reason:e?.message||String(e)}}}async function Wu(e=!1){if(!J.isVideo||!J.element)return null;let n=globalThis.AudioContext||globalThis.webkitAudioContext;if(!n)return{enabled:!1,reason:`No Web Audio API on this platform.`};let r=await Hu();if(!(e||r.detected))return J.audio={enabled:!1,headphones:r,reason:`Defaulting to normal stereo output.`},J.audio;let i=J.audio?.ctx||new n;if(i.state===`suspended`)try{await i.resume()}catch{}let a=pu[J.environment],o=J.audio?.source||i.createMediaElementSource(J.element),s=J.audio?.channelProbe?.file===J.file?J.audio.channelProbe:{...await Uu(i,o),file:J.file},c=s.channels;try{o.disconnect()}catch{}if(J.audio?.foa?.output)try{J.audio.foa.output.disconnect()}catch{}let l=i.createConvolver();l.buffer=Vu(i,a.reverb.seconds,a.reverb.decay);let u=i.createGain();u.gain.value=a.reverb.wet;let d=i.createGain();d.gain.value=1-a.reverb.wet*.5,d.connect(i.destination),u.connect(i.destination);let f=null,p,m,h=!1;if(c>=4)f=(await t(async()=>{let{default:e}=await import(`./omnitone.esm-BSknr-cd.js`);return{default:e}},[],import.meta.url)).default.createFOARenderer(i,{channelMap:[0,1,2,3]}),await f.initialize(),o.connect(f.input),f.output.connect(d),f.output.connect(l),h=!0,p=`Ambisonic B-format decode + HRTF binaural rendering (Omnitone FOARenderer)`,m=`True spatial audio — the captured sound field decoded as recorded, nothing synthesised.`;else{let e=new PannerNode(i,{panningModel:`HRTF`,distanceModel:`inverse`,positionX:0,positionY:J.screen.elevation||0,positionZ:-(J.screen.distance||3)});o.connect(e),e.connect(d),e.connect(l),l.connect(u),J.audio={...J.audio||{},panner:e},p=`HRTF binaural rendering (Web Audio PannerNode + ConvolverNode)`,m=`Virtual/enhanced surround — reshapes existing channels, not true object-based 3D audio.`}return l.connect(u),J.audio={...J.audio||{},enabled:!0,mechanism:p,honestLabel:m,sourceIsAmbisonic:h,channels:c,isDolbyAtmos:!1,ctx:i,source:o,convolver:l,foa:f,channelProbe:s,headphones:r,room:a.label,engine:h?`omnitone`:`web-audio-panner`},J.audio}function Gu(e){let t=J.audio;if(!t?.enabled||!t.ctx||!e)return!1;if(t.foa)return e.updateMatrixWorld?.(),t.foa.setRotationMatrix4(e.matrixWorld.elements),!0;let n=t.ctx.listener,r=new S(0,0,-1).applyQuaternion(e.quaternion),i=new S(0,1,0).applyQuaternion(e.quaternion);return n.forwardX?(n.forwardX.value=r.x,n.forwardY.value=r.y,n.forwardZ.value=r.z,n.upX.value=i.x,n.upY.value=i.y,n.upZ.value=i.z):n.setOrientation&&n.setOrientation(r.x,r.y,r.z,i.x,i.y,i.z),!0}function Y(){let e=xu(J.sourceWidth,J.sourceHeight,J.packing);return{active:J.active,fileName:J.file?.name||null,fileSize:J.file?.size||0,isVideo:J.isVideo,sourceWidth:J.sourceWidth,sourceHeight:J.sourceHeight,projection:J.projection,projectionAuto:J.projectionAuto,projectionWhy:J.projectionWhy,packing:J.packing,packingAuto:J.packingAuto,packingWhy:J.packingWhy,eyeWidth:e.width,eyeHeight:e.height,eyeSqueezed:!!e.squeezed,eyeDisplayAspect:e.displayAspect||e.width/e.height,environment:J.environment,environmentLabel:pu[J.environment]?.label,roomSuppressed:!!J.roomSuppressed,roomApplies:J.projection===`flat`,screen:J.screen,meshCount:J.meshes.length,meshNames:J.meshes.map(e=>e.name),stereoSource:J.packing!==`mono`,stereoRendered:!!J.stereoRendered,stereoPresenting:ku(),stereo:J.packing!==`mono`,ambientResponse:!!J.ambient,audio:J.audio?{enabled:J.audio.enabled,engine:J.audio.engine||null,mechanism:J.audio.mechanism||null,honestLabel:J.audio.honestLabel||null,sourceIsAmbisonic:!!J.audio.sourceIsAmbisonic,channels:J.audio.channels||null,channelPeaks:J.audio.channelProbe?.peaks||null,channelMethod:J.audio.channelProbe?.method||null,isDolbyAtmos:!1,headphones:J.audio.headphones,room:J.audio.room||null}:null,deviceLimits:J.deviceLimits,layers:J.layers||null,findings:J.findings.slice(),quality:zu()}}function Ku({keepScene:e=!1}={}){if(J.loop&&(yt(J.loop),J.loop=0),J.ambient?.timer&&clearInterval(J.ambient.timer),J.ambient=null,J.audio?.ctx&&J.audio.ctx.state!==`closed`)try{J.audio.ctx.close()}catch{}if(J.audio=null,ju({keepTexture:!1}),J.element&&J.isVideo){try{J.element.pause()}catch{}J.element.removeAttribute(`src`),J.element.load?.(),J.element.remove?.()}return J.objectUrl&&URL.revokeObjectURL(J.objectUrl),J.objectUrl=null,J.element=null,J.file=null,J.active=!1,J.quality=null,F(`mediaViewerActive`,!1),!0}function qu(){let e=ku(),t=()=>{let n=ku();if(n!==e&&(e=n,J.active&&J.packing!==`mono`&&J.element&&Au()),J.audio?.enabled){let e=I()?.camera;e&&Gu(e)}uu=P(t)};uu=P(t)}async function Ju(e){if(!e){J.aiDepth.timer&&clearInterval(J.aiDepth.timer),J.aiDepth.timer=0,J.aiDepth.enabled=!1;for(let e of J.meshes)e.material?.uniforms?.uDepthStrength&&(e.material.uniforms.uDepthStrength.value=0);return await cu(),{enabled:!1,provider:null,reason:`AI depth off. Showing the source exactly as decoded.`}}if(!J.active||!J.element)return{enabled:!1,provider:null,reason:`Open a photo or video first.`};try{await au()}catch(e){return J.aiDepth.error=e?.message||String(e),{enabled:!1,provider:null,reason:`The depth engine did not load: ${J.aiDepth.error}`}}let t=await ou(J.element);if(!t)return{enabled:!1,provider:null,reason:`The depth engine produced no output.`};let n=su(t),r=new ee(n.bytes,n.width,n.height,Re);return r.minFilter=f,r.magFilter=f,r.needsUpdate=!0,J.aiDepth.texture=r,J.aiDepth.enabled=!0,J.aiDepth.provider=iu().provider,J.aiDepth.lastMs=t.ms,Au(),J.isVideo&&(J.aiDepth.timer=setInterval(async()=>{if(!J.aiDepth.enabled||!J.element)return;let e=await ou(J.element).catch(()=>null);if(!e)return;let t=su(e);J.aiDepth.texture.image.data.set(t.bytes),J.aiDepth.texture.needsUpdate=!0,J.aiDepth.lastMs=e.ms},200),bt(()=>{J.aiDepth.timer&&clearInterval(J.aiDepth.timer)})),{enabled:!0,provider:J.aiDepth.provider,reason:`AI depth on — a synthesised second eye from an on-device depth estimate. This is a depth effect, not real stereo capture: pixels behind foreground objects were never filmed and are filled from their neighbours.`}}async function Yu(e,t={}){switch(e){case`open`:return k(`media-assistant-open`,t),{action:e,accepted:!0,needsPicker:!0,requested:t};case`projection`:return{action:e,state:Pu(t.projection)};case`packing`:return{action:e,state:Fu(t.packing)};case`environment`:return{action:e,state:Iu(t.environment)};case`adjust_screen`:return{action:e,state:Lu(t)};case`spatial_audio`:{let n=await Wu(!!t.enabled);return{action:e,enabled:!!n?.enabled,engine:n?.engine||null,reason:n?.reason}}case`ambient`:return{action:e,applied:Bu(!!t.enabled)};case`ai_depth`:{let n=await Ju(!!t.enabled);return{action:e,applied:n.enabled,engine:n.provider,reason:n.reason}}case`experimental_surround`:return{action:e,applied:!1,reason:`The generative surround model is not installed yet. It is a paid-tier feature that runs on pay-per-use GPU inference, which is not wired up.`};default:return{action:e,accepted:!1,reason:`Unknown media control '${e}'.`}}}function Xu(){return gu(),qu(),O(`media:control`,e=>{let{action:t,data:n}=e?.payload||e||{};t&&Yu(t,n||{})}),O(`media-open-request`,e=>{e?.file&&Du(e.file,e.options||{}).catch(e=>{C(e?.message||String(e),`Media`)})}),bt(()=>{uu&&yt(uu),uu=0,Ku()}),globalThis.JarvisMedia={open:Du,setProjection:Pu,setPacking:Fu,setEnvironment:Iu,adjustScreen:Lu,setAmbientResponse:Bu,setupSpatialAudio:Wu,updateAudioOrientation:Gu,detectHeadphones:Hu,getState:Y,getQualityReport:zu,probeDecodeCapability:gu,probeLayersSupport:Mu,tryMediaLayer:Nu,applyAssistantControl:Yu,close:Ku,PROJECTIONS:du,PACKINGS:fu,ENVIRONMENTS:pu,_math:{detectProjection:_u,detectPacking:yu,eyeUvRect:bu,unpackedEyeSize:xu,computeScreenDimensions:Eu,buildScreenGeometry:Su}},!0}var Zu={flat:`Flat`,180:`180`,360:`360`,fisheye:`Fisheye`},Qu={mono:`Mono`,"sbs-full":`SBS full`,"sbs-half":`SBS half`,"tb-full":`Top-bottom`,"tb-half":`TB half`},$u={passthrough:`<path d="M3 7h18v11H3z"/><path d="M3 12h18"/>`,mixed:`<path d="M4 6h9v9H4z"/><path d="M11 11h9v7h-9z"/>`,theater:`<path d="M3 5h18v10H3z"/><path d="M6 19h12M8 15v4M16 15v4"/>`,imax:`<path d="M2 6c5-2.5 15-2.5 20 0v9c-5 2.5-15 2.5-20 0z"/>`,pvr:`<path d="M3 6h18v9H3z"/><path d="M7 19h10"/>`,inox:`<path d="M2.5 6h19v10h-19z"/><path d="M6 20h12"/>`},X=null,ed=null,td=0,nd=!1,rd=!1;function id(e,t=``){return`<svg class="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">${e}</svg>`}function ad(e,t,n,r,i){return t.map(t=>{let a=t===r,o=a&&i?`<span class="mv-auto">AUTO</span>`:``;return`<button type="button" class="mv-chip" data-${e}="${t}" aria-pressed="${a}">${n[t]}${o}</button>`}).join(``)}function od(){if(X)return X.classList.add(`mv-open`),X;let e=gu();return X=document.createElement(`section`),X.id=`media-viewer-panel`,X.className=`mv-panel glass-panel mv-open`,X.setAttribute(`role`,`dialog`),X.setAttribute(`aria-label`,`Local media viewer`),X.innerHTML=`
<header class="mv-head">
<div>
<p class="mv-eyebrow">WebAR · immersive media</p>
<h2 class="mv-title">Local media viewer</h2>
</div>
<button type="button" class="mv-close" data-mv="close" aria-label="Close media viewer">
${id(`<path d="M5 5l14 14M19 5L5 19"/>`)}
</button>
</header>
<div class="mv-body">
<p class="mv-cap">1 · pick a file</p>
<div class="mv-card">
<span class="mv-brk tr"></span><span class="mv-brk bl"></span>
<div class="mv-drop" data-mv="drop">
${id(`<path d="M12 16V4M12 4 7.5 8.5M12 4l4.5 4.5"/><path d="M3.5 15v3.2A1.8 1.8 0 0 0 5.3 20h13.4a1.8 1.8 0 0 0 1.8-1.8V15"/>`,`mv-drop-icon`)}
<div class="mv-drop-big">Choose a photo or video</div>
<div class="mv-drop-small">From this device. Nothing is uploaded — the file never leaves your phone.</div>
<button type="button" class="mv-btn" data-mv="browse">Browse files</button>
</div>
<div class="mv-detected" data-mv="detected" hidden></div>
</div>
<p class="mv-cap">2 · projection format</p>
<div class="mv-card">
<span class="mv-brk tr"></span><span class="mv-brk bl"></span>
<p class="mv-h">Format</p>
<p class="mv-sub">What shape the source actually is. Auto-detected from the frame's dimensions
and the filename — override it if the guess is wrong.</p>
<div class="mv-row" data-mv="formats"></div>
<p class="mv-h mv-h-gap">Stereo packing</p>
<p class="mv-sub">How two eyes are stored in one frame. Half-packed sources are un-squeezed by
the projection geometry, never by resizing the picture.</p>
<div class="mv-row" data-mv="packings"></div>
</div>
<p class="mv-cap">3 · where you watch it</p>
<div class="mv-card">
<span class="mv-brk tr"></span><span class="mv-brk bl"></span>
<p class="mv-h">Viewing mode</p>
<p class="mv-sub">These change the room and the screen around the picture. They never change
decode quality, resolution, or bitrate.</p>
<div class="mv-modes" data-mv="modes"></div>
<p class="mv-note" data-mv="mode-note"></p>
</div>
<p class="mv-cap">4 · the screen itself</p>
<div class="mv-card">
<span class="mv-brk tr"></span><span class="mv-brk bl"></span>
<p class="mv-h">Screen placement</p>
<p class="mv-sub">A plan view of the room. Drag the screen's edges to resize it, drag it up or
down to move it nearer or further. It moves live.</p>
<div class="mv-gizmo" data-mv="gizmo">
<div class="mv-grid"></div>
<div class="mv-wedge" data-mv="wedge"></div>
<svg class="mv-screen" data-mv="screen-svg" viewBox="0 0 200 34" preserveAspectRatio="none">
<path d="M4 30 Q100 6 196 30"/>
</svg>
<span class="mv-handle l" data-mv="h-left" role="slider" tabindex="0" aria-label="Screen width"></span>
<span class="mv-handle r" data-mv="h-right" role="slider" tabindex="0" aria-label="Screen width"></span>
<span class="mv-handle d" data-mv="h-dist" role="slider" tabindex="0" aria-label="Screen distance"></span>
<span class="mv-viewer"></span>
<span class="mv-viewer-lbl">YOU</span>
</div>
<div class="mv-readouts" data-mv="readouts"></div>
</div>
<p class="mv-cap">5 · audio and enhancements</p>
<div class="mv-card">
<span class="mv-brk tr"></span><span class="mv-brk bl"></span>
<div class="mv-tog">
<div>
<div class="mv-lab">Spatial audio</div>
<div class="mv-hint">HRTF binaural rendering, matched to the room you're in. For headphones —
off automatically on speakers. This is not Dolby Atmos.</div>
</div>
<button type="button" class="mv-sw" data-mv="sw-audio" role="switch" aria-checked="false"><i></i></button>
</div>
<div class="mv-tog">
<div>
<div class="mv-lab">Ambient light response</div>
<div class="mv-hint">The room picks up the colour of what's on screen.</div>
</div>
<button type="button" class="mv-sw" data-mv="sw-ambient" role="switch" aria-checked="false"><i></i></button>
</div>
<div class="mv-tog">
<div>
<div class="mv-lab">AI 3D depth</div>
<div class="mv-hint">Synthesises a second eye from a flat video. Real depth estimation —
small areas behind foreground objects are filled in, not captured.</div>
</div>
<button type="button" class="mv-sw" data-mv="sw-depth" role="switch" aria-checked="false"><i></i></button>
</div>
<div class="mv-tog">
<div>
<div class="mv-lab">Experimental AI surround</div>
<div class="mv-hint">Invents the parts of the scene the camera never saw, to fill a full
sphere. Most of what you'd see is generated, not filmed.</div>
</div>
<button type="button" class="mv-sw warn" data-mv="sw-surround" role="switch" aria-checked="false"><i></i></button>
</div>
</div>
<p class="mv-cap">6 · what you're actually getting</p>
<div class="mv-card">
<span class="mv-brk tr"></span><span class="mv-brk bl"></span>
<p class="mv-h">Playback quality</p>
<p class="mv-sub">Measured, not asserted. If this device can't carry the source, it says so here
rather than quietly lowering the quality.</p>
<dl class="mv-q" data-mv="quality">
<dt>Max texture</dt><dd>${e.maxTextureSize||`unknown`} px</dd>
<dt>WebCodecs</dt><dd>${e.webCodecs?`available`:`absent`}</dd>
<dt>WebXR media layers</dt><dd>${e.webxrMediaLayers?`available`:`absent`}</dd>
</dl>
</div>
</div>
`,ed=document.createElement(`input`),ed.type=`file`,ed.accept=`video/*,image/*`,ed.style.cssText=`position:absolute;width:1px;height:1px;opacity:0;pointer-events:none`,X.appendChild(ed),(document.getElementById(`ui-layer`)||document.body).appendChild(X),cd(),vd(),X}function sd(e){let t=document.getElementById(`mv-experimental-label`);if(!e){t?.remove();return}t||(t=document.createElement(`div`),t.id=`mv-experimental-label`,t.setAttribute(`role`,`status`),t.innerHTML=`${id(`<path d="M12 3 22 20H2z"/><path d="M12 10v4M12 17h.01"/>`)}<p>Experimental — AI-generated surround, not real footage</p>`,(document.getElementById(`ui-layer`)||document.body).appendChild(t))}function cd(){N(X,`click`,e=>{let t=e.target.closest(`[data-mv],[data-format],[data-packing],[data-mode]`);if(t){if(t.dataset.format)return void ud(t.dataset.format);if(t.dataset.packing)return void dd(t.dataset.packing);if(t.dataset.mode)return void fd(t.dataset.mode);switch(t.dataset.mv){case`close`:return xd();case`browse`:case`drop`:return ed.click();case`sw-audio`:pd(t);return;case`sw-ambient`:md(t);return;case`sw-depth`:hd(t);return;case`sw-surround`:gd(t);return;default:return}}}),N(ed,`change`,()=>{let e=ed.files?.[0];e&&ld(e)}),N(X,`dragover`,e=>{e.preventDefault()}),N(X,`drop`,e=>{e.preventDefault();let t=e.dataTransfer?.files?.[0];t&&ld(t)}),_d(),bt(()=>xd())}async function ld(e){try{await Du(e,{environment:Y().environment||`theater`}),vd(),bd(),w(`${e.name} is open.`,`Media`)}catch(e){C(e?.message||String(e),`Media`)}}function ud(e){if(du.includes(e)){try{Pu(e)}catch(e){C(e.message,`Media`)}vd()}}function dd(e){if(fu.includes(e)){try{Fu(e)}catch(e){C(e.message,`Media`)}vd()}}function fd(e){if(pu[e]){try{Iu(e)}catch(e){C(e.message,`Media`)}vd()}}async function pd(e){let t=e.getAttribute(`aria-checked`)!==`true`,n=await Wu(t),r=!!n?.enabled;e.setAttribute(`aria-checked`,String(r)),t&&!r&&w(n?.headphones?.reason||`Spatial audio stays off until headphones are detected — it is built for headphone listening.`,`Spatial audio`)}function md(e){let t=e.getAttribute(`aria-checked`)!==`true`,n=Bu(t);e.setAttribute(`aria-checked`,String(!!n)),t&&!n&&w(`Open a video first — ambient response reads the playing frame.`,`Media`)}function hd(e){rd=e.getAttribute(`aria-checked`)!==`true`,e.setAttribute(`aria-checked`,`false`),rd&&(w(`AI 3D depth needs the depth model installed on the Space. The control is here; the engine is not ready yet.`,`Not available`),rd=!1)}function gd(e){nd=e.getAttribute(`aria-checked`)!==`true`,e.setAttribute(`aria-checked`,`false`),sd(!1),nd&&(w(`Experimental AI surround needs the generative model installed on the Space. The opt-in is here; the engine is not ready yet.`,`Not available`),nd=!1)}function _d(){let e=X.querySelector(`[data-mv="gizmo"]`);if(!e)return;let t=null,n=null,r=(e,r)=>{t=e;let i=Y().screen||{};n={x:r.clientX,y:r.clientY,width:i.width,distance:i.distance},r.preventDefault()};[`h-left`,`h-right`,`h-dist`].forEach(e=>{let t=X.querySelector(`[data-mv="${e}"]`);t&&(N(t,`pointerdown`,n=>{t.setPointerCapture?.(n.pointerId),r(e,n)}),N(t,`keydown`,t=>{let n=t.shiftKey?1:.25,r=Y().screen||{};if(t.key===`ArrowLeft`||t.key===`ArrowDown`)Lu(e===`h-dist`?{distance:Math.max(1,r.distance-n)}:{width:Math.max(.5,r.width-n)});else if(t.key===`ArrowRight`||t.key===`ArrowUp`)Lu(e===`h-dist`?{distance:r.distance+n}:{width:r.width+n});else return;t.preventDefault(),yd()}))}),N(e,`pointermove`,e=>{if(!(!t||!n)){if(t===`h-dist`){let t=(e.clientY-n.y)/26;Lu({distance:Math.max(1,n.distance+t)})}else{let r=(t===`h-right`?1:-1)*(e.clientX-n.x)/26;Lu({width:Math.max(.5,n.width+r*2)})}yd()}});let i=()=>{t=null,n=null};N(e,`pointerup`,i),N(e,`pointercancel`,i),N(window,`pointerup`,i)}function vd(){if(!X)return;let e=Y();X.querySelector(`[data-mv="formats"]`).innerHTML=ad(`format`,du,Zu,e.projection,e.projectionAuto),X.querySelector(`[data-mv="packings"]`).innerHTML=ad(`packing`,fu,Qu,e.packing,e.packingAuto),X.querySelector(`[data-mv="modes"]`).innerHTML=Object.keys(pu).map(t=>`<button type="button" class="mv-chip mv-mode" data-mode="${t}" aria-pressed="${t===e.environment}">${id($u[t])}${pu[t].label}</button>`).join(``);let t=X.querySelector(`[data-mv="mode-note"]`);t.textContent=e.roomSuppressed?`${Zu[e.projection]} content surrounds you, so there is no room to put it in — the ${pu[e.environment]?.label} preset applies to flat content only.`:`${pu[e.environment]?.note||``} Theater, PVR, INOX and IMAX are named room and screen presets — not licensed cinema formats.`,t.classList.toggle(`mv-note-warn`,!!e.roomSuppressed);let n=X.querySelector(`[data-mv="detected"]`);e.fileName?(n.hidden=!1,n.innerHTML=`${id(`<path d="M20 6 9 17l-5-5"/>`,`mv-ok-icon`)}
<p><b>${e.fileName}</b> — ${e.sourceWidth}×${e.sourceHeight}.
Detected as <b>${Zu[e.projection]}</b> (${e.projectionWhy}) packed
<b>${Qu[e.packing]}</b> (${e.packingWhy}).
Each eye is ${Math.round(e.eyeWidth)}×${Math.round(e.eyeHeight)}${e.eyeSqueezed?`, un-squeezed on playback`:``}.</p>`):n.hidden=!0,yd()}function yd(){if(!X)return;let e=Y().screen||{},t=X.querySelector(`[data-mv="readouts"]`);if(!t)return;t.innerHTML=[[`Width`,e.width?`${e.width.toFixed(2)} m`:`—`],[`Distance`,e.distance?`${e.distance.toFixed(1)} m`:`—`],[`Subtends`,e.width&&e.distance?`${(2*Math.atan(e.width/2/e.distance)*180/Math.PI).toFixed(0)}°`:`—`],[`Curve`,e.curvatureRadius?`${e.curvatureRadius.toFixed(1)} m`:`flat`]].map(([e,t])=>`<div class="mv-ro"><div class="mv-k">${e}</div><div class="mv-v">${t}</div></div>`).join(``);let n=X.querySelector(`[data-mv="screen-svg"]`);if(n&&e.width){let t=Math.max(40,Math.min(210,e.width*26));n.style.width=`${t}px`,n.style.top=`${Math.max(6,150-e.distance*13)}px`;let r=e.curvatureRadius>0?Math.min(24,900/e.curvatureRadius):0;n.querySelector(`path`).setAttribute(`d`,`M4 30 Q100 ${30-r} 196 30`);let i=X.querySelector(`[data-mv="h-left"]`),a=X.querySelector(`[data-mv="h-right"]`),o=X.querySelector(`[data-mv="h-dist"]`),s=parseFloat(n.style.top);i&&(i.style.left=`calc(50% - ${t/2}px - 7px)`,i.style.top=`${s+18}px`),a&&(a.style.left=`calc(50% + ${t/2}px - 7px)`,a.style.top=`${s+18}px`),o&&(o.style.top=`${s-4}px`)}}function bd(){td&&clearInterval(td),td=setInterval(()=>{let e=X?.querySelector(`[data-mv="quality"]`);if(!e)return;let t=Y(),n=zu();e.innerHTML=[[`Source`,`${t.sourceWidth} × ${t.sourceHeight}`,`plain`],[`Per eye`,`${Math.round(t.eyeWidth)} × ${Math.round(t.eyeHeight)}`,`plain`],[`Texture upload`,n&&n.textureWidth===t.sourceWidth?`Native, no downscale`:`pending`,n&&n.textureWidth===t.sourceWidth?`ok`:`plain`],[`Playback speed`,n?.realtimeRatio==null?`—`:`${(n.realtimeRatio*100).toFixed(0)}% of real time`,n&&n.realtimeRatio>=.97?`ok`:n?`warn`:`plain`],[`Stalled`,n?`${n.stallSeconds}s of ${n.elapsedSeconds}s`:`—`,n&&n.stallSeconds<1?`ok`:n?`warn`:`plain`],[`Render rate`,n?.rendererFps==null?`—`:`${n.rendererFps} fps`,n&&n.rendererFps>=55?`ok`:n?`warn`:`plain`],[`Mipmaps`,`Off — centre stays sharp`,`plain`],[`Adaptive reduction`,`Never applied`,`ok`]].map(([e,t,n])=>`<dt>${e}</dt><dd class="${n===`plain`?``:n}">${t}</dd>`).join(``)},500)}function xd(){return td&&(clearInterval(td),td=0),sd(!1),Ku(),X?.remove(),X=null,ed=null,!0}function Sd(){return O(`open-media`,()=>od()),globalThis.JarvisMediaUI={open:od,close:xd,isOpen:()=>!!X,click:e=>{let t=X?.querySelector(e);return t?(t.click(),!0):!1}},!0}var Cd=null,wd=null,Td=null,Ed=null,Dd=new Float32Array(1e3*3),Od=new Je;Od.setAttribute(`position`,new We(Dd,3)),Od.setDrawRange(0,0);var kd=1e3;function Ad(){return{name:`world-points-collector`,onUpdate:({processCpuResult:e})=>{let t=e?.worldPoints||e?.reality?.worldPoints||e?.reality?.points||e?.slam?.worldPoints;t&&t.length>0&&(D.worldPoints=t,jd(t))}}}function jd(e){if(!(!e||e.length<10)){for(let t of e){let e=t.position||t;!Number.isFinite(e.x)||!Number.isFinite(e.y)||!Number.isFinite(e.z)||D.worldPointBuffer.push(new S(e.x,e.y,e.z))}D.worldPointBuffer.length>1e3&&D.worldPointBuffer.splice(0,D.worldPointBuffer.length-1e3),D.frameCount+=1,D.frameCount%20==0&&(Md(D.worldPointBuffer),Nd(D.worldPointBuffer))}}function Md(e){if(!e.length)return;let{scene:t}=I(),n=Math.min(e.length,kd);for(let t=0;t<n;t+=1){let r=e[e.length-n+t];Dd[t*3]=r.x,Dd[t*3+1]=r.y,Dd[t*3+2]=r.z}Od.attributes.position.needsUpdate=!0,Od.setDrawRange(0,n),Cd||(Ed=new r({color:51455,size:.018,transparent:!0,opacity:.55,depthWrite:!1}),Cd=new te(Od,Ed),Cd.name=`jarvis-room-point-cloud`,Cd.scale.setScalar(1),t.add(Cd))}function Nd(e){if(!e.length)return;let t=[...e].sort((e,t)=>e.y-t.y),n=[],r=[];for(let e=0;e<t.length;e++){let i=t[e];if(r.length===0)r.push(i);else{let e=r[r.length-1];i.y-e.y<=.04?r.push(i):(n.push(r),r=[i])}}r.length>0&&n.push(r);let i=Math.max(8,Math.floor(t.length*.08)),a=null;for(let e of n)if(e.length>=i){a=e;break}let o;if(a)o=a.reduce((e,t)=>e+t.y,0)/a.length;else{let e=Math.max(4,Math.floor(t.length*.15)),n=t.slice(0,e);o=n.reduce((e,t)=>e+t.y,0)/n.length}if(!Number.isFinite(o))return;D.floorY!==void 0&&Number.isFinite(D.floorY)?D.floorY=D.floorY*.88+o*.12:D.floorY=o;let s=D.floorY,{scene:c}=I();if(!wd){let e=new x(10,10,20,20);wd=new b(e,new d({color:51455,transparent:!0,opacity:.06,side:2,depthWrite:!1})),Td=new b(e,new d({color:51455,transparent:!0,opacity:.2,wireframe:!0,depthWrite:!1})),wd.name=`jarvis-detected-floor`,Td.name=`jarvis-detected-floor-wire`,wd.rotation.x=-Math.PI/2,Td.rotation.x=-Math.PI/2,c.add(wd,Td)}wd.position.y=s,Td.position.y=s,D.shadowReceiver&&(D.shadowReceiver.position.y=s+.002),T(`status-tracking`,D.trackingMode===`8thwall-slam`?`slam+floor`:`basic floor`),k(`world-anchor-sample`,{floorY:s,pointCount:e.length})}function Pd(){D.worldPointBuffer.length<10&&Fd(),Md(D.worldPointBuffer),Nd(D.worldPointBuffer)}function Fd(){let e=[],{camera:t}=I(),n=new Me,r=Number.isFinite(D.floorY)?D.floorY:t&&t.position&&Number.isFinite(t.position.y)?t.position.y-1.45:-1.2;for(let i=0;i<9;i+=1)for(let a=0;a<20;a+=1){let o=.08+.84/19*a,s=.38+.46/8*i;n.setFromCamera(new Ce(o*2-1,-(s*2-1)),t);let c=(r-n.ray.origin.y)/n.ray.direction.y;Number.isFinite(c)&&c>.2&&c<8&&e.push(n.ray.origin.clone().add(n.ray.direction.clone().multiplyScalar(c)))}D.worldPointBuffer.push(...e),D.worldPointBuffer.length>1e3&&D.worldPointBuffer.splice(0,D.worldPointBuffer.length-1e3)}var Id={forest:[`Fox`,`Lantern`,`BarramundiFish`],lab:[`DamagedHelmet`,`AntiqueCamera`,`ReciprocatingSaw`],room:[`GlamVelvetSofa`,`WaterBottle`,`IridescenceLamp`],street:[`CesiumMilkTruck`,`ToyCar`,`Lantern`],default:[`Duck`,`Avocado`,`WaterBottle`]};function Ld(){O(`scan-room`,()=>{Pd(),w(`Room mesh scan updated from 8th Wall world points or basic fallback points.`,`Room Scan`)}),Bd()}async function Rd(e=`room`){let t=String(e||`room`).toLowerCase(),n=Id[t]||Id.default;Pd();let r=Math.min(3,Math.max(1,n.length));w(`Reconstructing ${t} scene with ${r} parallel model loads.`,`Scene Reconstruction`);try{await zd(t)}catch(e){C(e.message,`HDR Environment Failed`)}let i=(await Vd(n.map((e,t)=>async()=>{let r=t/n.length*Math.PI*2;return Hd(Ho(e,new S(Math.sin(r)*.75,D.floorY+.04,-1.5-Math.cos(r)*.45),new Ve),12e3,`Timed out loading ${e}`)}),r)).filter(e=>e.status===`rejected`);i.length&&C(`${i.length} reconstruction model(s) fell back or failed.`,`Scene Reconstruction`),w(`Reconstructed ${t} scene with ${n.length} placed objects.`,`Scene Reconstruction`)}async function zd(e){let{scene:t,renderer:n}=I(),r=await qn(e);return new Promise((e,i)=>{new ue().load(r,r=>{let a=new Le(n),o=a.fromEquirectangular(r),s=t.userData.jarvisEnvironmentTarget,c=t.environment;if(!o?.texture){r.dispose(),a.dispose(),i(Error(`HDR environment generation failed.`));return}t.environment=o.texture,t.userData.jarvisEnvironmentTarget=o,t.userData.jarvisEnvironmentSource=`hdr`,c?.dispose?.(),s?.dispose?.(),r.dispose(),a.dispose(),e(t.environment)},void 0,i)})}function Bd(){let e=new WeakSet;new MutationObserver(()=>{document.querySelectorAll(`video`).forEach(t=>{e.has(t)||(e.add(t),t.addEventListener(`play`,()=>{w(`A playing video was detected. Say "JARVIS reconstruct this scene" to build an AR scene.`,`Scene Detection`)},{once:!0}))})}).observe(document.documentElement,{childList:!0,subtree:!0})}async function Vd(e,t){let n=[],r=new Set;for(let i of e){let e=i().then(e=>({status:`fulfilled`,value:e})).catch(e=>({status:`rejected`,reason:e}));n.push(e),r.add(e),e.finally(()=>r.delete(e)),r.size>=t&&await Promise.race(r)}return Promise.all(n)}function Hd(e,t,n){let r=0,i=new Promise((e,i)=>{r=window.setTimeout(()=>i(Error(n)),t)});return Promise.race([e,i]).finally(()=>window.clearTimeout(r))}var Ud=.35,Wd=.65,Gd=.18,Kd=8,qd=4,Jd=12,Yd=60,Z={confidence:0,qualityTier:`initializing`,lostFrames:0,goodFrames:0,isLost:!1,worldOriginLocked:!1,worldOriginSamples:0,worldOriginPosition:new S,worldOriginQuaternion:new Ve,lastGoodPose:{position:new S,quaternion:new Ve,timestamp:0},smoothedPosition:new S,smoothedQuaternion:new Ve,anchorRegistry:new Map,planeRegistry:new Map,relocalizationAttempts:0,totalFrames:0};D.tracking=Z;function Xd(){return{name:`jarvis-tracking-quality`,onUpdate:({processCpuResult:e,processGpuResult:t})=>{Z.totalFrames++;let n=e?.reality||t?.reality||e||t,r=Zd(n),i=Qd(n);i&&(Z.confidence=Z.confidence*.85+r*.15,Z.qualityTier=$d(Z.confidence),D.trackingQuality=Z.qualityTier,document.body.dataset.jarvisTrackingQuality=Z.qualityTier,Z.confidence<Ud?(Z.lostFrames++,Z.goodFrames=0,!Z.isLost&&Z.lostFrames>=Kd&&of()):(Z.goodFrames++,Z.lostFrames=0,Z.isLost&&Z.goodFrames>=qd&&sf(i)),!Z.isLost&&(nf(i),Z.worldOriginLocked||af(Z.smoothedPosition,Z.smoothedQuaternion),uf(),Z.confidence>=Wd&&(Z.lastGoodPose.position.copy(Z.smoothedPosition),Z.lastGoodPose.quaternion.copy(Z.smoothedQuaternion),Z.lastGoodPose.timestamp=performance.now()),D.sessionAnchor.originPosition=Z.worldOriginPosition.toArray(),D.sessionAnchor.originQuaternion=Z.worldOriginQuaternion.toArray()))}}}function Zd(e){if(!e)return 0;let t=e.trackingStatus||e.slam?.trackingStatus;if(t){if(t===`NORMAL`)return .9;if(t===`LIMITED`)return .45;if(t===`INITIALIZING`)return .25}let n=e.confidence??e.slam?.confidence??e.poseConfidence;if(typeof n==`number`&&Number.isFinite(n))return Math.max(0,Math.min(1,n));let r=e.worldPoints||e.points;if(r&&Array.isArray(r)){let e=r.length;return e>80?.85:e>40?.65:e>15?.45:e>5?.25:.1}return .5}function Qd(e){if(!e)return null;let t=e.cameraPose||e.pose||e.slam?.cameraPose;if(!t)return null;let n=t.position||t,r=t.orientation||t.rotation;return Number.isFinite(n?.x)?{position:n,orientation:r}:null}function $d(e){return e>=.8?`excellent`:e>=.6?`good`:e>=.38?`fair`:e>=.15?`poor`:`initializing`}var ef=new S,tf=new Ve;function nf(e){let{position:t,orientation:n}=e;ef.set(Math.fround(t.x??0),Math.fround(t.y??0),Math.fround(t.z??0)),n&&tf.set(n.x??0,n.y??0,n.z??0,n.w??1);let r=Gd*(1+(1-Z.confidence)*1.5),i=Math.min(r,.45);Z.smoothedPosition.lerp(ef,i),Z.smoothedPosition.set(Math.fround(Z.smoothedPosition.x),Math.fround(Z.smoothedPosition.y),Math.fround(Z.smoothedPosition.z)),n&&(Z.smoothedQuaternion.slerp(tf,i),Z.smoothedQuaternion.normalize())}var rf=[];function af(e,t){if(Z.confidence<Wd){rf=[],Z.worldOriginSamples=0;return}rf.push({pos:e.clone(),quat:t.clone()}),rf.length>Jd&&rf.shift(),Z.worldOriginSamples=rf.length;let n=new S,r=new Ve;if(rf.forEach((e,t)=>{let i=1/(t+1);n.lerp(e.pos,i),r.slerp(e.quat,i)}),Z.worldOriginPosition.copy(n),Z.worldOriginQuaternion.copy(r),rf.length===Jd){let e=0;rf.forEach(t=>{e+=t.pos.distanceToSquared(n)}),e/Jd<.001&&(Z.worldOriginLocked=!0,D.sessionAnchor.restoredAt=Date.now(),k(`world-origin-locked`,{position:Z.worldOriginPosition.toArray(),quaternion:Z.worldOriginQuaternion.toArray()}),T(`status-tracking`,`${D.trackingMode} origin locked`))}}function of(){Z.isLost=!0,Z.worldOriginLocked=!1,Z.worldOriginSamples=0,rf=[],Z.relocalizationAttempts=0,document.body.dataset.jarvisTrackingState=`lost`,w(`Tracking lost — move camera slowly to reacquire environment.`,`Tracking`),T(`status-tracking`,`lost`),k(`tracking-lost`,{lastGoodPose:{position:Z.lastGoodPose.position.toArray(),age:performance.now()-Z.lastGoodPose.timestamp}}),Z.anchorRegistry.forEach(e=>{e.object&&(e.object.userData.trackingFrozen=!0)})}function sf(e){Z.isLost=!1,Z.lostFrames=0,Z.relocalizationAttempts++,document.body.dataset.jarvisTrackingState=`recovered`,T(`status-tracking`,D.trackingMode),k(`tracking-recovered`,{attempt:Z.relocalizationAttempts,confidence:Z.confidence}),Z.anchorRegistry.forEach(e=>{e.object&&(e.object.userData.trackingFrozen=!1)}),w(`Tracking recovered.`,`Tracking`)}function cf(e,t,n){let r={id:e,object:t,targetPosition:n.clone(),history:[],confidence:Z.confidence,createdAt:performance.now()};return Z.anchorRegistry.set(e,r),k(`anchor-registered`,{id:e,position:n.toArray()}),r}function lf(e){Z.anchorRegistry.delete(e),k(`anchor-removed`,{id:e})}function uf(){Z.anchorRegistry.forEach(e=>{if(!e.object||e.object.userData.trackingFrozen)return;let t=e.object,n=e.targetPosition,r=new S;t.getWorldPosition(r),r.set(Math.fround(r.x),Math.fround(r.y),Math.fround(r.z)),n.set(Math.fround(n.x),Math.fround(n.y),Math.fround(n.z));let i=r.distanceTo(n);if(e.history.push({drift:i,t:performance.now()}),e.history.length>Yd&&e.history.shift(),i>.001){let r=Math.max(.015,Math.min(.35,i*1.5));t.position.lerp(n,r),e.confidence=Z.confidence}})}function df(e){if(!e||e.length<20)return;let t=e.map(e=>{let t=e.position||e;return new S(t.x,t.y,t.z)}).filter(e=>Number.isFinite(e.x+e.y+e.z));if(t.length<20)return;let n=Math.min(...t.map(e=>e.y)),r=Math.max(...t.map(e=>e.y))-n;if(r<.1)return;let i=Array.from({length:10},()=>[]);t.forEach(e=>{i[Math.min(9,Math.floor((e.y-n)/r*10))].push(e)});let a=[];return i.forEach((e,t)=>{if(e.length<8)return;let i=n+t/10*r+r/10/2,o=e.reduce((e,t)=>e.add(t),new S).divideScalar(e.length),s=i<n+r*.25,c=i>n+r*.75,l=s?`floor`:c?`ceiling`:`surface`;a.push({yCenter:i,centroid:o,pointCount:e.length,type:l,confidence:Math.min(1,e.length/30)})}),a.forEach((e,t)=>{let n=`plane-${t}-${e.type}`;Z.planeRegistry.set(n,e)}),D.detectedPlanes=a,a.length>0&&k(`planes-updated`,{planes:a,count:a.length}),a}function ff(e,t){if(Z.confidence<Ud)return null;let{renderer:n}=I()||{};if(n?.xr?.enabled&&D.xrHitTestSource){let e=n.xr.getFrame();if(e){let t=n.xr.getReferenceSpace(),r=e.getHitTestResults(D.xrHitTestSource);if(r.length>0){let e=r[0].getPose(t);if(e){let t=new a().fromArray(e.transform.matrix);return{point:new S().setFromMatrixPosition(t),normal:new S(0,1,0).applyMatrix4(t).normalize(),confidence:Z.confidence,type:`webxr-hit-test`}}}}}if(globalThis.XR8?.XrController){let t=globalThis.XR8.XrController.hitTest(e.x,e.y,[`FEATURE_POINT`,`ESTIMATED_SURFACE`,`DETECTED_SURFACE`]);if(t&&t.length>0){let e=t[0];return{point:new S(e.position.x,e.position.y,e.position.z),normal:new S(0,1,0),confidence:Z.confidence*(e.type===`DETECTED_SURFACE`?.9:.5),type:e.type}}}let r=new Me;if(r.setFromCamera(new Ce(e.x*2-1,-(e.y*2-1)),t),Number.isFinite(D.floorY)){let e=new S(0,1,0),t=new oe(e,-D.floorY),n=new S;if(r.ray.intersectPlane(t,n)){let t=n.distanceTo(r.ray.origin);if(t>.2&&t<10)return{point:n,normal:e,confidence:Z.confidence,type:`floor`,distance:t}}}let i=D.detectedPlanes||[];for(let e of i){if(e.type===`floor`)continue;let t=new S(0,1,0),n=new oe(t,-e.yCenter),i=new S;if(r.ray.intersectPlane(n,i)){let n=i.distanceTo(r.ray.origin);if(n>.2&&n<10)return{point:i,normal:t,confidence:Z.confidence*e.confidence,type:e.type,distance:n}}}return null}function pf(){return{confidence:Z.confidence,tier:Z.qualityTier,isLost:Z.isLost,worldOriginLocked:Z.worldOriginLocked,anchorCount:Z.anchorRegistry.size,planeCount:Z.planeRegistry.size,relocalizationAttempts:Z.relocalizationAttempts,totalFrames:Z.totalFrames}}function mf(){Z.worldOriginLocked=!1,Z.worldOriginSamples=0,rf=[],Z.isLost=!1,Z.lostFrames=0,Z.goodFrames=0,w(`Relocalization requested — scanning environment.`,`Tracking`),k(`relocalization-requested`,{attempt:++Z.relocalizationAttempts})}function hf(){Z.confidence=0,Z.qualityTier=`initializing`,Z.lostFrames=0,Z.goodFrames=0,Z.isLost=!1,Z.worldOriginLocked=!1,Z.worldOriginSamples=0,rf=[],Z.anchorRegistry.clear(),Z.planeRegistry.clear(),Z.relocalizationAttempts=0,Z.totalFrames=0,D.detectedPlanes=[],document.body.dataset.jarvisTrackingQuality=`initializing`,document.body.dataset.jarvisTrackingState=`init`}O(`world-anchor-sample`,({floorY:e,pointCount:t})=>{D.worldPointBuffer?.length>20&&df(D.worldPointBuffer)}),O(`runtime-phase`,({phase:e})=>{(e===`created`||e===`booting`)&&hf()});var gf=null,_f=0;function vf(){return gf||(gf=wn(yf(`eternum`),`Eternum AR`,880,560),bf(gf,[[`NEXT`,`Enter`],[`AUTO`,`a`],[`SAVE`,`s`],[`MENU`,`Escape`]]),w(`Eternum opened as a floating AR panel. Normal game launch is unchanged outside AR.`,`Eternum AR`),gf)}function yf(e){let t=new URLSearchParams(location.search);return String(t.get(`${e}Url`)||t.get(`game${e[0].toUpperCase()}${e.slice(1)}Url`)||``).trim()||String(globalThis.FridayARConfig?.gameUrls?.[e]||``).trim()||`/api/ar_task?mode=game_launch&task=${encodeURIComponent(`open ${e} web mirror`)}`}function bf(e,t){let n=document.createElement(`div`);n.style.cssText=`position:absolute;left:10px;right:10px;bottom:10px;display:flex;gap:8px;justify-content:center;pointer-events:auto`,t.forEach(([t,r])=>{let i=document.createElement(`button`);i.textContent=t,i.style.cssText=`min-height:44px;min-width:70px;border:1px solid rgba(255,255,255,.25);border-radius:999px;background:rgba(0,0,0,.48);color:white;font-weight:700`,i.onclick=()=>xf(e.iframe,r),n.appendChild(i)}),e.container.style.position=`relative`,e.container.appendChild(n)}async function xf(e,t,n=!1,r=!1){let i=e?.contentWindow;if(!i)return C(`The game iframe is not ready yet.`,`Game Input Failed`),!1;try{let e={key:t,bubbles:!0,cancelable:!0,ctrlKey:n};return i.document.dispatchEvent(new KeyboardEvent(`keydown`,e)),r||window.setTimeout(()=>i.document.dispatchEvent(new KeyboardEvent(`keyup`,e)),50),!0}catch(e){let a=`key-${Date.now().toString(36)}-${++_f}`;return await new Promise(o=>{let s=window.setTimeout(()=>{window.removeEventListener(`message`,c),C(`The game iframe did not acknowledge the key relay before the timeout elapsed.`,`Game Input Timeout`),o(!1)},250),c=e=>{e.source===i&&(e.data?.type!==`keydown-ack`||e.data?.id!==a||(window.clearTimeout(s),window.removeEventListener(`message`,c),o(!0)))};window.addEventListener(`message`,c);try{i.postMessage({type:`keydown`,id:a,key:t,ctrl:n,hold:r},`*`)}catch(t){window.clearTimeout(s),window.removeEventListener(`message`,c),C(t.message||e.message,`Game Input Failed`),o(!1)}})}}var Sf=null;function Cf(){if(Sf)return Sf;let e=new URLSearchParams(location.search);Sf=wn(String(e.get(`ripplesUrl`)||globalThis.FridayARConfig?.gameUrls?.ripples||``).trim()||`/api/ar_task?mode=game_launch&task=open%20ripples%20web%20mirror`,`Ripples AR`,880,560);let t=document.createElement(`div`);return t.style.cssText=`position:absolute;left:10px;right:10px;bottom:10px;display:flex;gap:8px;justify-content:center;pointer-events:auto`,[[`NEXT`,`Enter`],[`AUTO`,`a`],[`SAVE`,`s`],[`MENU`,`Escape`]].forEach(([e,n])=>{let r=document.createElement(`button`);r.textContent=e,r.style.cssText=`min-height:44px;min-width:70px;border:1px solid rgba(255,255,255,.25);border-radius:999px;background:rgba(0,0,0,.48);color:white;font-weight:700`,r.onclick=()=>xf(Sf.iframe,n),t.appendChild(r)}),Sf.container.style.position=`relative`,Sf.container.appendChild(t),w(`Ripples opened as a floating AR panel.`,`Ripples AR`),Sf}async function wf(e,t){let n=await Tf(e,t),r=wn(Df(n.url||e),`${n.title||e} AR`,880,560);return jf(n.controls,r),r}async function Tf(e,t){if(t?.query)try{let n=await t.query(`Game "${e}" genre + controls as JSON only: {"title":"","url":"","genre":"","controls":[{"action":"","key":"","label":""}]}`),r=String(n).replace(/```json|```/g,``).trim(),i=JSON.parse(kf(r));if(Ef(i))return i}catch(e){C(e.message,`Game Schema AI Failed`)}return{title:e,url:Df(e),genre:`generic`,controls:[{action:`accept`,key:`Enter`,label:`NEXT`},{action:`back`,key:`Escape`,label:`BACK`},{action:`left`,key:`ArrowLeft`,label:`LEFT`},{action:`right`,key:`ArrowRight`,label:`RIGHT`}]}}function Ef(e){return!e||typeof e!=`object`||typeof e.title!=`string`||typeof e.url!=`string`||typeof e.genre!=`string`||!Array.isArray(e.controls)?!1:e.controls.every(e=>e&&typeof e==`object`&&typeof e.key==`string`&&typeof e.label==`string`&&e.key.trim()&&e.label.trim())}function Df(e){let t=String(e||``).trim();if(!t)return Of(`AR Game`);if(/^(https?:|blob:|data:|about:)/i.test(t)||t.startsWith(`/`))return t;let n=t.toLowerCase();if(n.includes(`eternum`)){let e=new URLSearchParams(location.search).get(`eternumUrl`);return String(e||globalThis.FridayARConfig?.gameUrls?.eternum||``).trim()||`/api/ar_task?mode=game_launch&task=open%20eternum%20web%20mirror`}if(n.includes(`ripples`)){let e=new URLSearchParams(location.search).get(`ripplesUrl`);return String(e||globalThis.FridayARConfig?.gameUrls?.ripples||``).trim()||`/api/ar_task?mode=game_launch&task=open%20ripples%20web%20mirror`}return Of(t)}function Of(e){let t=`<!doctype html>
<html>
<meta name="viewport" content="width=device-width,initial-scale=1">
<body style="margin:0;background:#05070a;color:white;font:16px system-ui;display:grid;place-items:center;height:100vh;text-align:center">
<main>
<h1 style="font-size:22px;margin:0 0 10px">${Af(e)}</h1>
<p style="opacity:.72;max-width:32rem">No direct web URL was configured for this game yet. Pass a URL in the launch query string or runtime config, or open a supported mirror command, then convert again.</p>
</main>
</body>
</html>`;return`data:text/html;charset=utf-8,${encodeURIComponent(t)}`}function kf(e){let t=e.indexOf(`{`),n=e.lastIndexOf(`}`);return t>=0&&n>t?e.slice(t,n+1):e}function Af(e){return String(e).replace(/[&<>"']/g,e=>({"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`})[e])}function jf(e,t){let n=document.createElement(`div`);return n.style.cssText=`position:absolute;left:10px;right:10px;bottom:10px;display:flex;gap:8px;justify-content:center;flex-wrap:wrap;pointer-events:auto`,e.forEach(e=>{let r=document.createElement(`button`);r.textContent=e.label||e.action,r.style.cssText=`min-height:44px;min-width:64px;border:1px solid var(--separator);border-radius:999px;background:var(--bg-dark);color:var(--text-primary);font-weight:700`,r.onclick=()=>xf(t.iframe,e.key||`Enter`),n.appendChild(r)}),t.container.style.position=`relative`,t.container.appendChild(n),n}var Mf=`jarvis_ar_game_builder_graphs_v1`,Nf=[`OnCollide`,`OnTap`,`OnGesture`,`OnTimerEnd`,`IsTag`,`IsHealth`,`IsDistance`,`Destroy`,`Spawn`,`MoveToward`,`SetScore`,`PlaySound`,`ShowMessage`,`EndGame`],Pf=null,Ff=null;function If(){if(Pf)return Pf.restore(),Pf;let e=document.createElement(`div`);e.append(Lf()),Pf=new bn({title:`AR Game Builder`,body:e,icon:`B`,width:400,height:600});let t=Pf.destroy.bind(Pf);return Pf.destroy=()=>{Ff?.dispose?.(),Ff=null,t(),Pf=null},Pf.focus(),Pf}function Lf(){let e=document.createElement(`div`),t=document.createElement(`div`),n=document.createElement(`div`);return t.className=`panel-row`,Object.entries({Entities:Rf,Logic:zf,Settings:Bf,Play:Vf}).forEach(([e,r],i)=>{let a=document.createElement(`button`);a.className=`panel-action`,a.textContent=e,a.onclick=()=>{t.querySelectorAll(`button`).forEach(e=>e.classList.toggle(`selected`,e===a)),n.replaceChildren(r())},t.appendChild(a),i===0&&window.setTimeout(()=>a.click(),0)}),e.append(t,n),e}function Rf(){let e=document.createElement(`div`),t=document.createElement(`input`),n=document.createElement(`input`),r=document.createElement(`button`);return t.placeholder=`Entity name`,n.placeholder=`Tag, e.g. target`,r.className=`panel-action`,r.textContent=`Add Entity`,r.onclick=()=>{let e=hr(Mf,[]).at(-1)||qf();e.entities.push({id:xr(`entity`),name:t.value||`Entity`,tag:n.value||`default`}),Jf(e),w(`Entity saved to AR game graph.`)},e.append(t,n,r,Yf()),e}function zf(){let e=document.createElement(`div`),t=document.createElement(`select`),n=document.createElement(`input`),r=document.createElement(`button`);return Sr(t,Nf),n.placeholder=`Node value`,r.className=`panel-action`,r.textContent=`Add Logic Node`,r.onclick=()=>{let e=hr(Mf,[]).at(-1)||qf();e.nodes.push({id:xr(`node`),type:t.value,value:n.value}),Jf(e),w(`${t.value} node added.`)},e.append(t,n,r,Yf()),e}function Bf(){let e=document.createElement(`div`),t=document.createElement(`input`),n=document.createElement(`input`),r=document.createElement(`button`);return t.placeholder=`Game title`,n.type=`number`,n.placeholder=`Timer seconds`,r.className=`panel-action`,r.textContent=`Save Settings`,r.onclick=()=>{let e=hr(Mf,[]).at(-1)||qf();e.title=t.value||e.title,e.duration=Number(n.value||e.duration||60),Jf(e),w(`Game settings saved.`)},e.append(t,n,r,Yf()),e}function Vf(){let e=document.createElement(`div`),t=document.createElement(`button`);return t.className=`btn-primary`,t.textContent=`Spawn Saved Game`,t.onclick=()=>{let e=hr(Mf,[]).at(-1);if(!e){w(`Create a game graph first.`);return}Ff?.dispose?.(),Ff=Hf(e),w(`Game "${e.title}" spawned ${Ff.entities.length} AR entity object(s).`,`Game Builder`)},e.append(t,Yf()),e}function Hf(e){let{scene:t,camera:n}=I(),r=new g;r.name=`jarvis-game-${e.id}`,r.userData.isARGame=!0,r.position.set(0,D.floorY+.08,-1.6),t.add(r);let i=(e.entities.length?e.entities:[{id:xr(`entity`),name:`Target`,tag:`target`}]).map((t,n)=>Uf(t,n,e.entities.length||1));i.forEach(e=>r.add(e.mesh));let a=0,o=!1,s=performance.now(),c=[],l=[],u=new Me,d=t=>{if(o)return;let n=String(t.type||``).toLowerCase(),s=String(t.value||``).trim();if(n===`spawn`){let e=Uf({id:xr(`entity`),name:s||`Spawned`,tag:`spawned`},i.length,i.length+1);i.push(e),r.add(e.mesh)}else if(n===`destroy`){let e=Wf(s,i);e&&(e.mesh.parent?.remove(e.mesh),e.destroyed=!0)}else if(n===`setscore`)a=Number(s||a+1),r.userData.score=a;else if(n===`showmessage`)w(s||e.title||`AR game event`,`Game Builder`);else if(n===`playsound`)Kf();else if(n===`endgame`)o=!0,w(`${e.title||`AR Game`} ended. Score: ${a}`,`Game Builder`);else if(n===`movetoward`){let e=Wf(s,i)||i[0];e&&e.mesh.position.lerp(new S(0,.12,-.35),.35)}},f=t=>{if(o||t.target.closest?.(`.ar-panel, .hud-toolbar, button, input, select, textarea, iframe`))return;u.setFromCamera(new Ce(t.clientX/innerWidth*2-1,-(t.clientY/innerHeight)*2+1),n);let s=u.intersectObjects(i.filter(e=>!e.destroyed).map(e=>e.mesh),!0)[0];if(!s)return;let c=Gf(s.object,i);a+=1,r.userData.score=a,c.mesh.scale.multiplyScalar(.92),e.nodes.filter(e=>e.type===`OnTap`||e.type===`SetScore`||e.type===`ShowMessage`).forEach(d)};document.addEventListener(`pointerup`,f,!0),l.push(()=>document.removeEventListener(`pointerup`,f,!0));let p=O(`gesture-pinch`,()=>{e.nodes.filter(e=>e.type===`OnGesture`||e.type===`SetScore`).forEach(d)});l.push(p),Number(e.duration)>0&&c.push(window.setTimeout(()=>{e.nodes.filter(e=>e.type===`OnTimerEnd`||e.type===`EndGame`).forEach(d),o||(o=!0,w(`${e.title||`AR Game`} timer finished. Score: ${a}`,`Game Builder`))},Number(e.duration)*1e3));let m=()=>{if(!r.parent||o)return;let e=(performance.now()-s)/1e3;i.forEach((t,n)=>{t.destroyed||(t.mesh.rotation.y+=.01+n*.001,t.mesh.position.y=.08+Math.sin(e*1.6+n)*.035)}),r.userData.frame=P(m)};return m(),{root:r,entities:i,dispose(){o=!0,yt(r.userData.frame),c.forEach(e=>window.clearTimeout(e)),l.forEach(e=>e()),r.traverse(e=>{e.geometry?.dispose?.(),e.material?.dispose?.()}),r.parent?.remove(r)}}}function Uf(e,t,n){let r=new v(.12,1),i=t/Math.max(n,1)*.78+.05,a=new b(r,new y({color:new ie().setHSL(i,.72,.55),emissive:new ie().setHSL(i,.72,.12),roughness:.25,metalness:.18})),o=t/Math.max(n,1)*Math.PI*2;return a.position.set(Math.sin(o)*.55,.08,-Math.cos(o)*.35),a.userData.entityId=e.id,a.userData.entityName=e.name,a.userData.tag=e.tag,a.castShadow=!0,a.receiveShadow=!0,{...e,mesh:a,destroyed:!1}}function Wf(e,t){let n=String(e||``).toLowerCase();return t.find(e=>String(e.name||``).toLowerCase().includes(n)||String(e.tag||``).toLowerCase().includes(n)||String(e.id||``).toLowerCase()===n)}function Gf(e,t){let n=e;for(;n;){let e=n.userData?.entityId;if(e)return t.find(t=>t.id===e);n=n.parent}return null}function Kf(){try{let e=new AudioContext,t=e.createOscillator(),n=e.createGain();t.frequency.value=660,n.gain.value=.035,t.connect(n),n.connect(e.destination),t.start(),window.setTimeout(()=>{t.stop(),e.close()},140)}catch{}}function qf(){return{id:xr(`game`),title:`Untitled AR Game`,duration:60,entities:[],nodes:[],createdAt:Date.now()}}function Jf(e){let t=hr(Mf,[]).filter(t=>t.id!==e.id);t.push(e),gr(Mf,t.slice(-20))}function Yf(){let e=document.createElement(`pre`),t=hr(Mf,[]).at(-1)||qf();return e.style.cssText=`white-space:pre-wrap;font:12px/1.4 monospace;color:rgba(255,255,255,.72);background:rgba(0,0,0,.25);padding:10px;border-radius:12px;max-height:160px;overflow:auto`,e.textContent=JSON.stringify(t,null,2),e}async function Xf(e,t={},n=0,r=1e4){let i=null;for(let a=0;a<=n;a+=1){let o=new AbortController,s=window.setTimeout(()=>o.abort(new DOMException(`Request timed out`,`AbortError`)),r);try{let n=await fetch(e,{...t,signal:o.signal});return window.clearTimeout(s),n}catch(e){if(window.clearTimeout(s),i=e,a>=n)throw e}}throw i||Error(`Request failed.`)}async function Zf(e,t={},n=0,r=1e4){let i=await Xf(e,t,n,r);if(!(i.headers.get(`content-type`)||``).includes(`application/json`)){let t=await i.text();throw Error(t||`Expected JSON response from ${e}`)}return i.json()}function Qf(e,t){if(!Array.isArray(e))return!1;let n=JSON.stringify(t);return e.some(e=>JSON.stringify(e)===n)?!1:(e.push(t),!0)}var $f=class{constructor(e){this.config=e,this.ws=null,this.connected=!1,this.reconnectTimer=0,this.pendingPatches=[],this.reconnectDelay=2e3,this.maxReconnectDelay=3e4,this.heartbeatTimer=0}connect(){return this.connectWebSocket(),this.loadConfig(),D.jarvis=this,this}async loadConfig(){try{let e=await Zf(`${this.apiBase()}/api/ar_config`,{headers:this.headers()},1,9e3);if(e.ok===!1)throw Error(e.error||`AR config failed.`);return k(`jarvis-config`,e),T(`status-omega`,`linked`),e}catch{return T(`status-omega`,`offline`),null}}connectWebSocket(){let e=this.config.wsBase||(location.protocol===`https:`?`wss://${location.host}/scene-ws`:`ws://${location.hostname}:5050`),t=cr(`omega_session`);t&&!/[?&]token=/.test(e)&&(e+=`${e.includes(`?`)?`&`:`?`}token=${encodeURIComponent(t)}`);try{this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=0),this._clearHeartbeat(),this.ws=new WebSocket(e),this.ws.onopen=()=>{this.connected=!0,clearTimeout(this.reconnectTimer),this.reconnectDelay=2e3,T(`status-omega`,`linked`),this.ws.send(JSON.stringify({type:`hello`,device_name:this.config.deviceName,source:`browser-8thwall-real-ar`})),this.flushPendingPatches(),this._startHeartbeat()},this.ws.onmessage=e=>this.onMessage(e),this.ws.onerror=()=>{this.connected&&T(`status-omega`,`ws error`)},this.ws.onclose=()=>{this.connected=!1,this._clearHeartbeat(),T(`status-omega`,`offline`),this.reconnectTimer&&clearTimeout(this.reconnectTimer);let e=this.reconnectDelay;this.reconnectDelay=Math.min(this.reconnectDelay*2,this.maxReconnectDelay),this.reconnectTimer=setTimeout(()=>this.connectWebSocket(),e)}}catch(e){C(e.message,`OMEGA WebSocket Failed`)}}_startHeartbeat(){this._clearHeartbeat(),this.heartbeatTimer=setInterval(()=>{if(!this.ws||this.ws.readyState!==WebSocket.OPEN){this._clearHeartbeat();return}try{this.ws.send(JSON.stringify({type:`ping`,ts:Date.now()}))}catch{this.ws.close()}},15e3)}_clearHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=0)}onMessage(e){try{let t=JSON.parse(e.data);k(`omega-message`,t),t.state&&k(`omega-scene-state`,t.state)}catch{}}async query(e){let t=await Xf(`${this.apiBase()}/api/ar_task`,{method:`POST`,headers:{"Content-Type":`application/json`,...this.headers()},body:JSON.stringify({task:e,mode:`jarvis`,device_name:this.config.deviceName})},0,9e3),n=await t.json();if(!t.ok||n.ok===!1)throw Error(n.error||`JARVIS query failed.`);return n.response||n.message||n.result||JSON.stringify(n)}async runTask(e,t=`task`){let n=await Xf(`${this.apiBase()}/api/ar_task`,{method:`POST`,headers:{"Content-Type":`application/json`,...this.headers()},body:JSON.stringify({task:e,mode:t,device_name:this.config.deviceName})},0,9e3),r=await n.json();if(!n.ok||r.ok===!1)throw Error(r.error||`Task endpoint failed.`);return k(`jarvis-task-result`,r),r}patchScene(e){let t={...e,device_name:this.config.deviceName,source:`browser-8thwall-real-ar`};return this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify({type:`patch`,patch:t,ts:Date.now()})),Promise.resolve(!0)):(Qf(this.pendingPatches,t),Xf(`${this.apiBase()}/api/ar_scene_patch`,{method:`POST`,headers:{"Content-Type":`application/json`,...this.headers()},body:JSON.stringify(t)},1,9e3).catch(()=>null))}headers(){let e={"X-FRIDAY-Device":this.config.deviceName},t=cr(`omega_session`);return t&&(e.Authorization=`Bearer ${t}`),e}apiBase(){return String(this.config.omegaBase||``).replace(/\/+$/,``)||``}flushPendingPatches(){!this.ws||this.ws.readyState!==WebSocket.OPEN||!this.pendingPatches.length||this.pendingPatches.splice(0).forEach(e=>{try{this.ws.send(JSON.stringify({type:`patch`,patch:{...e,device_name:this.config.deviceName,source:`browser-8thwall-real-ar`},ts:Date.now()}))}catch{}})}},ep={IDLE:`idle`,LISTENING:`listening`,THINKING:`thinking`,SPEAKING:`speaking`},tp={listening:`👂`,thinking:`🧠`,speaking:`🔊`},np={listening:`LISTENING`,thinking:`THINKING`,speaking:`SPEAKING`},rp=ep.IDLE,ip=new Set;function ap(){return rp}function op(e){return ip.add(e),()=>ip.delete(e)}function sp(e){let t=String(e||``).toLowerCase();Object.values(ep).includes(t)&&t!==rp&&(rp=t,lp(),ip.forEach(e=>{try{e(rp)}catch{}}))}function cp(){let e=document.getElementById(`jarvis-assistant-state`);return e||(e=document.createElement(`div`),e.id=`jarvis-assistant-state`,e.setAttribute(`aria-live`,`polite`),Object.assign(e.style,{position:`fixed`,top:`calc(env(safe-area-inset-top, 0px) + 12px)`,left:`50%`,transform:`translateX(-50%) translateY(-8px)`,display:`flex`,alignItems:`center`,gap:`8px`,padding:`7px 14px`,borderRadius:`999px`,background:`linear-gradient(180deg, rgba(10,10,15,.82), rgba(10,10,15,.62))`,border:`1px solid rgba(0,212,255,.35)`,boxShadow:`0 6px 24px rgba(0,0,0,.45), 0 0 18px rgba(0,212,255,.22)`,backdropFilter:`blur(14px) saturate(140%)`,color:`#eaf2ff`,font:`600 11px/1 'JetBrains Mono', ui-monospace, monospace`,letterSpacing:`2px`,zIndex:`99998`,pointerEvents:`none`,opacity:`0`,transition:`opacity .28s cubic-bezier(.2,.8,.2,1), transform .28s cubic-bezier(.2,.8,.2,1)`}),e.innerHTML=`<span data-glyph style="font-size:14px;letter-spacing:0"></span><span data-label></span>`,document.body.appendChild(e),e)}function lp(){let e;try{e=cp()}catch{return}if(!e)return;let t=e.querySelector(`[data-glyph]`),n=e.querySelector(`[data-label]`);if(rp===ep.IDLE){e.style.opacity=`0`,e.style.transform=`translateX(-50%) translateY(-8px)`;return}t&&(t.textContent=tp[rp]||``),n&&(n.textContent=np[rp]||``),e.style.opacity=`1`,e.style.transform=`translateX(-50%) translateY(0)`}var up=0,dp={idle:`JARVIS`,listening:`Listening`,thinking:`Working on it`,speaking:`JARVIS`,failed:`Couldn’t answer`};function fp(e){let t=document.getElementById(`jarvis-bubble`),n=document.getElementById(`jarvis-bubble-label`);if(!t)return;let r=String(e||`idle`).toLowerCase();t.setAttribute(`data-state`,r),n&&(n.textContent=dp[r]||`JARVIS`)}var pp=!1;function mp(){if(pp)return;pp=!0,op(fp),fp(ap());let e=document.getElementById(`jarvis-bubble-close`),t=document.getElementById(`jarvis-bubble`);e&&t&&e.addEventListener(`click`,()=>{clearTimeout(up),t.classList.add(`hidden`)})}function hp(e,{speak:t=!0}={}){let n=document.getElementById(`jarvis-bubble`),r=document.getElementById(`jarvis-bubble-text`);!n||!r||(mp(),n.classList.remove(`hidden`),clearTimeout(up),_p(r,String(e||`Ready.`),()=>{clearTimeout(up),up=window.setTimeout(()=>n.classList.add(`hidden`),6e3)}),t&&gp(e))}function gp(e){try{if(!(`speechSynthesis`in window))return;window.speechSynthesis.cancel();let t=new SpeechSynthesisUtterance(String(e||``));t.rate=.92,t.pitch=.82,t.volume=.88;let n=window.speechSynthesis.getVoices();t.voice=n.find(e=>String(e.lang||``).toLowerCase()===`en-gb`)||n.find(e=>/Daniel|George|Arthur|Google UK English Male|English.*United Kingdom|UK/i.test(`${e.name} ${e.lang}`))||n.find(e=>String(e.lang||``).toLowerCase().startsWith(`en-gb`))||n.find(e=>/en/i.test(e.lang))||null;let r=()=>{ap()===ep.SPEAKING&&sp(ep.IDLE)};t.onstart=()=>sp(ep.SPEAKING),t.onend=r,t.onerror=r,window.speechSynthesis.speak(t)}catch{ap()===ep.SPEAKING&&sp(ep.IDLE)}}function _p(e,t,n){e.textContent=``;let r=0,i=()=>{e.textContent=t.slice(0,r),r+=1,r<=t.length?window.setTimeout(i,14):n?.()};i()}var vp=null,yp=0,bp=0,xp=!1,Sp=!1,Cp=!1,wp=null,Tp=`unknown`,Ep=0,Dp=``;function Op(){let e=window.SpeechRecognition||window.webkitSpeechRecognition;return e?(vp=new e,vp.continuous=!0,vp.interimResults=!1,vp.lang=navigator.language||`en-US`,vp.onresult=Ap,vp.onerror=e=>{if(e.error===`not-allowed`||e.error===`service-not-allowed`||e.error===`audio-capture`){xp=!1,Tp=`blocked`,clearTimeout(bp),C(e.error||`Speech recognition blocked.`,`JARVIS Voice`),Mp(`blocked`,{error:e.error||`blocked`});return}e.error!==`no-speech`&&C(e.error||`Speech recognition failed.`,`JARVIS Voice`),Mp(`error`,{error:e.error||`unknown`})},vp.onend=()=>{xp&&(clearTimeout(bp),bp=setTimeout(()=>void kp(),850),Mp(`ended`))},!0):(w(`SpeechRecognition is not available here. Use the JARVIS text command panel.`),!1)}async function kp(){if(!vp&&!Op())return!1;if(Cp)return!0;xp=!0,Cp=!0,await jp();try{return vp.start(),window.setTimeout(()=>{Cp=!1},350),Sp||(w(`JARVIS wake word listening is active.`),Sp=!0),!0}catch(e){return Cp=!1,clearTimeout(bp),bp=setTimeout(()=>{xp&&kp()},1200),/InvalidStateError/i.test(e?.name||e?.message||``)||w(`JARVIS voice restart pending: ${e?.message||`recognizer busy`}`),Mp(`start-failed`,{error:e?.message||`busy`}),!1}}function Ap(e){if(!e.results?.[e.resultIndex]?.isFinal)return;let t=Array.from(e.results).slice(e.resultIndex).filter(e=>e?.isFinal).map(e=>e[0]?.transcript||``).join(` `).trim();if(!t)return;let n=t.toLowerCase().replace(/\s+/g,` `).trim(),r=Date.now(),i=n.match(/(?:^|\b)(?:hey\s+)?jarvis\b[:,]?\s*(.*)$/i)||n.match(/(?:^|\b)(?:hey\s+)?friday\b[:,]?\s*(.*)$/i),a=i?.[1]?.trim()||``;if(i){if(yp=r+4200,Mp(`wake`,{wakeWindowUntil:yp}),!a){hp(`Listening.`,{speak:!1});return}}else if(r>yp)return;if(r-Ep<650)return;Ep=r;let o=a||n;!o||o===Dp||(Dp=o,k(`jarvis-command`,{text:o,source:`voice`}),Mp(`command`,{wakeWindowUntil:yp}))}async function jp(){if(wp||Tp===`blocked`||!navigator.mediaDevices?.getUserMedia)return wp;try{return wp=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1},video:!1}),Tp=`granted`,Mp(`mic-ready`),wp}catch(e){return Tp=[`NotAllowedError`,`SecurityError`].includes(e?.name)?`blocked`:`error`,Mp(`mic-error`,{error:e?.name||e?.message||`unknown`}),null}}function Mp(e,t={}){try{k(`VOICE_STATE`,{reason:e,enabled:xp,starting:Cp,wakeWindowUntil:yp,micPermission:Tp,hasStream:!!wp,lastCommandAt:Ep,...t})}catch{}}var Np=5,Pp=.55,Fp=.3,Ip=null,Lp=null;function Rp(){return Ip||(Ip=document.getElementById(`world-label-layer`)),Ip}function zp(e,t){let n=t?.width||0,r=t?.height||0;if(!n||!r)return null;let i=t.source?.getBoundingClientRect?.(),a=i?.width||window.innerWidth,o=i?.height||window.innerHeight;if(!a||!o)return null;let s=i?.width?i.left:0,c=i?.height?i.top:0,l=`cover`;try{l=getComputedStyle(t.source).objectFit||`cover`}catch{}let u=l===`contain`||l===`scale-down`?Math.min(a/n,o/r):Math.max(a/n,o/r),d=s+(a-n*u)/2,f=c+(o-r*u)/2;return{cx:(e.originX+e.width/2)*u+d,top:e.originY*u+f}}function Bp(e){let t=Rp();if(!t)return;let n=gt();if(!n)return;let r=new Set,i=[];for(let t of e||[]){let e=t?.categories?.[0],a=e?.categoryName,o=e?.score??0;if(!a||o<Fp||r.has(a))continue;let s=zp(t.boundingBox||{},n);if(s&&!(s.cx<0||s.cx>window.innerWidth||s.top<0||s.top>window.innerHeight)&&(r.add(a),i.push({name:a,score:o,pos:s}),i.length>=Np))break}t.replaceChildren();for(let e of i){let n=document.createElement(`span`);n.className=e.score<Pp?`world-label low`:`world-label`,n.style.left=`${e.pos.cx}px`,n.style.top=`${e.pos.top}px`;let r=document.createElement(`b`);r.textContent=e.name.charAt(0).toUpperCase()+e.name.slice(1);let i=document.createElement(`span`);i.className=`world-label-conf`;let a=document.createElement(`i`);a.style.width=`${Math.round(Math.max(0,Math.min(1,e.score))*100)}%`,i.appendChild(a),n.append(r,i),t.appendChild(n)}}function Vp(){return Lp?!0:Rp()?(Lp=N(window,`ar-object-detections`,e=>{try{Bp(e.detail)}catch(e){console.warn(`[world-labels] render skipped`,e)}}),!0):!1}var Hp=null,Up=null,Wp=!1;async function Gp(){Wp=!0;try{Hp=new globalThis.FaceMesh({locateFile:e=>`https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/${e}`}),Hp.setOptions({maxNumFaces:1,refineLandmarks:!0,minDetectionConfidence:.5,minTrackingConfidence:.5}),Hp.onResults(e=>{window.dispatchEvent(new CustomEvent(`ar-face-mesh-results`,{detail:e}))}),console.log(`[AR Vision] Face mesh initialized.`)}catch(e){Hp=null,console.warn(`[AR Vision] Face mesh unavailable, continuing without it:`,e),T(`status-tracking`,`no face mesh`)}try{let t=await e.forVisionTasks(`https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision/wasm`);Vp(),Up=await n.createFromOptions(t,{baseOptions:{modelAssetPath:`https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/float16/1/efficientdet_lite0.tflite`,delegate:`GPU`},scoreThreshold:.5,maxResults:5,runningMode:`VIDEO`}),console.log(`[AR Vision] Object detector initialized.`)}catch(e){Up=null,console.warn(`[AR Vision] Object detector unavailable, continuing without it:`,e),T(`status-tracking`,`no object detect`)}P(Kp)}async function Kp(){if(!Wp)return;let e=gt();if(e){let t=e.source;try{if(Hp&&await Hp.send({image:t}),Up){let e=Up.detectForVideo(t,performance.now());e.detections.length>0&&window.dispatchEvent(new CustomEvent(`ar-object-detections`,{detail:e.detections}))}}catch(e){console.warn(`Vision frame skipped:`,e)}}P(Kp)}var qp=.6,Jp=new Map([[`wrist`,0],[`thumb-metacarpal`,1],[`thumb-phalanx-proximal`,2],[`thumb-phalanx-distal`,3],[`thumb-tip`,4],[`index-finger-phalanx-proximal`,5],[`index-finger-phalanx-intermediate`,6],[`index-finger-phalanx-distal`,7],[`index-finger-tip`,8],[`middle-finger-phalanx-proximal`,9],[`middle-finger-phalanx-intermediate`,10],[`middle-finger-phalanx-distal`,11],[`middle-finger-tip`,12],[`ring-finger-phalanx-proximal`,13],[`ring-finger-phalanx-intermediate`,14],[`ring-finger-phalanx-distal`,15],[`ring-finger-tip`,16],[`pinky-finger-phalanx-proximal`,17],[`pinky-finger-phalanx-intermediate`,18],[`pinky-finger-phalanx-distal`,19],[`pinky-finger-tip`,20]]),Yp=!1,Xp=0,Zp=16;function Qp(e,t){let n=e?.session;if(!n)return;let r=t?.xr?.getReferenceSpace?.();if(!r)return;let i=performance.now();if(i-Xp<Zp)return;Xp=i;let a=[];for(let t of n.inputSources){if(!t.hand)continue;let n=$p(e,t.hand,r);n&&a.push(n)}if(!a.length){D.handState.hands.length&&(D.handState.hands=[],D.handState.gestures=new Map);return}Yp||(Yp=!0,F(`webXRHandTracking`,!0),k(`xr-hands-detected`,{count:a.length})),D.handState.hands=a;let o=Pc(a);D.handState.gestures=o;for(let[e,t]of o)k(`gesture-${e}`,{...t,source:`webxr-hands`})}function $p(e,t,n){let r=Array(21),i=0;for(let[a,o]of Jp){let s=t.get(a);if(!s)continue;let c=e.getJointPose?.(s,n);if(!c)continue;let l=c.transform.position;r[o]={x:.5+l.x/qp,y:.5-l.y/qp,z:l.z/qp},i+=1}return i<15||!r[0]||!r[4]||!r[8]?null:r}function em(){Yp=!1,Xp=0,D.handState.hands=[],D.handState.gestures=new Map}var Q={active:!1,binding:null,depthTexture:null,uniforms:null,patched:new WeakSet,renderer:null},tm=`
uniform sampler2D uDepthTexture;
uniform mat4 uUvTransform;
uniform float uRawValueToMeters;
uniform float uDepthActive;
varying vec4 vOcclClip;
varying float vOcclEyeDepth;
`,nm=`
if (uDepthActive > 0.5) {
vec2 ndc = (vOcclClip.xy / vOcclClip.w) * 0.5 + 0.5;
vec2 depthUv = (uUvTransform * vec4(ndc, 0.0, 1.0)).xy;
if (depthUv.x >= 0.0 && depthUv.x <= 1.0 && depthUv.y >= 0.0 && depthUv.y <= 1.0) {
float realDepth = dot(texture2D(uDepthTexture, depthUv).ra, vec2(255.0, 65280.0)) * uRawValueToMeters;
// Real surface closer than this fragment (with a small bias) → occluded.
if (realDepth > 0.0 && realDepth < vOcclEyeDepth - 0.02) discard;
}
}
`;function rm(e,t,n={}){if(n.occlusion===!1||!e||!t)return!1;if(t.depthUsage!==`gpu-optimized`||typeof globalThis.XRWebGLBinding!=`function`)return F(`depthOcclusion`,!1),!1;try{let n=e.getContext();Q.binding=new globalThis.XRWebGLBinding(t,n),Q.renderer=e;let r=new Ie;r.minFilter=u,r.magFilter=u,r.generateMipmaps=!1,r.flipY=!1,Q.depthTexture=r,Q.uniforms={uDepthTexture:{value:r},uUvTransform:{value:new a},uRawValueToMeters:{value:.001},uDepthActive:{value:0}},Q.active=!0,D.occlusion={active:!0,disable:am},F(`depthOcclusion`,!0);for(let e of D.placedObjects||[])om(e);return O(`object-placed`,e=>om(e?.object)),t.addEventListener(`end`,am,{once:!0}),w(`Depth occlusion active — virtual objects hide behind real surfaces (Quest depth sensing).`,`Occlusion`),!0}catch(e){return console.warn(`Depth occlusion init failed; continuing without it:`,e?.message||e),am(),!1}}function im(e,t){if(!(!Q.active||!e||!t))try{let e=Q.binding.getDepthInformation(t);if(!e||!e.texture){Q.uniforms.uDepthActive.value=0;return}let n=Q.renderer.properties.get(Q.depthTexture);n.__webglTexture=e.texture,n.__webglInit=!0,Q.uniforms.uUvTransform.value.fromArray(e.normDepthBufferFromNormView.matrix),Q.uniforms.uRawValueToMeters.value=e.rawValueToMeters,Q.uniforms.uDepthActive.value=1}catch{Q.uniforms.uDepthActive.value=0}}function am(){Q.active=!1,Q.uniforms&&(Q.uniforms.uDepthActive.value=0),D.occlusion&&(D.occlusion.active=!1),F(`depthOcclusion`,!1)}function om(e){!Q.active||!e?.traverse||e.traverse(e=>{if(!e.isMesh)return;let t=Array.isArray(e.material)?e.material:[e.material];for(let e of t)sm(e)})}function sm(e){if(!e||Q.patched.has(e)||!e.isMeshStandardMaterial&&!e.isMeshPhysicalMaterial&&!e.isMeshLambertMaterial&&!e.isMeshPhongMaterial)return;Q.patched.add(e);let t=e.onBeforeCompile;e.onBeforeCompile=(e,n)=>{typeof t==`function`&&t(e,n),Object.assign(e.uniforms,Q.uniforms),e.vertexShader=e.vertexShader.replace(`#include <common>`,`#include <common>
varying vec4 vOcclClip;
varying float vOcclEyeDepth;`).replace(`#include <project_vertex>`,`#include <project_vertex>
vOcclClip = gl_Position;
vOcclEyeDepth = -mvPosition.z;`),e.fragmentShader=e.fragmentShader.replace(`#include <common>`,tm+`
#include <common>`).replace(`#include <dithering_fragment>`,nm+`
#include <dithering_fragment>`)},e.needsUpdate=!0}window.THREE=pe,window.addEventListener(`deviceorientation`,e=>{if(globalThis.JARVIS_AR&&globalThis.JARVIS_AR.runtime&&globalThis.JARVIS_AR.runtime.camera){let{alpha:t,beta:n,gamma:r}=e;if(t!=null&&n!=null&&r!=null){let e=new window.THREE.Euler(Xe.degToRad(n),Xe.degToRad(t),Xe.degToRad(-r),`YXZ`);globalThis.JARVIS_AR.runtime.camera.quaternion.setFromEuler(e)}}});var $=Kt();D.config=$;try{globalThis.JARVIS_AR=D,globalThis.JarvisWebAR={state:D,start:wm,resume:Pm,pause:Fm,destroy:Im,setNativeOptions:Rm,applyNativeState:zm,command:qm,spawn:e=>k(`spawn-model`,{query:e})}}catch{}var cm=0,lm=!1,um=null,dm=!1,fm=!1,pm=!1,mm=!1,hm=null,gm=new Promise(e=>{hm=e}),_m=!1;function vm(){lm=!0,hm?.(!0),vt(cm),E(`8th Wall engine loaded.`,30),$.autoStart||at(`Engine ready`),$.autoStart&&wm()}ym();function ym(){if(mm)return;if(mm=!0,document.visibilityState===`visible`){bm();return}E(`Waiting for this tab to become visible...`,8);let e=()=>{document.visibilityState===`visible`&&(document.removeEventListener(`visibilitychange`,e),bm())};document.addEventListener(`visibilitychange`,e)}async function bm(){if(pm)return;if(document.visibilityState!==`visible`){ym();return}if(pm=!0,mt(`ar-core`,{entrypoint:`ar-core/ar-init.js`,force:!0}),ft(`booting`),A(`booting`),document.body.dataset.jarvisBoot=`booting`,D.telemetry.startedAt=performance.now(),E(`Running AR preflight audit...`,10),!Gt()){ft(`blocked`,{reason:`https-required`}),A(`blocked`,{reason:`https-required`});return}await xm($),Bm(),M(`capability-matrix`,`ready`,D.capabilities),xn(),M(`panels`,`ready`),Nl(),M(`vr`,`ready`),Xu(),Sd(),M(`media-viewer`,`ready`),Ii(),M(`spatial-audio`,`ready`),Ld(),M(`reconstruction`,`ready`),M(`physics`,`initializing`);let e=()=>{ia().then(()=>M(`physics`,`ready`)).catch(e=>{console.error(`[AR Physics] initialization failed — physics disabled:`,e),M(`physics`,`failed`,{error:String(e?.message||e)})})};typeof requestIdleCallback==`function`?requestIdleCallback(e,{timeout:5e3}):setTimeout(e,2e3),Gp(),M(`vision`,`ready`),Um(),Cm(),Vm(),await en($);try{t(async()=>{let{initVrStereoSplitScreen:e}=await import(`./ar-compositor-BL0mQ4V3.js`);return{initVrStereoSplitScreen:e}},[],import.meta.url).then(({initVrStereoSplitScreen:e})=>{let{renderer:t,scene:n,camera:r}=I();e(t,n,r),console.log(`V15 AR: Stereo split-screen mounted.`)})}catch(e){console.error(`V15 AR Stereo Mount failed:`,e)}j(`scene`,!0),M(`scene`,`ready`,{renderer:D.runtime.rendererOwner}),sn(),M(`adaptive-quality`,`ready`),zt(I(),{mode:`boot-proxy`,tier:D.telemetry.qualityTier||`medium`}),wo(),M(`models`,`ready`),Hm(),M(`jarvis`,`ready`),E(`Waiting for 8th Wall engine binary...`,22),_m||(_m=!0,window.addEventListener(`xrloaded`,vm,{once:!0})),globalThis.XR8&&(lm=!0,hm?.(!0),vt(cm),E(`8th Wall engine loaded.`,30),$.autoStart||at(`Engine ready`),$.autoStart&&wm()),cm=_t(()=>{lm||w(`8th Wall is still loading. Holding real AR start instead of silently dropping into basic camera mode.`,`8th Wall Loading`)},4500),$.command&&(D._commandBootTimer=_t(()=>qm($.command),1200)),document.body.dataset.jarvisBoot=`ready`,j(`boot`,!0),j(`ui`,!0),ft(`ready`),A(`ready`)}function xm(e={}){if(globalThis.XR8)return Promise.resolve(!0);let t=document.getElementById(`jarvis-xr-static`);return t?t.dataset.loadFailed===`true`?Sm(e):new Promise(n=>{t.addEventListener(`load`,()=>{n(!0)},{once:!0}),t.addEventListener(`error`,()=>{t.dataset.loadFailed=`true`,Sm(e).then(n)},{once:!0})}):Sm(e)}function Sm(e={}){if(globalThis.XR8)return Promise.resolve(!0);let t=String(e.xrScriptUrl||``).trim();return t?document.querySelector(`script[data-jarvis-xr-script]`)?Promise.resolve(!0):new Promise(e=>{let n=document.createElement(`script`);n.src=t,n.async=!0,n.defer=!0,n.crossOrigin=`anonymous`,n.dataset.jarvisXrScript=`true`,n.setAttribute(`data-preload-chunks`,`slam`),n.addEventListener(`load`,()=>e(!0),{once:!0}),n.addEventListener(`error`,()=>{w(`Configured 8th Wall binary failed to load. The runtime will fall back instead of hanging on a dead CDN pin.`,`8th Wall Loading`),e(!1)},{once:!0}),document.head.appendChild(n)}):Promise.resolve(!1)}function Cm(){document.getElementById(`start-ar`)?.addEventListener(`click`,e=>{let t=e.currentTarget;t.disabled=!0,t.textContent=`STARTING...`,wm()}),document.getElementById(`camerafeed`)?.addEventListener(`click`,()=>{D.started||wm()})}async function wm(){return dm||um?um:D.runtime.lifecycleState===`running`?!0:(dm=!0,mt(`ar-core`,{entrypoint:`ar-core/ar-init.js`}),ft(`starting`),A(`starting`),E(`Starting real AR camera...`,34),D._cameraAcquired=!1,um=(async()=>{try{let e=await Tm(3e4);return D._commandBootTimer&&(vt(D._commandBootTimer),D._commandBootTimer=null),e&&Em()?await Dm():e?(C(`This device or browser is not supported by the 8th Wall SLAM engine (it needs a mobile browser with motion sensors). Running the fallback tracking path instead.`,`Using fallback tracking`,{timeout:0}),await Am()):(C(`8th Wall engine binary did not load within 30 seconds. Running fallback with reduced tracking.`,`8th Wall Timeout`,{timeout:0}),await Am()),Sn(),kc().catch(e=>C(e.message,`Gesture Startup Failed`)),kp(),fn(),D.started=!0,j(`camera`,!!(D.cameraVideo||D.xrStarted||D.xrSession)),j(`tracking`,!!(D.trackingMode&&D.trackingMode!==`standby`)),ft(`running`,{trackingMode:D.trackingMode}),A(`running`,{trackingMode:D.trackingMode}),kt(`AR runtime started: ${D.trackingMode}`),!0}catch(e){D.runtime.lastError=e?.message||String(e),D.runtime.degradationReason=D.runtime.lastError,ft(`degraded`,{error:D.runtime.lastError}),A(`degraded`,{error:D.runtime.lastError}),C(e.message,`AR Startup Failed`,{timeout:0}),D._commandBootTimer&&(vt(D._commandBootTimer),D._commandBootTimer=null);let t=await Nm();return Sn(),t?(D.started=!0,j(`camera`,!0),j(`tracking`,!0),A(`degraded-running`,{trackingMode:D.trackingMode,reason:D.runtime.degradationReason}),!0):(D.started=!1,um=null,A(`failed`,{error:D.runtime.lastError}),!1)}finally{dm=!1}})(),um)}async function Tm(e){if(globalThis.XR8&&lm)return!0;E(`Waiting for 8th Wall SLAM engine...`,36);let t=new Promise(t=>_t(()=>t(!1),e));return!!(await Promise.race([gm,t])&&globalThis.XR8)}function Em(){try{let e=globalThis.XR8?.XrDevice;if(!e?.isDeviceBrowserCompatible||e.isDeviceBrowserCompatible())return!0;let t=``;try{let n=e.incompatibleReasons?e.incompatibleReasons():null,r=e.deviceEstimate?e.deviceEstimate():null;t=` (reasons: ${JSON.stringify(n)}, os: ${r?.os||`unknown`})`}catch{}return console.warn(`[AR] 8th Wall reports this device/browser is unsupported${t}. Using the fallback tracking path.`),D.runtime.degradationReason=`8thwall-device-unsupported`,!1}catch{return!0}}async function Dm(){let e=globalThis.XR8;if(!e?.GlTextureRenderer?.pipelineModule)throw Error(`XR8.GlTextureRenderer.pipelineModule() is missing.`);if(!e?.Threejs?.pipelineModule)throw Error(`XR8.Threejs.pipelineModule() is missing.`);let t=document.getElementById(`camerafeed`);if(!t)throw Error(`Camera feed canvas was not found.`);e.addCameraPipelineModule({name:`app-camera-status`,onCameraStatusChange:({status:e})=>{e===`requesting`?(E(`Allow camera access to start AR...`,40),T(`status-camera`,`requesting`)):e===`hasStream`?(E(`Camera stream acquired. Initializing SLAM...`,52),T(`status-camera`,`stream`),D.runtime.permissionState=`granted`,D._cameraAcquired=!0,j(`camera`,!0)):e===`hasVideo`?(D._cameraAcquired=!0,E(`Camera live. Tracking world points...`,76),T(`status-camera`,`live`),D.runtime.permissionState=`granted`,j(`camera`,!0),ot()):e===`failed`&&(T(`status-camera`,`failed`),D.runtime.permissionState=`denied-or-failed`,D.runtime.degradationReason=`camera failed`,A(`permission-blocked`,{source:`xr8-camera`}),C(`Camera access failed. Check browser settings and allow camera for this browser.`,`Camera Failed`,{timeout:0,linkHref:`intent://settings#Intent;scheme=android-app;end`,linkLabel:`Open Chrome Android settings`}))}});let n=[e.GlTextureRenderer.pipelineModule(),Ut.FullWindowCanvas.pipelineModule(),e.Threejs.pipelineModule(),e.XrController.pipelineModule({enableWorldPoints:!0,disableWorldTracking:!1,imageTargets:Array.isArray($.imageTargets)?$.imageTargets:[]}),...e.CameraPixelArray?.pipelineModule?[e.CameraPixelArray.pipelineModule({maxDimension:480}),Xc()]:[],Ut.AlmostThere.pipelineModule(),Ut.Loading.pipelineModule(),Ut.RuntimeError.pipelineModule(),Ad(),Xd()];D.pipelineOrder=[`app-camera-status`,`XR8.GlTextureRenderer`,...n.slice(1).map(e=>e.name)],D.trackingAPI={getTrackingQuality:pf,registerAnchor:cf,unregisterAnchor:lf,performHitTest:ff,requestRelocalization:mf},e.addCameraPipelineModules(n),e.run({canvas:t,webgl2:!0,ownRunLoop:!0,glContextConfig:{alpha:!0,preserveDrawingBuffer:!0,powerPreference:`high-performance`},cameraConfig:{direction:e.XrConfig.camera().BACK}}),D.xrStarted=!0,D.xrAvailable=!0,F(`eightWallSLAM`,!0),D.trackingMode=`8thwall-slam`,await Om(12e3),await km();let r=Pt()||I();ht(`xr8-threejs`,r,{takeover:!0,engine:`8thwall-slam`}),zt(r,{mode:`xr8-session`,session:D.xrSession,tier:D.telemetry.qualityTier||`high`,stereo:!1,depthComposition:!0,frameBudgetMs:13.5,guardianProxy:!!$.guardianProxy}),M(`xr8`,`running`,{pipelineOrder:D.pipelineOrder}),an(r.renderer,$),dn(r.scene),Ft(r),j(`tracking`,!0),document.body.dataset.jarvisTracking=`8thwall-slam`,T(`status-tracking`,`8th wall`),nn(),ot(),w(`8th Wall SLAM path started. Camera texture renderer is first in the render pipeline.`)}async function Om(e){if(D._cameraAcquired)return!0;let t=performance.now();for(;performance.now()-t<e;){if(D._cameraAcquired)return!0;if(D.runtime.permissionState===`denied-or-failed`)throw Error(`Camera access was denied or failed.`);await new Promise(e=>_t(e,250))}throw Error(`The camera did not start within ${Math.round(e/1e3)}s. The AR engine could not obtain a rear-facing camera stream.`)}async function km(e=2200){let t=0,n=performance.now();for(;performance.now()-n<e&&t<132;){try{let e=globalThis.XR8?.Threejs?.xrScene?.();if(e?.scene&&e?.camera&&e?.renderer)return e}catch{}t++,await new Promise(e=>requestAnimationFrame(e))}return t>=132&&console.warn(`Timed out without a valid XR scene — returning null.`,132),null}async function Am(){if(D.trackingMode=`webxr-fallback`,document.body.dataset.jarvisTracking=`webxr-fallback`,T(`status-tracking`,`webxr/basic`),!(`xr`in navigator&&navigator.xr))return Nm();try{if(!await navigator.xr.isSessionSupported(`immersive-ar`))return Nm();let{renderer:e}=I(),t=await Promise.race([navigator.xr.requestSession(`immersive-ar`,{requiredFeatures:[`hit-test`],optionalFeatures:[`dom-overlay`,`light-estimation`,`depth-sensing`,`local-floor`,`anchors`,`bounded-floor`,`hand-tracking`,`unbounded`],depthSensing:{usagePreference:[`gpu-optimized`],dataFormatPreference:[`luminance-alpha`]},domOverlay:{root:document.getElementById(`ui-layer`)}}),new Promise((e,t)=>_t(()=>t(Error(`WebXR session request timed out`)),5e3))]);e.xr.enabled=!0,e.xr.setSession(t),jm(e,t),Mm(e,t),rm(e,t,$);let n=await t.requestReferenceSpace(`viewer`);return D.xrHitTestSource=await t.requestHitTestSource({space:n}),D.xrSession=t,t.addEventListener(`end`,()=>{if(D.xrSession===t){D.xrSession=null,D.xrStarted=!1;try{e.setAnimationLoop(null)}catch{}em(),Mt(),D.started&&A(`degraded`,{reason:`webxr-session-ended`})}},{once:!0}),ht(`webxr-threejs`,{scene:D.scene,camera:D.camera,renderer:e},{takeover:!0,engine:`webxr-fallback`}),zt({scene:D.scene,camera:D.camera,renderer:e},{mode:`webxr-session`,session:t,stereo:!1,depthComposition:!0,source:D.cameraVideo||document.getElementById(`camerafeed`)}),M(`webxr`,`running`),F(`webXRHitTest`,!0),Nt(),e.setAnimationLoop((t,n)=>{if(n&&(D.xrFrame=n,Qp(n,e),D.occlusion?.active)){let t=e.xr.getReferenceSpace?.(),r=t?n.getViewerPose?.(t):null;r?.views?.length&&im(n,r.views[0])}let r=D.scene||D.fallbackScene,i=D.camera||D.fallbackCamera;r&&i&&e.render(r,i)}),Ft(I()),j(`camera`,!0),j(`tracking`,!0),ot(),w(`Running WebXR fallback. 8th Wall SLAM is not active in this session.`),!0}catch(e){return C(e.message,`WebXR Fallback Failed`),Nm()}}function jm(e,t){try{let n=D.scene||I()?.scene;if(!n||!e)return;let r=new we(e);D.xrEstimatedLight=r;let i=n.environment;r.addEventListener(`estimationstart`,()=>{n.add(r),i=n.environment,r.environment&&(n.environment=r.environment),D.telemetry.iblEnvironment=`xr-light-estimation`,F(`lightEstimation`,!0)}),r.addEventListener(`estimationend`,()=>{try{n.remove(r)}catch{}n.environment=i,D.telemetry.iblEnvironment=n.userData?.jarvisEnvironmentSource||`room-default`}),t.addEventListener(`end`,()=>{try{n.remove(r)}catch{}n.environment=i,D.xrEstimatedLight=null},{once:!0})}catch(e){console.warn(`XR light estimation setup failed:`,e?.message||e)}}function Mm(e,t){let n=t=>{try{let n=D.xrFrame,r=e?.xr?.getReferenceSpace?.(),i=t.inputSource,a=i?.targetRaySpace;if(!n||!r||!a)return;let o=n.getPose?.(a,r);if(!o)return;let s=o.transform.matrix,c={x:s[12],y:s[13],z:s[14]},l={x:-s[8],y:-s[9],z:-s[10]};try{i.gamepad?.hapticActuators?.[0]?.pulse?.(.4,40)}catch{}let u=Os({origin:c,direction:l});u&&(D.telemetry.lastXRSelect=u.type)}catch(e){console.warn(`XR select handling failed:`,e?.message||e)}};t.addEventListener(`select`,n),t.addEventListener(`end`,()=>{try{t.removeEventListener(`select`,n)}catch{}},{once:!0})}async function Nm(){D.trackingMode=`manual-camera`,F(`manualCamera`,!0),document.body.dataset.jarvisTracking=`manual-camera`,T(`status-tracking`,`basic camera`),E(`Starting basic camera mode...`,48);try{Lm();let e=await navigator.mediaDevices.getUserMedia({video:{facingMode:{ideal:`environment`},width:{ideal:1280},height:{ideal:720},frameRate:{ideal:30}},audio:!1}),t=document.createElement(`video`);t.srcObject=e,t.autoplay=!0,t.playsInline=!0,t.muted=!0,t.setAttribute(`playsinline`,``),t.style.cssText=`position:fixed;top:0;left:0;width:100vw;height:100vh;object-fit:cover;z-index:0;background:#000`,document.body.insertBefore(t,document.body.firstChild),await t.play(),D.cameraVideo=t,D.runtime.permissionState=`granted`;try{return ht(`fallback-three`,I(),{takeover:D.runtime.rendererOwner!==`xr8-threejs`,engine:`manual-camera`}),M(`manual-camera`,`running`),zt(I(),{mode:`manual-camera`,stereo:!1,source:D.cameraVideo||document.getElementById(`camerafeed`),frameBudgetMs:20}),Mt(),Ft(I()),T(`status-camera`,`live`),j(`camera`,!0),j(`tracking`,!0),ot(),w(`Basic camera mode is active. Surface placement uses estimated floor fallback.`),!0}catch(e){return D.runtime.permissionState=`failed`,D.runtime.degradationReason=e?.message||String(e),C(`Manual camera fallback setup failed: ${e?.message||String(e)}`,`Manual Camera Setup Failed`,{timeout:0}),Lm(),!1}}catch(e){return D.runtime.permissionState=e.name===`NotAllowedError`?`denied`:`failed`,D.runtime.degradationReason=e?.message||String(e),A(e.name===`NotAllowedError`?`permission-blocked`:`failed`,{error:D.runtime.degradationReason}),e.name===`NotAllowedError`?C(`Camera permission denied. Please allow camera access.`,`Camera Denied`,{timeout:0}):e.name===`NotFoundError`?C(`No camera found on this device.`,`Camera Missing`,{timeout:0}):C(`Camera error: ${e.message}`,`Camera Error`,{timeout:0}),!1}}function Pm(){if(D.runtime.lifecycleState===`stopped`)return!1;if(D.paused=!1,D.xrStarted)try{globalThis.XR8?.resume?.()}catch{w(`8th Wall resume was not available in this browser session.`,`Lifecycle`)}try{D.cameraVideo?.play?.()}catch{}return!D.xrStarted&&D.fallbackRenderer&&Mt(),document.body.dataset.jarvisPaused=`false`,fn(),A(D.started?`running`:`ready`,{reason:`resume`}),kt(`AR runtime resumed`),!0}function Fm(e=`manual`){if(D.paused=!0,D.xrStarted)try{globalThis.XR8?.pause?.()}catch{w(`8th Wall pause was not available in this browser session.`,`Lifecycle`)}try{D.cameraVideo?.pause?.()}catch{}return Nt(),document.body.dataset.jarvisPaused=`true`,A(`paused`,{reason:e}),kt(`AR runtime paused`),!0}async function Im(){Fm(`shutdown`),D._commandBootTimer&&(vt(D._commandBootTimer),D._commandBootTimer=null),jc(),Zl(),Nn(),hf(),Nt();try{await D.xrSession?.end?.()}catch{}try{let e=I()?.renderer;e?.xr&&await e.xr.setSession(null)}catch{}try{typeof globalThis.XR8?.clearCameraPipelineModules==`function`&&globalThis.XR8.clearCameraPipelineModules(),globalThis.XR8?.stop?.()}catch{}return Lm(),document.querySelectorAll(`#ui-layer .ar-panel, #ui-layer .panel-orb, #error-host > *, #banner-host > *`).forEach(e=>e.remove()),Vt(),pt(),um=null,kt(`AR runtime shut down`),!0}function Lm(){try{(D.cameraVideo?.srcObject)?.getTracks?.().forEach(e=>e.stop()),D.cameraVideo?.remove?.()}catch{}D.cameraVideo=null}function Rm(e={}){D.nativeOptions={...D.nativeOptions,...e&&typeof e==`object`?e:{}},document.body.dataset.jarvisNativeOptions=`applied`,D.nativeOptions.handTrackingEnabled===!1&&w(`Native options disabled hand tracking for this AR session.`,`APK Options`),(D.nativeOptions.thermalPause===!0||D.nativeOptions.thermalState===`critical`)&&(Fm(`thermal`),D.runtime.degradationReason=`thermal`,A(`thermal-paused`,{thermalState:D.nativeOptions.thermalState||`critical`}));for(let e of[`eyeTracking`,`nativeCompositor`,`truePersistentWorldAnchors`,`nativeOpenXRBridge`])Object.prototype.hasOwnProperty.call(D.nativeOptions,e)&&F(e,D.nativeOptions[e]);return Object.prototype.hasOwnProperty.call(D.nativeOptions,`truePersistentWorldAnchors`)&&F(`persistentAnchorSupport`,D.nativeOptions.truePersistentWorldAnchors),Ot(`setCompositorState`,JSON.stringify({mode:D.compositor.mode,native:D.compositor.native,passthroughBlend:D.compositor.passthroughBlend,frameBudgetMs:D.compositor.frameBudgetMs,browserManaged:!0})),k(`native-options`,D.nativeOptions),kt(`APK AR options applied`),D.nativeOptions}function zm(e={}){let t=e;try{t=typeof e==`string`?JSON.parse(e):e}catch(e){return C(e.message,`APK State Sync Failed`),!1}let n=Array.isArray(t)?t:Array.isArray(t?.objects)?t.objects:t?.ar_objects;return Array.isArray(n)&&(k(`native-ar-state`,{objects:n}),Ot(`status`,`Applied ${n.length} native AR object(s)`)),t?.ui&&typeof t.ui==`object`&&k(`native-ui-state`,t.ui),!0}function Bm(){let e=Qt();wt(e),D.runtime.browserProfile=e,F(`mediaPipeHands`,!!globalThis.Hands),F(`spatialAudio`,!!(globalThis.AudioContext||globalThis.webkitAudioContext)),F(`microphone`,!!navigator.mediaDevices?.getUserMedia),F(`speechSynthesis`,!!window.speechSynthesis),F(`voiceRecognition`,!!(globalThis.SpeechRecognition||globalThis.webkitSpeechRecognition)),F(`webXRAvailable`,!!navigator.xr),F(`webXRHitTest`,!1),F(`browserLatencyCeiling`,!0),F(`limitedSensorAccess`,!0),F(`limitedOSIntegration`,!0),F(`limitedCompositorControl`,!0),F(`persistentAnchorSupport`,!!$.truePersistentWorldAnchors),F(`backgroundExecutionLimited`,!0),F(`passthroughControlLimited`,!0),F(`spatialMemoryLimited`,!0),F(`headsetOptimizationAccessLimited`,!0),F(`webXRFragmented`,e.webXRFragmented),F(`safariWebXRLimitations`,e.limits.safariWebXRLimitations),F(`visionOSBrowserRestrictions`,e.limits.visionOSBrowserRestrictions),F(`androidBrowserInconsistency`,e.limits.androidBrowserInconsistency),F(`webViewInconsistency`,e.limits.webViewInconsistency),F(`questBrowserQuirks`,e.limits.questBrowserQuirks),F(`fullscreenEdgeCases`,e.limits.fullscreenEdgeCases),F(`orientationLockEdgeCases`,e.limits.orientationLockEdgeCases),F(`webglContextLossRisk`,e.limits.webglContextLossRisk),F(`renderLoopDuplicationRisk`,e.limits.renderLoopDuplicationRisk),F(`eyeTracking`,!!$.eyeTracking),F(`nativeCompositor`,!!$.nativeCompositor),F(`truePersistentWorldAnchors`,!!$.truePersistentWorldAnchors),F(`nativeOpenXRBridge`,!!$.nativeOpenXRBridge),F(`eyeTrackingProxy`,!0),F(`persistentSpatialMemory`,!0),F(`ultraStableAnchoring`,!0),F(`naturalWindowPlacement`,!0),F(`depthAwareImmersion`,!0),F(`environmentAwareUI`,!0),F(`headsetComfortSystems`,!0),F(`lowLatencyCompositing`,!0),document.body.dataset.jarvisCapabilityModel=`browser-web-ar-with-explicit-native-limits`,document.body.dataset.jarvisBrowserProfile=e.browser,document.body.dataset.jarvisBrowserPlatform=e.platform,document.body.dataset.jarvisBrowserLatency=String(e.latencyCeilingMs);let t=$t(e).filter(e=>/safari|visionos|android|webview|webxr-fragmented|quest/.test(e));Tt({architecture:`browser-web-ar-runtime`,experienceClass:`web-ar-experiment`,spatialRuntimeClass:e.isVisionOS?`browser-managed-visionos-shell`:e.isQuest?`quest-browser-ar-shell`:e.isSafari?`safari-webxr-shell`:e.isWebView?`embedded-webview-ar-shell`:`browser-web-ar-shell`,platformRole:e.isVisionOS?`visionos-browser`:e.isQuest?`quest-browser`:e.isAndroid?`android-browser`:e.isIOS?`ios-browser`:`desktop-browser`,spatialGapStatement:e.isVisionOS||e.isSafari||e.isWebView||e.isAndroid?`This runtime is browser-managed spatial AR, not a native headset OS, compositor, or persistent spatial shell.`:`This runtime is browser-managed spatial AR, not a unified native spatial computing runtime.`}),Et([`No single authoritative native spatial runtime exists in this codebase.`,`Browser-layer AR, XR8/WebXR, fallback cameras, and compatibility shells coexist behind one shared authority instead of a native OS compositor stack.`,`Persistent world understanding, headset compositor control, and headset-grade platform integration remain unavailable because the runtime is bounded by browser APIs and vendor binaries.`,`Lifecycle and rendering governance must therefore be centralized in the web runtime, not spread across competing engines.`].join(` `)),Dt(`Vision Pro-style browser shell implemented as far as the web stack allows: gaze proxy, hand-eye fusion, persistent spatial memory, stabilized anchoring, low-latency compositor hints, natural window placement, depth-aware immersion, environment-aware UI, and comfort systems are active; true native eye tracking, headset OS integration, and native compositor control remain outside the browser runtime.`,[`gaze proxy`,`hand-eye fusion`,`persistent spatial memory`,`ultra-stable anchoring`,`low-latency compositing proxy`,`natural window placement`,`depth-aware immersion`,`environment-aware UI`,`headset comfort systems`]),Ot(`setNativeCapabilities`,JSON.stringify({browserProfile:e,capabilities:D.capabilities,runtime:{architecture:D.runtime.architecture,spatialRuntimeClass:D.runtime.spatialRuntimeClass,platformRole:D.runtime.platformRole}})),Ot(`setGuardianState`,JSON.stringify({requested:!0,boundary:D.capabilities.guardianBoundary,platformRole:D.runtime.platformRole,source:`ar-init`})),Ot(`setOpenXRState`,JSON.stringify({supported:e.isQuest||e.isVisionOS,browserManaged:!0,platformRole:D.runtime.platformRole,compositor:D.compositor})),t.length&&(D.runtime.degradationReason=t.join(`, `),kt(`Browser limits: ${t.join(`, `)}`),e.limits.visionOSBrowserRestrictions?w(`visionOS browser support is browser-managed only. Native compositor, passthrough control, and persistent anchors stay unavailable here.`,`visionOS Browser Limits`):e.limits.safariWebXRLimitations?w(`Safari WebXR support is fragmented. Chrome Android remains the primary AR path for this runtime.`,`Safari WebXR Limits`):e.limits.webViewInconsistency?w(`Embedded WebViews can be stricter than Chrome Custom Tabs for XR, sensors, and camera permissions.`,`WebView Limits`):e.limits.questBrowserQuirks&&w(`Quest Browser fullscreen, orientation, and session behavior can be quirky; the runtime is applying extra guard rails.`,`Quest Browser Limits`))}function Vm(){fm||(fm=!0,document.addEventListener(`visibilitychange`,()=>{document.hidden?D.started&&Fm(`background-tab`):D.started&&D.runtime.lifecycleState===`paused`&&Pm()}),window.addEventListener(`pagehide`,()=>{D.started&&Fm(`pagehide`)}),window.addEventListener(`pageshow`,()=>{D.started&&D.runtime.lifecycleState===`paused`&&Pm()}))}function Hm(){let e=new $f($).connect();Op();try{globalThis.Jarvis={query:t=>e.query(t),runTask:(t,n)=>e.runTask(t,n),command:e=>qm(e)}}catch{D.jarvisGlobalBlocked=!0}O(`jarvis-command`,({text:e})=>qm(e))}function Um(){O(`VOICE_STATE`,e=>{D.spatialAudio.micPermission=e?.micPermission||D.spatialAudio.micPermission,D.spatialAudio.micReady=!!(e?.micReady||e?.enabled||e?.listening),D.spatialAudio.wakeWindowUntil=e?.wakeWindowUntil||0,D.spatialAudio.lastVoiceCommandAt=e?.lastCommandAt||D.spatialAudio.lastVoiceCommandAt,(e?.reason===`mic-error`||e?.reason===`blocked`)&&kt(`Voice mic ${e.error||e.micPermission||`blocked`}`)}),O(`open-jarvis`,Wm),O(`open-games`,Gm),O(`open-builder`,If),O(`scan-room`,()=>hp(`Scanning the room.`,{speak:!1}))}function Wm(){let e=document.createElement(`div`),t=document.createElement(`input`),n=document.createElement(`button`);t.placeholder=`Command JARVIS`,n.className=`btn-primary`,n.textContent=`Run`,n.onclick=()=>qm(t.value),t.addEventListener(`keydown`,e=>{e.key===`Enter`&&n.click()}),e.append(t,n),new bn({title:`JARVIS`,body:e,icon:`J`,width:360,height:260}).focus()}function Gm(){let e=document.createElement(`div`),t=Km(`Eternum AR`,vf),n=Km(`Ripples AR`,Cf),r=document.createElement(`input`),i=Km(`Convert Game URL`,()=>wf(r.value||`about:blank`,globalThis.Jarvis||D.jarvis));r.placeholder=`Game URL or name`,e.append(t,n,r,i),Pn(`AR Games`,e,`G`)}function Km(e,t){let n=document.createElement(`button`);return n.className=`panel-action`,n.textContent=e,n.onclick=t,n}async function qm(e){let t=String(e||``).trim();if(!t)return;let n=t.toLowerCase();sp(ep.THINKING);try{let e=n.match(/\b(open|close|toggle|rotate|spin|turn|reconfigure|rebuild|transform|rearrange|shatter|break|explode|reveal|show|hide|grab|move|drag)\b/);if(e&&/(model|door|window|screen|panel|roof|drawer|wheel|part|house|room|car|vehicle|device|custom)/.test(n)){let r=n.replace(/\b(hey\s+jarvis|jarvis)\b/gi,``).replace(/\b(open|close|toggle|rotate|spin|turn|reconfigure|rebuild|transform|rearrange|shatter|break|explode|reveal|show|hide|grab|move|drag|the|a|an|model|part|on|of|in|for|to)\b/gi,` `).replace(/\s+/g,` `).trim();k(`jarvis-model-action`,{action:e[1],target:r,command:t,source:`voice`}),hp(`Model action queued: ${e[1]}${r?` on ${r}`:``}.`,{speak:!0});return}if(/spawn|place|load|model/.test(n)){let e=n.replace(/\b(spawn|place|load|model|a|an|the|in ar)\b/g,` `).trim()||`Duck`;k(`spawn-model`,{query:e}),hp(`Model armed: ${e}. Tap a surface to place it.`,{speak:!0});return}if(/scan room|room scan|scan/.test(n)){k(`scan-room`);return}if(/reconstruct/.test(n)){let e=n.replace(`reconstruct`,``).replace(`this scene`,``).trim()||`room`;await Rd(e),hp(`Scene reconstruction complete: ${e}.`,{speak:!0});return}if(/vr mode|vr screen|headset/.test(n)){await Pl();return}if(/eternum/.test(n)){vf(),hp(`Eternum AR panel is open.`,{speak:!0});return}if(/ripples/.test(n)){Cf(),hp(`Ripples AR panel is open.`,{speak:!0});return}if(/convert .* ar|game to ar/.test(n)){await wf(t.replace(/convert|to ar|game to ar/gi,``).trim(),globalThis.Jarvis||D.jarvis);return}if(/open models|model picker/.test(n)){Do();return}if(/forge model|interactive model|3d forge|custom interactive model|build custom model|custom 3d builder/.test(n)){k(`open-model-forge`),hp(`Interactive model forge opened.`,{speak:!0});return}if(/camera kit|lens studio|snap/.test(n)){let e=document.createElement(`div`);e.style.cssText=`display:flex;flex-direction:column;gap:10px;padding:8px 0`;let t=document.createElement(`p`);t.style.cssText=`margin:0;font-size:13px;opacity:0.75;line-height:1.4`,t.textContent=`Lens Studio Camera Kit requires a Snap developer token. Enter yours below to activate the Camera Kit AR layer.`;let n=document.createElement(`label`);n.textContent=`Snap Developer Token`,n.style.cssText=`font-size:12px;font-weight:600;opacity:0.9`;let r=document.createElement(`input`);r.type=`text`,r.placeholder=`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`,r.style.cssText=`width:100%;box-sizing:border-box;padding:8px 10px;border-radius:6px;border:1px solid rgba(255,255,255,0.2);background:rgba(255,255,255,0.08);color:var(--text-primary);font-size:13px`,D.config.snapToken&&(r.value=D.config.snapToken);let i=document.createElement(`button`);i.className=`btn-primary`,i.textContent=`Activate Camera Kit`,i.onclick=()=>{let e=r.value.trim();if(!e){w(`Please enter a valid Snap developer token.`,`Camera Kit`);return}D.config.snapToken=e,k(`camera-kit-token-set`,{token:e}),w(`Camera Kit token saved. Reload the AR session to activate the Lens Studio layer.`,`Camera Kit`),o.close?.()};let a=document.createElement(`a`);a.href=`https://docs.snap.com/snap-kit/camera-kit/guides/tutorials/integration-guides/web#set-up-your-api-token`,a.target=`_blank`,a.rel=`noopener noreferrer`,a.textContent=`How to get a Snap developer token ↗`,a.style.cssText=`font-size:12px;color:rgba(255,255,255,0.55);text-decoration:underline`,e.append(t,n,r,i,a);let o=new bn({title:`Camera Kit`,body:e,icon:`CK`,width:360,height:300});o.focus();return}hp(await(globalThis.Jarvis||D.jarvis).query(t),{speak:!0})}catch(e){C(e.message,`JARVIS Command Failed`)}finally{ap()===ep.THINKING&&sp(ep.IDLE)}}export{zm as applyNativeState,Bt as i,Ht as n,Fm as pauseRuntime,Vt as r,Pm as resumeRuntime,Rm as setNativeOptions,Im as shutdownRuntime,Nm as startManualCameraFallback,zt as t}; |