@cyberart-io/engine 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,4 +5,4 @@
5
5
  * Not an OSI open-source license.
6
6
  */
7
7
 
8
- var Vt=(t,e)=>()=>(t&&(e=t(t=0)),e);var Xt={};function Yt(t,e){let n=t.indexOf(at);if(n===-1)return null;let r=n+at.length,a=`const __cyberSkip=new Set(${JSON.stringify(e)});const __cyberOrig=registerProcessor;registerProcessor=(n,p)=>__cyberSkip.has(n)?undefined:__cyberOrig(n,p);`;return t.slice(0,r)+a+t.slice(r)}var Ee,pe,Jt,ee,at,st=Vt(()=>{"use strict";Ee=/AudioWorkletProcessor with name:\s*["'`][^"'`]+["'`]\s+is already registered/i,pe="__cyberartWorkletPatchApplied";typeof window<"u"&&!window[pe]&&(window.addEventListener("error",t=>{let e=t?.message??"";Ee.test(e)&&(t.preventDefault(),t.stopImmediatePropagation())},!0),window.addEventListener("unhandledrejection",t=>{let e=t?.reason,n=typeof e=="string"?e:e?.message??"";Ee.test(n)&&t.preventDefault()}),window[pe]=!0);Jt=!1,ee=(...t)=>{Jt&&console.log("[workletPatch]",...t)},at="((AudioWorkletProcessor,registerProcessor)=>{";if(typeof AudioWorklet<"u"&&!AudioWorklet.prototype[pe]){let t=new WeakMap,e=/registerProcessor\s*\(\s*['"`]([^'"`]+)['"`]/g,n=AudioWorklet.prototype.addModule,r=0;AudioWorklet.prototype.addModule=async function(a,o){let c=++r,l=t.get(this);l||(l=new Set,t.set(this,l)),ee(`#${c} addModule`,{url:a.slice(0,64),isBlob:a.startsWith("blob:"),knownBefore:[...l]});let y=a,m=null;if(a.startsWith("blob:")){let h=null;try{h=await(await fetch(a)).text()}catch(b){ee(`#${c} blob fetch failed`,b)}if(h!==null){let b=new Set;for(let w of h.matchAll(e))b.add(w[1]);if(b.size>0){let w=[...b].filter(E=>l.has(E)),d=[...b].filter(E=>!l.has(E));if(w.length>0&&d.length===0){ee(`#${c} short-circuit \u2014 all processors already registered`,w);return}if(w.length>0&&d.length>0){let E=Yt(h,w);if(E!==null){let R=new Blob([E],{type:"application/javascript"});m=URL.createObjectURL(R),y=m,ee(`#${c} rewrote blob; skipping`,w,"allowing",d)}else ee(`#${c} blob rewrite failed; passing original through`)}d.forEach(E=>l.add(E))}}}return n.call(this,y,o).then(()=>{m&&URL.revokeObjectURL(m)},h=>{m&&URL.revokeObjectURL(m);let b=(h&&h.message)??"";if(!(Ee.test(b)||/already registered/i.test(b)))throw h})},AudioWorklet.prototype[pe]=!0}});var qe=()=>{let t=["ms","moz","webkit","o"];for(let e=0;e<t.length&&!window.requestAnimationFrame;++e)window.requestAnimationFrame=window[t[e]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[t[e]+"CancelAnimationFrame"]||window[t[e]+"CancelRequestAnimationFrame"]},T=window.devicePixelRatio||1,K=/Headless/i.test(navigator.userAgent),qn=/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)||/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.platform);function Ge(){return Math.min(window.innerWidth,window.innerHeight)}var ie="data-cyberart-canvas",V=class{constructor(e,n,r=1,i={}){this.width=e,this.height=n;let a=i.container,o=i.adoptFromDocument??!a,c=a?a.querySelector(`canvas[${ie}]`)??a.querySelector("canvas"):null;if(c)this.canvas=c,this.adopted=!0;else if(o){let l=document.getElementById("canvas")??document.querySelector("canvas");l?(this.canvas=l,this.adopted=!0):(this.canvas=document.createElement("canvas"),this.canvas.setAttribute("id","canvas"),this.adopted=!1)}else this.canvas=document.createElement("canvas"),this.adopted=!1;this.canvas.hasAttribute(ie)||this.canvas.setAttribute(ie,""),this.canvas.style.display="block",this.canvas.style.margin="auto",this.ctx=this.canvas.getContext("2d",{colorSpace:"display-p3",alpha:!1}),this.ctx.globalAlpha=r,this.ctx.imageSmoothingEnabled=!1,this.setSize(e,n)}setSize(e,n){this.width=e,this.height=n,this.canvas.width=e,this.canvas.height=n,this.canvas.style.width=`${e/T}px`,this.canvas.style.height=`${n/T}px`,this.imageData=this.ctx.createImageData(e,n),this.ctx.putImageData(this.imageData,0,0)}_blank(e=1){let n=e?Math.max(e,.03):1;this.ctx.fillStyle=`rgba(0,0,0,${n})`,this.ctx.fillRect(0,0,this.width,this.height)}clearAll(){this.ctx.save(),this.ctx.globalAlpha=1,this._blank(),this.ctx.restore()}};function Je(t,e){let n=t/e,r,i;return n>1?(r=t,i=~~(t/n)):(i=e,r=~~(e*n)),{width:r,height:i,iWidth:1/r,iHeight:1/i,area:r*i,largeDim:Math.max(r,i),smallDim:Math.min(r,i),aspectRatio:n}}function Ye(t,e=window.innerWidth,n=window.innerHeight){let r=Ge(),i,a;return n<e?t>1?e>=r*t?(i=r*t,a=r):(i=e,a=i/t):(i=r*t,a=r):t>1?(i=r,a=r/t):n<r/t?(a=n,i=a*t):(i=r,a=r/t),[i,a]}var ae=class{constructor(e=!1,n=!0){this.debugMode=e,this.actionMap={},this.listening=n,this.checkKeypress=this.checkKeypress.bind(this),this.registerAction=this.registerAction.bind(this),this.listening&&window.addEventListener("keydown",this.checkKeypress,!1)}checkKeypress({key:e}){this.debugMode&&console.log(`Pressed ${e}`),e in this.actionMap&&this.actionMap[e]()}inject(e){this.checkKeypress({key:e})}registerAction(e,n,r=!1){if(e.length!==1)throw new Error(`Only single-character actions may be registered. Cannot register: ${e}`);if(e in this.actionMap&&!r)throw new Error(`Action already exists for code: ${e}`);this.actionMap[e]=n}destroy(){this.listening&&window.removeEventListener("keydown",this.checkKeypress,!1),this.actionMap={}}},Xe=ae;var se=class{constructor(e,n={}){this.x=-1;this.y=-1;this.isDown=!1;this.clicks=[];this.canvas=e,this.listening=n.listen!==!1,this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.listening&&(e.addEventListener("pointerdown",this.onPointerDown),e.addEventListener("pointermove",this.onPointerMove),e.addEventListener("pointerup",this.onPointerUp))}toCanvasCoords(e){let n=this.canvas.getBoundingClientRect();return{x:(e.clientX-n.left)*(this.canvas.width/n.width),y:(e.clientY-n.top)*(this.canvas.height/n.height)}}onPointerDown(e){let{x:n,y:r}=this.toCanvasCoords(e);this.x=n,this.y=r,this.isDown=!0,this.clicks.push({x:n,y:r})}onPointerMove(e){let{x:n,y:r}=this.toCanvasCoords(e);this.x=n,this.y=r}onPointerUp(e){let{x:n,y:r}=this.toCanvasCoords(e);this.x=n,this.y=r,this.isDown=!1}hasClick(){return this.clicks.length>0}consumeClick(){return this.clicks.shift()??null}inject(e,n,r){this.x=n,this.y=r,e==="down"?(this.isDown=!0,this.clicks.push({x:n,y:r})):e==="up"&&(this.isDown=!1)}destroy(){this.listening&&(this.canvas.removeEventListener("pointerdown",this.onPointerDown),this.canvas.removeEventListener("pointermove",this.onPointerMove),this.canvas.removeEventListener("pointerup",this.onPointerUp))}},Qe=se;function W(){return{now:()=>performance.now()}}function oe(t=0){let e=t;return{now:()=>e,set(n){e=n},advance(n){e+=n}}}var Ze=(t,e,n,r)=>({now:t,startTime:e,elapsedSinceStart:t-e,deltaSinceLastUpdate:n===null?0:t-n,deltaSinceLastRender:r===null?0:t-r}),de=class{constructor(e,n,r,i,a,o={}){this.startTime=0;this.lastUpdateAt=null;this.lastRenderAt=null;this.clockOffsetMs=0;this.pauseStartedAt=null;this.renderAnimation=this.renderAnimation.bind(this),this.dimensionContext=Je(e,n),this.R=r,this.gameManager=o.gameManager,this.hostChannel=o.hostChannel,this.clock=o.clock??W(),this.canvas=new V(this.dimensionContext.width,this.dimensionContext.height,1,o.canvasMount),this.drawingContext=this.canvas.ctx,this.keyboardManager=new Xe(!1,o.captureKeyboard??!0),this.pointerManager=new Qe(this.canvas.canvas,{listen:o.listenToPointer!==!1}),this.animationCart=a;let c=o.customState;this.featureState=a.getDefaultFeatureState?.(this.R,this.dimensionContext,i,this.keyboardManager,c,this.pointerManager,this.gameManager,this.hostChannel),this.cartState=a.getDefaultState(this.R,this.dimensionContext,i,this.keyboardManager,c,this.pointerManager,this.gameManager,this.featureState,this.hostChannel),this.startTime=this.clock.now(),this.canvas.clearAll()}captureFramebuffer(){let e=this.canvas.imageData,n=new ImageData(e.width,e.height);return n.data.set(e.data),n}restoreFramebuffer(e){let n=this.canvas.imageData;return n.width!==e.width||n.height!==e.height||n.data.length!==e.data.length?!1:(n.data.set(e.data),this.drawingContext.putImageData(n,0,0),!0)}setPaused(e){let n=this.clock.now();if(e){this.pauseStartedAt===null&&(this.pauseStartedAt=n);return}this.pauseStartedAt!==null&&(this.clockOffsetMs+=n-this.pauseStartedAt,this.pauseStartedAt=null)}resolveNow(e){let n=this.pauseStartedAt!==null?e-this.pauseStartedAt:0;return e-this.clockOffsetMs-n}getElapsedSinceStart(e=this.clock.now()){return Math.max(0,this.resolveNow(e)-this.startTime)}restoreClock(e,n){this.pauseStartedAt=null,this.lastUpdateAt=null,this.lastRenderAt=null;let r=Math.max(0,e);if(typeof n=="number"&&Number.isFinite(n)){this.startTime=n,this.clockOffsetMs=this.clock.now()-n-r;return}this.clockOffsetMs=0,this.startTime=this.clock.now()-r}getRandomState(){return this.R.getState()}injectKey(e){this.keyboardManager.inject(e)}injectPointer(e,n,r){this.pointerManager.inject(e,n,r)}async updateAnimationState(e,n,r=this.clock.now()){let i=this.resolveNow(r),a=Ze(i,this.startTime,this.lastUpdateAt,this.lastRenderAt);this.cartState=this.animationCart.update(this.R,e,n,this.dimensionContext,this.cartState,this.keyboardManager,this.pointerManager,this.gameManager,a,this.featureState,this.hostChannel),this.lastUpdateAt=i}async renderAnimation(e,n,r=this.clock.now()){let i=this.resolveNow(r),a=Ze(i,this.startTime,this.lastUpdateAt,this.lastRenderAt);this.animationCart.render(this.R,e,n,this.dimensionContext,this.cartState,this.drawingContext,this.canvas.imageData,this.pointerManager,this.gameManager,a,this.featureState,this.hostChannel),this.lastRenderAt=i}getCanvas(){return this.canvas.canvas}getDrawDetails(){return[this.canvas.canvas,0,0,this.dimensionContext.width,this.dimensionContext.height]}teardown(){try{this.animationCart.teardown?.(this.cartState,this.featureState)}catch(e){console.error("Error during cart teardown",e)}this.keyboardManager.destroy(),this.pointerManager.destroy()}};var ue=class extends V{constructor(e,n,r=1,i=!0,a={}){if(super(e,n,r,a),this.adopted)return;let o=a.container;if(o){this.canvas.parentNode!==o&&o.appendChild(this.canvas);return}if(i){let c=document.getElementById("canvas");c&&c!==this.canvas&&c.parentNode===document.body&&document.body.removeChild(c),document.body.appendChild(this.canvas)}}};function et(t){let e=parseInt(t.substring(0,8),16),n=parseInt(t.substring(8,8),16),r=parseInt(t.substring(16,8),16),i=parseInt(t.substring(24,8),16);return{next:()=>{e|=0,n|=0,r|=0,i|=0;let o=(e+n|0)+i|0;return i=i+1|0,e=n^n>>>9,n=r+(r<<3)|0,r=r<<21|r>>>11,r=r+o|0,(o>>>0)/4294967296},getRegs:()=>({a:e,b:n,c:r,d:i}),setRegs:o=>{e=o.a,n=o.b,r=o.c,i=o.d}}}var Q=class{constructor(e){this.seed=e.hash,this.useA=!1,this.genA=et(e.hash.substring(2,32)),this.genB=et(e.hash.substring(34,32)),this.prngA=this.genA.next,this.prngB=this.genB.next;for(let n=0;n<1e6;n+=2)this.prngA(),this.prngB()}getState(){let e=this.genA.getRegs(),n=this.genB.getRegs();return{seed:this.seed,useA:this.useA,prngA:{a:e.a,b:e.b,c:e.c,d:e.d},prngB:{a:n.a,b:n.b,c:n.c,d:n.d}}}setState(e){if(e.seed!==this.seed)throw new Error(`Random.setState: seed ${e.seed} does not match ${this.seed}`);this.useA=e.useA,this.genA.setRegs(e.prngA),this.genB.setRegs(e.prngB)}r_zero_one(){return this.useA=!this.useA,this.useA?this.prngA():this.prngB()}dec(e,n){return e===void 0?this.r_zero_one():n===void 0?e*this.r_zero_one():e+(n-e)*this.r_zero_one()}int(e,n){return n===void 0&&(n=e,e=0),Math.floor(this.dec(e,n))}bool(e=.5){return this.r_zero_one()<e}sign(){return this.bool()?1:-1}choose(e){return e[this.int(e.length)]}};var nt="bafybeicjwcq5lxxtfnyj4p2ugcr7ctyb5wl62cbcechj6tsabdq5whcs7u",tt="https://ipfs.io/ipfs/";function Wt(t){return t.endsWith("/")?t:`${t}/`}var Z=null;function $t(t){return[...Array(t)].map(()=>Math.floor(Math.random()*16).toString(16)).join("")}function jt(t){return t&&t.length>0?t:[{cid:nt}]}function zt(t){return t.startsWith("0x")?t:`0x${t}`}var rt=/^(0[xX])?[0-9a-fA-F]{64}$/;function qt(t){let e="",n=2166136261,r=522970236;for(let i=0;e.length<64;i++){for(let a=0;a<t.length;a++)n^=t.charCodeAt(a)+i,n=Math.imul(n,16777619),r^=t.charCodeAt(a)+i*17,r=Math.imul(r,16777619);e+=(n>>>0).toString(16).padStart(8,"0"),e+=(r>>>0).toString(16).padStart(8,"0")}return`0x${e.slice(0,64)}`}function ce(t){let e=typeof t=="number"?String(t):t;return rt.test(e)?`0x${(e.startsWith("0x")||e.startsWith("0X")?e.slice(2):e).toLowerCase()}`:qt(e)}function le(t,e){if(typeof t=="number"||e==="deterministic")return ce(t);let n=String(t);return rt.test(n)?ce(n):n.startsWith("0x")||n.startsWith("0X")?n:`0x${n}`}function Gt(t){if(!t&&typeof tokenData<"u"&&tokenData?.hash)return{hash:tokenData.hash,tokenId:String(tokenData.tokenId),externalAssetDependencies:jt(tokenData.externalAssetDependencies),preferredIPFSGateway:Wt(tokenData.preferredIPFSGateway||tt),preferredArweaveGateway:tokenData.preferredArweaveGateway};let e=typeof window<"u"?new URLSearchParams(window.location.search):new URLSearchParams;return{hash:t?zt(t):e.get("hash")||`0x${$t(64)}`,tokenId:"18009999",externalAssetDependencies:[{cid:nt}],preferredIPFSGateway:tt}}function we(t){let e=t?.useCache!==!1;if(e&&Z&&!t?.hash)return Z;let n=Gt(t?.hash);return e?Z=n:Z||(Z=n),n}function it(t){return new Array(32).fill(null).map((e,n)=>parseInt(t.hash.slice(2+n*2,4+n*2),16))}async function Se(){let t=await import("tone");if(typeof t.start=="function")return t;let e=t.default;return e&&typeof e.start=="function"?e:t}var ot={id:"tone",async load(){await Promise.resolve().then(()=>(st(),Xt))},async unlock(){await ot.load(),await(await Se()).start()},async resumeIfSuspended(){let t=await Se();t.context.state==="suspended"&&await t.context.resume()},async suspendIfRunning(){let e=(await Se()).context.rawContext;"suspend"in e&&e.state==="running"&&await e.suspend()}},dt={tone:ot};function Ae(t){if(!t)return[];let e=Array.isArray(t)?t:[t],n=[];for(let r of e){if(!(r in dt)){console.warn(`Unknown audio library "${r}"`);continue}let i=r;n.includes(i)||n.push(i)}return n}function Ce(t){return t.map(e=>dt[e])}var he="$cyberartTa",k=class extends Error{constructor(e){super(e),this.name="IncompatibleCartStateError"}},ke={Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array};function Qt(t){for(let e of Object.keys(ke))if(t instanceof ke[e])return e}function ct(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function I(t){if(t===null||typeof t!="object"||Array.isArray(t))return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function xe(t){return I(t)?typeof t[he]=="string"&&Array.isArray(t.d):!1}function Zt(t){return t==null?!1:typeof t=="function"?!0:!(typeof t!="object"||Array.isArray(t)||ct(t)||I(t))}var en=new Set(["audioContextStarted","midiSynths","keepRatioPrimed","audioInitStarted","musicSeekApplied"]);function ut(t){return t===null?"null":xe(t)?String(t[he]):Array.isArray(t)?"array":I(t)?"object":typeof t}function tn(t,e){return t===e||t==="null"||e==="null"}function _(t){return t.trim().toLowerCase().replace(/^0x/,"")}function lt(t,e,n,r){if(!(!n&&!r)&&_(t)!==_(e))throw new k(`Generative cart state is for seed "${e}", but the live token is "${t}"`)}function $(t){return typeof t=="number"&&Number.isFinite(t)&&t>0}function pt(t,e){let n=t.dimensions;if(n&&$(n.width)&&$(n.height))return n;if(e&&$(e.width)&&$(e.height))return{width:e.width,height:e.height};if(I(t.state)){let r=t.state.containerWidth,i=t.state.containerHeight;if($(r)&&$(i))return{width:r,height:i}}return null}function j(t,e=new WeakSet){if(t===null||typeof t=="string"||typeof t=="boolean")return t;if(typeof t=="number")return Number.isFinite(t)?t:null;if(!(typeof t=="function"||typeof t>"u"||typeof t=="bigint"||typeof t=="symbol")){if(ct(t)){let n=Qt(t);return n?{[he]:n,d:Array.from(t)}:void 0}if(typeof t=="object"&&!e.has(t)){e.add(t);try{if(Array.isArray(t)){let i=[],a=0;for(let o of t){let c=j(o,e);c!==void 0&&(i.push(c),a++)}return t.length>0&&a===0?void 0:i}if(!I(t)||Zt(t))return;let n=Object.keys(t),r={};for(let i of n){if(en.has(i))continue;let a=j(t[i],e);a!==void 0&&(r[i]=a)}return n.length>0&&Object.keys(r).length===0?void 0:r}finally{e.delete(t)}}}}function te(t){if(xe(t)){let e=ke[t[he]];return e?new e(t.d.map(n=>Number(n))):t}if(Array.isArray(t))return t.map(e=>te(e));if(I(t)){let e={};for(let n of Object.keys(t))e[n]=te(t[n]);return e}return t}function Te(t,e,n,r,i=!0){if(i&&n&&r&&n!==r)throw new k(`Cart state is for "${r}", but the live cart is "${n}"`);if(!I(e)){if(i)throw new k("Cart state snapshot is empty");return}let a=Object.keys(e);if(a.length===0){if(i)throw new k("Cart state snapshot is empty");return}let o=j(t);if(!I(o)||Object.keys(o).length===0){if(i)throw new k("Live cart has no serializable state");return}let c=a.filter(l=>l in o);if(c.length===0){if(i)throw new k("Cart state snapshot does not overlap the live cart shape");return}for(let l of c){let y=ut(o[l]),m=ut(e[l]);if(!tn(y,m))throw new k(`Cart state field "${l}" has type ${m}, live cart expects ${y}`);if(y==="object"){let h=e[l],b=t[l];I(h)&&!xe(h)&&Te(b,h,void 0,void 0,!1)}}}function ht(t,e){if(!I(t)||!I(e))return;let n=j(t);if(I(n))for(let r of Object.keys(e))r in n&&(t[r]=te(e[r]))}function mt(t){let e=typeof t=="string"?JSON.parse(t):t;if(!e||typeof e!="object")throw new k("Cart state bundle is not an object");if(e.version!==1)throw new k(`Unsupported cart state version ${String(e.version)}`);if(typeof e.seed!="string"||typeof e.framesElapsed!="number")throw new k("Cart state bundle is missing seed or framesElapsed");return e}var Pe="cyberart.asset.ready",De="cyberart.asset.failed";function L(t){try{return JSON.parse(JSON.stringify(t))}catch{return t}}function M(t){try{return JSON.stringify(t)}catch{return String(t)}}function Re(t,e,n){let r=e??[],i=n??[],a=Math.max(r.length,i.length);for(let o=0;o<a;o++)if(M(r[o])!==M(i[o]))return`${t}[${o}]: ${M(r[o])} vs ${M(i[o])}`}function ft(t,e){let n=[];t.seed!==e.seed&&n.push(`seed: ${t.seed} vs ${e.seed}`),t.clock.framesElapsed!==e.clock.framesElapsed&&n.push(`framesElapsed: ${t.clock.framesElapsed} vs ${e.clock.framesElapsed}`),t.clock.now!==e.clock.now&&n.push(`now: ${t.clock.now} vs ${e.clock.now}`),t.clock.frameRate!==e.clock.frameRate&&n.push(`frameRate: ${t.clock.frameRate} vs ${e.clock.frameRate}`),M(t.rng)!==M(e.rng)&&n.push(`rng: ${M(t.rng)} vs ${M(e.rng)}`);let r=Re("actions",t.actions,e.actions);r&&n.push(r);let i=Re("applied",t.applied,e.applied);i&&n.push(i);let a=Re("events",t.events,e.events);return a&&n.push(a),M(t.state)!==M(e.state)&&n.push(`state: ${M(t.state)} vs ${M(e.state)}`),n}function gt(t){return{type:t.status==="ready"?Pe:De,kind:"state",payload:t.detail===void 0?{id:t.id}:{id:t.id,detail:t.detail}}}function rn(t){if(!t||typeof t!="object")return 0;let e=t;return typeof e.startTime=="number"&&typeof e.lastSimulationUpdateAt=="number"?Math.max(0,e.lastSimulationUpdateAt-e.startTime):0}function an(t,e){if(typeof window.resizeTo!="function")return!1;try{if(window.top!==window)return!1}catch{return!1}let n=Math.max(1,Math.round(t)),r=Math.max(1,Math.round(e)),i=Math.max(0,window.outerWidth-window.innerWidth),a=Math.max(0,window.outerHeight-window.innerHeight);try{window.resizeTo(n+i,r+a)}catch{return!1}return Math.abs(window.innerWidth-n)<=8&&Math.abs(window.innerHeight-r)<=8}var sn=[[0,0],[16,9],[9,16],[4,3],[3,4],[2,1],[1,2],[3,1],[1,3],[1,1]],Me=sn[0],on=Me[0]/Me[1],Ie=30,dn=120,un=3840/2160,cn=2160/3840,me=class{constructor(e=Ie,n=!1,r=window.innerWidth,i=window.innerHeight,a=!0,o,c={}){this.framesElapsed=0;this.frameRate=Ie;this._paused=!1;this.savedToken=!1;this.prepared=!1;this.loopRunning=!1;this.fallbackAudio=[];this.audioLibrariesInternal=[];this.virtualClock=null;this.scriptedActions=[];this.initialScriptedActions=[];this.appliedActions=[];this.consumedActionIndexes=new Set;this.outboundEvents=[];this.consecutiveErrorCount=0;this.lastErrorLogAt=0;this.reinitStayPaused=!1;this.reinitPending=!1;this.lastExportedFramebuffer=null;this.pinnedOutput=null;this.pinViewportAtImport=null;this.importing=!1;this.drawLoop=this.drawLoop.bind(this),this.loadCart=this.loadCart.bind(this),this.prepareCart=this.prepareCart.bind(this),this.beginPlayback=this.beginPlayback.bind(this),this.reinit=this.reinit.bind(this),this.tuneFramerate=this.tuneFramerate.bind(this),this.container=c.container,this.seed=c.seed,this.captureKeyboard=c.captureKeyboard??!0,this.customState=c.customState,this.hostChannel=c.hostChannel,this.fallbackAudio=Ae(c.audio),this.audioLibrariesInternal=this.fallbackAudio;let l=c.deterministic;this.deterministic=!!l;let y=l&&typeof l=="object"?l:{};if(this.deterministic){if(c.clock){let m=c.clock;if(typeof m.advance!="function")throw new Error("deterministic mode requires a virtual clock with advance()");this.virtualClock=m,this.clock=m}else this.virtualClock=oe(y.origin??0),this.clock=this.virtualClock;this.initialScriptedActions=L(y.actions??[]),this.scriptedActions=L(this.initialScriptedActions)}else this.clock=c.clock??W();this.isBodyCanvas=this.container?!1:a,this.autoMode=n,this.aspectRatio=on,this.selectedAsp=Me,this.isFullscreen=!!document.fullscreenElement,this.updateFrameRate(e),this.tempUnpause=!1,this.synchronous=K,this.containerWidth=r,this.containerHeight=i,this.gameManager=o,this.init(!0)}setGameManager(e){this.gameManager=e}reinit(e){if(!this.importing){if(this.shouldKeepPinnedOutput()){this.fitPinnedCanvas();return}this.reinitPending||(this.reinitStayPaused=this._paused,this.reinitPending=!0),this.paused=!0,clearTimeout(this.reinitTimeout),this.reinitTimeout=setTimeout(()=>{if(this.importing){this.paused=this.reinitStayPaused,this.reinitPending=!1;return}this.updateInProgress?this.reinit(e):(this.requestedAnimationFrame&&cancelAnimationFrame(this.requestedAnimationFrame),this.clearPinnedOutput(),this.init(),this.reloadCart(),this.paused=this.reinitStayPaused,this.reinitPending=!1)},150)}}initSeed(){this.tokenData=this.seed?we({hash:this.seed,useCache:!1}):we(),this.rawParams=it(this.tokenData),this.mintNo=parseInt(this.tokenData.tokenId)%1e6,console.log("token",this.mintNo,this.tokenData.hash)}init(e=!1){e&&this.initSeed(),this.pureAspectUpdate(this.selectedAsp);let n=this.aspectRatio,[r,i]=Ye(n,this.containerWidth,this.containerHeight);r*=T,i*=T,this.width=~~r,this.height=~~i,this.atCenterX=this.width/2,this.atCenterY=this.height/2,this.mainCanvas?this.mainCanvas.setSize(this.width,this.height):this.mainCanvas=new ue(this.width,this.height,1,this.isBodyCanvas,this.canvasMountOptions())}loadCart(e){this.prepareCart(e)&&this.beginPlayback()}prepareCart(e){if(this.prepared)return!0;try{let n=~~(this.width/1),r=~~(this.height/this.width*n),i=new Q(this.tokenData),a=new de(n,r,i,this.rawParams,e,{gameManager:this.gameManager,canvasMount:this.canvasMountOptions(),customState:this.customState,captureKeyboard:this.deterministic?!1:this.captureKeyboard,hostChannel:this.hostChannel,clock:this.clock,listenToPointer:!this.deterministic});return this.animation=a,this.animationCart=e,this.paused=!1,this.framesElapsed=0,this.outboundEvents=[],this.scriptedActions=L(this.initialScriptedActions),this.appliedActions=[],this.consumedActionIndexes=new Set,this.outboundUnsubscribe?.(),this.outboundUnsubscribe=void 0,this.deterministic&&this.hostChannel&&(this.outboundUnsubscribe=this.hostChannel.onEvent(o=>{this.outboundEvents.push(o)})),this.R=i,this.applyCartFrameRate(e,a),this.resolveAudioLibraries(e),this.prepared=!0,!0}catch(n){return console.error(n),!1}}applyCartFrameRate(e,n){let r=e.metadata,i=r?.frameRate??Ie,a=n.cartState?.visualMode??n.featureState?.visualMode,o=a&&r?.frameRateByVisualMode?r.frameRateByVisualMode[a]:void 0;this.updateFrameRate(typeof o=="number"&&o>0?o:i)}get audioLibraries(){return this.audioLibrariesInternal}get needsAudio(){return this.audioLibrariesInternal.length>0}resolveAudioLibraries(e){this.audioLibrariesInternal=Ae(e.metadata?.audio)}async unlockAudio(){if(this.audioLibrariesInternal.length===0)return;let e=Ce(this.audioLibrariesInternal);if(K){for(let n of e)await n.load();return}for(let n of e)await n.unlock()}async resumeAudioLibraries(){if(!(this.paused||K))for(let e of Ce(this.audioLibrariesInternal))try{await e.resumeIfSuspended()}catch(n){console.error(`Failed to resume audio library "${e.id}" after reload`,n)}}beginPlayback(){!this.prepared||this.loopRunning||(this.prepared=!1,this.loopRunning=!0,this.consecutiveErrorCount=0,!this.deterministic&&(this.requestedAnimationFrame=requestAnimationFrame(this.drawLoop)))}get isPrepared(){return this.prepared}get isLoopRunning(){return this.loopRunning}get isDeterministic(){return this.deterministic}getClock(){return{now:this.clock.now(),framesElapsed:this.framesElapsed,frameRate:this.frameRate}}getRandomState(){return this.requirePreparedAnimation().getRandomState()}schedule(e){this.scriptedActions.push(L(e))}async getReplayMetadata(){let e=await this.exportState();return{seed:this.tokenData.hash,clock:this.getClock(),rng:this.getRandomState(),actions:L(this.scriptedActions),applied:L(this.appliedActions),events:L(this.outboundEvents),state:e.state}}async step(e=1){if(!this.deterministic)throw new Error("step() requires createRuntime({ deterministic: true })");this.requirePreparedAnimation(),this.prepared&&!this.loopRunning&&this.beginPlayback(),this.paused=!1;let n=Math.max(0,Math.floor(e));for(let r=0;r<n&&this.animation;r++){let i=this.framesElapsed;if(this.applyScheduledActions(i),await this.processFrame(this.clock.now(),{ignorePause:!0,scheduleNext:!1}),this.framesElapsed===i||(this.virtualClock?.advance(this.targetDrawTime),!this.loopRunning))break}}async advance(e){let n=Math.max(0,Math.round(e/this.targetDrawTime));await this.step(n)}applyScheduledActions(e){let n=this.animation;n&&this.scriptedActions.forEach((r,i)=>{r.atFrame===e&&(this.consumedActionIndexes.has(i)||(this.consumedActionIndexes.add(i),r.type==="pointer"?n.injectPointer(r.pointer.kind,r.pointer.x,r.pointer.y):r.type==="key"?n.injectKey(r.key):r.type==="event"?this.hostChannel?.dispatch(r.event):r.type==="asset"&&this.hostChannel?.dispatch(gt(r)),this.appliedActions.push({frame:e,action:r})))})}get paused(){return this._paused}set paused(e){this._paused!==e&&(this._paused=e,this.animation?.setPaused(e))}async waitUntilUpdateIdle(){for(;this.updateInProgress;)await new Promise(e=>{this.deterministic?queueMicrotask(e):typeof requestAnimationFrame=="function"?requestAnimationFrame(()=>e()):setTimeout(e,0)})}requirePreparedAnimation(){if(!this.animation)throw new Error("No prepared cart");return this.animation}async exportState(){let e=this.requirePreparedAnimation(),n=this._paused;this.paused=!0,await this.waitUntilUpdateIdle();try{this.lastExportedFramebuffer=e.captureFramebuffer();let r=e.getCanvas();return{version:1,cartId:this.animationCart?.metadata?.id,generative:this.animationCart?.metadata?.generative,seed:this.tokenData.hash,framesElapsed:this.framesElapsed,elapsedSinceStart:e.getElapsedSinceStart(),dimensions:{width:r.width,height:r.height,cssWidth:this.containerWidth,cssHeight:this.containerHeight,dpr:T},state:j(e.cartState)}}finally{this.paused=n}}async exportStateJSON(){return JSON.stringify(await this.exportState())}peekExportedFramebuffer(){return this.lastExportedFramebuffer}peekSeed(){return this.tokenData?.hash}isGenerative(){return this.animationCart?.metadata?.generative===!0}async importState(e,n){let r=this.requirePreparedAnimation(),i=mt(e),a=this._paused,o=this.loopRunning;this.paused=!0,await this.waitUntilUpdateIdle(),Te(r.cartState,i.state,this.animationCart?.metadata?.id,i.cartId),lt(this.tokenData.hash,i.seed,this.animationCart?.metadata?.generative,i.generative),clearTimeout(this.reinitTimeout),this.reinitPending=!1,this.importing=!0;let c=pt(i,n?.framebuffer??this.lastExportedFramebuffer);if(c){this.pinOutputSize(c);let m=c.cssWidth??c.width/T,h=c.cssHeight??c.height/T;an(m,h),this.syncContainerFromDom(),this.pinViewportAtImport={w:this.containerWidth,h:this.containerHeight}}let l=this.customState,y=!1;try{if(this.customState=te(i.state),this.unloadCart(),!this.prepareCart(this.animationCart))throw new Error("Failed to prepare cart while loading state");this.animation.cartState!==this.customState&&ht(this.animation.cartState,i.state),this.framesElapsed=i.framesElapsed;let m=this.animation,h=m.cartState,b=typeof i.elapsedSinceStart=="number"?i.elapsedSinceStart:rn(h);m.restoreClock(b,typeof h?.startTime=="number"?h.startTime:void 0),a&&m.setPaused(!0);let w=n?.framebuffer??this.lastExportedFramebuffer;w&&m.restoreFramebuffer(w)?h.keepRatioPrimed=!0:await m.renderAnimation(this.framesElapsed,this.rawParams),this.fitPinnedCanvas(),y=!0}catch(m){throw this.clearPinnedOutput(),this.customState=l,this.paused=a,this.animationCart&&(this.syncContainerFromDom(),this.init(),this.reloadCart()),m}finally{this.importing=!1,y&&(this.customState=l,this.paused=a,o&&this.beginPlayback())}}unloadCart(){this.loopRunning=!1,this.requestedAnimationFrame&&cancelAnimationFrame(this.requestedAnimationFrame),this.drawLoopTimeout&&clearTimeout(this.drawLoopTimeout),this.animation?.teardown(),this.animation=void 0,this.prepared=!1,this.audioLibrariesInternal=this.fallbackAudio,this.mainCanvas?.clearAll()}reloadCart(e=!1){let n=this.animationCart;if(!n)return;this.pinnedOutput&&(this.clearPinnedOutput(),this.syncContainerFromDom(),this.init());let r=this.reinitPending?this.reinitStayPaused:this._paused;this.unloadCart(),e&&this.initSeed(),this.loadCart(n),this.paused=r,!this.paused&&!K&&this.resumeAudioLibraries()}getFrameRate(){return this.frameRate}updateFrameRate(e){if(this.frameRate=e,e>=1)this.targetDrawTime=1e3/e;else{let r=1/(2-e);this.targetDrawTime=1e3/r}this.drawTime=this.targetDrawTime}canvasMountOptions(){return{container:this.container,adoptFromDocument:!this.container}}syncContainerFromDom(){if(this.container){this.containerWidth=this.container.clientWidth||this.containerWidth,this.containerHeight=this.container.clientHeight||this.containerHeight;return}this.containerWidth=window.innerWidth,this.containerHeight=window.innerHeight}pinOutputSize(e){this.pinnedOutput=e,this.width=~~e.width,this.height=~~e.height,this.atCenterX=this.width/2,this.atCenterY=this.height/2,this.aspectRatio=this.width/this.height,this.mainCanvas&&this.mainCanvas.setSize(this.width,this.height)}shouldKeepPinnedOutput(){return this.pinnedOutput?(this.syncContainerFromDom(),this.viewportMatches(this.pinnedCssSize())?!0:!!(this.pinViewportAtImport&&this.viewportMatches(this.pinViewportAtImport))):!1}pinnedCssSize(){let e=this.pinnedOutput;return{w:e.cssWidth??e.width/T,h:e.cssHeight??e.height/T}}viewportMatches(e){return Math.abs(this.containerWidth-e.w)<8&&Math.abs(this.containerHeight-e.h)<8}fitPinnedCanvas(){let e=this.pinnedOutput,n=this.canvas;if(!e||!n)return;this.container&&!this.container.style.position&&(this.container.style.position="relative");let r=this.containerWidth||window.innerWidth,i=this.containerHeight||window.innerHeight,a=e.width/T,o=e.height/T;if(a<1||o<1||r<1||i<1)return;let c=Math.min(r/a,i/o),l=a*c,y=o*c;n.style.position="absolute",n.style.left="50%",n.style.top="50%",n.style.transform="translate(-50%, -50%)",n.style.margin="0",n.style.width=`${l}px`,n.style.height=`${y}px`,n.style.imageRendering=Math.abs(c-1)<.01?"auto":"pixelated"}clearPinnedOutput(){let e=this.canvas;this.pinnedOutput=null,this.pinViewportAtImport=null,e&&(e.style.position="",e.style.left="",e.style.top="",e.style.transform="",e.style.imageRendering="",e.style.width="",e.style.height="",e.style.margin="auto")}get canvas(){return this.animation?.getCanvas()??this.mainCanvas?.canvas}destroy(){this.outboundUnsubscribe?.(),this.outboundUnsubscribe=void 0,this.clearPinnedOutput(),this.unloadCart(),clearTimeout(this.reinitTimeout),this.mainCanvas&&!this.mainCanvas.adopted&&this.mainCanvas.canvas.remove()}drawIt(){}tuneFramerate(e){let n=this.lastCall||e;this.lastCall=e,this.drawTime=Math.max(0,this.drawTime+this.targetDrawTime-this.lastCall+n)}async processFrame(e,n={}){let r=n.ignorePause===!0,i=n.scheduleNext!==!1;if(!this.loopRunning&&!r)return;let a=!1,o,c="update";try{if(r||!this.paused||this.tempUnpause){if(!K&&!r&&this.tuneFramerate(e),!this.animation)return;if(c="update",this.updateInProgress=!0,await this.animation.updateAnimationState(this.framesElapsed,this.rawParams,e),this.updateInProgress=!1,c="render",await this.animation.renderAnimation(this.framesElapsed,this.rawParams,e),this.autoMode&&this.animation.cartState.saveToken&&!this.savedToken&&!new URLSearchParams(window.location.search).get("hash")){let m=localStorage.getItem("goodones"),h=JSON.stringify(m?[...JSON.parse(m),this.tokenData.hash]:[this.tokenData.hash]);localStorage.setItem("goodones",h),this.savedToken=!0,localStorage.setItem(this.tokenData.hash,this.mainCanvas.canvas.toDataURL("image/png")),window.location.reload(),this.loopRunning=!1;return}this.framesElapsed++,this.tempUnpause&&(this.tempUnpause=!1)}c="draw",this.drawIt()}catch(l){a=!0,o=l,this.handleFrameError(l,c)}finally{this.updateInProgress=!1}a?(this.consecutiveErrorCount++,this.consecutiveErrorCount>=dn&&(this.loopRunning=!1,this.onError?.(o,{phase:c,consecutive:this.consecutiveErrorCount,stopped:!0}))):this.consecutiveErrorCount=0,!(!this.loopRunning||!i)&&(this.drawLoopTimeout=setTimeout(()=>{this.requestedAnimationFrame=requestAnimationFrame(this.drawLoop)},this.drawTime))}async drawLoop(e){await this.processFrame(e,{scheduleNext:!0})}handleFrameError(e,n){let r=performance.now();r-this.lastErrorLogAt>=1e3&&(this.lastErrorLogAt=r,console.error(`Animation ${n} error:`,e)),this.consecutiveErrorCount===0&&this.onError?.(e,{phase:n,consecutive:1,stopped:!1})}pureAspectUpdate(e){if(e[0]===0&&e[1]===0){let r=this.containerWidth||window.innerWidth,i=this.containerHeight||window.innerHeight,a=r/i;this.aspectRatio=Math.min(un,Math.max(cn,a))}else this.aspectRatio=e[0]/e[1]}};var z=class{constructor(){this.inbound=[];this.listeners=[]}dispatch(e){this.inbound.push(e),this.inbound.length>32&&this.inbound.splice(0,this.inbound.length-32)}consume(){if(this.inbound.length===0)return[];let e=this.inbound;return this.inbound=[],e}emit(e){for(let n of this.listeners)n(e)}onEvent(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(n=>n!==e)}}clear(){this.inbound=[],this.listeners=[]}};function He(t){qe();let{container:e,seed:n,captureKeyboard:r=!1,audio:i,deterministic:a}=t,o=n===void 0?void 0:le(n,a?"deterministic":"live"),c=new z,l=!1,y=null,m,h=!1,b=e.clientWidth||window.innerWidth,w=e.clientHeight||window.innerHeight,d=new me(30,!1,b,w,!1,void 0,{container:e,seed:o,captureKeyboard:r,hostChannel:c,audio:i,deterministic:a}),E=()=>{let C=e.clientWidth||window.innerWidth,P=e.clientHeight||window.innerHeight;return C===d.containerWidth&&P===d.containerHeight?!1:(d.containerWidth=C,d.containerHeight=P,!0)},R=null;return!d.isDeterministic&&typeof ResizeObserver<"u"&&(R=new ResizeObserver(()=>{if(l||!y)return;E()&&h&&d.reinit()}),R.observe(e)),d.onError=(C,P)=>{m?.(C,P)},{get tokenData(){return d.tokenData},get onError(){return m},set onError(C){m=C},mount(C,P={}){if(l)throw new Error("createRuntime: cannot mount on a destroyed runtime");y?.destroy(),h=!1,d.customState=P.initialState,d.setGameManager(P.gameManager);let N=P.onEvent?c.onEvent(P.onEvent):()=>{};if(!d.prepareCart(C))throw N(),new Error("createRuntime: failed to prepare cart");let v=!1,B={async start(){if(!v){if(E()&&d.isPrepared&&(d.init(),d.unloadCart(),!d.prepareCart(C)))throw new Error("createRuntime: failed to prepare cart");d.needsAudio&&(await d.unlockAudio(),v)||(h=!0,d.beginPlayback())}},pause(){v||(d.paused=!0)},resume(){v||(d.paused=!1)},dispatch(S){v||c.dispatch(S)},snapshot(){if(v)return{seed:"",pngDataUrl:""};let S=d.canvas;return{seed:d.tokenData.hash,metadata:C.metadata,pngDataUrl:S?S.toDataURL("image/png"):""}},destroy(){v||(v=!0,h=!1,N(),c.clear(),d.unloadCart(),y===B&&(y=null))},reload(){if(!v){if(!h){if(d.isPrepared&&(d.unloadCart(),!d.prepareCart(C)))throw new Error("createRuntime: failed to prepare cart");return}d.reloadCart()}},reinit(S){if(!v){if(!h){E();return}d.reinit(S)}},getCartState(){return d.animation?.cartState},exportState(){return v?Promise.reject(new Error("Cart handle has been destroyed")):d.exportState()},exportStateJSON(){return v?Promise.reject(new Error("Cart handle has been destroyed")):d.exportStateJSON()},async importState(S,re){if(v)throw new Error("Cart handle has been destroyed");await d.importState(S,re)},peekExportedFramebuffer(){return v?null:d.peekExportedFramebuffer()},peekSeed(){if(!v)return d.peekSeed()},isGenerative(){return v?!1:d.isGenerative()},async step(S=1){if(v)throw new Error("Cart handle has been destroyed");await d.step(S)},async advance(S){if(v)throw new Error("Cart handle has been destroyed");await d.advance(S)},schedule(S){v||d.schedule(S)},getClock(){if(v)throw new Error("Cart handle has been destroyed");return d.getClock()},getRandomState(){if(v)throw new Error("Cart handle has been destroyed");return d.getRandomState()},getReplayMetadata(){return v?Promise.reject(new Error("Cart handle has been destroyed")):d.getReplayMetadata()},get canvas(){return d.canvas},get paused(){return d.paused},set paused(S){v||(d.paused=S)},get tokenData(){return d.tokenData},get isPrepared(){return d.isPrepared},get isLoopRunning(){return d.isLoopRunning},get needsAudio(){return d.needsAudio},get audioLibraries(){return d.audioLibraries}};return y=B,B},async unlockAudio(){await d.unlockAudio()},destroy(){l||(l=!0,y?.destroy(),y=null,R?.disconnect(),R=null,c.clear(),d.destroy())}}}var yt="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",bt=320,vt=180,ln="Headless harness has been destroyed",wt=!1;function Et(){if(typeof globalThis.ImageData>"u"){class e{constructor(r,i){this.colorSpace="srgb";this.width=r,this.height=i,this.data=new Uint8ClampedArray(r*i*4)}}globalThis.ImageData=e}let t=HTMLCanvasElement.prototype;t.getContext=function(){return{globalAlpha:1,imageSmoothingEnabled:!1,fillStyle:"",save(){},restore(){},fillRect(){},putImageData(){},createImageData(r,i){return{data:new Uint8ClampedArray(r*i*4),width:r,height:i}}}},t.toDataURL=()=>yt,wt=!0}function pn(t,e){let n=document.createElement("div");return Object.defineProperty(n,"clientWidth",{value:t,configurable:!0}),Object.defineProperty(n,"clientHeight",{value:e,configurable:!0}),document.body.appendChild(n),n}function hn(t){let e=t.indexOf(","),n=e>=0?t.slice(e+1):t,r=globalThis.atob(n),i=new Uint8Array(r.length);for(let a=0;a<r.length;a++)i[a]=r.charCodeAt(a);return i}function mn(){return typeof process<"u"&&!!process.versions?.node}async function fn(t,e){if(!mn())throw new Error("captureFrame(path) requires Node.js; omit the path to get the snapshot only");let n;try{({writeFile:n}=await import("node:fs/promises"))}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`captureFrame(path) could not load node:fs/promises (${i}). Omit the path, or run under Node.`)}try{await n(t,hn(e))}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`captureFrame could not write ${t}: ${i}`)}}function gn(t){wt||Et();let e=t.width??bt,n=t.height??vt,r=pn(e,n),i=[],a=[],o=!1,c=t.onEvent,l=t.onError,y=He({container:r,seed:t.seed,deterministic:{origin:t.origin,actions:t.actions??[]}});y.onError=(d,E)=>{a.push({error:d,info:E}),l?.(d,E)},Object.defineProperty(y,"onError",{configurable:!0,enumerable:!0,get(){return l},set(d){l=d}});let m=d=>{i.push(d),c?.(d)},h=y.mount(t.cart,{initialState:t.initialState,gameManager:t.gameManager,onEvent:m}),b=()=>{if(o)throw new Error(ln)};return{runtime:y,container:r,get events(){return i.slice()},get errors(){return a.slice()},get cart(){return h},async step(d=1){b(),await h.step(d)},async advance(d){b(),await h.advance(d)},schedule(d){b(),h.schedule(d)},dispatch(d){b(),h.dispatch(d)},key(d){b(),h.schedule({type:"key",atFrame:h.getClock().framesElapsed,key:d})},click(d,E){b(),h.schedule({type:"pointer",atFrame:h.getClock().framesElapsed,pointer:{kind:"down",x:d,y:E}})},async inspect(){b();let d=await h.getReplayMetadata();return{state:d.state,events:i.slice(),errors:a.slice(),replay:d,clock:h.getClock()}},async captureFrame(d){b();let E=h.snapshot();return d&&await fn(d,E.pngDataUrl),E},remount(d={}){return b(),i.length=0,a.length=0,"onEvent"in d&&(c=d.onEvent),h=y.mount(t.cart,{initialState:d.initialState??t.initialState,gameManager:d.gameManager??t.gameManager,onEvent:m}),h},destroy(){if(!o){o=!0;try{h.destroy()}finally{try{y.destroy()}finally{r.remove()}}}}}}var q="cyberart.state.save",G="cyberart.state.load";function yn(t,e,n={}){let r=n.persist,i=r?{persist:r}:void 0,a=()=>{e.emit({type:q,payload:i})},o=()=>{e.emit({type:G,payload:i})};t.registerAction("w",a,!0),t.registerAction("W",a,!0),t.registerAction("e",o,!0),t.registerAction("E",o,!0)}function St(t){if(t.type!==q&&t.type!==G)return;let e=t.payload?.persist;return e==="localStorage"?e:void 0}var bn="cyberart-io",vn=1,O="framebuffers";function _e(t,e){return`${t||"unknown"}:${e?_(e):"none"}`}function Ct(t,e){return`${t||"unknown"}:${e||"none"}`}function Le(){return new Promise((t,e)=>{let n=indexedDB.open(bn,vn);n.onupgradeneeded=()=>{let r=n.result;r.objectStoreNames.contains(O)||r.createObjectStore(O)},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error??new Error("indexedDB open failed"))})}function wn(t){let e=t.data;return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}function At(t,e){return new Promise((n,r)=>{let a=t.transaction(O,"readonly").objectStore(O).get(e);a.onsuccess=()=>n(a.result),a.onerror=()=>r(a.error??new Error("indexedDB read failed"))})}async function kt(t,e,n){if(typeof indexedDB>"u")return;let r=await Le(),i={width:n.width,height:n.height,data:wn(n)};try{await new Promise((a,o)=>{let c=r.transaction(O,"readwrite");c.oncomplete=()=>a(),c.onerror=()=>o(c.error??new Error("indexedDB write failed")),c.objectStore(O).put(i,_e(t,e))})}finally{r.close()}}async function xt(t,e){if(typeof indexedDB>"u")return null;let n=await Le();try{let r=_e(t,e),i=Ct(t,e),a=await At(n,r)??(r===i?void 0:await At(n,i));if(!a||!a.data||a.width<1||a.height<1)return null;let o=new ImageData(a.width,a.height);return o.data.set(new Uint8ClampedArray(a.data)),o}finally{n.close()}}async function Tt(t,e){if(typeof indexedDB>"u")return;let n=await Le();try{await new Promise((r,i)=>{let a=n.transaction(O,"readwrite");a.oncomplete=()=>r(),a.onerror=()=>i(a.error??new Error("indexedDB delete failed"));let o=a.objectStore(O);o.delete(_e(t,e)),o.delete(Ct(t,e))})}finally{n.close()}}var Oe="cyberart.state.",En="Saved state",Sn="Loaded state",An="Failed to save state",Cn="Failed to load state",kn="No saved state";function F(t,e){let n=t||"unknown";return e?Oe+n+"."+_(e):Oe+n}function xn(t,e,n){return r=>{if(St(r)==="localStorage"){if(r.type===q){Tn(t,e,n);return}r.type===G&&Rn(t,e,n)}}}function J(t){try{let e=JSON.parse(t);if(!e||typeof e!="object")return null;let n=e;if(typeof n.savedAt=="number"&&n.bundle&&typeof n.bundle=="object")return{savedAt:n.savedAt,bundle:n.bundle};let r=e;return typeof r.seed=="string"&&typeof r.version=="number"?{savedAt:0,bundle:r}:null}catch{return null}}async function Tn(t,e,n){let r=t();if(r)try{let i=await r.exportState(),a=i.cartId??e?.();i.generative===!0?(Ln(a),fe(F(a,i.seed),i)):fe(F(a),i);let o=r.peekExportedFramebuffer?.();if(o)try{await kt(a,i.seed,o)}catch(c){console.warn("Failed to save cart framebuffer",c)}n?.(En,"transient")}catch(i){console.error("Failed to save cart state",i),n?.(An,"transient")}}async function Rn(t,e,n){let r=t();if(!r)return;let i=e?.(),a=r.peekSeed?.(),o=r.isGenerative?.()===!0,c=Hn(i,o,a);if(!c){console.warn("No saved cart state for",i||"unknown",o&&a?`(hash ${a})`:""),n?.(kn,"transient");return}try{let l=await xt(i,c.bundle.seed).catch(()=>null);await r.importState(c.bundle,{framebuffer:l}),n?.(Sn,"transient")}catch(l){console.error("Failed to load cart state",l),n?.(Cn,"transient")}}function fe(t,e){let n=JSON.stringify({savedAt:Date.now(),bundle:e});Pn(t,n)}function Pn(t,e){for(;;)try{localStorage.setItem(t,e);return}catch(n){if(!Dn(n)||!In(t))throw n}}function Dn(t){if(!t||typeof t!="object")return!1;let e=t.name,n=t.code;return e==="QuotaExceededError"||e==="NS_ERROR_DOM_QUOTA_REACHED"||n===22||n===1014}function In(t){let e=null,n=1/0;for(let a of Mn()){if(a===t)continue;let o=localStorage.getItem(a);if(!o)continue;let l=J(o)?.savedAt??0;l<n&&(n=l,e=a)}if(!e)return!1;let r=localStorage.getItem(e),i=r?J(r):null;return localStorage.removeItem(e),i?.bundle&&Tt(i.bundle.cartId,i.bundle.seed).catch(()=>{}),!0}function Mn(){let t=[];for(let e=0;e<localStorage.length;e++){let n=localStorage.key(e);n&&n.startsWith(Oe)&&t.push(n)}return t}function Hn(t,e,n){if(e&&n){let i=localStorage.getItem(F(t,n));if(i)return J(i);let a=localStorage.getItem(F(t));if(!a)return null;let o=J(a);if(!o||!_n(o.bundle,n))return null;try{fe(F(t,n),o.bundle)}catch{}return o}let r=localStorage.getItem(F(t));return r?J(r):null}function _n(t,e){return typeof t.seed=="string"&&_(t.seed)===_(e)}function Ln(t){let e=F(t),n=localStorage.getItem(e);if(!n)return;let r=J(n);if(r&&typeof r.bundle.seed=="string"){let i=F(t,r.bundle.seed);if(!localStorage.getItem(i))try{fe(i,r.bundle)}catch{return}}localStorage.removeItem(e)}var ne=1,Fe="cyberart.diagnostic.rejected",ge=8,On=new Set(["intent","state","diagnostic"]),Fn=new Set([q,G]);function Rt(t){return typeof t=="string"&&On.has(t)}function Pt(t){if(t.kind!==void 0)return Rt(t.kind)?t.kind:void 0;if(typeof t.type!="string"||t.type.length===0)return;if(Fn.has(t.type))return"intent";let e=t.type.split(".");if(e.length<2)return;let n=e[1];return Rt(n)?n:void 0}function Dt(t,e){let n=t.split("."),r=e.split(".");if(n.length!==r.length)return!1;for(let i=0;i<n.length;i++)if(n[i]!=="*"&&n[i]!==r[i])return!1;return!0}function Y(t,e){for(let n of t)if(Dt(n,e))return!0;return!1}function Nn(t){if(t===void 0)return{ok:!0,value:void 0};try{return{ok:!0,value:JSON.parse(JSON.stringify(t))}}catch{return{ok:!1}}}function ye(t,e){if(!t||typeof t.type!="string"||t.type.length===0)return{ok:!1,reason:"malformed",detail:"type is required"};if(t.schemaVersion!==void 0&&t.schemaVersion!==ne)return{ok:!1,reason:"malformed",detail:`unsupported schemaVersion ${String(t.schemaVersion)}`};let n=Pt(t);if(!n)return{ok:!1,reason:"malformed",detail:`cannot infer kind from type "${t.type}"`};let r=Nn(t.payload);if(!r.ok)return{ok:!1,reason:"malformed",detail:"payload is not JSON-serializable"};let i=e.createId(),a=typeof t.correlationId=="string"&&t.correlationId.length>0?t.correlationId:i,o=typeof t.causationId=="string"&&t.causationId.length>0?t.causationId:e.causationId,c=typeof t.target=="string"&&t.target.length>0?t.target:void 0,l=e.maxHops??ge,y=e.parentHops===void 0?l:Math.max(0,e.parentHops-1),m=typeof t.idempotencyKey=="string"&&t.idempotencyKey.length>0?t.idempotencyKey:void 0,h={schemaVersion:ne,type:t.type,kind:n,source:e.source,id:i,correlationId:a,seq:e.seq,hops:y};return c&&(h.target=c),o&&(h.causationId=o),m&&(h.idempotencyKey=m),r.value!==void 0&&(h.payload=r.value),{ok:!0,envelope:h}}var Bn=new Set(["rate-limited","storm-detected","hop-limit","loop-detected","not-subscribed"]),Un=8,Kn=8,Vn=16,Wn=256,$n=["*.intent.*"];function jn(t={}){let e=t.hostSource??"host",n="router",r=t.maxPerTurn??Un,i=t.maxCausationDepth??Kn,a=t.maxHops??ge,o=t.maxCorrelationPerTurn??Vn,c=t.maxIndex??Wn,l=t.maxPerWindow,y=t.windowMs??1e3,m=t.now??Date.now,h=0,b=t.createId??(()=>`evt-${++h}`),w=new Map,d=[],E=new Map,R=new Map,be=new Map,C=0,P=0,N=[],v=!1;function B(s,u,f){for(s.set(u,f);s.size>c;){let g=s.keys().next().value;if(g===void 0)break;s.delete(g)}}function S(s){B(E,s.id,{type:s.type,source:s.source,causationId:s.causationId,hops:s.hops,correlationId:s.correlationId,idempotencyKey:s.idempotencyKey})}function re(s,u){u&&(s.correlationId||(s.correlationId=u.correlationId),s.causationId||(s.causationId=u.id),!s.idempotencyKey&&u.idempotencyKey&&(s.idempotencyKey=`${u.idempotencyKey}::${s.type}`))}function Ne(s,u){if(s){let f=E.get(s);return f?f.hops:a}return u}function Be(s,u){return`${s}\0${u}`}function Ue(s,u){s.idempotencyKey&&B(be,Be(s.source,s.idempotencyKey),u)}function ve(s,u){if(u)return be.get(Be(s,u))}function It(s){return ve(s.source,s.idempotencyKey)}function Mt(s){return s.seq+=1,s.seq}function Ht(s,u){if(!(typeof u.causationId=="string"&&u.causationId.length>0))return s.lastDelivered}function Ke(s){let u=new Set,f=new Set([`${s.type}\0${s.source}`]),g=s.causationId,p=0;for(;g;){if(p+=1,p>i||u.has(g))return!0;u.add(g);let A=E.get(g);if(!A)break;let D=`${A.type}\0${A.source}`;if(f.has(D))return!0;f.add(D),g=A.causationId}return!1}function _t(s){let u=(R.get(s)??0)+1;return R.set(s,u),u}function Ve(s,u){l!==void 0&&(s.emitTimestamps=s.emitTimestamps.filter(f=>u-f<y))}function Lt(s,u){return(u.kind==="state"||u.kind==="diagnostic")&&!s.authoritative?!1:Y(s.emit,u.type)}function We(s){for(let u of d)if(Y(u.patterns,s.type))try{u.listener(s)}catch{}}function Ot(s){if(s.target){let u=w.get(s.target);if(!u||!Y(u.subscribe,s.type))return;u.channel.dispatch(s),u.lastDelivered={id:s.id,hops:s.hops,correlationId:s.correlationId,idempotencyKey:s.idempotencyKey};return}for(let u of w.values())Y(u.subscribe,s.type)&&(u.channel.dispatch(s),u.lastDelivered={id:s.id,hops:s.hops,correlationId:s.correlationId,idempotencyKey:s.idempotencyKey})}function Ft(s,u,f,g,p,A,D){let H={reason:g,eventType:u,source:f};p&&(H.detail=p),P+=1;let X=b(),U={schemaVersion:ne,type:Fe,kind:"diagnostic",source:n,id:X,correlationId:A??X,seq:P,hops:0,payload:H};D&&(U.causationId=D),S(U);let ze=w.get(s);ze&&ze.channel.dispatch(U),We(U)}function x(s,u,f,g,p){Ft(s,p?.type??(typeof u.type=="string"?u.type:""),p?.source??s,f,g,p?.correlationId,p?.id),p?.idempotencyKey&&!Bn.has(f)&&Ue(p,{status:"rejected"})}function Nt(s){S(s),Ue(s,{status:"accepted",envelope:s}),_t(s.correlationId),We(s),Ot(s)}function $e(s,u,f,g){if(!f.ok){x(s,u,"malformed",f.detail);return}let p=f.envelope,A=It(p);if(A)return A.status==="accepted"?A.envelope:void 0;if(p.hops<1){x(s,u,"hop-limit","no hops remaining",p);return}if(p.target&&p.target!==e){let D=w.get(p.target);if(!D){x(s,u,"unknown-target",`unknown target "${p.target}"`,p);return}if(!Y(D.subscribe,p.type)){x(s,u,"not-subscribed",`target "${p.target}" does not subscribe to ${p.type}`,p);return}}if(g){if(!Lt(g,p)){x(s,u,"unauthorized","source may not emit this event",p);return}if(g.emitsThisTurn+=1,g.emitsThisTurn>r){x(s,u,"rate-limited","maxPerTurn exceeded",p);return}if(l!==void 0){let H=m();if(Ve(g,H),g.emitTimestamps.push(H),g.emitTimestamps.length>l){x(s,u,"rate-limited","maxPerWindow exceeded",p);return}}if(Ke(p)){x(s,u,"loop-detected","causation chain cycle or depth exceeded",p);return}if((R.get(p.correlationId)??0)+1>o){x(s,u,"storm-detected","correlationId storm",p);return}if(t.validate){let H;try{H=t.validate(p)}catch(X){let U=X instanceof Error?X.message:"validate threw";x(s,u,"host-rejected",U,p);return}if(H!==!0){x(s,u,"host-rejected",H.detail,p);return}}}else{if(Ke(p)){x(s,u,"loop-detected","causation chain cycle or depth exceeded",p);return}if((R.get(p.correlationId)??0)+1>o){x(s,u,"storm-detected","correlationId storm",p);return}}return Nt(p),p}function Bt(s,u){let f=w.get(s);if(!f)return;let g={...u},p=Ht(f,g);if(re(g,p),ve(f.id,g.idempotencyKey))return;let D=Mt(f),H=ye(g,{source:f.id,createId:b,seq:D,causationId:p?.id,maxHops:a,parentHops:Ne(g.causationId??p?.id,p?.hops)});$e(s,g,H,f)}function Ut(s,u){let f=u?.cause,g={...s};re(g,f);let p=ve(e,g.idempotencyKey);if(p)return p.status==="accepted"?p.envelope:void 0;C+=1;let A=ye(g,{source:e,createId:b,seq:C,causationId:g.causationId,maxHops:a,parentHops:Ne(g.causationId,f?.hops)});return $e(e,g,A,void 0)}function Kt(){if(!v){v=!0;try{for(;N.length>0;){let s=N.shift();s&&(s.kind==="cart"?Bt(s.participantId,s.event):s.result=Ut(s.event,s.extras))}}finally{v=!1}}}function je(s){N.push(s),Kt()}return{attach(s,u,f={}){if(s===e||s===n)throw new Error(`createEventRouter: "${s}" is a reserved participant id`);for(let A of w.values())if(A.channel===u&&A.id!==s)throw new Error(`createEventRouter: channel already attached as "${A.id}"`);w.get(s)?.unsubscribe();let p={id:s,channel:u,emit:f.emit??$n,subscribe:f.subscribe??[],authoritative:f.authoritative===!0,seq:0,emitsThisTurn:0,emitTimestamps:[],unsubscribe:()=>{}};p.unsubscribe=u.onEvent(A=>{je({kind:"cart",participantId:s,event:A})}),w.set(s,p)},detach(s){let u=w.get(s);u&&(u.unsubscribe(),w.delete(s))},publish(s,u){let f={kind:"publish",event:s,extras:u};return je(f),f.result},subscribe(s,u){let f={patterns:s,listener:u};return d.push(f),()=>{let g=d.indexOf(f);g>=0&&d.splice(g,1)}},turn(){R.clear();for(let s of w.values())s.emitsThisTurn=0,s.lastDelivered=void 0,l!==void 0&&Ve(s,m())}}}export{De as ASSET_FAILED_EVENT,Pe as ASSET_READY_EVENT,ie as CYBERART_CANVAS_ATTR,vt as DEFAULT_HEADLESS_HEIGHT,bt as DEFAULT_HEADLESS_WIDTH,ge as DEFAULT_MAX_HOPS,ne as EVENT_ENVELOPE_VERSION,yt as HEADLESS_PNG_DATA_URL,z as HostChannel,k as IncompatibleCartStateError,ae as KeyboardManager,se as PointerManager,Fe as REJECTED_EVENT_TYPE,Q as Random,xn as attachCartStatePersistence,ce as canonicalizeSeed,jn as createEventRouter,gn as createHeadlessHarness,He as createRuntime,oe as createVirtualClock,W as createWallClock,ft as describeReplayMismatch,Pt as inferEventKind,Et as installHeadlessCanvas,Dt as matchEventPattern,ye as normalizeEvent,yn as registerCartStateHotkeys,le as resolveRuntimeSeed};
8
+ var lr=(e,t)=>()=>(e&&(t=e(e=0)),t);var Er={};function vr(e,t){let n=e.indexOf(nn);if(n===-1)return null;let r=n+nn.length,o=`const __cyberSkip=new Set(${JSON.stringify(t)});const __cyberOrig=registerProcessor;registerProcessor=(n,p)=>__cyberSkip.has(n)?undefined:__cyberOrig(n,p);`;return e.slice(0,r)+o+e.slice(r)}var lt,qe,br,Me,nn,rn=lr(()=>{"use strict";lt=/AudioWorkletProcessor with name:\s*["'`][^"'`]+["'`]\s+is already registered/i,qe="__cyberartWorkletPatchApplied";typeof window<"u"&&!window[qe]&&(window.addEventListener("error",e=>{let t=e?.message??"";lt.test(t)&&(e.preventDefault(),e.stopImmediatePropagation())},!0),window.addEventListener("unhandledrejection",e=>{let t=e?.reason,n=typeof t=="string"?t:t?.message??"";lt.test(n)&&e.preventDefault()}),window[qe]=!0);br=!1,Me=(...e)=>{br&&console.log("[workletPatch]",...e)},nn="((AudioWorkletProcessor,registerProcessor)=>{";if(typeof AudioWorklet<"u"&&!AudioWorklet.prototype[qe]){let e=new WeakMap,t=/registerProcessor\s*\(\s*['"`]([^'"`]+)['"`]/g,n=AudioWorklet.prototype.addModule,r=0;AudioWorklet.prototype.addModule=async function(o,a){let d=++r,u=e.get(this);u||(u=new Set,e.set(this,u)),Me(`#${d} addModule`,{url:o.slice(0,64),isBlob:o.startsWith("blob:"),knownBefore:[...u]});let g=o,m=null;if(o.startsWith("blob:")){let y=null;try{y=await(await fetch(o)).text()}catch(C){Me(`#${d} blob fetch failed`,C)}if(y!==null){let C=new Set;for(let E of y.matchAll(t))C.add(E[1]);if(C.size>0){let E=[...C].filter(f=>u.has(f)),N=[...C].filter(f=>!u.has(f));if(E.length>0&&N.length===0){Me(`#${d} short-circuit \u2014 all processors already registered`,E);return}if(E.length>0&&N.length>0){let f=vr(y,E);if(f!==null){let l=new Blob([f],{type:"application/javascript"});m=URL.createObjectURL(l),g=m,Me(`#${d} rewrote blob; skipping`,E,"allowing",N)}else Me(`#${d} blob rewrite failed; passing original through`)}N.forEach(f=>u.add(f))}}}return n.call(this,g,a).then(()=>{m&&URL.revokeObjectURL(m)},y=>{m&&URL.revokeObjectURL(m);let C=(y&&y.message)??"";if(!(lt.test(C)||/already registered/i.test(C)))throw y})},AudioWorklet.prototype[qe]=!0}});var Ut=()=>{let e=["ms","moz","webkit","o"];for(let t=0;t<e.length&&!window.requestAnimationFrame;++t)window.requestAnimationFrame=window[e[t]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[e[t]+"CancelAnimationFrame"]||window[e[t]+"CancelRequestAnimationFrame"]},z=window.devicePixelRatio||1,pe=/Headless/i.test(navigator.userAgent),_o=/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)||/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.platform);function jt(){return Math.min(window.innerWidth,window.innerHeight)}var Ke="data-cyberart-canvas",fe=class{constructor(t,n,r=1,i={}){this.width=t,this.height=n;let o=i.container,a=i.adoptFromDocument??!o,d=o?o.querySelector(`canvas[${Ke}]`)??o.querySelector("canvas"):null;if(d)this.canvas=d,this.adopted=!0;else if(a){let u=document.getElementById("canvas")??document.querySelector("canvas");u?(this.canvas=u,this.adopted=!0):(this.canvas=document.createElement("canvas"),this.canvas.setAttribute("id","canvas"),this.adopted=!1)}else this.canvas=document.createElement("canvas"),this.adopted=!1;this.canvas.hasAttribute(Ke)||this.canvas.setAttribute(Ke,""),this.canvas.style.display="block",this.canvas.style.margin="auto",this.ctx=this.canvas.getContext("2d",{colorSpace:"display-p3",alpha:!1}),this.ctx.globalAlpha=r,this.ctx.imageSmoothingEnabled=!1,this.setSize(t,n)}setSize(t,n){this.width=t,this.height=n,this.canvas.width=t,this.canvas.height=n,this.canvas.style.width=`${t/z}px`,this.canvas.style.height=`${n/z}px`,this.imageData=this.ctx.createImageData(t,n),this.ctx.putImageData(this.imageData,0,0)}_blank(t=1){let n=t?Math.max(t,.03):1;this.ctx.fillStyle=`rgba(0,0,0,${n})`,this.ctx.fillRect(0,0,this.width,this.height)}clearAll(){this.ctx.save(),this.ctx.globalAlpha=1,this._blank(),this.ctx.restore()}};function zt(e,t){let n=e/t,r,i;return n>1?(r=e,i=~~(e/n)):(i=t,r=~~(t*n)),{width:r,height:i,iWidth:1/r,iHeight:1/i,area:r*i,largeDim:Math.max(r,i),smallDim:Math.min(r,i),aspectRatio:n}}function Wt(e,t=window.innerWidth,n=window.innerHeight){let r=jt(),i,o;return n<t?e>1?t>=r*e?(i=r*e,o=r):(i=t,o=i/e):(i=r*e,o=r):e>1?(i=r,o=r/e):n<r/e?(o=n,i=o*e):(i=r,o=r/e),[i,o]}var Ge=class{constructor(t=!1,n=!0){this.debugMode=t,this.actionMap={},this.listening=n,this.checkKeypress=this.checkKeypress.bind(this),this.registerAction=this.registerAction.bind(this),this.listening&&window.addEventListener("keydown",this.checkKeypress,!1)}checkKeypress({key:t}){this.debugMode&&console.log(`Pressed ${t}`),t in this.actionMap&&this.actionMap[t]()}inject(t){this.checkKeypress({key:t})}registerAction(t,n,r=!1){if(t.length!==1)throw new Error(`Only single-character actions may be registered. Cannot register: ${t}`);if(t in this.actionMap&&!r)throw new Error(`Action already exists for code: ${t}`);this.actionMap[t]=n}destroy(){this.listening&&window.removeEventListener("keydown",this.checkKeypress,!1),this.actionMap={}}},qt=Ge;var $e=class{constructor(t,n={}){this.x=-1;this.y=-1;this.isDown=!1;this.clicks=[];this.canvas=t,this.listening=n.listen!==!1,this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.listening&&(t.addEventListener("pointerdown",this.onPointerDown),t.addEventListener("pointermove",this.onPointerMove),t.addEventListener("pointerup",this.onPointerUp))}toCanvasCoords(t){let n=this.canvas.getBoundingClientRect();return{x:(t.clientX-n.left)*(this.canvas.width/n.width),y:(t.clientY-n.top)*(this.canvas.height/n.height)}}onPointerDown(t){let{x:n,y:r}=this.toCanvasCoords(t);this.x=n,this.y=r,this.isDown=!0,this.clicks.push({x:n,y:r})}onPointerMove(t){let{x:n,y:r}=this.toCanvasCoords(t);this.x=n,this.y=r}onPointerUp(t){let{x:n,y:r}=this.toCanvasCoords(t);this.x=n,this.y=r,this.isDown=!1}hasClick(){return this.clicks.length>0}consumeClick(){return this.clicks.shift()??null}inject(t,n,r){this.x=n,this.y=r,t==="down"?(this.isDown=!0,this.clicks.push({x:n,y:r})):t==="up"&&(this.isDown=!1)}destroy(){this.listening&&(this.canvas.removeEventListener("pointerdown",this.onPointerDown),this.canvas.removeEventListener("pointermove",this.onPointerMove),this.canvas.removeEventListener("pointerup",this.onPointerUp))}},Yt=$e;function me(){return{now:()=>performance.now()}}function Be(e=0){let t=e;return{now:()=>t,set(n){t=n},advance(n){t+=n}}}var Jt=(e,t,n,r)=>({now:e,startTime:t,elapsedSinceStart:e-t,deltaSinceLastUpdate:n===null?0:e-n,deltaSinceLastRender:r===null?0:e-r}),Ue=class{constructor(t,n,r,i,o,a={}){this.startTime=0;this.lastUpdateAt=null;this.lastRenderAt=null;this.clockOffsetMs=0;this.pauseStartedAt=null;this.renderAnimation=this.renderAnimation.bind(this),this.dimensionContext=zt(t,n),this.R=r,this.gameManager=a.gameManager,this.hostChannel=a.hostChannel,this.clock=a.clock??me(),this.canvas=new fe(this.dimensionContext.width,this.dimensionContext.height,1,a.canvasMount),this.drawingContext=this.canvas.ctx,this.keyboardManager=new qt(!1,a.captureKeyboard??!0),this.pointerManager=new Yt(this.canvas.canvas,{listen:a.listenToPointer!==!1}),this.animationCart=o;let d=a.customState;this.featureState=o.getDefaultFeatureState?.(this.R,this.dimensionContext,i,this.keyboardManager,d,this.pointerManager,this.gameManager,this.hostChannel),this.cartState=o.getDefaultState(this.R,this.dimensionContext,i,this.keyboardManager,d,this.pointerManager,this.gameManager,this.featureState,this.hostChannel),this.startTime=this.clock.now(),this.canvas.clearAll()}captureFramebuffer(){let t=this.canvas.imageData,n=new ImageData(t.width,t.height);return n.data.set(t.data),n}restoreFramebuffer(t){let n=this.canvas.imageData;return n.width!==t.width||n.height!==t.height||n.data.length!==t.data.length?!1:(n.data.set(t.data),this.drawingContext.putImageData(n,0,0),!0)}setPaused(t){let n=this.clock.now();if(t){this.pauseStartedAt===null&&(this.pauseStartedAt=n);return}this.pauseStartedAt!==null&&(this.clockOffsetMs+=n-this.pauseStartedAt,this.pauseStartedAt=null)}resolveNow(t){let n=this.pauseStartedAt!==null?t-this.pauseStartedAt:0;return t-this.clockOffsetMs-n}getElapsedSinceStart(t=this.clock.now()){return Math.max(0,this.resolveNow(t)-this.startTime)}restoreClock(t,n){this.pauseStartedAt=null,this.lastUpdateAt=null,this.lastRenderAt=null;let r=Math.max(0,t);if(typeof n=="number"&&Number.isFinite(n)){this.startTime=n,this.clockOffsetMs=this.clock.now()-n-r;return}this.clockOffsetMs=0,this.startTime=this.clock.now()-r}getRandomState(){return this.R.getState()}injectKey(t){this.keyboardManager.inject(t)}injectPointer(t,n,r){this.pointerManager.inject(t,n,r)}async updateAnimationState(t,n,r=this.clock.now()){let i=this.resolveNow(r),o=Jt(i,this.startTime,this.lastUpdateAt,this.lastRenderAt);this.cartState=this.animationCart.update(this.R,t,n,this.dimensionContext,this.cartState,this.keyboardManager,this.pointerManager,this.gameManager,o,this.featureState,this.hostChannel),this.lastUpdateAt=i}async renderAnimation(t,n,r=this.clock.now()){let i=this.resolveNow(r),o=Jt(i,this.startTime,this.lastUpdateAt,this.lastRenderAt);this.animationCart.render(this.R,t,n,this.dimensionContext,this.cartState,this.drawingContext,this.canvas.imageData,this.pointerManager,this.gameManager,o,this.featureState,this.hostChannel),this.lastRenderAt=i}getCanvas(){return this.canvas.canvas}getDrawDetails(){return[this.canvas.canvas,0,0,this.dimensionContext.width,this.dimensionContext.height]}teardown(){try{this.animationCart.teardown?.(this.cartState,this.featureState)}catch(t){console.error("Error during cart teardown",t)}this.keyboardManager.destroy(),this.pointerManager.destroy()}};var je=class extends fe{constructor(t,n,r=1,i=!0,o={}){if(super(t,n,r,o),this.adopted)return;let a=o.container;if(a){this.canvas.parentNode!==a&&a.appendChild(this.canvas);return}if(i){let d=document.getElementById("canvas");d&&d!==this.canvas&&d.parentNode===document.body&&document.body.removeChild(d),document.body.appendChild(this.canvas)}}};function Xt(e){let t=parseInt(e.substring(0,8),16),n=parseInt(e.substring(8,8),16),r=parseInt(e.substring(16,8),16),i=parseInt(e.substring(24,8),16);return{next:()=>{t|=0,n|=0,r|=0,i|=0;let a=(t+n|0)+i|0;return i=i+1|0,t=n^n>>>9,n=r+(r<<3)|0,r=r<<21|r>>>11,r=r+a|0,(a>>>0)/4294967296},getRegs:()=>({a:t,b:n,c:r,d:i}),setRegs:a=>{t=a.a,n=a.b,r=a.c,i=a.d}}}var Te=class{constructor(t){this.seed=t.hash,this.useA=!1,this.genA=Xt(t.hash.substring(2,32)),this.genB=Xt(t.hash.substring(34,32)),this.prngA=this.genA.next,this.prngB=this.genB.next;for(let n=0;n<1e6;n+=2)this.prngA(),this.prngB()}getState(){let t=this.genA.getRegs(),n=this.genB.getRegs();return{seed:this.seed,useA:this.useA,prngA:{a:t.a,b:t.b,c:t.c,d:t.d},prngB:{a:n.a,b:n.b,c:n.c,d:n.d}}}setState(t){if(t.seed!==this.seed)throw new Error(`Random.setState: seed ${t.seed} does not match ${this.seed}`);this.useA=t.useA,this.genA.setRegs(t.prngA),this.genB.setRegs(t.prngB)}r_zero_one(){return this.useA=!this.useA,this.useA?this.prngA():this.prngB()}dec(t,n){return t===void 0?this.r_zero_one():n===void 0?t*this.r_zero_one():t+(n-t)*this.r_zero_one()}int(t,n){return n===void 0&&(n=t,t=0),Math.floor(this.dec(t,n))}bool(t=.5){return this.r_zero_one()<t}sign(){return this.bool()?1:-1}choose(t){return t[this.int(t.length)]}};var Zt="bafybeicjwcq5lxxtfnyj4p2ugcr7ctyb5wl62cbcechj6tsabdq5whcs7u",Qt="https://ipfs.io/ipfs/";function pr(e){return e.endsWith("/")?e:`${e}/`}var Ie=null;function fr(e){return[...Array(e)].map(()=>Math.floor(Math.random()*16).toString(16)).join("")}function mr(e){return e&&e.length>0?e:[{cid:Zt}]}function hr(e){return e.startsWith("0x")?e:`0x${e}`}var en=/^(0[xX])?[0-9a-fA-F]{64}$/;function yr(e){let t="",n=2166136261,r=522970236;for(let i=0;t.length<64;i++){for(let o=0;o<e.length;o++)n^=e.charCodeAt(o)+i,n=Math.imul(n,16777619),r^=e.charCodeAt(o)+i*17,r=Math.imul(r,16777619);t+=(n>>>0).toString(16).padStart(8,"0"),t+=(r>>>0).toString(16).padStart(8,"0")}return`0x${t.slice(0,64)}`}function ze(e){let t=typeof e=="number"?String(e):e;return en.test(t)?`0x${(t.startsWith("0x")||t.startsWith("0X")?t.slice(2):t).toLowerCase()}`:yr(t)}function We(e,t){if(typeof e=="number"||t==="deterministic")return ze(e);let n=String(e);return en.test(n)?ze(n):n.startsWith("0x")||n.startsWith("0X")?n:`0x${n}`}function gr(e){if(!e&&typeof tokenData<"u"&&tokenData?.hash)return{hash:tokenData.hash,tokenId:String(tokenData.tokenId),externalAssetDependencies:mr(tokenData.externalAssetDependencies),preferredIPFSGateway:pr(tokenData.preferredIPFSGateway||Qt),preferredArweaveGateway:tokenData.preferredArweaveGateway};let t=typeof window<"u"?new URLSearchParams(window.location.search):new URLSearchParams;return{hash:e?hr(e):t.get("hash")||`0x${fr(64)}`,tokenId:"18009999",externalAssetDependencies:[{cid:Zt}],preferredIPFSGateway:Qt}}function ct(e){let t=e?.useCache!==!1;if(t&&Ie&&!e?.hash)return Ie;let n=gr(e?.hash);return t?Ie=n:Ie||(Ie=n),n}function tn(e){return new Array(32).fill(null).map((t,n)=>parseInt(e.hash.slice(2+n*2,4+n*2),16))}async function pt(){let e=await import("tone");if(typeof e.start=="function")return e;let t=e.default;return t&&typeof t.start=="function"?t:e}var on={id:"tone",async load(){await Promise.resolve().then(()=>(rn(),Er))},async unlock(){await on.load(),await(await pt()).start()},async resumeIfSuspended(){let e=await pt();e.context.state==="suspended"&&await e.context.resume()},async suspendIfRunning(){let t=(await pt()).context.rawContext;"suspend"in t&&t.state==="running"&&await t.suspend()}},an={tone:on};function ft(e){if(!e)return[];let t=Array.isArray(e)?e:[e],n=[];for(let r of t){if(!(r in an)){console.warn(`Unknown audio library "${r}"`);continue}let i=r;n.includes(i)||n.push(i)}return n}function mt(e){return e.map(t=>an[t])}var Ye="$cyberartTa",j=class extends Error{constructor(t){super(t),this.name="IncompatibleCartStateError"}},ht={Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array};function Ar(e){for(let t of Object.keys(ht))if(e instanceof ht[t])return t}function dn(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function J(e){if(e===null||typeof e!="object"||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function yt(e){return J(e)?typeof e[Ye]=="string"&&Array.isArray(e.d):!1}function Cr(e){return e==null?!1:typeof e=="function"?!0:!(typeof e!="object"||Array.isArray(e)||dn(e)||J(e))}var Sr=new Set(["audioContextStarted","midiSynths","keepRatioPrimed","audioInitStarted","musicSeekApplied"]);function sn(e){return e===null?"null":yt(e)?String(e[Ye]):Array.isArray(e)?"array":J(e)?"object":typeof e}function wr(e,t){return e===t||e==="null"||t==="null"}function re(e){return e.trim().toLowerCase().replace(/^0x/,"")}function un(e,t,n,r){if(!(!n&&!r)&&re(e)!==re(t))throw new j(`Generative cart state is for seed "${t}", but the live token is "${e}"`)}function he(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function cn(e,t){let n=e.dimensions;if(n&&he(n.width)&&he(n.height))return n;if(t&&he(t.width)&&he(t.height))return{width:t.width,height:t.height};if(J(e.state)){let r=e.state.containerWidth,i=e.state.containerHeight;if(he(r)&&he(i))return{width:r,height:i}}return null}function ye(e,t=new WeakSet){if(e===null||typeof e=="string"||typeof e=="boolean")return e;if(typeof e=="number")return Number.isFinite(e)?e:null;if(!(typeof e=="function"||typeof e>"u"||typeof e=="bigint"||typeof e=="symbol")){if(dn(e)){let n=Ar(e);return n?{[Ye]:n,d:Array.from(e)}:void 0}if(typeof e=="object"&&!t.has(e)){t.add(e);try{if(Array.isArray(e)){let i=[],o=0;for(let a of e){let d=ye(a,t);d!==void 0&&(i.push(d),o++)}return e.length>0&&o===0?void 0:i}if(!J(e)||Cr(e))return;let n=Object.keys(e),r={};for(let i of n){if(Sr.has(i))continue;let o=ye(e[i],t);o!==void 0&&(r[i]=o)}return n.length>0&&Object.keys(r).length===0?void 0:r}finally{t.delete(e)}}}}function De(e){if(yt(e)){let t=ht[e[Ye]];return t?new t(e.d.map(n=>Number(n))):e}if(Array.isArray(e))return e.map(t=>De(t));if(J(e)){let t={};for(let n of Object.keys(e))t[n]=De(e[n]);return t}return e}function gt(e,t,n,r,i=!0){if(i&&n&&r&&n!==r)throw new j(`Cart state is for "${r}", but the live cart is "${n}"`);if(!J(t)){if(i)throw new j("Cart state snapshot is empty");return}let o=Object.keys(t);if(o.length===0){if(i)throw new j("Cart state snapshot is empty");return}let a=ye(e);if(!J(a)||Object.keys(a).length===0){if(i)throw new j("Live cart has no serializable state");return}let d=o.filter(u=>u in a);if(d.length===0){if(i)throw new j("Cart state snapshot does not overlap the live cart shape");return}for(let u of d){let g=sn(a[u]),m=sn(t[u]);if(!wr(g,m))throw new j(`Cart state field "${u}" has type ${m}, live cart expects ${g}`);if(g==="object"){let y=t[u],C=e[u];J(y)&&!yt(y)&&gt(C,y,void 0,void 0,!1)}}}function ln(e,t){if(!J(e)||!J(t))return;let n=ye(e);if(J(n))for(let r of Object.keys(t))r in n&&(e[r]=De(t[r]))}function pn(e){let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object")throw new j("Cart state bundle is not an object");if(t.version!==1)throw new j(`Unsupported cart state version ${String(t.version)}`);if(typeof t.seed!="string"||typeof t.framesElapsed!="number")throw new j("Cart state bundle is missing seed or framesElapsed");return t}var _e="cyberart.asset.ready",Oe="cyberart.asset.failed";function ie(e){try{return JSON.parse(JSON.stringify(e))}catch{return e}}function X(e){try{return JSON.stringify(e)}catch{return String(e)}}function bt(e,t,n){let r=t??[],i=n??[],o=Math.max(r.length,i.length);for(let a=0;a<o;a++)if(X(r[a])!==X(i[a]))return`${e}[${a}]: ${X(r[a])} vs ${X(i[a])}`}function fn(e,t){let n=[];e.seed!==t.seed&&n.push(`seed: ${e.seed} vs ${t.seed}`),e.clock.framesElapsed!==t.clock.framesElapsed&&n.push(`framesElapsed: ${e.clock.framesElapsed} vs ${t.clock.framesElapsed}`),e.clock.now!==t.clock.now&&n.push(`now: ${e.clock.now} vs ${t.clock.now}`),e.clock.frameRate!==t.clock.frameRate&&n.push(`frameRate: ${e.clock.frameRate} vs ${t.clock.frameRate}`),X(e.rng)!==X(t.rng)&&n.push(`rng: ${X(e.rng)} vs ${X(t.rng)}`);let r=bt("actions",e.actions,t.actions);r&&n.push(r);let i=bt("applied",e.applied,t.applied);i&&n.push(i);let o=bt("events",e.events,t.events);return o&&n.push(o),X(e.state)!==X(t.state)&&n.push(`state: ${X(e.state)} vs ${X(t.state)}`),n}function mn(e){return{type:e.status==="ready"?_e:Oe,kind:"state",payload:e.detail===void 0?{id:e.id}:{id:e.id,detail:e.detail}}}function Pr(e){if(!e||typeof e!="object")return 0;let t=e;return typeof t.startTime=="number"&&typeof t.lastSimulationUpdateAt=="number"?Math.max(0,t.lastSimulationUpdateAt-t.startTime):0}function kr(e,t){if(typeof window.resizeTo!="function")return!1;try{if(window.top!==window)return!1}catch{return!1}let n=Math.max(1,Math.round(e)),r=Math.max(1,Math.round(t)),i=Math.max(0,window.outerWidth-window.innerWidth),o=Math.max(0,window.outerHeight-window.innerHeight);try{window.resizeTo(n+i,r+o)}catch{return!1}return Math.abs(window.innerWidth-n)<=8&&Math.abs(window.innerHeight-r)<=8}var Rr=[[0,0],[16,9],[9,16],[4,3],[3,4],[2,1],[1,2],[3,1],[1,3],[1,1]],Et=Rr[0],Tr=Et[0]/Et[1],vt=30,Ir=120,Mr=3840/2160,Dr=2160/3840,Je=class{constructor(t=vt,n=!1,r=window.innerWidth,i=window.innerHeight,o=!0,a,d={}){this.framesElapsed=0;this.frameRate=vt;this._paused=!1;this.savedToken=!1;this.prepared=!1;this.loopRunning=!1;this.fallbackAudio=[];this.audioLibrariesInternal=[];this.virtualClock=null;this.scriptedActions=[];this.initialScriptedActions=[];this.appliedActions=[];this.consumedActionIndexes=new Set;this.outboundEvents=[];this.consecutiveErrorCount=0;this.lastErrorLogAt=0;this.reinitStayPaused=!1;this.reinitPending=!1;this.lastExportedFramebuffer=null;this.pinnedOutput=null;this.pinViewportAtImport=null;this.importing=!1;this.drawLoop=this.drawLoop.bind(this),this.loadCart=this.loadCart.bind(this),this.prepareCart=this.prepareCart.bind(this),this.beginPlayback=this.beginPlayback.bind(this),this.reinit=this.reinit.bind(this),this.tuneFramerate=this.tuneFramerate.bind(this),this.container=d.container,this.seed=d.seed,this.captureKeyboard=d.captureKeyboard??!0,this.customState=d.customState,this.hostChannel=d.hostChannel,this.fallbackAudio=ft(d.audio),this.audioLibrariesInternal=this.fallbackAudio;let u=d.deterministic;this.deterministic=!!u;let g=u&&typeof u=="object"?u:{};if(this.deterministic){if(d.clock){let m=d.clock;if(typeof m.advance!="function")throw new Error("deterministic mode requires a virtual clock with advance()");this.virtualClock=m,this.clock=m}else this.virtualClock=Be(g.origin??0),this.clock=this.virtualClock;this.initialScriptedActions=ie(g.actions??[]),this.scriptedActions=ie(this.initialScriptedActions)}else this.clock=d.clock??me();this.isBodyCanvas=this.container?!1:o,this.autoMode=n,this.aspectRatio=Tr,this.selectedAsp=Et,this.isFullscreen=!!document.fullscreenElement,this.updateFrameRate(t),this.tempUnpause=!1,this.synchronous=pe,this.containerWidth=r,this.containerHeight=i,this.gameManager=a,this.init(!0)}setGameManager(t){this.gameManager=t}reinit(t){if(!this.importing){if(this.shouldKeepPinnedOutput()){this.fitPinnedCanvas();return}this.reinitPending||(this.reinitStayPaused=this._paused,this.reinitPending=!0),this.paused=!0,clearTimeout(this.reinitTimeout),this.reinitTimeout=setTimeout(()=>{if(this.importing){this.paused=this.reinitStayPaused,this.reinitPending=!1;return}this.updateInProgress?this.reinit(t):(this.requestedAnimationFrame&&cancelAnimationFrame(this.requestedAnimationFrame),this.clearPinnedOutput(),this.init(),this.reloadCart(),this.paused=this.reinitStayPaused,this.reinitPending=!1)},150)}}initSeed(){this.tokenData=this.seed?ct({hash:this.seed,useCache:!1}):ct(),this.rawParams=tn(this.tokenData),this.mintNo=parseInt(this.tokenData.tokenId)%1e6,console.log("token",this.mintNo,this.tokenData.hash)}init(t=!1){t&&this.initSeed(),this.pureAspectUpdate(this.selectedAsp);let n=this.aspectRatio,[r,i]=Wt(n,this.containerWidth,this.containerHeight);r*=z,i*=z,this.width=~~r,this.height=~~i,this.atCenterX=this.width/2,this.atCenterY=this.height/2,this.mainCanvas?this.mainCanvas.setSize(this.width,this.height):this.mainCanvas=new je(this.width,this.height,1,this.isBodyCanvas,this.canvasMountOptions())}loadCart(t){this.prepareCart(t)&&this.beginPlayback()}prepareCart(t){if(this.prepared)return!0;try{let n=~~(this.width/1),r=~~(this.height/this.width*n),i=new Te(this.tokenData),o=new Ue(n,r,i,this.rawParams,t,{gameManager:this.gameManager,canvasMount:this.canvasMountOptions(),customState:this.customState,captureKeyboard:this.deterministic?!1:this.captureKeyboard,hostChannel:this.hostChannel,clock:this.clock,listenToPointer:!this.deterministic});return this.animation=o,this.animationCart=t,this.paused=!1,this.framesElapsed=0,this.outboundEvents=[],this.scriptedActions=ie(this.initialScriptedActions),this.appliedActions=[],this.consumedActionIndexes=new Set,this.outboundUnsubscribe?.(),this.outboundUnsubscribe=void 0,this.deterministic&&this.hostChannel&&(this.outboundUnsubscribe=this.hostChannel.onEvent(a=>{this.outboundEvents.push(a)})),this.R=i,this.applyCartFrameRate(t,o),this.resolveAudioLibraries(t),this.prepared=!0,!0}catch(n){return console.error(n),!1}}applyCartFrameRate(t,n){let r=t.metadata,i=r?.frameRate??vt,o=n.cartState?.visualMode??n.featureState?.visualMode,a=o&&r?.frameRateByVisualMode?r.frameRateByVisualMode[o]:void 0;this.updateFrameRate(typeof a=="number"&&a>0?a:i)}get audioLibraries(){return this.audioLibrariesInternal}get needsAudio(){return this.audioLibrariesInternal.length>0}resolveAudioLibraries(t){this.audioLibrariesInternal=ft(t.metadata?.audio)}async unlockAudio(){if(this.audioLibrariesInternal.length===0)return;let t=mt(this.audioLibrariesInternal);if(pe){for(let n of t)await n.load();return}for(let n of t)await n.unlock()}async resumeAudioLibraries(){if(!(this.paused||pe))for(let t of mt(this.audioLibrariesInternal))try{await t.resumeIfSuspended()}catch(n){console.error(`Failed to resume audio library "${t.id}" after reload`,n)}}beginPlayback(){!this.prepared||this.loopRunning||(this.prepared=!1,this.loopRunning=!0,this.consecutiveErrorCount=0,!this.deterministic&&(this.requestedAnimationFrame=requestAnimationFrame(this.drawLoop)))}get isPrepared(){return this.prepared}get isLoopRunning(){return this.loopRunning}get isDeterministic(){return this.deterministic}getClock(){return{now:this.clock.now(),framesElapsed:this.framesElapsed,frameRate:this.frameRate}}getRandomState(){return this.requirePreparedAnimation().getRandomState()}schedule(t){this.scriptedActions.push(ie(t))}async getReplayMetadata(){let t=await this.exportState();return{seed:this.tokenData.hash,clock:this.getClock(),rng:this.getRandomState(),actions:ie(this.scriptedActions),applied:ie(this.appliedActions),events:ie(this.outboundEvents),state:t.state}}async step(t=1){if(!this.deterministic)throw new Error("step() requires createRuntime({ deterministic: true })");this.requirePreparedAnimation(),this.prepared&&!this.loopRunning&&this.beginPlayback(),this.paused=!1;let n=Math.max(0,Math.floor(t));for(let r=0;r<n&&this.animation;r++){let i=this.framesElapsed;if(this.applyScheduledActions(i),await this.processFrame(this.clock.now(),{ignorePause:!0,scheduleNext:!1}),this.framesElapsed===i||(this.virtualClock?.advance(this.targetDrawTime),!this.loopRunning))break}}async advance(t){let n=Math.max(0,Math.round(t/this.targetDrawTime));await this.step(n)}applyScheduledActions(t){let n=this.animation;n&&this.scriptedActions.forEach((r,i)=>{r.atFrame===t&&(this.consumedActionIndexes.has(i)||(this.consumedActionIndexes.add(i),r.type==="pointer"?n.injectPointer(r.pointer.kind,r.pointer.x,r.pointer.y):r.type==="key"?n.injectKey(r.key):r.type==="event"?this.hostChannel?.dispatch(r.event):r.type==="asset"&&this.hostChannel?.dispatch(mn(r)),this.appliedActions.push({frame:t,action:r})))})}get paused(){return this._paused}set paused(t){this._paused!==t&&(this._paused=t,this.animation?.setPaused(t))}async waitUntilUpdateIdle(){for(;this.updateInProgress;)await new Promise(t=>{this.deterministic?queueMicrotask(t):typeof requestAnimationFrame=="function"?requestAnimationFrame(()=>t()):setTimeout(t,0)})}requirePreparedAnimation(){if(!this.animation)throw new Error("No prepared cart");return this.animation}async exportState(){let t=this.requirePreparedAnimation(),n=this._paused;this.paused=!0,await this.waitUntilUpdateIdle();try{this.lastExportedFramebuffer=t.captureFramebuffer();let r=t.getCanvas();return{version:1,cartId:this.animationCart?.metadata?.id,generative:this.animationCart?.metadata?.generative,seed:this.tokenData.hash,framesElapsed:this.framesElapsed,elapsedSinceStart:t.getElapsedSinceStart(),dimensions:{width:r.width,height:r.height,cssWidth:this.containerWidth,cssHeight:this.containerHeight,dpr:z},state:ye(t.cartState)}}finally{this.paused=n}}async exportStateJSON(){return JSON.stringify(await this.exportState())}peekExportedFramebuffer(){return this.lastExportedFramebuffer}peekSeed(){return this.tokenData?.hash}isGenerative(){return this.animationCart?.metadata?.generative===!0}async importState(t,n){let r=this.requirePreparedAnimation(),i=pn(t),o=this._paused,a=this.loopRunning;this.paused=!0,await this.waitUntilUpdateIdle(),gt(r.cartState,i.state,this.animationCart?.metadata?.id,i.cartId),un(this.tokenData.hash,i.seed,this.animationCart?.metadata?.generative,i.generative),clearTimeout(this.reinitTimeout),this.reinitPending=!1,this.importing=!0;let d=cn(i,n?.framebuffer??this.lastExportedFramebuffer);if(d){this.pinOutputSize(d);let m=d.cssWidth??d.width/z,y=d.cssHeight??d.height/z;kr(m,y),this.syncContainerFromDom(),this.pinViewportAtImport={w:this.containerWidth,h:this.containerHeight}}let u=this.customState,g=!1;try{if(this.customState=De(i.state),this.unloadCart(),!this.prepareCart(this.animationCart))throw new Error("Failed to prepare cart while loading state");this.animation.cartState!==this.customState&&ln(this.animation.cartState,i.state),this.framesElapsed=i.framesElapsed;let m=this.animation,y=m.cartState,C=typeof i.elapsedSinceStart=="number"?i.elapsedSinceStart:Pr(y);m.restoreClock(C,typeof y?.startTime=="number"?y.startTime:void 0),o&&m.setPaused(!0);let E=n?.framebuffer??this.lastExportedFramebuffer;E&&m.restoreFramebuffer(E)?y.keepRatioPrimed=!0:await m.renderAnimation(this.framesElapsed,this.rawParams),this.fitPinnedCanvas(),g=!0}catch(m){throw this.clearPinnedOutput(),this.customState=u,this.paused=o,this.animationCart&&(this.syncContainerFromDom(),this.init(),this.reloadCart()),m}finally{this.importing=!1,g&&(this.customState=u,this.paused=o,a&&this.beginPlayback())}}unloadCart(){this.loopRunning=!1,this.requestedAnimationFrame&&cancelAnimationFrame(this.requestedAnimationFrame),this.drawLoopTimeout&&clearTimeout(this.drawLoopTimeout),this.animation?.teardown(),this.animation=void 0,this.prepared=!1,this.audioLibrariesInternal=this.fallbackAudio,this.mainCanvas?.clearAll()}reloadCart(t=!1){let n=this.animationCart;if(!n)return;this.pinnedOutput&&(this.clearPinnedOutput(),this.syncContainerFromDom(),this.init());let r=this.reinitPending?this.reinitStayPaused:this._paused;this.unloadCart(),t&&this.initSeed(),this.loadCart(n),this.paused=r,!this.paused&&!pe&&this.resumeAudioLibraries()}getFrameRate(){return this.frameRate}updateFrameRate(t){if(this.frameRate=t,t>=1)this.targetDrawTime=1e3/t;else{let r=1/(2-t);this.targetDrawTime=1e3/r}this.drawTime=this.targetDrawTime}canvasMountOptions(){return{container:this.container,adoptFromDocument:!this.container}}syncContainerFromDom(){if(this.container){this.containerWidth=this.container.clientWidth||this.containerWidth,this.containerHeight=this.container.clientHeight||this.containerHeight;return}this.containerWidth=window.innerWidth,this.containerHeight=window.innerHeight}pinOutputSize(t){this.pinnedOutput=t,this.width=~~t.width,this.height=~~t.height,this.atCenterX=this.width/2,this.atCenterY=this.height/2,this.aspectRatio=this.width/this.height,this.mainCanvas&&this.mainCanvas.setSize(this.width,this.height)}shouldKeepPinnedOutput(){return this.pinnedOutput?(this.syncContainerFromDom(),this.viewportMatches(this.pinnedCssSize())?!0:!!(this.pinViewportAtImport&&this.viewportMatches(this.pinViewportAtImport))):!1}pinnedCssSize(){let t=this.pinnedOutput;return{w:t.cssWidth??t.width/z,h:t.cssHeight??t.height/z}}viewportMatches(t){return Math.abs(this.containerWidth-t.w)<8&&Math.abs(this.containerHeight-t.h)<8}fitPinnedCanvas(){let t=this.pinnedOutput,n=this.canvas;if(!t||!n)return;this.container&&!this.container.style.position&&(this.container.style.position="relative");let r=this.containerWidth||window.innerWidth,i=this.containerHeight||window.innerHeight,o=t.width/z,a=t.height/z;if(o<1||a<1||r<1||i<1)return;let d=Math.min(r/o,i/a),u=o*d,g=a*d;n.style.position="absolute",n.style.left="50%",n.style.top="50%",n.style.transform="translate(-50%, -50%)",n.style.margin="0",n.style.width=`${u}px`,n.style.height=`${g}px`,n.style.imageRendering=Math.abs(d-1)<.01?"auto":"pixelated"}clearPinnedOutput(){let t=this.canvas;this.pinnedOutput=null,this.pinViewportAtImport=null,t&&(t.style.position="",t.style.left="",t.style.top="",t.style.transform="",t.style.imageRendering="",t.style.width="",t.style.height="",t.style.margin="auto")}get canvas(){return this.animation?.getCanvas()??this.mainCanvas?.canvas}destroy(){this.outboundUnsubscribe?.(),this.outboundUnsubscribe=void 0,this.clearPinnedOutput(),this.unloadCart(),clearTimeout(this.reinitTimeout),this.mainCanvas&&!this.mainCanvas.adopted&&this.mainCanvas.canvas.remove()}drawIt(){}tuneFramerate(t){let n=this.lastCall||t;this.lastCall=t,this.drawTime=Math.max(0,this.drawTime+this.targetDrawTime-this.lastCall+n)}async processFrame(t,n={}){let r=n.ignorePause===!0,i=n.scheduleNext!==!1;if(!this.loopRunning&&!r)return;let o=!1,a,d="update";try{if(r||!this.paused||this.tempUnpause){if(!pe&&!r&&this.tuneFramerate(t),!this.animation)return;if(d="update",this.updateInProgress=!0,await this.animation.updateAnimationState(this.framesElapsed,this.rawParams,t),this.updateInProgress=!1,d="render",await this.animation.renderAnimation(this.framesElapsed,this.rawParams,t),this.autoMode&&this.animation.cartState.saveToken&&!this.savedToken&&!new URLSearchParams(window.location.search).get("hash")){let m=localStorage.getItem("goodones"),y=JSON.stringify(m?[...JSON.parse(m),this.tokenData.hash]:[this.tokenData.hash]);localStorage.setItem("goodones",y),this.savedToken=!0,localStorage.setItem(this.tokenData.hash,this.mainCanvas.canvas.toDataURL("image/png")),window.location.reload(),this.loopRunning=!1;return}this.framesElapsed++,this.tempUnpause&&(this.tempUnpause=!1)}d="draw",this.drawIt()}catch(u){o=!0,a=u,this.handleFrameError(u,d)}finally{this.updateInProgress=!1}o?(this.consecutiveErrorCount++,this.consecutiveErrorCount>=Ir&&(this.loopRunning=!1,this.onError?.(a,{phase:d,consecutive:this.consecutiveErrorCount,stopped:!0}))):this.consecutiveErrorCount=0,!(!this.loopRunning||!i)&&(this.drawLoopTimeout=setTimeout(()=>{this.requestedAnimationFrame=requestAnimationFrame(this.drawLoop)},this.drawTime))}async drawLoop(t){await this.processFrame(t,{scheduleNext:!0})}handleFrameError(t,n){let r=performance.now();r-this.lastErrorLogAt>=1e3&&(this.lastErrorLogAt=r,console.error(`Animation ${n} error:`,t)),this.consecutiveErrorCount===0&&this.onError?.(t,{phase:n,consecutive:1,stopped:!1})}pureAspectUpdate(t){if(t[0]===0&&t[1]===0){let r=this.containerWidth||window.innerWidth,i=this.containerHeight||window.innerHeight,o=r/i;this.aspectRatio=Math.min(Mr,Math.max(Dr,o))}else this.aspectRatio=t[0]/t[1]}};var _r="HostChannel has been destroyed",ge=class{constructor(){this.inbound=[];this.listeners=[];this.closed=!1}dispatch(t){this.requireOpen(),this.inbound.push(t),this.inbound.length>32&&this.inbound.splice(0,this.inbound.length-32)}consume(){if(this.requireOpen(),this.inbound.length===0)return[];let t=this.inbound;return this.inbound=[],t}emit(t){this.requireOpen();for(let n of this.listeners)n(t)}onEvent(t){return this.requireOpen(),this.listeners.push(t),()=>{this.listeners=this.listeners.filter(n=>n!==t)}}clearInbound(){this.requireOpen(),this.inbound=[]}clear(){this.inbound=[],this.listeners=[]}close(){this.closed=!0,this.clear()}requireOpen(){if(this.closed)throw new Error(_r)}};var vn=["image","audio","font","spritesheet"],En=["timeout","cors","not-found","invalid","aborted","resolver"],be="cyberart:fallback/silent",hn="Asset preloader has been destroyed",Or=4,Fr=new Set(vn),Nr=new Set(En),Lr={timeout:"asset load timed out",cors:"CORS blocked this asset","not-found":"asset was not found",invalid:"asset declaration or resource is invalid",aborted:"asset load was aborted",resolver:"asset resolver failed"};function An(e){return typeof e=="string"&&Fr.has(e)}function Cn(e){return typeof e=="string"&&Nr.has(e)}function Xe(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.id=="string"&&typeof t.ref=="string"&&Cn(t.code)&&typeof t.message=="string"}function H(e){return{id:e.id,ref:e.ref,code:e.code,message:e.message&&e.message.length>0?e.message:Lr[e.code]}}function ce(e,t){return{type:e==="ready"?_e:Oe,kind:"state",payload:t}}function Sn(e){if(!e?.aborted)return;let t=new Error("aborted");throw t.name="AbortError",t}function Vr(e){return e instanceof Error&&e.name==="AbortError"||typeof DOMException<"u"&&e instanceof DOMException&&e.name==="AbortError"}function At(e){return e?{...e}:void 0}function te(e){let t={id:e.id,ref:e.ref,type:e.type,url:e.url};return e.integrity!==void 0&&(t.integrity=e.integrity),e.provenance&&(t.provenance=At(e.provenance)),e.cors!==void 0&&(t.cors=e.cors),e.usedFallback&&(t.usedFallback=!0),e.managed&&(t.managed=!0),t}function Fe(e){return{id:e.id,ref:e.ref,code:e.code,message:e.message}}function Hr(e){if(e.state==="ready"){let t={state:"ready",resource:te(e.resource)};return e.failure&&(t.failure=Fe(e.failure)),t}return e.state==="failed"?{state:"failed",failure:Fe(e.failure)}:{state:e.state}}function Kr(e){return/^https?:/i.test(e)}function wn(e){return e.endsWith("/")?e:`${e}/`}function xn(e,t){let n=wn(t);if(/^(https?:|data:|blob:)/i.test(e))return e;let r=/^moltazine:post\/([^#]+)#(.+)$/.exec(e);if(r)return`${n}moltazine/${encodeURIComponent(r[1])}/${r[2]}`;let i=/^world:asset\/(.+)$/.exec(e);if(i)return`${n}world/${i[1]}`;let o=/^library:(.+)$/.exec(e);return o?`${n}library/${o[1]}`:`${n}${e.replace(/^\//,"")}`}function Gr(e){return{async resolve(t,n){Sn(n);let r=e[t.ref];if(!r)throw H({id:t.id,ref:t.ref,code:"not-found",message:`no fixture for ${t.ref}`});if("error"in r)throw H({id:t.id,ref:t.ref,code:r.error,message:r.message});return{id:t.id,ref:t.ref,type:t.type,url:r.url,integrity:r.integrity??t.integrity,cors:r.cors??"omit",provenance:r.provenance??t.provenance}}}}function $r(e){let t=wn(e.cdnBase);return{async resolve(n,r){Sn(r);let i=e.failures?.[n.ref];if(i){let a=typeof i=="string"?i:i.code,d=typeof i=="string"?void 0:i.message;throw H({id:n.id,ref:n.ref,code:a,message:d})}let o=xn(n.ref,t);return{id:n.id,ref:n.ref,type:n.type,url:o,integrity:n.integrity,cors:Kr(o)?"anonymous":"omit",provenance:n.provenance}}}}function Br(e){if(!e||typeof e!="object")return H({id:"",ref:"",code:"invalid",message:"declaration is required"});if(typeof e.id!="string"||e.id.length===0)return H({id:typeof e.id=="string"?e.id:"",ref:typeof e.ref=="string"?e.ref:"",code:"invalid",message:"id is required"});if(typeof e.ref!="string"||e.ref.length===0)return H({id:e.id,ref:"",code:"invalid",message:"ref is required"});if(!An(e.type))return H({id:e.id,ref:e.ref,code:"invalid",message:`unsupported type ${String(e.type)}`});if(e.integrity!==void 0&&typeof e.integrity!="string")return H({id:e.id,ref:e.ref,code:"invalid",message:"integrity must be a string"});if(e.timeoutMs!==void 0&&(typeof e.timeoutMs!="number"||!Number.isFinite(e.timeoutMs)||e.timeoutMs<0))return H({id:e.id,ref:e.ref,code:"invalid",message:"timeoutMs must be a non-negative finite number"})}function yn(e){return{id:e.id,ref:be,type:e.type,url:be,usedFallback:!0,cors:"omit"}}function gn(e,t){return Xe(t)?{id:e.id,ref:e.ref,code:t.code,message:t.message}:Vr(t)?H({id:e.id,ref:e.ref,code:"aborted"}):H({id:e.id,ref:e.ref,code:"resolver",message:t instanceof Error?t.message:String(t)})}function bn(e,t){if(!t||typeof t.url!="string"||t.url.length===0)throw H({id:e.id,ref:e.ref,code:"invalid",message:"resolver returned no url"});if(t.integrity&&e.integrity&&t.integrity!==e.integrity)throw H({id:e.id,ref:e.ref,code:"invalid",message:"integrity mismatch"});let n=te(t);return n.id=e.id,n.ref=t.ref||e.ref,n.type=e.type,!n.integrity&&e.integrity&&(n.integrity=e.integrity),!n.provenance&&e.provenance&&(n.provenance=At(e.provenance)),n}function Ct(e){if(typeof e?.resolver?.resolve!="function")throw new Error("createAssetPreloader: resolver is required");let t=e.emitEvents!==!1,n=e.wallClockTimeout!==!1,r=new Map,i=[],o=new Map,a=new Map,d=new Map,u=new Map,g=new Map,m=new Set,y=!1;function C(s){return s.code==="aborted"||s.code==="timeout"}function E(s,v,A){let R=gn(s,A);return R.code==="timeout"?R:v.aborted?H({id:s.id,ref:s.ref,code:"aborted"}):R}function N(s,v){let A=g.get(s);A||(A=new Set,g.set(s,A)),A.add(v)}function f(s){if(s?.state==="ready")return`${s.resource.type}\0${s.resource.ref}`}function l(s,v){for(let[A,R]of g)if(A!==v&&R.has(s))return!0;for(let[A,R]of r)if(A!==v&&f(R)===s)return!0;return!1}function P(s,v){let A=new Set(g.get(s)),R=f(v);R&&A.add(R),g.delete(s);for(let $ of A)l($,s)||d.delete($)}function T(){let s=0,v=0,A=0,R=0,$={};for(let[O,M]of r)$[O]=Hr(M),M.state==="pending"||M.state==="loading"?s+=1:M.state==="failed"?A+=1:(v+=1,(M.resource.usedFallback||M.failure)&&(R+=1));return{total:r.size,pending:s,ready:v,failed:A,fallbacks:R,items:$,failures:i.map(Fe)}}function W(){if(m.size===0)return;let s=T();for(let v of m)v(s)}function L(s){i.push(Fe(s))}function p(s){y||!t||!e.dispatch||e.dispatch(s)}function I(s){if(s?.managed&&s.url.startsWith("blob:")&&!(typeof URL>"u"||typeof URL.revokeObjectURL!="function"))try{URL.revokeObjectURL(s.url)}catch{}}function S(s,v){if(y)return;let A=r.get(s);A?.state==="ready"&&I(A.resource),r.set(s,v),W()}function _(s){if(s.fallback!==void 0)return s.fallback==="silent"?{id:`${s.id}::fallback`,ref:be,type:s.type}:typeof s.fallback=="string"?{id:`${s.id}::fallback`,ref:s.fallback,type:s.type}:{...s.fallback,id:typeof s.fallback.id=="string"&&s.fallback.id.length>0?s.fallback.id:`${s.id}::fallback`}}function F(s,v,A){let R=`${s.type}\0${s.ref}`,$=d.get(R);if($)return v.aborted?Promise.reject(H({id:s.id,ref:s.ref,code:"aborted"})):(N(A,R),Promise.resolve(te($.resource)));if(v.aborted)return Promise.reject(H({id:s.id,ref:s.ref,code:"aborted"}));let O=u.get(R);if(!O){let k=new AbortController,V={id:s.id,ref:s.ref,type:s.type};s.integrity!==void 0&&(V.integrity=s.integrity),s.provenance&&(V.provenance=At(s.provenance)),O={promise:Promise.resolve().then(()=>e.resolver.resolve(V,k.signal)).then(K=>{let ee=bn(s,K);if(k.signal.aborted)throw H({id:s.id,ref:s.ref,code:"aborted"});return d.set(R,{resource:te(ee)}),ee}).catch(K=>{throw gn(s,K)}).finally(()=>{u.delete(R)}),controller:k,waiters:0},u.set(R,O)}let M=O;return M.waiters+=1,new Promise((k,V)=>{let Z=!1,K=(ne,ut)=>{Z||(Z=!0,v.removeEventListener("abort",ee),M.waiters-=1,ut&&M.waiters<=0&&M.controller.abort(),ne())},ee=()=>{K(()=>V(H({id:s.id,ref:s.ref,code:"aborted"})),!0)};if(v.aborted){ee();return}v.addEventListener("abort",ee,{once:!0}),M.promise.then(ne=>{if(!Z){if(v.aborted){ee();return}N(A,R),K(()=>k(te(ne)),!1)}},ne=>{if(!Z){if(v.aborted){ee();return}K(()=>V(ne),!1)}})})}function U(s,v,A){if(v.aborted)return Promise.reject(H({id:s.id,ref:s.ref,code:"aborted"}));if(s.ref===be)return Promise.resolve(yn(s));let R=new AbortController,$=()=>R.abort();v.addEventListener("abort",$,{once:!0});let O=s.timeoutMs??e.timeoutMs,M,k=!1;return n&&O!==void 0&&O>0&&Number.isFinite(O)&&(M=setTimeout(()=>{k=!0,R.abort()},O)),F(s,R.signal,A).then(V=>{let Z=bn(s,V);return Z.id=s.id,Z}).catch(V=>{throw k?H({id:s.id,ref:s.ref,code:"timeout"}):V}).finally(()=>{M!==void 0&&clearTimeout(M),v.removeEventListener("abort",$)})}async function q(s,v,A,R){try{return{resource:await U(s,v,R)}}catch($){let O=E(s,v,$);if(C(O)||v.aborted||A>=Or)throw O;let M=_(s);if(!M)throw O;if(v.aborted)throw H({id:s.id,ref:s.ref,code:"aborted"});if(s.fallback==="silent"||M.ref===be)return{resource:yn(s),failure:O};try{let k=await q(M,v,A+1,R);return{resource:{...te(k.resource),id:s.id,usedFallback:!0},failure:O}}catch(k){let V=Xe(k)&&!C(k)&&!v.aborted?k:E(s,v,k);throw!C(V)&&!v.aborted&&L(O),V}}}async function ue(s,v){if(y)throw new Error(hn);let A=r.get(s.id);if(A?.state==="ready"||A?.state==="failed")return;let R=o.get(s.id);if(R){await R;return}let $=(async()=>{let O=Br(s);if(O){S(s.id,{state:"failed",failure:O}),L(O),p(ce("failed",{id:s.id,ref:s.ref,failure:O}));return}S(s.id,{state:"loading"});let M=a.get(s.id)??new AbortController;a.has(s.id)||a.set(s.id,M);try{let k=await q(s,M.signal,v,s.id);if(y)return;if(M.signal.aborted){let V=H({id:s.id,ref:s.ref,code:"aborted"});S(s.id,{state:"failed",failure:V}),L(V),p(ce("failed",{id:s.id,ref:s.ref,failure:V}));return}if(k.resource.id=s.id,k.failure){S(s.id,{state:"ready",resource:k.resource,failure:k.failure}),L(k.failure),p(ce("failed",{id:s.id,ref:s.ref,failure:k.failure,resource:te(k.resource)})),p(ce("ready",{id:s.id,ref:k.resource.ref,resource:te(k.resource),failure:k.failure}));return}S(s.id,{state:"ready",resource:k.resource}),p(ce("ready",{id:s.id,ref:s.ref,resource:te(k.resource)}))}catch(k){if(y)return;let V=Xe(k)&&!C(k)&&!M.signal.aborted?{...Fe(k),id:s.id}:E(s,M.signal,k);S(s.id,{state:"failed",failure:V}),L(V),p(ce("failed",{id:s.id,ref:s.ref,failure:V}))}finally{a.get(s.id)===M&&a.delete(s.id)}})();o.set(s.id,$);try{await $}finally{o.delete(s.id)}}return{async preload(s){if(y)throw new Error(hn);let v=Array.isArray(s)?s:[];for(let A of v)A&&typeof A.id=="string"&&A.id.length>0&&(r.has(A.id)||r.set(A.id,{state:"pending"}),a.has(A.id)||a.set(A.id,new AbortController));return W(),await Promise.all(v.map(A=>ue(A,0))),T()},get(s){let v=r.get(s);if(v?.state==="ready")return te(v.resource)},getProgress(){return T()},onProgress(s){return m.add(s),()=>{m.delete(s)}},abort(s){if(!y){if(s!==void 0){a.get(s)?.abort();return}for(let v of a.values())v.abort()}},forget(s){if(y)return;if(s===void 0){for(let A of r.values())A.state==="ready"&&I(A.resource);r.clear(),i.length=0,d.clear(),g.clear(),W();return}let v=r.get(s);v?.state==="ready"&&I(v.resource),P(s,v),r.delete(s);for(let A=i.length-1;A>=0;A--)i[A].id===s&&i.splice(A,1);W()},dispose(){if(!y){y=!0;for(let s of a.values())s.abort();a.clear();for(let s of r.values())s.state==="ready"&&I(s.resource);r.clear(),i.length=0,o.clear();for(let s of u.values())s.controller.abort();d.clear(),u.clear(),g.clear(),m.clear()}}}}function St(e){Ut();let{container:t,seed:n,captureKeyboard:r=!1,audio:i,deterministic:o,assets:a}=e,d=n===void 0?void 0:We(n,o?"deterministic":"live"),u=new ge;if(a&&typeof a.resolver?.resolve!="function")throw new Error("createRuntime: assets.resolver is required");let g=a?Ct({resolver:a.resolver,timeoutMs:a.timeoutMs,emitEvents:a.emitEvents??!o,wallClockTimeout:!o,dispatch:L=>u.dispatch(L)}):void 0,m=!1,y=null,C,E=!1,N=t.clientWidth||window.innerWidth,f=t.clientHeight||window.innerHeight,l=new Je(30,!1,N,f,!1,void 0,{container:t,seed:d,captureKeyboard:r,hostChannel:u,audio:i,deterministic:o}),P=()=>{let L=t.clientWidth||window.innerWidth,p=t.clientHeight||window.innerHeight;return L===l.containerWidth&&p===l.containerHeight?!1:(l.containerWidth=L,l.containerHeight=p,!0)},T=null;return!l.isDeterministic&&typeof ResizeObserver<"u"&&(T=new ResizeObserver(()=>{if(m||!y)return;P()&&E&&l.reinit()}),T.observe(t)),l.onError=(L,p)=>{C?.(L,p)},{get tokenData(){return l.tokenData},get hostChannel(){return u},get assets(){return g},get onError(){return C},set onError(L){C=L},mount(L,p={}){if(m)throw new Error("createRuntime: cannot mount on a destroyed runtime");y?.destroy(),E=!1,l.customState=p.initialState,l.setGameManager(p.gameManager);let I=p.onEvent?u.onEvent(p.onEvent):()=>{};if(!l.prepareCart(L))throw I(),new Error("createRuntime: failed to prepare cart");let S=!1,_={async start(){if(!S){if(P()&&l.isPrepared&&(l.init(),l.unloadCart(),!l.prepareCart(L)))throw new Error("createRuntime: failed to prepare cart");l.needsAudio&&(await l.unlockAudio(),S)||(E=!0,l.beginPlayback())}},pause(){S||(l.paused=!0)},resume(){S||(l.paused=!1)},dispatch(F){S||u.dispatch(F)},snapshot(){if(S)return{seed:"",pngDataUrl:""};let F=l.canvas;return{seed:l.tokenData.hash,metadata:L.metadata,pngDataUrl:F?F.toDataURL("image/png"):""}},destroy(){S||(S=!0,E=!1,I(),u.clearInbound(),l.unloadCart(),y===_&&(y=null))},reload(){if(!S){if(!E){if(l.isPrepared&&(l.unloadCart(),!l.prepareCart(L)))throw new Error("createRuntime: failed to prepare cart");return}l.reloadCart()}},reinit(F){if(!S){if(!E){P();return}l.reinit(F)}},getCartState(){return l.animation?.cartState},exportState(){return S?Promise.reject(new Error("Cart handle has been destroyed")):l.exportState()},exportStateJSON(){return S?Promise.reject(new Error("Cart handle has been destroyed")):l.exportStateJSON()},async importState(F,U){if(S)throw new Error("Cart handle has been destroyed");await l.importState(F,U)},peekExportedFramebuffer(){return S?null:l.peekExportedFramebuffer()},peekSeed(){if(!S)return l.peekSeed()},isGenerative(){return S?!1:l.isGenerative()},async step(F=1){if(S)throw new Error("Cart handle has been destroyed");await l.step(F)},async advance(F){if(S)throw new Error("Cart handle has been destroyed");await l.advance(F)},schedule(F){S||l.schedule(F)},getClock(){if(S)throw new Error("Cart handle has been destroyed");return l.getClock()},getRandomState(){if(S)throw new Error("Cart handle has been destroyed");return l.getRandomState()},getReplayMetadata(){return S?Promise.reject(new Error("Cart handle has been destroyed")):l.getReplayMetadata()},get canvas(){return l.canvas},get paused(){return l.paused},set paused(F){S||(l.paused=F)},get tokenData(){return l.tokenData},get isPrepared(){return l.isPrepared},get isLoopRunning(){return l.isLoopRunning},get needsAudio(){return l.needsAudio},get audioLibraries(){return l.audioLibraries}};return y=_,_},async unlockAudio(){await l.unlockAudio()},destroy(){m||(m=!0,y?.destroy(),y=null,T?.disconnect(),T=null,g?.dispose(),u.close(),l.destroy())}}}var ve="cyberart.state.save",Ee="cyberart.state.load";function Ur(e,t,n={}){let r=n.persist,i=r?{persist:r}:void 0,o=()=>{t.emit({type:ve,payload:i})},a=()=>{t.emit({type:Ee,payload:i})};e.registerAction("w",o,!0),e.registerAction("W",o,!0),e.registerAction("e",a,!0),e.registerAction("E",a,!0)}function Pn(e){if(e.type!==ve&&e.type!==Ee)return;let t=e.payload?.persist;return t==="localStorage"?t:void 0}var jr="cyberart-io",zr=1,oe="framebuffers";function wt(e,t){return`${e||"unknown"}:${t?re(t):"none"}`}function Rn(e,t){return`${e||"unknown"}:${t||"none"}`}function xt(){return new Promise((e,t)=>{let n=indexedDB.open(jr,zr);n.onupgradeneeded=()=>{let r=n.result;r.objectStoreNames.contains(oe)||r.createObjectStore(oe)},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error??new Error("indexedDB open failed"))})}function Wr(e){let t=e.data;return t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength)}function kn(e,t){return new Promise((n,r)=>{let o=e.transaction(oe,"readonly").objectStore(oe).get(t);o.onsuccess=()=>n(o.result),o.onerror=()=>r(o.error??new Error("indexedDB read failed"))})}async function Tn(e,t,n){if(typeof indexedDB>"u")return;let r=await xt(),i={width:n.width,height:n.height,data:Wr(n)};try{await new Promise((o,a)=>{let d=r.transaction(oe,"readwrite");d.oncomplete=()=>o(),d.onerror=()=>a(d.error??new Error("indexedDB write failed")),d.objectStore(oe).put(i,wt(e,t))})}finally{r.close()}}async function In(e,t){if(typeof indexedDB>"u")return null;let n=await xt();try{let r=wt(e,t),i=Rn(e,t),o=await kn(n,r)??(r===i?void 0:await kn(n,i));if(!o||!o.data||o.width<1||o.height<1)return null;let a=new ImageData(o.width,o.height);return a.data.set(new Uint8ClampedArray(o.data)),a}finally{n.close()}}async function Mn(e,t){if(typeof indexedDB>"u")return;let n=await xt();try{await new Promise((r,i)=>{let o=n.transaction(oe,"readwrite");o.oncomplete=()=>r(),o.onerror=()=>i(o.error??new Error("indexedDB delete failed"));let a=o.objectStore(oe);a.delete(wt(e,t)),a.delete(Rn(e,t))})}finally{n.close()}}var Pt="cyberart.state.",qr="Saved state",Yr="Loaded state",Jr="Failed to save state",Xr="Failed to load state",Qr="No saved state";function ae(e,t){let n=e||"unknown";return t?Pt+n+"."+re(t):Pt+n}function Zr(e,t,n){return r=>{if(Pn(r)==="localStorage"){if(r.type===ve){ei(e,t,n);return}r.type===Ee&&ti(e,t,n)}}}function Ae(e){try{let t=JSON.parse(e);if(!t||typeof t!="object")return null;let n=t;if(typeof n.savedAt=="number"&&n.bundle&&typeof n.bundle=="object")return{savedAt:n.savedAt,bundle:n.bundle};let r=t;return typeof r.seed=="string"&&typeof r.version=="number"?{savedAt:0,bundle:r}:null}catch{return null}}async function ei(e,t,n){let r=e();if(r)try{let i=await r.exportState(),o=i.cartId??t?.();i.generative===!0?(di(o),Qe(ae(o,i.seed),i)):Qe(ae(o),i);let a=r.peekExportedFramebuffer?.();if(a)try{await Tn(o,i.seed,a)}catch(d){console.warn("Failed to save cart framebuffer",d)}n?.(qr,"transient")}catch(i){console.error("Failed to save cart state",i),n?.(Jr,"transient")}}async function ti(e,t,n){let r=e();if(!r)return;let i=t?.(),o=r.peekSeed?.(),a=r.isGenerative?.()===!0,d=ai(i,a,o);if(!d){console.warn("No saved cart state for",i||"unknown",a&&o?`(hash ${o})`:""),n?.(Qr,"transient");return}try{let u=await In(i,d.bundle.seed).catch(()=>null);await r.importState(d.bundle,{framebuffer:u}),n?.(Yr,"transient")}catch(u){console.error("Failed to load cart state",u),n?.(Xr,"transient")}}function Qe(e,t){let n=JSON.stringify({savedAt:Date.now(),bundle:t});ni(e,n)}function ni(e,t){for(;;)try{localStorage.setItem(e,t);return}catch(n){if(!ri(n)||!ii(e))throw n}}function ri(e){if(!e||typeof e!="object")return!1;let t=e.name,n=e.code;return t==="QuotaExceededError"||t==="NS_ERROR_DOM_QUOTA_REACHED"||n===22||n===1014}function ii(e){let t=null,n=1/0;for(let o of oi()){if(o===e)continue;let a=localStorage.getItem(o);if(!a)continue;let u=Ae(a)?.savedAt??0;u<n&&(n=u,t=o)}if(!t)return!1;let r=localStorage.getItem(t),i=r?Ae(r):null;return localStorage.removeItem(t),i?.bundle&&Mn(i.bundle.cartId,i.bundle.seed).catch(()=>{}),!0}function oi(){let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n&&n.startsWith(Pt)&&e.push(n)}return e}function ai(e,t,n){if(t&&n){let i=localStorage.getItem(ae(e,n));if(i)return Ae(i);let o=localStorage.getItem(ae(e));if(!o)return null;let a=Ae(o);if(!a||!si(a.bundle,n))return null;try{Qe(ae(e,n),a.bundle)}catch{}return a}let r=localStorage.getItem(ae(e));return r?Ae(r):null}function si(e,t){return typeof e.seed=="string"&&re(e.seed)===re(t)}function di(e){let t=ae(e),n=localStorage.getItem(t);if(!n)return;let r=Ae(n);if(r&&typeof r.bundle.seed=="string"){let i=ae(e,r.bundle.seed);if(!localStorage.getItem(i))try{Qe(i,r.bundle)}catch{return}}localStorage.removeItem(t)}var Ne=1,se="cyberart.diagnostic.rejected",et=8,ui=new Set(["intent","state","diagnostic"]),ci=new Set([ve,Ee]);function Ze(e){return typeof e=="string"&&ui.has(e)}function Dn(e){if(e.kind!==void 0)return Ze(e.kind)?e.kind:void 0;if(!(typeof e.type!="string"||e.type.length===0)){if(ci.has(e.type))return"intent";for(let t of e.type.split("."))if(Ze(t))return t}}function _n(e,t){let n=e.split("."),r=t.split(".");if(n.length!==r.length)return!1;for(let i=0;i<n.length;i++)if(n[i]!=="*"&&n[i]!==r[i])return!1;return!0}function de(e,t){for(let n of e)if(_n(n,t))return!0;return!1}function Ce(e){if(e===void 0)return{ok:!0,value:void 0};try{return{ok:!0,value:JSON.parse(JSON.stringify(e))}}catch{return{ok:!1}}}function tt(e,t){if(!e||typeof e.type!="string"||e.type.length===0)return{ok:!1,reason:"malformed",detail:"type is required"};if(e.schemaVersion!==void 0&&e.schemaVersion!==Ne)return{ok:!1,reason:"malformed",detail:`unsupported schemaVersion ${String(e.schemaVersion)}`};let n=Dn(e);if(!n)return{ok:!1,reason:"malformed",detail:`cannot infer kind from type "${e.type}"`};let r=Ce(e.payload);if(!r.ok)return{ok:!1,reason:"malformed",detail:"payload is not JSON-serializable"};let i=t.createId(),o=typeof e.correlationId=="string"&&e.correlationId.length>0?e.correlationId:i,a=typeof e.causationId=="string"&&e.causationId.length>0?e.causationId:t.causationId,d=typeof e.target=="string"&&e.target.length>0?e.target:void 0,u=t.maxHops??et,g=t.parentHops===void 0?u:Math.max(0,t.parentHops-1),m=typeof e.idempotencyKey=="string"&&e.idempotencyKey.length>0?e.idempotencyKey:void 0,y={schemaVersion:Ne,type:e.type,kind:n,source:t.source,id:i,correlationId:o,seq:t.seq,hops:g};return d&&(y.target=d),a&&(y.causationId=a),m&&(y.idempotencyKey=m),r.value!==void 0&&(y.payload=r.value),{ok:!0,envelope:y}}var li=new Set(["rate-limited","storm-detected","hop-limit","loop-detected","not-subscribed"]),pi=8,fi=8,mi=16,hi=256,yi=["*.intent.*"];function kt(e={}){let t=e.hostSource??"host",n="router",r=e.maxPerTurn??pi,i=e.maxCausationDepth??fi,o=e.maxHops??et,a=e.maxCorrelationPerTurn??mi,d=e.maxIndex??hi,u=e.maxPerWindow,g=e.windowMs??1e3,m=e.now??Date.now,y=0,C=e.createId??(()=>`evt-${++y}`),E=new Map,N=[],f=new Map,l=new Map,P=new Map,T=0,W=0,L=[],p=!1;function I(c,h,w){for(c.set(h,w);c.size>d;){let x=c.keys().next().value;if(x===void 0)break;c.delete(x)}}function S(c){I(f,c.id,{type:c.type,source:c.source,causationId:c.causationId,hops:c.hops,correlationId:c.correlationId,idempotencyKey:c.idempotencyKey})}function _(c,h){h&&(c.correlationId||(c.correlationId=h.correlationId),c.causationId||(c.causationId=h.id),!c.idempotencyKey&&h.idempotencyKey&&(c.idempotencyKey=`${h.idempotencyKey}::${c.type}`))}function F(c,h){if(c){let w=f.get(c);return w?w.hops:o}return h}function U(c,h){return`${c}\0${h}`}function q(c,h){c.idempotencyKey&&I(P,U(c.source,c.idempotencyKey),h)}function ue(c,h){if(h)return P.get(U(c,h))}function s(c){return ue(c.source,c.idempotencyKey)}function v(c){return c.seq+=1,c.seq}function A(c,h){if(!(typeof h.causationId=="string"&&h.causationId.length>0))return c.lastDelivered}function R(c){let h=new Set,w=new Set([`${c.type}\0${c.source}`]),x=c.causationId,b=0;for(;x;){if(b+=1,b>i||h.has(x))return!0;h.add(x);let G=f.get(x);if(!G)break;let Y=`${G.type}\0${G.source}`;if(w.has(Y))return!0;w.add(Y),x=G.causationId}return!1}function $(c){let h=(l.get(c)??0)+1;return l.set(c,h),h}function O(c,h){u!==void 0&&(c.emitTimestamps=c.emitTimestamps.filter(w=>h-w<g))}function M(c,h){return(h.kind==="state"||h.kind==="diagnostic")&&!c.authoritative?!1:de(c.emit,h.type)}function k(c){for(let h of N)if(de(h.patterns,c.type))try{h.listener(c)}catch{}}function V(c){if(c.target){let h=E.get(c.target);if(!h||!de(h.subscribe,c.type))return;h.channel.dispatch(c),h.lastDelivered={id:c.id,hops:c.hops,correlationId:c.correlationId,idempotencyKey:c.idempotencyKey};return}for(let h of E.values())de(h.subscribe,c.type)&&(h.channel.dispatch(c),h.lastDelivered={id:c.id,hops:c.hops,correlationId:c.correlationId,idempotencyKey:c.idempotencyKey})}function Z(c,h,w,x,b,G,Y){let Q={reason:x,eventType:h,source:w};b&&(Q.detail=b),W+=1;let Re=C(),le={schemaVersion:Ne,type:se,kind:"diagnostic",source:n,id:Re,correlationId:G??Re,seq:W,hops:0,payload:Q};Y&&(le.causationId=Y),S(le);let Bt=E.get(c);Bt&&Bt.channel.dispatch(le),k(le)}function K(c,h,w,x,b){Z(c,b?.type??(typeof h.type=="string"?h.type:""),b?.source??c,w,x,b?.correlationId,b?.id),b?.idempotencyKey&&!li.has(w)&&q(b,{status:"rejected"})}function ee(c){S(c),q(c,{status:"accepted",envelope:c}),$(c.correlationId),k(c),V(c)}function ne(c,h,w,x){if(!w.ok){K(c,h,"malformed",w.detail);return}let b=w.envelope,G=s(b);if(G)return G.status==="accepted"?G.envelope:void 0;if(b.hops<1){K(c,h,"hop-limit","no hops remaining",b);return}if(b.target&&b.target!==t){let Y=E.get(b.target);if(!Y){K(c,h,"unknown-target",`unknown target "${b.target}"`,b);return}if(!de(Y.subscribe,b.type)){K(c,h,"not-subscribed",`target "${b.target}" does not subscribe to ${b.type}`,b);return}}if(x){if(!M(x,b)){K(c,h,"unauthorized","source may not emit this event",b);return}if(x.emitsThisTurn+=1,x.emitsThisTurn>r){K(c,h,"rate-limited","maxPerTurn exceeded",b);return}if(u!==void 0){let Q=m();if(O(x,Q),x.emitTimestamps.push(Q),x.emitTimestamps.length>u){K(c,h,"rate-limited","maxPerWindow exceeded",b);return}}if(R(b)){K(c,h,"loop-detected","causation chain cycle or depth exceeded",b);return}if((l.get(b.correlationId)??0)+1>a){K(c,h,"storm-detected","correlationId storm",b);return}if(e.validate){let Q;try{Q=e.validate(b)}catch(Re){let le=Re instanceof Error?Re.message:"validate threw";K(c,h,"host-rejected",le,b);return}if(Q!==!0){K(c,h,"host-rejected",Q.detail,b);return}}}else{if(R(b)){K(c,h,"loop-detected","causation chain cycle or depth exceeded",b);return}if((l.get(b.correlationId)??0)+1>a){K(c,h,"storm-detected","correlationId storm",b);return}}return ee(b),b}function ut(c,h){let w=E.get(c);if(!w)return;let x={...h},b=A(w,x);if(_(x,b),ue(w.id,x.idempotencyKey))return;let Y=v(w),Q=tt(x,{source:w.id,createId:C,seq:Y,causationId:b?.id,maxHops:o,parentHops:F(x.causationId??b?.id,b?.hops)});ne(c,x,Q,w)}function ur(c,h){let w=h?.cause,x={...c};_(x,w);let b=ue(t,x.idempotencyKey);if(b)return b.status==="accepted"?b.envelope:void 0;T+=1;let G=tt(x,{source:t,createId:C,seq:T,causationId:x.causationId,maxHops:o,parentHops:F(x.causationId,w?.hops)});return ne(t,x,G,void 0)}function cr(){if(!p){p=!0;try{for(;L.length>0;){let c=L.shift();c&&(c.kind==="cart"?ut(c.participantId,c.event):c.result=ur(c.event,c.extras))}}finally{p=!1}}}function $t(c){L.push(c),cr()}return{attach(c,h,w={}){if(c===t||c===n)throw new Error(`createEventRouter: "${c}" is a reserved participant id`);for(let G of E.values())if(G.channel===h&&G.id!==c)throw new Error(`createEventRouter: channel already attached as "${G.id}"`);E.get(c)?.unsubscribe();let b={id:c,channel:h,emit:w.emit??yi,subscribe:w.subscribe??[],authoritative:w.authoritative===!0,seq:0,emitsThisTurn:0,emitTimestamps:[],unsubscribe:()=>{}};b.unsubscribe=h.onEvent(G=>{$t({kind:"cart",participantId:c,event:G})}),E.set(c,b)},detach(c){let h=E.get(c);h&&(h.unsubscribe(),E.delete(c))},publish(c,h){let w={kind:"publish",event:c,extras:h};return $t(w),w.result},subscribe(c,h){let w={patterns:c,listener:h};return N.push(w),()=>{let x=N.indexOf(w);x>=0&&N.splice(x,1)}},turn(){l.clear();for(let c of E.values())c.emitsThisTurn=0,c.lastDelivered=void 0,u!==void 0&&O(c,m())}}}var gi=new Set(["string","number","boolean","object","array"]);function B(e,t,n){return n?{code:e,detail:t,path:n}:{code:e,detail:t}}function On(e){if(!(typeof e!="string"||e.length===0)){for(let t of e.split("."))if(Ze(t))return t}}function Fn(e){let t=e.split(".");return t.length===0?"*":(t[t.length-1]="*",t.join("."))}function Rt(e){let t=[];if(!e||typeof e!="object")return[B("invalid-schema","payload schema is required")];if((typeof e.version!="number"||!Number.isInteger(e.version)||e.version<1)&&t.push(B("invalid-version","payload schema version must be an integer >= 1")),!e.fields||typeof e.fields!="object"||Array.isArray(e.fields))return t.push(B("invalid-fields","payload schema fields must be an object")),t;for(let[n,r]of Object.entries(e.fields)){if(!n){t.push(B("invalid-field","field name is required",n));continue}(!r||typeof r!="object"||!gi.has(r.type))&&t.push(B("invalid-field-type",`field "${n}" type must be string | number | boolean | object | array`,n))}return t}function bi(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e=="string"?"string":typeof e=="number"&&Number.isFinite(e)?"number":typeof e=="boolean"?"boolean":typeof e=="object"?"object":"other"}function vi(e,t){if(t===void 0){let i=Object.entries(e.fields).filter(([,o])=>o.optional!==!0);return i.length===0?{ok:!0,payload:void 0}:{ok:!1,errors:i.map(([o])=>B("missing-field",`payload is missing required field "${o}"`,o))}}if(t===null||typeof t!="object"||Array.isArray(t))return{ok:!1,errors:[B("invalid-payload","payload must be a JSON object")]};let n=t,r=[];for(let[i,o]of Object.entries(e.fields)){if(!(i in n)||n[i]===void 0){o.optional!==!0&&r.push(B("missing-field",`payload is missing required field "${i}"`,i));continue}let a=bi(n[i]);a!==o.type&&r.push(B("field-type",`payload.${i} expected ${o.type}, got ${a}`,i))}return r.length>0?{ok:!1,errors:r}:{ok:!0,payload:t}}function Ei(e,t,n){let r=Fn(e);return{type:e,kind:t,payloadSchema:{version:n.version,fields:{...n.fields}},emitPattern:r,subscribePattern:r,toManifest(){let i={};for(let[o,a]of Object.entries(this.payloadSchema.fields))i[o]={type:a.type,optional:a.optional===!0};return{type:this.type,kind:this.kind,version:this.payloadSchema.version,fields:i,emitPattern:this.emitPattern,subscribePattern:this.subscribePattern}},validatePayload(i){return vi(this.payloadSchema,i)}}}function Tt(e,t,n){let r=[];if(typeof t!="string"||t.length===0)r.push(B("invalid-type","event type is required"));else if(t.split(".").some(i=>i.length===0))r.push(B("invalid-type",`event type "${t}" has empty dotted segments`));else{let i=On(t);i?i!==e&&r.push(B("kind-mismatch",`type "${t}" infers kind "${i}" but this helper defines "${e}"`)):r.push(B("kind-mismatch",`type "${t}" has no "${e}" segment; Adventure-style names like adventure.presentation.* need e.g. adventure.presentation.${e}.cue-started`))}return r.push(...Rt(n)),r.length>0?{ok:!1,errors:r}:{ok:!0,contract:Ei(t,e,n)}}function Ai(e,t){return Tt("intent",e,t)}function Ci(e,t){return Tt("state",e,t)}function Si(e,t){return Tt("diagnostic",e,t)}function wi(e,t){let n=Rt(e),r=Rt(t);if(n.length>0||r.length>0||t.version<e.version)return"breaking";let i=Object.keys(e.fields),o=Object.keys(t.fields),a=new Set(i),d=new Set(o);for(let m of i){if(!d.has(m))return"breaking";let y=e.fields[m],C=t.fields[m];if(y.type!==C.type)return"breaking";let E=y.optional!==!0,N=C.optional===!0;if(E&&N||!E&&C.optional!==!0&&y.optional===!0)return"breaking"}let u=!1;for(let m of o)if(!a.has(m)){if(t.fields[m].optional!==!0)return"breaking";u=!0}let g=i.length===o.length&&i.every(m=>t.fields[m].type===e.fields[m].type&&t.fields[m].optional===!0==(e.fields[m].optional===!0));return g&&t.version===e.version?"identical":t.version>e.version&&(u||g)?"backward-compatible":t.version===e.version&&u?"breaking":g?"identical":"breaking"}function xi(e,t){let n=[],r=[],i=new Set,o=new Set;for(let a of e)(t==="authoritative"||a.kind==="intent")&&!i.has(a.emitPattern)&&(i.add(a.emitPattern),n.push(a.emitPattern)),a.kind!=="intent"&&!o.has(a.subscribePattern)&&(o.add(a.subscribePattern),r.push(a.subscribePattern));return{emit:n,subscribe:r,authoritative:t==="authoritative"}}function Pi(e,t){let n=e.emit??["*.intent.*"],r=e.authoritative===!0,i=[];for(let o of t)de(n,o.type)&&(o.kind==="state"||o.kind==="diagnostic")&&!r&&i.push(B("unauthorized-emit",`emit pattern allows ${o.kind} "${o.type}" but attach is not authoritative`,o.type));return i.length>0?{ok:!1,errors:i}:{ok:!0}}function ki(e){let t=new Map;for(let i of e)t.set(i.type,i);let n=i=>{let o=t.get(i.type);return o?o.kind!==i.kind?{ok:!1,errors:[B("kind-mismatch",`envelope kind "${i.kind}" does not match contract "${o.kind}"`,i.type)]}:o.validatePayload(i.payload):{ok:!1,errors:[B("unknown-type",`no contract registered for "${i.type}"`,i.type)]}};return{get(i){return t.get(i)},manifest(){return[...t.values()].sort((i,o)=>i.type.localeCompare(o.type)).map(i=>i.toManifest())},validateEnvelope:n,asRouterValidate:i=>{let o=n(i);return o.ok?!0:{reason:"host-rejected",detail:o.errors.map(a=>a.detail).join("; ")}}}}var Se=1,Mt="presentation.state.model",Ln="presentation.intent.unsupported",Vn=["loading","ready","error","unsupported"],Ri=["presentation.state.*",se],Ti="Presentation adapter has been destroyed",Hn="Presentation adapter: model is invalid or not JSON-serializable",Ii=new Set(Vn);function Kn(e){return typeof e=="string"&&Ii.has(e)}function Dt(e){if(e===null||typeof e!="object")return!1;let t=e;return!(t.contractVersion!==Se||!Kn(t.phase)||t.reason!==void 0&&typeof t.reason!="string"||t.view!==void 0&&(t.view===null||typeof t.view!="object"))}function It(e,t){let n={type:Mt,kind:"state",payload:e};return t?.correlationId&&(n.correlationId=t.correlationId),t?.causationId&&(n.causationId=t.causationId),t?.idempotencyKey&&(n.idempotencyKey=t.idempotencyKey),n}function _t(){return{contractVersion:Se,phase:"loading"}}function Ot(e){return{contractVersion:Se,phase:"unsupported",reason:e}}function Ft(e){let t=Ce(e);return t.ok?Dt(t.value)?{ok:!0,model:t.value}:t.value!==null&&typeof t.value=="object"&&"contractVersion"in t.value&&t.value.contractVersion!==Se?{ok:!1,reason:"unknown-contract-version",contractVersion:t.value.contractVersion}:{ok:!1,reason:"invalid-model"}:{ok:!1,reason:"model-not-serializable"}}function nt(e){let t=Ft(e);if(!t.ok)throw new Error(Hn);return t.model}function Mi(e){let t=Ce(e);return t.ok&&Dt(t.value)?t.value:Ot("model-not-serializable")}function Di(e,t){if(e.type!==Mt)return{model:t};let n=Ft(e.payload);return n.ok?{model:n.model}:{model:Ot(n.reason),rejected:{reason:n.reason,contractVersion:n.contractVersion}}}function _i(e){if(e===null||typeof e!="object"||!("regions"in e))return[];let t=e.regions;return Array.isArray(t)?t:[]}function Oi(e,t,n){return e>=n.x&&e<n.x+n.width&&t>=n.y&&t<n.y+n.height}function Fi(e,t){let n=t.intent;if(!n||typeof n.type!="string"||n.type.length===0)return;let r={type:n.type,kind:"intent"};if(n.payload!==void 0){let i=Ce(n.payload);if(!i.ok)return;r.payload=i.value}n.target&&(r.target=n.target),n.correlationId&&(r.correlationId=n.correlationId),n.idempotencyKey&&(r.idempotencyKey=n.idempotencyKey),e.emit(r)}function Gn(e,t,n){let r={reason:t};if(n!==void 0){let i=Ce(n);i.ok&&(r.contractVersion=i.value)}e.emit({type:Ln,kind:"intent",payload:r})}function Nn(e,t,n){let r=t;for(let i of e){let o=Di(i,r);o.rejected&&n&&Gn(n,o.rejected.reason,o.rejected.contractVersion),r=o.model}return r}function $n(){return{metadata:{id:"cyberart.presentation.reference",name:"Reference presentation",frameRate:30},getDefaultState:(e,t,n,r,i,o,a,d,u)=>{let g=i?.model;if(g===void 0)return{model:_t()};let m=Ft(g);return m.ok?{model:m.model}:(u&&Gn(u,m.reason,m.contractVersion),{model:Ot(m.reason)})},update:(e,t,n,r,i,o,a,d,u,g,m)=>{let y=Nn(m?.consume()??[],i.model,m);for(;a?.hasClick();){let C=a.consumeClick();if(!(!C||y.phase!=="ready"||!m)){for(let E of _i(y.view))if(Oi(C.x,C.y,E)){Fi(m,E);break}}}return m&&(y=Nn(m.consume(),y,m)),y===i.model?i:{...i,model:y}},render:(e,t,n,r,i,o)=>{let a=i.model.view?.background;o.fillStyle=a??"#111",o.fillRect(0,0,r.width,r.height)}}}function Bn(e,t={}){let n=e,r=t.model?nt(t.model):_t(),i=!1,o=t.present??t.model!==void 0,a=()=>{if(i)throw new Error(Ti)},d=u=>{a(),r=nt(u),n.dispatch(It(r))};return o&&n.dispatch(It(r)),{version:Se,get target(){return n},get model(){return Mi(r)},get phase(){return r.phase},get paused(){return n.paused===!0},present:d,async start(){return a(),n.start()},pause(){a(),n.pause()},resume(){a(),n.resume()},retarget(u){a(),n=u},destroy(){i||(i=!0,n.destroy())}}}function Ni(e,t={}){let n=t.model?nt(t.model):t.initialState?.model!==void 0?nt(t.initialState.model):_t(),r=t.cart??$n(),i=e.mount(r,{initialState:{...t.initialState,model:n},onEvent:t.onEvent});return Bn(i,{model:n,present:!1})}var Le="cue.started",it="cue.completed",Ve="cue.cancelled",ot="cue.replaced",Li=[Le,it,Ve,ot];function Vi(e){return e===Le||e===it||e===Ve||e===ot}function jn(e,t){let n=e<0?0:e>1?1:e;return t==="ease-out"?1-(1-n)*(1-n):n}function Un(e){return{type:e.type,atFrame:e.atFrame,name:e.name,idempotencyKey:e.idempotencyKey,progress:e.progress}}function rt(e){return{name:e.name,idempotencyKey:e.idempotencyKey,phase:e.phase,startFrame:e.startFrame,durationFrames:e.durationFrames,delayFrames:e.delayFrames,easing:e.easing,progress:e.progress,repeatIndex:e.repeatIndex}}function Nt(e){return e.startFrame+e.delayFrames}function Hi(e,t){if(!e||typeof e!="object")return{ok:!1,reason:"invalid",detail:"spec is required"};if(typeof e.name!="string"||e.name.length===0)return{ok:!1,reason:"invalid",detail:"name is required"};if(typeof e.idempotencyKey!="string"||e.idempotencyKey.length===0)return{ok:!1,reason:"invalid",detail:"idempotencyKey is required"};if(typeof e.durationFrames!="number"||!Number.isFinite(e.durationFrames)||e.durationFrames<0)return{ok:!1,reason:"invalid",detail:"durationFrames must be a non-negative finite number"};let n=e.startFrame===void 0?t:e.startFrame;if(typeof n!="number"||!Number.isFinite(n))return{ok:!1,reason:"invalid",detail:"startFrame must be finite"};let r=e.delayFrames??0;if(typeof r!="number"||!Number.isFinite(r)||r<0)return{ok:!1,reason:"invalid",detail:"delayFrames must be a non-negative finite number"};let i=e.easing??"linear";if(i!=="linear"&&i!=="ease-out")return{ok:!1,reason:"invalid",detail:"unsupported easing"};let o=e.onDuplicate??"replace";if(o!=="ignore"&&o!=="replace"&&o!=="reject")return{ok:!1,reason:"invalid",detail:"unsupported onDuplicate"};let a=0;if(e.repeat)if("forever"in e.repeat&&e.repeat.forever)a="forever";else if("count"in e.repeat){if(typeof e.repeat.count!="number"||!Number.isFinite(e.repeat.count)||e.repeat.count<0)return{ok:!1,reason:"invalid",detail:"repeat.count must be >= 0"};a=Math.floor(e.repeat.count)}else return{ok:!1,reason:"invalid",detail:"unsupported repeat"};let d=e.reducedMotion??"complete";return d!=="skip"&&d!=="complete"&&(typeof d!="object"||typeof d.durationFrames!="number"||!Number.isFinite(d.durationFrames)||d.durationFrames<0)?{ok:!1,reason:"invalid",detail:"unsupported reducedMotion"}:{name:e.name,idempotencyKey:e.idempotencyKey,startFrame:n,durationFrames:e.durationFrames,delayFrames:r,easing:i,repeatRemaining:a,repeatIndex:0,reducedMotion:d,onDuplicate:o,phase:"scheduled",progress:0}}function Ki(e,t){if(!t)return e;let n=e.reducedMotion;return n==="skip"||n==="complete"?{...e,durationFrames:0,delayFrames:0,startFrame:e.startFrame}:{...e,durationFrames:n.durationFrames}}function Gi(e={}){let t=!!e.reducedMotion,n=e.originFrame??0,r=new Map,i=[];function o(f){i.push(f)}function a(f,l){let P=Nt(f)-Nt(l);return P!==0?P:f.name<l.name?-1:f.name>l.name?1:f.idempotencyKey<l.idempotencyKey?-1:f.idempotencyKey>l.idempotencyKey?1:0}function d(f,l){o({type:l,atFrame:n,name:f.name,idempotencyKey:f.idempotencyKey,progress:f.progress})}function u(f){if(f.phase="completed",f.progress=1,d(f,it),f.repeatRemaining==="forever"||f.repeatRemaining>0){if(typeof f.repeatRemaining=="number"&&(f.repeatRemaining-=1),f.repeatIndex+=1,f.phase="scheduled",f.progress=0,f.startFrame=n,f.delayFrames=0,f.durationFrames===0){r.delete(f.idempotencyKey);return}f.phase="active",d(f,Le)}else r.delete(f.idempotencyKey)}function g(f){if(f.phase==="cancelled"||f.phase==="completed")return;let l=Nt(f);if(!(n<l)){if(f.phase==="scheduled"&&(f.phase="active",f.progress=f.durationFrames===0?1:0,d(f,Le),f.durationFrames===0)){u(f);return}if(f.phase==="active"){let P=n-l;P>=f.durationFrames?(f.progress=1,u(f)):f.progress=jn(f.durationFrames===0?1:P/f.durationFrames,f.easing)}}}function m(){let f=[...r.values()].sort(a);for(let l of f)g(l)}function y(f){let l=Hi(f,n);if("ok"in l&&l.ok===!1)return l;let P=Ki(l,t),T=r.get(P.idempotencyKey);if(T&&(T.phase==="scheduled"||T.phase==="active")){if(T.onDuplicate==="reject"||P.onDuplicate==="reject")return{ok:!1,reason:"duplicate",detail:`cue ${P.idempotencyKey} is already ${T.phase}`};if(T.onDuplicate==="ignore"||P.onDuplicate==="ignore")return{ok:!0,cue:rt(T)};T.phase="cancelled",T.progress=T.progress,d(T,ot),r.delete(T.idempotencyKey)}r.set(P.idempotencyKey,P),g(P);let W=r.get(P.idempotencyKey)??P;return{ok:!0,cue:rt(W)}}function C(f){let l=r.get(f);return!l||l.phase==="completed"||l.phase==="cancelled"?!1:(l.phase="cancelled",d(l,Ve),r.delete(f),!0)}function E(){for(let f of[...r.values()].sort(a))(f.phase==="scheduled"||f.phase==="active")&&(f.phase="cancelled",d(f,Ve));r.clear(),i.length=0,n=e.originFrame??0}function N(f=1){let l=Number.isFinite(f)?Math.max(0,Math.floor(f)):0,P=i.length;for(let T=0;T<l;T++)n+=1,m();return i.slice(P).map(Un)}return{play:y,step:N,cancel:C,reset:E,snapshot(){return{frame:n,reducedMotion:t,cues:[...r.values()].sort(a).map(rt),events:i.map(Un)}},get(f){let l=r.get(f);return l?rt(l):void 0},get frame(){return n},get reducedMotion(){return t}}}var $i=1,Wn=["loading","ready","error","unsupported"],qn=["keyboard","pointer","audio","assets","hostChannel"],Yn=["image","audio","font","spritesheet"],Jn=["tone","midi"],Bi=new Set(Wn),Xn=new Set(qn),zn=new Set(Yn),Qn=new Set(Jn),Ui=new Set(["version","id","runtime","phases","managers","assets","acceptedEvents","emittedEvents","permissions","integrations"]),ji=new Set(["minContractVersion","features"]),zi=new Set(["kinds","declarations"]),Wi=new Set(["id","kind"]),qi=new Set(["emit","subscribe","authoritative"]),Yi=new Set(["contractVersion","features","integrations","managers","emit","subscribe"]);function D(e,t,n){return n?{code:e,detail:t,path:n}:{code:e,detail:t}}function we(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function xe(e,t,n){let r=[];for(let i of Object.keys(e))t.has(i)||r.push(D("unknown-field",`unknown field "${i}"`,n?`${n}.${i}`:i));return r}function Ji(e){if(typeof e!="string"||e.length===0)return!1;let t=e.split(".");return t.some(n=>n.length===0)?!1:t.every(n=>n==="*"||/^[a-z0-9][a-z0-9-]*$/i.test(n))}function Xi(e,t){let n=e.split("."),r=t.split(".");if(n.length!==r.length)return!1;for(let i=0;i<n.length;i++)if(n[i]!=="*"&&n[i]!==r[i])return!1;return!0}function st(e,t){for(let n of t)if(e===n||Xi(n,e))return!0;return!1}function at(e){let t=new Set,n=[];for(let r of e)t.has(r)||(t.add(r),n.push(r));return n}function Lt(e,t,n){if(!Array.isArray(e))return{ok:!1,errors:[D("invalid-field",`${t} must be an array`,t)]};let r=[],i=[];return e.forEach((o,a)=>{let d=`${t}[${a}]`;if(typeof o!="string"||o.length===0){r.push(D("invalid-field",`${t} entries must be non-empty strings`,d));return}let u=n(o,d);u?r.push(u):i.push(o)}),r.length>0?{ok:!1,errors:r}:{ok:!0,values:i}}function Pe(e,t){return Lt(e,t,(n,r)=>Ji(n)?void 0:D("invalid-pattern",`invalid event pattern "${n}"`,r))}function ke(e,t,n,r,i){return Lt(e,t,(o,a)=>n.has(o)?void 0:D(r,`invalid ${i} "${o}"`,a))}function Zn(e,t){return Lt(e,t,(n,r)=>/^[a-z0-9][a-z0-9.-]*$/i.test(n)?void 0:D("invalid-feature",`invalid feature tag "${n}"`,r))}function Qi(e){if(!we(e))return[D("invalid-manifest","capability manifest must be a JSON object")];let t=[...xe(e,Ui,"")];if(e.version!==void 0&&e.version!==1&&t.push(D("invalid-version","capability manifest version must be 1","version")),(typeof e.id!="string"||e.id.length===0)&&t.push(D("invalid-id","id is required","id")),!we(e.runtime))t.push(D("invalid-runtime","runtime is required","runtime"));else{t.push(...xe(e.runtime,ji,"runtime"));let d=e.runtime.minContractVersion;(typeof d!="number"||!Number.isInteger(d)||d<1)&&t.push(D("invalid-runtime","runtime.minContractVersion must be an integer >= 1","runtime.minContractVersion"));let u=Zn(e.runtime.features,"runtime.features");u.ok||t.push(...u.errors)}let n=ke(e.phases,"phases",Bi,"invalid-phase","phase");n.ok||t.push(...n.errors);let r=ke(e.managers,"managers",Xn,"invalid-manager","manager");if(r.ok||t.push(...r.errors),!we(e.assets))t.push(D("invalid-assets","assets is required","assets"));else{t.push(...xe(e.assets,zi,"assets"));let d=ke(e.assets.kinds,"assets.kinds",zn,"invalid-asset-kind","asset kind");d.ok||t.push(...d.errors),Array.isArray(e.assets.declarations)?e.assets.declarations.forEach((u,g)=>{let m=`assets.declarations[${g}]`;if(!we(u)){t.push(D("invalid-assets","asset declaration must be an object",m));return}t.push(...xe(u,Wi,m)),(typeof u.id!="string"||u.id.length===0)&&t.push(D("invalid-assets","asset declaration id is required",`${m}.id`)),(typeof u.kind!="string"||!zn.has(u.kind))&&t.push(D("invalid-asset-kind",`invalid asset kind "${String(u.kind)}"`,`${m}.kind`))}):t.push(D("invalid-assets","assets.declarations must be an array","assets.declarations"))}let i=Pe(e.acceptedEvents,"acceptedEvents");i.ok||t.push(...i.errors);let o=Pe(e.emittedEvents,"emittedEvents");if(o.ok||t.push(...o.errors),!we(e.permissions))t.push(D("invalid-permissions","permissions is required","permissions"));else{t.push(...xe(e.permissions,qi,"permissions"));let d=Pe(e.permissions.emit,"permissions.emit");d.ok||t.push(...d.errors);let u=Pe(e.permissions.subscribe,"permissions.subscribe");u.ok||t.push(...u.errors),e.permissions.authoritative!==void 0&&typeof e.permissions.authoritative!="boolean"&&t.push(D("invalid-permissions","permissions.authoritative must be a boolean","permissions.authoritative"))}let a=ke(e.integrations,"integrations",Qn,"invalid-integration","integration");return a.ok||t.push(...a.errors),t}function Zi(e){let t=[];return e.emittedEvents.forEach((n,r)=>{st(n,e.permissions.emit)||t.push(D("undeclared-permission",`emitted event "${n}" is not covered by permissions.emit`,`emittedEvents[${r}]`))}),e.acceptedEvents.forEach((n,r)=>{st(n,e.permissions.subscribe)||t.push(D("undeclared-permission",`accepted event "${n}" is not covered by permissions.subscribe`,`acceptedEvents[${r}]`))}),t}function eo(e){let t=at(e.assets.kinds),n=e.assets.declarations.map(i=>({id:i.id,kind:i.kind})),r={emit:[...e.permissions.emit],subscribe:[...e.permissions.subscribe]};return e.permissions.authoritative===!0&&(r.authoritative=!0),{version:1,id:e.id,runtime:{minContractVersion:e.runtime.minContractVersion,features:[...e.runtime.features]},phases:at(e.phases),managers:at(e.managers),assets:{kinds:t,declarations:n},acceptedEvents:[...e.acceptedEvents],emittedEvents:[...e.emittedEvents],permissions:r,integrations:at(e.integrations)}}function Vt(e){let t=Qi(e);if(t.length>0)return{ok:!1,errors:t};let n=eo(e);return t.push(...Zi(n)),t.length>0?{ok:!1,errors:t}:{ok:!0,manifest:n}}function to(e){let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{return{ok:!1,errors:[D("invalid-json","capability manifest JSON is not parseable")]}}return Vt(t)}function no(e){return JSON.parse(JSON.stringify(e))}function ro(e,t){let n=Vt(e),r=n.ok?[]:[...n.errors];if(!we(t))return{ok:!1,errors:[D("invalid-host","host capabilities must be a JSON object")]};r.push(...xe(t,Yi,"host")),typeof t.contractVersion!="number"||!Number.isInteger(t.contractVersion)||t.contractVersion<1?r.push(D("invalid-host","host.contractVersion must be an integer >= 1","host.contractVersion")):n.ok&&t.contractVersion<n.manifest.runtime.minContractVersion&&r.push(D("unsupported-runtime",`host contract version ${t.contractVersion} is below required ${n.manifest.runtime.minContractVersion}`,"runtime.minContractVersion"));let i=Zn(t.features,"host.features");if(!i.ok)r.push(...i.errors);else if(n.ok){let a=new Set(i.values);n.manifest.runtime.features.forEach((d,u)=>{a.has(d)||r.push(D("unsupported-feature",`host does not support required feature "${d}"`,`runtime.features[${u}]`))})}let o=ke(t.integrations,"host.integrations",Qn,"invalid-integration","integration");if(!o.ok)r.push(...o.errors);else if(n.ok){let a=new Set(o.values);n.manifest.integrations.forEach((d,u)=>{a.has(d)||r.push(D("missing-integration",`host does not provide required integration "${d}"`,`integrations[${u}]`))})}if(t.managers!==void 0){let a=ke(t.managers,"host.managers",Xn,"invalid-manager","manager");if(!a.ok)r.push(...a.errors);else if(n.ok){let d=new Set(a.values);n.manifest.managers.forEach((u,g)=>{d.has(u)||r.push(D("missing-manager",`host does not provide required manager "${u}"`,`managers[${g}]`))})}}if(t.emit!==void 0){let a=Pe(t.emit,"host.emit");a.ok?n.ok&&n.manifest.permissions.emit.forEach((d,u)=>{st(d,a.values)||r.push(D("unknown-permission",`host does not allow emit permission "${d}"`,`permissions.emit[${u}]`))}):r.push(...a.errors)}if(t.subscribe!==void 0){let a=Pe(t.subscribe,"host.subscribe");a.ok?n.ok&&n.manifest.permissions.subscribe.forEach((d,u)=>{st(d,a.values)||r.push(D("unknown-permission",`host does not allow subscribe permission "${d}"`,`permissions.subscribe[${u}]`))}):r.push(...a.errors)}return r.length>0?{ok:!1,errors:r}:{ok:!0}}var io=1,oo=1e-6,ao=.5,so=["normalized","asset","canvas","css","viewport"],uo=["center","top-left","top-right","bottom-left","bottom-right","top","bottom","left","right"],co={center:{x:.5,y:.5},"top-left":{x:0,y:0},"top-right":{x:1,y:0},"bottom-left":{x:0,y:1},"bottom-right":{x:1,y:1},top:{x:.5,y:0},bottom:{x:.5,y:1},left:{x:0,y:.5},right:{x:1,y:.5}};function lo(e){let t=co[e];return{x:t.x,y:t.y}}function po(e){let t=e.devicePixelRatio??1,{contentWidth:n,contentHeight:r,viewportWidth:i,viewportHeight:o,mode:a}=e,d=i/n,u=o/r,g=a==="contain"?Math.min(d,u):Math.max(d,u),m=n*g,y=r*g,C=(i-m)/2,E=(o-y)/2,N=dt(-C/m),f=dt(-E/y),l=dt(i/m),P=dt(o/y);return{mode:a,contentWidth:n,contentHeight:r,viewportWidth:i,viewportHeight:o,devicePixelRatio:t,scale:g,offsetX:C,offsetY:E,canvasWidth:i*t,canvasHeight:o*t,visibleNormalizedRect:{x:N,y:f,width:Math.min(l,1-N),height:Math.min(P,1-f)}}}function fo(e,t){return{x:e.x*t.contentWidth,y:e.y*t.contentHeight}}function mo(e,t){return{x:e.x/t.contentWidth,y:e.y/t.contentHeight}}function Ht(e,t){return{x:t.offsetX+e.x*t.contentWidth*t.scale,y:t.offsetY+e.y*t.contentHeight*t.scale}}function Kt(e,t){return{x:(e.x-t.offsetX)/(t.contentWidth*t.scale),y:(e.y-t.offsetY)/(t.contentHeight*t.scale)}}function tr(e,t){return{x:e.x*t.devicePixelRatio,y:e.y*t.devicePixelRatio}}function nr(e,t){return{x:e.x/t.devicePixelRatio,y:e.y/t.devicePixelRatio}}function ho(e,t){return tr(Ht(e,t),t)}function rr(e,t){return Kt(nr(e,t),t)}function Gt(e,t){let n=Ht({x:e.x,y:e.y},t);return{x:n.x,y:n.y,width:e.width*t.contentWidth*t.scale,height:e.height*t.contentHeight*t.scale}}function ir(e,t){let n=Gt(e,t),r=t.devicePixelRatio;return{x:n.x*r,y:n.y*r,width:n.width*r,height:n.height*r}}function yo(e,t,n,r){let o=(r?.space??"canvas")==="css"?Kt(e,t):rr(e,t);for(let a of n.regions)if(xo(a,o))return a}function go(e,t){let n=He(e);if(n)return Gt(n,t)}function bo(e){let t=new Map,n=r=>{if(t.has(r.id))return{ok:!1,error:"duplicate-id",id:r.id};let i={id:r.id,point:{x:r.point.x,y:r.point.y},...r.origin!==void 0?{origin:r.origin}:{}};return t.set(i.id,i),{ok:!0,landmark:i}};if(e)for(let r of e){let i=n(r);if(!i.ok)throw new Error(`Duplicate landmark id: ${i.id}`)}return{register:n,get:r=>t.get(r),list:()=>[...t.values()]}}function vo(e){let t=[];e.version!==1&&t.push({code:"version-mismatch",detail:`expected version 1, got ${String(e.version)}`});let n=new Set,r=i=>{if(n.has(i)){t.push({code:"duplicate-id",id:i,detail:`duplicate id ${i}`});return}n.add(i)};for(let i of e.landmarks)r(i.id),er(i.point)||t.push({code:"out-of-bounds",id:i.id,detail:`landmark ${i.id} is outside 0\u20131`});for(let i of e.regions){r(i.id);let o=He(i);if(!i.rect&&!i.polygon){t.push({code:"invalid-shape",id:i.id,detail:`region ${i.id} has neither rect nor polygon`});continue}if(i.polygon&&i.polygon.length<3&&t.push({code:"invalid-shape",id:i.id,detail:`region ${i.id} polygon needs at least 3 points`}),o&&!So(o)&&t.push({code:"out-of-bounds",id:i.id,detail:`region ${i.id} is outside 0\u20131`}),i.polygon){for(let a of i.polygon)if(!er(a)){t.push({code:"out-of-bounds",id:i.id,detail:`region ${i.id} has a vertex outside 0\u20131`});break}}}for(let i=0;i<e.regions.length;i+=1){let o=e.regions[i],a=He(o);if(a)for(let d=i+1;d<e.regions.length;d+=1){let u=e.regions[d],g=He(u);g&&wo(a,g)&&t.push({code:"overlap",id:o.id,with:u.id,detail:`region ${o.id} overlaps ${u.id}`})}}return{ok:t.length===0,diagnostics:t}}function Eo(e,t,n,r=[]){let i=[],o=(a,d,u)=>{i.push({method:a,id:u,args:d})};for(let a of n.regions){let d=He(a);if(!d)continue;let u=ir(d,t);e.fillStyle="rgba(0, 180, 255, 0.15)",e.strokeStyle="#00b4ff",e.fillRect&&e.fillRect(u.x,u.y,u.width,u.height),o("fillRect",[u.x,u.y,u.width,u.height],a.id),e.strokeRect&&e.strokeRect(u.x,u.y,u.width,u.height),o("strokeRect",[u.x,u.y,u.width,u.height],a.id),e.font="12px sans-serif";let g=a.id;e.fillText&&e.fillText(g,u.x+4,u.y+14),o("fillText",[g,u.x+4,u.y+14],a.id)}for(let a of r){let d=a.id?`${a.id}: ${a.code}`:a.code,u=16+i.filter(g=>g.method==="fillText").length*14;e.fillText&&e.fillText(d,8,u),o("fillText",[d,8,u],a.id)}return i}function Ao(e){return JSON.stringify(e)}function Co(e){return JSON.parse(e)}function dt(e){return e<=0?0:e>=1?1:e}function er(e){return e.x>=0&&e.x<=1&&e.y>=0&&e.y<=1}function So(e){return e.x>=0&&e.y>=0&&e.width>=0&&e.height>=0&&e.x+e.width<=1&&e.y+e.height<=1}function wo(e,t){return e.x<t.x+t.width&&e.x+e.width>t.x&&e.y<t.y+t.height&&e.y+e.height>t.y}function He(e){if(e.rect)return e.rect;if(!e.polygon||e.polygon.length===0)return;let t=1/0,n=1/0,r=-1/0,i=-1/0;for(let o of e.polygon)t=Math.min(t,o.x),n=Math.min(n,o.y),r=Math.max(r,o.x),i=Math.max(i,o.y);return{x:t,y:n,width:r-t,height:i-n}}function xo(e,t){return e.polygon&&e.polygon.length>=3?Po(t,e.polygon):e.rect?t.x>=e.rect.x&&t.x<e.rect.x+e.rect.width&&t.y>=e.rect.y&&t.y<e.rect.y+e.rect.height:!1}function Po(e,t){let n=!1;for(let r=0,i=t.length-1;r<t.length;i=r,r+=1){let o=t[r],a=t[i];o.y>e.y!=a.y>e.y&&e.x<(a.x-o.x)*(e.y-o.y)/(a.y-o.y)+o.x&&(n=!n)}return n}var ar=320,sr=180,ko="Runtime group has been destroyed";function Ro(e){let t="";for(let n=0;n<32;n++){let r=e.charCodeAt(n%Math.max(e.length,1))+n*17&255;t+=r.toString(16).padStart(2,"0")}return`0x${t}`}function To(e,t){let n=document.createElement("div");return Object.defineProperty(n,"clientWidth",{value:e,configurable:!0}),Object.defineProperty(n,"clientHeight",{value:t,configurable:!0}),document.body.appendChild(n),n}function dr(e){let t=e.capability,n={},r=e.emit??t?.emit,i=e.subscribe??t?.subscribe,o=e.authoritative??t?.authoritative;return r&&(n.emit=r),i&&(n.subscribe=i),o!==void 0&&(n.authoritative=o),n}function or(e){try{return JSON.parse(JSON.stringify(e))}catch{return e}}function Io(e){let t=new Set([se,"*.*","*.*.*","*.*.*.*","*.*.*.*.*"]);for(let n of e){let r=dr(n);for(let i of r.emit??[])t.add(i);for(let i of r.subscribe??[])t.add(i)}return[...t]}function Mo(e){if(!e.participants.length)throw new Error("createRuntimeGroup: at least one participant is required");let t=new Set;for(let p of e.participants){if(!p.id)throw new Error("createRuntimeGroup: participant id is required");if(t.has(p.id))throw new Error(`createRuntimeGroup: duplicate participant id "${p.id}"`);t.add(p.id)}let n=e.origin??0,r=e.width??ar,i=e.height??sr,o=[...e.participants].sort((p,I)=>p.id.localeCompare(I.id)),a=[],d=new Map,u=0,g=e.createId??e.router?.createId??(()=>`evt-${++u}`),m=e.now??e.router?.now??(()=>{let p=a[0];if(!p)return n;try{return p.cart.getClock().now}catch{return n}}),y=kt({...e.router,createId:g,now:m,validate:e.validate??e.router?.validate}),C=[],E=!1,N=!1,f=()=>{},l=p=>I=>{p.events.push(I),p.userOnEvent?.(I)},P=()=>{if(N)throw new Error(ko)},T=()=>{f();for(let p of a){try{y.detach(p.id)}catch{}try{p.runtime.destroy()}catch{}p.ownsContainer&&p.container.remove()}a.length=0,d.clear()};try{for(let p of o){let I=p.width??r,S=p.height??i,_=!p.container,F=p.container??To(I,S),U=St({container:F,seed:p.seed??Ro(p.id),deterministic:{origin:n}}),q={id:p.id,kind:p.kind??"render",cartDef:p.cart,initialState:p.initialState,gameManager:p.gameManager,userOnEvent:p.onEvent,runtime:U,container:F,ownsContainer:_,cart:void 0,events:[],errors:[]};U.onError=(ue,s)=>{q.errors.push({error:ue,info:s})},y.attach(p.id,U.hostChannel,dr(p)),q.cart=U.mount(p.cart,{initialState:p.initialState,gameManager:p.gameManager,onEvent:l(q)}),a.push(q),d.set(q.id,q)}f=y.subscribe(Io(o),p=>{C.push(or(p))})}catch(p){throw T(),p}let W=p=>({id:p.id,kind:p.kind,runtime:p.runtime,container:p.container,get events(){return p.events.slice()},get errors(){return p.errors.slice()},get cart(){return p.cart}});return{router:y,origin:n,get paused(){return E},participant(p){P();let I=d.get(p);if(!I)throw new Error(`createRuntimeGroup: unknown participant "${p}"`);return W(I)},async step(p=1){if(P(),E)return;let I=Math.max(0,Math.floor(p));for(let S=0;S<I;S++){y.turn();for(let _ of a)await _.cart.step(1)}},pause(){P(),E=!0;for(let p of a)p.cart.pause()},resume(){P(),E=!1;for(let p of a)p.cart.resume()},reset(){P(),C.length=0;for(let p of a)p.events.length=0,p.errors.length=0,p.cart=p.runtime.mount(p.cartDef,{initialState:p.initialState,gameManager:p.gameManager,onEvent:l(p)});y.turn()},dispatch(p,I){P();let S=d.get(p);if(!S)throw new Error(`createRuntimeGroup: unknown participant "${p}"`);S.cart.dispatch(I)},publish(p,I){return P(),y.publish(p,I)},async inspect(){P();let p={},I={};for(let _ of a){let F=await _.cart.getReplayMetadata(),U=_.cart.getClock();I[_.id]=U,p[_.id]={state:F.state,events:_.events.slice(),errors:_.errors.slice(),kind:_.kind,clock:U}}let S=C.map(_=>or(_));return{participants:p,trace:S,diagnostics:{paused:E,participantIds:a.map(_=>_.id),clocks:I,rejections:S.filter(_=>_.type===se).map(_=>_.payload)}}},destroy(){if(!N){N=!0,E=!1;try{T()}finally{C.length=0}}}}}export{uo as ANCHOR_ORIGINS,Oe as ASSET_FAILED_EVENT,En as ASSET_FAILURE_CODES,vn as ASSET_KINDS,_e as ASSET_READY_EVENT,Yn as CAPABILITY_ASSET_KINDS,Jn as CAPABILITY_INTEGRATIONS,qn as CAPABILITY_MANAGERS,$i as CAPABILITY_MANIFEST_VERSION,Wn as CAPABILITY_PHASES,so as COORDINATE_SPACES,Ve as CUE_CANCELLED_EVENT,it as CUE_COMPLETED_EVENT,Li as CUE_LIFECYCLE_EVENTS,ot as CUE_REPLACED_EVENT,Le as CUE_STARTED_EVENT,Ke as CYBERART_CANVAS_ATTR,sr as DEFAULT_GROUP_HEIGHT,ar as DEFAULT_GROUP_WIDTH,et as DEFAULT_MAX_HOPS,Ne as EVENT_ENVELOPE_VERSION,io as GEOMETRY_CONTRACT_VERSION,ge as HostChannel,Hn as INVALID_PRESENTATION_MODEL_MESSAGE,j as IncompatibleCartStateError,Ge as KeyboardManager,Se as PRESENTATION_ADAPTER_VERSION,Mt as PRESENTATION_MODEL_EVENT,Vn as PRESENTATION_PHASES,Ri as PRESENTATION_SUBSCRIBE_PATTERNS,Ln as PRESENTATION_UNSUPPORTED_EVENT,$e as PointerManager,se as REJECTED_EVENT_TYPE,oo as ROUND_TRIP_TOLERANCE,ao as ROUND_TRIP_TOLERANCE_CANVAS_PX,Te as Random,be as SILENT_ASSET_FALLBACK_REF,jn as applyCueEasing,ce as assetStatusEvent,mo as assetToNormalized,Zr as attachCartStatePersistence,Bn as attachPresentationAdapter,ze as canonicalizeSeed,nr as canvasToCss,rr as canvasToNormalized,no as capabilityManifestToJSON,wi as comparePayloadSchemas,H as createAssetFailure,Ct as createAssetPreloader,ki as createContractRegistry,kt as createEventRouter,Gr as createFixtureAssetResolver,$r as createHostedAssetResolver,bo as createLandmarkRegistry,po as createPresentationLayout,It as createPresentationModelEvent,Gi as createPresentationTimeline,$n as createReferencePresentationCart,St as createRuntime,Mo as createRuntimeGroup,Be as createVirtualClock,me as createWallClock,tr as cssToCanvas,Kt as cssToNormalized,Vt as defineCapabilityManifest,Si as defineDiagnostic,Ai as defineIntent,Ci as defineStateEvent,xi as deriveAttachOptions,fn as describeReplayMismatch,Eo as drawGeometryDebug,Fn as familyPatternForType,Dn as inferEventKind,Xe as isAssetFailure,Cn as isAssetFailureCode,An as isAssetKind,Vi as isCueLifecycleType,Dt as isPresentationModel,Kn as isPresentationPhase,On as kindSegmentInType,_n as matchEventPattern,Ni as mountPresentationAdapter,tt as normalizeEvent,fo as normalizedToAsset,ho as normalizedToCanvas,Ht as normalizedToCss,to as parseCapabilityManifest,Co as parseGeometry,lo as pointFromOrigin,yo as pointerToRegion,ir as rectToCanvas,Gt as rectToCss,go as regionToViewport,Ur as registerCartStateHotkeys,We as resolveRuntimeSeed,xn as rewriteHostedAssetRef,Ao as serializeGeometry,ro as validateCapabilityManifest,vo as validateGeometry,Pi as verifyAttachOptions};
@@ -0,0 +1,155 @@
1
+ # Asset resolver / preloader
2
+
3
+ Host-owned URL policy. The engine caches, dedupes, tracks progress, applies timeouts and fallbacks, and (in live mode) dispatches `ASSET_READY_EVENT` / `ASSET_FAILED_EVENT`. Authored carts keep logical refs (`moltazine:post/<id>#primary-image`, `world:asset/…`, `library:…`, or ordinary URLs). Adventure Kit, Cyberart, and a local preview each supply a different `AssetResolver`.
4
+
5
+ Deterministic timing: [deterministic mode](deterministic-mode.md). CI: [headless harness](headless-harness.md). Event mailbox: [events](events.md).
6
+
7
+ Back to the [package README](../README.md).
8
+
9
+ ## One-command reproduce (this repo)
10
+
11
+ ```bash
12
+ pnpm exec vitest run packages/engine/src/canvas/cyb-26-asset-resolver.repro.spec.ts
13
+ ```
14
+
15
+ ## Why this exists
16
+
17
+ The same room must load through two resolvers without changing cart or world content:
18
+
19
+ | Host | Resolver | Example URL |
20
+ |---|---|---|
21
+ | Local fixtures | `createFixtureAssetResolver` | `fixture://images/porch.png` |
22
+ | Hosted / Library | `createHostedAssetResolver({ cdnBase })` | `https://cdn.example/moltazine/porch-1/primary-image` |
23
+
24
+ Resolution policy stays in the host. The engine never fetches over the network.
25
+
26
+ ## `createRuntime({ assets })`
27
+
28
+ ```ts
29
+ import {
30
+ createRuntime,
31
+ createFixtureAssetResolver,
32
+ createHostedAssetResolver,
33
+ } from '@cyberart-io/engine';
34
+
35
+ const runtime = createRuntime({
36
+ container,
37
+ assets: {
38
+ resolver: createHostedAssetResolver({
39
+ cdnBase: 'https://cdn.example/library/',
40
+ failures: { 'world:asset/stream-loop': 'cors' },
41
+ }),
42
+ },
43
+ });
44
+
45
+ await runtime.assets!.preload([
46
+ { id: 'room-bg', ref: 'moltazine:post/porch-1#primary-image', type: 'image' },
47
+ {
48
+ id: 'ambience',
49
+ ref: 'world:asset/stream-loop',
50
+ type: 'audio',
51
+ fallback: 'silent',
52
+ },
53
+ ]);
54
+ ```
55
+
56
+ `runtime.assets` is undefined when `assets` is omitted. It survives cart remount. `runtime.destroy()` disposes it (aborts in-flight work, revokes `managed` blob URLs).
57
+
58
+ | Option | Default | Meaning |
59
+ |---|---|---|
60
+ | `resolver` | required | Host `resolve(request, signal?)`. |
61
+ | `timeoutMs` | none | Default per-asset timeout. Ignored under `deterministic` (no wall-clock). |
62
+ | `emitEvents` | `!deterministic` | When true, preload dispatches `ASSET_READY_EVENT` / `ASSET_FAILED_EVENT`. |
63
+
64
+ Under `deterministic`, emit and wall-clock timeout are off so scripted `{ type: 'asset', atFrame, id, status }` own when the cart `consume()`s ready/failed. Preload still fills the cache and progress snapshot immediately.
65
+
66
+ ## Declarations
67
+
68
+ ```ts
69
+ import type { AssetDeclaration } from '@cyberart-io/engine';
70
+
71
+ const roomBg: AssetDeclaration = {
72
+ id: 'room-bg',
73
+ ref: 'moltazine:post/porch-1#primary-image',
74
+ type: 'image', // 'image' | 'audio' | 'font' | 'spritesheet'
75
+ integrity: 'sha256-…', // optional; mismatch → `invalid`
76
+ provenance: { source: 'moltazine', postId: 'porch-1' },
77
+ timeoutMs: 8_000,
78
+ fallback: 'silent', // or another ref string, or a nested declaration
79
+ };
80
+ ```
81
+
82
+ `fallback: 'silent'` synthesizes `SILENT_ASSET_FALLBACK_REF` (`cyberart:fallback/silent`) so a failed audio load does not hang on a black screen. A string is another logical ref of the same type. A nested `AssetDeclaration` may itself declare `fallback` (up to four levels). The host still sees the typed failure on `getProgress().failures`. `abort` and live `timeout` skip fallbacks and terminate as `aborted` / `timeout`.
83
+
84
+ ## Resolvers (built-in)
85
+
86
+ ```ts
87
+ createFixtureAssetResolver({
88
+ 'moltazine:post/porch-1#primary-image': { url: 'fixture://images/porch.png' },
89
+ 'world:asset/stream-loop': { error: 'cors' },
90
+ });
91
+
92
+ createHostedAssetResolver({
93
+ cdnBase: 'https://cdn.example/library/',
94
+ failures: { 'world:asset/stream-loop': { code: 'timeout', message: 'cdn stalled' } },
95
+ });
96
+ ```
97
+
98
+ `rewriteHostedAssetRef(ref, cdnBase)`:
99
+
100
+ | Authored ref | Rewritten |
101
+ |---|---|
102
+ | `https://…` / `data:` / `blob:` | unchanged |
103
+ | `moltazine:post/<id>#fragment` | `{cdnBase}moltazine/<id>/<fragment>` |
104
+ | `world:asset/<name>` | `{cdnBase}world/<name>` |
105
+ | `library:<path>` | `{cdnBase}library/<path>` |
106
+ | other | `{cdnBase}{ref}` |
107
+
108
+ Hosted HTTP(S) results use `cors: 'anonymous'`. CORS / timeout / not-found are **structured failures the resolver emits** — do not `fetch` in tests or CI. Custom hosts implement `AssetResolver`.
109
+
110
+ `createAssetFailure({ id, ref, code, message? })` builds a typed error. Codes: `timeout` | `cors` | `not-found` | `invalid` | `aborted` | `resolver`.
111
+
112
+ ## Preloader
113
+
114
+ `createAssetPreloader({ resolver, timeoutMs, emitEvents, wallClockTimeout, dispatch })` is the same object `createRuntime` stores on `runtime.assets`.
115
+
116
+ | Member | Meaning |
117
+ |---|---|
118
+ | `preload(declarations)` | Validate, resolve, cache, fallback. Returns a snapshot. |
119
+ | `get(id)` | Copy of the ready resource, including silent fallback. |
120
+ | `getProgress()` | Copy: `total` / `pending` / `ready` / `failed` / `fallbacks` / `items` / `failures`. |
121
+ | `onProgress(listener)` | Fires after each item state change. Unsubscribe by calling the return. |
122
+ | `abort(id?)` | Cancel that id (or all), including in-flight fallback work. Terminates as `aborted`, or `timeout` if a live timer already fired. Does not apply silent, string, or nested fallbacks. A sibling that shares type+ref is not aborted. |
123
+ | `forget(id?)` | Drop item(s) and revoke `managed` blob URLs. If no other id still uses those type+ref keys (including fallback refs), drop the resolver cache so the next preload re-resolves. |
124
+ | `dispose()` | Idempotent teardown. Further `preload` throws. |
125
+
126
+ Repeated `preload` of the same `id` joins the in-flight promise or returns the cached terminal state. The same `type`+`ref` under two ids shares one `resolver.resolve` call.
127
+
128
+ Live `dispatch` uses the existing envelope: `{ type: ASSET_READY_EVENT \| ASSET_FAILED_EVENT, kind: 'state', payload: { id, ref?, resource?, failure? } }`. Payload still always has `id`. Do not `await fetch` inside cart `update` / `render`.
129
+
130
+ ## Deterministic tests
131
+
132
+ ```ts
133
+ const runtime = createRuntime({
134
+ container,
135
+ seed: 42,
136
+ deterministic: {
137
+ actions: [
138
+ { type: 'asset', atFrame: 2, id: 'room-bg', status: 'ready' },
139
+ {
140
+ type: 'asset',
141
+ atFrame: 3,
142
+ id: 'ambience',
143
+ status: 'failed',
144
+ detail: { code: 'cors' },
145
+ },
146
+ ],
147
+ },
148
+ assets: { resolver: fixtureResolver },
149
+ });
150
+ await runtime.assets!.preload(ROOM_ASSETS);
151
+ // progress is already terminal; the cart has not seen events yet
152
+ await cart.step(4);
153
+ ```
154
+
155
+ A resolver used under `deterministic` must not be what tests wait on for ready/failed. Scripted actions remain the clock.
@@ -0,0 +1,84 @@
1
+ # Capability manifest
2
+
3
+ Versioned JSON for what a cart needs from the host: runtime contract, lifecycle phases, managers, asset kinds, event patterns, permissions, and integrations. Related: [events](events.md) (emit / subscribe patterns), [asset resolver](asset-resolver.md) (kinds only — this file does not resolve URLs).
4
+
5
+ Back to the [package README](../README.md).
6
+
7
+ ## One-command reproduce (this repo)
8
+
9
+ ```bash
10
+ pnpm exec vitest run packages/engine/src/canvas/cyb-25-capability-manifest.repro.spec.ts
11
+ ```
12
+
13
+ ## Shape (`CAPABILITY_MANIFEST_VERSION = 1`)
14
+
15
+ `defineCapabilityManifest` / `parseCapabilityManifest` return `{ ok: true, manifest }` or `{ ok: false, errors }`. `validateCapabilityManifest(manifest, host)` checks the host can actually run it. The manifest is a plain object: `JSON.parse(JSON.stringify(m))` equals `toJSON(m)`.
16
+
17
+ | Field | Meaning |
18
+ |---|---|
19
+ | `id` | Cart / module id. |
20
+ | `runtime.minContractVersion` | Lowest host contract version that may load this cart. |
21
+ | `runtime.features` | Feature tags the host must list (e.g. `router`, `assets`). |
22
+ | `phases` | Presentation phases used: `loading` \| `ready` \| `error` \| `unsupported`. |
23
+ | `managers` | Required host managers: `keyboard`, `pointer`, `audio`, `assets`, `hostChannel`. |
24
+ | `assets.kinds` | Asset kinds the cart declares (`image`, `audio`, `font`, `spritesheet`). |
25
+ | `assets.declarations` | `{ id, kind }` summary only — not a resolver. |
26
+ | `acceptedEvents` / `emittedEvents` | Dotted type patterns (`*` = one segment). |
27
+ | `permissions` | `emit` / `subscribe` patterns; optional `authoritative`. |
28
+ | `integrations` | Required host libraries: `tone` \| `midi`. |
29
+
30
+ Emitted types must be covered by `permissions.emit`; accepted types by `permissions.subscribe`.
31
+
32
+ ## Host check
33
+
34
+ ```ts
35
+ import {
36
+ defineCapabilityManifest,
37
+ parseCapabilityManifest,
38
+ validateCapabilityManifest,
39
+ } from '@cyberart-io/engine';
40
+
41
+ const defined = defineCapabilityManifest({
42
+ id: 'adventure.presentation',
43
+ runtime: { minContractVersion: 1, features: ['router'] },
44
+ phases: ['loading', 'ready', 'error', 'unsupported'],
45
+ managers: ['pointer', 'hostChannel'],
46
+ assets: { kinds: ['image'], declarations: [{ id: 'room-bg', kind: 'image' }] },
47
+ acceptedEvents: ['adventure.state.*'],
48
+ emittedEvents: ['adventure.intent.exit-requested'],
49
+ permissions: { emit: ['adventure.intent.*'], subscribe: ['adventure.state.*'] },
50
+ integrations: ['tone'],
51
+ });
52
+ if (!defined.ok) throw new Error(defined.errors.map((e) => e.detail).join('; '));
53
+
54
+ const host = {
55
+ contractVersion: 1,
56
+ features: ['router'],
57
+ integrations: ['tone'] as const,
58
+ emit: ['adventure.intent.*'],
59
+ subscribe: ['adventure.state.*'],
60
+ };
61
+
62
+ const check = validateCapabilityManifest(defined.manifest, host);
63
+ // check.ok === true
64
+ const parsed = parseCapabilityManifest(JSON.stringify(defined.manifest));
65
+ ```
66
+
67
+ `host.managers`, `host.emit`, and `host.subscribe` are optional. When omitted, `missing-manager` and `unknown-permission` are not checked. Pass them when the host wants to enforce those allowlists.
68
+
69
+ | Diagnostic `code` | When |
70
+ |---|---|
71
+ | `unknown-field` | Extra key on the manifest or host object. |
72
+ | `invalid-json` | `parseCapabilityManifest` received unparseable text. |
73
+ | `invalid-manifest` / `invalid-host` | Root value is not a JSON object. |
74
+ | `invalid-id` / `invalid-runtime` / `invalid-assets` / `invalid-permissions` | Required object missing or malformed. |
75
+ | `invalid-field` | Array/string field has the wrong shape. |
76
+ | `invalid-phase` | Phase is not loading/ready/error/unsupported. |
77
+ | `invalid-pattern` | Event pattern is empty or malformed. |
78
+ | `invalid-feature` | Feature tag is empty or malformed. |
79
+ | `undeclared-permission` | An accepted/emitted pattern is not covered by cart permissions. |
80
+ | `unsupported-runtime` | Host contract version is below `minContractVersion`. |
81
+ | `unsupported-feature` | A required feature tag is missing on the host. |
82
+ | `missing-integration` | Host does not provide `tone` / `midi` as required. |
83
+ | `missing-manager` | Host listed `managers` but omitted one the cart requires. |
84
+ | `unknown-permission` | Cart emit/subscribe permission is not on the host allowlist (only if host listed `emit` / `subscribe`). |