@guinetik/gcanvas 1.0.5 → 2.0.0

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.
Files changed (78) hide show
  1. package/dist/aizawa.html +27 -0
  2. package/dist/clifford.html +25 -0
  3. package/dist/cmb.html +24 -0
  4. package/dist/dadras.html +26 -0
  5. package/dist/dejong.html +25 -0
  6. package/dist/gcanvas.es.js +5130 -372
  7. package/dist/gcanvas.es.min.js +1 -1
  8. package/dist/gcanvas.umd.js +1 -1
  9. package/dist/gcanvas.umd.min.js +1 -1
  10. package/dist/halvorsen.html +27 -0
  11. package/dist/index.html +96 -48
  12. package/dist/js/aizawa.js +425 -0
  13. package/dist/js/bezier.js +5 -5
  14. package/dist/js/clifford.js +236 -0
  15. package/dist/js/cmb.js +594 -0
  16. package/dist/js/dadras.js +405 -0
  17. package/dist/js/dejong.js +257 -0
  18. package/dist/js/halvorsen.js +405 -0
  19. package/dist/js/isometric.js +34 -46
  20. package/dist/js/lorenz.js +425 -0
  21. package/dist/js/painter.js +8 -8
  22. package/dist/js/rossler.js +480 -0
  23. package/dist/js/schrodinger.js +314 -18
  24. package/dist/js/thomas.js +394 -0
  25. package/dist/lorenz.html +27 -0
  26. package/dist/rossler.html +27 -0
  27. package/dist/scene-interactivity-test.html +220 -0
  28. package/dist/thomas.html +27 -0
  29. package/package.json +1 -1
  30. package/readme.md +30 -22
  31. package/src/game/objects/go.js +7 -0
  32. package/src/game/objects/index.js +2 -0
  33. package/src/game/objects/isometric-scene.js +53 -3
  34. package/src/game/objects/layoutscene.js +57 -0
  35. package/src/game/objects/mask.js +241 -0
  36. package/src/game/objects/scene.js +19 -0
  37. package/src/game/objects/wrapper.js +14 -2
  38. package/src/game/pipeline.js +17 -0
  39. package/src/game/ui/button.js +101 -16
  40. package/src/game/ui/theme.js +0 -6
  41. package/src/game/ui/togglebutton.js +25 -14
  42. package/src/game/ui/tooltip.js +12 -4
  43. package/src/index.js +3 -0
  44. package/src/io/gesture.js +409 -0
  45. package/src/io/index.js +4 -1
  46. package/src/io/keys.js +9 -1
  47. package/src/io/screen.js +476 -0
  48. package/src/math/attractors.js +664 -0
  49. package/src/math/heat.js +106 -0
  50. package/src/math/index.js +1 -0
  51. package/src/mixins/draggable.js +15 -19
  52. package/src/painter/painter.shapes.js +11 -5
  53. package/src/particle/particle-system.js +165 -1
  54. package/src/physics/index.js +26 -0
  55. package/src/physics/physics-updaters.js +333 -0
  56. package/src/physics/physics.js +375 -0
  57. package/src/shapes/image.js +5 -5
  58. package/src/shapes/index.js +2 -0
  59. package/src/shapes/parallelogram.js +147 -0
  60. package/src/shapes/righttriangle.js +115 -0
  61. package/src/shapes/svg.js +281 -100
  62. package/src/shapes/text.js +22 -6
  63. package/src/shapes/transformable.js +5 -0
  64. package/src/sound/effects.js +807 -0
  65. package/src/sound/index.js +13 -0
  66. package/src/webgl/index.js +7 -0
  67. package/src/webgl/shaders/clifford-point-shaders.js +131 -0
  68. package/src/webgl/shaders/dejong-point-shaders.js +131 -0
  69. package/src/webgl/shaders/point-sprite-shaders.js +152 -0
  70. package/src/webgl/webgl-clifford-renderer.js +477 -0
  71. package/src/webgl/webgl-dejong-renderer.js +472 -0
  72. package/src/webgl/webgl-line-renderer.js +391 -0
  73. package/src/webgl/webgl-particle-renderer.js +410 -0
  74. package/types/index.d.ts +30 -2
  75. package/types/io.d.ts +217 -0
  76. package/types/physics.d.ts +299 -0
  77. package/types/shapes.d.ts +8 -0
  78. package/types/webgl.d.ts +188 -109
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).GCanvas={})}(this,function(t){"use strict";var e,i,s,n,o,r,a,h,l,c,u,d,f,p,g,m,y,x,v,_,w,b,M,k,C,S,T,R,P,A,D,I,z,B,E,F,O,X,Y,W,L,H,N,G,U,q,Z,V,$,j,K,J,Q,tt,et,it,st,nt,ot,rt,at,ht,lt,ct,ut,dt,ft,pt,gt,mt,yt=Object.defineProperty,xt=t=>{throw TypeError(t)},vt=(t,e,i)=>((t,e,i)=>e in t?yt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i)(t,"symbol"!=typeof e?e+"":e,i),_t=(t,e,i)=>e.has(t)||xt("Cannot "+i),wt=(t,e,i)=>(_t(t,e,"read from private field"),i?i.call(t):e.get(t)),bt=(t,e,i)=>e.has(t)?xt("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,i),Mt=(t,e,i,s)=>(_t(t,e,"write to private field"),s?s.call(t,i):e.set(t,i),i),kt=(t,e,i)=>(_t(t,e,"access private method"),i);class Ct{constructor(t={}){this.children=[],this.sortByZIndex=t.sortByZIndex||!0,this._zOrderDirty=!1}add(t){return this.children.includes(t)?(console.warn("Object is already in this collection"),t):(this.children.push(t),t.parent=this._owner||this,this.sortByZIndex&&(this._zOrderDirty=!0,void 0!==t.zIndex&&null!==t.zIndex||(t.zIndex=this.children.length-1)),t)}remove(t){const e=this.children.indexOf(t);return-1!==e&&(this.children.splice(e,1),t.parent=null,!0)}clear(){this.children.forEach(t=>{t.parent=null}),this.children=[]}bringToFront(t){const e=this.children.indexOf(t);if(-1!==e)if(this.sortByZIndex){let e=!0;for(const i of this.children)if(i!==t&&(i.zIndex||0)>=(t.zIndex||0)){e=!1;break}e||(t.zIndex=Number.MAX_SAFE_INTEGER,this._zOrderDirty=!0,this._normalizeZIndices())}else e!==this.children.length-1&&(this.children.splice(e,1),this.children.push(t));else this.add(t)}sendToBack(t){const e=this.children.indexOf(t);if(-1===e)return this.children.unshift(t),void(t.parent=this._owner||this);if(this.sortByZIndex){let e=!0;for(const i of this.children)if(i!==t&&(i.zIndex||0)<=(t.zIndex||0)){e=!1;break}e||(t.zIndex=Number.MIN_SAFE_INTEGER,this._zOrderDirty=!0,this._normalizeZIndices())}else 0!==e&&(this.children.splice(e,1),this.children.unshift(t))}bringForward(t){const e=this.children.indexOf(t);if(-1!==e&&e!==this.children.length-1)if(this.sortByZIndex){const e=[...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),i=e.indexOf(t);if(i<e.length-1){const s=e[i+1],n=s.zIndex||0,o=t.zIndex||0;n-o>1?t.zIndex=o+Math.floor((n-o)/2):(t.zIndex=n,s.zIndex=o),this._zOrderDirty=!0,this._normalizeZIndices()}}else{const i=this.children[e+1];this.children[e+1]=t,this.children[e]=i}}sendBackward(t){const e=this.children.indexOf(t);if(!(e<=0))if(this.sortByZIndex){const e=[...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),i=e.indexOf(t);if(i>0){const s=e[i-1],n=s.zIndex||0,o=t.zIndex||0;o-n>1?t.zIndex=n+Math.floor((o-n)/2):(t.zIndex=n,s.zIndex=o),this._zOrderDirty=!0,this._normalizeZIndices()}}else{const i=this.children[e-1];this.children[e-1]=t,this.children[e]=i}}_normalizeZIndices(){this.children.length<=1||this.children.some(t=>(t.zIndex||0)>1e3||(t.zIndex||0)<-1e3)&&([...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)).forEach((t,e)=>{t.zIndex=10*e}),this._zOrderDirty=!0)}getSortedChildren(){return this.sortByZIndex&&this._zOrderDirty&&(this.children.sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),this._zOrderDirty=!1),this.children}}const St=class t{static calculate(e,i,s,n=10,o=0,r=0){const a=i.width||0,h=i.height||0,l=s.width||0,c=s.height||0,u=s.x||0,d=s.y||0;let f,p,g,m;switch(e){case t.TOP_LEFT:f=u-l/2+n+a/2,p=d-c/2+n+h/2,g="left",m="top";break;case t.TOP_CENTER:f=u,p=d-c/2+n+h/2,g="center",m="top";break;case t.TOP_RIGHT:f=u+l/2-n-a/2,p=d-c/2+n+h/2,g="right",m="top";break;case t.CENTER_LEFT:f=u-l/2+n+a/2,p=d,g="left",m="middle";break;case t.CENTER:f=u,p=d,g="center",m="middle";break;case t.CENTER_RIGHT:f=u+l/2-n-a/2,p=d,g="right",m="middle";break;case t.BOTTOM_LEFT:f=u-l/2+n+a/2,p=d+c/2-n-h/2,g="left",m="bottom";break;case t.BOTTOM_CENTER:f=u,p=d+c/2-n-h/2,g="center",m="bottom";break;case t.BOTTOM_RIGHT:f=u+l/2-n-a/2,p=d+c/2-n-h/2,g="right",m="bottom";break;default:f=u-l/2+n+a/2,p=d-c/2+n+h/2,g="left",m="top"}return f+=o,p+=r,{x:f,y:p,align:g,baseline:m}}static calculateAbsolute(e,i,s,n=10,o=0,r=0){const a={width:s.width,height:s.height,x:s.width/2,y:s.height/2};return t.calculate(e,i,a,n,o,r)}};vt(St,"TOP_LEFT","top-left"),vt(St,"TOP_CENTER","top-center"),vt(St,"TOP_RIGHT","top-right"),vt(St,"CENTER_LEFT","center-left"),vt(St,"CENTER","center"),vt(St,"CENTER_RIGHT","center-right"),vt(St,"BOTTOM_LEFT","bottom-left"),vt(St,"BOTTOM_CENTER","bottom-center"),vt(St,"BOTTOM_RIGHT","bottom-right");let Tt=St;function Rt(t,e,i={}){const s=i.offsetX??0,n=i.offsetY??0,o=i.transform;return t.forEach((t,i)=>{if(i<e.length){const r=e[i];if(o){const e=o(r);t.x=e.x+s,t.y=e.y+n}else t.x=r.x+s,t.y=r.y+n}}),t}function Pt(t,e={}){const i=e.spacing??10,s=e.padding??0,n=e.align??"start",o=e.centerItems??!0;let r=s,a=0;const h=[];for(const e of t)a=Math.max(a,e.height??0);for(let e=0;e<t.length;e++){const s=t[e],l=s.width??0,c=s.height??0,u=o?r+l/2:r;let d;switch(n){case"center":d=(a-c)/2;break;case"end":d=a-c;break;default:d=0}h.push({x:u,y:d}),r+=l,e<t.length-1&&(r+=i)}return{positions:h,width:r+s,height:a+2*s}}function At(t,e={}){const i=e.spacing??10,s=e.padding??0,n=e.align??"start",o=e.centerItems??!0;let r=s,a=0;const h=[];for(const e of t)a=Math.max(a,e.width??0);for(let e=0;e<t.length;e++){const s=t[e],l=s.width??0,c=s.height??0,u=o?r+c/2:r;let d;switch(n){case"center":d=(a-l)/2;break;case"end":d=a-l;break;default:d=0}h.push({x:d,y:u}),r+=c,e<t.length-1&&(r+=i)}return{positions:h,width:a+2*s,height:r+s}}function Dt(t,e={}){if(0===t.length)return{positions:[],width:0,height:0};const i=e.columns??4,s=e.spacing??10,n=e.padding??0,o=e.centerItems??!0,r=t[0].width??0,a=t[0].height??0,h=Math.ceil(t.length/i),l=[],c=i*r+(i-1)*s+2*n,u=h*a+(h-1)*s+2*n;let d=n,f=n,p=0;for(let e=0;e<t.length;e++){const t=o?d+r/2:d,e=o?f+a/2:f;l.push({x:t,y:e}),p++,p<i?d+=r+s:(p=0,d=n,f+=a+s)}return{positions:l,width:c,height:u}}function It(t,e={}){if(0===t.length)return{positions:[],width:0,height:0};const i=e.columns??4,s=e.spacing??10,n=e.padding??0,o=e.centerItems??!0,r=new Array(i).fill(0),a=[];t.forEach((t,e)=>{const s=e%i,n=Math.floor(e/i),o=t.width??0,h=t.height??0;r[s]=Math.max(r[s],o),void 0===a[n]?a[n]=h:a[n]=Math.max(a[n],h)});const h=[];let l=n,c=n,u=0;for(let e=0;e<t.length;e++){const d=t[e],f=d.width??0,p=d.height??0,g=a[Math.floor(e/i)],m=o?l+f/2:l,y=o?c+p/2:c;h.push({x:m,y:y}),u++,u<i?l+=r[u-1]+s:(u=0,l=n,c+=g+s)}return{positions:h,width:2*n+r.reduce((t,e)=>t+e,0)+s*(i-1),height:2*n+a.reduce((t,e)=>t+e,0)+s*(a.length-1),cols:i,rows:a.length}}class zt{constructor(t={}){this.x=0,this.y=0,this.target=t.target??null,this.deadzone=t.deadzone??null,this.lerp=t.lerp??.1,this.zoom=t.zoom??1,this.bounds=t.bounds??null,this.viewportWidth=t.viewportWidth??800,this.viewportHeight=t.viewportHeight??600,this.offsetX=t.offsetX??0,this.offsetY=t.offsetY??0,this._shakeIntensity=0,this._shakeDuration=0,this._shakeTime=0,this._shakeOffsetX=0,this._shakeOffsetY=0,this._initialX=this.x,this._initialY=this.y}update(t){if(!this.target)return;const e=this.target.x+this.offsetX,i=this.target.y+this.offsetY,s=this.x+this.viewportWidth/2,n=this.y+this.viewportHeight/2;let o=this.x,r=this.y;if(this.deadzone){const t=this.deadzone.width/2,a=this.deadzone.height/2;e<s-t?o=e+t-this.viewportWidth/2:e>s+t&&(o=e-t-this.viewportWidth/2),i<n-a?r=i+a-this.viewportHeight/2:i>n+a&&(r=i-a-this.viewportHeight/2)}else o=e-this.viewportWidth/2,r=i-this.viewportHeight/2;if(this.x+=(o-this.x)*this.lerp,this.y+=(r-this.y)*this.lerp,this.bounds){const t=this.bounds.maxX-this.viewportWidth,e=this.bounds.maxY-this.viewportHeight;this.x=Math.max(this.bounds.minX,Math.min(this.x,t)),this.y=Math.max(this.bounds.minY,Math.min(this.y,e))}this._updateShake(t)}_updateShake(t){if(this._shakeDuration>0&&this._shakeTime<this._shakeDuration){this._shakeTime+=t;const e=1-this._shakeTime/this._shakeDuration;this._shakeOffsetX=2*(Math.random()-.5)*this._shakeIntensity*e,this._shakeOffsetY=2*(Math.random()-.5)*this._shakeIntensity*e,this._shakeTime>=this._shakeDuration&&(this._shakeOffsetX=0,this._shakeOffsetY=0,this._shakeDuration=0,this._shakeTime=0)}}getOffset(){return{x:this.x+this._shakeOffsetX,y:this.y+this._shakeOffsetY}}setPosition(t,e){return this.x=t,this.y=e,this}setTarget(t){return this.target=t,this}shake(t,e){return this._shakeIntensity=t,this._shakeDuration=e,this._shakeTime=0,this}stopShake(){return this._shakeIntensity=0,this._shakeDuration=0,this._shakeTime=0,this._shakeOffsetX=0,this._shakeOffsetY=0,this}isVisible(t){if(!t)return!1;const e=this.x+this.viewportWidth,i=this.y+this.viewportHeight,s=t.x+(t.width||0),n=t.y+(t.height||0);return!(t.x>e||s<this.x||t.y>i||n<this.y)}screenToWorld(t,e){return{x:t/this.zoom+this.x,y:e/this.zoom+this.y}}worldToScreen(t,e){return{x:(t-this.x)*this.zoom,y:(e-this.y)*this.zoom}}getWorldBounds(){return{x:this.x,y:this.y,width:this.viewportWidth/this.zoom,height:this.viewportHeight/this.zoom}}reset(){return this.x=this._initialX,this.y=this._initialY,this.stopShake(),this}isShaking(){return this._shakeDuration>0&&this._shakeTime<this._shakeDuration}}class Bt{static symmetric(t,e,i,s,n=1,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+(Math.random()-.5)*i*n,y:r+(Math.random()-.5)*s*n}}static pointInBox(t,e,i,s,n="topleft"){return"centered"===n?{x:t+(Math.random()-.5)*i,y:e+(Math.random()-.5)*s}:{x:t+Math.random()*i,y:e+Math.random()*s}}static centered(t,e,i,s,n=50,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+2*(Math.random()-.5)*n,y:r+2*(Math.random()-.5)*n}}static gaussian(t,e,i,s,n=40,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+Bt._gaussian(0,n),y:r+Bt._gaussian(0,n)}}static radial(t,e,i,s,n=100,o="topleft"){const r="centered"===o?t:t+i/2,a="centered"===o?e:e+s/2,h=Math.random()*Math.PI*2,l=Math.random()*n;return{x:r+Math.cos(h)*l,y:a+Math.sin(h)*l}}static pick(t){return t[Math.floor(Math.random()*t.length)]}static pickOther(t,e){const i=t.filter(t=>t!==e);if(0!==i.length)return Bt.pick(i)}static float(t,e){return t+Math.random()*(e-t)}static int(t,e){return Math.floor(Bt.float(t,e+1))}static chance(t=.5){return Math.random()<t}static coin(){return Math.random()<.5}static _gaussian(t=0,e=1){let i=1-Math.random(),s=1-Math.random();return t+e*Math.sqrt(-2*Math.log(i))*Math.cos(2*Math.PI*s)}}class Et{constructor(t,e=0){this.real=t,this.imag=e}static fromPolar(t,e){return new Et(t*Math.cos(e),t*Math.sin(e))}add(t){return new Et(this.real+t.real,this.imag+t.imag)}subtract(t){return new Et(this.real-t.real,this.imag-t.imag)}multiply(t){return new Et(this.real*t.real-this.imag*t.imag,this.real*t.imag+this.imag*t.real)}divide(t){return new Et(this.real/t,this.imag/t)}scale(t){return new Et(this.real*t,this.imag*t)}abs(){return Math.sqrt(this.real*this.real+this.imag*this.imag)}}class Ft{static applyColorScheme(t,e,i,s,n,o){const r=(null==e?void 0:e.data)||[];for(let e=0;e<t.length;e++){const a=t[e],h=4*e;switch(i){case"futuristic":{const i=t[e]/10,s={r:0,g:5,b:10},n={r:0,g:30,b:20};if(i>.7){const t=3.33*(i-.7);r[h]=Math.floor(s.r*(1-t)+n.r*t),r[h+1]=Math.floor(s.g*(1-t)+n.g*t),r[h+2]=Math.floor(s.b*(1-t)+n.b*t)}else{const t=1.43*i;r[h]=Math.floor(s.r*t),r[h+1]=Math.floor(s.g*t),r[h+2]=Math.floor(s.b*t)}r[h+3]=255}break;case"rainbow":if(0===a)r[h]=0,r[h+1]=0,r[h+2]=0,r[h+3]=255;else{const t=(10*a+n)%360,[e,i,s]=o(t,.8,.5);r[h]=e,r[h+1]=i,r[h+2]=s,r[h+3]=255}break;case"grayscale":{const t=0===a?0:255-255*a/s;r[h]=t,r[h+1]=t,r[h+2]=t,r[h+3]=255}break;case"binary":0!==a?(r[h]=0,r[h+1]=0,r[h+2]=0):(r[h]=255,r[h+1]=255,r[h+2]=255),r[h+3]=255;break;case"fire":if(0==a)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=a/s;if(t<.3){const e=t/.3;r[h]=Math.floor(255*e),r[h+1]=0,r[h+2]=0}else if(t<.6){const e=(t-.3)/.3;r[h]=255,r[h+1]=Math.floor(165*e),r[h+2]=0}else if(t<.9){const e=(t-.6)/.3;r[h]=255,r[h+1]=165+Math.floor(90*e),r[h+2]=Math.floor(255*e)}else r[h]=255,r[h+1]=255,r[h+2]=255}r[h+3]=255;break;case"ocean":if(0===a)r[h]=0,r[h+1]=20,r[h+2]=50;else{const t=a/s;r[h]=Math.floor(10+50*t),r[h+1]=Math.floor(50+150*t),r[h+2]=Math.floor(100+155*t)}r[h+3]=255;break;case"electric":if(0===a)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=(a+n)%3,e=a%20/20;0===t?(r[h]=Math.floor(255*(.5+.5*Math.sin(e*Math.PI*2))),r[h+1]=Math.floor(128*e),r[h+2]=Math.floor(255*e)):1===t?(r[h]=Math.floor(255*e),r[h+1]=Math.floor(255*(.5+.5*Math.sin(e*Math.PI*2))),r[h+2]=Math.floor(128*e)):(r[h]=Math.floor(128*e),r[h+1]=Math.floor(255*e),r[h+2]=Math.floor(255*(.5+.5*Math.sin(e*Math.PI*2))))}r[h+3]=255;break;case"topographic":if(0===a)r[h]=5,r[h+1]=15,r[h+2]=30;else{const t=a/s;if(t<.1){const e=t/.1;r[h]=Math.floor(5+20*e),r[h+1]=Math.floor(15+40*e),r[h+2]=Math.floor(30+50*e)}else if(t<.3){const e=(t-.1)/.2;r[h]=Math.floor(210+45*e),r[h+1]=Math.floor(180+40*e),r[h+2]=Math.floor(140+30*e)}else if(t<.7){const e=(t-.3)/.4;r[h]=Math.floor(50*(1-e)),r[h+1]=Math.floor(100+80*e),r[h+2]=Math.floor(50*(1-e))}else{const e=(t-.7)/.3;r[h]=Math.floor(150+105*e),r[h+1]=Math.floor(150+105*e),r[h+2]=Math.floor(150+105*e)}}r[h+3]=255;break;default:if(0===a)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=(a+n)%64;t<16?(r[h]=16*t,r[h+1]=0,r[h+2]=0):t<32?(r[h]=255,r[h+1]=16*(t-16),r[h+2]=0):t<48?(r[h]=255-16*(t-32),r[h+1]=255,r[h+2]=0):(r[h]=0,r[h+1]=255-16*(t-48),r[h+2]=16*(t-48))}r[h+3]=255}}return null!=e?e:r}static pythagorasTree(t,e,i=10,s=-2,n=2,o=-.5,r=3.5){const a=new Uint8Array(t*e),h=e=>Math.floor((e-s)*t/(n-s)),l=t=>Math.floor((t-o)*e/(r-o)),c=(i,s,n,o)=>{const r=h(i),c=l(s),u=h(n),d=l(o);let f=r,p=c;const g=Math.abs(u-r),m=Math.abs(d-c),y=r<u?1:-1,x=c<d?1:-1;let v=g-m;for(;f>=0&&f<t&&p>=0&&p<e&&(a[p*t+f]=255),f!==u||p!==d;){const t=2*v;t>-m&&(v-=m,f+=y),t<g&&(v+=g,p+=x)}},u=(t,e,i,s,n)=>{if(n<=0)return;const o=i-t,r=s-e,a=i+r,h=s-o,l=t+r,d=e-o;((t,e,i,s,n,o,r,a)=>{c(t,e,i,s),c(i,s,n,o),c(n,o,r,a),c(r,a,t,e)})(t,e,i,s,a,h,l,d);const f=Math.PI/4,p=.7*Math.sqrt(o*o+r*r),g=p*Math.cos(Math.atan2(r,o)-f),m=p*Math.sin(Math.atan2(r,o)-f),y=.7*Math.sqrt(o*o+r*r),x=l,v=d,_=x+y*Math.cos(Math.atan2(r,o)+f),w=v+y*Math.sin(Math.atan2(r,o)+f);u(a,h,a+g,h+m,n-1),u(x,v,_,w,n-1)},d=Math.min(i,12);return u(-.5,0,.5,0,d),a}static mandelbrot(t,e,i=100,s=-2.5,n=1,o=-1.5,r=1.5){const a=new Uint8Array(t*e),h=(n-s)/t,l=(r-o)/e;for(let n=0;n<e;n++){const e=n*t,r=o+n*l;for(let n=0;n<t;n++){const t=s+n*h;let o=0,l=0,c=0,u=0,d=0;do{l=2*o*l+r,o=c-u+t,c=o*o,u=l*l,d++}while(c+u<4&&d<i);a[e+n]=d<i?d%256:0}}return a}static julia(t,e,i=100,s=-.7,n=.27,o=1,r=0,a=0){const h=new Uint8Array(t*e),l=2/o,c=-l+r,u=-l+a,d=(l+r-c)/t,f=(l+a-u)/e;for(let o=0;o<e;o++){const e=o*t,r=u+o*f;for(let o=0;o<t;o++){let t=c+o*d,a=r,l=0,u=0,f=0;do{l=t*t,u=a*a,a=2*t*a+n,t=l-u+s,f++}while(l+u<4&&f<i);h[e+o]=f<i?f%256:0}}return h}static tricorn(t,e,i=100,s=-2.5,n=1.5,o=-1.5,r=1.5){const a=new Uint8Array(t*e),h=(n-s)/t,l=(r-o)/e;for(let n=0;n<e;n++){const e=n*t,r=o+n*l;for(let n=0;n<t;n++){const t=s+n*h;let o=0,l=0,c=0,u=0,d=0;do{l=-2*o*l+r,o=c-u+t,c=o*o,u=l*l,d++}while(c+u<4&&d<i);a[e+n]=d<i?d%256:0}}return a}static phoenix(t,e,i=100,s=.5,n=.5,o=-2,r=2,a=-2,h=2){const l=new Uint8Array(t*e),c=(r-o)/t,u=(h-a)/e;for(let r=0;r<e;r++){const e=r*t,h=a+r*u;for(let r=0;r<t;r++){const t=o+r*c;let a=0,u=0,d=0,f=0,p=0,g=0,m=0;do{const e=p-g+t+s*d+n,i=2*a*u+h+s*f;d=a,f=u,a=e,u=i,p=a*a,g=u*u,m++}while(p+g<4&&m<i);l[e+r]=m<i?m%256:0}}return l}static newton(t,e,i=100,s=1e-6,n=-2,o=2,r=-2,a=2){const h=new Uint8Array(t*e),l=s*s,c=o-n,u=a-r,d=new Float64Array(3),f=new Float64Array(3);for(let t=0;t<3;t++){const e=2*Math.PI*t/3;d[t]=Math.cos(e),f[t]=Math.sin(e)}const p=c/t,g=u/e;for(let s=0;s<e;s++){const e=s*t,o=r+s*g;for(let s=0;s<t;s++){let t=n+s*p,r=o,a=0,c=-1;for(;a<i&&c<0;){const e=t*t-r*r,i=2*t*r,s=e*t-i*r-1,n=e*r+i*t,o=3*e,h=3*i,u=o*o+h*h;if(u<l)break;const p=1/u,g=t-(s*o+n*h)*p,m=r-(n*o-s*h)*p;for(let t=0;t<3;t++){const e=g-d[t],i=m-f[t];if(e*e+i*i<l){c=t;break}}t=g,r=m,a++}if(c>=0){const t=1-Math.min(a/i,1),n=85*c;h[e+s]=Math.floor(n+85*t)}else h[e+s]=0}}return h}static sierpinski(t,e,i=6,s=0,n=1,o=0,r=1){const a=new Uint8Array(t*e).fill(1),h=Math.sqrt(3)/2,l=n-s,c=(r-o)/l;if(Math.abs(c-h)>1e-9){const t=(o+r)/2,e=l*h;o=t-e/2,r=t+e/2}const u=(1<<Math.min(i,32))-1,d=(n-s)/t,f=(r-o)/e,p=2/Math.sqrt(3);for(let i=0;i<e;++i){const e=o+i*f,n=Math.floor(e*p),r=.5*n;for(let e=0;e<t;++e){const o=s+e*d;0!==(Math.floor(o-r)&n&u)&&(a[i*t+e]=0)}}return a}static sierpinskiCarpet(t,e,i=5,s=0,n=1,o=0,r=1){const a=new Uint8Array(t*e).fill(1),h=n-s,l=r-o,c=Math.max(h,l),u=(s+n)/2,d=(o+r)/2;s=u-c/2,n=u+c/2,o=d-c/2,r=d+c/2;const f=Math.pow(3,i),p=(t,e)=>{let i=t,s=e;for(;i>0||s>0;){if(i%3==1&&s%3==1)return!0;i=Math.floor(i/3),s=Math.floor(s/3)}return!1};for(let i=0;i<e;++i){const h=(o+i/e*(r-o))*f,l=(Math.floor(h)%f+f)%f;for(let e=0;e<t;++e){const o=(s+e/t*(n-s))*f;p((Math.floor(o)%f+f)%f,l)&&(a[i*t+e]=0)}}return a}static barnsleyFern(t,e,i=1e5){const s=new Uint8Array(t*e).fill(0);let n=0,o=0;const r=Math.min(t,e)/10,a=t/2;for(let h=0;h<i;h++){const i=Math.random();let h,l;i<.01?(h=0,l=.16*o):i<.86?(h=.85*n+.04*o,l=-.04*n+.85*o+1.6):i<.93?(h=.2*n-.26*o,l=.23*n+.22*o+1.6):(h=-.15*n+.28*o,l=.26*n+.24*o+.44),n=h,o=l;const c=Math.floor(n*r+a),u=Math.floor(e-o*r);if(c>=0&&c<t&&u>=0&&u<e){const e=u*t+c;s[e]<255&&s[e]++}}return s}static lyapunov(t,e,i=1e3,s="AB",n=3.4,o=4,r=3.4,a=4){console.time("lyapunov");const h=(s=s.toUpperCase().replace(/[^AB]/g,"")||"AB").length,l=new Float32Array(t*e);let c=1/0,u=-1/0;for(let d=0;d<e;d++){const f=r+(a-r)*d/e;for(let e=0;e<t;e++){const r=n+(o-n)*e/t;let a=.5;for(let t=0;t<100;t++)a=("A"===s[t%h]?r:f)*a*(1-a);let p=0,g=0;for(;g<i;){const t="A"===s[g%h]?r:f;a=t*a*(1-a);const e=Math.abs(t*(1-2*a));if(p+=Math.log(Math.max(e,1e-10)),g++,Math.abs(p/g)>10)break}const m=p/g;l[d*t+e]=m,m>-10&&m<10&&(m<c&&(c=m),m>u&&(u=m))}}c===u&&(c-=1,u+=1);const d=u-c,f=new Uint8Array(t*e);for(let t=0;t<l.length;t++){let e=l[t];e=Math.max(-10,Math.min(10,e));let i=(e-c)/d;f[t]=Math.floor(255*i)}return console.timeEnd("lyapunov"),f}static koch(t,e,i=4,s=-2,n=2,o=-2,r=2){const a=new Uint8Array(t*e),h=e=>Math.floor((e-s)*t/(n-s)),l=t=>Math.floor((t-o)*e/(r-o)),c=(i,s,n,o,r)=>{if(r<=0)return void((i,s,n,o)=>{const r=h(i),c=l(s),u=h(n),d=l(o);let f=r,p=c;const g=Math.abs(u-r),m=Math.abs(d-c),y=r<u?1:-1,x=c<d?1:-1;let v=g-m;for(;f>=0&&f<t&&p>=0&&p<e&&(a[p*t+f]=255),f!==u||p!==d;){const t=2*v;t>-m&&(v-=m,f+=y),t<g&&(v+=g,p+=x)}})(i,s,n,o);const u=(n-i)/3,d=(o-s)/3,f=i+u,p=s+d,g=i+2*u,m=s+2*d,y=Math.PI/3,x=f+u*Math.cos(y)-d*Math.sin(y),v=p+u*Math.sin(y)+d*Math.cos(y);c(i,s,f,p,r-1),c(f,p,x,v,r-1),c(x,v,g,m,r-1),c(g,m,n,o,r-1)},u=Math.min(i,10),d=3*Math.sqrt(3)/2,f=[0,-d/2+.5],p=[-1.5,d/2+.5],g=[1.5,d/2+.5];return c(f[0],f[1],p[0],p[1],u),c(p[0],p[1],g[0],g[1],u),c(g[0],g[1],f[0],f[1],u),a}}vt(Ft,"types",{MANDELBROT:"mandelbrot",TRICORN:"tricorn",PHOENIX:"phoenix",JULIA:"julia",SIERPINSKI:"sierpinski",SCARPET:"sierpinskiCarpet",BARNSEY_FERN:"barnsleyFern",KOCH:"koch",PYTHAGORAS_TREE:"pythagorasTree",NEWTON:"newton",LYAPUNOV:"lyapunov"}),vt(Ft,"colors",{FUTURISTIC:"futuristic",RAINBOW:"rainbow",GRAYSCALE:"grayscale",TOPOGRAPHIC:"topographic",FIRE:"fire",OCEAN:"ocean",ELECTRIC:"electric",BINARY:"binary",HISTORIC:"historic"});const Ot=class{static seed(t){t>0&&t<1&&(t*=65536),(t=Math.floor(t))<256&&(t|=t<<8);for(let e=0;e<256;e++){let r;r=1&e?wt(this,s)[e]^255&t:wt(this,s)[e]^t>>8&255,wt(this,n)[e]=wt(this,n)[e+256]=r,wt(this,o)[e]=wt(this,o)[e+256]=wt(this,i)[r%12]}}static simplex2(t,e){let i,s,h;const l=(t+e)*wt(this,r),c=Math.floor(t+l),u=Math.floor(e+l),d=(c+u)*wt(this,a),f=t-c+d,p=e-u+d;let g,m;f>p?(g=1,m=0):(g=0,m=1);const y=f-g+wt(this,a),x=p-m+wt(this,a),v=f-1+2*wt(this,a),_=p-1+2*wt(this,a),w=255&c,b=255&u,M=wt(this,o)[w+wt(this,n)[b]],k=wt(this,o)[w+g+wt(this,n)[b+m]],C=wt(this,o)[w+1+wt(this,n)[b+1]];let S=.5-f*f-p*p;S<0?i=0:(S*=S,i=S*S*M.dot2(f,p));let T=.5-y*y-x*x;T<0?s=0:(T*=T,s=T*T*k.dot2(y,x));let R=.5-v*v-_*_;return R<0?h=0:(R*=R,h=R*R*C.dot2(v,_)),70*(i+s+h)}static simplex3(t,e,i){let s,r,a,c;const u=(t+e+i)*wt(this,h),d=Math.floor(t+u),f=Math.floor(e+u),p=Math.floor(i+u),g=(d+f+p)*wt(this,l),m=t-d+g,y=e-f+g,x=i-p+g;let v,_,w,b,M,k;m>=y?y>=x?(v=1,_=0,w=0,b=1,M=1,k=0):m>=x?(v=1,_=0,w=0,b=1,M=0,k=1):(v=0,_=0,w=1,b=1,M=0,k=1):y<x?(v=0,_=0,w=1,b=0,M=1,k=1):m<x?(v=0,_=1,w=0,b=0,M=1,k=1):(v=0,_=1,w=0,b=1,M=1,k=0);const C=m-v+wt(this,l),S=y-_+wt(this,l),T=x-w+wt(this,l),R=m-b+2*wt(this,l),P=y-M+2*wt(this,l),A=x-k+2*wt(this,l),D=m-1+3*wt(this,l),I=y-1+3*wt(this,l),z=x-1+3*wt(this,l),B=255&d,E=255&f,F=255&p,O=wt(this,o)[B+wt(this,n)[E+wt(this,n)[F]]],X=wt(this,o)[B+v+wt(this,n)[E+_+wt(this,n)[F+w]]],Y=wt(this,o)[B+b+wt(this,n)[E+M+wt(this,n)[F+k]]],W=wt(this,o)[B+1+wt(this,n)[E+1+wt(this,n)[F+1]]];let L=.6-m*m-y*y-x*x;L<0?s=0:(L*=L,s=L*L*O.dot3(m,y,x));let H=.6-C*C-S*S-T*T;H<0?r=0:(H*=H,r=H*H*X.dot3(C,S,T));let N=.6-R*R-P*P-A*A;N<0?a=0:(N*=N,a=N*N*Y.dot3(R,P,A));let G=.6-D*D-I*I-z*z;return G<0?c=0:(G*=G,c=G*G*W.dot3(D,I,z)),32*(s+r+a+c)}static perlin2(t,e){const i=Math.floor(t),s=Math.floor(e);t-=i,e-=s;const r=255&i,a=255&s,h=wt(this,o)[r+wt(this,n)[a]].dot2(t,e),l=wt(this,o)[r+wt(this,n)[a+1]].dot2(t,e-1),f=wt(this,o)[r+1+wt(this,n)[a]].dot2(t-1,e),p=wt(this,o)[r+1+wt(this,n)[a+1]].dot2(t-1,e-1),g=kt(this,c,u).call(this,t);return kt(this,c,d).call(this,kt(this,c,d).call(this,h,f,g),kt(this,c,d).call(this,l,p,g),kt(this,c,u).call(this,e))}static perlin3(t,e,i){const s=Math.floor(t),r=Math.floor(e),a=Math.floor(i);t-=s,e-=r,i-=a;const h=255&s,l=255&r,f=255&a,p=wt(this,o)[h+wt(this,n)[l+wt(this,n)[f]]].dot3(t,e,i),g=wt(this,o)[h+wt(this,n)[l+wt(this,n)[f+1]]].dot3(t,e,i-1),m=wt(this,o)[h+wt(this,n)[l+1+wt(this,n)[f]]].dot3(t,e-1,i),y=wt(this,o)[h+wt(this,n)[l+1+wt(this,n)[f+1]]].dot3(t,e-1,i-1),x=wt(this,o)[h+1+wt(this,n)[l+wt(this,n)[f]]].dot3(t-1,e,i),v=wt(this,o)[h+1+wt(this,n)[l+wt(this,n)[f+1]]].dot3(t-1,e,i-1),_=wt(this,o)[h+1+wt(this,n)[l+1+wt(this,n)[f]]].dot3(t-1,e-1,i),w=wt(this,o)[h+1+wt(this,n)[l+1+wt(this,n)[f+1]]].dot3(t-1,e-1,i-1),b=kt(this,c,u).call(this,t),M=kt(this,c,u).call(this,e),k=kt(this,c,u).call(this,i);return kt(this,c,d).call(this,kt(this,c,d).call(this,kt(this,c,d).call(this,p,x,b),kt(this,c,d).call(this,g,v,b),k),kt(this,c,d).call(this,kt(this,c,d).call(this,m,_,b),kt(this,c,d).call(this,y,w,b),k),M)}};e=new WeakMap,i=new WeakMap,s=new WeakMap,n=new WeakMap,o=new WeakMap,r=new WeakMap,a=new WeakMap,h=new WeakMap,l=new WeakMap,c=new WeakSet,u=function(t){return t*t*t*(t*(6*t-15)+10)},d=function(t,e,i){return(1-i)*t+i*e},bt(Ot,c),bt(Ot,e,class{constructor(t,e,i){this.x=t,this.y=e,this.z=i}dot2(t,e){return this.x*t+this.y*e}dot3(t,e,i){return this.x*t+this.y*e+this.z*i}}),bt(Ot,i,[new(wt(Ot,e))(1,1,0),new(wt(Ot,e))(-1,1,0),new(wt(Ot,e))(1,-1,0),new(wt(Ot,e))(-1,-1,0),new(wt(Ot,e))(1,0,1),new(wt(Ot,e))(-1,0,1),new(wt(Ot,e))(1,0,-1),new(wt(Ot,e))(-1,0,-1),new(wt(Ot,e))(0,1,1),new(wt(Ot,e))(0,-1,1),new(wt(Ot,e))(0,1,-1),new(wt(Ot,e))(0,-1,-1)]),bt(Ot,s,[151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]),bt(Ot,n,new Array(512)),bt(Ot,o,new Array(512)),bt(Ot,r,.5*(Math.sqrt(3)-1)),bt(Ot,a,(3-Math.sqrt(3))/6),bt(Ot,h,1/3),bt(Ot,l,1/6),Ot.seed(0);let Xt=Ot;function Yt(t=800,e=800,i){const{divisions:s=5,zoomType:n="in",color1:o=[255,0,0,255],color2:r=[0,0,255,255],color3:a=[0,0,0,255],backgroundColor:h=[255,255,255,255]}=i||{},l=new Uint8ClampedArray(t*e*4);for(let t=0;t<l.length;t+=4)l[t]=h[0],l[t+1]=h[1],l[t+2]=h[2],l[t+3]=h[3]||255;const c="in"===n?1:2,u=Math.max(t,e),d=u/c,f=u/c,p=.5*c,g=.5*c,m=(Math.sqrt(5)+1)/2;let y=[];for(let t=0;t<10;t++){const e=Et.fromPolar(1,(2*t-1)*Math.PI/10),i=Et.fromPolar(1,(2*t+1)*Math.PI/10);t%2==0?y.push(["thin",new Et(0),i,e]):y.push(["thin",new Et(0),e,i])}for(let t=0;t<s;t++){const t=[];for(const[e,i,s,n]of y)if("thin"===e){const e=i.add(s.subtract(i).scale(1/m));t.push(["thin",n,e,s]),t.push(["thicc",e,n,i])}else{const e=s.add(i.subtract(s).scale(1/m)),o=s.add(n.subtract(s).scale(1/m));t.push(["thicc",o,n,i]),t.push(["thicc",e,o,s]),t.push(["thin",o,e,i])}y=t}function x(i){return{x:Math.floor((i.real*d+p*d)*t/u),y:Math.floor((i.imag*f+g*f)*e/u)}}for(const[i,s,n,a]of y)Wt(l,x(s),x(n),x(a),"thin"===i?o:r,t,e);if(a&&a[3]>0)for(const[i,s,n,o]of y){const i=x(s),r=x(n),h=x(o);Nt(l,i,r,a,t,e),Nt(l,r,h,a,t,e),Nt(l,h,i,a,t,e)}return l}function Wt(t,e,i,s,n,o,r){e.y>i.y&&([e,i]=[i,e]),e.y>s.y&&([e,s]=[s,e]),i.y>s.y&&([i,s]=[s,i]);const a=n[0],h=n[1],l=n[2],c=n[3]||255;if(i.y===s.y)Lt(t,e,i,s,a,h,l,c,o,r);else if(e.y===i.y)Ht(t,e,i,s,a,h,l,c,o,r);else{const n={x:Math.floor(e.x+(i.y-e.y)/(s.y-e.y)*(s.x-e.x)),y:i.y};Lt(t,e,i,n,a,h,l,c,o,r),Ht(t,i,n,s,a,h,l,c,o,r)}}function Lt(t,e,i,s,n,o,r,a,h,l){const c=(i.x-e.x)/(i.y-e.y||1),u=(s.x-e.x)/(s.y-e.y||1);let d=e.x,f=e.x;for(let s=e.y;s<=i.y;s++){if(s>=0&&s<l){const e=Math.max(0,Math.min(Math.floor(d),h-1)),i=Math.max(0,Math.min(Math.floor(f),h-1));for(let l=Math.min(e,i);l<=Math.max(e,i);l++){const e=4*(s*h+l);e>=0&&e<t.length-3&&(t[e]=n,t[e+1]=o,t[e+2]=r,t[e+3]=a)}}d+=c,f+=u}}function Ht(t,e,i,s,n,o,r,a,h,l){const c=(s.x-e.x)/(s.y-e.y||1),u=(s.x-i.x)/(s.y-i.y||1);let d=s.x,f=s.x;for(let i=s.y;i>e.y;i--)if(i>=0&&i<l){d-=c,f-=u;const e=Math.max(0,Math.min(Math.floor(d),h-1)),s=Math.max(0,Math.min(Math.floor(f),h-1));for(let l=Math.min(e,s);l<=Math.max(e,s);l++){const e=4*(i*h+l);e>=0&&e<t.length-3&&(t[e]=n,t[e+1]=o,t[e+2]=r,t[e+3]=a)}}}function Nt(t,e,i,s,n,o){const r=s[0],a=s[1],h=s[2],l=s[3]||255;let c=e.x,u=e.y,d=i.x,f=i.y;const p=Math.abs(d-c),g=Math.abs(f-u),m=c<d?1:-1,y=u<f?1:-1;let x=p-g;for(;;){if(c>=0&&c<n&&u>=0&&u<o){const e=4*(u*n+c);if(e>=0&&e<t.length-3){const i=l/255;t[e]=Math.round(t[e]*(1-i)+r*i),t[e+1]=Math.round(t[e+1]*(1-i)+a*i),t[e+2]=Math.round(t[e+2]*(1-i)+h*i),t[e+3]=255}}if(c===d&&u===f)break;const e=2*x;e>-g&&(x-=g,c+=m),e<p&&(x+=p,u+=y)}}f=new WeakMap,p=new WeakMap,g=new WeakMap,m=new WeakMap,y=new WeakMap;const Gt={tokens:{unaryNot:["!","~","¬","NOT"],and:["&","∧","AND"],nand:["NAND"],or:["|","∨","OR"],nor:["NOR"],xor:["^","⊕","XOR"],xnor:["XNOR"]},precedence:{OR:1,NOR:1,XOR:2,XNOR:2,AND:3,NAND:3,NOT:4},constants:{true:["1","TRUE"],false:["0","FALSE"]}};function Ut(t){return Boolean(t)}function qt(t){return String(t).toUpperCase()}function Zt(t){const e=qt(t);if(Gt.tokens.unaryNot.map(qt).includes(e))return"NOT";if(Gt.tokens.and.map(qt).includes(e))return"AND";if(Gt.tokens.nand.map(qt).includes(e))return"NAND";if(Gt.tokens.or.map(qt).includes(e))return"OR";if(Gt.tokens.nor.map(qt).includes(e))return"NOR";if(Gt.tokens.xor.map(qt).includes(e))return"XOR";if(Gt.tokens.xnor.map(qt).includes(e))return"XNOR";throw new Error(`[BooleanAlgebra] Unknown operator "${t}"`)}function Vt(t){return Gt.precedence[t]??0}function $t(t){let e=0;const i=()=>t[e],s=()=>t[e++];function n(){const t=s();if(!t)throw new Error("[BooleanAlgebra] Unexpected end of input");if("const"===t.type){const e=qt(t.value);return{type:"const",value:Gt.constants.true.includes(e)}}if("ident"===t.type)return{type:"var",name:t.value};if("lp"===t.type){const t=o(0),e=s();if(!e||"rp"!==e.type)throw new Error("[BooleanAlgebra] Missing closing ')'");return t}if("op"===t.type){if("NOT"!==Zt(t.value))throw new Error(`[BooleanAlgebra] Unexpected binary operator "${t.value}"`);return{type:"not",left:n()}}throw new Error(`[BooleanAlgebra] Unexpected token "${t.type}"`)}function o(t){let e=n();for(;;){const n=i();if(!n||"op"!==n.type)break;const r=Zt(n.value);if("NOT"===r)break;const a=Vt(r);if(a<t)break;s(),e={type:"AND"===r?"and":"OR"===r?"or":"XOR"===r?"xor":"NAND"===r?"nand":"NOR"===r?"nor":"xnor",left:e,right:o(a+1)}}return e}const r=o(0);if(e<t.length)throw new Error("[BooleanAlgebra] Unexpected trailing tokens");return r}function jt(t,e){switch(t.type){case"const":return Boolean(t.value);case"var":return Ut((null==e?void 0:e[t.name])??!1);case"not":return!jt(t.left,e);case"and":return jt(t.left,e)&&jt(t.right,e);case"nand":return!(jt(t.left,e)&&jt(t.right,e));case"or":return jt(t.left,e)||jt(t.right,e);case"nor":return!(jt(t.left,e)||jt(t.right,e));case"xor":{const i=jt(t.left,e),s=jt(t.right,e);return i&&!s||!i&&s}case"xnor":return jt(t.left,e)===jt(t.right,e);default:throw new Error(`[BooleanAlgebra] Unknown AST node type "${t.type}"`)}}function Kt(t,e){t&&("var"===t.type&&t.name&&e.add(t.name),t.left&&Kt(t.left,e),t.right&&Kt(t.right,e))}function Jt(t){const e=1<<t,i=new Array(e);for(let t=0;t<e;t++)i[t]=t^t>>1;return i}class Qt{static and(t,e){return Ut(t)&&Ut(e)}static nand(t,e){return!(Ut(t)&&Ut(e))}static or(t,e){return Ut(t)||Ut(e)}static nor(t,e){return!(Ut(t)||Ut(e))}static xor(t,e){const i=Ut(t),s=Ut(e);return i&&!s||!i&&s}static xnor(t,e){return Ut(t)===Ut(e)}static not(t){return!Ut(t)}static parse(t){return $t(function(t){const e=[],i=String(t??"");let s=0;const n=t=>" "===t||"\n"===t||"\t"===t||"\r"===t,o=t=>t>="A"&&t<="Z"||t>="a"&&t<="z"||"_"===t,r=t=>o(t)||t>="0"&&t<="9";for(;s<i.length;){const t=i[s];if(n(t))s++;else if("("!==t)if(")"!==t){if("!"!==t&&"~"!==t&&"¬"!==t&&"&"!==t&&"∧"!==t&&"|"!==t&&"∨"!==t&&"^"!==t&&"⊕"!==t){if(o(t)||t>="0"&&t<="9"){let t=s+1;for(;t<i.length&&r(i[t]);)t++;const n=i.slice(s,t),o=qt(n);Gt.constants.true.includes(o)||Gt.constants.false.includes(o)?e.push({type:"const",value:o}):Gt.tokens.unaryNot.includes(o)||Gt.tokens.and.includes(o)||Gt.tokens.nand.includes(o)||Gt.tokens.or.includes(o)||Gt.tokens.nor.includes(o)||Gt.tokens.xor.includes(o)||Gt.tokens.xnor.includes(o)?e.push({type:"op",value:o}):e.push({type:"ident",value:n}),s=t;continue}throw new Error(`[BooleanAlgebra] Unexpected character "${t}" at ${s}`)}e.push({type:"op",value:t}),s++}else e.push({type:"rp",value:t}),s++;else e.push({type:"lp",value:t}),s++}return e}(t))}static evaluate(t,e={}){return jt("string"==typeof t?Qt.parse(t):t,e)}static variables(t){const e="string"==typeof t?Qt.parse(t):t,i=new Set;return Kt(e,i),[...i].sort((t,e)=>t.localeCompare(e))}static grayCode(t){return Jt(t)}static truthTable(t,e,i={}){const s="string"==typeof t?Qt.parse(t):t,n=e&&e.length>0?[...e]:Qt.variables(s),o=n.length,r=1<<o,a="gray"===i.order?"gray":"binary",h=("gray"===a?Jt(o):Array.from({length:r},(t,e)=>e)).map(t=>{const e={};for(let i=0;i<o;i++){const s=1<<o-1-i;e[n[i]]=Boolean(t&s)}return{index:t,inputs:e,output:jt(s,e)}});return{variables:n,order:a,rows:h}}}function te(t,e,i){return t<=e?0:Math.sqrt(8*i*(t-e))}function ee(t,e,i,s,n=5){return t<=n||t>=e?0:Math.exp(-t*s)*i}class ie{static lerp(t,e,i){return t+(e-t)*i}static linear(t){return t}static smoothstep(t){return t*t*(3-2*t)}static smootherstep(t){return t*t*t*(t*(6*t-15)+10)}static easeInQuad(t){return t*t}static easeOutQuad(t){return t*(2-t)}static easeInOutQuad(t){return t<.5?2*t*t:(4-2*t)*t-1}static easeInCubic(t){return t*t*t}static easeOutCubic(t){return--t*t*t+1}static easeInOutCubic(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1}static easeInQuart(t){return t*t*t*t}static easeOutQuart(t){return 1- --t*t*t*t}static easeInOutQuart(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t}static easeInSine(t){return 1-Math.cos(t*Math.PI/2)}static easeOutSine(t){return Math.sin(t*Math.PI/2)}static easeInOutSine(t){return-(Math.cos(Math.PI*t)-1)/2}static easeInExpo(t){return 0===t?0:Math.pow(2,10*(t-1))}static easeOutExpo(t){return 1===t?1:1-Math.pow(2,-10*t)}static easeInOutExpo(t){return 0===t||1===t?t:t<.5?.5*Math.pow(2,20*t-10):.5*(2-Math.pow(2,-20*t+10))}static easeInCirc(t){return 1-Math.sqrt(1-t*t)}static easeOutCirc(t){return Math.sqrt(1- --t*t)}static easeInOutCirc(t){return t<.5?.5*(1-Math.sqrt(1-4*t*t)):.5*(Math.sqrt(-(2*t-3)*(2*t-1))+1)}static easeInElastic(t,e=1,i=.3){if(0===t||1===t)return t;const s=i/(2*Math.PI)*Math.asin(1/e);return-e*Math.pow(2,10*(t-1))*Math.sin((t-1-s)*(2*Math.PI)/i)}static easeOutElastic(t,e=1,i=.3){if(0===t||1===t)return t;const s=i/(2*Math.PI)*Math.asin(1/e);return e*Math.pow(2,-10*t)*Math.sin((t-s)*(2*Math.PI)/i)+1}static easeInOutElastic(t,e=1,i=.3){if(0===t||1===t)return t;const s=i/(2*Math.PI)*Math.asin(1/e);return t<.5?e*Math.pow(2,10*(2*t-1))*Math.sin((2*t-1-s)*(2*Math.PI)/i)*-.5:e*Math.pow(2,-10*(2*t-1))*Math.sin((2*t-1-s)*(2*Math.PI)/i)*.5+1}static easeInBack(t,e=1.70158){return t*t*((e+1)*t-e)}static easeOutBack(t,e=1.70158){return--t*t*((e+1)*t+e)+1}static easeInOutBack(t,e=1.70158){const i=1.525*e;return t<.5?2*t*.5*(2*t)*(2*(i+1)*t-i):.5*((2*t-2)*(2*t-2)*((i+1)*(2*t-2)+i)+2)}static easeOutBounce(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}static easeInBounce(t){return 1-ie.easeOutBounce(1-t)}static easeInOutBounce(t){return t<.5?.5*ie.easeInBounce(2*t):.5*ie.easeOutBounce(2*t-1)+.5}}function se(t,e,i){const s=Math.max(0,Math.min(1,(i-t)/(e-t)));return ie.smoothstep(s)}function ne(t,e,i){const{heatZone:s,coolZone:n,rate:o,heatMultiplier:r=1.5,coolMultiplier:a=1.5,middleMultiplier:h=.05,transitionWidth:l=.1}=i,c=se(s-l,s+.5*l,t),u=1-se(n-.5*l,n+l,t),d=1-c-u;let f=0;return c>0&&(f+=(1-e)*o*r*c),u>0&&(f+=(0-e)*o*a*u),d>0&&(f+=(t-e)*o*h*d),Math.max(0,Math.min(1,e+f))}const oe={smoothingRadius:28},re={restDensity:1.1,particleMass:1,pressureStiffness:1800,nearPressureStiffness:2.5,viscosity:.18,surfaceTension:0,maxForce:6e3},ae={interactionRadius:34,pressure:12,diffusion:.08,drag:.04,buoyancy:260,neutralTemperature:.5,turbulence:16},he={gravity:{x:0,y:820}},le=1e-4;function ce(t={}){return{kernel:{...oe,...t.kernel||{}},fluid:{...re,...t.fluid||{}},gas:{...ae,...t.gas||{}},external:{...he,...t.external||{}}}}const ue={poly6(t,e){const i=e*e;if(t>=i)return 0;const s=i-t;return 4/(Math.PI*Math.pow(e,8))*s*s*s},spikyPow2(t,e){if(t>=e)return 0;const i=e-t;return 6/(Math.PI*Math.pow(e,4))*i*i},spikyPow3(t,e){if(t>=e)return 0;const i=e-t;return 10/(Math.PI*Math.pow(e,5))*i*i*i},spikyPow2Derivative:(t,e)=>0===t||t>=e?0:-12/(Math.PI*Math.pow(e,4))*(e-t),spikyPow3Derivative(t,e){if(0===t||t>=e)return 0;const i=e-t;return-30/(Math.PI*Math.pow(e,5))*i*i},spikyGradient:(t,e)=>0===t||t>=e?0:-30/(Math.PI*Math.pow(e,5))*((e-t)*(e-t)),viscosityLaplacian:(t,e)=>t>=e?0:40/(Math.PI*Math.pow(e,5))*(e-t)};function de(t,e={},i){const s=ce(e).kernel.smoothingRadius,n=s*s,o=i??ve(t,s),r=t.length,a=new Float32Array(r),h=new Float32Array(r);for(let e=0;e<r;e++)a[e]=ue.spikyPow2(0,s),h[e]=ue.spikyPow3(0,s),_e(e,t,o,n,(t,i,n,o)=>{const r=Math.sqrt(o);a[e]+=ue.spikyPow2(r,s),h[e]+=ue.spikyPow3(r,s)});return{densities:a,nearDensities:h}}function fe(t,e,i={}){const s=ce(i),n=t.length,o=new Float32Array(n),r=new Float32Array(n),{pressureStiffness:a,nearPressureStiffness:h,restDensity:l}=s.fluid;for(let i=0;i<n;i++)o[i]=(t[i]-l)*a,r[i]=e[i]*h;return{pressures:o,nearPressures:r}}function pe(t,e={}){const i=ce(e),s=i.kernel.smoothingRadius,n=s*s,o=t.length,r=ve(t,s),{densities:a,nearDensities:h}=de(t,i,r),{pressures:l,nearPressures:c}=fe(a,h,i),u=new Array(o);for(let t=0;t<o;t++)u[t]={x:0,y:0};for(let e=0;e<o;e++){const o=t[e];Math.max(a[e],le),_e(e,t,r,n,(n,r,d,f)=>{if(n<=e)return;const p=Math.sqrt(f);if(p<le||p>=s)return;const g=t[n],m=1/p,y=-r*m,x=-d*m,v=Math.max(a[n],le),_=Math.max(h[n],le),w=.5*(l[e]+l[n]),b=.5*(c[e]+c[n]),M=w*ue.spikyPow2Derivative(p,s)/v+b*ue.spikyPow3Derivative(p,s)/_,k=y*M,C=x*M;u[e].x+=k,u[e].y+=C,u[n].x-=k,u[n].y-=C;const S=ue.poly6(f,s),T=i.fluid.viscosity*S,R=(g.vx-o.vx)*T,P=(g.vy-o.vy)*T;u[e].x+=R,u[e].y+=P,u[n].x-=R,u[n].y-=P})}return xe(u,i.fluid.maxForce),{forces:u,densities:a,pressures:l}}function ge(t,e={}){var i;const s=ce(e),n=s.gas.interactionRadius,o=n*n,r=t.length,a=ve(t,n),h=new Array(r);for(let t=0;t<r;t++)h[t]={x:0,y:0};for(let e=0;e<r;e++){const r=t[e],l=ye(r,s),c=r.temperature??(null==(i=r.custom)?void 0:i.temperature)??s.gas.neutralTemperature;_e(e,t,a,o,(i,o,a,u)=>{var d;if(i<=e)return;if(0===u)return;const f=Math.sqrt(u),p=1/f,g=t[i],m=ye(g,s),y=g.temperature??(null==(d=g.custom)?void 0:d.temperature)??s.gas.neutralTemperature,x=s.gas.pressure*(1-f/n),v=o*p*x,_=a*p*x;h[e].x+=v,h[e].y+=_,h[i].x-=v,h[i].y-=_;const w=s.gas.diffusion,b=(g.vx-r.vx)*w,M=(g.vy-r.vy)*w;h[e].x+=b*m,h[e].y+=M*m,h[i].x-=b*l,h[i].y-=M*l;const k=(c-y)*s.gas.buoyancy*.5;h[e].y-=k,h[i].y+=k})}for(let e=0;e<r;e++){const i=t[e],n=s.gas.drag;h[e].x+=-i.vx*n,h[e].y+=-i.vy*n,h[e].x+=(Math.random()-.5)*s.gas.turbulence,h[e].y+=(Math.random()-.5)*s.gas.turbulence}return xe(h,s.fluid.maxForce),{forces:h}}function me(t,e,i){const s=Math.min(t.length,e.length),n=new Array(s);for(let o=0;o<s;o++)n[o]={x:ie.lerp(t[o].x,e[o].x,i),y:ie.lerp(t[o].y,e[o].y,i)};return n}function ye(t,e){return t.custom&&"number"==typeof t.custom.mass?t.custom.mass:t.mass?t.mass:t.size?.5*t.size+e.fluid.particleMass:e.fluid.particleMass}function xe(t,e){const i=e*e;for(let s=0;s<t.length;s++){const n=t[s],o=n.x*n.x+n.y*n.y;if(o>i){const t=1/Math.sqrt(o);n.x*=e*t,n.y*=e*t}}}function ve(t,e){const i=e,s=new Map;for(let e=0;e<t.length;e++){const n=t[e],o=`${Math.floor(n.x/i)},${Math.floor(n.y/i)}`;let r=s.get(o);r||(r=[],s.set(o,r)),r.push(e)}return{cellSize:i,buckets:s}}function _e(t,e,i,s,n){const o=e[t],r=i.cellSize,a=Math.floor(o.x/r),h=Math.floor(o.y/r);for(let r=-1;r<=1;r++)for(let l=-1;l<=1;l++){const c=`${a+r},${h+l}`,u=i.buckets.get(c);if(u)for(let i=0;i<u.length;i++){const r=u[i];if(r===t)continue;const a=e[r],h=o.x-a.x,l=o.y-a.y,c=h*h+l*l;c<s&&n(r,h,l,c)}}}const we=class t{static disableAll(){t.enabledClasses=new Set,t.globalLevel=0}static disable(){t.enabled=!1}static enable(){t.enabled=!0}static setLevel(e){t.globalLevel=e}static enableFor(e){t.enabledClasses.add(e)}static disableFor(e){t.enabledClasses.delete(e)}static setOutput(e){t.output=e}constructor(t){this.className=t}static getLogger(e){return t.loggerz[e]||(t.loggerz[e]=new t(e)),t.loggerz[e]}_log(e,i,...s){t.enabled&&(t.globalLevel>=e||t.enabledClasses.has(this.className))&&t.output[i](`[${this.className}]`,...s)}log(...e){this._log(t.INFO,"log",...e)}warn(...e){this._log(t.WARN,"warn",...e)}error(...e){this._log(t.ERROR,"error",...e)}debug(...e){this._log(t.DEBUG,"log",...e)}table(...e){this._log(t.INFO,"table",...e)}groupCollapsed(e){t.enabled&&t.output.groupCollapsed(`[${this.className}] ${e}`)}groupEnd(){t.enabled&&t.output.groupEnd()}time(e){t.enabled&&t.output.time(`[${this.className}] ${e}`)}timeEnd(e){t.enabled&&t.output.timeEnd(`[${this.className}] ${e}`)}clear(){t.output.clear()}};vt(we,"ERROR",1),vt(we,"WARN",2),vt(we,"INFO",3),vt(we,"DEBUG",4),vt(we,"globalLevel",we.ERROR),vt(we,"enabledClasses",new Set),vt(we,"output",console),vt(we,"enabled",!0),vt(we,"loggerz",[]);let be=we;class Me{constructor(t={}){this.name=t.name||this.constructor.name,this._logger=this.getLogger(t)}get logger(){return null==this._logger?this.getLogger():this._logger}trace(t="render"){this.logger.log(null==this.name?this.constructor.name:this.name,t,"x",this.x,"y",this.y,"w",this.width,"h",this.height,"opacity",this._opacity,"visible",this._visible,"active",this._active,"debug",this.debug)}getLogger(t){return be.getLogger(t.name||this.constructor.name)}}const ke=class t{static getInstance(){return t.instance||(t.instance=new t),t.instance}constructor(){this.createTab()}createTab(){this.tab=document.createElement("div"),Object.assign(this.tab.style,{position:"fixed",bottom:"0",left:"0",right:"0",height:"30px",backgroundColor:"#333",color:"#fff",padding:"5px",cursor:"pointer",fontFamily:"monospace",zIndex:"10000",display:"flex",justifyContent:"space-between",alignItems:"center"}),this.tab.innerText="Console";const t=document.createElement("div"),e=(t,e)=>{const i=document.createElement("button");return i.innerText=t,Object.assign(i.style,{marginLeft:"5px",padding:"2px 5px",fontFamily:"monospace",cursor:"pointer"}),i.onclick=e,i};this.paused=!1,this.scrollLock=!0,t.appendChild(e("Clear",()=>this.consoleArea.value="")),t.appendChild(e("Pause",()=>this.paused=!this.paused)),t.appendChild(e("Scroll Lock",()=>this.scrollLock=!this.scrollLock)),this.tab.appendChild(t),document.body.appendChild(this.tab),this.consoleArea=document.createElement("textarea"),Object.assign(this.consoleArea.style,{position:"fixed",bottom:"30px",left:"0",right:"0",height:"200px",display:"none",backgroundColor:"#111",color:"#0f0",fontFamily:"monospace",zIndex:"9999",padding:"10px",resize:"none"}),this.consoleArea.readOnly=!0,document.body.appendChild(this.consoleArea),this.tab.onclick=t=>{t.target===this.tab&&(this.consoleArea.style.display="none"===this.consoleArea.style.display?"block":"none")}}appendMessage(t,e,...i){if(this.paused)return;const s=`[${t.toUpperCase()}] ${e} ${i.join(" ")}\n`;this.consoleArea.value+=s,this.scrollLock&&(this.consoleArea.scrollTop=this.consoleArea.scrollHeight)}log(t,...e){this.appendMessage("log",t,...e)}warn(t,...e){this.appendMessage("warn",t,...e)}error(t,...e){this.appendMessage("error",t,...e)}table(t){const e=JSON.stringify(t,null,2);this.appendMessage("table",e)}groupCollapsed(t){this.appendMessage("group",`Group Start: ${t}`)}groupEnd(){this.appendMessage("group","Group End")}time(t){this[`time_${t}`]=performance.now()}timeEnd(t){const e=(performance.now()-this[`time_${t}`]).toFixed(2);this.appendMessage("time",`${t}: ${e} ms`)}};vt(ke,"instance");let Ce=ke;const Se=class t{static dropShadow(t,e,i=0,s=0){Be.ctx.shadowColor=t,Be.ctx.shadowBlur=e,Be.ctx.shadowOffsetX=i,Be.ctx.shadowOffsetY=s}static clearShadow(){Be.ctx.shadowColor="rgba(0, 0, 0, 0)",Be.ctx.shadowBlur=0,Be.ctx.shadowOffsetX=0,Be.ctx.shadowOffsetY=0}static setAlpha(t){Be.ctx.globalAlpha=t}static setBlendMode(t){Be.ctx.globalCompositeOperation=t}static clipRect(t,e,i,s){Be.ctx.beginPath(),Be.ctx.rect(t,e,i,s),Be.ctx.clip()}static clipCircle(t,e,i){Be.ctx.beginPath(),Be.shapes.arc(t,e,i,0,2*Math.PI),Be.ctx.clip()}static blurRegion(t,e,i,s,n){const o=Be.ctx.filter;Be.ctx.filter=`blur(${n}px)`;const r=Be.ctx.getImageData(t,e,i,s);Be.ctx.putImageData(r,t,e),Be.ctx.filter=o}static createGlow(e,i,s={}){const n="glow-"+Math.random().toString(36).substr(2,9),o={id:n,type:"glow",active:!0,time:0,color:e,blur:i,options:{pulseSpeed:0,pulseMin:.5*i,pulseMax:1.5*i,colorShift:0,...s},update(t){return Object.assign(this,t),this},stop(){return this.active=!1,t._activeEffects.delete(this.id),this},apply(){if(!this.active)return;let t=this.blur,e=this.color;if(this.options.pulseSpeed>0){const e=.5*Math.sin(this.time*this.options.pulseSpeed)+.5;t=this.options.pulseMin+e*(this.options.pulseMax-this.options.pulseMin)}return this.options.colorShift>0&&(e=e.replace("hue",this.time*this.options.colorShift%360)),Be.ctx.shadowColor=e,Be.ctx.shadowBlur=t,Be.ctx.shadowOffsetX=0,Be.ctx.shadowOffsetY=0,this.time+=1/60,this}};return t._activeEffects.set(n,o),t._startAnimationLoop(),o}static _startAnimationLoop(){if(null!==t._animationId)return;const e=()=>{if(t._activeEffects.forEach(t=>{t.active&&t.apply()}),0===t._activeEffects.size)return cancelAnimationFrame(t._animationId),void(t._animationId=null);t._animationId=requestAnimationFrame(e)};t._animationId=requestAnimationFrame(e)}static clearAllEffects(){t._activeEffects.forEach(t=>t.stop()),t._activeEffects.clear(),Be.ctx.shadowColor="rgba(0, 0, 0, 0)",Be.ctx.shadowBlur=0,Be.ctx.shadowOffsetX=0,Be.ctx.shadowOffsetY=0,Be.ctx.filter="none",Be.ctx.globalAlpha=1,Be.ctx.globalCompositeOperation="source-over"}};vt(Se,"_activeEffects",new Map),vt(Se,"_animationId",null);let Te=Se;class Re{static draw(t,e=0,i=0,{width:s,height:n,crop:o=null,anchor:r="top‑left",rotation:a=0,scaleX:h=1,scaleY:l=1,flipX:c=!1,flipY:u=!1,alpha:d=1,smoothing:f=!0}={}){const p=Be.ctx;if(!p||!t)return;const g=s??(o?o.sw:t.width??t.videoWidth),m=n??(o?o.sh:t.height??t.videoHeight),y=-g*({left:0,center:.5,right:1}[r.split("-").pop()]??0),x=-m*({top:0,center:.5,bottom:1}[r.split("-")[0]]??0);if(p.save(),p.imageSmoothingEnabled=f,p.globalAlpha*=d,p.translate(e,i),a&&p.rotate(a),(c||u)&&p.scale(c?-1:1,u?-1:1),p.scale(h,l),o){const{sx:e,sy:i,sw:s,sh:n}=o;p.drawImage(t,e,i,s,n,y,x,g,m)}else p.drawImage(t,y,x,g,m);p.restore()}static blit(t,e,i,s,n){this.draw(t,e,i,{width:s,height:n})}static createPattern(t,e="repeat"){return Be.ctx.createPattern(t,e)}static fillPattern(t,e,i,s,n){const o=Be.ctx;o.save(),o.fillStyle=t,o.fillRect(e,i,s,n),o.restore()}static createImageData(t,e){return Be.ctx.createImageData(t,e)}static cloneImageData(t){return new ImageData(new Uint8ClampedArray(t.data),t.width,t.height)}static getImageData(t,e,i,s){return Be.ctx.getImageData(t,e,i,s)}static putImageData(t,e,i,s=0,n=0,o=t.width,r=t.height){Be.ctx.putImageData(t,e,i,s,n,o,r)}static mapPixels(t,e){const i=t.data;for(let t=0;t<i.length;t+=4){const s=t>>2,n=e(i[t],i[t+1],i[t+2],i[t+3],s);n&&([i[t],i[t+1],i[t+2],i[t+3]]=n)}return t}static setPixel(t,e,i,s,n,o,r=255){const a=4*(i*t.width+e),h=t.data;h[a]=s,h[a+1]=n,h[a+2]=o,h[a+3]=r}static async toBitmap({type:t="image/png",quality:e=.92}={}){const i=Be.ctx.canvas,s=await i.convertToBlob({type:t,quality:e});return createImageBitmap(s)}static async createBitmap(t){return createImageBitmap(t)}static toImageData(t,e,i){if(t.length!==e*i*4)throw new Error("Invalid RGBA array size for given dimensions");return new ImageData(t,e,i)}static async createImageBitmapFromPixels(t,e,i){const s=this.toImageData(t,e,i);return await createImageBitmap(s)}static createPatternFromImageData(t,e="repeat"){const i=document.createElement("canvas");i.width=t.width,i.height=t.height;const s=i.getContext("2d");return s.putImageData(t,0,0),s.createPattern(i,e)}static createPatternFromPixels(t,e,i,s="repeat"){const n=this.toImageData(t,e,i);return this.createPatternFromImageData(n,s)}}class Pe{static path(t,e,i,s=1){const n=Be.ctx;n.beginPath();for(const e of t){const[t,...i]=e;"M"===t?n.moveTo(...i):"L"===t?n.lineTo(...i):"C"===t?n.bezierCurveTo(...i):"Q"===t?n.quadraticCurveTo(...i):"Z"===t&&n.closePath()}e&&(n.fillStyle=e,Be.colors.fill(e)),i&&(n.strokeStyle=i,n.lineWidth=s,Be.colors.stroke())}static line(t,e,i,s,n,o){Be.ctx.beginPath(),Be.ctx.moveTo(t,e),Be.ctx.lineTo(i,s),Be.colors.stroke(n,o)}static beginPath(){Be.ctx.beginPath()}static closePath(){Be.ctx.closePath()}static moveTo(t,e){Be.ctx.moveTo(t,e)}static lineTo(t,e){Be.ctx.lineTo(t,e)}static bezierCurveTo(t,e,i,s,n,o){Be.ctx.bezierCurveTo(t,e,i,s,n,o)}static dashedLine(t,e,i,s,n,o,r){Be.ctx.beginPath(),o&&(Be.ctx.strokeStyle=o),void 0!==r&&(Be.ctx.lineWidth=r),Be.ctx.setLineDash(n),Be.ctx.moveTo(t,e),Be.ctx.lineTo(i,s),Be.colors.stroke(),Be.ctx.setLineDash([])}static dottedLine(t,e,i,s,n=2,o=5,r){return Be.lines.dashedLine(t,e,i,s,[n,o],r,n)}static setLineDash(t){Be.ctx.setLineDash(t)}static resetLineDash(){Be.ctx.setLineDash([])}static setLineWidth(t){Be.ctx.lineWidth=t}static quadraticCurve(t,e,i,s,n,o,r,a){Be.ctx.beginPath(),Be.ctx.moveTo(t,e),Be.ctx.quadraticCurveTo(i,s,n,o),r&&(Be.ctx.strokeStyle=r),void 0!==a&&(Be.ctx.lineWidth=a),Be.colors.stroke()}}class Ae{static pushOpacity(t){const e=this._opacityStack[this._opacityStack.length-1]*t;this._opacityStack.push(e),Be.logger.log("NEXT OPACITY WILL BE",e),Be.effects.setAlpha(e)}static popOpacity(){if(this._opacityStack.length>1){this._opacityStack.pop();const t=this._opacityStack[this._opacityStack.length-1];Be.logger.log("NEXT OPACITY WILL BE",t),Be.effects.setAlpha(t)}}static _clone(){this._opacityStack=[...this._opacityStack]}static saveOpacityState(){this._opacityStateBackup=[...this._opacityStack]}static restoreOpacityState(){this._opacityStateBackup&&(this._opacityStack=this._opacityStateBackup,delete this._opacityStateBackup)}}vt(Ae,"_opacityStack",[1]);class De{static rect(t,e,i,s,n){const o=Be.ctx.fillStyle;Be.colors.fill(n),Be.ctx.fillRect(t,e,i,s),Be.ctx.fillStyle=o}static outlineRect(t,e,i,s,n,o=1){const r=Be.ctx.strokeStyle,a=Be.ctx.lineWidth;Be.ctx.strokeStyle=n,Be.ctx.lineWidth=o,Be.ctx.strokeRect(t,e,i,s),Be.ctx.strokeStyle=r,Be.ctx.lineWidth=a}static roundRect(t,e,i,s,n=0,o,r,a){let h;h="number"==typeof n?[n,n,n,n]:Array.isArray(n)?4===n.length?n:[n[0]||0,n[1]||n[0]||0,n[2]||n[0]||0,n[3]||n[1]||n[0]||0]:[0,0,0,0];const[l,c,u,d]=h,f=t+i,p=e+s;Be.lines.beginPath(),Be.lines.moveTo(t+l,e),Be.lines.lineTo(f-c,e),this.arc(f-c,e+c,c,-Math.PI/2,0),Be.lines.lineTo(f,p-u),this.arc(f-u,p-u,u,0,Math.PI/2),Be.lines.lineTo(t+d,p),this.arc(t+d,p-d,d,Math.PI/2,Math.PI),Be.lines.lineTo(t,e+l),this.arc(t+l,e+l,l,Math.PI,-Math.PI/2),Be.lines.closePath(),o&&(Be.fillStyle=o,Be.colors.fill(o)),r&&Be.colors.stroke(r,a)}static fillRoundRect(t,e,i,s,n=0,o){this.roundRect(t,e,i,s,n,o,null)}static strokeRoundRect(t,e,i,s,n=0,o,r){this.roundRect(t,e,i,s,n,null,o,r)}static fillCircle(t,e,i,s){Be.logger.log("PainterShapes.fillCircle",t,e,i,s),Be.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Be.colors.fill(s)}static arc(t,e,i,s,n,o){Be.ctx.arc(t,e,i,s,n,o)}static strokeCircle(t,e,i,s,n){Be.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Be.colors.stroke(s,n)}static fillEllipse(t,e,i,s,n=0,o){Be.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Be.fillStyle=o),Be.colors.fill(o)}static strokeEllipse(t,e,i,s,n=0,o,r){Be.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Be.strokeStyle=o),void 0!==r&&(Be.lineWidth=r),Be.colors.stroke(o,r)}static ellipse(t,e,i,s,n,o,r,a){Be.ctx.ellipse(t,e,i,s,n,o,r,a)}static polygon(t,e,i,s){if(!(t.length<2)){Be.lines.beginPath(),Be.lines.moveTo(t[0].x,t[0].y);for(let e=1;e<t.length;e++)Be.lines.lineTo(t[e].x,t[e].y);Be.lines.closePath(),e&&Be.colors.fill(e),i&&Be.colors.stroke(i,s)}}}class Ie{static font(){return Be.ctx.font}static setFont(t){Be.ctx.font=t}static setTextAlign(t){Be.ctx.textAlign=t}static setTextBaseline(t){Be.ctx.textBaseline=t}static fillText(t,e,i,s,n){s&&(Be.ctx.fillStyle=s),n&&(Be.ctx.font=n),Be.ctx.fillText(t,e,i)}static strokeText(t,e,i,s,n,o){s&&(Be.ctx.strokeStyle=s),void 0!==n&&(Be.ctx.lineWidth=n),o&&(Be.ctx.font=o),Be.ctx.strokeText(t,e,i)}static measureTextDimensions(t,e,i="start",s="alphabetic"){e&&(Be.ctx.font=e);const n=Be.ctx.measureText(t);let o=0;return"middle"===s&&(o=-1.5),{width:n.width,height:n.actualBoundingBoxAscent+n.actualBoundingBoxDescent,verticalAdjustment:o}}static measureTextWidth(t,e){return e&&(Be.ctx.font=e),Be.ctx.measureText(t).width}static outlinedText(t,e,i,s,n,o,r){r&&(Be.ctx.font=r),Be.ctx.strokeStyle=n,Be.ctx.lineWidth=o,Be.ctx.strokeText(t,e,i),Be.ctx.fillStyle=s,Be.ctx.fillText(t,e,i)}static wrappedText(t,e,i,s,n,o,r){o&&(Be.ctx.fillStyle=o),r&&(Be.ctx.font=r);const a=t.split(" ");let h="",l="",c=1;for(let t=0;t<a.length;t++)l=h+a[t]+" ",Be.ctx.measureText(l).width>s&&t>0?(Be.ctx.fillText(h,e,i),h=a[t]+" ",i+=n,c++):h=l;return Be.ctx.fillText(h,e,i),c*n}static textOnPath(t,e,i,s,n=!1){if(e.length<2)return;i&&(Be.ctx.fillStyle=i),s&&(Be.ctx.font=s);const o=t.split(""),r=o.map(t=>Be.ctx.measureText(t).width);n&&(o.reverse(),r.reverse(),e.reverse());let a=0;for(let t=1;t<e.length;t++){const i=e[t].x-e[t-1].x,s=e[t].y-e[t-1].y;a+=Math.sqrt(i*i+s*s)}let h=(a-r.reduce((t,e)=>t+e,0))/2;h<0&&(h=0);let l=h;for(let t=0;t<o.length;t++){const i=r[t],{x:s,y:n,angle:a}=getPositionOnPath(e,l);Be.ctx.save(),Be.ctx.translate(s,n),Be.ctx.rotate(a),Be.ctx.fillText(o[t],0,0),Be.ctx.restore(),l+=i}}static getPositionOnPath(t,e){let i=0;for(let s=1;s<t.length;s++){const n=t[s-1],o=t[s],r=o.x-n.x,a=o.y-n.y,h=Math.sqrt(r*r+a*a);if(i+h>=e){const t=(e-i)/h;return{x:n.x+r*t,y:n.y+a*t,angle:Math.atan2(a,r)}}i+=h}const s=t[t.length-1],n=t[t.length-2],o=Math.atan2(s.y-n.y,s.x-n.x);return{x:s.x,y:s.y,angle:o}}}const ze=class t{static get colors(){return kt(this,C,S).call(this,"colors",wt(this,x)),wt(this,x)}static get effects(){return kt(this,C,S).call(this,"effects",wt(this,v)),wt(this,v)}static get img(){return kt(this,C,S).call(this,"img",wt(this,_)),wt(this,_)}static get lines(){return kt(this,C,S).call(this,"lines",wt(this,w)),wt(this,w)}static get opacity(){return kt(this,C,S).call(this,"opacity",wt(this,b)),wt(this,b)}static get shapes(){return kt(this,C,S).call(this,"shapes",wt(this,M)),wt(this,M)}static get text(){return kt(this,C,S).call(this,"text",wt(this,k)),wt(this,k)}static set ctx(t){this._ctx=t}static get ctx(){if(!this._ctx)throw new Error("Cannot access Painter.ctx before initialization!");return this._ctx}static init(e){this._ctx=e,this.saveStack=[],Mt(this,x,Ee),Mt(this,v,Te),Mt(this,_,Re),Mt(this,w,Pe),Mt(this,b,Ae),Mt(this,M,De),Mt(this,k,Ie),t.logger=be.getLogger("Painter"),t.saveStack=[]}static setContext(t){this._ctx=t}static save(){const e=((new Error).stack.split("\n")[2]||"").match(/at\s+(\w+)\.(\w+)/),i=e?`${e[1]}.${e[2]}`:"unknown";this.saveStack.push(i),this.logger.log(`Painter.save() by: ${i}`),this.ctx.save(),t.opacity.saveOpacityState()}static restore(){if(0===this.saveStack.length)return void console.error("PAINTER ERROR: restore() without matching save()!");const e=this.saveStack.pop();this.logger.log(`Painter.restore() balancing save from: ${e}`),this.ctx.restore(),t.opacity.restoreOpacityState()}static translateTo(t,e){(isNaN(t)||void 0===t)&&(t=0),(isNaN(e)||void 0===e)&&(e=0),this.logger.log("moveTo",t,e),this.ctx.translate(t,e)}static resetPosition(){this.logger.log("resetPosition");const t=this.ctx.getTransform();this.ctx.setTransform(t.a,t.b,t.c,t.d,0,0)}static withPosition(t,e,i){this.logger.log("withPosition",t,e),this.save(),this.translateTo(t,e),i(),this.restore()}static clear(e=0,i=0,s=t.ctx.canvas.width,n=t.ctx.canvas.height){t.ctx.clearRect(e,i,s,n)}static translate(e,i){t.ctx.translate(e,i)}static rotate(e){t.logger.log("Painter.rotate",e),t.ctx.rotate(e)}static scale(e,i){t.logger.log("Painter.scale",e,i),t.ctx.scale(e,i)}static useCtx(t,e={}){const i=this.ctx,{saveState:s=!1}=e;s&&this.save(),i.beginPath(),t(i),i.beginPath(),s&&this.restore()}};x=new WeakMap,v=new WeakMap,_=new WeakMap,w=new WeakMap,b=new WeakMap,M=new WeakMap,k=new WeakMap,C=new WeakSet,S=function(t,e){if(!e)throw new Error(`Painter.${t} is not initialized. Call Painter.init(ctx) first.`)},bt(ze,C),bt(ze,x,null),bt(ze,v,null),bt(ze,_,null),bt(ze,w,null),bt(ze,b,null),bt(ze,M,null),bt(ze,k,null),vt(ze,"logger");let Be=ze;class Ee{static fill(t){Be.logger.log("PainterColors.fill - before:",Be.ctx.fillStyle,"setting to:",t),Be.ctx.fillStyle,Be.ctx.fillStyle=t,Be.ctx.fill(),Be.logger.log("PainterColors.fill - after:",Be.ctx.fillStyle)}static strokeOptions(t){t.color&&(Be.ctx.strokeStyle=t.color),void 0!==t.lineWidth&&(Be.ctx.lineWidth=t.lineWidth),t.lineCap&&(Be.ctx.lineCap=t.lineCap),t.lineJoin&&(Be.ctx.lineJoin=t.lineJoin),t.strokeStyle&&(Be.ctx.strokeStyle=t.strokeStyle)}static stroke(t,e){t&&(Be.ctx.strokeStyle=t),void 0!==e&&(Be.ctx.lineWidth=e),Be.ctx.stroke()}static setFillColor(t){Be.ctx.fillStyle=t}static setStrokeColor(t){Be.ctx.strokeStyle=t}static randomColorRGB(){const t=Math.floor(360*Math.random()),e=70+Math.floor(30*Math.random()),i=50+Math.floor(20*Math.random());return Be.colors.hslToRgb(t,e,i)}static randomColorRGBA(t=255){const[e,i,s]=this.randomColorRGB();return[e,i,s,t]}static randomColorHSL(){return`hsl(${360*Math.random()}, 100%, 50%)`}static randomColorHSL_RGBA(t=255){const e=360*Math.random(),i=60+40*Math.random(),s=40+40*Math.random(),[n,o,r]=Be.colors.hslToRgb(e,i,s);return[n,o,r,t]}static randomColorHEX(){return"#"+(1048575*Math.random()*1e6).toString(16).slice(0,6)}static parseColorString(t){if((t=t.trim().toLowerCase()).startsWith("hsl")){const e=t.replace(/hsla?\(|\)/g,""),[i,s,n]=e.split(",").map(t=>t.trim()),o=parseFloat(i),r=parseFloat(s)/100,a=parseFloat(n)/100;return Be.colors.hslToRgb(o,r,a)}if(t.startsWith("#"))return hexToRgb(t);if(t.startsWith("rgb")){const e=t.replace(/rgba?\(|\)/g,""),[i,s,n]=e.split(",").map(t=>parseInt(t.trim()));return[i,s,n]}return[0,0,0]}static rgbArrayToCSS([t,e,i]){return`rgb(${Math.round(t)}, ${Math.round(e)}, ${Math.round(i)})`}static hslToRgb(t,e,i){i/=100;const s=e=>(e+t/30)%12,n=(e/=100)*Math.min(i,1-i),o=t=>i-n*Math.max(-1,Math.min(s(t)-3,Math.min(9-s(t),1)));return[Math.round(255*o(0)),Math.round(255*o(8)),Math.round(255*o(4))]}static rgbToHsl(t,e,i){t/=255,e/=255,i/=255;const s=Math.max(t,e,i),n=Math.min(t,e,i),o=s-n;let r=0,a=0,h=(s+n)/2;if(0!==o)switch(a=o/(1-Math.abs(2*h-1)),s){case t:r=((e-i)/o+6)%6*60;break;case e:r=60*((i-t)/o+2);break;case i:r=60*((t-e)/o+4)}return[r%360,a,h]}static hexToRgb(t){const e=t.replace("#","");return[parseInt(e.substring(0,2),16),parseInt(e.substring(2,4),16),parseInt(e.substring(4,6),16)]}static linearGradient(t,e,i,s,n){const o=Be.ctx.createLinearGradient(t,e,i,s);for(const t of n)o.addColorStop(t.offset,t.color);return o}static radialGradient(t,e,i,s,n,o,r){const a=Be.ctx.createRadialGradient(t,e,i,s,n,o);for(const t of r)a.addColorStop(t.offset,t.color);return a}static verticalGradient(t,e,i,s,n){return Be.colors.linearGradient(t,e,t,e+s,n)}static horizontalGradient(t,e,i,s,n){return Be.colors.linearGradient(t,e,t+i,e,n)}static conicGradient(t,e,i,s){if("function"==typeof Be.ctx.createConicGradient){const n=Be.ctx.createConicGradient(i,t,e);for(const t of s)n.addColorStop(t.offset,t.color);return n}return null}static rgba(t,e,i,s=1){return`rgba(${Math.round(t)}, ${Math.round(e)}, ${Math.round(i)}, ${s})`}static hsl(t,e,i){return`hsl(${t}, ${e}%, ${i}%)`}static hsla(t,e,i,s){return`hsla(${t}, ${e}%, ${i}%, ${s})`}}class Fe extends Me{constructor(t={}){super(t),this._x="number"==typeof t.x?t.x:0,this._y="number"==typeof t.y?t.y:0,this._width="number"==typeof t.width?t.width:0,this._height="number"==typeof t.height?t.height:0,this.logger.log("Euclidian",this._x,this._y,this._width,this._height)}get x(){return this._x}set x(t){this.validateProp(t,"x"),this._x=t}get y(){return this._y}set y(t){this.validateProp(t,"y"),this._y=t}get width(){return this._width}set width(t){this.validateProp(t,"width"),this._width=Math.max(0,t)}get height(){return this._height}set height(t){this.validateProp(t,"height"),this._height=Math.max(0,t)}get debug(){return this._debug}set debug(t){this.validateProp(t,"debug"),this._debug=Boolean(t)}get debugColor(){return this._debugColor}set debugColor(t){this.validateProp(t,"debugColor"),this._debugColor=t}validateProp(t,e){if(null==t)throw new Error("Invalid property value: "+e+" "+t)}}class Oe extends Fe{constructor(t={}){super(t),this._minX=t.minX,this._maxX=t.maxX,this._minY=t.minY,this._maxY=t.maxY,this._boundsDirty=!0,this._cachedBounds=null,this.crisp=t.crisp??!0,this.logger.log("Geometry2d",this.x,this.y,this.width,this.height)}update(){this.trace("Geometry2d.update"),this.applyConstraints(),this.getBounds()}get minX(){return this._minX}set minX(t){this._minX=t}get maxX(){return this._maxX}set maxX(t){this._maxX=t}get minY(){return this._minY}set minY(t){this._minY=t}get maxY(){return this._maxY}set maxY(t){this._maxY=t}get boundsDirty(){return this._boundsDirty}applyConstraints(){void 0!==this._minX&&(this.x=Math.max(this.x,this._minX)),void 0!==this._maxX&&(this.x=Math.min(this.x,this._maxX)),void 0!==this._minY&&(this.y=Math.max(this.y,this._minY)),void 0!==this._maxY&&(this.y=Math.min(this.y,this._maxY)),this.crisp&&(this.x=Math.round(this.x),this.y=Math.round(this.y),this.width=Math.round(this.width),this.height=Math.round(this.height))}getBounds(){return!this._boundsDirty&&this._cachedBounds||(this._cachedBounds=this.calculateBounds(),this._boundsDirty=!1),this._cachedBounds}calculateBounds(){return{width:this.width,height:this.height,x:this.x,y:this.y}}getLocalPosition(){let t=0,e=0;return this.parent&&(t=this.parent.x,e=this.parent.y),{x:this.x-t-this.width/2,y:this.y-e-this.height/2}}markBoundsDirty(){this._boundsDirty=!0}validateProp(t,e){super.validateProp(t,e),t!==this[e]&&this.markBoundsDirty()}setTopLeft(t,e){return this.x=t+this.width/2,this.y=e+this.height/2,this}setCenter(t,e){return this.x=t,this.y=e,this}}class Xe extends Oe{constructor(t={}){super(t),this._debug=Boolean(t.debug),this._debugColor="string"==typeof t.debugColor?t.debugColor:"#0f0",this.logger.log("Traceable",this.x,this.y,this.width,this.height)}drawDebug(){if(!this._debug)return;const t=this.getDebugBounds();this.logger.log(this.constructor.name,"drawDebug",t.x,t.y,t.width,t.height),Be.shapes.outlineRect(t.x,t.y,t.width,t.height,this._debugColor,2)}getDebugBounds(){return{width:this.width,height:this.height,x:-this.width/2,y:-this.height/2}}trace(t="render"){this.logger.log(null==this.name?this.constructor.name:this.name,t,"x",this.x,"y",this.y,"w",this.width,"h",this.height,"opacity",this._opacity,"visible",this._visible,"active",this._active,"debug",this.debug)}}class Ye extends Xe{constructor(t={}){super(t),this._visible=!1!==t.visible,this._opacity="number"==typeof t.opacity?t.opacity:1,this._active=!1!==t.active,this.zIndex=t.zIndex??0,this._shadowColor=t.shadowColor??void 0,this._shadowBlur=t.shadowBlur??0,this._shadowOffsetX=t.shadowOffsetX??0,this._shadowOffsetY=t.shadowOffsetY??0,this._cacheRendering=t.cacheRendering??!1,this._cacheCanvas=null,this._cacheDirty=!0,this._cachePadding=t.cachePadding??2,this._tick=0,this.logger.log("Renderable",this.x,this.y,this.width,this.height)}render(){if(this._visible&&!(this._opacity<=0)){if(Be.save(),Be.effects.setBlendMode(this._blendMode),this.crisp?Be.translateTo(Math.round(this.x),Math.round(this.y)):Be.translateTo(this.x,this.y),this.applyShadow(Be.ctx),this._cacheRendering&&"Renderable"!==this.constructor.name){const t="number"==typeof this.width?this.width:0,e="number"==typeof this.height?this.height:0,i=2*this._cachePadding,s=Math.ceil(t+i)||1,n=Math.ceil(e+i)||1;this._cacheCanvas&&this._cacheCanvas.width===s&&this._cacheCanvas.height===n||(this._cacheCanvas=document.createElement("canvas"),this._cacheCanvas.width=s,this._cacheCanvas.height=n,this._cacheDirty=!0),this._cacheDirty&&(this._renderToCache(s,n),this._cacheDirty=!1),Be.opacity.pushOpacity(this._opacity);const o=this.rotation??0,r=this.scaleX??1,a=this.scaleY??1;Be.img.draw(this._cacheCanvas,0,0,{width:s,height:n,rotation:o,scaleX:r,scaleY:a,anchor:"center"}),Be.opacity.popOpacity()}else Be.opacity.pushOpacity(this._opacity),this.draw(),Be.opacity.popOpacity();Be.restore()}}_renderToCache(t,e){const i=this._cacheCanvas.getContext("2d");i.clearRect(0,0,t,e);const s=Be.ctx;Be.ctx=i,this._isCaching=!0,i.save(),i.translate(t/2,e/2),this.draw(),i.restore(),this._isCaching=!1,Be.ctx=s}invalidateCache(){this._cacheDirty=!0}draw(){this.drawDebug()}update(t){this.trace("Renderable.update"),this._tick+=t,super.update(t)}applyShadow(t){this._shadowColor&&(t.shadowColor=this._shadowColor,t.shadowBlur=this._shadowBlur,t.shadowOffsetX=this._shadowOffsetX,t.shadowOffsetY=this._shadowOffsetY)}get visible(){return this._visible}set visible(t){this._visible=Boolean(t)}get width(){return super.width}set width(t){super.width=t,this.invalidateCache()}get height(){return super.height}set height(t){super.height=t,this.invalidateCache()}get active(){return this._active}set active(t){this._active=Boolean(t)}get opacity(){return this._opacity}set opacity(t){this._opacity=Math.min(1,Math.max(0,"number"==typeof t?t:1))}get shadowColor(){return this._shadowColor}set shadowColor(t){this._shadowColor=t,this.invalidateCache()}get shadowBlur(){return this._shadowBlur}set shadowBlur(t){this._shadowBlur=t,this.invalidateCache()}get shadowOffsetX(){return this._shadowOffsetX}set shadowOffsetX(t){this._shadowOffsetX=t,this.invalidateCache()}get shadowOffsetY(){return this._shadowOffsetY}set shadowOffsetY(t){this._shadowOffsetY=t,this.invalidateCache()}get tick(){return this._tick}get cacheRendering(){return this._cacheRendering}set cacheRendering(t){this._cacheRendering=Boolean(t),t&&this.invalidateCache()}}const We=class t{constructor(t){this._owner=t}get owner(){return this._owner}x(t){return this._owner._x=t,this._owner.markBoundsDirty(),this}y(t){return this._owner._y=t,this._owner.markBoundsDirty(),this}position(t,e){return this._owner._x=t,this._owner._y=e,this._owner.markBoundsDirty(),this}translateBy(t,e){return this._owner._x+=t,this._owner._y+=e,this._owner.markBoundsDirty(),this}width(t){var e,i;return this._owner._width=Math.max(0,t),this._owner.markBoundsDirty(),null==(i=(e=this._owner).invalidateCache)||i.call(e),this}height(t){var e,i;return this._owner._height=Math.max(0,t),this._owner.markBoundsDirty(),null==(i=(e=this._owner).invalidateCache)||i.call(e),this}size(t,e){var i,s;return this._owner._width=Math.max(0,t),this._owner._height=Math.max(0,e),this._owner.markBoundsDirty(),null==(s=(i=this._owner).invalidateCache)||s.call(i),this}rotation(t){return this._owner._rotation=t*Math.PI/180,this._owner.markBoundsDirty(),this}rotationRad(t){return this._owner._rotation=t,this._owner.markBoundsDirty(),this}rotateBy(t){return this._owner._rotation+=t*Math.PI/180,this._owner.markBoundsDirty(),this}scaleX(t){return this._owner._scaleX=t,this._owner.markBoundsDirty(),this}scaleY(t){return this._owner._scaleY=t,this._owner.markBoundsDirty(),this}scale(t){return this._owner._scaleX=t,this._owner._scaleY=t,this._owner.markBoundsDirty(),this}scaleBy(t){return this._owner._scaleX*=t,this._owner._scaleY*=t,this._owner.markBoundsDirty(),this}set(t){var e,i;let s=!1;return void 0!==t.x&&(this._owner._x=t.x),void 0!==t.y&&(this._owner._y=t.y),void 0!==t.width&&(this._owner._width=Math.max(0,t.width),s=!0),void 0!==t.height&&(this._owner._height=Math.max(0,t.height),s=!0),void 0!==t.rotation&&(this._owner._rotation=t.rotation*Math.PI/180),void 0!==t.scaleX&&(this._owner._scaleX=t.scaleX),void 0!==t.scaleY&&(this._owner._scaleY=t.scaleY),this._owner.markBoundsDirty(),s&&(null==(i=(e=this._owner).invalidateCache)||i.call(e)),this}reset(){return this._owner._rotation=0,this._owner._scaleX=1,this._owner._scaleY=1,this._owner.markBoundsDirty(),this}resetAll(){var t,e;return this._owner._x=0,this._owner._y=0,this._owner._width=0,this._owner._height=0,this._owner._rotation=0,this._owner._scaleX=1,this._owner._scaleY=1,this._owner.markBoundsDirty(),null==(e=(t=this._owner).invalidateCache)||e.call(t),this}toObject(){return{x:this._owner._x,y:this._owner._y,width:this._owner._width,height:this._owner._height,rotation:180*this._owner._rotation/Math.PI,scaleX:this._owner._scaleX,scaleY:this._owner._scaleY}}copyFrom(e){const i=e instanceof t?e.toObject():e;return this.set(i)}static handleDirectSet(e,i){if(t.strictMode)throw new Error(`Direct property assignment "${e} = ${i}" is disabled. Use shape.transform.${e}(${i}) instead. Set Transform.strictMode = false to allow direct assignment.`);console.warn(`[Deprecation] Direct assignment "${e} = ${i}" is deprecated. Use shape.transform.${e}(${i}) instead.`)}};vt(We,"strictMode",!1);let Le=We;class He extends Ye{constructor(t={}){super(t),this._rotation=t.rotation*Math.PI/180,this._scaleX=t.scaleX??1,this._scaleY=t.scaleY??1,this.transform=new Le(this),this.logger.log("Transformable",this.x,this.y,this.width,this.height)}draw(){this.applyTransforms(),this.drawDebug()}applyTransforms(){this._isCaching||(Be.rotate(this._rotation),Be.scale(this._scaleX,this._scaleY))}get rotation(){return this._rotation}set rotation(t){this._rotation=t*Math.PI/180,this.markBoundsDirty()}get scaleX(){return this._scaleX}set scaleX(t){this._scaleX=t,this.markBoundsDirty()}get scaleY(){return this._scaleY}set scaleY(t){this._scaleY=t,this.markBoundsDirty()}calculateBounds(){const t=this.width/2,e=this.height/2,i=[{x:-t,y:-e},{x:t,y:-e},{x:t,y:e},{x:-t,y:e}],s=Math.cos(this._rotation),n=Math.sin(this._rotation),o=i.map(({x:t,y:e})=>{t*=this._scaleX,e*=this._scaleY;const i=t*n+e*s;return{x:t*s-e*n+this.x,y:i+this.y}}),r=o.map(t=>t.x),a=o.map(t=>t.y),h=Math.min(...r),l=Math.max(...r),c=Math.min(...a),u=Math.max(...a);return{x:(h+l)/2,y:(c+u)/2,width:l-h,height:u-c}}}class Ne extends He{constructor(t={}){super(t),this._color=t.color??null,this._stroke=t.stroke??null,this._lineWidth=t.lineWidth??1,this._lineJoin=t.lineJoin??"miter",this._lineCap=t.lineCap??"butt",this._miterLimit=t.miterLimit??10,this.logger.log("Shape",this.x,this.y,this.width,this.height)}get color(){return this._color}set color(t){this._color=t,this.invalidateCache()}get stroke(){return this._stroke}set stroke(t){this._stroke=t,this.invalidateCache()}get lineWidth(){return this._lineWidth}set lineWidth(t){this._lineWidth=Math.max(0,t),this.invalidateCache()}get lineJoin(){return this._lineJoin}set lineJoin(t){this._lineJoin=t,this.invalidateCache()}get lineCap(){return this._lineCap}set lineCap(t){this._lineCap=t,this.invalidateCache()}get miterLimit(){return this._miterLimit}set miterLimit(t){this._miterLimit=t,this.invalidateCache()}}class Ge extends He{constructor(t={}){super(t),this._collection=new Ct({sortByZIndex:t.sortByZIndex||!0}),this._collection._owner=this,this._childrenVersion=0,this._cachedBounds=null,t.width=Math.max(0,t.width||0),t.height=Math.max(0,t.height||0),this.userDefinedWidth=t.width,this.userDefinedHeight=t.height,this.userDefinedDimensions=void 0!==t.width&&void 0!==t.height&&(t.width>0||t.height>0)}add(t){if(null==t||null==t)throw new Error("Object is null or undefined");if(!(t instanceof He))throw new TypeError("Group can only add Transformable instances");return t.parent=this,this._collection.add(t),this._childrenVersion++,this.markBoundsDirty(),this.invalidateCache(),t}remove(t){const e=this._collection.remove(t);return e&&(t.parent=null,this._childrenVersion++,this.markBoundsDirty(),this.invalidateCache()),e}clear(){this._collection.clear(),this._childrenVersion++,this.markBoundsDirty(),this.invalidateCache()}bringToFront(t){return this._collection.bringToFront(t)}sendToBack(t){return this._collection.sendToBack(t)}bringForward(t){return this._collection.bringForward(t)}sendBackward(t){return this._collection.sendBackward(t)}draw(){super.draw(),this.logger.log("Group.draw children:",this.children.length),this._renderChildren()}_renderChildren(){const t=this._collection.getSortedChildren();for(let e=0;e<t.length;e++){const i=t[e];i.visible&&(Be.save(),i.render(),Be.restore())}}update(t){this.logger.groupCollapsed("Group.update");const e=this._collection.getSortedChildren();for(let i=0;i<e.length;i++){const s=e[i];s.active&&"function"==typeof s.update&&s.update(t)}super.update(t),this.logger.groupEnd()}get children(){var t;return(null==(t=this._collection)?void 0:t.children)||[]}get width(){return this.userDefinedDimensions?this._width:this.getBounds().width}set width(t){const e=Math.max(0,t);this._width=e,this.userDefinedWidth=e,this.userDefinedDimensions=(this.userDefinedWidth>0||this.userDefinedHeight>0)&&void 0!==this.userDefinedWidth&&void 0!==this.userDefinedHeight,this.markBoundsDirty()}get height(){return this.userDefinedDimensions?this._height:this.getBounds().height}set height(t){const e=Math.max(0,t);this._height=e,this.userDefinedHeight=e,this.userDefinedDimensions=(this.userDefinedWidth>0||this.userDefinedHeight>0)&&void 0!==this.userDefinedWidth&&void 0!==this.userDefinedHeight,this.markBoundsDirty()}calculateBounds(){var t;if(this.userDefinedDimensions)return{x:this.x,y:this.y,width:this._width,height:this._height};if(!(null==(t=this.children)?void 0:t.length))return{x:this.x,y:this.y,width:0,height:0};let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const t of this.children){const o=t.x,r=t.y,a=t.width,h=t.height,l=o-a/2,c=o+a/2,u=r-h/2,d=r+h/2;e=Math.min(e,l),s=Math.max(s,c),i=Math.min(i,u),n=Math.max(n,d)}const o=s-e,r=n-i;return{x:this.x,y:this.y,width:o,height:r}}getDebugBounds(){const t=this.calculateBounds();return{width:t.width,height:t.height,x:-t.width/2,y:-t.height/2}}forEachTransform(t){return this.children.forEach((e,i)=>{e.transform&&t(e.transform,e,i)}),this}translateChildren(t,e){return this.forEachTransform(i=>i.translateBy(t,e))}scaleChildren(t){return this.forEachTransform(e=>e.scaleBy(t))}rotateChildren(t){return this.forEachTransform(e=>e.rotateBy(t))}resetChildTransforms(){return this.forEachTransform(t=>t.reset())}}class Ue extends Ne{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Be.lines.beginPath(),Be.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle,!1),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}getBounds(){const t=this.radius;return{x:this.x,y:this.y,width:2*t,height:2*t}}}class qe extends Ne{constructor(t,e={}){super(e),this._radius=t,this.width=2*t,this.height=2*t}draw(){super.draw(),this.color&&Be.shapes.fillCircle(0,0,this._radius,this.color),this.stroke&&Be.shapes.strokeCircle(0,0,this._radius,this.stroke,this.lineWidth)}calculateBounds(){const t=2*this._radius;return this.trace("Circle.calculateBounds:"+t),{x:this.x,y:this.y,width:t,height:t}}get radius(){return this._radius}set radius(t){this.validateProp(t,"radius"),t!=this._radius&&(this._radius=t,this.width=2*t,this.height=2*t,this._boundsDirty=!0,this.calculateBounds())}}class Ze extends Ne{constructor(t=40,e={}){super(e),this.size=t,this.width=2*t,this.height=2*t}draw(){super.draw();const t=this.size,e=Be.ctx,i=[{x:.5*-t,y:0,r:.4*t},{x:.2*-t,y:.3*-t,r:.35*t},{x:.2*t,y:.35*-t,r:.4*t},{x:.5*t,y:0,r:.35*t},{x:0,y:.15*t,r:.5*t}];if(this.color){e.fillStyle=this.color;for(const t of i)e.beginPath(),e.arc(t.x,t.y,t.r,0,2*Math.PI),e.fill()}if(this.stroke){e.strokeStyle=this.stroke,e.lineWidth=this.lineWidth;for(const t of i)e.beginPath(),e.arc(t.x,t.y,t.r,0,2*Math.PI),e.stroke()}}getBounds(){const t=2*this.size;return{x:this.x,y:this.y,width:t,height:t}}}class Ve extends Ne{constructor(t={}){super(t)}draw(){super.draw(),this.drawRect()}drawRect(){const t=-this.width/2,e=-this.height/2;this.color&&Be.shapes.rect(t,e,this.width,this.height,this.color),this.stroke&&Be.shapes.outlineRect(t,e,this.width,this.height,this.stroke,this.lineWidth)}}class $e extends Ne{constructor(t=0,e={}){super(e),"number"==typeof t?this.radii=[t,t,t,t]:Array.isArray(t)?this.radii=4===t.length?t:[t[0]||0,t[1]||t[0]||0,t[2]||t[0]||0,t[3]||t[1]||t[0]||0]:this.radii=[0,0,0,0]}draw(){super.draw();const t=-this.width/2,e=-this.height/2;this.color&&this.stroke?Be.shapes.roundRect(t,e,this.width,this.height,this.radii,this.color,this.stroke,this.lineWidth):this.color?Be.shapes.fillRoundRect(t,e,this.width,this.height,this.radii,this.color):this.stroke&&Be.shapes.strokeRoundRect(t,e,this.width,this.height,this.radii,this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}}class je extends Ve{constructor(t,e={}){super(e),this.width=t,this.height=t}}class Ke extends Ne{constructor(t={}){super(t)}draw(){super.draw();const t=this.width/2,e=this.height/2,i=[{x:0,y:-e},{x:t,y:0},{x:0,y:e},{x:-t,y:0}];Be.shapes.polygon(i,this.color,this.stroke,this.lineWidth)}}class Je extends Ne{constructor(t=40,e={}){super(e),this.length=t}draw(){super.draw();const t=this.length/2;Be.lines.line(-t,-t,t,t,this.stroke,this.lineWidth)}}class Qe extends Ne{constructor(t=50,e={}){super(e),this.size=t}draw(){super.draw();const t=this.size/2,e=[{x:0,y:-t},{x:t,y:t},{x:-t,y:t}];Be.shapes.polygon(e,this.color,this.stroke,this.lineWidth)}}class ti extends Ne{constructor(t=40,e=5,i=.5,s={}){super(s),this.radius=t,this.spikes=e,this.inset=i}draw(){super.draw();const t=Math.PI/this.spikes,e=-Math.PI/2;Be.lines.beginPath();for(let i=0;i<2*this.spikes;i++){const s=i%2==0?this.radius:this.radius*this.inset,n=i*t+e,o=Math.cos(n)*s,r=Math.sin(n)*s;0===i?Be.lines.moveTo(o,r):Be.lines.lineTo(o,r)}Be.lines.closePath(),this.color&&Be.colors.fill(this.color),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}}class ei{constructor(t,e){if(this.width=t,this.height=e,this.canvas=document.createElement("canvas"),this.canvas.width=t,this.canvas.height=e,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!0,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available, falling back to Canvas 2D"),void(this.available=!1);this.available=!0;const i=this.gl;i.enable(i.BLEND),i.blendFunc(i.ONE,i.ONE_MINUS_SRC_ALPHA),i.viewport(0,0,t,e),this.programs=new Map,this.currentProgram=null,this.uniformLocations=new Map,this._needsAttributeRebind=!1,this._createQuad()}isAvailable(){return this.available}resize(t,e){this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.gl&&(this.gl.viewport(0,0,t,e),this._needsAttributeRebind=!0)}_createQuad(){const t=this.gl,e=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),i=new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1]);this.positionBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),this.uvBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.uvBuffer),t.bufferData(t.ARRAY_BUFFER,i,t.STATIC_DRAW)}_compileShader(t,e){const i=this.gl,s=i.createShader(t);return i.shaderSource(s,e),i.compileShader(s),i.getShaderParameter(s,i.COMPILE_STATUS)?s:(console.error("Shader compile error:",i.getShaderInfoLog(s)),console.error("Source:",e),i.deleteShader(s),null)}useProgram(t,e,i){if(!this.available)return null;const s=this.gl;if(this.programs.has(t)){const e=this.programs.get(t);return s.useProgram(e),this.currentProgram=t,this._needsAttributeRebind&&(this._bindAttributes(e),this._needsAttributeRebind=!1),e}const n=this._compileShader(s.VERTEX_SHADER,e),o=this._compileShader(s.FRAGMENT_SHADER,i);if(!n||!o)return null;const r=s.createProgram();return s.attachShader(r,n),s.attachShader(r,o),s.linkProgram(r),s.getProgramParameter(r,s.LINK_STATUS)?(this.programs.set(t,r),this.uniformLocations.set(t,new Map),s.useProgram(r),this.currentProgram=t,this._bindAttributes(r),r):(console.error("Program link error:",s.getProgramInfoLog(r)),s.deleteProgram(r),null)}_bindAttributes(t){const e=this.gl,i=e.getAttribLocation(t,"aPosition"),s=e.getAttribLocation(t,"aUv");-1!==i&&(e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(i),e.vertexAttribPointer(i,2,e.FLOAT,!1,0,0)),-1!==s&&(e.bindBuffer(e.ARRAY_BUFFER,this.uvBuffer),e.enableVertexAttribArray(s),e.vertexAttribPointer(s,2,e.FLOAT,!1,0,0))}_getUniformLocation(t){const e=this.gl,i=this.programs.get(this.currentProgram),s=this.uniformLocations.get(this.currentProgram);return s.has(t)||s.set(t,e.getUniformLocation(i,t)),s.get(t)}setUniforms(t){if(!this.available||!this.currentProgram)return;const e=this.gl;for(const[i,s]of Object.entries(t)){const t=this._getUniformLocation(i);if(null!==t)if("number"==typeof s)e.uniform1f(t,s);else if(Array.isArray(s))switch(s.length){case 2:e.uniform2fv(t,s);break;case 3:e.uniform3fv(t,s);break;case 4:e.uniform4fv(t,s)}else s instanceof Float32Array&&(9===s.length?e.uniformMatrix3fv(t,!1,s):16===s.length&&e.uniformMatrix4fv(t,!1,s))}}setColorUniform(t,e){if(!this.available||!this.currentProgram)return;const i=e.replace("#",""),s=parseInt(i.substring(0,2),16)/255,n=parseInt(i.substring(2,4),16)/255,o=parseInt(i.substring(4,6),16)/255,r=this._getUniformLocation(t);null!==r&&this.gl.uniform3f(r,s,n,o)}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(){if(!this.available||!this.currentProgram)return;const t=this.gl;t.drawArrays(t.TRIANGLES,0,6)}compositeOnto(t,e,i,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}getCanvas(){return this.canvas}destroy(){if(!this.available)return;const t=this.gl;for(const e of this.programs.values())t.deleteProgram(e);t.deleteBuffer(this.positionBuffer),t.deleteBuffer(this.uvBuffer),this.programs.clear(),this.uniformLocations.clear()}}const ii="\nprecision highp float;\n\nvarying vec2 vUv;\n\n// Uniforms common to all sphere shaders\nuniform float uTime;\nuniform vec2 uResolution;\nuniform vec3 uCameraRotation; // rotationX, rotationY, rotationZ\n\n// =============================================================================\n// NOISE FUNCTIONS\n// =============================================================================\n\nfloat hash(float n) {\n return fract(sin(n) * 43758.5453123);\n}\n\nfloat hash2(vec2 p) {\n return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);\n}\n\nfloat hash3(vec3 p) {\n return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453123);\n}\n\n// 3D Value noise\nfloat noise3D(vec3 x) {\n vec3 i = floor(x);\n vec3 f = fract(x);\n f = f * f * (3.0 - 2.0 * f);\n\n float n = dot(i, vec3(1.0, 57.0, 113.0));\n\n return mix(\n mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),\n mix(hash(n + 57.0), hash(n + 58.0), f.x), f.y),\n mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),\n mix(hash(n + 170.0), hash(n + 171.0), f.x), f.y), f.z\n );\n}\n\n// FBM (Fractional Brownian Motion)\nfloat fbm(vec3 p, int octaves) {\n float value = 0.0;\n float amplitude = 0.5;\n float frequency = 1.0;\n\n for (int i = 0; i < 8; i++) {\n if (i >= octaves) break;\n value += amplitude * noise3D(p * frequency);\n frequency *= 2.0;\n amplitude *= 0.5;\n }\n\n return value;\n}\n\n// =============================================================================\n// RAY-SPHERE INTERSECTION\n// =============================================================================\n\n/**\n * Ray-sphere intersection\n * @param rayOrigin - Ray origin (camera position)\n * @param rayDir - Normalized ray direction\n * @param sphereCenter - Sphere center\n * @param sphereRadius - Sphere radius\n * @return t value for intersection, -1.0 if no hit\n */\nfloat raySphereIntersect(vec3 rayOrigin, vec3 rayDir, vec3 sphereCenter, float sphereRadius) {\n vec3 oc = rayOrigin - sphereCenter;\n float a = dot(rayDir, rayDir);\n float b = 2.0 * dot(oc, rayDir);\n float c = dot(oc, oc) - sphereRadius * sphereRadius;\n float discriminant = b * b - 4.0 * a * c;\n\n if (discriminant < 0.0) {\n return -1.0;\n }\n\n return (-b - sqrt(discriminant)) / (2.0 * a);\n}\n\n// =============================================================================\n// CAMERA AND ROTATION\n// =============================================================================\n\n/**\n * Create rotation matrix from Euler angles\n */\nmat3 rotationMatrix(vec3 rotation) {\n float cx = cos(rotation.x);\n float sx = sin(rotation.x);\n float cy = cos(rotation.y);\n float sy = sin(rotation.y);\n float cz = cos(rotation.z);\n float sz = sin(rotation.z);\n\n mat3 rx = mat3(\n 1.0, 0.0, 0.0,\n 0.0, cx, -sx,\n 0.0, sx, cx\n );\n\n mat3 ry = mat3(\n cy, 0.0, sy,\n 0.0, 1.0, 0.0,\n -sy, 0.0, cy\n );\n\n mat3 rz = mat3(\n cz, -sz, 0.0,\n sz, cz, 0.0,\n 0.0, 0.0, 1.0\n );\n\n return rz * ry * rx;\n}\n\n/**\n * Calculate ray direction from UV coordinates\n * Uses a simple pinhole camera model\n */\nvec3 getRayDirection(vec2 uv) {\n // Convert UV to normalized device coordinates (-1 to 1)\n vec2 ndc = uv * 2.0 - 1.0;\n // Field of view ~53 degrees (atan(0.5) * 2)\n return normalize(vec3(ndc * 0.5, 1.0));\n}\n\n// =============================================================================\n// LIGHTING\n// =============================================================================\n\n/**\n * Simple diffuse + ambient lighting\n */\nfloat lighting(vec3 normal, vec3 lightDir, float ambient) {\n float diffuse = max(0.0, dot(normal, lightDir));\n return ambient + (1.0 - ambient) * diffuse;\n}\n\n/**\n * Fresnel effect for rim lighting\n */\nfloat fresnel(vec3 normal, vec3 viewDir, float power) {\n return pow(1.0 - abs(dot(normal, viewDir)), power);\n}\n",si={vertex:"\nprecision highp float;\n\nattribute vec2 aPosition;\nattribute vec2 aUv;\n\nvarying vec2 vUv;\n\nvoid main() {\n vUv = aUv;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n",common:ii,star:`\n${ii}\n\nuniform vec3 uStarColor;\nuniform float uTemperature; // Kelvin, affects color\nuniform float uActivityLevel; // 0-1, affects turbulence\nuniform float uRotationSpeed; // Self-rotation speed (radians/second)\n\n// Tidal disruption uniforms\nuniform float uTidalStretch; // 0 = sphere, 1+ = elongated toward BH\nuniform float uStretchDirX; // Direction to black hole (X component)\nuniform float uStretchDirZ; // Direction to black hole (Z component)\nuniform float uStressLevel; // 0-1, surface chaos from tidal forces\nuniform float uBaseRadius; // Dynamic base radius for proper sizing\nuniform float uTidalFlare; // 0-1, sudden brightness burst at disruption start\nuniform float uTidalWobble; // 0-1, violent geometry wobble during trauma\n\n// =============================================================================\n// TIDAL DISTORTION - True Spaghettification via Ellipsoid Deformation\n// Uses ray-ellipsoid intersection for physically correct stretching\n// =============================================================================\n\n/**\n * Ray-Ellipsoid intersection\n * Ellipsoid defined by semi-axes (a, b, c) where:\n * - a = stretch along BH direction (in XZ plane)\n * - b = Y axis (slight compression)\n * - c = perpendicular to BH direction in XZ plane (compression)\n *\n * Technique: Transform ray into "unit sphere space" via inverse scaling\n */\nfloat rayEllipsoidIntersect(vec3 rayOrigin, vec3 rayDir, vec3 center, vec3 semiAxes) {\n // Scale ray into unit sphere space\n vec3 scaledOrigin = (rayOrigin - center) / semiAxes;\n vec3 scaledDir = rayDir / semiAxes;\n\n // Standard ray-sphere intersection in scaled space\n float a = dot(scaledDir, scaledDir);\n float b = 2.0 * dot(scaledOrigin, scaledDir);\n float c = dot(scaledOrigin, scaledOrigin) - 1.0;\n float discriminant = b * b - 4.0 * a * c;\n\n if (discriminant < 0.0) {\n return -1.0;\n }\n\n return (-b - sqrt(discriminant)) / (2.0 * a);\n}\n\n/**\n * Calculate ellipsoid normal at hit point\n * Normal = gradient of ellipsoid equation = 2*(x/a², y/b², z/c²)\n */\nvec3 ellipsoidNormal(vec3 hitPoint, vec3 center, vec3 semiAxes) {\n vec3 localPos = hitPoint - center;\n // Gradient of (x/a)² + (y/b)² + (z/c)² = 1\n vec3 grad = localPos / (semiAxes * semiAxes);\n return normalize(grad);\n}\n\n/**\n * Build tidal stretch axes from BH direction\n * Returns semi-axes (stretchAxis, Y, perpAxis) for ellipsoid\n * Includes violent wobble effect during trauma\n */\nvec3 tidalSemiAxes(float stretch, vec2 stretchDir, float baseRadius, float wobble, float time) {\n // Stretch factor along BH direction (elongation toward/away from BH)\n float stretchFactor = 1.0 + stretch * 0.8; // Up to 1.8x longer\n\n // Compression factor perpendicular (volume roughly conserved)\n float compressFactor = 1.0 / sqrt(stretchFactor); // Compress to conserve volume\n\n // Y axis gets slight compression too\n float yFactor = 1.0 - stretch * 0.15;\n\n // === TRAUMA WOBBLE ===\n // Violent, chaotic geometry distortion during tidal shock\n if (wobble > 0.01) {\n // Multiple frequency wobbles for organic chaos\n float wobble1 = sin(time * 12.0) * cos(time * 7.3);\n float wobble2 = sin(time * 19.0 + 1.5) * cos(time * 11.0);\n float wobble3 = sin(time * 8.0 + 3.0);\n \n // Asymmetric wobble - more violent on stretch axis\n float stretchWobble = wobble * (0.3 + wobble1 * 0.2 + wobble2 * 0.15);\n float yWobble = wobble * (wobble2 * 0.25 + wobble3 * 0.15);\n float perpWobble = wobble * (wobble3 * 0.2 + wobble1 * 0.1);\n \n stretchFactor *= (1.0 + stretchWobble);\n yFactor *= (1.0 + yWobble);\n compressFactor *= (1.0 + perpWobble);\n }\n\n return vec3(\n baseRadius * stretchFactor, // Stretch along BH radial\n baseRadius * yFactor, // Slight Y compression\n baseRadius * compressFactor // Compress perpendicular\n );\n}\n\n// =============================================================================\n// PLASMA NOISE with flowing distortion\n// =============================================================================\n\nfloat plasmaNoise(vec3 p, float time) {\n float value = 0.0;\n float amplitude = 1.0;\n float frequency = 1.0;\n float totalAmp = 0.0;\n\n for (int i = 0; i < 5; i++) {\n vec3 offset = vec3(\n sin(time * 0.1 + float(i)) * 0.5,\n cos(time * 0.15 + float(i) * 0.7) * 0.5,\n time * 0.05\n );\n value += amplitude * noise3D((p + offset) * frequency);\n totalAmp += amplitude;\n amplitude *= 0.5;\n frequency *= 2.0;\n }\n\n return value / totalAmp;\n}\n\n// =============================================================================\n// HOT BUBBLES - bright spots that appear and pop\n// =============================================================================\n\nfloat hotBubbles(vec3 p, float time) {\n // Large slow bubbles\n vec3 p1 = p * 5.0 + vec3(0.0, time * 0.06, 0.0);\n float b1 = noise3D(p1);\n b1 = smoothstep(0.3, 0.6, b1);\n\n // Medium bubbles, faster\n vec3 p2 = p * 9.0 + vec3(time * 0.04, time * 0.08, 0.0);\n float b2 = noise3D(p2);\n b2 = smoothstep(0.35, 0.65, b2);\n\n // Small rapid bubbles\n vec3 p3 = p * 16.0 + vec3(time * 0.1, 0.0, time * 0.12);\n float b3 = noise3D(p3);\n b3 = smoothstep(0.4, 0.7, b3);\n\n float bubbles = b1 * 0.5 + b2 * 0.35 + b3 * 0.15;\n float pulse = sin(time * 2.0 + p.x * 10.0) * 0.3 + 0.7;\n\n return bubbles * pulse;\n}\n\n// =============================================================================\n// BOILING TURBULENCE - fast chaotic movement\n// =============================================================================\n\nfloat boilingTurbulence(vec3 p, float time) {\n float turb = 0.0;\n float amp = 1.0;\n float freq = 4.0;\n\n for (int i = 0; i < 4; i++) {\n vec3 offset = vec3(\n sin(time * 0.3 + float(i) * 1.7) * 0.5,\n cos(time * 0.25 + float(i) * 2.3) * 0.5,\n time * 0.15 * (1.0 + float(i) * 0.3)\n );\n turb += amp * abs(noise3D(p * freq + offset));\n amp *= 0.5;\n freq *= 2.1;\n }\n return turb;\n}\n\n// =============================================================================\n// CORONA FLAMES - structures around the edge\n// =============================================================================\n\nfloat coronaFlames(float angle, float rimFactor, float time, float activity) {\n // Multiple flame frequencies\n float flames = 0.0;\n\n // Large slow flames\n float f1 = sin(angle * 5.0 + time * 0.5) * 0.5 + 0.5;\n f1 *= noise3D(vec3(angle * 2.0, time * 0.3, 0.0));\n\n // Medium flames\n float f2 = sin(angle * 12.0 + time * 0.8) * 0.5 + 0.5;\n f2 *= noise3D(vec3(angle * 4.0, time * 0.5, 5.0));\n\n // Small rapid flames\n float f3 = sin(angle * 25.0 + time * 1.5) * 0.5 + 0.5;\n f3 *= noise3D(vec3(angle * 8.0, time * 0.8, 10.0));\n\n flames = f1 * 0.5 + f2 * 0.3 + f3 * 0.2;\n\n // Flames only visible at rim\n flames *= pow(rimFactor, 1.5);\n flames *= 0.5 + activity * 0.5;\n\n return flames;\n}\n\n// =============================================================================\n// SELF ROTATION - rotate normal around Y axis\n// =============================================================================\n\nvec3 rotateY(vec3 v, float angle) {\n float c = cos(angle);\n float s = sin(angle);\n return vec3(v.x * c + v.z * s, v.y, -v.x * s + v.z * c);\n}\n\nvoid main() {\n // === CIRCULAR MASK - prevents square canvas artifacts ===\n vec2 center = vUv - 0.5;\n float distFromCenter = length(center) * 2.0;\n\n // Wider cutoff for stretched ellipsoid\n if (distFromCenter > 1.6) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n float circularMask = 1.0 - smoothstep(1.3, 1.6, distFromCenter);\n\n // Setup ray - camera looking at sphere from fixed position\n vec3 rayOrigin = vec3(0.0, 0.0, -2.5);\n vec3 rayDir = getRayDirection(vUv);\n\n float time = uTime;\n float selfRotation = time * uRotationSpeed;\n\n // === TIDAL ELLIPSOID SETUP ===\n // Direction toward black hole in XZ plane\n vec2 stretchDir2D = normalize(vec2(uStretchDirX, uStretchDirZ) + 0.0001);\n float stretch = uTidalStretch;\n\n // Build rotation matrix to align ellipsoid X-axis with stretch direction\n // This rotates the ellipsoid so its long axis points toward the BH\n float stretchAngle = atan(stretchDir2D.y, stretchDir2D.x);\n float cs = cos(stretchAngle);\n float sn = sin(stretchAngle);\n\n // Rotation matrix around Y axis (to align stretch in XZ plane)\n mat3 stretchRot = mat3(\n cs, 0.0, -sn,\n 0.0, 1.0, 0.0,\n sn, 0.0, cs\n );\n mat3 stretchRotInv = mat3(\n cs, 0.0, sn,\n 0.0, 1.0, 0.0,\n -sn, 0.0, cs\n );\n\n // Transform ray into ellipsoid-aligned space\n vec3 rotatedRayDir = stretchRotInv * rayDir;\n vec3 rotatedRayOrigin = stretchRotInv * rayOrigin;\n\n // Calculate ellipsoid semi-axes based on stretch\n // Use dynamic base radius passed from JS (scales with render texture size)\n // Falls back to 0.4 if uniform not set\n float baseRadius = uBaseRadius > 0.0 ? uBaseRadius : 0.4;\n vec3 semiAxes = tidalSemiAxes(stretch, stretchDir2D, baseRadius, uTidalWobble, time);\n\n // Ray-ellipsoid intersection for SURFACE\n float t = rayEllipsoidIntersect(rotatedRayOrigin, rotatedRayDir, vec3(0.0), semiAxes);\n\n // === NO CORONA - just render solid ellipsoid ===\n // If ray doesn't hit the surface, render transparent\n if (t < 0.0) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n // === SURFACE RENDERING ===\n // Calculate hit point in rotated (ellipsoid-aligned) space\n vec3 rotatedHitPoint = rotatedRayOrigin + rotatedRayDir * t;\n\n // Calculate ellipsoid normal (gradient of implicit surface)\n vec3 rotatedNormalRaw = ellipsoidNormal(rotatedHitPoint, vec3(0.0), semiAxes);\n\n // Transform hit point and normal back to world space\n vec3 hitPoint = stretchRot * rotatedHitPoint;\n vec3 normal = normalize(stretchRot * rotatedNormalRaw);\n\n // Apply inverse camera rotation to the normal (camera orbit)\n mat3 camRotMat = rotationMatrix(-uCameraRotation);\n vec3 rotatedNormal = camRotMat * normal;\n\n // Apply self-rotation to surface features\n rotatedNormal = rotateY(rotatedNormal, selfRotation);\n\n // === SPHERICAL DISTORTION for boiling effect ===\n vec2 sp = normal.xy;\n float r = dot(sp, sp);\n\n float brightness = 0.15 + (uTemperature / 10000.0) * 0.1;\n float distortStrength = 2.0 - brightness;\n\n vec2 warpedUV;\n if (r < 0.0001) {\n // At pole - use alternative coords\n float poleAngle = atan(rotatedNormal.y, rotatedNormal.x) + time * 0.15;\n float poleElev = acos(clamp(rotatedNormal.z, -1.0, 1.0));\n warpedUV = vec2(cos(poleAngle), sin(poleAngle)) * (poleElev / 3.14159) * distortStrength;\n } else {\n sp *= distortStrength;\n r = dot(sp, sp);\n float f = (1.0 - sqrt(abs(1.0 - r))) / (r + 0.001) + brightness * 0.5;\n warpedUV = sp * f + vec2(time * 0.05, 0.0);\n }\n\n // === PLASMA TEXTURE ===\n vec3 plasmaCoord = vec3(warpedUV * 3.0, time * 0.12);\n float plasma1 = plasmaNoise(plasmaCoord, time);\n float plasma2 = plasmaNoise(plasmaCoord * 1.3 + vec3(50.0), time * 1.2);\n float plasma = plasma1 * 0.6 + plasma2 * 0.4;\n plasma = plasma * 0.5 + 0.5;\n\n // === VIEW GEOMETRY ===\n float viewAngle = dot(normal, -rayDir);\n float edgeDist = 1.0 - viewAngle;\n float limbDarkening = pow(max(0.0, viewAngle), 0.4);\n\n // === TIDAL FACE INTENSITY ===\n // The side facing the black hole experiences more violent tidal forces\n // Calculate how much this surface point faces the BH direction\n vec3 bhDir3D = normalize(vec3(uStretchDirX, 0.0, uStretchDirZ));\n float facingBH = dot(normal, bhDir3D); // -1 to 1, positive = facing BH\n float tidalFace = smoothstep(-0.2, 0.8, facingBH); // Gradual transition\n tidalFace = tidalFace * tidalFace; // More concentrated on BH side\n \n // Tidal face boost - up to 3x more violent on the BH-facing side\n float tidalFaceBoost = 1.0 + tidalFace * uStressLevel * 2.0;\n\n // === MULTI-LAYER EFFECTS (stress-enhanced) ===\n // Stress amplifies all turbulent effects - star is being torn apart!\n // Much more violent - up to 5x chaos at max stress\n float stressBoost = 1.0 + uStressLevel * 4.0;\n \n // Combined boost: general stress + extra violence on BH-facing side\n float combinedBoost = stressBoost * tidalFaceBoost;\n\n float turbIntensity = boilingTurbulence(rotatedNormal, time * combinedBoost) * 0.6;\n turbIntensity *= combinedBoost;\n\n float bubbles = hotBubbles(rotatedNormal, time * combinedBoost);\n bubbles *= combinedBoost * 1.5; // More dramatic bubbles on tidal face\n\n // Granulation becomes violent under stress - larger and faster\n float gran = noise3D(rotatedNormal * 15.0 + time * 0.5 * combinedBoost);\n gran *= combinedBoost * 1.2;\n\n // === TIDAL FRACTURING ===\n // Stress causes visible cracks/tears - concentrated on BH-facing side\n float fractures = 0.0;\n if (uStressLevel > 0.15) { // Start fractures earlier (was 0.3)\n // Fractures are more intense on the tidal face\n float fractureBoost = 1.0 + tidalFace * 2.0; // Up to 3x on BH side\n float fractureNoise = noise3D(rotatedNormal * 6.0 + time * 0.8 * fractureBoost);\n float fractureThreshold = 1.0 - (uStressLevel - 0.15) * 1.2 * fractureBoost;\n fractures = smoothstep(fractureThreshold, fractureThreshold + 0.08, fractureNoise);\n fractures *= uStressLevel * 1.2 * fractureBoost; // More intense on BH side\n }\n\n // === PULSATION (amplified by stress) ===\n float pulse1 = cos(time * 0.5) * 0.5;\n float pulse2 = sin(time * 0.25) * 0.5;\n float pulseAmp = uActivityLevel * (1.0 + uStressLevel);\n float pulse = (pulse1 + pulse2) * 0.3 * pulseAmp;\n\n // === TIDAL HOTSPOT ===\n // Bright glowing region on the BH-facing side - like matter being pulled off\n float tidalHotspot = pow(tidalFace, 3.0) * uStressLevel;\n // Add some flickering/chaos to the hotspot\n tidalHotspot *= 0.7 + 0.3 * noise3D(rotatedNormal * 8.0 + time * 2.0);\n\n // === COMBINED INTENSITY ===\n float totalIntensity = plasma * 0.35 + turbIntensity * 0.25 + gran * 0.2;\n totalIntensity += bubbles * 0.4;\n totalIntensity += fractures * 0.5; // Fractures glow hot\n totalIntensity += tidalHotspot * 0.8; // Bright tidal hotspot\n totalIntensity *= 1.0 + pulse;\n\n // === 4-TIER COLOR SYSTEM ===\n vec3 baseColor = uStarColor;\n float maxComp = max(baseColor.r, max(baseColor.g, baseColor.b));\n if (maxComp > 0.01) baseColor = baseColor / maxComp * 0.85;\n\n // Temperature-based color blending\n float tempBlend = smoothstep(5000.0, 7500.0, uTemperature);\n\n vec3 hotColor = baseColor * vec3(1.6, 1.35, 1.2);\n vec3 coolColor = mix(baseColor * vec3(0.5, 0.3, 0.2), baseColor * vec3(0.7, 0.8, 0.95), tempBlend);\n vec3 warmColor = mix(baseColor * vec3(1.2, 1.0, 0.85), baseColor * vec3(1.0, 1.05, 1.2), tempBlend);\n vec3 blazingColor = mix(baseColor * vec3(2.0, 1.6, 1.3), baseColor * vec3(1.4, 1.5, 1.8), tempBlend);\n\n // Map intensity to color\n vec3 surfaceColor;\n if (totalIntensity < 0.35) {\n surfaceColor = mix(coolColor, warmColor, totalIntensity / 0.35);\n } else if (totalIntensity < 0.65) {\n surfaceColor = mix(warmColor, hotColor, (totalIntensity - 0.35) / 0.3);\n } else if (totalIntensity < 1.0) {\n surfaceColor = mix(hotColor, blazingColor, (totalIntensity - 0.65) / 0.35);\n } else {\n surfaceColor = blazingColor * (1.0 + (totalIntensity - 1.0) * 0.8);\n }\n\n // Bubble highlights\n float bubbleHighlight = pow(bubbles, 1.5) * turbIntensity;\n surfaceColor += blazingColor * bubbleHighlight * 0.6;\n\n // === LIMB DARKENING ===\n surfaceColor *= 0.75 + limbDarkening * 0.25;\n\n // === ORGANIC RIM GLOW ===\n float rimAngle = atan(normal.y, normal.x) + selfRotation;\n float rimNoise = noise3D(vec3(rimAngle * 3.0, edgeDist * 2.0, time * 0.2));\n rimNoise = rimNoise * 0.5 + 0.5;\n\n float rimIntensity = pow(edgeDist, 2.0) * (0.4 + rimNoise * 0.6);\n vec3 rimColor = baseColor * vec3(1.3, 0.95, 0.6);\n surfaceColor += rimColor * rimIntensity * 0.6 * uActivityLevel;\n\n // === EDGE GLOW (corona bleeding into surface) ===\n float edgeGlow = pow(edgeDist, 0.5) * 0.3 * uActivityLevel;\n surfaceColor += warmColor * edgeGlow;\n\n // === CENTER BOOST ===\n float centerBoost = pow(viewAngle, 1.5) * 0.2;\n surfaceColor += baseColor * centerBoost;\n\n // === SHIMMER ===\n float shimmer = sin(turbIntensity * 10.0 + time * 3.0) * 0.05 + 1.0;\n surfaceColor *= shimmer;\n\n // === TIDAL FLARE ===\n // Sudden brightness burst when disruption begins\n // Concentrated on the BH-facing side with violent flickering\n if (uTidalFlare > 0.01) {\n // Flare is brightest on the BH-facing side\n float flareFace = 0.3 + tidalFace * 0.7;\n \n // Violent flickering during the flare\n float flareFlicker = 0.7 + 0.3 * noise3D(rotatedNormal * 10.0 + time * 8.0);\n \n // White-hot flare color\n vec3 flareColor = vec3(1.0, 0.95, 0.8);\n \n // Additive flare - makes entire star brighter\n float flareIntensity = uTidalFlare * flareFace * flareFlicker * 2.0;\n surfaceColor += flareColor * flareIntensity;\n \n // Extra bloom at the BH-facing tip\n float tipFlare = pow(tidalFace, 4.0) * uTidalFlare * 1.5;\n surfaceColor += vec3(1.0, 0.9, 0.7) * tipFlare;\n }\n\n surfaceColor = clamp(surfaceColor, 0.0, 3.5); // Allow brighter for flare\n\n gl_FragColor = vec4(surfaceColor, 1.0);\n}\n`,blackHole:`\n${ii}\n\nuniform float uAwakeningLevel; // 0 = dormant, 1 = fully active\nuniform float uFeedingPulse; // Temporary glow from feeding\nuniform float uRotation; // Black hole spin angle (Kerr rotation)\n\nvoid main() {\n vec2 uv = vUv;\n vec2 center = uv - 0.5;\n float dist = length(center) * 2.0; // 0 at center, 1 at edge\n float angle = atan(center.y, center.x);\n\n float time = uTime;\n float awakeFactor = uAwakeningLevel;\n float pulseFactor = uFeedingPulse;\n\n // Spin angle for rotating effects (frame dragging)\n // Using uTime since custom uniforms don't update properly\n float spinAngle = angle + uTime * 4.0; // Faster spin\n\n // === RADII (normalized to quad size) ===\n float eventHorizon = 0.42; // Slightly larger core\n float photonSphere = 0.54; // Tighten ring closer to horizon\n float shadowEdge = 0.5; // Shadow boundary\n\n // === CIRCULAR MASK ===\n if (dist > 1.5) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n // === NO INTERNAL STARFIELD ===\n // The real starfield is rendered separately in the scene\n // This shader just renders the dark void + subtle edge effects\n // True gravitational lensing would require render-to-texture of background\n\n // === EVENT HORIZON - Gradient from pure black to very dark edge ===\n // Edge color ~#110b06 = RGB(17,11,6) = vec3(0.067, 0.043, 0.024)\n if (dist < shadowEdge) {\n // Use shadowEdge (0.52) as outer boundary for smooth transition to ring\n float edgeT = dist / shadowEdge; // 0 at center, 1 at shadow edge\n\n // Very steep curve - stays pure black until very close to edge\n float glowFactor = pow(edgeT, 8.0);\n\n // Very dark brownish-black - NO yellow, matches #110b06\n vec3 edgeColor = vec3(0.067, 0.043, 0.024) * glowFactor;\n\n gl_FragColor = vec4(edgeColor, 1.0);\n return;\n }\n\n // === PHOTON SPHERE - Subtle ring with gentler spin asymmetry ===\n float photonRingWidth = 0.035;\n float photonDist = abs(dist - photonSphere);\n float photonRing = exp(-photonDist * photonDist / (photonRingWidth * photonRingWidth));\n\n // Softer Doppler asymmetry to avoid pointy highlights\n float doppler = 0.78 + 0.22 * cos(spinAngle); // narrower asymmetry\n photonRing *= 0.18 + doppler * 0.38; // 18%..56% brightness\n\n // Soft tip highlight to indicate spin without a spike\n float tipAlign = max(0.0, cos(spinAngle));\n float tipRadial = smoothstep(photonRingWidth * 1.2, 0.0, photonDist);\n float hotSpotGlow = tipAlign * tipAlign * tipRadial * 0.25;\n\n // Scale with awakening - more visible when feeding\n photonRing *= 0.15 + awakeFactor * 0.35;\n\n // === FEEDING PULSE - Subtle ripple when consuming ===\n float pulseRipple = 0.0;\n if (pulseFactor > 0.01) {\n float ripplePhase = fract(time * 1.5) * 0.3;\n float rippleRadius = shadowEdge + ripplePhase;\n float ripple = exp(-pow(dist - rippleRadius, 2.0) * 80.0);\n pulseRipple = ripple * pulseFactor * 0.15; // Subtle\n }\n\n // === EDGE GLOW - keep subtle; avoid wide smear\n float edgeGlow = 0.0;\n if (dist > shadowEdge && dist < photonSphere + 0.08) {\n float edgeFactor = smoothstep(shadowEdge, photonSphere, dist);\n edgeFactor *= smoothstep(photonSphere + 0.08, photonSphere, dist);\n edgeGlow = edgeFactor * pulseFactor * 0.06;\n }\n\n // === COMBINE EFFECTS ===\n vec3 color = vec3(0.0);\n\n // Photon sphere ring (warm orange-yellow)\n vec3 photonColor = vec3(1.0, 0.8, 0.45);\n color += photonColor * photonRing;\n\n // Soft tip highlight (spin indicator)\n vec3 hotSpotColor = vec3(1.0, 0.9, 0.65);\n color += hotSpotColor * hotSpotGlow;\n\n // Edge glow when feeding\n vec3 glowColor = vec3(1.0, 0.5, 0.2);\n color += glowColor * edgeGlow;\n\n // Feeding pulse ripple\n vec3 pulseColor = vec3(1.0, 0.6, 0.3);\n color += pulseColor * pulseRipple;\n\n // === OUTER FADE ===\n float outerFade = 1.0 - smoothstep(0.9, 1.25, dist);\n color *= outerFade;\n\n // === ALPHA ===\n // Event horizon and photon sphere are fully opaque to occlude background\n float alpha;\n if (dist < photonSphere) {\n alpha = 1.0;\n color = (dist < shadowEdge) ? vec3(0.0) : color; // keep core solid black\n } else {\n // Alpha based on visible content\n float contentBrightness = max(max(color.r, color.g), color.b);\n alpha = smoothstep(0.01, 0.06, contentBrightness);\n alpha = max(alpha, smoothstep(photonSphere + 0.12, shadowEdge, dist) * 0.25);\n alpha *= outerFade;\n }\n\n gl_FragColor = vec4(color, alpha);\n}\n`,rockyPlanet:`\n${ii}\n\nuniform vec3 uBaseColor;\nuniform float uHasAtmosphere; // 0-1\nuniform float uSeed;\n\nvoid main() {\n // Setup ray - camera looking at sphere from fixed position\n vec3 rayOrigin = vec3(0.0, 0.0, -2.5);\n vec3 rayDir = getRayDirection(vUv);\n\n // Ray-sphere intersection (sphere at origin with radius 0.5)\n float t = raySphereIntersect(rayOrigin, rayDir, vec3(0.0), 0.5);\n\n if (t < 0.0) {\n // Atmosphere halo\n if (uHasAtmosphere > 0.0) {\n vec2 center = vUv - 0.5;\n float dist = length(center) * 2.0;\n float atmo = smoothstep(0.6, 0.5, dist) * smoothstep(0.45, 0.52, dist);\n atmo *= uHasAtmosphere * 0.4;\n vec3 atmoColor = vec3(0.5, 0.7, 1.0) * atmo;\n // Premultiplied alpha\n gl_FragColor = vec4(atmoColor * atmo, atmo);\n } else {\n gl_FragColor = vec4(0.0);\n }\n return;\n }\n\n // Calculate hit point and normal\n vec3 hitPoint = rayOrigin + rayDir * t;\n vec3 normal = normalize(hitPoint);\n\n // Apply inverse camera rotation for surface features\n mat3 rotMat = rotationMatrix(-uCameraRotation);\n vec3 rotatedNormal = rotMat * normal;\n\n // Seeded noise for consistent terrain\n vec3 noiseCoord = rotatedNormal * 4.0 + uSeed * 100.0;\n float terrain = fbm(noiseCoord, 5);\n\n // Height-based coloring\n vec3 lowColor = uBaseColor * 0.6; // Valleys/lowlands\n vec3 highColor = uBaseColor * 1.2; // Mountains/highlands\n vec3 surfaceColor = mix(lowColor, highColor, terrain);\n\n // Add some variation\n float variation = noise3D(rotatedNormal * 10.0 + uSeed * 50.0);\n surfaceColor *= 0.9 + variation * 0.2;\n\n // Lighting\n vec3 lightDir = normalize(vec3(1.0, 1.0, 0.5));\n float light = lighting(normal, lightDir, 0.3);\n surfaceColor *= light;\n\n // Atmosphere scattering at edges\n if (uHasAtmosphere > 0.0) {\n float rim = fresnel(normal, -rayDir, 3.0);\n vec3 atmoColor = vec3(0.5, 0.7, 1.0);\n surfaceColor = mix(surfaceColor, atmoColor, rim * uHasAtmosphere * 0.4);\n }\n\n gl_FragColor = vec4(surfaceColor, 1.0);\n}\n`,gasGiant:`\n${ii}\n\nuniform vec3 uBaseColor;\nuniform float uSeed;\nuniform float uStormIntensity; // 0-1\nuniform float uRotationSpeed; // rotation speed multiplier (default ~0.1)\n\nvoid main() {\n // Setup ray - camera looking at sphere from fixed position\n vec3 rayOrigin = vec3(0.0, 0.0, -2.5);\n vec3 rayDir = getRayDirection(vUv);\n\n // Ray-sphere intersection (sphere at origin with radius 0.5)\n float t = raySphereIntersect(rayOrigin, rayDir, vec3(0.0), 0.5);\n\n if (t < 0.0) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n // Calculate hit point and normal\n vec3 hitPoint = rayOrigin + rayDir * t;\n vec3 normal = normalize(hitPoint);\n\n // Apply inverse camera rotation for surface features\n mat3 rotMat = rotationMatrix(-uCameraRotation);\n vec3 rotatedNormal = rotMat * normal;\n\n // Convert to spherical coordinates for banding (use rotated normal)\n float latitude = asin(rotatedNormal.y); // -PI/2 to PI/2\n float longitude = atan(rotatedNormal.z, rotatedNormal.x); // -PI to PI\n\n // Animated rotation (use uRotationSpeed, default to 0.1 if not set)\n float rotSpeed = uRotationSpeed > 0.0 ? uRotationSpeed : 0.1;\n float time = uTime * rotSpeed;\n\n // Create bands based on latitude\n float bands = sin(latitude * 15.0 + time) * 0.5 + 0.5;\n bands += sin(latitude * 25.0 - time * 0.5) * 0.25;\n bands += sin(latitude * 40.0 + time * 0.3) * 0.125;\n\n // Turbulent distortion of bands\n vec3 noiseCoord = vec3(longitude + time * 0.2, latitude * 3.0, uSeed);\n float turb = fbm(noiseCoord * 5.0, 4) * 0.3;\n bands += turb;\n\n // Color variation based on bands\n vec3 lightBand = uBaseColor * 1.3;\n vec3 darkBand = uBaseColor * 0.7;\n vec3 surfaceColor = mix(darkBand, lightBand, bands);\n\n // Add storm features\n if (uStormIntensity > 0.0) {\n // Great red spot style storm\n float stormLat = 0.3; // Storm latitude\n float stormLon = time * 0.5; // Storm drifts\n vec2 stormCenter = vec2(stormLon, stormLat);\n vec2 pos = vec2(longitude, latitude);\n float stormDist = length(pos - stormCenter);\n float storm = smoothstep(0.5, 0.2, stormDist);\n storm *= uStormIntensity;\n\n // Storm color and swirl\n vec3 stormColor = vec3(0.8, 0.3, 0.2);\n float swirl = sin(stormDist * 20.0 - time * 3.0) * 0.5 + 0.5;\n surfaceColor = mix(surfaceColor, stormColor * swirl, storm);\n }\n\n // Lighting with some subsurface scattering effect\n vec3 lightDir = normalize(vec3(1.0, 0.5, 0.3));\n float light = lighting(normal, lightDir, 0.4);\n surfaceColor *= light;\n\n // Limb darkening\n float viewAngle = dot(normal, -rayDir);\n surfaceColor *= 0.7 + max(0.0, viewAngle) * 0.3;\n\n gl_FragColor = vec4(surfaceColor, 1.0);\n}\n`},ni=class t extends Ne{static _getGLRenderer(e,i){return t._glRenderer?t._glRendererSize.width===e&&t._glRendererSize.height===i||(t._glRenderer.resize(e,i),t._glRendererSize={width:e,height:i}):(t._glRenderer=new ei(e,i),t._glRendererSize={width:e,height:i}),t._glRenderer}constructor(t,e={}){super(e),this.radius=t,this.camera=e.camera??null,this.debug=e.debug??!1,this.segments=e.segments??20,this.useShader=e.useShader??!1,this.shaderType=e.shaderType??"star",this.shaderUniforms=e.shaderUniforms??{},this._shaderInitialized=!1,this.selfRotationX=e.selfRotationX??0,this.selfRotationY=e.selfRotationY??0,this.selfRotationZ=e.selfRotationZ??0,this._generateGeometry()}setCamera(t){return this.camera=t,this}setShaderUniforms(t){return Object.assign(this.shaderUniforms,t),this}_getFragmentShader(){switch(this.shaderType){case"star":default:return si.star;case"blackHole":return si.blackHole;case"rockyPlanet":return si.rockyPlanet;case"gasGiant":return si.gasGiant}}_initShader(e,i){const s=t._getGLRenderer(e,i);if(!s||!s.isAvailable())return void(this.useShader=!1);const n=`sphere_${this.shaderType}`;s.useProgram(n,si.vertex,this._getFragmentShader()),this._shaderInitialized=!0}_renderWithShader(e,i,s,n){var o,r,a,h;const l=n*(1+((null==(o=this.shaderUniforms)?void 0:o.uTidalStretch)??0)),c=Math.ceil(2*(n+l)),u=t._getGLRenderer(c,c);if(!u||!u.isAvailable())return!1;this._shaderInitialized||this._initShader(c,c);const d=`sphere_${this.shaderType}`;u.useProgram(d,si.vertex,this._getFragmentShader()),u.clear(0,0,0,0);const f=1.25*n/(c/2);u.setUniforms({uTime:performance.now()/1e3,uResolution:[c,c],uBaseRadius:f,uCameraRotation:[(null==(r=this.camera)?void 0:r.rotationX)??0,(null==(a=this.camera)?void 0:a.rotationY)??0,(null==(h=this.camera)?void 0:h.rotationZ)??0]}),u.setUniforms(this.shaderUniforms);for(const[t,e]of Object.entries(this.shaderUniforms))"string"==typeof e&&e.startsWith("#")&&u.setColorUniform(t,e);u.render();const p=i-c/2,g=s-c/2;return u.compositeOnto(e,p,g,c,c),!0}_generateGeometry(){this.vertices=[],this.faces=[];const t=this.segments,e=2*this.segments;for(let i=0;i<=t;i++){const s=i*Math.PI/t,n=Math.sin(s),o=Math.cos(s);for(let t=0;t<=e;t++){const i=2*t*Math.PI/e,s=Math.sin(i),r=Math.cos(i),a=this.radius*n*r,h=this.radius*o,l=this.radius*n*s;this.vertices.push({x:a,y:h,z:l,nx:n*r,ny:o,nz:n*s})}}for(let i=0;i<t;i++)for(let t=0;t<e;t++){const s=i*(e+1)+t,n=s+e+1;this.faces.push([s,n,s+1]),this.faces.push([n,n+1,s+1])}}_applySelfRotation(t,e,i){if(0!==this.selfRotationY){const e=Math.cos(this.selfRotationY),s=Math.sin(this.selfRotationY),n=t*s+i*e;t=t*e-i*s,i=n}if(0!==this.selfRotationX){const t=Math.cos(this.selfRotationX),s=Math.sin(this.selfRotationX),n=e*s+i*t;e=e*t-i*s,i=n}if(0!==this.selfRotationZ){const i=Math.cos(this.selfRotationZ),s=Math.sin(this.selfRotationZ),n=t*s+e*i;t=t*i-e*s,e=n}return{x:t,y:e,z:i}}_calculateLighting(t,e,i){const s=Math.sqrt(.99);let n=t*(.5/s)+e*(.7/s)+i*(.5/s);return n=.7*Math.max(0,n)+.3,n}_applyLighting(t,e){if(!t||"string"!=typeof t||!t.startsWith("#"))return t;const i=t.replace("#",""),s=parseInt(i.substring(0,2),16),n=parseInt(i.substring(2,4),16),o=parseInt(i.substring(4,6),16);return`rgb(${Math.round(s*e)}, ${Math.round(n*e)}, ${Math.round(o*e)})`}draw(){if(super.draw(),!this.camera)return this.color&&Be.shapes.fillCircle(0,0,this.radius,this.color),void(this.debug&&this.stroke&&Be.shapes.strokeCircle(0,0,this.radius,this.stroke,this.lineWidth));if(this.useShader&&!this.debug){const t=this.camera.project(this.x||0,this.y||0,this.z||0),e=this.camera.perspective/(this.camera.perspective+t.z),i=this.radius*e,s=Be.ctx,n=s.getTransform(),o=n.e,r=n.f;s.save(),s.setTransform(1,0,0,1,0,0);const a=this._renderWithShader(s,o+t.x,r+t.y,i);if(s.restore(),a)return}const t=0!==this.selfRotationX||0!==this.selfRotationY||0!==this.selfRotationZ,e=this.vertices.map(e=>{let i=e.x,s=e.y,n=e.z,o=e.nx,r=e.ny,a=e.nz;if(t){const t=this._applySelfRotation(i,s,n);i=t.x,s=t.y,n=t.z;const e=this._applySelfRotation(o,r,a);o=e.x,r=e.y,a=e.z}const h=this.camera.project(i+(this.x||0),s+(this.y||0),n+(this.z||0));if(0!==this.camera.rotationZ){const t=Math.cos(this.camera.rotationZ),e=Math.sin(this.camera.rotationZ),i=o;o=i*t-r*e,r=i*e+r*t}const l=Math.cos(this.camera.rotationY),c=Math.sin(this.camera.rotationY),u=o*l-a*c,d=o*c+a*l,f=Math.cos(this.camera.rotationX),p=Math.sin(this.camera.rotationX);return{...h,nx:u,ny:r*f-d*p,nz:r*p+d*f}});this.debug&&this.trace("Sphere3D.draw: projected vertices",e.length);const i=[];for(const t of this.faces){const s=e[t[0]],n=e[t[1]],o=e[t[2]];if(s.z<10-this.camera.perspective||n.z<10-this.camera.perspective||o.z<10-this.camera.perspective)continue;const r=(s.z+n.z+o.z)/3,a=(s.nx+n.nx+o.nx)/3,h=(s.ny+n.ny+o.ny)/3,l=(s.nz+n.nz+o.nz)/3;if(l>.1)continue;const c=this._calculateLighting(a,h,l);i.push({vertices:[s,n,o],avgZ:r,intensity:c})}i.sort((t,e)=>e.avgZ-t.avgZ);for(const t of i){const e=t.vertices.map(t=>({x:t.x,y:t.y}));if(this.debug)Be.ctx.beginPath(),Be.ctx.moveTo(e[0].x,e[0].y),Be.ctx.lineTo(e[1].x,e[1].y),Be.ctx.lineTo(e[2].x,e[2].y),Be.ctx.closePath(),this.stroke&&(Be.ctx.strokeStyle=this.stroke,Be.ctx.lineWidth=this.lineWidth??1,Be.ctx.stroke());else if(this.color){const i=this._applyLighting(this.color,t.intensity);Be.ctx.beginPath(),Be.ctx.moveTo(e[0].x,e[0].y),Be.ctx.lineTo(e[1].x,e[1].y),Be.ctx.lineTo(e[2].x,e[2].y),Be.ctx.closePath(),Be.ctx.fillStyle=i,Be.ctx.fill()}}}calculateBounds(){const t=2*this.radius;return{x:this.x,y:this.y,width:t,height:t}}};vt(ni,"_glRenderer",null),vt(ni,"_glRendererSize",{width:0,height:0});let oi=ni;const ri="\nprecision highp float;\n\nvarying vec2 vUv;\n\nuniform float uTime;\nuniform vec2 uResolution;\n\n// =============================================================================\n// NOISE FUNCTIONS\n// =============================================================================\n\nfloat hash(float n) {\n return fract(sin(n) * 43758.5453123);\n}\n\nfloat hash2(vec2 p) {\n return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);\n}\n\n// 2D Value noise\nfloat noise2D(vec2 x) {\n vec2 i = floor(x);\n vec2 f = fract(x);\n f = f * f * (3.0 - 2.0 * f);\n\n float a = hash2(i);\n float b = hash2(i + vec2(1.0, 0.0));\n float c = hash2(i + vec2(0.0, 1.0));\n float d = hash2(i + vec2(1.0, 1.0));\n\n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\n\n// FBM (Fractional Brownian Motion)\nfloat fbm2D(vec2 p, int octaves) {\n float value = 0.0;\n float amplitude = 0.5;\n float frequency = 1.0;\n\n for (int i = 0; i < 8; i++) {\n if (i >= octaves) break;\n value += amplitude * noise2D(p * frequency);\n frequency *= 2.0;\n amplitude *= 0.5;\n }\n\n return value;\n}\n",ai={vertex:"\nprecision highp float;\n\nattribute vec2 aPosition;\nattribute vec2 aUv;\n\nvarying vec2 vUv;\n\nvoid main() {\n vUv = aUv;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n",gradient:`\n${ri}\n\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uAngle;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Calculate gradient direction from angle\n vec2 dir = vec2(cos(uAngle), sin(uAngle));\n\n // Project UV onto gradient direction\n // Center at 0.5 so gradient goes through middle\n float t = dot(uv - 0.5, dir) + 0.5;\n t = clamp(t, 0.0, 1.0);\n\n // Interpolate colors\n vec3 color = mix(uColor1, uColor2, t);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`,grid:`\n${ri}\n\nuniform vec3 uLineColor;\nuniform vec3 uBackgroundColor;\nuniform float uGridSize;\nuniform float uLineWidth;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Scale UV to grid space\n vec2 grid = fract(uv * uGridSize);\n\n // Calculate distance to nearest grid line\n float lineX = min(grid.x, 1.0 - grid.x);\n float lineY = min(grid.y, 1.0 - grid.y);\n\n // Smoothstep for anti-aliased lines\n float halfWidth = uLineWidth * 0.5;\n float edgeSmooth = 0.01;\n\n float lineAlphaX = 1.0 - smoothstep(halfWidth - edgeSmooth, halfWidth + edgeSmooth, lineX);\n float lineAlphaY = 1.0 - smoothstep(halfWidth - edgeSmooth, halfWidth + edgeSmooth, lineY);\n float lineAlpha = max(lineAlphaX, lineAlphaY);\n\n // Mix colors\n vec3 color = mix(uBackgroundColor, uLineColor, lineAlpha);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`,checkerboard:`\n${ri}\n\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uSize;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Calculate which square we're in\n vec2 cell = floor(uv * uSize);\n\n // Alternating pattern based on cell coordinates\n float checker = mod(cell.x + cell.y, 2.0);\n\n // Select color\n vec3 color = mix(uColor1, uColor2, checker);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`,noise:`\n${ri}\n\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uNoiseScale;\nuniform float uAnimSpeed;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Animated noise\n float n = fbm2D(uv * uNoiseScale + uTime * uAnimSpeed, 4);\n\n // Map noise to colors\n vec3 color = mix(uColor1, uColor2, n);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`},hi=class t extends Ne{static _getGLRenderer(e,i){return t._glRenderer?t._glRendererSize.width===e&&t._glRendererSize.height===i||(t._glRenderer.resize(e,i),t._glRendererSize={width:e,height:i}):(t._glRenderer=new ei(e,i),t._glRendererSize={width:e,height:i}),t._glRenderer}constructor(t,e,i={}){super(i),this.planeWidth=t,this.planeHeight=e,this.x=i.x??0,this.y=i.y??0,this.z=i.z??0,this.camera=i.camera??null,this.debug=i.debug??!1,this.doubleSided=i.doubleSided??!0,this.texture=i.texture??null,this.selfRotationX=i.selfRotationX??0,this.selfRotationY=i.selfRotationY??0,this.selfRotationZ=i.selfRotationZ??0,this.useShader=i.useShader??!1,this.shaderType=i.shaderType??"gradient",this.shaderUniforms=i.shaderUniforms??{},this._shaderInitialized=!1,this._generateGeometry()}setCamera(t){return this.camera=t,this}setTexture(t){return this.texture=t,this}setShaderUniforms(t){return Object.assign(this.shaderUniforms,t),this}_generateGeometry(){const t=this.planeWidth/2,e=this.planeHeight/2;this.vertices=[{x:-t,y:-e,z:0,nx:0,ny:0,nz:-1,u:0,v:0},{x:t,y:-e,z:0,nx:0,ny:0,nz:-1,u:1,v:0},{x:t,y:e,z:0,nx:0,ny:0,nz:-1,u:1,v:1},{x:-t,y:e,z:0,nx:0,ny:0,nz:-1,u:0,v:1}],this.faces=[[0,1,2],[0,2,3]]}_getFragmentShader(){switch(this.shaderType){case"gradient":default:return ai.gradient;case"grid":return ai.grid;case"checkerboard":return ai.checkerboard;case"noise":return ai.noise}}_initShader(e,i){const s=t._getGLRenderer(e,i);if(!s||!s.isAvailable())return!1;const n=`plane_${this.shaderType}`,o=ai.vertex,r=this._getFragmentShader();try{return s.useProgram(n,o,r),this._shaderInitialized=!0,!0}catch(t){return console.warn("Plane3D shader init failed:",t),!1}}_renderWithShader(e,i,s,n,o){const r=Math.max(Math.ceil(Math.max(n,o)),16);if(!this._shaderInitialized&&!this._initShader(r,r))return!1;const a=t._getGLRenderer(r,r);if(!a||!a.isAvailable())return!1;const h=`plane_${this.shaderType}`;a.useProgram(h,ai.vertex,this._getFragmentShader());const l=performance.now()/1e3;a.setUniforms({uTime:l,uResolution:[r,r]}),a.setUniforms(this.shaderUniforms),a.render();const c=i-n/2,u=s-o/2;return a.compositeOnto(e,c,u,n,o),!0}_applySelfRotation(t,e,i){if(0!==this.selfRotationY){const e=Math.cos(this.selfRotationY),s=Math.sin(this.selfRotationY),n=t*s+i*e;t=t*e-i*s,i=n}if(0!==this.selfRotationX){const t=Math.cos(this.selfRotationX),s=Math.sin(this.selfRotationX),n=e*s+i*t;e=e*t-i*s,i=n}if(0!==this.selfRotationZ){const i=Math.cos(this.selfRotationZ),s=Math.sin(this.selfRotationZ),n=t*s+e*i;t=t*i-e*s,e=n}return{x:t,y:e,z:i}}_calculateLighting(t,e,i){const s=Math.sqrt(.99);let n=t*(.5/s)+e*(.7/s)+i*(.5/s);return n=.7*Math.max(0,n)+.3,n}_applyLighting(t,e){if(!t||"string"!=typeof t||!t.startsWith("#"))return t;const i=t.replace("#",""),s=parseInt(i.substring(0,2),16),n=parseInt(i.substring(2,4),16),o=parseInt(i.substring(4,6),16);return`rgb(${Math.round(s*e)}, ${Math.round(n*e)}, ${Math.round(o*e)})`}draw(){if(super.draw(),!this.camera)return void(this.color&&Be.shapes.fillRect(-this.planeWidth/2,-this.planeHeight/2,this.planeWidth,this.planeHeight,this.color));const t=0!==this.selfRotationX||0!==this.selfRotationY||0!==this.selfRotationZ,e=this.vertices.map(e=>{let i=e.x,s=e.y,n=e.z,o=e.nx,r=e.ny,a=e.nz;if(t){const t=this._applySelfRotation(i,s,n);i=t.x,s=t.y,n=t.z;const e=this._applySelfRotation(o,r,a);o=e.x,r=e.y,a=e.z}const h=this.camera.project(i+this.x,s+this.y,n+this.z);if(0!==this.camera.rotationZ){const t=Math.cos(this.camera.rotationZ),e=Math.sin(this.camera.rotationZ),i=o;o=i*t-r*e,r=i*e+r*t}const l=Math.cos(this.camera.rotationY),c=Math.sin(this.camera.rotationY),u=o*l-a*c,d=o*c+a*l,f=Math.cos(this.camera.rotationX),p=Math.sin(this.camera.rotationX);return{...h,nx:u,ny:r*f-d*p,nz:r*p+d*f,u:e.u,v:e.v}}),i=(e[0].nz+e[1].nz+e[2].nz+e[3].nz)/4;if(!this.doubleSided&&i>.1)return;if(e[0].z,e[1].z,e[2].z,e[3].z,e.some(t=>t.z<10-this.camera.perspective))return;if(this.useShader&&!this.debug){const t=e.map(t=>t.x),i=e.map(t=>t.y),s=Math.min(...t),n=Math.max(...t),o=Math.min(...i),r=Math.max(...i),a=n-s,h=r-o,l=(s+n)/2,c=(o+r)/2,u=Be.ctx,d=u.getTransform(),f=d.e,p=d.f;u.save(),u.setTransform(1,0,0,1,0,0);const g=this._renderWithShader(u,f+l,p+c,a,h);if(u.restore(),g)return}const s=Be.ctx;let n=(e[0].nx+e[1].nx+e[2].nx+e[3].nx)/4,o=(e[0].ny+e[1].ny+e[2].ny+e[3].ny)/4,r=n,a=o,h=i;this.doubleSided&&i>0&&(r=-n,a=-o,h=-i);const l=this._calculateLighting(r,a,h);for(const t of this.faces){const i=e[t[0]],n=e[t[1]],o=e[t[2]];if(this.debug)s.beginPath(),s.moveTo(i.x,i.y),s.lineTo(n.x,n.y),s.lineTo(o.x,o.y),s.closePath(),this.stroke&&(s.strokeStyle=this.stroke,s.lineWidth=this.lineWidth??1,s.stroke());else if(this.texture)this._renderTexturedTriangle(s,i,n,o);else if(this.color){const t=this._applyLighting(this.color,l);s.beginPath(),s.moveTo(i.x,i.y),s.lineTo(n.x,n.y),s.lineTo(o.x,o.y),s.closePath(),s.fillStyle=t,s.fill()}}}_renderTexturedTriangle(t,e,i,s){if(!this.texture||!this.texture.complete)return;const n=this.texture,o=n.width,r=n.height,a=e.u*o,h=e.v*r,l=i.u*o,c=i.v*r,u=s.u*o,d=s.v*r,f=e.x,p=e.y,g=i.x,m=i.y,y=s.x,x=s.y,v=(l-a)*(d-h)-(u-a)*(c-h);if(Math.abs(v)<1e-4)return;const _=((g-f)*(d-h)-(y-f)*(c-h))/v,w=((y-f)*(l-a)-(g-f)*(u-a))/v,b=f-_*a-w*h,M=((m-p)*(d-h)-(x-p)*(c-h))/v,k=((x-p)*(l-a)-(m-p)*(u-a))/v,C=p-M*a-k*h;t.save(),t.beginPath(),t.moveTo(f,p),t.lineTo(g,m),t.lineTo(y,x),t.closePath(),t.clip(),t.setTransform(_,M,w,k,b,C),t.drawImage(n,0,0),t.restore()}getCenter(){return{x:this.x,y:this.y,z:this.z}}getBounds(){return{x:this.x-this.planeWidth/2,y:this.y-this.planeHeight/2,width:this.planeWidth,height:this.planeHeight}}};vt(hi,"_glRenderer",null),vt(hi,"_glRendererSize",{width:0,height:0});let li=hi;class ci extends Ne{constructor(t,e={}){console.log("SVGShape",e.x),super(e),this.scale=e.scale||1,this.centerPath=void 0===e.centerPath||e.centerPath,this.animationProgress=void 0!==e.animationProgress?e.animationProgress:1,this.svgPathData=t,this.pathCommands=this.parseSVGPath(t),this.centerPath?this.pathCommands=this.centerAndScalePath(this.pathCommands,this.scale):this.pathCommands=this.scalePath(this.pathCommands,this.scale),this.prevX=0,this.prevY=0,this.currentPoint={x:0,y:0}}parseSVGPath(t){const e=/M\s*([-\d.]+)[,\s]*([-\d.]+)/g,i=/L\s*([-\d.]+)[,\s]*([-\d.]+)/g,s=/C\s*([-\d.]+)[,\s]*([-\d.]+)\s*([-\d.]+)[,\s]*([-\d.]+)\s*([-\d.]+)[,\s]*([-\d.]+)/g,n=[];let o;for(;null!==(o=e.exec(t));)n.push(["M",parseFloat(o[1]),parseFloat(o[2])]);for(;null!==(o=i.exec(t));){const t=parseFloat(o[1]),e=parseFloat(o[2]);let i=0,s=0;for(let t=n.length-1;t>=0;t--){const e=n[t];if("M"===e[0]){i=e[1],s=e[2];break}if("C"===e[0]){i=e[5],s=e[6];break}}const r=i+(t-i)/3,a=s+(e-s)/3,h=i+2*(t-i)/3,l=s+2*(e-s)/3;n.push(["C",r,a,h,l,t,e])}for(;null!==(o=s.exec(t));)n.push(["C",parseFloat(o[1]),parseFloat(o[2]),parseFloat(o[3]),parseFloat(o[4]),parseFloat(o[5]),parseFloat(o[6])]);return/Z/g.test(t)&&n.push(["Z"]),n}centerAndScalePath(t,e){let i=1/0,s=1/0,n=-1/0,o=-1/0;for(const e of t)"M"===e[0]?(i=Math.min(i,e[1]),s=Math.min(s,e[2]),n=Math.max(n,e[1]),o=Math.max(o,e[2])):"C"===e[0]&&(i=Math.min(i,e[1],e[3],e[5]),s=Math.min(s,e[2],e[4],e[6]),n=Math.max(n,e[1],e[3],e[5]),o=Math.max(o,e[2],e[4],e[6]));const r=(i+n)/2,a=(s+o)/2;return this.originalWidth=(n-i)*e,this.originalHeight=(o-s)*e,t.map(t=>"M"===t[0]?["M",(t[1]-r)*e,(t[2]-a)*e]:"C"===t[0]?["C",(t[1]-r)*e,(t[2]-a)*e,(t[3]-r)*e,(t[4]-a)*e,(t[5]-r)*e,(t[6]-a)*e]:[...t])}scalePath(t,e){let i=1/0,s=1/0,n=-1/0,o=-1/0;for(const e of t)"M"===e[0]?(i=Math.min(i,e[1]),s=Math.min(s,e[2]),n=Math.max(n,e[1]),o=Math.max(o,e[2])):"C"===e[0]&&(i=Math.min(i,e[1],e[3],e[5]),s=Math.min(s,e[2],e[4],e[6]),n=Math.max(n,e[1],e[3],e[5]),o=Math.max(o,e[2],e[4],e[6]));return this.originalWidth=(n-i)*e,this.originalHeight=(o-s)*e,t.map(t=>"M"===t[0]?["M",t[1]*e,t[2]*e]:"C"===t[0]?["C",t[1]*e,t[2]*e,t[3]*e,t[4]*e,t[5]*e,t[6]*e]:[...t])}getBezierPoint(t,e){if("M"===t[0])return{x:t[1],y:t[2]};if("C"===t[0]){const i=this.prevX,s=this.prevY,n=t[1],o=t[2],r=t[3],a=t[4],h=t[5],l=t[6];return{x:Math.pow(1-e,3)*i+3*Math.pow(1-e,2)*e*n+3*(1-e)*Math.pow(e,2)*r+Math.pow(e,3)*h,y:Math.pow(1-e,3)*s+3*Math.pow(1-e,2)*e*o+3*(1-e)*Math.pow(e,2)*a+Math.pow(e,3)*l}}return{x:0,y:0}}getPartialPath(){const t=[];let e=this.pathCommands.length,i=Math.floor(this.animationProgress*e),s=this.animationProgress*e%1,n=!1;this.prevX=0,this.prevY=0;for(let e=0;e<i;e++){const i=this.pathCommands[e];t.push([...i]),"M"===i[0]?(this.prevX=i[1],this.prevY=i[2],n=!0):"C"===i[0]&&(this.prevX=i[5],this.prevY=i[6],n=!0)}if(i<e){const e=this.pathCommands[i];if("M"===e[0])t.push([...e]),this.prevX=e[1],this.prevY=e[2],this.currentPoint={x:e[1],y:e[2]},n=!0;else if("C"===e[0]){if(!n){for(let t=i-1;t>=0;t--)if("M"===this.pathCommands[t][0]){this.prevX=this.pathCommands[t][1],this.prevY=this.pathCommands[t][2],n=!0;break}n||(this.prevX=0,this.prevY=0)}const o=this.getBezierPoint(e,s);t.push(["C",e[1],e[2],e[3],e[4],o.x,o.y]),this.currentPoint=o}}return t}draw(){super.draw();const t=this.getPartialPath();Be.lines.path(t,this.color,this.stroke,this.lineWidth)}getCurrentPoint(){return{x:this.currentPoint.x,y:this.currentPoint.y}}setAnimationProgress(t){this.animationProgress=Math.max(0,Math.min(1,t))}calculateBounds(){return{x:this.x,y:this.y,width:this.originalWidth||100,height:this.originalHeight||100}}}class ui extends Ne{constructor(t,e,i={}){super(i),this.outerRadius=t,this.innerRadius=e}draw(){super.draw(),Be.lines.beginPath(),Be.shapes.arc(0,0,this.outerRadius,0,2*Math.PI),Be.shapes.arc(0,0,this.innerRadius,0,2*Math.PI,!0),Be.lines.closePath(),this.color&&Be.colors.fill(this.color),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}}class di extends Ne{constructor(t=6,e=40,i={}){super(i),this.sides=t,this.radius=e}draw(){super.draw();const t=[],e=2*Math.PI/this.sides;for(let i=0;i<this.sides;i++){const s=i*e;t.push({x:Math.cos(s)*this.radius,y:Math.sin(s)*this.radius})}Be.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class fi extends Ne{constructor(t,e={}){super(e),this.length=t}draw(){super.draw();const t=this.width/2,e=.4*this.length,i=this.length-e;Be.lines.beginPath(),Be.lines.moveTo(-i/2,-t),Be.lines.lineTo(i/2,-t),Be.lines.lineTo(i/2,-this.width),Be.lines.lineTo(this.length/2,0),Be.lines.lineTo(i/2,this.width),Be.lines.lineTo(i/2,t),Be.lines.lineTo(-i/2,t),Be.lines.closePath(),this.color&&Be.colors.fill(this.color),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}}class pi extends Ne{constructor(t=20,e={}){super(e),this.radius=t}draw(){super.draw();const t=this.radius,e=2.5*t;Be.lines.beginPath(),Be.shapes.arc(0,0,t,Math.PI,0),Be.lines.lineTo(t,0),Be.lines.lineTo(0,e),Be.lines.lineTo(-t,0),Be.lines.closePath(),this.color&&Be.colors.fill(this.color),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y+.98*this.radius,width:2*this.radius,height:2.5*this.radius}}}class gi extends Ne{constructor(t,e={}){super(e),this.radius=t}draw(){super.draw();const t=Array.from({length:6},(t,e)=>{const i=Math.PI/3*e;return{x:Math.cos(i)*this.radius,y:Math.sin(i)*this.radius}});Be.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class mi extends Ne{constructor(t={}){super(t)}draw(){super.draw();const t=this.width,e=this.height,i=.3*e,s=Be.lines;s.beginPath(),s.moveTo(0,i),s.bezierCurveTo(0,0,-t/2,0,-t/2,i),s.bezierCurveTo(-t/2,.8*e,0,e,0,e),s.bezierCurveTo(0,e,t/2,.8*e,t/2,i),s.bezierCurveTo(t/2,0,0,0,0,i),s.closePath(),this.color&&Be.colors.fill(this.color),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y+this.height/2,width:this.width,height:this.height}}}class yi extends Ne{constructor(t,e,i={}){super(i),this.size=t,this.thickness=e,this.diagonal=i.diagonal||!1}draw(){super.draw();const t=this.size/2,e=this.thickness/2;this.diagonal?(Be.lines.beginPath(),Be.lines.moveTo(-t,-t+e),Be.lines.lineTo(-t+e,-t),Be.lines.lineTo(0,-e),Be.lines.lineTo(t-e,-t),Be.lines.lineTo(t,-t+e),Be.lines.lineTo(e,0),Be.lines.lineTo(t,t-e),Be.lines.lineTo(t-e,t),Be.lines.lineTo(0,e),Be.lines.lineTo(-t+e,t),Be.lines.lineTo(-t,t-e),Be.lines.lineTo(-e,0),Be.lines.closePath()):(Be.lines.beginPath(),Be.lines.moveTo(-e,-t),Be.lines.lineTo(e,-t),Be.lines.lineTo(e,-e),Be.lines.lineTo(t,-e),Be.lines.lineTo(t,e),Be.lines.lineTo(e,e),Be.lines.lineTo(e,t),Be.lines.lineTo(-e,t),Be.lines.lineTo(-e,e),Be.lines.lineTo(-t,e),Be.lines.lineTo(-t,-e),Be.lines.lineTo(-e,-e),Be.lines.closePath()),this.color&&Be.colors.fill(this.color),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}}class xi extends Ne{constructor(t,e={}){super(e),this._text=t,this._font=e.font||"12px monospace",this._color=e.color||"yellow",this._align=e.align||"center",this._baseline=e.baseline||"middle",this._calculateBounds(),this._calculateAlignmentOffsets()}draw(){super.draw(),this.logger.log("draw",this.font,this.color,this.opacity),Be.text.setFont(this.font),Be.text.setTextAlign(this.align),Be.text.setTextBaseline(this.baseline),Be.text.fillText(this.text,0,0,this.color)}_calculateAlignmentOffsets(){if(!Be.text)return;const t=Be.text.measureTextDimensions(this.text,this.font);switch(this._align){case"left":this._centerOffsetX=t.width/2;break;case"center":this._centerOffsetX=0;break;case"right":this._centerOffsetX=-t.width/2-5}switch(this._baseline){case"top":this._centerOffsetY=t.height/4;break;case"middle":this._centerOffsetY=-2;break;case"bottom":this._centerOffsetY=-t.height}}getTextBounds(){if(Be.text){const t=Be.text.measureTextDimensions(this.text,this.font),e=2;return{x:this._centerOffsetX-t.width/2,y:this._centerOffsetY-t.height/2,width:t.width+2*e,height:t.height+2*e}}return{x:this._centerOffsetX,y:this._centerOffsetY,width:this._width,height:this._height}}_calculateBounds(){if(Be.text){const t=Be.text.measureTextDimensions(this.text,this.font);this._width=t.width,this._height=t.height,this._calculateAlignmentOffsets()}else this._width=this.text?8*this.text.length:0,this._height=16;this.trace("TextShape.calculateBounds: "+this._width+"x"+this._height)}getDebugBounds(){const t=this.getTextBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}checkDirty(t,e){t!==e&&(this._boundsDirty=!0,this._calculateBounds())}get text(){return this._text}set text(t){this.checkDirty(t,this._text),this._text=t}get font(){return this._font}set font(t){this.checkDirty(t,this._font),this._font=t}get color(){return this._color}set color(t){this._color=t}get align(){return this._align}set align(t){this.checkDirty(t,this._align),this._align=t}get baseline(){return this._baseline}set baseline(t){this.checkDirty(t,this._baseline),this._baseline=t}}class vi extends Ne{constructor(t,e={}){if(!t&&!e.width&&!e.height)throw new Error("ImageShape must be initialized with either a bitmap or width and height");super(e),this._bitmap=t??Be.img.createImageData(e.width,e.height),this._width=e.width??(null==t?void 0:t.width)??0,this._height=e.height??(null==t?void 0:t.height)??0,this.anchor=e.anchor??"center",this._anchorX=.5,this._anchorY=.5,this._updateAnchorOffsets(),this.smoothing=!1!==e.smoothing,t instanceof ImageData&&this.buffer(t)}_updateAnchorOffsets(){var t;const e=(null==(t=this.anchor)?void 0:t.toLowerCase())??"center";e.includes("left")?this._anchorX=0:e.includes("right")?this._anchorX=1:this._anchorX=.5,e.includes("top")?this._anchorY=0:e.includes("bottom")?this._anchorY=1:this._anchorY=.5}get bitmap(){return this._bitmap}set bitmap(t){t&&(this._bitmap=t,!this._width&&t.width&&(this._width=t.width),!this._height&&t.height&&(this._height=t.height),t instanceof ImageData&&this.buffer(t))}buffer(t){t&&(this._buffer||(this._buffer=document.createElement("canvas")),this._buffer.width===t.width&&this._buffer.height===t.height||(this._buffer.width=t.width,this._buffer.height=t.height),this._buffer.getContext("2d").putImageData(t,0,0))}reset(){this._buffer=null,this._bitmap=Be.img.createImageData(this.width,this.height)}setAnchor(t){this.anchor=t,this._updateAnchorOffsets()}draw(){if(!this.visible)return;if(!this._bitmap&&!this._buffer)return;super.draw();let t=this._bitmap instanceof ImageData?this._buffer:this._bitmap;(!t||this._bitmap instanceof ImageData&&!this._buffer)&&(this._bitmap instanceof ImageData&&(this.buffer(this._bitmap),t=this._buffer),!t)||Be.img.draw(t,0,0,{width:this.width,height:this.height,anchor:this.anchor,rotation:this.rotation,scaleX:this.scaleX,scaleY:this.scaleY,alpha:this.opacity,smoothing:this.smoothing,flipX:this.scaleX<0,flipY:this.scaleY<0})}calculateBounds(){return{x:-this._anchorX*this.width,y:-this._anchorY*this.height,width:this.width,height:this.height}}}class _i{constructor(){this.listeners={}}on(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)}off(t,e){this.listeners[t]&&(this.listeners[t]=this.listeners[t].filter(t=>t!==e))}emit(t,e){this.listeners[t]&&this.listeners[t].forEach(t=>t(e))}}class wi{static init(t){wi.game=t,wi.x=0,wi.y=0,wi.down=!1,t.events.on("mousedown",e=>wi._onDown(e,t)),t.events.on("mouseup",e=>wi._onUp(e,t)),t.events.on("mousemove",e=>wi._onMove(e,t)),t.events.on("touchstart",e=>wi._onTouchStart(e,t)),t.events.on("touchend",e=>wi._onTouchEnd(e,t)),t.events.on("touchmove",e=>wi._onTouchMove(e,t))}static _scaleToCanvas(t,e,i){const s=t.canvas,n=s.getBoundingClientRect();return{x:e*(s.width/n.width),y:i*(s.height/n.height)}}static _setPosition(t,e){wi.x=t,wi.y=e}static _onDown(t,e){wi.down=!0;const i=wi._scaleToCanvas(e,t.offsetX,t.offsetY);wi._setPosition(i.x,i.y),Object.defineProperty(t,"x",{value:i.x,configurable:!0}),Object.defineProperty(t,"y",{value:i.y,configurable:!0}),e.events.emit("inputdown",t)}static _onUp(t,e){wi.down=!1;const i=wi._scaleToCanvas(e,t.offsetX,t.offsetY);wi._setPosition(i.x,i.y),Object.defineProperty(t,"x",{value:i.x,configurable:!0}),Object.defineProperty(t,"y",{value:i.y,configurable:!0}),e.events.emit("inputup",t)}static _onMove(t,e){const i=wi._scaleToCanvas(e,t.offsetX,t.offsetY);wi._setPosition(i.x,i.y),Object.defineProperty(t,"x",{value:i.x,configurable:!0}),Object.defineProperty(t,"y",{value:i.y,configurable:!0}),e.events.emit("inputmove",t)}static _onTouchStart(t,e){const i=t.touches[0],s=e.canvas.getBoundingClientRect();wi.down=!0;const n=i.clientX-s.left,o=i.clientY-s.top,r=wi._scaleToCanvas(e,n,o);wi._setPosition(r.x,r.y),Object.defineProperty(t,"x",{value:r.x,configurable:!0}),Object.defineProperty(t,"y",{value:r.y,configurable:!0}),e.events.emit("inputdown",t)}static _onTouchEnd(t,e){wi.down=!1,e.events.emit("inputup",t)}static _onTouchMove(t,e){const i=t.touches[0],s=e.canvas.getBoundingClientRect(),n=i.clientX-s.left,o=i.clientY-s.top,r=wi._scaleToCanvas(e,n,o);wi._setPosition(r.x,r.y),Object.defineProperty(t,"x",{value:r.x,configurable:!0}),Object.defineProperty(t,"y",{value:r.y,configurable:!0}),e.events.emit("inputmove",t)}}const bi=class t{static init(e){t._gameMap.set(e.canvas,e),t.game=e,t.canvas=e.canvas,t.x=0,t.y=0,t.leftDown=!1,t.middleDown=!1,t.rightDown=!1,e.canvas.addEventListener("mousemove",t._onMove),e.canvas.addEventListener("mousedown",t._onDown),e.canvas.addEventListener("mouseup",t._onUp),e.canvas.addEventListener("click",t._onClick),e.canvas.addEventListener("wheel",t._onWheel)}static _getGameForEvent(e){const i=e.currentTarget;return t._gameMap.get(i)||t.game}static _updatePosition(e,i){const s=i.canvas,n=s.getBoundingClientRect(),o=e.clientX-n.left,r=e.clientY-n.top,a=s.width/n.width,h=s.height/n.height;t.x=o*a,t.y=r*h}};vt(bi,"_gameMap",new Map),vt(bi,"_onMove",t=>{const e=bi._getGameForEvent(t);bi._updatePosition(t,e),e.events.emit("mousemove",t)}),vt(bi,"_onDown",t=>{const e=bi._getGameForEvent(t);bi._updatePosition(t,e),0===t.button&&(bi.leftDown=!0),1===t.button&&(bi.middleDown=!0),2===t.button&&(bi.rightDown=!0),e.events.emit("mousedown",t)}),vt(bi,"_onUp",t=>{const e=bi._getGameForEvent(t);bi._updatePosition(t,e),0===t.button&&(bi.leftDown=!1),1===t.button&&(bi.middleDown=!1),2===t.button&&(bi.rightDown=!1),e.events.emit("mouseup",t)}),vt(bi,"_onClick",t=>{const e=bi._getGameForEvent(t);bi._updatePosition(t,e),t.canvasX=bi.x,t.canvasY=bi.y,Object.defineProperty(t,"x",{value:bi.x,writable:!1}),Object.defineProperty(t,"y",{value:bi.y,writable:!1}),e.events.emit("click",t)}),vt(bi,"_onWheel",t=>{const e=bi._getGameForEvent(t);bi._updatePosition(t,e),e.events.emit("wheel",t)});let Mi=bi;const ki=class t{static init(e){t.game=e,window.addEventListener("keydown",t._onKeyDown),window.addEventListener("keyup",t._onKeyUp)}static isDown(e){return t._down.has(e)}static _onKeyDown(e){const i=t._codeMap[e.code];i&&(t._down.has(i)||(t._down.add(i),t.game.events.emit(i,e))),t.game.events.emit(e.type,e)}static _onKeyUp(e){const i=t._codeMap[e.code];i&&t._down.has(i)&&(t._down.delete(i),t.game.events.emit(i+"_up",e)),t.game.events.emit(e.type,e)}};vt(ki,"W","W"),vt(ki,"A","A"),vt(ki,"S","S"),vt(ki,"D","D"),vt(ki,"Q","Q"),vt(ki,"E","E"),vt(ki,"R","R"),vt(ki,"F","F"),vt(ki,"Z","Z"),vt(ki,"C","C"),vt(ki,"UP","UP"),vt(ki,"DOWN","DOWN"),vt(ki,"LEFT","LEFT"),vt(ki,"RIGHT","RIGHT"),vt(ki,"SPACE","SPACE"),vt(ki,"SHIFT","SHIFT"),vt(ki,"ENTER","ENTER"),vt(ki,"ESC","ESC"),vt(ki,"_codeMap",{KeyW:ki.W,KeyA:ki.A,KeyS:ki.S,KeyD:ki.D,KeyQ:ki.Q,KeyE:ki.E,KeyR:ki.R,KeyF:ki.F,KeyZ:ki.Z,KeyC:ki.C,ArrowUp:ki.UP,ArrowDown:ki.DOWN,ArrowLeft:ki.LEFT,ArrowRight:ki.RIGHT,Space:ki.SPACE,ShiftLeft:ki.SHIFT,ShiftRight:ki.SHIFT,Enter:ki.ENTER,NumpadEnter:ki.ENTER,Escape:ki.ESC}),vt(ki,"_down",new Set),vt(ki,"game",null);let Ci=ki;const Si=class t{static init(e){t._gameMap.set(e.canvas,e),t.game=e,t.canvas=e.canvas,t.x=0,t.y=0,t.active=!1,e.canvas.addEventListener("touchstart",t._onStart),e.canvas.addEventListener("touchend",t._onEnd),e.canvas.addEventListener("touchmove",t._onMove)}static _getGameForEvent(e){const i=e.currentTarget;return t._gameMap.get(i)||t.game}static _updatePosition(e,i){const s=i.canvas,n=s.getBoundingClientRect(),o=e.clientX-n.left,r=e.clientY-n.top,a=s.width/n.width,h=s.height/n.height;t.x=o*a,t.y=r*h}};vt(Si,"_gameMap",new Map),vt(Si,"_onStart",t=>{if(t.touches.length>0){const e=Si._getGameForEvent(t);Si.active=!0,Si._updatePosition(t.touches[0],e),e.events.emit("touchstart",t)}}),vt(Si,"_onEnd",t=>{const e=Si._getGameForEvent(t);Si.active=!1,e.events.emit("touchend",t)}),vt(Si,"_onMove",t=>{if(t.touches.length>0){const e=Si._getGameForEvent(t);Si._updatePosition(t.touches[0],e),e.events.emit("touchmove",t)}});let Ti=Si;function Ri(t,e={}){var i;if(!(t&&t instanceof Pi))return console.warn("applyAnchor can only be applied to GameObject instances"),t;t._anchor={position:e.anchor??null,margin:e.anchorMargin??10,offsetX:e.anchorOffsetX??0,offsetY:e.anchorOffsetY??0,relative:e.anchorRelative??!1,setTextAlign:!1!==e.anchorSetTextAlign,lastUpdate:0};const s=null==(i=t.update)?void 0:i.bind(t);return t.update=function(e){const i=!0===t._anchor.relative&&t.parent?t.parent:t._anchor.relative;if(t._anchor.position&&(t.boundsDirty||i&&i.boundsDirty||t.parent&&t.parent.boundsDirty)){let e,s,o;if(i){const s={x:i.x,y:i.y,width:i.width,height:i.height};e=Tt.calculate(t._anchor.position,t,s,t._anchor.margin,t._anchor.offsetX,t._anchor.offsetY)}else e=Tt.calculateAbsolute(t._anchor.position,t,t.game,t._anchor.margin,t._anchor.offsetX,t._anchor.offsetY);!t.parent||(n=t).game&&n.game.pipeline&&n.game.pipeline.gameObjects&&n.game.pipeline.gameObjects.includes(n)?(s=e.x,o=e.y):i===t.parent?(s=e.x-i.x,o=e.y-i.y):(s=e.x-t.parent.x,o=e.y-t.parent.y),t.transform&&"function"==typeof t.transform.position?t.transform.position(s,o):(t.x=s,t.y=o),t._anchor.setTextAlign&&("align"in t&&(t.align=e.align),"baseline"in t&&(t.baseline=e.baseline)),t._anchor.lastUpdate=t.game?t.game.lastTime:Date.now()}var n;s&&s(e)},t}class Pi extends He{constructor(t,e={}){super(e),this.game=t,this.parent=null,this.events=new _i,this._interactive=e.interactive??!1,this._hovered=!1,e.anchor&&Ri(this,e)}update(t){this.logger.groupCollapsed("GameObject.update: "+(null==this.name?this.constructor.name:this.name)),super.update(t),this.logger.groupEnd()}get interactive(){return this._interactive}set interactive(t){const e=Boolean(t);this._interactive!==e&&(this._interactive=e,!0===e?this._enableEvents():(this._disableEvents(),this._hovered&&(this._hovered=!1,this.events.emit("mouseout"))))}_enableEvents(){this.logger.log(`${this.constructor.name} is now interactive`)}_disableEvents(){this.logger.log(`${this.constructor.name} is no longer interactive`)}get hovered(){return this._hovered}set hovered(t){this._hovered=Boolean(t)}_setHovered(t){this._hovered=Boolean(t)}_hitTest(t,e){var i;if(!this._interactive)return!1;const s=null==(i=this.getBounds)?void 0:i.call(this);if(!s)return!1;let n=t,o=e;const r=[];let a=this;for(;a;)r.unshift(a),a=a.parent;for(const t of r){if(n-=t.x||0,o-=t.y||0,t.rotation){const e=Math.cos(-t.rotation),i=Math.sin(-t.rotation),s=n;n=s*e-o*i,o=s*i+o*e}void 0!==t.scaleX&&0!==t.scaleX&&(n/=t.scaleX),void 0!==t.scaleY&&0!==t.scaleY&&(o/=t.scaleY)}const h=(s.width||this.width||0)/2,l=(s.height||this.height||0)/2;return n>=-h&&n<=h&&o>=-l&&o<=l}on(t,e){this.events.on(t,e)}off(t,e){this.events.off(t,e)}emit(t,...e){this.events.emit(t,...e)}}class Ai extends Pi{constructor(t,e,i={}){if(super(t,i),!e||null==e||null==e)throw new Error("GameObjectShapeWrapper requires a shape");this.shape=e,void 0!==i.color&&(e.color=i.color),void 0!==i.stroke&&(e.stroke=i.stroke),void 0!==i.lineWidth&&(e.lineWidth=i.lineWidth),void 0!==i.lineJoin&&(e.lineJoin=i.lineJoin),void 0!==i.lineCap&&(e.lineCap=i.lineCap),void 0!==i.miterLimit&&(e.miterLimit=i.miterLimit),this.syncPropertiesToShape(),this.logger.log(`Created GameObject(${this.constructor.name}):`,{x:this.x,y:this.y,width:this.width,height:this.height,color:this.color,stroke:this.stroke})}syncPropertiesToShape(){if(!this.shape)return;const t=["width","height","rotation","scaleX","scaleY","visible","debug","debugColor"];for(const e of t)e in this&&e in this.shape&&this[e]!==this.shape[e]&&(this.shape[e]=this[e])}get color(){return this.shape?this.shape.color:null}set color(t){this.shape&&(this.shape.color=t)}get stroke(){return this.shape?this.shape.stroke:null}set stroke(t){this.shape&&(this.shape.stroke=t)}get lineWidth(){return this.shape?this.shape.lineWidth:1}set lineWidth(t){this.shape&&(this.shape.lineWidth=t)}get lineJoin(){return this.shape?this.shape.lineJoin:"miter"}set lineJoin(t){this.shape&&(this.shape.lineJoin=t)}get lineCap(){return this.shape?this.shape.lineCap:"butt"}set lineCap(t){this.shape&&(this.shape.lineCap=t)}get miterLimit(){return this.shape?this.shape.miterLimit:10}set miterLimit(t){this.shape&&(this.shape.miterLimit=t)}update(t){var e;this.active&&(null==(e=this.onUpdate)||e.call(this,t),(this._boundsDirty||this.tweening)&&(this.syncPropertiesToShape(),this._boundsDirty=!1),super.update(t))}draw(){super.draw(),this.shape.render()}}class Di extends Pi{constructor(t,e={}){super(t,e),this._collection=new Ct({sortByZIndex:e.sortByZIndex||!0}),this._collection._owner=this,this._width=e.width??0,this._height=e.height??0,this.forceWidth=null,this.forceHeight=null,this._naturalWidth=null,this._naturalHeight=null,this.userDefinedDimensions=!1,null!=e.width&&null!=e.height&&(this.userDefinedWidth=e.width,this.userDefinedHeight=e.height,this.userDefinedDimensions=!0)}update(t){this.logger.groupCollapsed("Scene.update: "+(null==this.name?this.constructor.name:this.name));for(let e=0;e<this.children.length;e++){const i=this.children[e];i.active&&i.update&&i.update(t)}super.update(t),this.logger.groupEnd()}add(t){if(null==t||null==t)throw new Error("GameObject is null or undefined");return null!=t.parent&&console.warn("This GameObject already has a parent. Consider removing it first."),t.parent=this,this._collection.add(t),this.markBoundsDirty(),t.init&&t.init(),t}markBoundsDirty(){super.markBoundsDirty(),this.children.forEach(t=>{t.markBoundsDirty()})}remove(t){const e=this._collection.remove(t);return e&&(t.parent=null,this.markBoundsDirty()),e}draw(){super.draw(),this.logger.log("Scene.draw chilren:"),this._collection.getSortedChildren().filter(t=>t.visible).map(function(t){return Be.save(),t.render(),Be.restore(),t})}getDebugBounds(){return{width:this.width,height:this.height,x:-this.width/2,y:-this.height/2}}getBounds(){return{x:this.x,y:this.y,width:this._width||0,height:this._height||0}}bringToFront(t){return this._collection.bringToFront(t)}sendToBack(t){return this._collection.sendToBack(t)}bringForward(t){return this._collection.bringForward(t)}sendBackward(t){return this._collection.sendBackward(t)}clear(){return this._collection.children.forEach(t=>this.remove(t)),this._collection.clear()}get children(){return this._collection.children}}class Ii extends Di{constructor(t,e={}){super(t,e),this.spacing=e.spacing??10,this.padding=e.padding??0,this.autoSize=e.autoSize??!0,this.align=e.align??"start",this.debug=e.debug??!1,this._layoutDirty=!0,this.scrollable=e.scrollable??!1,this.scrollFriction=e.scrollFriction??.92,this.scrollBounce=e.scrollBounce??.3,this.scrollThreshold=e.scrollThreshold??.5,this._viewportWidth=e.viewportWidth??null,this._viewportHeight=e.viewportHeight??null,this._scrollOffset={x:0,y:0},this._scrollVelocity={x:0,y:0},this._scrollDragging=!1,this._scrollDragStart={x:0,y:0},this._scrollDragStartOffset={x:0,y:0},this._lastDragPosition={x:0,y:0},this._lastDragTime=0,this.scrollable&&this._setupScrollInteraction(),this._scrollInitialized=!1}calculateLayout(){throw new Error("Subclasses must implement calculateLayout()")}update(t){if(this._boundsDirty||this._layoutDirty){const t=this.width,e=this.height,i=this.calculateLayout();if(this.autoSize&&i){this._contentWidth=i.width,this._contentHeight=i.height;const t=this.getScrollAxis(),e=this._viewportWidth,s=this._viewportHeight;let n=i.width,o=i.height;this.scrollable&&null!==e&&t.horizontal&&(n=Math.min(i.width,e)),this.scrollable&&null!==s&&t.vertical&&(o=Math.min(i.height,s)),Math.abs(this.width-n)>.1&&(this.width=n),Math.abs(this.height-o)>.1&&(this.height=o)}if(i&&i.positions&&this.applyPositionsToChildren(i.positions),this.scrollable&&!this._scrollInitialized&&this._needsScrolling()){const t=this._getScrollBounds(),e=this.getScrollAxis();e.horizontal&&(this._scrollOffset.x=t.maxX),e.vertical&&(this._scrollOffset.y=t.maxY),this._scrollInitialized=!0}this._boundsDirty=!1,this._layoutDirty=!1,t===this.width&&e===this.height||this._updatingBoundsFromLayout||(this._updatingBoundsFromLayout=!0,Di.prototype.markBoundsDirty.call(this),this._updatingBoundsFromLayout=!1)}this.scrollable&&!this._scrollDragging&&this._updateScrollMomentum(t),super.update(t)}markBoundsDirty(){this._updatingBoundsFromLayout?this._boundsDirty=!0:(super.markBoundsDirty(),this._layoutDirty=!0)}applyPositionsToChildren(t){Rt(this.children,t,this.getLayoutOffset())}getLayoutOffset(){return{offsetX:0,offsetY:0}}add(t){const e=super.add(t);return this._layoutDirty=!0,e}remove(t){const e=super.remove(t);return this._layoutDirty=!0,e}getScrollAxis(){return{horizontal:!1,vertical:!0}}calculateBounds(){if(this.scrollable&&(this._viewportWidth||this._viewportHeight)){const t=this._viewportWidth??this.width,e=this._viewportHeight??this.height;return{x:-t/2,y:-e/2,width:t,height:e}}return super.calculateBounds()}_getScrollBounds(){const t=this._contentWidth??this.width,e=this._contentHeight??this.height,i=this._viewportWidth??t,s=this._viewportHeight??e,n=Math.max(0,t-i),o=Math.max(0,e-s);return{minX:-n/2,maxX:n/2,minY:-o/2,maxY:o/2}}_clampScrollBounds(){const t=this._getScrollBounds(),e=this.getScrollAxis();e.horizontal&&(this._scrollOffset.x<t.minX?(this._scrollOffset.x+=(t.minX-this._scrollOffset.x)*this.scrollBounce,this._scrollVelocity.x=0):this._scrollOffset.x>t.maxX&&(this._scrollOffset.x+=(t.maxX-this._scrollOffset.x)*this.scrollBounce,this._scrollVelocity.x=0)),e.vertical&&(this._scrollOffset.y<t.minY?(this._scrollOffset.y+=(t.minY-this._scrollOffset.y)*this.scrollBounce,this._scrollVelocity.y=0):this._scrollOffset.y>t.maxY&&(this._scrollOffset.y+=(t.maxY-this._scrollOffset.y)*this.scrollBounce,this._scrollVelocity.y=0))}_updateScrollMomentum(t){const e=this.getScrollAxis();e.horizontal&&(this._scrollVelocity.x*=this.scrollFriction,Math.abs(this._scrollVelocity.x)<this.scrollThreshold&&(this._scrollVelocity.x=0),this._scrollOffset.x+=this._scrollVelocity.x*t*60),e.vertical&&(this._scrollVelocity.y*=this.scrollFriction,Math.abs(this._scrollVelocity.y)<this.scrollThreshold&&(this._scrollVelocity.y=0),this._scrollOffset.y+=this._scrollVelocity.y*t*60),this._clampScrollBounds()}_setupScrollInteraction(){this.interactive=!0,this._scrollInputDownHandler=t=>{this._isPointInViewport(t.x,t.y)&&this._onScrollDragStart(t)},this._scrollInputMoveHandler=t=>this._onScrollDragMove(t),this._scrollInputUpHandler=t=>this._onScrollDragEnd(t),this.game.events.on("inputdown",this._scrollInputDownHandler),this.game.events.on("inputmove",this._scrollInputMoveHandler),this.game.events.on("inputup",this._scrollInputUpHandler)}_isPointInViewport(t,e){let i=t-this.x,s=e-this.y,n=this.parent;for(;n;)i-=n.x||0,s-=n.y||0,n=n.parent;const o=(this._viewportWidth??this.width)/2,r=(this._viewportHeight??this.height)/2;return i>=-o&&i<=o&&s>=-r&&s<=r}_onScrollDragStart(t){this._scrollDragging=!0,this._scrollDragStart={x:t.x,y:t.y},this._scrollDragStartOffset={...this._scrollOffset},this._lastDragPosition={x:t.x,y:t.y},this._lastDragTime=performance.now(),this._scrollVelocity={x:0,y:0}}_onScrollDragMove(t){if(!this._scrollDragging)return;const e=this.getScrollAxis(),i=performance.now(),s=Math.max(1,i-this._lastDragTime)/1e3;if(e.horizontal){const e=t.x-this._scrollDragStart.x;this._scrollOffset.x=this._scrollDragStartOffset.x+e,this._scrollVelocity.x=(t.x-this._lastDragPosition.x)/(60*s)}if(e.vertical){const e=t.y-this._scrollDragStart.y;this._scrollOffset.y=this._scrollDragStartOffset.y+e,this._scrollVelocity.y=(t.y-this._lastDragPosition.y)/(60*s)}this._lastDragPosition={x:t.x,y:t.y},this._lastDragTime=i}_onScrollDragEnd(){this._scrollDragging=!1}_needsScrolling(){if(!this.scrollable)return!1;const t=this._contentWidth??this.width,e=this._contentHeight??this.height,i=this._viewportWidth??t,s=this._viewportHeight??e,n=this.getScrollAxis();return!!(n.horizontal&&t>i)||!!(n.vertical&&e>s)}draw(){this._needsScrolling()?this._drawScrollable():super.draw()}_drawScrollable(){this.applyTransforms(),this.drawDebug();const t=this.padding??0,e=(this._viewportWidth??this.width)-2*t,i=(this._viewportHeight??this.height)-2*t;Be.save(),Be.ctx.beginPath(),Be.ctx.rect(-e/2,-i/2,e,i),Be.ctx.clip(),Be.ctx.beginPath(),Be.ctx.translate(this._scrollOffset.x,this._scrollOffset.y),this._collection.getSortedChildren().filter(t=>t.visible).forEach(t=>{Be.save(),t.render(),Be.restore()}),Be.restore()}scrollTo(t,e){const i=this.getScrollAxis();i.horizontal&&(this._scrollOffset.x=t),i.vertical&&(this._scrollOffset.y=e),this._scrollVelocity={x:0,y:0}}scrollBy(t,e){const i=this.getScrollAxis();i.horizontal&&(this._scrollOffset.x+=t),i.vertical&&(this._scrollOffset.y+=e)}getScrollPosition(){return{...this._scrollOffset}}resetScroll(){this._scrollOffset={x:0,y:0},this._scrollVelocity={x:0,y:0}}}class zi extends Pi{constructor(t,e={}){super(t,e),this._frames=[],this._currentFrame=0,this._frameAccumulator=0,this._isPlaying=e.autoPlay||!1,this._loop=void 0===e.loop||e.loop,this._frameRate=e.frameRate||12,this._frameDuration=1/this._frameRate,this._animations=new Map,this._currentAnimation=null,e.frames&&Array.isArray(e.frames)&&e.frames.forEach(t=>this.addFrame(t))}addAnimation(t,e,i={}){if(!t||"string"!=typeof t)throw new Error("Sprite.addAnimation: name is required");if(!e||!Array.isArray(e)||0===e.length)throw new Error("Sprite.addAnimation: frames array is required");return e.forEach(t=>{t.parent=this}),this._animations.set(t,{frames:e,loop:void 0===i.loop||i.loop,frameRate:i.frameRate||null}),this}removeAnimation(t){const e=this._animations.get(t);return!!e&&(e.frames.forEach(t=>{t.parent=null}),this._animations.delete(t),this._currentAnimation===t&&(this._currentAnimation=null,this._frames=[]),!0)}playAnimation(t,e=!1){const i=this._animations.get(t);return i?(this._currentAnimation===t&&this._isPlaying&&!e||(this._currentAnimation=t,this._frames=i.frames,this._loop=i.loop,null!==i.frameRate&&(this._frameRate=i.frameRate,this._frameDuration=1/this._frameRate),this._currentFrame=0,this._frameAccumulator=0,this._isPlaying=!0),this):(console.warn(`Sprite.playAnimation: animation '${t}' not found`),this)}stopAnimation(t){const e=this._animations.get(t);return e?(this._currentAnimation=t,this._frames=e.frames,this._loop=e.loop,this._currentFrame=0,this._frameAccumulator=0,this._isPlaying=!1,this):(console.warn(`Sprite.stopAnimation: animation '${t}' not found`),this)}get currentAnimationName(){return this._currentAnimation}get animationNames(){return Array.from(this._animations.keys())}hasAnimation(t){return this._animations.has(t)}addFrame(t){if(!t)throw new Error("Sprite.addFrame: shape is required");return t.parent=this,this._frames.push(t),this.markBoundsDirty(),this._frames.length-1}removeFrame(t){if(t<0||t>=this._frames.length)return null;const e=this._frames.splice(t,1)[0];return e&&(e.parent=null,this.markBoundsDirty(),this._currentFrame>=this._frames.length&&this._frames.length>0&&(this._currentFrame=this._frames.length-1)),e}clearFrames(){this._frames.forEach(t=>{t.parent=null}),this._frames=[],this._currentFrame=0,this.markBoundsDirty()}get totalFrames(){return this._frames.length}get currentFrame(){return this._currentFrame}get currentShape(){return this._frames[this._currentFrame]||null}get frames(){return this._frames}get isPlaying(){return this._isPlaying}get loop(){return this._loop}set loop(t){this._loop=t}get frameRate(){return this._frameRate}set frameRate(t){if(t<=0)throw new Error("Sprite.frameRate must be greater than 0");this._frameRate=t,this._frameDuration=1/t}play(){return this._isPlaying=!0,this}pause(){return this._isPlaying=!1,this}stop(){return this._isPlaying=!1,this._currentFrame=0,this._frameAccumulator=0,this}rewind(){return this._currentFrame=0,this._frameAccumulator=0,this}goto(t){return 0===this._frames.length||(this._currentFrame=Math.max(0,Math.min(t,this._frames.length-1)),this._frameAccumulator=0),this}gotoAndStop(t){return this.goto(t),this.pause(),this}gotoAndPlay(t){return this.goto(t),this.play(),this}update(t){if(super.update(t),!this._isPlaying||0===this._frames.length)return;for(this._frameAccumulator+=t;this._frameAccumulator>=this._frameDuration;)this._frameAccumulator-=this._frameDuration,this._advanceFrame();const e=this.currentShape;e&&"function"==typeof e.update&&e.update(t)}_advanceFrame(){this._currentFrame++,this._currentFrame>=this._frames.length&&(this._loop?this._currentFrame=0:(this._currentFrame=this._frames.length-1,this._isPlaying=!1))}draw(){super.draw();const t=this.currentShape;t&&!1!==t.visible&&(Be.save(),t.render(),Be.restore())}calculateBounds(){if(0===this._frames.length)return{x:this.x,y:this.y,width:0,height:0};let t=1/0,e=1/0,i=-1/0,s=-1/0;return this._frames.forEach(n=>{const o=n.getBounds();t=Math.min(t,o.x),e=Math.min(e,o.y),i=Math.max(i,o.x+o.width),s=Math.max(s,o.y+o.height)}),{x:t+this.x,y:e+this.y,width:i-t,height:s-e}}toString(){return`[Sprite frames=${this.totalFrames} current=${this.currentFrame} playing=${this.isPlaying}]`}}class Bi extends zi{constructor(t,e={}){super(t,{frameRate:e.frameRate||12,loop:void 0===e.loop||e.loop,autoPlay:!1,...e}),this._src=e.src,this._frameWidth=e.frameWidth,this._frameHeight=e.frameHeight,this._columns=e.columns,this._rows=e.rows,this._frameCount=e.frameCount||e.columns*e.rows,this._startFrame=e.startFrame||0,this._smoothing=void 0!==e.smoothing&&e.smoothing,this._autoPlayAfterLoad=e.autoPlay||!1,this._loaded=!1,this._loading=!1,this._image=null,this._frameCanvases=[],this.width=this._frameWidth,this.height=this._frameHeight}static async create(t,e){const i=new Bi(t,e);return await i.load(),i}async load(){if(this._loaded||this._loading)return this;this._loading=!0;try{return this._image=await this._loadImage(this._src),await this._sliceFrames(),this._loaded=!0,this._loading=!1,this._autoPlayAfterLoad&&this.play(),this}catch(t){throw this._loading=!1,console.error("SpriteSheet.load failed:",t),t}}_loadImage(t){return new Promise((e,i)=>{const s=new Image;s.onload=()=>e(s),s.onerror=e=>i(new Error(`Failed to load image: ${t}`)),s.src=t})}async _sliceFrames(){const{_image:t,_frameWidth:e,_frameHeight:i,_columns:s}=this;this.clearFrames(),this._frameCanvases=[];for(let n=this._startFrame;n<this._startFrame+this._frameCount;n++){const o=n%s*e,r=Math.floor(n/s)*i,a=document.createElement("canvas");a.width=e,a.height=i;const h=a.getContext("2d");h.imageSmoothingEnabled=this._smoothing,h.drawImage(t,o,r,e,i,0,0,e,i),this._frameCanvases.push(a);const l=new vi(a,{width:e,height:i,anchor:"center",smoothing:this._smoothing});this.addFrame(l)}}get loaded(){return this._loaded}get loading(){return this._loading}get frameWidth(){return this._frameWidth}get frameHeight(){return this._frameHeight}get columns(){return this._columns}get rows(){return this._rows}update(t){this._loaded&&super.update(t)}draw(){this._loaded&&super.draw()}toString(){return`[SpriteSheet src="${this._src}" frames=${this._frameCount} loaded=${this._loaded}]`}}class Ei extends Ai{constructor(t,e,i={}){super(t,new xi(e,{font:i.font||"16px monospace",color:i.color||"yellow",align:i.align||"left",baseline:i.baseline||"top",strokeColor:i.strokeColor||"#000",lineWidth:i.lineWidth||1,debugColor:i.debugColor||"yellow"}),i),this._textOptions={font:i.font||"16px monospace",color:i.color||"yellow",align:i.align||"left",baseline:i.baseline||"top"}}get text(){return this.shape.text}set text(t){this.shape.text=t,this.markBoundsDirty()}get font(){return this.shape.font}set font(t){this.shape.font=t,this._textOptions.font=t,this.markBoundsDirty()}get color(){return this.shape.color}set color(t){this.shape.color=t,this._textOptions.color=t}get align(){return this.shape.align}set align(t){this.shape.align=t,this._textOptions.align=t,this.markBoundsDirty()}get baseline(){return this.shape.baseline}set baseline(t){this.shape.baseline=t,this._textOptions.baseline=t,this.markBoundsDirty()}measureWidth(){return Be.ctx?Be.text.measureTextWidth(this.text,this.font):0}measureHeight(){if(!this.font)return 16;const t=parseInt(this.font);return isNaN(t)?16:t}getBounds(){const t=super.getBounds();if(this.shape.getTextBounds){const t=this.shape.getTextBounds();return{x:this.x,y:this.y,width:t.width,height:t.height}}return t}update(t){super.update(t),this.shape&&(this.width=this.shape.width||this.measureWidth(),this.height=this.shape.height||this.measureHeight())}}class Fi{static lerp(t,e,i){return t+(e-t)*i}static lerpAngle(t,e,i){let s=e-t;for(;s<-Math.PI;)s+=2*Math.PI;for(;s>Math.PI;)s-=2*Math.PI;return t+s*i}static tweenColor(t,e,i){return t.map((t,s)=>Fi.lerp(t,e[s],i))}static tweenGradient(t,e,i){let s=t[0],n=e[0];return Math.abs(n-s)>180&&(s<n?s+=360:n+=360),[Fi.lerp(s,n,i)%360,Fi.lerp(t[1],e[1],i),Fi.lerp(t[2],e[2],i)]}}function Oi(t,e,i,s,n,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=Ji._frame(s,n,o,r,a,h),f=1/(i+1),p=Math.min(Math.floor(c/f),i),g=c%f/f,m=t*Math.pow(.6,p),y=e-Math.sin(g*Math.PI)*(e-m);return Ji.animationResult({y:y,segment:p,bounceHeight:m},l,o,u,d)}function Xi(t,e,i,s,n,o,r=!0,a=null,h={},l=null){if(i<=0)return Ji.animationResult({x:t.x,y:t.y,moving:!1},1,!1,!0);l||(l={initialX:t.x,initialY:t.y,started:!1,completed:!1,loopCount:0});const c=l.initialX,u=l.initialY,{t:d,easedT:f,completed:p,state:g}=Ji._frame(e,i,r,a,h,l);l={...l,...g};const m=e*s,y=Math.max(0,Math.min(1,n)),x=c+(Math.sin(.7*m)+.4*y*Math.sin(2.3*m+.5))*o,v=u+(Math.cos(.9*m)+.4*y*Math.cos(1.9*m+.7))*o,_=.7*Math.cos(.7*m)+.4*y*2.3*Math.cos(2.3*m+.5),w=-.9*Math.sin(.9*m)+.4*y*-1.9*Math.sin(1.9*m+.7),b=Math.sqrt(_*_+w*w),M=b>.8,k=Math.sqrt((x-c)*(x-c)+(v-u)*(v-u));return Ji.animationResult({x:x,y:v,centerX:c,centerY:u,offsetX:x-c,offsetY:v-u,distance:k,moving:M,velocity:b},d,r,p,l)}function Yi(t,e=!1,i,s,n=!1,o=null,r={},a=null){if(!t||t.length<2)return this._createResult({x:0,y:0},0,n,!1);const{t:h,easedT:l,completed:c,state:u}=Ji._frame(i,s,n,o,r,a);if(!a||!a.pathData){const i={segmentLengths:[],totalLength:0,points:[...t]};for(let e=0;e<t.length-1;e++){const s=t[e],n=t[e+1],o=n[0]-s[0],r=n[1]-s[1],a=Math.sqrt(o*o+r*r);i.segmentLengths.push(a),i.totalLength+=a}if(e){const e=t[t.length-1],s=t[0],n=s[0]-e[0],o=s[1]-e[1],r=Math.sqrt(n*n+o*o);i.segmentLengths.push(r),i.totalLength+=r}u.pathData=i}const{segmentLengths:d,totalLength:f,points:p}=u.pathData,g=l*f;let m=0,y=0;for(let t=0;t<d.length;t++){if(m+d[t]>=g){y=t;break}m+=d[t]}const x=(g-m)/d[y],v=p[y],_=y<p.length-1?p[y+1]:p[0],w=Fi.lerp(v[0],_[0],x),b=Fi.lerp(v[1],_[1],x),M=Math.atan2(_[1]-v[1],_[0]-v[0]);return Ji.animationResult({x:w,y:b,angle:M,segmentIndex:y,segmentProgress:x,pathProgress:l},h,n,c,u)}function Wi(t,e,i,s,n,o,r,a=!0,h=!0,l=null,c={},u=null){const{t:d,easedT:f,completed:p,state:g}=Ji._frame(o,r,a,l,c,u),m=n+(h?1:-1)*f*Math.PI*2,y=t+i*Math.cos(m),x=e+s*Math.sin(m);return Ji.animationResult({x:y,y:x,angle:m},d,a,p,g)}function Li(t,e,i,s,n=!0,o=null,r={},a=null){const{t:h,easedT:l,completed:c,state:u}=Ji._frame(i,s,n,o,r,a),d=(e-t)/2,f=t+d+d*Math.sin(l*Math.PI*2);return Ji.animationResult({value:f},h,n,c,u)}function Hi(t,e,i,s,n,o=!1,r=!1,a=null,h={},l=null){l||(l={started:!1,loopCount:0,direction:1,lastDirection:1,completed:!1});let c=n>0?s/n:1,u=!1,d={...h};if(r||o)if(o)if(r){const t=2*n,e=s%t,i=Math.floor(s/t),o=e<n?1:-1;c=1===o?e/n:2-e/n,o!==l.direction&&(l.direction=o,1===l.direction&&d.onLoop&&d.onLoop(i)),i>l.loopCount&&(l.loopCount=i)}else{c%=1;const t=Math.floor(s/n);t>l.loopCount&&d.onLoop&&(d.onLoop(t),l.loopCount=t)}else r&&!o&&(c<=1?l.direction=1:c<=2?(c=2-c,l.direction=-1):(c=0,u=!0,l.direction=1));else c>=1&&(c=1,u=!0);!l.started&&d.onStart&&(d.onStart(),l.started=!0),u&&!l.completed&&d.onComplete&&(d.onComplete(),l.completed=!0);const f=a?a(c):c,p=(t+i-2*e)*f*f+2*(e-t)*f+t,g={...l,lastDirection:l.direction,completed:u||l.completed};return Ji.animationResult({value:p,direction:l.direction},c,o||r&&!u,u,g)}function Ni(t,e,i,s,n,o,r=!0,a=null){a||(a={currentX:t,currentY:e,targetX:t,targetY:e,isWaiting:!0,waitStartTime:0,moveStartTime:0,moveCount:0,direction:"idle"});const h=()=>Math.random();let l=a.isWaiting,c=a.currentX,u=a.currentY,d=a.direction;if(l){if(i-a.waitStartTime>=n){l=!1,a.moveStartTime=i,d=["up","down","left","right"][Math.floor(4*h())];let s=a.currentX,n=a.currentY;const r=o*(.2+.6*h());switch(d){case"up":n=a.currentY-r;break;case"down":n=a.currentY+r;break;case"left":s=a.currentX-r;break;case"right":s=a.currentX+r}Math.pow(s-t,2)+Math.pow(n-e,2)>o*o&&("up"===d||"down"===d?(n=e,d=a.currentY>e?"up":"down"):(s=t,d=a.currentX>t?"left":"right")),a.targetX=s,a.targetY=n,a.direction=d,a.moveCount++}}else{const t=(i-a.moveStartTime)/s;t>=1?(l=!0,a.waitStartTime=i,a.currentX=a.targetX,a.currentY=a.targetY,d="idle"):(c=a.currentX+(a.targetX-a.currentX)*t,u=a.currentY+(a.targetY-a.currentY)*t)}a.isWaiting=l,a.direction=d,l||(a.currentX=c,a.currentY=u);const f=s+n,p=i%f/f,g=Math.sqrt(Math.pow(c-t,2)+Math.pow(u-e,2));return Ji.animationResult({x:c,y:u,moving:!l,direction:d,distanceFromCenter:g},p,r,!1,a)}function Gi(t,e,i,s,n=!0,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=Ji._frame(i,s,n,null,a,h),f=o&&!n?Math.exp(-4*l):1;let p=t+e*Math.cos(2*c*Math.PI)*f;return r&&(p=t+r(((p-t)/(e*f)+1)/2)*e*f*2-e*f),Ji.animationResult({angle:p},l,n,u,d)}function Ui(t,e,i,s,n=!0,o=!1,r=null,a={}){let h,l=i/s,c="forward";if(n){const t=Math.floor(l);l%=1,t>0&&a.onLoop&&a.onLoop(t)}else l>1&&(l=1);if(l>0&&i<=s&&a.onStart&&a.onStart(),o)if(l<.5){const i=2*l;h=t+(e-t)*(r?r(i):i),c="forward"}else{const i=2*(l-.5);h=e-(e-t)*(r?r(i):i),c="return",l>=.5&&l<.51&&a.onYoyoTurn&&a.onYoyoTurn()}else{const i=r?r(l):l;h=t+(e-t)*(i<.5?2*i:2-2*i)}const u=!n&&l>=1;return u&&a.onComplete&&a.onComplete(),Ji.animationResult({value:h,phase:c},l,n,u)}function qi(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=Ji._frame(i,s,n,r,a,h,o);let f=0;f=n||o?o?Math.sin(c*Math.PI):Math.sin(Math.min(l,1)*Math.PI*.5):u?1:Math.sin(Math.min(l,1)*Math.PI*.5);const p=t-e*f;return Ji.animationResult({y:p},l,n,u,d)}function Zi(t,e,i,s,n,o,r,a,h=!1,l=null,c={},u=null){const{t:d,easedT:f,completed:p,state:g}=Ji._frame(r,a,h,l,c,u),m=Math.pow(1-f,o),y=f*Math.PI*2*n,x=f*Math.PI*2*n*1.3,v=m*i*(.6*Math.sin(y)+.3*Math.sin(2.5*y)+.1*Math.sin(5.6*y)),_=m*s*(.6*Math.cos(x)+.3*Math.cos(2.7*x)+.1*Math.cos(6.3*x));let w=t+v,b=e+_;if(f>.9){const i=(f-.9)/.1;w=t+v*(1-i),b=e+_*(1-i)}return Ji.animationResult({x:w,y:b,intensity:m},d,h,p,g)}function Vi(t,e,i,s,n,o,r,a,h=!1,l=!1,c=null,u={},d=null){d||(d={started:!1,loopCount:0,direction:1,lastDirection:1});let f=a>0?r/a:1,p=!1,g={...u};if(l||h)if(h)if(l){const t=2*a,e=r%t,i=Math.floor(r/t),s=e<a?1:-1;f=1===s?e/a:2-e/a,s!==d.direction&&(d.direction=s,1===d.direction&&g.onLoop&&g.onLoop(i)),i>d.loopCount&&(d.loopCount=i)}else{f%=1;const t=Math.floor(r/a);t>d.loopCount&&g.onLoop&&(g.onLoop(t),d.loopCount=t)}else l&&!h&&(f<=1?d.direction=1:f<=2?(f=2-f,d.direction=-1):(f=0,p=!0,d.direction=1));else f>=1&&(f=1,p=!0);!d.started&&g.onStart&&(g.onStart(),d.started=!0),p&&!d.completed&&g.onComplete&&(g.onComplete(),d.completed=!0);const m=c?c(f):f,y=Fi.lerp(i,s,m),x=n+m*o*Math.PI*2,v=t+y*Math.cos(x),_=e+y*Math.sin(x),w={...d,lastDirection:d.direction};return Ji.animationResult({x:v,y:_,radius:y,angle:x,direction:d.direction},f,h||l&&!p,p,w)}function $i(t,e,i,s,n=!1,o=!1,r={},a={}){if(s<=0)return this.animationResult({value:e,velocity:0,done:!0,phase:"complete"},1,!1,!0);let h,l,c,u=i/s,d="forward",f=0;n?(f=Math.floor(u),u%=1,f>0&&a.onLoop&&a.onLoop(f)):u>1&&(u=1),u>0&&i<=s&&a.onStart&&a.onStart(),o?u>=.5?(h=t,l=e,c=2*(u-.5),d="return",u>=.5&&u<.51&&a.onYoyoTurn&&a.onYoyoTurn()):(h=e,l=t,c=2*u,d="forward"):(h=e,l=t,c=u);const p=void 0!==r.stiffness?r.stiffness:.3,g=void 0!==r.damping?r.damping:.6,m=Math.max(.1,1/(1.5*g)),y=Math.max(.1,.8/(1.5*p+.5));let x;if(c<.99)x=ie.easeOutElastic(c,m,y);else{const t=(c-.99)/.01;x=ie.easeOutElastic(.99,m,y)*(1-t)+1*t}const v=Fi.lerp(l,h,x),_=Math.min(c+.01,1);let w;if(_<.99)w=ie.easeOutElastic(_,m,y);else{const t=(_-.99)/.01;w=ie.easeOutElastic(.99,m,y)*(1-t)+1*t}const b=(Fi.lerp(l,h,w)-v)/.01*s,M=!n&&u>=1;return M&&a.onComplete&&a.onComplete(),Ji.animationResult({value:v,velocity:b,delta:"forward"===d?e-v:t-v,done:M,phase:d},u,n,M)}function ji(t,e,i,s,n,o=!0,r=!0,a=null,h={},l=null){const{t:c,easedT:u,completed:d,state:f}=Ji._frame(s,n,o,a,h,l),p=(r?Math.sin(u*Math.PI*2):Math.sin(u*Math.PI))*i;return Ji.animationResult({angle:p},c,o,d,f)}function Ki(t,e,i,s,n,o=!0,r={},a=null){if(!i||!Array.isArray(i)||i.length<2)return console.warn("Patrol animation requires at least 2 waypoints"),Ji._createResult({x:0,y:0,moving:!1,direction:"idle",waypoint:0},0,!1,!0);a||(a={currentWaypoint:0,nextWaypoint:1,isWaiting:!0,waitStartTime:0,lastWaypointTime:0,lastWaypointReached:-1,completed:!1});let h=0;for(let t=0;t<i.length;t++){const e=(t+1)%i.length;if(!o&&t===i.length-1)break;const s=i[e][0]-i[t][0],n=i[e][1]-i[t][1];h+=Math.abs(s)+Math.abs(n)}const l=h/s+n*i.length;let c=e;c=o?e%l:Math.min(e,l);const u=c/l;let d,f,p,g=c,m=0,y=1,x=!0,v=0,_=0,w=!1;if(g<n)v=g/n,m=0,y=1,x=!0;else{g-=n;for(let t=0;t<i.length;t++){if(!o&&t===i.length-1){m=t,y=t,x=!0,v=1,w=!0;break}const e=(t+1)%i.length,h=i[e][0]-i[t][0],l=i[e][1]-i[t][1],c=(Math.abs(h)+Math.abs(l))/s;if(g<c){m=t,y=e,x=!1,_=g/c;break}if(g-=c,g<n){m=e,y=(e+1)%i.length,x=!0,v=g/n,a.lastWaypointReached!==m&&(r.onWaypointReached&&r.onWaypointReached(m),r.onWaitStart&&r.onWaitStart(m),a.lastWaypointReached=m);break}g-=n}}if(x||w)d=i[m][0],f=i[m][1],p="idle",!a.isWaiting&&x&&r.onWaitEnd&&r.onWaitEnd(m);else{const t=i[m],e=i[y],s=e[0]-t[0],n=e[1]-t[1],o=Math.abs(s)+Math.abs(n),r=Math.abs(s)/o;if(_<=r&&0!==s){const e=_/r;d=t[0]+s*e,f=t[1],p=s>0?"right":"left"}else{const i=(_-r)/(1-r);d=e[0],f=t[1]+n*i,p=n>0?"down":"up"}}return a.currentWaypoint=m,a.nextWaypoint=y,a.isWaiting=x,!a.completed&&w&&r.onPatrolComplete&&(r.onPatrolComplete(),a.completed=!0),Ji.animationResult({x:d,y:f,moving:!x,waiting:x,waitProgress:x?v:0,direction:p,waypoint:m,nextWaypoint:y},u,o,w,a)}class Ji{static animationResult(t,e,i,s=!1,n=null){return{...t,t:e,progress:e,loop:i,completed:s,state:n}}static _step(t,e,i,s={},n={started:!1,loopCount:0}){let o=e>0?t/e:1,r=!1;if(!(n=n||{started:!1,loopCount:0}).started&&s.onStart&&(s.onStart(),n.started=!0),i){o%=1;const i=Math.floor(t/e);i>n.loopCount&&s.onLoop&&(s.onLoop(i),n.loopCount=i)}else o>=1&&(o=1,r=!0,!n.completed&&s.onComplete&&(s.onComplete(),n.completed=!0));return{t:o,completed:r,state:n}}static _frame(t,e,i,s=null,n={},o=null){const{t:r,completed:a,state:h}=this._step(t,e,i,n,o);return{t:r,easedT:s?s(r):r,completed:a,state:h}}static oscillate(t,e,i,s,n=!0,o=null,r={},a=null){return Li(t,e,i,s,n,o,r,a)}static parabolic(t,e,i,s,n,o=!1,r=!1,a=null,h={},l=null){return Hi(t,e,i,s,n,o,r,a,h,l)}static float(t,e,i,s,n,o,r=!0,a=null,h={},l=null){return Xi(t,e,i,s,n,o,r,a,h,l)}static spring(t,e,i,s,n=!1,o=!1,r={},a={}){return $i(t,e,i,s,n,o,r,a)}static swing(t,e,i,s,n,o=!0,r=!0,a=null,h={},l=null){return ji(0,0,i,s,n,o,r,a,h,l)}static pendulum(t,e,i,s,n=!0,o=!1,r=null,a={},h=null){return Gi(t,e,i,s,n,o,r,a,h)}static pulse(t,e,i,s,n=!0,o=!1,r=null,a={}){return Ui(t,e,i,s,n,o,r,{})}static spiral(t,e,i,s,n,o,r,a,h=!1,l=!1,c=null,u={},d=null){return Vi(t,e,i,s,n,o,r,a,h,l,c,u,d)}static orbit(t,e,i,s,n,o,r,a=!0,h=!0,l=null,c={},u=null){return Wi(t,e,i,s,n,o,r,a,h,l,c,u)}static bezier(t,e,i,s,n,o,r=!1,a=!1,h=null,l={},c=null){return Qi(t,e,i,s,n,o,r,a,h,l,c)}static bounce(t,e,i,s,n,o=!1,r=null,a={},h=null){return Oi(t,e,i,s,n,o,r,a,h)}static shake(t,e,i,s,n,o,r,a,h=!1,l=null,c={},u=null){return Zi(t,e,i,s,n,o,r,a,h,l,c,u)}static follow(t,e=!1,i,s,n=!1,o=null,r={},a=null){return Yi(t,e,i,s,n,o,r,a)}static waypoint(t,e,i,s,n,o=!0,r={},a=null){return Ki(0,e,i,s,n,o,r,a)}static patrol(t,e,i,s,n,o,r=!0,a=null){return Ni(t,e,i,s,n,o,r,a)}static hop(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){return qi(t,e,i,s,n,o,r,a,h)}static group(t,e,i,s,n=!1,o=null,r={},a=null){a||(a={started:!1,loopCount:0,animationStates:Array(t.length).fill(null)});const{t:h,easedT:l,completed:c,state:u}=this._frame(i,s,n,o,r,a),d={};for(let a=0;a<t.length;a++){const h=t[a],l=[...e[a]];h===this.parabolic||h===this.oscillate||h===this.pulse?(l[3]=i,l[4]=s,l[5]=n,void 0===l[6]&&(l[6]=o)):h===this.spring?(l[2]=i,l[3]=s,l[4]=n):h===this.spiral||h===this.bezier?(l[6]=i,l[7]=s,l[8]=n,void 0===l[9]&&(l[9]=o)):h===this.orbit?(l[5]=i,l[6]=s,l[7]=n,void 0===l[9]&&(l[9]=o)):h===this.bounce||h===this.shake?(l[6]=i,l[7]=s,l[8]=n,void 0===l[9]&&(l[9]=o)):h===this.followPath&&(l[2]=i,l[3]=s,l[4]=n,void 0===l[5]&&(l[5]=o)),l.push(r),l.push(u.animationStates[a]);const c=h.apply(this,l);u.animationStates[a]=c.state,d[`anim${a}`]=c}return this.animationResult(d,h,n,c,u)}static sequence(t,e,i,s,n=!1,o=null,r={},a=null,h=null){if(!h){h={started:!1,loopCount:0,animationStates:Array(t.length).fill(null),currentAnim:0,animStartTimes:[0],totalDuration:0};let e=0;for(let t=0;t<i.length;t++)e+=i[t],t<i.length-1&&h.animStartTimes.push(e);h.totalDuration=e}let l=s;if(n&&h.totalDuration>0){l=s%h.totalDuration;const t=Math.floor(s/h.totalDuration);t>h.loopCount&&r.onLoop&&(r.onLoop(t),h.loopCount=t)}!h.started&&r.onStart&&(r.onStart(),h.started=!0);let c=0;for(let e=t.length-1;e>=0;e--)if(l>=h.animStartTimes[e]){c=e;break}h.currentAnim=c;const u=l-h.animStartTimes[c],d=i[c],f=t[c],p=[...e[c]];f===this.parabolic||f===this.oscillate||f===this.pulse?(p[3]=u,p[4]=d,p[5]=!1,o&&o[c]&&(p[6]=o[c])):f===this.spring?(p[2]=u,p[3]=d,p[4]=!1):f===this.spiral||f===this.bezier?(p[6]=u,p[7]=d,p[8]=!1,o&&o[c]&&(p[9]=o[c])):f===this.orbit?(p[5]=u,p[6]=d,p[7]=!1,o&&o[c]&&(p[9]=o[c])):f===this.bounce||f===this.shake?(p[6]=u,p[7]=d,p[8]=!1,o&&o[c]&&(p[9]=o[c])):f===this.followPath&&(p[2]=u,p[3]=d,p[4]=!1,o&&o[c]&&(p[5]=o[c]));const g=a&&a[c]?a[c]:{},m=f.apply(this,[...p,g,h.animationStates[c]]);h.animationStates[c]=m.state;const y=!n&&l>=h.totalDuration;return y&&!h.completed&&r.onComplete&&(r.onComplete(),h.completed=!0),this.animationResult({...m,currentAnim:c,totalAnimations:t.length,sequenceProgress:Math.min(l/h.totalDuration,1)},l/h.totalDuration,n,y,h)}}function Qi(t,e,i,s,n,o,r=!1,a=!1,h=null,l={},c=null){if(o<=0)return Ji.animationResult({x:s[0],y:s[1],phase:"complete"},1,!1,!0);let u=n/o,d="forward",f=0;r?(f=Math.floor(u),u%=1,f>0&&l.onLoop&&l.onLoop(f)):u>1&&(u=1),u>0&&n<=o&&l.onStart&&l.onStart();let p=h?h(u):u;a&&(u>=.5?(p=1-2*(u-.5),d="return",u>=.5&&u<.51&&l.onYoyoTurn&&l.onYoyoTurn()):(p=2*u,d="forward"),p=h?h(p):p);const g=3*(e[0]-t[0]),m=3*(i[0]-e[0])-g,y=s[0]-t[0]-g-m,x=3*(e[1]-t[1]),v=3*(i[1]-e[1])-x,_=s[1]-t[1]-x-v,w=y*Math.pow(p,3)+m*Math.pow(p,2)+g*p+t[0],b=_*Math.pow(p,3)+v*Math.pow(p,2)+x*p+t[1],M=!r&&u>=1;return M&&l.onComplete&&l.onComplete(),Ji.animationResult({x:w,y:b,phase:d},u,r,M,c)}class ts{constructor(t,e,i,s,n={}){this.target=t,this.toProps={...e},this.duration=i,this.easingFn=s||ie.easeOutQuad,this.delay=n.delay||0,this.onStart=n.onStart||null,this.onComplete=n.onComplete||null,this.onUpdate=n.onUpdate||null,this._elapsed=0,this._started=!1,this._finished=!1,this._startProps={};for(const t in this.toProps)t in this.target&&(this._startProps[t]=this.target[t])}static to(t,e,i,s,n){const o=new ts(t,e,i,s,n);return ts._active.push(o),o}update(t){if(this._finished)return;if(this._elapsed+=t,this._elapsed<this.delay)return;const e=this._elapsed-this.delay,i=Math.min(e/this.duration,1);!this._started&&i>0&&(this._started=!0,this.onStart&&this.onStart());const s=this.easingFn(i);for(const t in this._startProps){const e=this._startProps[t],i=this.toProps[t];this.target[t]=Fi.lerp(e,i,s)}this.onUpdate&&this.onUpdate(),i>=1&&(this._finished=!0,this.onComplete&&this.onComplete())}static updateAll(t){for(const e of ts._active)e.update(t);ts._active=ts._active.filter(t=>!t._finished)}static killTarget(t){ts._active=ts._active.filter(e=>e.target!==t)}static killAll(){ts._active=[]}}class es extends Me{constructor(t){super(),this.game=t,this._collection=new Ct,this._collection._owner=this,["inputdown","inputup","inputmove","click"].forEach(t=>{this.game.events.on(t,e=>{this.dispatchInputEvent(t,e)})})}_hoverObject(t,e){if(!t.interactive||!t._hitTest)return;const i=t._hitTest(e.x,e.y);i&&!t._hovered?(t._hovered=!0,t.events.emit("mouseover",e)):!i&&t._hovered&&(t._hovered=!1,t.events.emit("mouseout",e))}_hoverScene(t,e){if(t.children&&t.children.length>0)for(let i=t.children.length-1;i>=0;i--){const s=t.children[i];s instanceof Di?this._hoverScene(s,e):this._hoverObject(s,e)}this._hoverObject(t,e)}dispatchInputEvent(t,e){var i;for(let s=this.gameObjects.length-1;s>=0;s--){const n=this.gameObjects[s];if(n instanceof Di){if(this._dispatchToScene(n,t,e))break}else if(n.interactive&&(null==(i=n._hitTest)?void 0:i.call(n,e.x,e.y))){n.events.emit(t,e);break}}"inputmove"===t&&this._dispatchHover(e)}_dispatchHover(t){for(let e=this.gameObjects.length-1;e>=0;e--){const i=this.gameObjects[e];i instanceof Di?this._hoverScene(i,t):this._hoverObject(i,t)}}_dispatchToScene(t,e,i){var s,n;for(let n=t.children.length-1;n>=0;n--){const o=t.children[n];if(o instanceof Di){if(this._dispatchToScene(o,e,i))return!0}else if(o.interactive&&(null==(s=o._hitTest)?void 0:s.call(o,i.x,i.y)))return o.events.emit(e,i),!0}return!(!t.interactive||!(null==(n=t._hitTest)?void 0:n.call(t,i.x,i.y))||(t.events.emit(e,i),0))}add(t){t.parent=this.game;const e=this._collection.add(t);return e.init&&e.init(),e}remove(t){null!=t?this._collection.remove(t):this.logger.warn("Cannot remove undefined or null object",t)}bringToFront(t){return this._collection.bringToFront(t)}sendToBack(t){return this._collection.sendToBack(t)}bringForward(t){return this._collection.bringForward(t)}sendBackward(t){return this._collection.sendBackward(t)}clear(){return this._collection.clear()}get gameObjects(){return this._collection.children}update(t){this.logger.groupCollapsed("Pipeline.update"),this._collection.children.filter(t=>t.active).forEach(e=>e.update(t)),ts.updateAll(t),this.logger.groupEnd()}render(){this.logger.groupCollapsed("Pipeline.render"),this._collection.getSortedChildren().filter(t=>t.visible).filter(t=>t.active).forEach(t=>t.render()),this.logger.groupEnd()}}class is{constructor(t){bt(this,T,0),bt(this,R,0),this.canvas=t,this.ctx=t.getContext("2d"),this.events=new _i,this._cursor=null,this.lastTime=0,this.dt=0,this.running=!1,this._frame=0,this.pipeline=new es(this),Be.init(this.ctx),this.targetFPS=60,this._frameInterval=1e3/this.targetFPS,this._accumulator=0,this._pauseOnBlur=!1,this._isPaused=!1,this._init=!1,this.initLogging()}setFPS(t){this.targetFPS=t,this._frameInterval=1e3/t}init(){this.initIO(),this.initMotion(),this._init=!0,this.logger.log("[Game] Initialized")}initMouse(){Mi.init(this)}initTouch(){Ti.init(this)}initInput(){wi.init(this)}initKeyboard(){Ci.init(this)}initIO(){this.initMouse(),this.initTouch(),this.initInput(),this.initKeyboard()}initMotion(){ts._active=[]}initLogging(){this.logger=new be("Game"),be.setOutput(console),be.disableAll(),be.disable(),be.setLevel(be.INFO),this.logger.groupCollapsed("Initializing Game...")}enableLogging(){be.enable()}disableLogging(){be.disableAll(),be.disable()}markBoundsDirty(){this._boundsDirty=!0}get boundsDirty(){return this._boundsDirty}set boundsDirty(t){this._boundsDirty=t}enableFluidSize(t=window,e={}){const{top:i=0,right:s=0,bottom:n=0,left:o=0}=e;if(t===window){const t=()=>{var t;this.canvas.width=window.innerWidth-o-s,this.canvas.height=window.innerHeight-i-n,wt(this,T)===this.canvas.width&&wt(this,R)===this.canvas.height||(this.markBoundsDirty(),null==(t=this.onResize)||t.call(this)),Mt(this,T,this.canvas.width),Mt(this,R,this.canvas.height)};t(),window.addEventListener("resize",t),this._fluidResizeCleanup=()=>{window.removeEventListener("resize",t)}}else{if(!("ResizeObserver"in window))return void console.warn("ResizeObserver not supported in this browser.");const e=()=>{const e=t.getBoundingClientRect();this.canvas.width=e.width-o-s,this.canvas.height=e.height-i-n},r=new ResizeObserver(()=>{e()});r.observe(t),e(),this._fluidResizeCleanup=()=>r.disconnect()}}disableFluidSize(){this._fluidResizeCleanup&&(this._fluidResizeCleanup(),this._fluidResizeCleanup=null)}start(){if(this.logger.groupCollapsed("[Game] Starting..."),this.init(),!this._init)throw new Error("Game not initialized. Did you call init()? Remember to call super.init() in your subclass.");this.running=!0,this.loop=this.loop.bind(this),requestAnimationFrame(this.loop),this.logger.log("[Game] Started"),this.logger.groupEnd()}stop(){this.running=!1,this.logger.log("[Game] Stopped")}restart(){this.pipeline.clear(),this.init(),this.start(),this.logger.log("[Game] Restarted")}loop(t){if(!this.running)return;const e=t-this.lastTime;if(this.lastTime=t,this._accumulator+=e,this.actualFps=1e3/e,this._accumulator>=this._frameInterval){const t=this._frameInterval/1e3;this.dt=t,this._frame++,this.logger.groupCollapsed(`Frame #${this._frame}`),this.logger.time("render time"),this.update(t),this.render(),this.logger.timeEnd("render time"),this.logger.groupEnd(),this._accumulator-=this._frameInterval}this.boundsDirty&&(this.boundsDirty=!1),requestAnimationFrame(this.loop)}update(t){this.pipeline.update(t)}render(){Be.setContext(this.ctx),this.running&&this.clear(),this.pipeline.render()}clear(){Be.clear()}get width(){return this.canvas.width}get height(){return this.canvas.height}set backgroundColor(t){this.canvas.style.backgroundColor=t}set cursor(t){this._cursor&&(this._cursor.destroy(),this.pipeline.remove(this._cursor)),this._cursor=t,this._cursor.activate(),this.pipeline.add(t)}get cursor(){return this._cursor}resetCursor(){this._cursor&&(this._cursor.destroy(),this.pipeline.remove(this._cursor),this._cursor=null)}enablePauseOnBlur(t){this._pauseOnBlur=t,t?window.addEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1):window.removeEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1)}_handleVisibilityChange(){this.logger.log("Visibility change detected"),document.hidden?this._pauseOnBlur&&this.running&&(this._isPaused=!0,this.stop(),this.logger.log("Paused due to tab visibility change")):this._isPaused&&(this._isPaused=!1,this.start(),this.logger.log("Resumed after tab visibility change"))}}T=new WeakMap,R=new WeakMap;const ss={colors:{neonGreen:"#0f0",terminalGreen:"#16F529",cyanAccent:"#0ff",darkBg:"rgba(0, 0, 0, 0.85)",darkerBg:"rgba(0, 0, 0, 0.92)",hoverBg:"#0f0",pressedBg:"#0c0",activeBg:"rgba(0, 255, 0, 0.15)",lightText:"#0f0",darkText:"#000",dimText:"rgba(0, 255, 0, 0.7)",subtleBorder:"rgba(0, 255, 0, 0.4)",activeBorder:"#0f0",glowBorder:"rgba(0, 255, 0, 0.5)"},fonts:{primary:"monospace",small:"11px monospace",medium:"14px monospace",large:"18px monospace",heading:"bold 24px monospace"},spacing:{xs:4,sm:8,md:12,lg:16,xl:24},button:{default:{bg:"rgba(0, 0, 0, 0.85)",stroke:"rgba(0, 255, 0, 0.4)",text:"#0f0"},hover:{bg:"#0f0",stroke:"#0f0",text:"#000"},pressed:{bg:"#0c0",stroke:"#0f0",text:"#000"},active:{bg:"rgba(0, 255, 0, 0.15)",stroke:"#0f0",text:"#0f0"}},tooltip:{bg:"rgba(0, 0, 0, 0.92)",border:"rgba(0, 255, 0, 0.5)",text:"#0f0"}};class ns extends Pi{constructor(t,e={}){super(t,e);const{x:i=0,y:s=0,width:n=120,height:o=40,text:r="Button",font:a="14px monospace",textColor:h="#000",textAlign:l="center",textBaseline:c="middle",shape:u=null,label:d=null,onClick:f=null,onHover:p=null,onPressed:g=null,onRelease:m=null,padding:y=10,colorDefaultBg:x=ss.button.default.bg,colorDefaultStroke:v=ss.button.default.stroke,colorDefaultText:_=ss.button.default.text,colorHoverBg:w=ss.button.hover.bg,colorHoverStroke:b=ss.button.hover.stroke,colorHoverText:M=ss.button.hover.text,colorPressedBg:k=ss.button.pressed.bg,colorPressedStroke:C=ss.button.pressed.stroke,colorPressedText:S=ss.button.pressed.text}=e;this.x=i,this.y=s,this.width=n,this.height=o,this.padding=y,this.textAlign=l,this.textBaseline=c,this.initColorScheme({colorDefaultBg:x,colorDefaultStroke:v,colorDefaultText:_,colorHoverBg:w,colorHoverStroke:b,colorHoverText:M,colorPressedBg:k,colorPressedStroke:C,colorPressedText:S}),this.initBackground(u),this.initLabel(r,a,h,d),this.initGroup(),this.initEvents(f,p,g,m),this.setState("default")}initColorScheme(t){this.colors={default:{bg:t.colorDefaultBg,stroke:t.colorDefaultStroke,text:t.colorDefaultText},hover:{bg:t.colorHoverBg,stroke:t.colorHoverStroke,text:t.colorHoverText},pressed:{bg:t.colorPressedBg,stroke:t.colorPressedStroke,text:t.colorPressedText}}}initBackground(t){this.bg=t??new Ve({width:this.width,height:this.height,color:this.colors.default.bg,stroke:this.colors.default.stroke,lineWidth:2})}initLabel(t,e,i,s){this.label=s??new xi(t,{font:e,color:i,align:this.textAlign,baseline:this.textBaseline}),this.alignText()}alignText(){if(!this.label)return;const t=this.width/2,e=this.height/2;switch(this.textAlign){case"left":this.label.x=-t+this.padding;break;case"right":this.label.x=t-this.padding;break;default:this.label.x=0}switch(this.textBaseline){case"top":this.label.y=-e+this.padding;break;case"bottom":this.label.y=e-this.padding;break;default:this.label.y=0}}initGroup(){this.group=new Ge,this.group.add(this.bg),this.group.add(this.label)}initEvents(t,e,i,s){this.interactive=!0,this.onHover=e,this.onPressed=i,this.onRelease=s,this.on("mouseover",this.setState.bind(this,"hover")),this.on("mouseout",this.setState.bind(this,"default")),this.on("inputdown",this.setState.bind(this,"pressed")),this.on("inputup",()=>{"pressed"===this.state&&"function"==typeof t&&t(),this.setState("hover")})}setState(t){var e,i,s;if(this.state!==t)switch(this.state=t,t){case"default":this.game.cursor&&setTimeout(()=>{this.game.cursor.activate()},0),this.bg.color=this.colors.default.bg,this.bg.stroke=this.colors.default.stroke,this.label.color=this.colors.default.text,this.game.canvas.style.cursor="default",null==(e=this.onRelease)||e.call(this);break;case"hover":this.game.cursor&&this.game.cursor.deactivate(),this.bg.color=this.colors.hover.bg,this.bg.stroke=this.colors.hover.stroke,this.label.color=this.colors.hover.text,this.game.canvas.style.cursor="pointer",null==(i=this.onHover)||i.call(this);break;case"pressed":this.game.cursor&&this.game.cursor.deactivate(),this.bg.color=this.colors.pressed.bg,this.bg.stroke=this.colors.pressed.stroke,this.label.color=this.colors.pressed.text,this.game.canvas.style.cursor="pointer",null==(s=this.onPressed)||s.call(this)}}update(t){super.update(t),this._boundsDirty&&this.alignText()}get text(){return this.label.text}set text(t){this.label.text=t,this._boundsDirty=!0}setTextAlign(t){this.textAlign=t,this.label.align=t,this._boundsDirty=!0}setTextBaseline(t){this.textBaseline=t,this.label.baseline=t,this._boundsDirty=!0}setFont(t){this.label.font=t,this._boundsDirty=!0}resize(t,e){this.width=t,this.height=e,this.bg.width=t,this.bg.height=e,this._boundsDirty=!0}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}draw(){super.draw(),this.group.render()}}class os{constructor(){this.x=0,this.y=0,this.z=0,this.vx=0,this.vy=0,this.vz=0,this.size=1,this.color={r:255,g:255,b:255,a:1},this.shape="circle",this.age=0,this.lifetime=1,this.alive=!0,this.custom={}}reset(){this.x=0,this.y=0,this.z=0,this.vx=0,this.vy=0,this.vz=0,this.size=1,this.color.r=255,this.color.g=255,this.color.b=255,this.color.a=1,this.shape="circle",this.age=0,this.lifetime=1,this.alive=!0;for(const t in this.custom)delete this.custom[t]}get progress(){return this.lifetime>0?this.age/this.lifetime:1}}class rs{constructor(t={}){this.rate=t.rate??10,this.position={x:0,y:0,z:0,...t.position},this.spread={x:0,y:0,z:0,...t.spread},this.velocity={x:0,y:0,z:0,...t.velocity},this.velocitySpread={x:0,y:0,z:0,...t.velocitySpread},this.lifetime={min:1,max:2,...t.lifetime},this.size={min:1,max:1,...t.size},this.color={r:255,g:255,b:255,a:1,...t.color},this.shape=t.shape??"circle",this.active=!1!==t.active,this._timer=0}_spread(t){return 2*(Math.random()-.5)*t}_range(t,e){return t+Math.random()*(e-t)}emit(t){t.x=this.position.x+this._spread(this.spread.x),t.y=this.position.y+this._spread(this.spread.y),t.z=this.position.z+this._spread(this.spread.z),t.vx=this.velocity.x+this._spread(this.velocitySpread.x),t.vy=this.velocity.y+this._spread(this.velocitySpread.y),t.vz=this.velocity.z+this._spread(this.velocitySpread.z),t.lifetime=this._range(this.lifetime.min,this.lifetime.max),t.age=0,t.alive=!0,t.size=this._range(this.size.min,this.size.max),t.color.r=this.color.r,t.color.g=this.color.g,t.color.b=this.color.b,t.color.a=this.color.a,t.shape=this.shape}update(t){if(!this.active||this.rate<=0)return 0;this._timer+=t;const e=1/this.rate;let i=0;for(;this._timer>=e;)this._timer-=e,i++;return i}reset(){this._timer=0}}const as={velocity:(t,e)=>{t.x+=t.vx*e,t.y+=t.vy*e,t.z+=t.vz*e},lifetime:(t,e)=>{t.age+=e,t.age>=t.lifetime&&(t.alive=!1)},gravity:(t=200)=>(e,i)=>{e.vy+=t*i},rise:(t=100)=>(e,i)=>{e.vy-=t*i},damping:(t=.98)=>(e,i)=>{e.vx*=t,e.vy*=t,e.vz*=t},fadeOut:(t,e)=>{t.color.a=Math.max(0,1-t.progress)},fadeInOut:(t,e)=>{const i=t.progress;t.color.a=i<.5?2*i:2*(1-i)},shrink:(t=0)=>(e,i)=>{void 0===e.custom._initialSize&&(e.custom._initialSize=e.size),e.size=e.custom._initialSize*(1-e.progress*(1-t))},grow:(t=2)=>(e,i)=>{void 0===e.custom._initialSize&&(e.custom._initialSize=e.size),e.size=e.custom._initialSize*(1+e.progress*(t-1))},colorOverLife:(t,e)=>(i,s)=>{const n=i.progress;i.color.r=Math.floor(t.r+(e.r-t.r)*n),i.color.g=Math.floor(t.g+(e.g-t.g)*n),i.color.b=Math.floor(t.b+(e.b-t.b)*n)},wobble:(t=10)=>(e,i)=>{e.vx+=(Math.random()-.5)*t*i,e.vy+=(Math.random()-.5)*t*i},bounds:(t,e=.8)=>(i,s)=>{i.x<t.left?(i.x=t.left,i.vx=Math.abs(i.vx)*e):i.x>t.right&&(i.x=t.right,i.vx=-Math.abs(i.vx)*e),i.y<t.top?(i.y=t.top,i.vy=Math.abs(i.vy)*e):i.y>t.bottom&&(i.y=t.bottom,i.vy=-Math.abs(i.vy)*e)},attract:(t,e=100)=>(i,s)=>{const n=t.x-i.x,o=t.y-i.y,r=(t.z??0)-i.z,a=Math.sqrt(n*n+o*o+r*r);if(a>1){const t=e*s/a;i.vx+=n*t,i.vy+=o*t,i.vz+=r*t}}};class hs extends Pi{constructor(t,e={}){super(t,e),this.particles=[],this.pool=[],this.maxParticles=e.maxParticles??5e3,this.emitters=new Map,this.camera=e.camera??null,this.depthSort=e.depthSort??!1,this.updaters=e.updaters??[as.velocity,as.lifetime],this.blendMode=e.blendMode??"source-over",this.worldSpace=e.worldSpace??!1,this._particleCount=0}addEmitter(t,e){return this.emitters.set(t,e),this}removeEmitter(t){return this.emitters.delete(t),this}getEmitter(t){return this.emitters.get(t)}acquire(){return this.pool.length>0?this.pool.pop():new os}release(t){t.reset(),this.pool.push(t)}emit(t,e){for(let i=0;i<t&&this.particles.length<this.maxParticles;i++){const t=this.acquire();e.emit(t),this.particles.push(t)}}burst(t,e){const i="string"==typeof e?this.emitters.get(e):e;i&&this.emit(t,i)}update(t){super.update(t);for(const e of this.emitters.values())if(e.active){const i=e.update(t);this.emit(i,e)}for(let e=this.particles.length-1;e>=0;e--){const i=this.particles[e];for(const e of this.updaters)e(i,t,this);i.alive||(this.release(i),this.particles.splice(e,1))}this._particleCount=this.particles.length}render(){super.render(),0!==this.particles.length&&(this.camera&&this.depthSort?this.renderWithDepthSort():this.renderSimple())}renderSimple(){Be.useCtx(t=>{t.globalCompositeOperation=this.blendMode;for(const e of this.particles)this.drawParticle(t,e,e.x,e.y,1);t.globalCompositeOperation="source-over"})}renderWithDepthSort(){const t=[];for(const e of this.particles){const i=this.camera.project(e.x,e.y,e.z);i.z<10-this.camera.perspective||t.push({p:e,x:i.x,y:i.y,z:i.z,scale:i.scale})}t.sort((t,e)=>e.z-t.z),Be.useCtx(e=>{e.globalCompositeOperation=this.blendMode;const i=this.parent&&"Scene3D"===this.parent.constructor.name;this.worldSpace||i||(e.save(),e.translate(this.game.width/2,this.game.height/2));for(const i of t)this.drawParticle(e,i.p,i.x,i.y,i.scale);this.worldSpace||i||e.restore(),e.globalCompositeOperation="source-over"})}drawParticle(t,e,i,s,n){const{r:o,g:r,b:a,a:h}=e.color,l=e.size*n;if(l<.5||h<=0)return;t.fillStyle=`rgba(${Math.floor(o)},${Math.floor(r)},${Math.floor(a)},${h})`;const c=e.shape??"circle",u=l/2;t.beginPath(),"circle"===c?t.arc(i,s,u,0,2*Math.PI):"square"===c?t.rect(i-u,s-u,l,l):"triangle"===c&&(t.moveTo(i,s-u),t.lineTo(i+u,s+u),t.lineTo(i-u,s+u),t.closePath()),t.fill()}clear(){for(const t of this.particles)this.release(t);this.particles=[],this._particleCount=0}get particleCount(){return this._particleCount}get poolSize(){return this.pool.length}}class ls{static rectRect(t,e){return t.x<e.x+e.width&&t.x+t.width>e.x&&t.y<e.y+e.height&&t.y+t.height>e.y}static intersects(t,e){return ls.rectRect(t,e)}static pointRect(t,e,i){return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}static circleCircle(t,e){const i=t.x-e.x,s=t.y-e.y,n=i*i+s*s,o=t.radius+e.radius;return n<=o*o}static getCircleOverlap(t,e){const i=t.x-e.x,s=t.y-e.y,n=i*i+s*s,o=t.radius+e.radius;if(n>=o*o||n<1e-4)return null;const r=Math.sqrt(n),a=1/r;return{overlap:o-r,nx:i*a,ny:s*a,dist:r}}static applyCircleSeparation(t,e,i={}){const s=i.strength??5e3,n=i.useSizeAsRadius??!0,o=t.length;for(let i=0;i<o;i++){const r=t[i],a=n?.5*r.size:r.radius??10;for(let h=i+1;h<o;h++){const o=t[h],l=n?.5*o.size:o.radius??10,c=ls.getCircleOverlap({x:r.x,y:r.y,radius:a},{x:o.x,y:o.y,radius:l});if(c){const t=s*(c.overlap/(a+l)),n=c.nx*t,o=c.ny*t;e[i].x+=n,e[i].y+=o,e[h].x-=n,e[h].y-=o}}}}static pointCircle(t,e,i){const s=t-i.x,n=e-i.y;return s*s+n*n<=i.radius*i.radius}static circleRect(t,e){const i=Math.max(e.x,Math.min(t.x,e.x+e.width)),s=Math.max(e.y,Math.min(t.y,e.y+e.height)),n=t.x-i,o=t.y-s;return n*n+o*o<=t.radius*t.radius}static lineRect(t,e,i,s,n,o=0){const r=n.x-o/2,a=n.y-o/2,h=n.width+o,l=n.height+o;if(ls.pointRect(t,e,{x:r,y:a,width:h,height:l})||ls.pointRect(i,s,{x:r,y:a,width:h,height:l}))return!0;const c=ls.lineLine(t,e,i,s,r,a,r,a+l),u=ls.lineLine(t,e,i,s,r+h,a,r+h,a+l),d=ls.lineLine(t,e,i,s,r,a,r+h,a),f=ls.lineLine(t,e,i,s,r,a+l,r+h,a+l);return c||u||d||f}static lineLine(t,e,i,s,n,o,r,a){const h=(a-o)*(i-t)-(r-n)*(s-e);if(0===h)return!1;const l=((r-n)*(e-o)-(a-o)*(t-n))/h,c=((i-t)*(e-o)-(s-e)*(t-n))/h;return l>=0&&l<=1&&c>=0&&c<=1}static segmentsRect(t,e,i=0){for(const s of t)if(ls.lineRect(s.x1,s.y1,s.x2,s.y2,e,i))return!0;return!1}static getOverlap(t,e){return ls.rectRect(t,e)?{x:Math.min(t.x+t.width,e.x+e.width)-Math.max(t.x,e.x),y:Math.min(t.y+t.height,e.y+e.height)-Math.max(t.y,e.y)}:null}static getMTV(t,e){const i=ls.getOverlap(t,e);if(!i)return null;const s=t.x+t.width/2,n=t.y+t.height/2,o=e.x+e.width/2,r=e.y+e.height/2,a=s<o?-i.x:i.x,h=n<r?-i.y:i.y;return Math.abs(i.x)<Math.abs(i.y)?{x:a,y:0}:{x:0,y:h}}static sweep(t,e,i,s){const n=s.x-t.width/2,o=s.y-t.height/2,r=s.width+t.width,a=s.height+t.height,h=t.x+t.width/2,l=t.y+t.height/2;let c,u,d,f;0!==e?(c=(n-h)/e,u=(n+r-h)/e,c>u&&([c,u]=[u,c])):(c=h>=n&&h<=n+r?-1/0:1/0,u=h>=n&&h<=n+r?1/0:-1/0),0!==i?(d=(o-l)/i,f=(o+a-l)/i,d>f&&([d,f]=[f,d])):(d=l>=o&&l<=o+a?-1/0:1/0,f=l>=o&&l<=o+a?1/0:-1/0);const p=Math.max(c,d);if(p>Math.min(u,f)||p<0||p>1)return null;let g=0,m=0;return c>d?g=e>0?-1:1:m=i>0?-1:1,{time:p,normalX:g,normalY:m}}}const cs={maxParticles:500,particleSize:20,particleColor:{r:100,g:180,b:255,a:.9},physics:"liquid",gravity:200,damping:.98,bounce:.3,maxSpeed:400,fluid:{smoothingRadius:null,restDensity:3,pressureStiffness:80,nearPressureStiffness:3,viscosity:.005,maxForce:5e3},gas:{interactionRadius:null,pressure:150,diffusion:.15,drag:.02,turbulence:50,buoyancy:300,sinking:200,repulsion:300},heat:{enabled:!1,heatZone:.88,coolZone:.25,rate:.03,heatMultiplier:1.5,coolMultiplier:2,middleMultiplier:.005,transitionWidth:.08,neutralTemp:.5,deadZone:.15,buoyancy:300,sinking:200},collision:{enabled:!0,strength:5e3},boundary:{enabled:!0,strength:4e3,radius:null},shake:{enabled:!0,sensitivity:2,maxForce:2500,damping:.8},blendMode:"source-over"};class us extends hs{constructor(t,e={}){var i,s,n,o;const r=us._mergeConfig(e),a=(null==(i=e.bounds)?void 0:i.x)??0,h=(null==(s=e.bounds)?void 0:s.y)??0,l=e.width??(null==(n=e.bounds)?void 0:n.w)??0,c=e.height??(null==(o=e.bounds)?void 0:o.h)??0;super(t,{maxParticles:r.maxParticles,blendMode:r.blendMode,updaters:[as.velocity,as.lifetime],x:e.x??a+l/2,y:e.y??h+c/2,width:l,height:c,debug:e.debug??!1,debugColor:e.debugColor??"#0f0"}),this.config=r,this.bounds=e.bounds||null,this.gravityEnabled=e.gravityEnabled??!0,this.modeMix="gas"===r.physics?1:0,this._targetMode=this.modeMix,this._modeLerpSpeed=5,this._forces=[],this._shake={lastX:window.screenX,lastY:window.screenY,velocityX:0,velocityY:0,forceX:0,forceY:0},this._createEmitter()}static _mergeConfig(t){const e={...cs,...t},i=e.particleSize;return e.fluid={...cs.fluid,...t.fluid},e.gas={...cs.gas,...t.gas},e.heat={...cs.heat,...t.heat},e.collision={...cs.collision,...t.collision},e.boundary={...cs.boundary,...t.boundary},e.shake={...cs.shake,...t.shake},null===e.fluid.smoothingRadius&&(e.fluid.smoothingRadius=2*i),null===e.gas.interactionRadius&&(e.gas.interactionRadius=4*i),null===e.boundary.radius&&(e.boundary.radius=.8*i),e}_createEmitter(){const{particleSize:t,particleColor:e}=this.config,i=new rs({rate:0,position:{x:0,y:0},spread:{x:100,y:100},velocity:{x:0,y:0},velocitySpread:{x:10,y:10},size:{min:t,max:t+2},lifetime:{min:99999,max:99999},color:e,shape:"circle"});this.addEmitter("fluid",i)}spawn(t,e={}){const i=this.emitters.get("fluid");if(!i)return;let s=e.x,n=e.y,o=e.spreadX??100,r=e.spreadY??100;this.bounds&&void 0===s&&(s=this.bounds.x+this.bounds.w/2,n=this.bounds.y+.6*this.bounds.h,o=Math.min(.8*this.bounds.w,400),r=Math.min(.5*this.bounds.h,250)),i.position.x=s??this.game.width/2,i.position.y=n??this.game.height/2,i.spread.x=o,i.spread.y=r,this.burst(t,"fluid");for(const t of this.particles)t.custom.initialized||(t.custom.initialized=!0,t.custom.mass=1,t.custom.temperature=.5,t.vx=20*(Math.random()-.5),t.vy=20*(Math.random()-.5))}setBounds(t){this.bounds=t,this.x=t.x+t.w/2,this.y=t.y+t.h/2,this.width=t.w,this.height=t.h}update(t){t=Math.min(t,.033),this.modeMix=ie.lerp(this.modeMix,this._targetMode,t*this._modeLerpSpeed);const e=this.particles;0!==e.length?(this._ensureForceArray(e.length),this._resetForces(),this._computePhysicsForces(e),this.modeMix>.5&&((this.config.heat.enabled||this.modeMix>.95)&&(this._updateTemperatures(e),this._applyThermalForces(e)),this.modeMix>.95&&this._applyGasRepulsion(e)),this.config.collision.enabled&&ls.applyCircleSeparation(e,this._forces,{strength:this.config.collision.strength,useSizeAsRadius:!0}),this.bounds&&this.config.boundary.enabled&&this._applyBoundaryForces(e),this.config.shake.enabled&&(this._updateShakeForces(t),this._applyShakeForces()),this._integrateForces(e,t),super.update(t),this.bounds&&this._clampBounds(e)):super.update(t)}_ensureForceArray(t){for(;this._forces.length<t;)this._forces.push({x:0,y:0})}_resetForces(){for(let t=0;t<this._forces.length;t++)this._forces[t].x=0,this._forces[t].y=0}_computePhysicsForces(t){const{fluid:e,gas:i}=this.config;if(this.modeMix<.01){const i=pe(t,{kernel:{smoothingRadius:e.smoothingRadius},fluid:{restDensity:e.restDensity,pressureStiffness:e.pressureStiffness,nearPressureStiffness:e.nearPressureStiffness,viscosity:e.viscosity,maxForce:e.maxForce}});this._accumulateForces(i.forces)}else if(this.modeMix>.95){const e=ge(t,{gas:{interactionRadius:i.interactionRadius,pressure:i.pressure,diffusion:i.diffusion,drag:i.drag,turbulence:i.turbulence,buoyancy:i.buoyancy}});this._accumulateForces(e.forces)}else{const s=pe(t,{kernel:{smoothingRadius:e.smoothingRadius},fluid:e}),n=ge(t,{gas:i}),o=me(s.forces,n.forces,this.modeMix);this._accumulateForces(o)}}_accumulateForces(t){const e=Math.min(t.length,this._forces.length);for(let i=0;i<e;i++)this._forces[i].x+=t[i].x,this._forces[i].y+=t[i].y}_applyBoundaryForces(t){const{x:e,y:i,w:s,h:n}=this.bounds,{radius:o,strength:r}=this.config.boundary,a=e,h=e+s,l=i,c=i+n;for(let e=0;e<t.length;e++){const i=t[e],s=.5*i.size,n=i.x-s-a,u=h-i.x-s,d=i.y-s-l,f=c-i.y-s;if(n<o){const t=Math.max(0,1-n/o);this._forces[e].x+=r*t*t}if(u<o){const t=Math.max(0,1-u/o);this._forces[e].x-=r*t*t}if(d<o){const t=Math.max(0,1-d/o);this._forces[e].y+=r*t*t}if(f<o){const t=Math.max(0,1-f/o);this._forces[e].y-=r*t*t}}}_updateTemperatures(t){if(!this.bounds)return;const{heat:e}=this.config,i=this.bounds.y,s=this.bounds.h;for(let n=0;n<t.length;n++){const o=t[n],r=o.custom.temperature??e.neutralTemp,a=ne(Math.min(1,Math.max(0,(o.y-i)/s)),r,e);o.custom.temperature=Math.min(1,Math.max(0,a))}}_applyThermalForces(t){const{heat:e}=this.config,i=e.neutralTemp,s=e.deadZone;for(let n=0;n<t.length;n++){const o=(t[n].custom.temperature??i)-i;if(Math.abs(o)>s){let t=0;t=o>0?-(o-s)*e.buoyancy*2:(-o-s)*e.sinking*2,this._forces[n].y+=t}}}_applyGasRepulsion(t){const{gas:e}=this.config,i=e.interactionRadius,s=i*i,n=e.repulsion||200,o=t.length;for(let e=0;e<o;e++){const r=t[e];for(let a=e+1;a<o;a++){const o=t[a],h=r.x-o.x,l=r.y-o.y,c=h*h+l*l;if(c>=s||c<1)continue;const u=Math.sqrt(c),d=1-u/i,f=n*d*d*d,p=h/u*f,g=l/u*f;this._forces[e].x+=p,this._forces[e].y+=g,this._forces[a].x-=p,this._forces[a].y-=g}}}_updateShakeForces(t){const{shake:e}=this.config;if(!e.enabled)return;const i=window.screenX,s=window.screenY,n=i-this._shake.lastX,o=s-this._shake.lastY;t>0&&t<.1&&(this._shake.velocityX=n/t,this._shake.velocityY=o/t),this._shake.lastX=i,this._shake.lastY=s;const r=-this._shake.velocityX*e.sensitivity,a=-this._shake.velocityY*e.sensitivity;this._shake.forceX=ie.lerp(this._shake.forceX,r,1-e.damping),this._shake.forceY=ie.lerp(this._shake.forceY,a,1-e.damping);const h=Math.sqrt(this._shake.forceX*this._shake.forceX+this._shake.forceY*this._shake.forceY);if(h>e.maxForce){const t=e.maxForce/h;this._shake.forceX*=t,this._shake.forceY*=t}}_applyShakeForces(){const t=this._shake.forceX,e=this._shake.forceY;if(!(Math.abs(t)<1&&Math.abs(e)<1))for(let i=0;i<this._forces.length;i++)this._forces[i].x+=t,this._forces[i].y+=e}_integrateForces(t,e){const{gravity:i,damping:s,maxSpeed:n,heat:o}=this.config,r=n*n,a=ie.lerp(s,.995,this.modeMix);for(let s=0;s<t.length;s++){const h=t[s],l=this._forces[s],c=h.custom.mass||1;let u,d;if(this.modeMix>.5){const t=h.custom.temperature??o.neutralTemp;u=c*ie.lerp(1.5,.3,t),d=this.gravityEnabled?i*ie.lerp(1.2,.6,t):0}else u=c,d=this.gravityEnabled?i:0;h.vx+=l.x/u*e,h.vy+=(l.y/u+d)*e,h.vx*=a,h.vy*=a;const f=h.vx*h.vx+h.vy*h.vy;if(f>r){const t=n/Math.sqrt(f);h.vx*=t,h.vy*=t}}}_clampBounds(t){const{x:e,y:i,w:s,h:n}=this.bounds,{bounce:o}=this.config;for(let r=0;r<t.length;r++){const a=t[r],h=.5*a.size,l=e+h,c=e+s-h,u=i+h,d=i+n-h;a.x<l?(a.x=l,a.vx=Math.abs(a.vx)*o):a.x>c&&(a.x=c,a.vx=-Math.abs(a.vx)*o),a.y<u?(a.y=u,a.vy=Math.abs(a.vy)*o):a.y>d&&(a.y=d,a.vy=-Math.abs(a.vy)*o)}}reset(){const t=this.particles.length;this.particles.length=0,this._forces.length=0,this.spawn(t)}toggleGravity(){return this.gravityEnabled=!this.gravityEnabled,this.gravityEnabled}setPhysicsMode(t,e=!1){let i;if("liquid"===t)i=0;else if("gas"===t)i=1;else{if("number"!=typeof t)return;i=Math.max(0,Math.min(1,t))}this._targetMode=i,e&&(this.modeMix=i)}getPhysicsMode(){return this.modeMix<.01?"liquid":this.modeMix>.99?"gas":"blending"}isHeatEnabled(){return this.config.heat.enabled||this.modeMix>.5}}P=new WeakMap,A=new WeakMap,D=new WeakMap,I=new WeakMap,z=new WeakMap,B=new WeakMap,E=new WeakSet,F=function(t){var e;if(wt(this,z).push(t),1===wt(this,z).length){wt(this,A)._fluentShape=t,wt(this,A).renderable=t;const i=(null==(e=wt(this,A).draw)?void 0:e.bind(wt(this,A)))||(()=>{});wt(this,A).draw=function(){i(),this._fluentShape&&this.visible&&this._fluentShape.render()};const s=wt(this,A);wt(this,A).getBounds=function(){return s._fluentShape&&s._fluentShape.getBounds?s._fluentShape.getBounds():null}}else{if(!(wt(this,A)._fluentShape instanceof Ge)){const t=wt(this,z)[0],e=new Ge;e.add(t),wt(this,A)._fluentShape=e,wt(this,A).renderable=e}wt(this,A)._fluentShape.add(t)}return this},O=function(t){const e={...t};return void 0!==t.fill&&(e.color=t.fill,e.fillColor=t.fill,delete e.fill),void 0!==t.stroke&&(e.strokeColor=t.stroke,delete e.stroke),e},X=function(t){for(const e of wt(this,A)._fluentMotions){const i=kt(this,E,Y).call(this,e,t);e.state=null==i?void 0:i.state}},Y=function(t,e){const{type:i,opts:s,state:n}=t,o=wt(this,A)._motionTime,r=wt(this,A);switch(i){case"oscillate":{const{prop:t="y",min:e=-50,max:i=50,duration:n=2}=s,a=Ji.oscillate(e,i,o,n,!0),h=`_base_${t}`;return void 0===r[h]&&(r[h]=r[t]),r[t]=r[h]+a.value,a}case"pulse":{const{prop:t="scale",min:e=.8,max:i=1.2,duration:n=1}=s,a=Ji.pulse(e,i,o,n,!0);return"scale"===t?(r.scaleX=a.value,r.scaleY=a.value):"opacity"===t&&r.renderable?r.renderable.opacity=a.value:r[t]=a.value,a}case"orbit":{const{centerX:t=r._baseX,centerY:e=r._baseY,radiusX:i=100,radiusY:n=100,duration:a=3,clockwise:h=!0}=s;r._orbitCenter||(r._orbitCenter={x:t,y:e});const l=Ji.orbit(r._orbitCenter.x,r._orbitCenter.y,i,n,0,o,a,!0,h);return r.x=l.x,r.y=l.y,l}case"float":{const{radius:t=20,speed:e=.5,randomness:i=.3,duration:n=5}=s;r._floatState||(r._floatState={baseX:r._baseX,baseY:r._baseY});const a=Ji.float(r._floatState,o,n,e,i,t,!0);return r.x=a.x,r.y=a.y,a}case"shake":{const{intensity:t=5,frequency:e=20,decay:i=.9,duration:n=.5}=s,a=Ji.shake(r._baseX,r._baseY,t,t,e,i,o,n,!0);return r.x=a.x,r.y=a.y,a}case"bounce":{const{height:t=100,bounces:e=3,duration:i=2}=s,n=Ji.bounce(t,r._baseY,e,o,i,!0);return r.y=n.y,n}case"spiral":{const{startRadius:t=50,endRadius:e=150,revolutions:i=3,duration:n=4}=s;r._spiralCenter||(r._spiralCenter={x:r._baseX,y:r._baseY});const a=Ji.spiral(r._spiralCenter.x,r._spiralCenter.y,t,e,0,i,o,n,!0);return r.x=a.x,r.y=a.y,a}case"pendulum":{const{amplitude:t=45,duration:e=2,damped:i=!1}=s,n=Ji.pendulum(0,t,o,e,!0,i);return r.rotation=n.value*(Math.PI/180),n}case"waypoint":{const{waypoints:t=[],speed:e=100,waitTime:i=0}=s;if(0===t.length)return{state:null};const a=Ji.waypoint(r,o,t,e,i,!0,null,n);return r.x=a.x??r.x,r.y=a.y??r.y,a}default:return console.warn(`Unknown motion type: ${i}`),{state:null}}};let ds=class t{constructor(t,e,i,s){bt(this,E),bt(this,P),bt(this,A),bt(this,D),bt(this,I),bt(this,z,[]),bt(this,B,[]),Mt(this,P,t),Mt(this,A,e),Mt(this,D,i),Mt(this,I,s)}circle(t={}){const e=kt(this,E,O).call(this,t),{radius:i=30,...s}=e,n=new qe(i,s);return kt(this,E,F).call(this,n)}rect(t={}){const e=kt(this,E,O).call(this,t),i=new Ve(e);return kt(this,E,F).call(this,i)}roundRect(t={}){const e=kt(this,E,O).call(this,t),{radius:i=10,...s}=e,n=new $e(i,s);return kt(this,E,F).call(this,n)}square(t={}){const e=kt(this,E,O).call(this,t),{size:i=50,...s}=e,n=new je(i,s);return kt(this,E,F).call(this,n)}star(t={}){const e=kt(this,E,O).call(this,t),{radius:i=40,points:s=5,inset:n=.5,...o}=e,r=new ti(i,s,n,o);return kt(this,E,F).call(this,r)}triangle(t={}){const e=kt(this,E,O).call(this,t),{size:i=50,...s}=e,n=new Qe(i,s);return kt(this,E,F).call(this,n)}poly(t={}){const e=kt(this,E,O).call(this,t),i=new di(e);return kt(this,E,F).call(this,i)}line(t={}){const e=kt(this,E,O).call(this,t),{length:i=40,...s}=e,n=new Je(i,s);return kt(this,E,F).call(this,n)}hexagon(t={}){const e=kt(this,E,O).call(this,t),{radius:i=30,...s}=e,n=new gi(i,s);return kt(this,E,F).call(this,n)}diamond(t={}){const e=kt(this,E,O).call(this,t),i=new Ke(e);return kt(this,E,F).call(this,i)}heart(t={}){const e=kt(this,E,O).call(this,t),{size:i,...s}=e;i&&!s.width&&(s.width=i),i&&!s.height&&(s.height=i);const n=new mi(s);return kt(this,E,F).call(this,n)}arc(t={}){const e=kt(this,E,O).call(this,t),{radius:i=30,startAngle:s=0,endAngle:n=Math.PI,...o}=e,r=new Ue(i,s,n,o);return kt(this,E,F).call(this,r)}ring(t={}){const e=kt(this,E,O).call(this,t),{outerRadius:i=40,innerRadius:s=20,...n}=e,o=new ui(i,s,n);return kt(this,E,F).call(this,o)}arrow(t={}){const e=kt(this,E,O).call(this,t),{length:i=50,...s}=e,n=new fi(i,s);return kt(this,E,F).call(this,n)}cross(t={}){const e=kt(this,E,O).call(this,t),{size:i=40,thickness:s=10,...n}=e,o=new yi(i,s,n);return kt(this,E,F).call(this,o)}pin(t={}){const e=kt(this,E,O).call(this,t),{radius:i=20,...s}=e,n=new pi(i,s);return kt(this,E,F).call(this,n)}cloud(t={}){const e=kt(this,E,O).call(this,t),{size:i,width:s,height:n,...o}=e,r=i||Math.min(s||40,n||40),a=new Ze(r,o);return kt(this,E,F).call(this,a)}text(t,e={}){const i=kt(this,E,O).call(this,e);i.fillColor&&(i.color=i.fillColor,delete i.fillColor);const s=new xi(t,i);return kt(this,E,F).call(this,s)}image(t,e={}){const i=kt(this,E,O).call(this,e);if("string"==typeof t){const s=new Image;s.src=t;const n=new vi(s,i);return s.onload=()=>{n._bitmap=s,n._width=e.width??s.width,n._height=e.height??s.height},kt(this,E,F).call(this,n)}{const e=new vi(t,i);return kt(this,E,F).call(this,e)}}svg(t,e={}){const i=kt(this,E,O).call(this,e),s=new ci({path:t,...i});return kt(this,E,F).call(this,s)}add(t,e={}){const i=new t(kt(this,E,O).call(this,e));return kt(this,E,F).call(this,i)}oscillate(t={}){return this.motion("oscillate",t)}pulse(t={}){return this.motion("pulse",t)}orbit(t={}){return this.motion("orbit",t)}float(t={}){return this.motion("float",t)}shake(t={}){return this.motion("shake",t)}bounce(t={}){return this.motion("bounce",t)}spring(t={}){return this.motion("spring",t)}spiral(t={}){return this.motion("spiral",t)}pendulum(t={}){return this.motion("pendulum",t)}waypoint(t={}){return this.motion("waypoint",t)}motion(t,e={}){var i;if(wt(this,B).push({type:t,opts:e}),!wt(this,A)._fluentMotions){wt(this,A)._fluentMotions=[],wt(this,A)._motionTime=0,wt(this,A)._baseX=wt(this,A).x,wt(this,A)._baseY=wt(this,A).y;const t=(null==(i=wt(this,A).update)?void 0:i.bind(wt(this,A)))||(()=>{}),e=this;wt(this,A).update=function(i){var s;t(i),this._motionTime+=i,kt(s=e,E,X).call(s,i)}}return wt(this,A)._fluentMotions.push({type:t,opts:e,state:null}),this}tween(t,e={}){const{duration:i=1,easing:s="easeOutQuad",delay:n=0,onComplete:o}=e;return n>0?setTimeout(()=>{ts.to(wt(this,A),t,i,s,{onComplete:o})},1e3*n):ts.to(wt(this,A),t,i,s,{onComplete:o}),this}child(e,i,s){let n,o,r;"function"==typeof e&&e.prototype?(n=e,"function"==typeof i?(o={},r=i):(o=i||{},r=s)):(n=Pi,o=e||{},r=i);const a=new n(wt(this,A).game,o);wt(this,A).addChild(a),o.name&&(wt(this,D)[o.name]=a);const h=new t(this,a,wt(this,D),wt(this,I));return r?(r(h),this):h}on(t,e){const i={go:wt(this,A),shapes:wt(this,z),refs:wt(this,D),state:wt(this,I)};return["click","mousedown","mouseup","mousemove","mouseover","mouseout","inputdown","inputup","inputmove"].includes(t)&&(wt(this,A).interactive=!0),wt(this,A).events&&wt(this,A).events.on(t,t=>e(i,t)),this}update(t){var e;const i=(null==(e=wt(this,A).update)?void 0:e.bind(wt(this,A)))||(()=>{}),s=wt(this,z),n=wt(this,D),o=wt(this,I),r=wt(this,A);return wt(this,A).update=e=>{i(e),t(e,{go:r,shapes:s,refs:n,state:o})},this}pos(t,e){return wt(this,A).x=t,wt(this,A).y=e,this}scale(t,e){return wt(this,A).scaleX=t,wt(this,A).scaleY=e??t,this}rotate(t){return wt(this,A).rotation=t*(Math.PI/180),this}opacity(t){return wt(this,A).opacity=t,wt(this,A).renderable&&(wt(this,A).renderable.opacity=t),this}zIndex(t){return wt(this,A).zIndex=t,this}end(){return wt(this,P)}go(t){var e;let i=wt(this,P);for(;i&&!i.sceneInstance;)i=null==(e=i.end)?void 0:e.call(i);if(i&&i.go)return i.go(t);throw new Error("Cannot find scene context")}scene(t,e){var i;let s=wt(this,P);for(;s&&!s.sceneInstance;)s=null==(i=s.end)?void 0:i.call(s);if(s&&s.scene)return s.scene(t,e);throw new Error("Cannot find game context")}start(){let t=wt(this,P);for(;t&&t.end;){const e=t.end();if(e===t)break;t=e}return t.start()}get goInstance(){return wt(this,A)}get shapes(){return wt(this,z)}get refs(){return wt(this,D)}get state(){return wt(this,I)}};class fs{constructor(t,e,i,s,n){bt(this,W),bt(this,L),bt(this,H),bt(this,N),bt(this,G),Mt(this,W,t),Mt(this,L,e),Mt(this,H,i),Mt(this,N,s),Mt(this,G,n)}go(t={},e){var i;const{name:s,x:n=0,y:o=0,visible:r=!0,...a}=t,h=new Pi({x:n,y:o,visible:r,...a});(null==(i=wt(this,W).parent)?void 0:i.game)&&(h.game=wt(this,W).parent.game),wt(this,H).add(h),s&&(h.name=s,wt(this,N)[s]=h);const l=new ds(this,h,wt(this,N),wt(this,G));return e?(e(l),this):l}visible(t){return wt(this,L).visible=t,this}opacity(t){return wt(this,H).opacity=t,this}endLayer(){return wt(this,W)}end(){return wt(this,W)}scene(t,e){return wt(this,W).scene(t,e)}start(){return wt(this,W).start()}get layerGO(){return wt(this,L)}get group(){return wt(this,H)}get refs(){return wt(this,N)}get state(){return wt(this,G)}}W=new WeakMap,L=new WeakMap,H=new WeakMap,N=new WeakMap,G=new WeakMap;class ps{constructor(t,e,i,s){bt(this,U),bt(this,q),bt(this,Z),bt(this,V),bt(this,$,null),Mt(this,U,t),Mt(this,q,e),Mt(this,Z,i),Mt(this,V,s)}go(t,e,i){let s,n,o;"function"==typeof t&&t.prototype?(s=t,"function"==typeof e?(n={},o=e):(n=e||{},o=i)):(s=Pi,n=t||{},o=e);const{name:r,x:a=0,y:h=0,visible:l=!0,...c}=n,u=new s(wt(this,U).game,{x:a,y:h,visible:l,...c});wt(this,q).add(u),Mt(this,$,u),r&&(u.name=r,wt(this,Z)[r]=u);const d=new ds(this,u,wt(this,Z),wt(this,V));return o?(o(d),this):d}group(t,e){const i="string"==typeof t?t:null,s=[];return("function"==typeof t?t:e)({go:t=>{const e=this.go(t);return s.push(e.goInstance),e}}),i&&(wt(this,Z)[i]=s),this}layer(t,e=0){var i;const s=new Ge({zIndex:e});s.name=t;const n=new Pi(wt(this,U).game,{x:0,y:0});n._fluentShape=s,n.renderable=s,n.zIndex=e;const o=(null==(i=n.draw)?void 0:i.bind(n))||(()=>{});return n.draw=function(){o(),this._fluentShape&&this.visible&&this._fluentShape.render()},wt(this,q).add(n),t&&(wt(this,Z)[`${wt(this,q).name}_${t}`]=n),new fs(this,n,s,wt(this,Z),wt(this,V))}onEnter(t){return wt(this,q)._onEnter=t,this}onExit(t){return wt(this,q)._onExit=t,this}scene(t,e){return wt(this,U).scene(t,e)}end(){return wt(this,U)}start(){return wt(this,U).start()}stop(){return wt(this,U).stop()}on(t,e){return wt(this,U).on(t,e)}use(t){return wt(this,U).use(t)}state(t){return wt(this,U).state(t)}get sceneInstance(){return wt(this,q)}get refs(){return wt(this,Z)}get state(){return wt(this,V)}get parent(){return wt(this,U)}}function gs(t={}){return new ms(t)}U=new WeakMap,q=new WeakMap,Z=new WeakMap,V=new WeakMap,$=new WeakMap;class ms{constructor(t={}){bt(this,st),bt(this,j),bt(this,K,new Map),bt(this,J,null),bt(this,Q,{}),bt(this,tt,{}),bt(this,et,[]),bt(this,it,null);const{canvas:e,width:i=800,height:s=600,bg:n,fluid:o,container:r,fps:a=60,pixelRatio:h=("undefined"!=typeof window?window.devicePixelRatio:1)}=t;Mt(this,it,e||kt(this,st,nt).call(this,i,s,r)),Mt(this,j,new is(wt(this,it))),wt(this,j).init(),n&&(wt(this,j).backgroundColor=n),(void 0!==o?o:!e)&&wt(this,j).enableFluidSize(),60!==a&&(wt(this,j).targetFPS=a),wt(this,j)._pixelRatio=h}scene(t,e,i){let s,n,o;"function"==typeof t?(n=t,s=n.name||"custom_scene",o=e||{}):"function"==typeof e?(s=t,n=e,o=i||{}):(s=t,n=Di,o=e||{});const{zIndex:r=0,active:a=!0,onEnter:h,onExit:l,...c}=o;let u=wt(this,K).get(s);return u||(u=new n(wt(this,j),c),u.name=s,u.zIndex=r,u.visible=a,u._onEnter=h,u._onExit=l,wt(this,K).set(s,u),wt(this,j).pipeline.add(u)),Mt(this,J,u),new ps(this,u,wt(this,Q),wt(this,tt))}inScene(t){const e=wt(this,K).get(t);if(!e)throw new Error(`Scene '${t}' does not exist. Use .scene('${t}') to create it.`);return Mt(this,J,e),new ps(this,e,wt(this,Q),wt(this,tt))}go(t,e){return wt(this,J)||this.scene("default"),new ps(this,wt(this,J),wt(this,Q),wt(this,tt)).go(t,e)}showScene(t){var e;const i=wt(this,K).get(t);return i&&(i.visible=!0,null==(e=i._onEnter)||e.call(i,kt(this,st,ot).call(this))),this}hideScene(t){var e;const i=wt(this,K).get(t);return i&&(null==(e=i._onExit)||e.call(i,kt(this,st,ot).call(this)),i.visible=!1),this}transition(t,e,i={}){const{fade:s=0,onComplete:n}=i;return this.hideScene(t),this.showScene(e),null==n||n(),this}state(t){return Object.assign(wt(this,tt),t),this}getState(t){return wt(this,tt)[t]}setState(t,e){return wt(this,tt)[t]=e,this}on(t,e){const i=kt(this,st,ot).call(this);if("update"===t){const t=wt(this,j).update.bind(wt(this,j));wt(this,j).update=s=>{t(s),e(s,i)}}else if(t.startsWith("keydown:")){const s=t.split(":")[1];wt(this,j).events.on("keydown",t=>{var n,o;(null==(n=t.key)?void 0:n.toLowerCase())!==s.toLowerCase()&&(null==(o=t.code)?void 0:o.toLowerCase())!==s.toLowerCase()||e(i,t)})}else if(t.startsWith("keyup:")){const s=t.split(":")[1];wt(this,j).events.on("keyup",t=>{var n;(null==(n=t.key)?void 0:n.toLowerCase())===s.toLowerCase()&&e(i,t)})}else wt(this,j).events.on(t,t=>e(i,t));return this}use(t){return t(this),wt(this,et).push(t),this}start(){return wt(this,j).start(),this}stop(){return wt(this,j).stop(),this}restart(){return wt(this,j).restart(),this}get game(){return wt(this,j)}get refs(){return wt(this,Q)}get scenes(){return wt(this,K)}get canvas(){return wt(this,it)}get width(){return wt(this,it).width}get height(){return wt(this,it).height}}j=new WeakMap,K=new WeakMap,J=new WeakMap,Q=new WeakMap,tt=new WeakMap,et=new WeakMap,it=new WeakMap,st=new WeakSet,nt=function(t,e,i){const s=document.createElement("canvas");return s.width=t,s.height=e,s.style.display="block",(i||document.body).appendChild(s),s},ot=function(){return{refs:wt(this,Q),state:wt(this,tt),scenes:Object.fromEntries(wt(this,K)),game:wt(this,j),width:wt(this,it).width,height:wt(this,it).height,showScene:t=>this.showScene(t),hideScene:t=>this.hideScene(t),transition:(t,e,i)=>this.transition(t,e,i)}};class ys{static applyADSR(t,e={}){const{attack:i=.01,decay:s=.1,sustain:n=.7,release:o=.2,startTime:r=0,duration:a=1,peakVolume:h=1}=e,l=h*n,c=Math.max(0,a-i-s);t.setValueAtTime(0,r),t.linearRampToValueAtTime(h,r+i),t.linearRampToValueAtTime(l,r+i+s),t.setValueAtTime(l,r+i+s+c),t.linearRampToValueAtTime(0,r+a+o)}static get presets(){return{pluck:{attack:.001,decay:.2,sustain:0,release:.1},pad:{attack:.5,decay:.3,sustain:.8,release:1},organ:{attack:.01,decay:0,sustain:1,release:.05},perc:{attack:.001,decay:.1,sustain:0,release:.05},string:{attack:.1,decay:.2,sustain:.7,release:.3},brass:{attack:.05,decay:.1,sustain:.8,release:.2},blip:{attack:.001,decay:.05,sustain:0,release:.02},laser:{attack:.001,decay:.15,sustain:0,release:.05},explosion:{attack:.001,decay:.3,sustain:.2,release:.5}}}}class xs{static init(t,e){Mt(this,rt,t),Mt(this,at,e)}static get ctx(){return wt(this,rt)}static get now(){return wt(this,rt).currentTime}static tone(t,e,i={}){const{type:s="sine",volume:n=.5,attack:o=.01,decay:r=.1,sustain:a=.7,release:h=.2,detune:l=0,startTime:c=wt(this,rt).currentTime}=i,u=wt(this,rt).createOscillator(),d=wt(this,rt).createGain();return u.type=s,u.frequency.setValueAtTime(t,c),u.detune.setValueAtTime(l,c),ys.applyADSR(d.gain,{attack:o,decay:r,sustain:a,release:h,startTime:c,duration:e,peakVolume:n}),u.connect(d),d.connect(wt(this,at)),u.start(c),u.stop(c+e+h),u}static continuous(t={}){const{type:e="sine",frequency:i=440,volume:s=.5}=t,n=wt(this,rt).createOscillator(),o=wt(this,rt).createGain();n.type=e,n.frequency.value=i,o.gain.value=s,n.connect(o),o.connect(wt(this,at)),n.start();const r=wt(this,rt);return{osc:n,gain:o,setFrequency:(t,e=0)=>{e>0?n.frequency.linearRampToValueAtTime(t,r.currentTime+e):n.frequency.setValueAtTime(t,r.currentTime)},setVolume:(t,e=0)=>{e>0?o.gain.linearRampToValueAtTime(t,r.currentTime+e):o.gain.setValueAtTime(t,r.currentTime)},stop:(t=0)=>{t>0?(o.gain.linearRampToValueAtTime(0,r.currentTime+t),n.stop(r.currentTime+t+.01)):n.stop()}}}static fm(t,e,i,s,n={}){const{volume:o=.5,startTime:r=wt(this,rt).currentTime}=n,a=wt(this,rt).createOscillator(),h=wt(this,rt).createOscillator(),l=wt(this,rt).createGain(),c=wt(this,rt).createGain();return h.frequency.value=e,l.gain.value=i,a.frequency.value=t,c.gain.value=o,h.connect(l),l.connect(a.frequency),a.connect(c),c.connect(wt(this,at)),c.gain.setValueAtTime(o,r),c.gain.linearRampToValueAtTime(0,r+s),h.start(r),a.start(r),h.stop(r+s+.1),a.stop(r+s+.1),{carrier:a,modulator:h,outputGain:c}}static additive(t,e,i,s={}){const{volume:n=.5,startTime:o=wt(this,rt).currentTime}=s,r=[],a=wt(this,rt).createGain();return a.gain.value=n/e.length,a.connect(wt(this,at)),a.gain.setValueAtTime(n/e.length,o),a.gain.linearRampToValueAtTime(0,o+i),e.forEach((e,s)=>{if(e>0){const n=wt(this,rt).createOscillator(),h=wt(this,rt).createGain();n.frequency.value=t*(s+1),h.gain.value=e,n.connect(h),h.connect(a),n.start(o),n.stop(o+i+.1),r.push(n)}}),r}static sweep(t,e,i,s={}){const{type:n="sine",volume:o=.5,exponential:r=!0,startTime:a=wt(this,rt).currentTime}=s,h=wt(this,rt).createOscillator(),l=wt(this,rt).createGain();return h.type=n,h.frequency.setValueAtTime(t,a),r&&e>0?h.frequency.exponentialRampToValueAtTime(e,a+i):h.frequency.linearRampToValueAtTime(e,a+i),l.gain.setValueAtTime(o,a),l.gain.linearRampToValueAtTime(0,a+i),h.connect(l),l.connect(wt(this,at)),h.start(a),h.stop(a+i+.01),h}static pulse(t,e,i=.5,s={}){const{volume:n=.5,startTime:o=wt(this,rt).currentTime}=s,r=wt(this,rt).createOscillator(),a=wt(this,rt).createOscillator(),h=wt(this,rt).createGain(),l=wt(this,rt).createGain(),c=wt(this,rt).createGain();return r.type="sawtooth",a.type="sawtooth",r.frequency.value=t,a.frequency.value=t,h.gain.value=.5,l.gain.value=-.5,c.gain.setValueAtTime(n,o),c.gain.linearRampToValueAtTime(0,o+e),r.connect(h),a.connect(l),h.connect(c),l.connect(c),c.connect(wt(this,at)),r.start(o),a.start(o),r.stop(o+e+.01),a.stop(o+e+.01),{osc1:r,osc2:a,output:c}}}rt=new WeakMap,at=new WeakMap,bt(xs,rt,null),bt(xs,at,null);class vs{static init(t,e){Mt(this,ht,t),Mt(this,lt,e)}static get ctx(){return wt(this,ht)}static filter(t="lowpass",e=1e3,i=1){const s=wt(this,ht).createBiquadFilter();return s.type=t,s.frequency.value=e,s.Q.value=i,s}static delay(t=.3,e=.4,i=.5){const s=wt(this,ht).createDelay(5),n=wt(this,ht).createGain(),o=wt(this,ht).createGain(),r=wt(this,ht).createGain(),a=wt(this,ht).createGain(),h=wt(this,ht).createGain();return s.delayTime.value=t,n.gain.value=e,o.gain.value=i,r.gain.value=1-i,a.connect(s),a.connect(r),s.connect(n),n.connect(s),s.connect(o),o.connect(h),r.connect(h),{input:a,output:h,setTime:t=>s.delayTime.setValueAtTime(t,wt(this,ht).currentTime),setFeedback:t=>n.gain.setValueAtTime(t,wt(this,ht).currentTime),setMix:t=>{o.gain.setValueAtTime(t,wt(this,ht).currentTime),r.gain.setValueAtTime(1-t,wt(this,ht).currentTime)}}}static reverb(t=2,e=2){const i=wt(this,ht).createConvolver(),s=wt(this,ht).sampleRate,n=s*t,o=wt(this,ht).createBuffer(2,n,s);for(let t=0;t<2;t++){const i=o.getChannelData(t);for(let t=0;t<n;t++)i[t]=(2*Math.random()-1)*Math.pow(1-t/n,e)}return i.buffer=o,i}static distortion(t=50){const e=wt(this,ht).createWaveShaper(),i=t,s=44100,n=new Float32Array(s);for(let t=0;t<s;t++){const e=2*t/s-1;n[t]=(3+i)*e*20*(Math.PI/180)/(Math.PI+i*Math.abs(e))}return e.curve=n,e.oversample="4x",e}static tremolo(t=5,e=.5){const i=wt(this,ht).createOscillator(),s=wt(this,ht).createGain(),n=wt(this,ht).createGain();return i.frequency.value=t,s.gain.value=.5*e,n.gain.value=1-.5*e,i.connect(s),s.connect(n.gain),i.start(),{input:n,output:n,lfo:i,setRate:t=>i.frequency.setValueAtTime(t,wt(this,ht).currentTime),setDepth:t=>s.gain.setValueAtTime(.5*t,wt(this,ht).currentTime),stop:()=>i.stop()}}static compressor(t={}){const{threshold:e=-24,knee:i=30,ratio:s=12,attack:n=.003,release:o=.25}=t,r=wt(this,ht).createDynamicsCompressor();return r.threshold.value=e,r.knee.value=i,r.ratio.value=s,r.attack.value=n,r.release.value=o,r}static panner(t=0){const e=wt(this,ht).createStereoPanner();return e.pan.value=t,e}static gain(t=1){const e=wt(this,ht).createGain();return e.gain.value=t,e}}ht=new WeakMap,lt=new WeakMap,bt(vs,ht,null),bt(vs,lt,null);class _s{static white(t,e){const i=t.sampleRate*e,s=t.createBuffer(1,i,t.sampleRate),n=s.getChannelData(0);for(let t=0;t<i;t++)n[t]=2*Math.random()-1;const o=t.createBufferSource();return o.buffer=s,o}static pink(t,e){const i=t.sampleRate*e,s=t.createBuffer(1,i,t.sampleRate),n=s.getChannelData(0);let o=0,r=0,a=0,h=0,l=0,c=0,u=0;for(let t=0;t<i;t++){const e=2*Math.random()-1;o=.99886*o+.0555179*e,r=.99332*r+.0750759*e,a=.969*a+.153852*e,h=.8665*h+.3104856*e,l=.55*l+.5329522*e,c=-.7616*c-.016898*e,n[t]=.11*(o+r+a+h+l+c+u+.5362*e),u=.115926*e}const d=t.createBufferSource();return d.buffer=s,d}static brown(t,e){const i=t.sampleRate*e,s=t.createBuffer(1,i,t.sampleRate),n=s.getChannelData(0);let o=0;for(let t=0;t<i;t++){const e=2*Math.random()-1;n[t]=(o+.02*e)/1.02,o=n[t],n[t]*=3.5}const r=t.createBufferSource();return r.buffer=s,r}}class ws{static noteToFreq(t){const e=t.match(/^([A-G][#b]?)(\d+)$/);if(!e)throw new Error(`Invalid note: ${t}`);const[,i,s]=e,n=this.NOTE_FREQUENCIES[i];if(void 0===n)throw new Error(`Unknown note: ${i}`);return n*Math.pow(2,parseInt(s))}static scale(t,e="major",i=1){const s=this.noteToFreq(t),n=this.SCALES[e];if(!n)throw new Error(`Unknown scale: ${e}`);const o=[];for(let t=0;t<i;t++)for(const e of n)o.push(s*Math.pow(2,(e+12*t)/12));return o}static chord(t,e="major"){const i=this.noteToFreq(t),s=this.CHORDS[e];if(!s)throw new Error(`Unknown chord type: ${e}`);return s.map(t=>i*Math.pow(2,t/12))}static mapToScale(t,e="C4",i="pentatonic",s=2){const n=this.scale(e,i,s),o=Math.max(0,Math.min(1,t));return n[Math.floor(o*n.length)%n.length]}static midiToFreq(t){return 440*Math.pow(2,(t-69)/12)}static freqToMidi(t){return Math.round(12*Math.log2(t/440)+69)}static randomNote(t="C4",e="pentatonic",i=2){const s=this.scale(t,e,i);return s[Math.floor(Math.random()*s.length)]}static detune(t,e){return t*Math.pow(2,e/1200)}}vt(ws,"NOTE_FREQUENCIES",{C:16.35,"C#":17.32,Db:17.32,D:18.35,"D#":19.45,Eb:19.45,E:20.6,F:21.83,"F#":23.12,Gb:23.12,G:24.5,"G#":25.96,Ab:25.96,A:27.5,"A#":29.14,Bb:29.14,B:30.87}),vt(ws,"SCALES",{major:[0,2,4,5,7,9,11],minor:[0,2,3,5,7,8,10],pentatonic:[0,2,4,7,9],pentatonicMinor:[0,3,5,7,10],blues:[0,3,5,6,7,10],dorian:[0,2,3,5,7,9,10],mixolydian:[0,2,4,5,7,9,10],chromatic:[0,1,2,3,4,5,6,7,8,9,10,11],wholeTone:[0,2,4,6,8,10],diminished:[0,2,3,5,6,8,9,11]}),vt(ws,"CHORDS",{major:[0,4,7],minor:[0,3,7],diminished:[0,3,6],augmented:[0,4,8],sus2:[0,2,7],sus4:[0,5,7],major7:[0,4,7,11],minor7:[0,3,7,10],dom7:[0,4,7,10],dim7:[0,3,6,9],add9:[0,4,7,14],power:[0,7]});class bs{static init(t,e){Mt(this,ct,t),Mt(this,ut,t.createAnalyser()),wt(this,ut).fftSize=2048,e.connect(wt(this,ut)),wt(this,ut).connect(t.destination),Mt(this,dt,new Uint8Array(wt(this,ut).frequencyBinCount)),Mt(this,ft,new Uint8Array(wt(this,ut).frequencyBinCount))}static get isInitialized(){return null!==wt(this,ut)}static get node(){return wt(this,ut)}static setFFTSize(t){wt(this,ut)&&(wt(this,ut).fftSize=t,Mt(this,dt,new Uint8Array(wt(this,ut).frequencyBinCount)),Mt(this,ft,new Uint8Array(wt(this,ut).frequencyBinCount)))}static getWaveform(){return wt(this,ut)?(wt(this,ut).getByteTimeDomainData(wt(this,dt)),wt(this,dt)):new Uint8Array(0)}static getFrequency(){return wt(this,ut)?(wt(this,ut).getByteFrequencyData(wt(this,ft)),wt(this,ft)):new Uint8Array(0)}static getBands(t=8){const e=this.getFrequency();if(0===e.length)return new Array(t).fill(0);const i=Math.floor(e.length/t),s=[];for(let n=0;n<t;n++){let t=0;for(let s=0;s<i;s++)t+=e[n*i+s];s.push(t/(255*i))}return s}static getAmplitude(){const t=this.getWaveform();if(0===t.length)return 0;let e=0;for(let i=0;i<t.length;i++){const s=(t[i]-128)/128;e+=s*s}return Math.sqrt(e/t.length)}static getPeakFrequency(){if(!wt(this,ut)||!wt(this,ct))return 0;const t=this.getFrequency();let e=0,i=0;for(let s=0;s<t.length;s++)t[s]>i&&(i=t[s],e=s);return e*(wt(this,ct).sampleRate/2)/wt(this,ut).frequencyBinCount}static dispose(){wt(this,ut)&&(wt(this,ut).disconnect(),Mt(this,ut,null)),Mt(this,dt,null),Mt(this,ft,null)}}ct=new WeakMap,ut=new WeakMap,dt=new WeakMap,ft=new WeakMap,bt(bs,ct,null),bt(bs,ut,null),bt(bs,dt,null),bt(bs,ft,null);class Ms{static init(t={}){if(wt(this,mt))return void console.warn("[Synth] Already initialized");const{masterVolume:e=.5,sampleRate:i=44100,enableAnalyzer:s=!1}=t;try{Mt(this,pt,new(window.AudioContext||window.webkitAudioContext)({sampleRate:i})),Mt(this,gt,wt(this,pt).createGain()),wt(this,gt).gain.value=e,wt(this,gt).connect(wt(this,pt).destination),xs.init(wt(this,pt),wt(this,gt)),vs.init(wt(this,pt),wt(this,gt)),s&&bs.init(wt(this,pt),wt(this,gt)),Mt(this,mt,!0),console.log("[Synth] Audio system initialized")}catch(t){console.error("[Synth] Failed to initialize audio:",t)}}static get isInitialized(){return wt(this,mt)}static get ctx(){return wt(this,pt)}static get master(){return wt(this,gt)}static get osc(){return xs}static get fx(){return vs}static get env(){return ys}static get noise(){return _s}static get music(){return ws}static get analyzer(){return bs}static async resume(){wt(this,pt)&&"suspended"===wt(this,pt).state&&(await wt(this,pt).resume(),console.log("[Synth] Audio context resumed"))}static async suspend(){wt(this,pt)&&"running"===wt(this,pt).state&&await wt(this,pt).suspend()}static get now(){return wt(this,pt)?wt(this,pt).currentTime:0}static get state(){return wt(this,pt)?wt(this,pt).state:"closed"}static set volume(t){wt(this,gt)&&wt(this,gt).gain.setValueAtTime(Math.max(0,Math.min(1,t)),wt(this,pt).currentTime)}static get volume(){return wt(this,gt)?wt(this,gt).gain.value:0}static chain(...t){for(let e=0;e<t.length-1;e++)t[e].connect(t[e+1]);return{first:t[0],last:t[t.length-1],connectTo:e=>t[t.length-1].connect(e)}}static schedule(t,e){const i=Math.max(0,1e3*(e-this.now));return setTimeout(t,i)}static async close(){wt(this,pt)&&(bs.dispose(),await wt(this,pt).close(),Mt(this,pt,null),Mt(this,gt,null),Mt(this,mt,!1),console.log("[Synth] Audio system closed"))}}pt=new WeakMap,gt=new WeakMap,mt=new WeakMap,bt(Ms,pt,null),bt(Ms,gt,null),bt(Ms,mt,!1);class ks{constructor(t={}){this.states=t.states||{},this.currentState=null,this.previousState=null,this.stateTime=0,this.context=t.context||null,this.paused=!1,this.onStateChange=null,t.initial&&this.setState(t.initial)}get state(){return this.currentState}get currentStateConfig(){return this.currentState?this.states[this.currentState]:null}is(t){return this.currentState===t}isAny(...t){return t.includes(this.currentState)}addState(t,e){return this.states[t]=e,this}removeState(t){return delete this.states[t],this}setState(t,e){if(!this.states[t])return console.warn(`StateMachine: Unknown state '${t}'`),!1;if(this.currentState){const t=this.states[this.currentState];(null==t?void 0:t.exit)&&this._call(t.exit,e)}this.previousState=this.currentState,this.currentState=t,this.stateTime=0;const i=this.states[t];return(null==i?void 0:i.enter)&&this._call(i.enter,e),this.onStateChange&&this.onStateChange(t,this.previousState,e),!0}trigger(t,e){const i=this.currentStateConfig;if(!(null==i?void 0:i.on))return!1;const s=i.on[t];return!!s&&("string"==typeof s?this.setState(s,e):!(s.guard&&!this._call(s.guard,e))&&(s.action&&this._call(s.action,e),!!s.target&&this.setState(s.target,e)))}update(t){if(this.paused||!this.currentState)return;this.stateTime+=t;const e=this.states[this.currentState];e&&(e.update&&this._call(e.update,t),void 0!==e.duration&&this.stateTime>=e.duration&&(e.next?this.setState(e.next):e.onComplete&&this._call(e.onComplete)))}get progress(){const t=this.currentStateConfig;return(null==t?void 0:t.duration)?Math.min(1,this.stateTime/t.duration):0}get remaining(){const t=this.currentStateConfig;return(null==t?void 0:t.duration)?Math.max(0,t.duration-this.stateTime):1/0}get isTimed(){var t;return void 0!==(null==(t=this.currentStateConfig)?void 0:t.duration)}pause(){this.paused=!0}resume(){this.paused=!1}reset(t){if(this.stateTime=0,this.previousState=null,t)this.setState(t);else{const t=Object.keys(this.states)[0];t&&this.setState(t)}}_call(t,...e){if("function"==typeof t)return this.context?t.call(this.context,...e):t(...e)}static fromSequence(t,e={}){var i;const s={};for(let i=0;i<t.length;i++){const n=t[i],o=i===t.length-1,r=o?e.loop?t[0].name:null:t[i+1].name;s[n.name]={duration:n.duration,next:r,enter:n.enter,update:n.update,exit:n.exit,onComplete:o&&!e.loop?e.onComplete:void 0}}return new ks({initial:null==(i=t[0])?void 0:i.name,states:s,context:e.context})}}t.Arc=Ue,t.Arrow=fi,t.BezierShape=class extends Ne{constructor(t=[],e={}){super(e),this.path=t}draw(){super.draw(),Be.lines.path(this.path,this.color,this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:100,height:100}}},t.BooleanAlgebra=Qt,t.Button=ns,t.Camera2D=zt,t.Camera3D=class{constructor(t={}){this.rotationX=t.rotationX??0,this.rotationY=t.rotationY??0,this.rotationZ=t.rotationZ??0,this.x=t.x??0,this.y=t.y??0,this.z=t.z??0,this._initialRotationX=this.rotationX,this._initialRotationY=this.rotationY,this._initialRotationZ=this.rotationZ,this._initialX=this.x,this._initialY=this.y,this._initialZ=this.z,this.perspective=t.perspective??800,this.sensitivity=t.sensitivity??.005,this.minRotationX=t.minRotationX??-1.5,this.maxRotationX=t.maxRotationX??1.5,this.clampX=t.clampX??!0,this.autoRotate=t.autoRotate??!1,this.autoRotateSpeed=t.autoRotateSpeed??.5,this.autoRotateAxis=t.autoRotateAxis??"y",this.inertia=t.inertia??!1,this.friction=t.friction??.92,this.velocityScale=t.velocityScale??1,this._velocityX=0,this._velocityY=0,this._lastDeltaX=0,this._lastDeltaY=0,this._lastMoveTime=0,this._isDragging=!1,this._lastMouseX=0,this._lastMouseY=0,this._canvas=null,this._boundHandlers=null,this._followTarget=null,this._followOffset={x:0,y:0,z:0},this._followLookAt=!0,this._followLerp=.1,this._targetX=null,this._targetY=null,this._targetZ=null,this._targetRotationX=null,this._targetRotationY=null,this._positionLerp=.05}project(t,e,i){if(t-=this.x,e-=this.y,i-=this.z,0!==this.rotationZ){const i=Math.cos(this.rotationZ),s=Math.sin(this.rotationZ),n=t;t=n*i-e*s,e=n*s+e*i}const s=Math.cos(this.rotationY),n=Math.sin(this.rotationY),o=t*s-i*n,r=t*n+i*s,a=Math.cos(this.rotationX),h=Math.sin(this.rotationX),l=e*a-r*h,c=e*h+r*a,u=this.perspective/(this.perspective+c);return{x:o*u,y:l*u,z:c,scale:u}}projectAll(t){return t.map(t=>this.project(t.x,t.y,t.z))}update(t){var e,i,s;if(this._followTarget){const t=this._followTarget,n=(t.x??0)+this._followOffset.x,o=(t.y??0)+this._followOffset.y,r=(t.z??0)+this._followOffset.z;if(this.x+=(n-this.x)*this._followLerp,this.y+=(o-this.y)*this._followLerp,this.z+=(r-this.z)*this._followLerp,this._followLookAt){const t=(null==(e=this._followLookAtTarget)?void 0:e.x)??0,n=(null==(i=this._followLookAtTarget)?void 0:i.y)??0,o=(null==(s=this._followLookAtTarget)?void 0:s.z)??0,r=t-this.x,a=n-this.y,h=o-this.z,l=Math.sqrt(r*r+h*h),c=Math.atan2(r,h),u=Math.atan2(-a,l);this.rotationY+=this._angleDiff(this.rotationY,c)*this._followLerp,this.rotationX+=(u-this.rotationX)*this._followLerp}}else if(null!==this._targetX){const t=this._positionLerp;this.x+=(this._targetX-this.x)*t,this.y+=(this._targetY-this.y)*t,this.z+=(this._targetZ-this.z)*t,null!==this._targetRotationX&&(this.rotationX+=(this._targetRotationX-this.rotationX)*t),null!==this._targetRotationY&&(this.rotationY+=this._angleDiff(this.rotationY,this._targetRotationY)*t),Math.abs(this._targetX-this.x)+Math.abs(this._targetY-this.y)+Math.abs(this._targetZ-this.z)<.1&&(this.x=this._targetX,this.y=this._targetY,this.z=this._targetZ,this._targetX=null,this._targetY=null,this._targetZ=null,this._targetRotationX=null,this._targetRotationY=null)}if(!this.inertia||this._isDragging||this._followTarget||(Math.abs(this._velocityX)>1e-4||Math.abs(this._velocityY)>1e-4)&&(this.rotationY+=this._velocityY,this.rotationX+=this._velocityX,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this._velocityX*=this.friction,this._velocityY*=this.friction,Math.abs(this._velocityX)<1e-4&&(this._velocityX=0),Math.abs(this._velocityY)<1e-4&&(this._velocityY=0)),this.autoRotate&&!this._isDragging&&!this._followTarget&&!(Math.abs(this._velocityX)>.001||Math.abs(this._velocityY)>.001)){const e=this.autoRotateSpeed*t;switch(this.autoRotateAxis){case"x":this.rotationX+=e;break;case"y":this.rotationY+=e;break;case"z":this.rotationZ+=e}}}_angleDiff(t,e){let i=e-t;for(;i>Math.PI;)i-=2*Math.PI;for(;i<-Math.PI;)i+=2*Math.PI;return i}enableMouseControl(t,e={}){this._canvas&&this.disableMouseControl(),this._canvas=t;const i=e.invertX?-1:1,s=e.invertY?-1:1;return this._boundHandlers={mousedown:t=>{this._isDragging=!0,this._lastMouseX=t.clientX,this._lastMouseY=t.clientY,this._lastMoveTime=performance.now(),this._velocityX=0,this._velocityY=0},mousemove:t=>{if(!this._isDragging)return;const e=t.clientX-this._lastMouseX,n=t.clientY-this._lastMouseY,o=e*this.sensitivity*i,r=n*this.sensitivity*s;this.rotationY+=o,this.rotationX+=r,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this.inertia&&(this._lastDeltaX=r,this._lastDeltaY=o,this._lastMoveTime=performance.now()),this._lastMouseX=t.clientX,this._lastMouseY=t.clientY},mouseup:()=>{this.inertia&&this._isDragging&&performance.now()-this._lastMoveTime<50&&(this._velocityX=this._lastDeltaX*this.velocityScale,this._velocityY=this._lastDeltaY*this.velocityScale),this._isDragging=!1},mouseleave:()=>{this.inertia&&this._isDragging&&performance.now()-this._lastMoveTime<50&&(this._velocityX=this._lastDeltaX*this.velocityScale,this._velocityY=this._lastDeltaY*this.velocityScale),this._isDragging=!1},touchstart:t=>{1===t.touches.length&&(this._isDragging=!0,this._lastMouseX=t.touches[0].clientX,this._lastMouseY=t.touches[0].clientY,this._lastMoveTime=performance.now(),this._velocityX=0,this._velocityY=0)},touchmove:t=>{if(!this._isDragging||1!==t.touches.length)return;t.preventDefault();const e=t.touches[0].clientX-this._lastMouseX,n=t.touches[0].clientY-this._lastMouseY,o=e*this.sensitivity*i,r=n*this.sensitivity*s;this.rotationY+=o,this.rotationX+=r,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this.inertia&&(this._lastDeltaX=r,this._lastDeltaY=o,this._lastMoveTime=performance.now()),this._lastMouseX=t.touches[0].clientX,this._lastMouseY=t.touches[0].clientY},touchend:()=>{this.inertia&&this._isDragging&&performance.now()-this._lastMoveTime<50&&(this._velocityX=this._lastDeltaX*this.velocityScale,this._velocityY=this._lastDeltaY*this.velocityScale),this._isDragging=!1},dblclick:()=>{this.reset()}},t.addEventListener("mousedown",this._boundHandlers.mousedown),t.addEventListener("mousemove",this._boundHandlers.mousemove),t.addEventListener("mouseup",this._boundHandlers.mouseup),t.addEventListener("mouseleave",this._boundHandlers.mouseleave),t.addEventListener("touchstart",this._boundHandlers.touchstart),t.addEventListener("touchmove",this._boundHandlers.touchmove,{passive:!1}),t.addEventListener("touchend",this._boundHandlers.touchend),t.addEventListener("dblclick",this._boundHandlers.dblclick),this}disableMouseControl(){return this._canvas&&this._boundHandlers&&(this._canvas.removeEventListener("mousedown",this._boundHandlers.mousedown),this._canvas.removeEventListener("mousemove",this._boundHandlers.mousemove),this._canvas.removeEventListener("mouseup",this._boundHandlers.mouseup),this._canvas.removeEventListener("mouseleave",this._boundHandlers.mouseleave),this._canvas.removeEventListener("touchstart",this._boundHandlers.touchstart),this._canvas.removeEventListener("touchmove",this._boundHandlers.touchmove),this._canvas.removeEventListener("touchend",this._boundHandlers.touchend),this._canvas.removeEventListener("dblclick",this._boundHandlers.dblclick)),this._canvas=null,this._boundHandlers=null,this}reset(){return this.rotationX=this._initialRotationX,this.rotationY=this._initialRotationY,this.rotationZ=this._initialRotationZ,this.x=this._initialX,this.y=this._initialY,this.z=this._initialZ,this._velocityX=0,this._velocityY=0,this._followTarget=null,this._targetX=null,this._targetY=null,this._targetZ=null,this}stopInertia(){return this._velocityX=0,this._velocityY=0,this}setPosition(t,e,i){return this.x=t,this.y=e,this.z=i,this}moveTo(t,e,i,s={}){return this._targetX=t,this._targetY=e,this._targetZ=i,this._targetRotationX=s.rotationX??null,this._targetRotationY=s.rotationY??null,this._positionLerp=s.lerp??.05,this}follow(t,e={}){return this._followTarget=t,this._followOffset={x:e.offsetX??0,y:e.offsetY??0,z:e.offsetZ??0},this._followLookAt=e.lookAt??!0,this._followLookAtTarget=e.lookAtTarget??null,this._followLerp=e.lerp??.1,this}unfollow(t=!1){return this._followTarget=null,t&&this.moveTo(this._initialX,this._initialY,this._initialZ,{rotationX:this._initialRotationX,rotationY:this._initialRotationY,lerp:.05}),this}isFollowing(){return null!==this._followTarget}setRotation(t,e,i=0){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i=0){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this}isDragging(){return this._isDragging}lookAt(t,e,i){const s=t-this.x,n=e-this.y,o=i-this.z,r=Math.sqrt(s*s+o*o);return this.rotationY=Math.atan2(s,o),this.rotationX=Math.atan2(-n,r),this}},t.Circle=qe,t.Cloud=Ze,t.Collision=ls,t.CollisionSystem=class{constructor(){this.groups=new Map,this.pairs=[],this.useQuadtree=!1}createGroup(t){return this.groups.has(t)||this.groups.set(t,new Set),this}add(t,e){const i=this.groups.get(t);if(!i)throw new Error(`Collision group '${t}' does not exist. Call createGroup('${t}') first.`);return i.add(e),this}remove(t,e){const i=this.groups.get(t);return!!i&&i.delete(e)}removeFromAll(t){for(const e of this.groups.values())e.delete(t)}clearGroup(t){const e=this.groups.get(t);e&&e.clear()}clearAll(){for(const t of this.groups.values())t.clear()}getGroup(t){const e=this.groups.get(t);return e?Array.from(e):[]}onCollision(t,e,i,s={}){return this.pairs.push({groupA:t,groupB:e,callback:i,once:s.once??!1}),this}offCollision(t,e){this.pairs=this.pairs.filter(i=>!(i.groupA===t&&i.groupB===e))}update(){for(const t of this.pairs)this._checkPair(t)}check(t,e){const i=this.groups.get(t),s=this.groups.get(e);if(!i||!s)return[];const n=[];for(const t of i){if(!this._isActive(t))continue;const e=this._getBounds(t);if(e)for(const i of s){if(t===i)continue;if(!this._isActive(i))continue;const s=this._getBounds(i);s&&ls.rectRect(e,s)&&n.push([t,i])}}return n}checkAgainstGroup(t,e){const i=this.groups.get(e);if(!i)return null;const s=this._getBounds(t);if(!s)return null;for(const e of i){if(t===e)continue;if(!this._isActive(e))continue;const i=this._getBounds(e);if(i&&ls.rectRect(s,i))return e}return null}checkAllAgainstGroup(t,e){const i=this.groups.get(e);if(!i)return[];const s=this._getBounds(t);if(!s)return[];const n=[];for(const e of i){if(t===e)continue;if(!this._isActive(e))continue;const i=this._getBounds(e);i&&ls.rectRect(s,i)&&n.push(e)}return n}_checkPair(t){const e=this.groups.get(t.groupA),i=this.groups.get(t.groupB);if(e&&i)for(const s of e){if(!this._isActive(s))continue;const e=this._getBounds(s);if(e)for(const n of i){if(s===n)continue;if(!this._isActive(n))continue;const i=this._getBounds(n);if(i&&ls.rectRect(e,i)&&(t.callback(s,n),t.once))break}}}_getBounds(t){return"function"==typeof t.getBounds?t.getBounds():t.bounds?t.bounds:void 0!==t.x&&void 0!==t.y?{x:t.x-(t.width||0)/2,y:t.y-(t.height||0)/2,width:t.width||0,height:t.height||0}:null}_isActive(t){return!1!==t.active&&!0!==t.destroyed&&!1!==t.alive}},t.Complex=Et,t.Cone=class extends Ne{constructor(t=50,e=100,i={}){super(i),this.radius=t,this.height=e||i.height||100,this.segments=i.segments||24,this.bottomColor=i.bottomColor||"#eee",this.sideColor=i.sideColor||"#aaa",this.stroke=i.stroke||null,this.lineWidth=i.lineWidth||1,this.rotationX=i.rotationX||0,this.rotationY=i.rotationY||0,this.rotationZ=i.rotationZ||0,this.visibleFaces=i.visibleFaces||["bottom","side"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.radius,e=this.height/2,i=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},s=(t,e,s)=>{const n=i(t,e,s);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z,z:n.z}},n=s(0,0,e),o=[],r=2*Math.PI/this.segments;for(let i=0;i<this.segments;i++){const n=i*r,a=Math.cos(n)*t,h=Math.sin(n)*t;o.push(s(a,h,-e))}const a=[];for(let t=0;t<this.segments;t++){const e=(t+1)%this.segments;a.push({points:[n,o[t],o[e]],z:(n.z+o[t].z+o[e].z)/3})}const h=[];this.visibleFaces.includes("bottom")&&h.push({type:"bottom",points:[...o].reverse(),z:-e}),this.visibleFaces.includes("side")&&h.push(...a.map(t=>({type:"side",points:t.points,z:t.z}))),h.sort((t,e)=>e.z-t.z);for(const t of h){const e="bottom"===t.type?this.bottomColor:this.sideColor;Be.shapes.polygon(t.points,e,this.stroke,this.lineWidth)}}getBounds(){const t=1.5*Math.max(2*this.radius,this.height);return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Cross=yi,t.Cube=class extends Ne{constructor(t=50,e={}){super(e),this.size=t,this.faceTopColor=e.faceTopColor||"#eee",this.faceBottomColor=e.faceBottomColor||"#ccc",this.faceLeftColor=e.faceLeftColor||"#aaa",this.faceRightColor=e.faceRightColor||"#888",this.faceFrontColor=e.faceFrontColor||"#666",this.faceBackColor=e.faceBackColor||"#444",this.strokeColor=e.strokeColor||null,this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0,this.visibleFaces=e.visibleFaces||["top","left","right","front","back","bottom"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.size/2,e=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},i=(t,i,s)=>{const n=e(t,i,s);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z}},s={p0:i(-t,-t,-t),p1:i(t,-t,-t),p2:i(t,t,-t),p3:i(-t,t,-t),p4:i(-t,-t,t),p5:i(t,-t,t),p6:i(t,t,t),p7:i(-t,t,t)},n={top:{points:[s.p4,s.p5,s.p6,s.p7],color:this.faceTopColor,normal:[0,0,1]},bottom:{points:[s.p0,s.p1,s.p2,s.p3],color:this.faceBottomColor,normal:[0,0,-1]},left:{points:[s.p0,s.p4,s.p7,s.p3],color:this.faceLeftColor,normal:[-1,0,0]},right:{points:[s.p1,s.p5,s.p6,s.p2],color:this.faceRightColor,normal:[1,0,0]},front:{points:[s.p0,s.p1,s.p5,s.p4],color:this.faceFrontColor,normal:[0,-1,0]},back:{points:[s.p3,s.p2,s.p6,s.p7],color:this.faceBackColor,normal:[0,1,0]}};this.visibleFaces.map(t=>{const e=n[t];if(!e)return null;const i=e.points.reduce((t,e)=>({x:t.x+e.x,y:t.y+e.y}),{x:0,y:0});return i.x/=e.points.length,i.y/=e.points.length,{key:t,face:e,depth:i.x*i.x+i.y*i.y}}).filter(t=>null!==t).sort((t,e)=>e.depth-t.depth).forEach(({key:t,face:e})=>{(null==e?void 0:e.color)&&Be.shapes.polygon(e.points,e.color,this.strokeColor,this.lineWidth)})}getBounds(){const t=1.5*this.size;return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Cube3D=class extends Ne{constructor(t,e={}){var i,s,n,o,r,a;super(e),this.size=t,this.x=e.x??0,this.y=e.y??0,this.z=e.z??0,this.camera=e.camera??null,this.debug=e.debug??!1,this.selfRotationX=e.selfRotationX??0,this.selfRotationY=e.selfRotationY??0,this.selfRotationZ=e.selfRotationZ??0,this.faceColors={front:(null==(i=e.faceColors)?void 0:i.front)??"#B71234",back:(null==(s=e.faceColors)?void 0:s.back)??"#FF5800",top:(null==(n=e.faceColors)?void 0:n.top)??"#FFFFFF",bottom:(null==(o=e.faceColors)?void 0:o.bottom)??"#FFD500",left:(null==(r=e.faceColors)?void 0:r.left)??"#009B48",right:(null==(a=e.faceColors)?void 0:a.right)??"#0046AD"},this.stroke=e.stroke??null,this.lineWidth=e.lineWidth??1,this.stickerMode=e.stickerMode??!1,this.stickerMargin=e.stickerMargin??.15,this.stickerBackgroundColor=e.stickerBackgroundColor??"#0A0A0A",this._faceConfigs=this._createFaceConfigs()}_createFaceConfigs(){const t=this.size/2;return{front:{localPos:{x:0,y:0,z:-t},faceRotX:0,faceRotY:0,color:this.faceColors.front},back:{localPos:{x:0,y:0,z:t},faceRotX:0,faceRotY:Math.PI,color:this.faceColors.back},top:{localPos:{x:0,y:-t,z:0},faceRotX:-Math.PI/2,faceRotY:0,color:this.faceColors.top},bottom:{localPos:{x:0,y:t,z:0},faceRotX:Math.PI/2,faceRotY:0,color:this.faceColors.bottom},left:{localPos:{x:-t,y:0,z:0},faceRotX:0,faceRotY:Math.PI/2,color:this.faceColors.left},right:{localPos:{x:t,y:0,z:0},faceRotX:0,faceRotY:-Math.PI/2,color:this.faceColors.right}}}setCamera(t){return this.camera=t,this}setFaceColors(t){Object.assign(this.faceColors,t);for(const[e,i]of Object.entries(this._faceConfigs))t[e]&&(i.color=t[e]);return this}_applySelfRotation(t,e,i){if(0!==this.selfRotationY){const e=Math.cos(this.selfRotationY),s=Math.sin(this.selfRotationY),n=t*s+i*e;t=t*e-i*s,i=n}if(0!==this.selfRotationX){const t=Math.cos(this.selfRotationX),s=Math.sin(this.selfRotationX),n=e*s+i*t;e=e*t-i*s,i=n}if(0!==this.selfRotationZ){const i=Math.cos(this.selfRotationZ),s=Math.sin(this.selfRotationZ),n=t*s+e*i;t=t*i-e*s,e=n}return{x:t,y:e,z:i}}_calculateLighting(t,e,i){const s=Math.sqrt(.99);let n=t*(.5/s)+e*(.7/s)+i*(.5/s);return n=.7*Math.max(0,n)+.3,n}_applyLighting(t,e){if(!t||"string"!=typeof t||!t.startsWith("#"))return t;const i=t.replace("#",""),s=parseInt(i.substring(0,2),16),n=parseInt(i.substring(2,4),16),o=parseInt(i.substring(4,6),16);return`rgb(${Math.round(s*e)}, ${Math.round(n*e)}, ${Math.round(o*e)})`}draw(){if(super.draw(),!this.camera){const t=this.size/2;return void(this.faceColors.front&&Be.shapes.fillRect(-t,-t,this.size,this.size,this.faceColors.front))}const t=Be.ctx;this.size;const e=0!==this.selfRotationX||0!==this.selfRotationY||0!==this.selfRotationZ,i=[];for(const[t,s]of Object.entries(this._faceConfigs)){let{x:n,y:o,z:r}=s.localPos;if(e){const t=this._applySelfRotation(n,o,r);n=t.x,o=t.y,r=t.z}const a=this.x+n,h=this.y+o,l=this.z+r;let c=0,u=0,d=0;if("front"===t?(c=0,u=0,d=-1):"back"===t?(c=0,u=0,d=1):"top"===t?(c=0,u=-1,d=0):"bottom"===t?(c=0,u=1,d=0):"left"===t?(c=-1,u=0,d=0):"right"===t&&(c=1,u=0,d=0),e){const t=this._applySelfRotation(c,u,d);c=t.x,u=t.y,d=t.z}let f=c,p=u,g=d;if(0!==this.camera.rotationZ){const t=Math.cos(this.camera.rotationZ),e=Math.sin(this.camera.rotationZ),i=f;f=i*t-p*e,p=i*e+p*t}const m=Math.cos(this.camera.rotationY),y=Math.sin(this.camera.rotationY),x=f*m-g*y,v=f*y+g*m,_=Math.cos(this.camera.rotationX),w=Math.sin(this.camera.rotationX),b=p*_-v*w,M=p*w+v*_;if(M>.01)continue;const k=this.camera.project(a,h,l);if(k.z<10-this.camera.perspective)continue;const C=this._calculateLighting(x,b,M),S=this._getFaceVertices(t,s,e);i.push({name:t,config:s,projected:k,vertices:S,depth:k.z,intensity:C,nx:x,ny:b,nz:M})}i.sort((t,e)=>e.depth-t.depth);for(const e of i)this._renderFace(t,e)}_getFaceVertices(t,e,i){const s=this.size/2;let n;switch(t){case"front":n=[{x:-s,y:-s,z:-s},{x:s,y:-s,z:-s},{x:s,y:s,z:-s},{x:-s,y:s,z:-s}];break;case"back":n=[{x:s,y:-s,z:s},{x:-s,y:-s,z:s},{x:-s,y:s,z:s},{x:s,y:s,z:s}];break;case"top":n=[{x:-s,y:-s,z:s},{x:s,y:-s,z:s},{x:s,y:-s,z:-s},{x:-s,y:-s,z:-s}];break;case"bottom":n=[{x:-s,y:s,z:-s},{x:s,y:s,z:-s},{x:s,y:s,z:s},{x:-s,y:s,z:s}];break;case"left":n=[{x:-s,y:-s,z:s},{x:-s,y:-s,z:-s},{x:-s,y:s,z:-s},{x:-s,y:s,z:s}];break;case"right":n=[{x:s,y:-s,z:-s},{x:s,y:-s,z:s},{x:s,y:s,z:s},{x:s,y:s,z:-s}]}return n.map(t=>{let{x:e,y:s,z:n}=t;if(i){const t=this._applySelfRotation(e,s,n);e=t.x,s=t.y,n=t.z}return e+=this.x,s+=this.y,n+=this.z,this.camera.project(e,s,n)})}_renderFace(t,e){const{vertices:i,config:s,intensity:n}=e,o=this._applyLighting(s.color,n);t.beginPath(),t.moveTo(i[0].x,i[0].y);for(let e=1;e<i.length;e++)t.lineTo(i[e].x,i[e].y);if(t.closePath(),this.debug)t.strokeStyle=this.stroke||"#fff",t.lineWidth=this.lineWidth??1,t.stroke();else if(this.stickerMode){const e=this._applyLighting(this.stickerBackgroundColor,n);t.fillStyle=e,t.fill(),this.stroke&&(t.strokeStyle=this.stroke,t.lineWidth=this.lineWidth??1,t.stroke());const s=this._getInsetVertices(i,this.stickerMargin);t.beginPath(),t.moveTo(s[0].x,s[0].y);for(let e=1;e<s.length;e++)t.lineTo(s[e].x,s[e].y);t.closePath(),t.fillStyle=o,t.fill()}else t.fillStyle=o,t.fill(),this.stroke&&(t.strokeStyle=this.stroke,t.lineWidth=this.lineWidth??1,t.stroke())}_getInsetVertices(t,e){let i=0,s=0;for(const e of t)i+=e.x,s+=e.y;i/=t.length,s/=t.length;const n=1-2*e;return t.map(t=>({x:i+(t.x-i)*n,y:s+(t.y-s)*n}))}getCenter(){return{x:this.x,y:this.y,z:this.z}}getBounds(){const t=this.size/2;return{x:this.x-t,y:this.y-t,width:this.size,height:this.size}}},t.Cursor=class extends Pi{constructor(t,e,i=null,s={}){super(t,s),this.normalShape=e,this.pressedShape=i||e,this.active=!1,this.offsetX=0,this.offsetY=0,this.isDown=!1,this.game.events.on("inputmove",t=>{this.x=t.x,this.y=t.y}),this.game.events.on("inputdown",()=>{this.isDown=!0}),this.game.events.on("inputup",()=>{this.isDown=!1}),this.game.events.on("mouseover",()=>{this.visible=!1}),this.game.events.on("mouseout",()=>{this.visible=!0})}activate(){this.active=!0,this.game.canvas.style.cursor="none"}deactivate(){this.active=!1,this.game.canvas.style.cursor="default"}draw(){if(super.draw(),!this.active)return;const t=this.isDown&&this.pressedShape?this.pressedShape:this.normalShape;t&&t.render()}},t.Cylinder=class extends Ne{constructor(t=40,e={}){super(e),this.radius=t,this.height=e.height||80,this.segments=e.segments||24,this.topColor=e.topColor||"#FF00FF",this.bottomColor=e.bottomColor||"#FF0FFF",this.sideColor=e.sideColor||"#00FF00",this.stroke=e.stroke||"#000000",this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0,this.visibleFaces=e.visibleFaces||["top","bottom","side"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.radius,e=this.height/2,i=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},s=(t,e,s)=>{const n=i(t,e,s);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z,z:n.z}},n=[],o=[],r=2*Math.PI/this.segments;for(let i=0;i<this.segments;i++){const a=i*r,h=Math.cos(a)*t,l=Math.sin(a)*t;n.push(s(h,l,e)),o.push(s(h,l,-e))}const a=[];for(let t=0;t<this.segments;t++){const e=(t+1)%this.segments;a.push({points:[o[t],o[e],n[e],n[t]],z:(n[t].z+n[e].z+o[t].z+o[e].z)/4})}const h=[];this.visibleFaces.includes("top")&&h.push({type:"top",points:n,z:e}),this.visibleFaces.includes("bottom")&&h.push({type:"bottom",points:[...o].reverse(),z:-e}),this.visibleFaces.includes("side")&&h.push(...a.map(t=>({type:"side",points:t.points,z:t.z}))),h.sort((t,e)=>e.z-t.z);for(const t of h){let e;switch(t.type){case"top":e=this.topColor;break;case"bottom":e=this.bottomColor;break;case"side":e=this.sideColor}Be.shapes.polygon(t.points,e,this.stroke,this.lineWidth)}}getBounds(){const t=1.5*Math.max(2*this.radius,this.height);return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.DebugTab=Ce,t.Diamond=Ke,t.Easing=ie,t.Euclidian=Fe,t.EventEmitter=_i,t.FPSCounter=class extends Ei{constructor(t,e={}){super(t,"0 FPS",{x:0,y:0,font:ss.fonts.small,color:ss.colors.neonGreen,align:"center",baseline:"middle",debug:!1,...e}),this.fps=0,this._frames=0,this._accum=0}update(t){const e=this.game.actualFps;e&&(this._frames++,this._accum+=t,this._accum>=.5&&(this.fps=Math.round(e),this.text=`${this.fps} FPS`,this._accum=0,this._frames=0),super.update(t))}getBounds(){if(this.shape&&this.shape.getTextBounds){const t=this.shape.getTextBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}return super.getBounds()}getDebugBounds(){if(this.shape&&this.shape.getDebugBounds){const t=this.shape.getDebugBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}return super.getDebugBounds()}},t.FluentGO=ds,t.FluentGame=ms,t.FluentLayer=fs,t.FluentScene=ps,t.FluidSystem=us,t.Fractals=Ft,t.Game=is,t.GameObject=Pi,t.GameObjectShapeWrapper=Ai,t.Geometry2d=Oe,t.GridLayout=class extends Ii{constructor(t,e={}){super(t,e),this.columns=e.columns??4,this.debug=e.debug??!1}calculateLayout(){return this.children.length?It(this.children,{columns:this.columns,spacing:this.spacing,padding:this.padding,centerItems:this.centerItems,width:this.autoSize?void 0:this.width,height:this.autoSize?void 0:this.height}):null}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:-(this._contentHeight??this.height)/2}}},t.Group=Ge,t.Heart=mi,t.Hexagon=gi,t.HorizontalLayout=class extends Ii{getScrollAxis(){return{horizontal:!0,vertical:!1}}calculateLayout(){return Pt(this.children,{spacing:this.spacing,padding:this.padding,align:this.align,centerItems:!0})}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:0}}},t.ImageGo=class extends Ai{constructor(t,e,i={}){super(t,e instanceof vi?e:new vi(e,i),i)}reset(){this.shape.reset()}},t.ImageShape=vi,t.Input=wi,t.IsometricCamera=class{constructor(t={}){this.angle=t.angle??0,this._targetAngle=this.angle,this.rotationStep=t.rotationStep??Math.PI/2,this.animationDuration=t.animationDuration??.4,this.easingType=t.easing??"easeInOutCubic",this._animating=!1,this._animationProgress=0,this._startAngle=0,this._onRotationStart=null,this._onRotationEnd=null}rotateRight(){return this._animating||this._startRotation(this._targetAngle+this.rotationStep),this}rotateLeft(){return this._animating||this._startRotation(this._targetAngle-this.rotationStep),this}rotateTo(t){return this._animating||this._startRotation(t),this}setAngle(t){return this.angle=t,this._targetAngle=t,this._animating=!1,this}_startRotation(t){this._startAngle=this.angle,this._targetAngle=t,this._animationProgress=0,this._animating=!0,this._onRotationStart&&this._onRotationStart(this._startAngle,this._targetAngle)}update(t){if(this._animating)if(this._animationProgress+=t/this.animationDuration,this._animationProgress>=1)this._animationProgress=1,this.angle=this._targetAngle,this._animating=!1,this._onRotationEnd&&this._onRotationEnd(this.angle);else{const t=this._ease(this._animationProgress);this.angle=this._startAngle+(this._targetAngle-this._startAngle)*t}}_ease(t){switch(this.easingType){case"linear":return t;case"easeInQuad":return t*t;case"easeOutQuad":return t*(2-t);case"easeInOutQuad":return t<.5?2*t*t:(4-2*t)*t-1;case"easeInCubic":return t*t*t;case"easeOutCubic":return--t*t*t+1;case"easeInOutCubic":default:return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1;case"easeOutBack":const e=1.70158;return 1+(e+1)*Math.pow(t-1,3)+e*Math.pow(t-1,2)}}isAnimating(){return this._animating}getAngleDegrees(){return 180*this.angle/Math.PI%360}getNormalizedAngle(){let t=this.angle%(2*Math.PI);return t<0&&(t+=2*Math.PI),t}onRotationStart(t){return this._onRotationStart=t,this}onRotationEnd(t){return this._onRotationEnd=t,this}reset(){return this.setAngle(0),this}},t.IsometricScene=class extends Di{constructor(t,e={}){super(t,e),this.tileWidth=e.tileWidth??64,this.tileHeight=e.tileHeight??this.tileWidth/2,this.depthSort=e.depthSort??!0,this.scaleByDepth=e.scaleByDepth??!1,this.gridSize=e.gridSize??10,this.elevationScale=e.elevationScale??1,this.camera=e.camera??null}setCamera(t){return this.camera=t,this}toIsometric(t,e,i=0){let s=t,n=e;if(this.camera){const i=this.camera.angle,o=Math.cos(i),r=Math.sin(i);s=t*o-e*r,n=t*r+e*o}return{x:(s-n)*(this.tileWidth/2),y:(s+n)*(this.tileHeight/2)-i*this.elevationScale,depth:s+n-.01*i}}fromIsometric(t,e){const i=this.tileWidth/2,s=this.tileHeight/2;let n=(t/i+e/s)/2,o=(e/s-t/i)/2;if(this.camera){const t=-this.camera.angle,e=Math.cos(t),i=Math.sin(t);return{x:n*e-o*i,y:n*i+o*e}}return{x:n,y:o}}update(t){super.update(t),this.camera&&this.camera.update(t)}getTileAt(t,e){const i=this.fromIsometric(t,e);return{x:Math.floor(i.x),y:Math.floor(i.y)}}getDepthScale(t){return.7+Math.abs(t)/this.gridSize*.6}render(){if(!this.visible)return;Be.save(),Be.translateTo(this.x,this.y);const t=[];for(const e of this._collection.getSortedChildren()){if(!e.visible)continue;let i;if(void 0!==e.isoDepth)i=e.isoDepth;else{const t=e.z??0;i=e.x+e.y+.05*t}t.push({child:e,depth:i})}this.depthSort&&t.sort((t,e)=>{const i=t.child.zIndex??0,s=e.child.zIndex??0;return i!==s?i-s:t.depth-e.depth});for(const e of t)Be.save(),e.child.render(),Be.restore();Be.restore()}},t.Kernels=ue,t.Keys=Ci,t.LayoutScene=Ii,t.Line=Je,t.Loggable=Me,t.Logger=be,t.Motion=Ji,t.Mouse=Mi,t.Noise=Xt,t.OutlinedText=class extends Ne{constructor(t,e,i,s={}){super(t,e,s),this.text=i,this.centered=s.centered||!1,this.color=s.color||"#000000",this.stroke=s.stroke||"#FFFFFF",this.lineWidth=s.lineWidth||1,this.font=s.font||null,this.align=s.align||"left",this.baseline=s.baseline||"alphabetic",this.calculateDimensions()}calculateDimensions(){if(!Be.ctx)return console.warn("Painter context not initialized. Cannot calculate text dimensions."),this.width=0,void(this.height=0);const t=Be.text.font();this.font&&Be.text.setFont(this.font);const e=Be.text.measureText(this.text);if(this.width=e.width,this.font){const t=parseInt(this.font);this.height=isNaN(t)?20:t}else this.height=e.actualBoundingBoxAscent+e.actualBoundingBoxDescent||20;this.width+=2*this.lineWidth,this.height+=2*this.lineWidth,Be.text.setFont(t)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Be.ctx)return void console.warn("Painter context not initialized. Cannot draw text.");let t=0;this.font&&Be.text.setFont(this.font),Be.text.setTextAlign(this.align),Be.text.setTextBaseline(this.baseline),this.centered&&("middle"===this.baseline||"alphabetic"===this.baseline?t=0:"top"===this.baseline?t=this.height/2:"bottom"===this.baseline&&(t=-this.height/2)),Be.outlinedText(this.text,0,t,this.color,this.stroke,this.lineWidth,this.font)}getBounds(){if(!Be.ctx)return super.getBounds();const t=Be.text.font();Be.text.setFont(this.font);const e=Be.text.measureText(this.text),i=e.width,s=e.actualBoundingBoxAscent+e.actualBoundingBoxDescent||parseInt(this.font)||20;return Be.text.setFont(t),this.width=i,this.height=s,{x:this.x,y:this.y,width:i,height:s}}},t.Painter=Be,t.PainterColors=Ee,t.PainterEffects=Te,t.PainterImages=Re,t.PainterLines=Pe,t.PainterOpacity=Ae,t.PainterShapes=De,t.PainterText=Ie,t.Particle=os,t.ParticleEmitter=rs,t.ParticleSystem=hs,t.PatternRectangle=class extends Ne{constructor(t=null,e="repeat",i={}){super(i),this.image=t,this.repetition=e,this.pattern=null,t&&this._tryCreatePattern(t)}_tryCreatePattern(t){t instanceof HTMLImageElement||"boolean"==typeof t.complete?t.complete?this._createPattern():t.addEventListener("load",()=>this._createPattern(),{once:!0}):this._createPattern()}_createPattern(){this.pattern=Be.img.createPattern(this.image,this.repetition)}setImage(t,e){this.image=t,e&&(this.repetition=e),this.pattern=null,this._tryCreatePattern(t)}draw(){super.draw(),!this.pattern&&this.image&&this._tryCreatePattern(this.image);const t=-this.width/2,e=-this.height/2;this.pattern?Be.img.fillPattern(this.pattern,t,e,this.width,this.height):this.strokeColor&&Be.shapes.outlineRect(t,e,this.width,this.height,this.strokeColor,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},t.Patterns=class{static void(t,e,i={}){const{background:s=[255,255,255,255],foreground:n=[0,0,200,255]}=i,o=new Uint8ClampedArray(t*e*4);for(let t=0;t<o.length;t+=4)o[t]=s[0],o[t+1]=s[1],o[t+2]=s[2],o[t+3]=s[3];return o}static solidGrid(t,e,i={}){const{spacing:s=8,background:n=[0,0,0,0],foreground:o=[128,128,128,255]}=i,r=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++){const e=i%s===0;for(let a=0;a<t;a++){const h=4*(i*t+a),l=a%s===0||e?o:n;r[h]=l[0],r[h+1]=l[1],r[h+2]=l[2],r[h+3]=l[3]}}return r}static checkerboard(t,e,i={}){const{cellSize:s=8,color1:n=[0,0,0,255],color2:o=[255,255,255,255]}=i,r=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++){const e=Math.floor(i/s);for(let a=0;a<t;a++){const h=(Math.floor(a/s)+e)%2==0?n:o,l=4*(i*t+a);r.set(h,l)}}return r}static stripes(t,e,i={}){const{spacing:s=4,thickness:n=1,background:o=[0,0,0,0],foreground:r=[255,255,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++)for(let e=0;e<t;e++){const h=(e+i)%s<n,l=4*(i*t+e);a.set(h?r:o,l)}return a}static honeycomb(t,e,i={}){const{radius:s=10,lineWidth:n=1,foreground:o=[255,255,255,255],background:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=r[0],a[t+1]=r[1],a[t+2]=r[2],a[t+3]=r[3];const h=Math.floor(t/2),l=Math.floor(e/2),c=(t,e,i,s,n)=>{const o=Math.abs(t-i),r=Math.abs(e-s),a=n*Math.sqrt(3)/2;return!(r>a)&&!(o>n)&&n*a*2>=n*r*2+a*o},u=s-n,d=s*Math.sqrt(3),f=Math.max(0,Math.floor(h-s-1)),p=Math.min(t-1,Math.ceil(h+s+1)),g=Math.max(0,Math.floor(l-d/2-1)),m=Math.min(e-1,Math.ceil(l+d/2+1));for(let e=g;e<=m;e++)for(let i=f;i<=p;i++){const n=c(i,e,h,l,s),r=u>0&&c(i,e,h,l,u);if(n&&!r){const s=4*(e*t+i);a[s]=o[0],a[s+1]=o[1],a[s+2]=o[2],a[s+3]=o[3]}}return a}static harlequin(t,e,i={}){const{size:s=20,spacing:n=0,background:o=[255,255,255,255],foreground:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];const h=2*s,l=2*s,c=h+n,u=l+n,d=(t,e,i,s)=>Math.abs(t-i)/(h/2)+Math.abs(e-s)/(l/2)<=1;for(let i=-1;i<e/u+1;i++)for(let s=-1;s<t/c+1;s++){const n=s*c+c/2,o=i*u+u/2;if((i+s)%2!=0)continue;const f=Math.max(0,Math.floor(n-h/2)),p=Math.min(t-1,Math.ceil(n+h/2)),g=Math.max(0,Math.floor(o-l/2)),m=Math.min(e-1,Math.ceil(o+l/2));for(let e=g;e<=m;e++)for(let i=f;i<=p;i++)if(d(i,e,n,o)){const s=4*(e*t+i);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static circles(t,e,i={}){const{radius:s=10,lineWidth:n=2,spacing:o=5,background:r=[0,0,0,255],foreground:a=[255,255,255,255]}=i,h=new Uint8ClampedArray(t*e*4);for(let t=0;t<h.length;t+=4)h[t]=r[0],h[t+1]=r[1],h[t+2]=r[2],h[t+3]=r[3];const l=2*s+o,c=(t,e,i,s,n)=>{const o=t-i,r=e-s;return o*o+r*r<=n*n};for(let i=0;i<Math.ceil(e/l)+1;i++)for(let o=0;o<Math.ceil(t/l)+1;o++){const r=o*l+s,u=i*l+s;if(r<-s||r>t+s||u<-s||u>e+s)continue;const d=Math.max(0,Math.floor(r-s)),f=Math.min(t-1,Math.ceil(r+s)),p=Math.max(0,Math.floor(u-s)),g=Math.min(e-1,Math.ceil(u+s)),m=s-n;for(let e=p;e<=g;e++)for(let i=d;i<=f;i++){const n=c(i,e,r,u,s),o=c(i,e,r,u,m);if(n&&!o){const s=4*(e*t+i);h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]}}}return h}static diamonds(t,e,i={}){const{size:s=16,squareSize:n=6,background:o=[255,255,255,255],foreground:r=[0,0,0,255],innerColor:a=[255,255,255,255]}=i,h=new Uint8ClampedArray(t*e*4);for(let t=0;t<h.length;t+=4)h[t]=o[0],h[t+1]=o[1],h[t+2]=o[2],h[t+3]=o[3];const l=s,c=(t,e,i,s,n)=>Math.abs(t-i)+Math.abs(e-s)<=n/2,u=(t,e,i,s,n)=>Math.abs(t-i)<=n/2&&Math.abs(e-s)<=n/2;for(let i=-1;i<e/l+1;i++)for(let s=-1;s<t/l+1;s++){const o=s*l+l/2,d=i*l+l/2;if(o<-l||o>t+l||d<-l||d>e+l)continue;const f=Math.max(0,Math.floor(o-l/2)),p=Math.min(t-1,Math.ceil(o+l/2)),g=Math.max(0,Math.floor(d-l/2)),m=Math.min(e-1,Math.ceil(d+l/2));for(let e=g;e<=m;e++)for(let i=f;i<=p;i++){const s=c(i,e,o,d,l),f=u(i,e,o,d,n);if(s){const s=4*(e*t+i);f?(h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]):(h[s]=r[0],h[s+1]=r[1],h[s+2]=r[2],h[s+3]=r[3])}}}return h}static cubes(t,e,i={}){const{size:s=10,spacing:n=2,background:o=[0,0,0,255],foreground:r=[255,100,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];const h=s+n;for(let i=0;i<Math.ceil(e/h)+1;i++)for(let n=0;n<Math.ceil(t/h)+1;n++){const o=n*h,l=i*h;if(!(o>=t||l>=e))for(let i=l;i<Math.min(l+s,e);i++)for(let e=o;e<Math.min(o+s,t);e++){const s=4*(i*t+e);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static cross(t,e,i={}){const{size:s=8,thickness:n=2,spacing:o=16,background:r=[255,255,255,255],foreground:a=[80,80,80,255]}=i,h=new Uint8ClampedArray(t*e*4);for(let t=0;t<h.length;t+=4)h[t]=r[0],h[t+1]=r[1],h[t+2]=r[2],h[t+3]=r[3];for(let i=0;i<Math.ceil(e/o)+1;i++)for(let r=0;r<Math.ceil(t/o)+1;r++){const l=r*o,c=i*o;if(l<-s||l>t+s||c<-s||c>e+s)continue;const u=l-s/2,d=l+s/2,f=c-n/2,p=c+n/2;for(let i=Math.max(0,Math.floor(f));i<Math.min(e,Math.ceil(p));i++)for(let e=Math.max(0,Math.floor(u));e<Math.min(t,Math.ceil(d));e++){const s=4*(i*t+e);h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]}const g=l-n/2,m=l+n/2,y=c-s/2,x=c+s/2;for(let i=Math.max(0,Math.floor(y));i<Math.min(e,Math.ceil(x));i++)for(let e=Math.max(0,Math.floor(g));e<Math.min(t,Math.ceil(m));e++){const s=4*(i*t+e);h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]}}return h}static mesh(t,e,i={}){const{spacing:s=20,lineWidth:n=2,background:o=[255,255,255,0],foreground:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];for(let i=0;i<e;i++)for(let o=0;o<t;o++){const h=(o+i)%s,l=(o-i+e)%s;if(h<n||h>s-n||l<n||l>s-n){const e=4*(i*t+o);a[e]=r[0],a[e+1]=r[1],a[e+2]=r[2],a[e+3]=r[3]}}return a}static isometric(t,e,i={}){const{cellSize:s=20,lineWidth:n=1,background:o=[0,0,0,0],foreground:r=[0,255,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];const h=s,l=s/2;for(let i=0;i<e;i++)for(let e=0;e<t;e++){const s=e%h,o=i%l,c=o-s/2,u=o+s/2-l,d=Math.abs(c)<n/2,f=Math.abs(u)<n/2;if(d||f){const s=4*(i*t+e);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static weave(t,e,i={}){const{tileSize:s=40,lineWidth:n=2,background:o=[255,255,255,255],foreground:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];for(let i=0;i<e;i++)for(let e=0;e<t;e++){const o=e%s,h=i%s,l=Math.abs((h+s/2)%s-s/2)<n/2,c=Math.abs((o+2*h+1.5*s)%s-s/2)<n/2,u=Math.abs((o-2*h+1.5*s)%s-s/2)<n/2;if(l||c||u){const s=4*(i*t+e);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static perlinNoise(t,e,i={}){const{background:s=[0,0,0,0],foreground:n=[255,255,255,255],scale:o=.1,octaves:r=4,persistence:a=.5,lacunarity:h=2,seed:l=65536*Math.random()}=i,c=new Uint8ClampedArray(t*e*4);Xt.seed(l);for(let i=0;i<e;i++)for(let e=0;e<t;e++){let l=1,u=1,d=0,f=0;for(let t=0;t<r;t++){const t=e*o*u,s=i*o*u;d+=Xt.perlin2(t,s)*l,f+=l,l*=a,u*=h}d/=f;const p=.5*(d+1),g=[Math.floor(s[0]+p*(n[0]-s[0])),Math.floor(s[1]+p*(n[1]-s[1])),Math.floor(s[2]+p*(n[2]-s[2])),Math.floor(s[3]+p*(n[3]-s[3]))],m=4*(i*t+e);c.set(g,m)}return c}static circularGradient(t,e,i={}){const{innerColor:s=[255,255,255,255],outerColor:n=[0,0,0,255],centerX:o=t/2,centerY:r=e/2,radius:a=Math.min(t,e)/2,fadeExponent:h=1}=i,l=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++)for(let e=0;e<t;e++){const c=4*(i*t+e),u=e-o,d=i-r,f=Math.sqrt(u*u+d*d);let p=Math.min(f/a,1);p=Math.pow(p,h);const g=[Math.floor(s[0]+p*(n[0]-s[0])),Math.floor(s[1]+p*(n[1]-s[1])),Math.floor(s[2]+p*(n[2]-s[2])),Math.floor(s[3]+p*(n[3]-s[3]))];l.set(g,c)}return l}static noiseDisplacement(t,e,i={}){const{gridSpacing:s=16,gridColor:n=[255,255,255,255],background:o=[0,0,0,0],displacementScale:r=8,noiseScale:a=.05,gridThickness:h=1,seed:l=65536*Math.random()}=i,c=new Uint8ClampedArray(t*e*4);Xt.seed(l);for(let t=0;t<c.length;t+=4)c.set(o,t);for(let i=0;i<e;i++)for(let e=0;e<t;e++){const o=e+Xt.perlin2(e*a,i*a)*r,l=i+Xt.perlin2((e+31.416)*a,(i+27.182)*a)*r;if(o%s<h||o%s>s-h||l%s<h||l%s>s-h){const s=4*(i*t+e);c.set(n,s)}}return c}static dotPattern(t,e,i={}){const{dotSize:s=3,spacing:n=12,dotColor:o=[0,0,0,255],background:r=[255,255,255,255],useNoise:a=!1,noiseScale:h=.1,noiseDensity:l=.4,seed:c=65536*Math.random()}=i,u=new Uint8ClampedArray(t*e*4);a&&Xt.seed(c);for(let t=0;t<u.length;t+=4)u.set(r,t);if(a){for(let i=0;i<e;i++)for(let n=0;n<t;n++)if(.5*(Xt.perlin2(n*h,i*h)+1)>l)for(let r=-s;r<=s;r++)for(let a=-s;a<=s;a++){const h=n+a,l=i+r;if(h>=0&&h<t&&l>=0&&l<e&&a*a+r*r<=s*s){const e=4*(l*t+h);u.set(o,e)}}}else for(let i=Math.floor(n/2);i<e;i+=n)for(let r=Math.floor(n/2);r<t;r+=n)for(let n=-s;n<=s;n++)for(let a=-s;a<=s;a++){const h=r+a,l=i+n;if(h>=0&&h<t&&l>=0&&l<e&&a*a+n*n<=s*s){const e=4*(l*t+h);u.set(o,e)}}return u}static voronoi(t,e,i={}){const{cellCount:s=20,cellColors:n=null,edgeColor:o=[0,0,0,255],edgeThickness:r=1.5,seed:a=1e3*Math.random(),jitter:h=.5,baseColor:l=null,colorVariation:c=.3}=i,u=new Uint8ClampedArray(t*e*4);Xt.seed(a);const d=[],f=[],p=()=>{let t=1e4*Math.sin(.167*a+.423*d.length);return t-Math.floor(t)},g=Math.sqrt(s),m=t/g,y=e/g,x=t=>{if(l){const[e,i,s,n]=l,o=Math.max(e,i,s)/255,r=Math.min(e,i,s)/255,a=(o+r)/2;let h,u;if(o===r)h=u=0;else{const t=o-r;u=a>.5?t/(2-o-r):t/(o+r),h=o===e/255?(i/255-s/255)/t+(i/255<s/255?6:0):o===i/255?(s/255-e/255)/t+2:(e/255-i/255)/t+4,h/=6}const d=Xt.perlin2(.15*t,0)*c*.3,f=Xt.perlin2(0,.15*t)*c,g=Xt.perlin2(.15*t,.15*t)*c*.5;h=(h+d)%1,u=Math.min(1,Math.max(0,u*(1+f)));const m=Math.min(.9,Math.max(.1,a*(1+g)));let y,x,v;if(0===u)y=x=v=m;else{const t=(t,e,i)=>(i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t),e=m<.5?m*(1+u):m+u-m*u,i=2*m-e;y=t(i,e,h+1/3),x=t(i,e,h),v=t(i,e,h-1/3)}const _=.05,w=()=>(2*p()-1)*_;return[Math.min(255,Math.max(0,Math.floor(255*y*(1+w())))),Math.min(255,Math.max(0,Math.floor(255*x*(1+w())))),Math.min(255,Math.max(0,Math.floor(255*v*(1+w())))),n]}{let e,i,s;const n=.618033988749895*t%1*6,o=Math.floor(n),r=n-o,a=.5,h=.5*(1-r),l=.5*(1-(1-r));switch(o%6){case 0:e=.5,i=l,s=a;break;case 1:e=h,i=.5,s=a;break;case 2:e=a,i=.5,s=l;break;case 3:e=a,i=h,s=.5;break;case 4:e=l,i=a,s=.5;break;case 5:e=.5,i=a,s=h}return[Math.floor(255*e+50+100*p()),Math.floor(255*i+50+100*p()),Math.floor(255*s+50+100*p()),255]}};for(let t=0;t<g;t++)for(let e=0;e<g&&!(d.length>=s);e++){const i=e*m+m/2,s=t*y+y/2,o=(2*p()-1)*h*m,r=(2*p()-1)*h*y;d.push({x:Math.floor(i+o),y:Math.floor(s+r)}),n&&d.length-1<n.length?f.push(n[d.length-1]):f.push(x(d.length-1))}const v=(i,s,n,o)=>{let r=Math.abs(i-n),a=Math.abs(s-o);return r=Math.min(r,t-r),a=Math.min(a,e-a),.8*Math.sqrt(r*r+a*a)+.2*(r+a)};for(let i=0;i<e;i++)for(let s=0;s<t;s++){const n=4*(i*t+s);let a=1/0,h=1/0,l=0;for(let t=0;t<d.length;t++){const e=v(s,i,d[t].x,d[t].y);e<a?(h=a,a=e,l=t):e<h&&(h=e)}for(let n=0;n<d.length;n++)for(let o=-1;o<=1;o++)for(let r=-1;r<=1;r++){if(0===o&&0===r)continue;const c=d[n].x+o*t,u=d[n].y+r*e,f=Math.sqrt(Math.pow(s-c,2)+Math.pow(i-u,2));f<a?(h=a,a=f,l=n):f<h&&(h=f)}h-a<r?u.set(o,n):u.set(f[l],n)}return u}static penrose(t,e,i={}){return Yt(t,e,i)}},t.PieSlice=class extends Ne{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Be.lines.beginPath(),Be.lines.moveTo(0,0),Be.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle),Be.lines.closePath(),this.color&&Be.colors.fill(this.color),this.stroke&&Be.colors.stroke(this.stroke,this.lineWidth)}},t.Pin=pi,t.Pipeline=es,t.Plane3D=li,t.PlatformerScene=class extends Di{constructor(t,e={}){super(t,e),this.player=e.player??null,this._layers=[],this.gravity=e.gravity??1200,this.groundY=e.groundY??null,this.moveSpeed=e.moveSpeed??300,this.jumpVelocity=e.jumpVelocity??-500,this.autoInput=e.autoInput??!0,this.autoGravity=e.autoGravity??!0,this._viewportWidth=e.viewportWidth??null,this._viewportHeight=e.viewportHeight??null,this.player&&(void 0===this.player.vx&&(this.player.vx=0),void 0===this.player.vy&&(this.player.vy=0),void 0===this.player._grounded&&(this.player._grounded=!0)),e.camera?this.camera=e.camera:this.player?this.camera=new zt({target:this.player,viewportWidth:this._viewportWidth??t.width,viewportHeight:this._viewportHeight??t.height,lerp:.1}):this.camera=null}addLayer(t,e={}){const i={gameObject:t,speed:e.speed??1,offsetX:e.offsetX??0,offsetY:e.offsetY??0};return this._layers.push(i),this.add(t),t}removeLayer(t){const e=this._layers.findIndex(e=>e.gameObject===t);return-1!==e&&(this._layers.splice(e,1),this.remove(t),!0)}getLayers(){return[...this._layers]}isLayer(t){return this._layers.some(e=>e.gameObject===t)}applyGravity(t,e){t.vy=(t.vy||0)+this.gravity*e}applyInput(t,e){let i=0;Ci.isDown(Ci.LEFT)||Ci.isDown(Ci.A)?i=-1:(Ci.isDown(Ci.RIGHT)||Ci.isDown(Ci.D))&&(i=1),t.vx=i*this.moveSpeed,(Ci.isDown(Ci.SPACE)||Ci.isDown(Ci.W)||Ci.isDown(Ci.UP))&&this.isPlayerGrounded()&&(t.vy=this.jumpVelocity,t._grounded=!1)}updateCamera(t){this.camera&&this.camera.update(t)}getCameraOffset(){return this.camera?this.camera.getOffset():{x:0,y:0}}isPlayerGrounded(){var t;return!0===(null==(t=this.player)?void 0:t._grounded)}applyVelocity(t,e){t.x+=(t.vx||0)*e,t.y+=(t.vy||0)*e}handleGroundCollision(t){null!==this.groundY&&t.y>=this.groundY&&(t.y=this.groundY,t.vy=0,t._grounded=!0)}update(t){this.player&&(this.autoGravity&&this.applyGravity(this.player,t),this.autoInput&&this.applyInput(this.player,t),this.applyVelocity(this.player,t),this.handleGroundCollision(this.player)),this.updateCamera(t),super.update(t)}draw(){this.applyTransforms(),this.drawDebug();const t=this._viewportWidth??this.game.width,e=this._viewportHeight??this.game.height,i=this.getCameraOffset();Be.save(),Be.ctx.beginPath(),Be.ctx.rect(-this.x,-this.y,t,e),Be.ctx.clip(),Be.ctx.beginPath(),Be.ctx.translate(-this.x,-this.y);for(const t of this._layers){if(!t.gameObject.visible)continue;Be.save();const e=i.x*t.speed+(t.offsetX||0),s=i.y*t.speed+(t.offsetY||0);Be.ctx.translate(-e,-s),t.gameObject.render(),Be.restore()}for(const t of this._collection.getSortedChildren())t.visible&&(this._layers.some(e=>e.gameObject===t)||(Be.save(),Be.ctx.translate(-i.x,-i.y),t.render(),Be.restore()));Be.restore()}shakeCamera(t,e){return this.camera&&this.camera.shake(t,e),this}setViewport(t,e){return this._viewportWidth=t,this._viewportHeight=e,this.camera&&(this.camera.viewportWidth=t,this.camera.viewportHeight=e),this}getViewport(){return{width:this._viewportWidth??this.game.width,height:this._viewportHeight??this.game.height}}},t.Polygon=di,t.Position=Tt,t.Prism=class extends Ne{constructor(t=100,e={}){super(e),this.depth=t,this.faceTopColor=e.faceTopColor||"#eee",this.faceBottomColor=e.faceBottomColor||"#ccc",this.faceLeftColor=e.faceLeftColor||"#aaa",this.faceRightColor=e.faceRightColor||"#888",this.faceFrontColor=e.faceFrontColor||"#666",this.faceBackColor=e.faceBackColor||"#444",this.stroke=e.stroke||null,this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0,this.visibleFaces=e.visibleFaces||["top","left","right","front","back","bottom"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.width/2,e=this.height/2,i=this.depth/2,s=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},n=(t,e,i)=>{const n=s(t,e,i);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z,z:n.z}},o={p0:n(-t,-i,-e),p1:n(t,-i,-e),p2:n(0,-i,e),p3:n(-t,i,-e),p4:n(t,i,-e),p5:n(0,i,e)},r={front:{points:[o.p0,o.p1,o.p2],color:this.faceFrontColor},back:{points:[o.p3,o.p4,o.p5],color:this.faceBackColor},bottom:{points:[o.p0,o.p1,o.p4,o.p3],color:this.faceBottomColor},right:{points:[o.p1,o.p2,o.p5,o.p4],color:this.faceRightColor},left:{points:[o.p0,o.p2,o.p5,o.p3],color:this.faceLeftColor}};this.visibleFaces.filter(t=>r[t]).map(t=>{const e=r[t],i=e.points.reduce((t,e)=>t+e.x,0)/e.points.length,s=e.points.reduce((t,e)=>t+e.y,0)/e.points.length,n=e.points.reduce((t,e)=>t+(e.z||0),0)/e.points.length;return{key:t,face:e,depth:i*i+s*s+n*n}}).sort((t,e)=>e.depth-t.depth).forEach(({key:t,face:e})=>{(null==e?void 0:e.color)&&Be.shapes.polygon(e.points,e.color,this.stroke,this.lineWidth)})}getBounds(){const t=1.5*Math.max(this.width,this.height,this.depth);return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Random=Bt,t.Rectangle=Ve,t.Renderable=Ye,t.Ring=ui,t.RoundedRectangle=$e,t.SPHERE_SHADERS=si,t.SVGShape=ci,t.Scene=Di,t.Scene3D=class extends Di{constructor(t,e={}){if(super(t,e),!e.camera)throw new Error("Scene3D requires a camera option");this.camera=e.camera,this.depthSort=e.depthSort??!0,this.scaleByDepth=e.scaleByDepth??!0}render(){if(!this.visible)return;Be.save(),Be.translateTo(this.x,this.y);const t=[];for(const e of this._collection.getSortedChildren()){if(!e.visible)continue;const i=e.z??0,s=this.camera.project(e.x,e.y,i);s.z<10-this.camera.perspective||t.push({child:e,x:s.x,y:s.y,z:s.z,scale:s.scale})}this.depthSort&&t.sort((t,e)=>{const i=t.child.zIndex??0,s=e.child.zIndex??0;return i!==s?i-s:e.z-t.z});for(const e of t)Be.save(),Be.translateTo(e.x,e.y),this.scaleByDepth&&Be.ctx.scale(e.scale,e.scale),Be.translateTo(-e.child.x,-e.child.y),e.child.render(),Be.restore();Be.restore()}},t.Shape=Ne,t.ShapeGOFactory=class{static create(t,e,i={}){const s={x:(null==e?void 0:e.x)??0,y:(null==e?void 0:e.y)??0,width:(null==e?void 0:e.width)??0,height:(null==e?void 0:e.height)??0,rotation:(null==e?void 0:e.rotation)??0,scaleX:(null==e?void 0:e.scaleX)??1,scaleY:(null==e?void 0:e.scaleY)??1,opacity:(null==e?void 0:e.opacity)??1,visible:(null==e?void 0:e.visible)??!0,active:!0,debug:(null==e?void 0:e.debug)??!1,color:(null==e?void 0:e.color)??null,stroke:(null==e?void 0:e.stroke)??null,lineWidth:(null==e?void 0:e.lineWidth)??1,lineJoin:(null==e?void 0:e.lineJoin)??"miter",lineCap:(null==e?void 0:e.lineCap)??"butt",miterLimit:(null==e?void 0:e.miterLimit)??10,...i,name:i.name??(null==e?void 0:e.constructor.name)??"ShapeWrapper"};return new Ai(t,e,s)}},t.Sound=class{static beep(t=440,e=.1,i={}){if(!Ms.isInitialized)return;const{volume:s=.3,type:n="sine"}=i;Ms.osc.tone(t,e,{type:n,volume:s,attack:.001,decay:.8*e,sustain:0,release:.2*e})}static click(t=.3){Ms.isInitialized&&Ms.osc.tone(1e3,.01,{type:"square",volume:t,attack:.001,decay:.009,sustain:0,release:.001})}static sweep(t,e,i,s={}){if(!Ms.isInitialized)return;const{volume:n=.3,type:o="sine"}=s;Ms.osc.sweep(t,e,i,{type:o,volume:n})}static fromValue(t,e={}){if(!Ms.isInitialized)return;const{root:i="C4",scale:s="pentatonic",octaves:n=2,duration:o=.2,volume:r=.3,type:a="sine"}=e,h=Ms.music.mapToScale(t,i,s,n);Ms.osc.tone(h,o,{volume:r,type:a})}static impact(t=.5){if(!Ms.isInitialized)return;const e=80+200*t,i=.05+.15*t;Ms.osc.tone(e,i,{type:"sine",volume:.4*t,attack:.001,decay:i,sustain:0,release:.02});const s=Ms.noise.white(Ms.ctx,.08),n=Ms.ctx.createGain();n.gain.setValueAtTime(.25*t,Ms.now),n.gain.exponentialRampToValueAtTime(.001,Ms.now+.08),s.connect(n),n.connect(Ms.master),s.start(),s.stop(Ms.now+.1)}static explosion(t=.7){if(!Ms.isInitialized)return;const e=.3+.4*t;Ms.osc.tone(50+30*t,e,{type:"sine",volume:.4*t,attack:.001,decay:.3*e,sustain:.3,release:.7*e});const i=Ms.noise.brown(Ms.ctx,e),s=Ms.ctx.createGain(),n=Ms.fx.filter("lowpass",800+400*t,1);s.gain.setValueAtTime(.5*t,Ms.now),s.gain.exponentialRampToValueAtTime(.001,Ms.now+e),i.connect(n),n.connect(s),s.connect(Ms.master),i.start(),i.stop(Ms.now+e+.1)}static laser(t={}){if(!Ms.isInitialized)return;const{startFreq:e=1200,endFreq:i=200,duration:s=.15,volume:n=.25,type:o="sawtooth"}=t;Ms.osc.sweep(e,i,s,{type:o,volume:n})}static powerUp(t={}){if(!Ms.isInitialized)return;const{startFreq:e=300,endFreq:i=1200,duration:s=.3,volume:n=.3}=t;Ms.osc.sweep(e,i,s,{type:"square",volume:n}),Ms.osc.sweep(1.5*e,1.5*i,s,{type:"sine",volume:.5*n})}static hurt(t=.5){Ms.isInitialized&&(Ms.osc.tone(80+40*t,.1,{type:"sine",volume:.4*t,attack:.001,decay:.08,sustain:0,release:.02}),Ms.osc.tone(200+100*t,.08,{type:"sawtooth",volume:.2*t,attack:.001,decay:.06,sustain:0,release:.02}))}static coin(t={}){if(!Ms.isInitialized)return;const{baseFreq:e=987.77,volume:i=.25}=t;Ms.osc.tone(e,.08,{type:"square",volume:i,attack:.001,decay:.05,sustain:.3,release:.02}),setTimeout(()=>{Ms.isInitialized&&Ms.osc.tone(1.5*e,.12,{type:"square",volume:i,attack:.001,decay:.08,sustain:.2,release:.04})},80)}static jump(t={}){if(!Ms.isInitialized)return;const{startFreq:e=150,endFreq:i=400,duration:s=.15,volume:n=.25}=t;Ms.osc.sweep(e,i,s,{type:"square",volume:n})}static select(t={}){if(!Ms.isInitialized)return;const{frequency:e=660,volume:i=.2}=t;Ms.osc.tone(e,.08,{type:"sine",volume:i,attack:.001,decay:.05,sustain:.3,release:.03})}static error(t={}){if(!Ms.isInitialized)return;const{volume:e=.25}=t;Ms.osc.tone(400,.1,{type:"square",volume:e,attack:.001,decay:.08,sustain:0,release:.02}),setTimeout(()=>{Ms.isInitialized&&Ms.osc.tone(300,.15,{type:"square",volume:e,attack:.001,decay:.12,sustain:0,release:.03})},100)}static drone(t="C2",e={}){if(!Ms.isInitialized)return null;const{volume:i=.2,richness:s=.5}=e,n=Ms.music.noteToFreq(t),o=[],r=[],a=[1,.5*s,.3*s,.2*s];return[n,1.5*n,2*n,3*n].forEach((t,e)=>{const s=Ms.ctx.createOscillator(),n=Ms.ctx.createGain();s.type="sine",s.frequency.value=t,n.gain.value=a[e]*i,s.connect(n),n.connect(Ms.master),s.start(),o.push(s),r.push(n)}),{stop:(t=.5)=>{const e=Ms.now;r.forEach(i=>{i.gain.linearRampToValueAtTime(0,e+t)}),setTimeout(()=>{o.forEach(t=>{try{t.stop()}catch(t){}})},1e3*t+100)},setVolume:t=>{r.forEach((e,i)=>{e.gain.linearRampToValueAtTime(a[i]*t,Ms.now+.1)})}}}static note(t,e=.5,i={}){if(!Ms.isInitialized)return;const{volume:s=.3,type:n="sine",envelope:o={}}=i,r=Ms.music.noteToFreq(t);Ms.osc.tone(r,e,{type:n,volume:s,...Ms.env.presets.pluck,...o})}static chord(t,e="major",i=.5,s={}){if(!Ms.isInitialized)return;const{volume:n=.2,type:o="sine",strum:r=0}=s,a=Ms.music.chord(t,e);a.forEach((t,e)=>{const s=r*e;Ms.osc.tone(t,i,{type:o,volume:n/a.length,attack:.01,decay:.1,sustain:.6,release:.2,startTime:Ms.now+s})})}static sequence(t,e=.2,i=0,s={}){if(!Ms.isInitialized)return;const{volume:n=.3,type:o="sine"}=s,r=e+i;t.forEach((t,i)=>{const s=Ms.now+i*r,a=Ms.music.noteToFreq(t);Ms.osc.tone(a,e,{type:o,volume:n,attack:.01,decay:.05,sustain:.5,release:.1,startTime:s})})}static win(){Ms.isInitialized&&this.sequence(["C5","E5","G5","C6"],.15,.05,{volume:.25,type:"square"})}static lose(){Ms.isInitialized&&this.sequence(["E4","D4","C4"],.25,0,{volume:.25,type:"sawtooth"})}},t.Sphere=class extends Ne{constructor(t=50,e={}){super(e),this.radius=t,this.hSegments=e.hSegments||16,this.vSegments=e.vSegments||12,this.color=e.color||"#6495ED",this.highlightColor=e.highlightColor||"#FFFFFF",this.wireframe=e.wireframe||!1,this.stroke=e.stroke||"#333333",this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}calculateSurfaceColor(t,e,i){let s=t*(1/Math.sqrt(3))+e*(1/Math.sqrt(3))+i*(1/Math.sqrt(3));if(s=Math.max(.3,s),this.highlightColor){const t=this.hexToRgb(this.color),e=this.hexToRgb(this.highlightColor);return`rgb(${Math.round(t.r*(1-s)+e.r*s)}, ${Math.round(t.g*(1-s)+e.g*s)}, ${Math.round(t.b*(1-s)+e.b*s)})`}const n=this.hexToRgb(this.color);return`rgb(${Math.min(255,Math.round(n.r*s))}, ${Math.min(255,Math.round(n.g*s))}, ${Math.min(255,Math.round(n.b*s))})`}hexToRgb(t){const e={r:100,g:100,b:255};if(!t||"string"!=typeof t)return e;const i=t.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,(t,e,i,s)=>e+e+i+i+s+s),s=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(i);return s?{r:parseInt(s[1],16),g:parseInt(s[2],16),b:parseInt(s[3],16)}:e}draw(){super.draw();const t=this.radius,e=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},i=(i,s,n)=>{const o=e(i,s,n);return{x:(o.x-o.y)*Math.cos(Math.PI/6),y:(o.x+o.y)*Math.sin(Math.PI/6)-o.z,z:o.z,nx:o.x/t,ny:o.y/t,nz:o.z/t}},s=[];for(let e=0;e<=this.vSegments;e++){const n=[],o=e/this.vSegments,r=Math.PI*o-Math.PI/2;for(let e=0;e<=this.hSegments;e++){const s=e/this.hSegments,o=2*Math.PI*s,a=t*Math.cos(r)*Math.cos(o),h=t*Math.cos(r)*Math.sin(o),l=t*Math.sin(r);n.push(i(a,h,l))}s.push(n)}const n=[];for(let t=0;t<this.vSegments;t++)for(let e=0;e<this.hSegments;e++){const i=s[t][e],o=s[t][e+1],r=s[t+1][e],a=s[t+1][e+1],h=(i.z+o.z+r.z+a.z)/4,l=(i.nx+o.nx+r.nx+a.nx)/4,c=(i.ny+o.ny+r.ny+a.ny)/4,u=(i.nz+o.nz+r.nz+a.nz)/4;n.push({points:[i,o,a,r],z:h,color:this.calculateSurfaceColor(l,c,u)})}if(n.sort((t,e)=>e.z-t.z),this.wireframe)for(const t of n){const e=t.points;for(let t=0;t<e.length;t++){const i=(t+1)%e.length;Be.lines.line(e[t].x,e[t].y,e[i].x,e[i].y,this.stroke,this.lineWidth)}}for(const t of n)Be.shapes.polygon(t.points,t.color,this.stroke,this.lineWidth)}getBounds(){const t=2*this.radius*1.5;return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Sphere3D=oi,t.Sprite=zi,t.SpriteSheet=Bi,t.Square=je,t.Star=ti,t.StateMachine=ks,t.Stepper=class extends Pi{constructor(t,e={}){super(t,e);const{x:i=0,y:s=0,value:n=0,min:o=-1/0,max:r=1/0,step:a=1,buttonSize:h=32,valueWidth:l=60,height:c=32,gap:u=4,font:d=ss.fonts.medium,onChange:f=null,formatValue:p=null,label:g=""}=e;this.x=i,this.y=s,this.buttonSize=h,this.valueWidth=l,this.stepperHeight=c,this.gap=u,this.font=d,this._value=this.clamp(n,o,r),this.min=o,this.max=r,this.step=a,this.onChange=f,this.formatValue=p||(t=>String(t)),this.labelText=g,this.width=h+u+l+u+h,this.height=g?c+20:c,this.initComponents(),this.initEvents()}clamp(t,e,i){return Math.max(e,Math.min(i,t))}initComponents(){this.group=new Ge;const t=this.width/2,e=this.buttonSize/2;this.valueWidth;const i=-t+e,s=t-e,n=this.labelText?8:0,o=this.labelText?-(this.stepperHeight/2+4):0;this.labelText&&(this.label=new xi(this.labelText,{font:ss.fonts.small,color:ss.colors.dimText,align:"center",baseline:"middle"}),this.label.y=o,this.group.add(this.label)),this.decrementBg=new Ve({width:this.buttonSize,height:this.stepperHeight,color:ss.button.default.bg,stroke:ss.button.default.stroke,lineWidth:1}),this.decrementBg.x=i,this.decrementBg.y=n,this.decrementText=new xi("−",{font:this.font,color:ss.button.default.text,align:"center",baseline:"middle"}),this.decrementText.x=i,this.decrementText.y=n,this.valueBg=new Ve({width:this.valueWidth,height:this.stepperHeight,color:ss.colors.darkerBg,stroke:ss.colors.subtleBorder,lineWidth:1}),this.valueBg.x=0,this.valueBg.y=n,this.valueText=new xi(this.formatValue(this._value),{font:this.font,color:ss.colors.neonGreen,align:"center",baseline:"middle"}),this.valueText.x=0,this.valueText.y=n,this.incrementBg=new Ve({width:this.buttonSize,height:this.stepperHeight,color:ss.button.default.bg,stroke:ss.button.default.stroke,lineWidth:1}),this.incrementBg.x=s,this.incrementBg.y=n,this.incrementText=new xi("+",{font:this.font,color:ss.button.default.text,align:"center",baseline:"middle"}),this.incrementText.x=s,this.incrementText.y=n,this.group.add(this.decrementBg),this.group.add(this.decrementText),this.group.add(this.valueBg),this.group.add(this.valueText),this.group.add(this.incrementBg),this.group.add(this.incrementText),this._decrementBounds={x:i-this.buttonSize/2,y:n-this.stepperHeight/2,width:this.buttonSize,height:this.stepperHeight},this._incrementBounds={x:s-this.buttonSize/2,y:n-this.stepperHeight/2,width:this.buttonSize,height:this.stepperHeight},this._decrementHover=!1,this._incrementHover=!1,this._decrementPressed=!1,this._incrementPressed=!1}initEvents(){this.interactive=!0,this._isMouseOver=!1,this.on("mouseover",()=>{this._isMouseOver=!0}),this.on("mouseout",()=>{this._isMouseOver=!1,this.handleMouseOut()}),this.game.events.on("inputmove",t=>{this._isMouseOver&&this.handleMouseMove(t)}),this.on("inputdown",t=>this.handleInputDown(t)),this.on("inputup",()=>this.handleInputUp())}screenToLocal(t,e){let i=t,s=e;const n=[];let o=this;for(;o;)n.unshift(o),o=o.parent;for(const t of n){if(i-=t.x||0,s-=t.y||0,t.rotation){const e=Math.cos(-t.rotation),n=Math.sin(-t.rotation),o=i;i=o*e-s*n,s=o*n+s*e}void 0!==t.scaleX&&0!==t.scaleX&&(i/=t.scaleX),void 0!==t.scaleY&&0!==t.scaleY&&(s/=t.scaleY)}return{x:i,y:s}}isPointInBounds(t,e,i){return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}handleMouseMove(t){const e=this.screenToLocal(t.x,t.y),i=this._decrementHover,s=this._incrementHover;this._decrementHover=this.isPointInBounds(e.x,e.y,this._decrementBounds),this._incrementHover=this.isPointInBounds(e.x,e.y,this._incrementBounds),i===this._decrementHover&&s===this._incrementHover||this.updateButtonStates(),this._decrementHover||this._incrementHover?this.game.canvas.style.cursor="pointer":this.game.canvas.style.cursor="default"}handleMouseOut(){this._decrementHover=!1,this._incrementHover=!1,this._decrementPressed=!1,this._incrementPressed=!1,this.updateButtonStates(),this.game.canvas.style.cursor="default"}handleInputDown(t){const e=this.screenToLocal(t.x,t.y);this.isPointInBounds(e.x,e.y,this._decrementBounds)?(this._decrementPressed=!0,this.decrement()):this.isPointInBounds(e.x,e.y,this._incrementBounds)&&(this._incrementPressed=!0,this.increment()),this.updateButtonStates()}handleInputUp(){this._decrementPressed=!1,this._incrementPressed=!1,this.updateButtonStates()}updateButtonStates(){this._decrementPressed?(this.decrementBg.color=ss.button.pressed.bg,this.decrementBg.stroke=ss.button.pressed.stroke,this.decrementText.color=ss.button.pressed.text):this._decrementHover?(this.decrementBg.color=ss.button.hover.bg,this.decrementBg.stroke=ss.button.hover.stroke,this.decrementText.color=ss.button.hover.text):(this.decrementBg.color=ss.button.default.bg,this.decrementBg.stroke=ss.button.default.stroke,this.decrementText.color=ss.button.default.text),this._value<=this.min&&(this.decrementBg.stroke=ss.colors.subtleBorder,this.decrementText.color=ss.colors.dimText),this._incrementPressed?(this.incrementBg.color=ss.button.pressed.bg,this.incrementBg.stroke=ss.button.pressed.stroke,this.incrementText.color=ss.button.pressed.text):this._incrementHover?(this.incrementBg.color=ss.button.hover.bg,this.incrementBg.stroke=ss.button.hover.stroke,this.incrementText.color=ss.button.hover.text):(this.incrementBg.color=ss.button.default.bg,this.incrementBg.stroke=ss.button.default.stroke,this.incrementText.color=ss.button.default.text),this._value>=this.max&&(this.incrementBg.stroke=ss.colors.subtleBorder,this.incrementText.color=ss.colors.dimText)}increment(){this.value=this._value+this.step}decrement(){this.value=this._value-this.step}get value(){return this._value}set value(t){const e=this.clamp(t,this.min,this.max);e!==this._value&&(this._value=e,this.valueText.text=this.formatValue(this._value),this.updateButtonStates(),"function"==typeof this.onChange&&this.onChange(this._value))}setBounds(t,e){this.min=t,this.max=e,this.value=this._value}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}draw(){super.draw(),this.group.render()}},t.StickFigure=class extends Ne{constructor(t=1,e={}){super(e),this.scale=t,this.stroke=e.stroke||"#000",this.headColor=e.headColor||this.stroke,this.jointColor=e.jointColor||this.stroke,this.lineWidth=e.lineWidth||2,this.showJoints=!1!==e.showJoints}draw(){super.draw();const t=this.scale,e=10*t,i=-30*t,s=i+e,n=s+40*t,o=s+10*t,r=15*t,a=10*t,h=n+40*t,l=3*t;Be.shapes.fillCircle(0,i,e,this.headColor),Be.shapes.strokeCircle(0,i,e,this.stroke,this.lineWidth),Be.lines.line(0,s,0,n,this.stroke,this.lineWidth),Be.lines.line(-r,o,r,o,this.stroke,this.lineWidth),Be.lines.line(0,n,-a,h,this.stroke,this.lineWidth),Be.lines.line(0,n,a,h,this.stroke,this.lineWidth),this.showJoints&&[[0,s],[-r,o],[r,o],[0,n],[-a,h],[a,h]].forEach(([t,e])=>Be.shapes.fillCircle(t,e,l,this.jointColor))}getBounds(){const t=100*this.scale,e=40*this.scale;return{x:this.x,y:this.y,width:e,height:t}}},t.Synth=Ms,t.SynthAnalyzer=bs,t.SynthEffects=vs,t.SynthEnvelope=ys,t.SynthMusical=ws,t.SynthNoise=_s,t.SynthOscillators=xs,t.TaskManager=class{constructor(t){this.worker=new Worker(t),this.nextTaskId=1,this.pendingTasks=new Map,this.worker.onmessage=this.handleMessage.bind(this)}handleMessage(t){const{taskId:e,status:i,result:s,error:n}=t.data;if(this.pendingTasks.has(e)){const{resolve:t,reject:o}=this.pendingTasks.get(e);"complete"===i?t(s):"error"===i&&o(new Error(n)),this.pendingTasks.delete(e)}}runTask(t,e){return new Promise((i,s)=>{const n=this.nextTaskId++;this.pendingTasks.set(n,{resolve:i,reject:s}),this.worker.postMessage({taskId:n,taskName:t,params:e})})}terminate(){this.worker.terminate()}},t.Tensor=class t{constructor(t,e={}){bt(this,f),bt(this,p),bt(this,g),bt(this,m),bt(this,y),Mt(this,f,t.map(t=>[...t])),Mt(this,p,t.length),Mt(this,g,e.name||""),Mt(this,m,e.signature||null),Mt(this,y,e.coordinates||null)}static minkowski(){return new t([[-1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],{name:"Minkowski",signature:[-1,1,1,1],coordinates:["t","x","y","z"]})}static schwarzschild(e,i,s=Math.PI/2){e<=i&&(e=1.001*i);const n=1-i/e,o=Math.sin(s);return new t([[-n,0,0,0],[0,1/n,0,0],[0,0,e*e,0],[0,0,0,e*e*o*o]],{name:"Schwarzschild",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static schwarzschildContravariant(e,i,s=Math.PI/2){e<=i&&(e=1.001*i);const n=1-i/e,o=Math.sin(s);return new t([[-1/n,0,0,0],[0,n,0,0],[0,0,1/(e*e),0],[0,0,0,1/(e*e*o*o)]],{name:"Schwarzschild (Contravariant)",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static kerr(e,i,s,n){const o=(n=Math.min(Math.abs(n),s))*n,r=e*e,a=Math.cos(i),h=Math.sin(i),l=h*h,c=a*a,u=r+o*c,d=r-2*s*e+o,f=s+Math.sqrt(Math.max(0,s*s-o));if(e<=f){const r=(e=1.001*f)*e,a=r+o*c,h=r-2*s*e+o;return t._buildKerrMetric(e,i,s,n,a,h,l)}return t._buildKerrMetric(e,i,s,n,u,d,l)}static kerrContravariant(e,i,s,n){const o=(n=Math.min(Math.abs(n),s))*n,r=e*e,a=Math.cos(i),h=Math.sin(i),l=h*h,c=r+o*a*a,u=r-2*s*e+o,d=s+Math.sqrt(Math.max(0,s*s-o));e<=d&&(e=1.001*d);const f=-(Math.pow(r+o,2)-o*u*l)/(c*u),p=-2*s*n*e/(c*u);return new t([[f,0,0,p],[0,u/c,0,0],[0,0,1/c,0],[p,0,0,(u-o*l)/(c*u*l)]],{name:"Kerr (Contravariant)",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static _buildKerrMetric(e,i,s,n,o,r,a){const h=n*n,l=-2*s*n*e*a/o;return new t([[-(1-2*s*e/o),0,0,l],[0,o/r,0,0],[0,0,o,0],[l,0,0,(e*e+h+2*s*h*e*a/o)*a]],{name:"Kerr",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static kerrHorizonRadius(t,e,i=!1){const s=t*t-e*e;if(s<0)return NaN;const n=Math.sqrt(s);return i?t-n:t+n}static kerrErgosphereRadius(t,e,i){const s=Math.cos(i),n=t*t-e*e*s*s;return n<0?NaN:t+Math.sqrt(n)}static kerrISCO(t,e,i=!0){const s=e/t,n=i?1:-1,o=1+Math.cbrt(1-s*s)*(Math.cbrt(1+s)+Math.cbrt(1-s)),r=Math.sqrt(3*s*s+o*o);return t*(3+r-n*Math.sqrt((3-o)*(3+o+2*r)))}static kerrFrameDraggingOmega(e,i,s,n){const o=t.kerr(e,i,s,n),r=o.get(0,3),a=o.get(3,3);return Math.abs(a)<1e-10?0:-r/a}static kerrEffectivePotential(t,e,i,s,n){if(n<=0)return 1/0;const o=n*n;return-t/n+(s*s-e*e*(i*i-1))/(2*o)+-t*Math.pow(s-e*i,2)/(o*n)}static diagonal(e,i={}){const s=e.length,n=[];for(let t=0;t<s;t++){n[t]=[];for(let i=0;i<s;i++)n[t][i]=t===i?e[t]:0}return new t(n,i)}static identity(e=4){const i=new Array(e).fill(1);return t.diagonal(i,{name:"Identity"})}static zero(e=4){const i=[];for(let t=0;t<e;t++)i[t]=new Array(e).fill(0);return new t(i,{name:"Zero"})}get(t,e){return wt(this,f)[t][e]}set(e,i,s){const n=wt(this,f).map(t=>[...t]);return n[e][i]=s,new t(n,{name:wt(this,g),signature:wt(this,m),coordinates:wt(this,y)})}getDiagonal(){const t=[];for(let e=0;e<wt(this,p);e++)t.push(wt(this,f)[e][e]);return t}get dimension(){return wt(this,p)}get name(){return wt(this,g)}get signature(){return wt(this,m)}get coordinates(){return wt(this,y)}add(e){const i=[];for(let t=0;t<wt(this,p);t++){i[t]=[];for(let s=0;s<wt(this,p);s++)i[t][s]=wt(this,f)[t][s]+e.get(t,s)}return new t(i)}subtract(e){const i=[];for(let t=0;t<wt(this,p);t++){i[t]=[];for(let s=0;s<wt(this,p);s++)i[t][s]=wt(this,f)[t][s]-e.get(t,s)}return new t(i)}scale(e){const i=[];for(let t=0;t<wt(this,p);t++){i[t]=[];for(let s=0;s<wt(this,p);s++)i[t][s]=wt(this,f)[t][s]*e}return new t(i)}multiply(e){const i=[];for(let t=0;t<wt(this,p);t++){i[t]=[];for(let s=0;s<wt(this,p);s++){let n=0;for(let i=0;i<wt(this,p);i++)n+=wt(this,f)[t][i]*e.get(i,s);i[t][s]=n}}return new t(i)}transpose(){const e=[];for(let t=0;t<wt(this,p);t++){e[t]=[];for(let i=0;i<wt(this,p);i++)e[t][i]=wt(this,f)[i][t]}return new t(e,{name:wt(this,g)?`${wt(this,g)}ᵀ`:"",signature:wt(this,m),coordinates:wt(this,y)})}inverse(){const e=wt(this,p);if(this.isDiagonal()){const e=this.getDiagonal().map(t=>{if(Math.abs(t)<1e-15)throw new Error("Diagonal matrix is singular, cannot compute inverse");return 1/t});return t.diagonal(e,{name:wt(this,g)?`${wt(this,g)}⁻¹`:"",signature:wt(this,m),coordinates:wt(this,y)})}const i=[];for(let t=0;t<e;t++){i[t]=[];for(let s=0;s<e;s++)i[t][s]=wt(this,f)[t][s];for(let s=0;s<e;s++)i[t][e+s]=t===s?1:0}for(let t=0;t<e;t++){let s=t;for(let n=t+1;n<e;n++)Math.abs(i[n][t])>Math.abs(i[s][t])&&(s=n);if([i[t],i[s]]=[i[s],i[t]],Math.abs(i[t][t])<1e-10)throw new Error("Matrix is singular, cannot compute inverse");const n=i[t][t];for(let s=0;s<2*e;s++)i[t][s]/=n;for(let s=0;s<e;s++)if(s!==t){const n=i[s][t];for(let o=0;o<2*e;o++)i[s][o]-=n*i[t][o]}}const s=[];for(let t=0;t<e;t++){s[t]=[];for(let n=0;n<e;n++)s[t][n]=i[t][e+n]}return new t(s,{name:wt(this,g)?`${wt(this,g)}⁻¹`:"",signature:wt(this,m),coordinates:wt(this,y)})}determinant(){const t=wt(this,p);if(this.isDiagonal())return this.getDiagonal().reduce((t,e)=>t*e,1);if(2===t)return wt(this,f)[0][0]*wt(this,f)[1][1]-wt(this,f)[0][1]*wt(this,f)[1][0];if(3===t){const t=wt(this,f);return t[0][0]*(t[1][1]*t[2][2]-t[1][2]*t[2][1])-t[0][1]*(t[1][0]*t[2][2]-t[1][2]*t[2][0])+t[0][2]*(t[1][0]*t[2][1]-t[1][1]*t[2][0])}const e=wt(this,f).map(t=>[...t]);let i=1,s=0;for(let n=0;n<t;n++){let o=n;for(let i=n+1;i<t;i++)Math.abs(e[i][n])>Math.abs(e[o][n])&&(o=i);if(o!==n&&([e[n],e[o]]=[e[o],e[n]],s++),Math.abs(e[n][n])<1e-10)return 0;i*=e[n][n];for(let i=n+1;i<t;i++){e[i][n]/=e[n][n];for(let s=n+1;s<t;s++)e[i][s]-=e[i][n]*e[n][s]}}return s%2==0?i:-i}trace(){let t=0;for(let e=0;e<wt(this,p);e++)t+=wt(this,f)[e][e];return t}isDiagonal(t=1e-10){for(let e=0;e<wt(this,p);e++)for(let i=0;i<wt(this,p);i++)if(e!==i&&Math.abs(wt(this,f)[e][i])>t)return!1;return!0}isSymmetric(t=1e-10){for(let e=0;e<wt(this,p);e++)for(let i=e+1;i<wt(this,p);i++)if(Math.abs(wt(this,f)[e][i]-wt(this,f)[i][e])>t)return!1;return!0}static christoffel(e,i,s=.001){const n=e(i);if("Schwarzschild"===n.name){const e=i._rs||2;return t.schwarzschildChristoffel(i[1],e,i[2])}const o=[],r=n.inverse(),a=[];for(let t=0;t<4;t++){const n=[...i],o=[...i];n[t]+=s,o[t]-=s;const r=e(n),h=e(o);a[t]=[];for(let e=0;e<4;e++){a[t][e]=[];for(let i=0;i<4;i++)a[t][e][i]=(r.get(e,i)-h.get(e,i))/(2*s)}}for(let t=0;t<4;t++){o[t]=[];for(let e=0;e<4;e++){o[t][e]=[];for(let i=0;i<4;i++){let s=0;for(let n=0;n<4;n++){const o=r.get(t,n);Math.abs(o)<1e-15||(s+=o*(a[e][i][n]+a[i][e][n]-a[n][e][i])/2)}o[t][e][i]=s}}}return o}static schwarzschildChristoffel(t,e,i){const s=[];for(let t=0;t<4;t++){s[t]=[];for(let e=0;e<4;e++)s[t][e]=new Array(4).fill(0)}const n=1-e/t;if(Math.abs(n)<1e-10)return s;const o=e/(2*t*t),r=1/Math.tan(i),a=Math.sin(i),h=Math.cos(i);return s[0][0][1]=s[0][1][0]=o/n,s[1][0][0]=e*n/(2*t*t),s[1][1][1]=-o/n,s[1][2][2]=-(t-e),s[1][3][3]=-(t-e)*a*a,s[2][1][2]=s[2][2][1]=1/t,s[2][3][3]=-a*h,s[3][1][3]=s[3][3][1]=1/t,s[3][2][3]=s[3][3][2]=r,s}static effectivePotential(t,e,i){if(i<=0)return 1/0;const s=e*e;return-t/i+s/(2*i*i)-t*s/(i*i*i)}static iscoRadius(t){return 3*t}static photonSphereRadius(t){return 1.5*t}toArray(){const t=[];for(let e=0;e<wt(this,p);e++)for(let i=0;i<wt(this,p);i++)t.push(wt(this,f)[e][i]);return t}toMatrix(){return wt(this,f).map(t=>[...t])}toString(t=3){return(wt(this,g)?`${wt(this,g)} Tensor:\n`:"")+wt(this,f).map(e=>`[ ${e.map(e=>e.toFixed(t).padStart(10)).join(" ")} ]`).join("\n")}toLatex(t=3){return`\\begin{pmatrix}\n${wt(this,f).map(e=>e.map(e=>e.toFixed(t)).join(" & ")).join(" \\\\\n")}\n\\end{pmatrix}`}},t.Text=Ei,t.TextShape=xi,t.TileLayout=class extends Ii{constructor(t,e={}){super(t,e),this.columns=e.columns??4}calculateLayout(){return this.children.length?Dt(this.children,{columns:this.columns,spacing:this.spacing,padding:this.padding,centerItems:!0}):null}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:-(this._contentHeight??this.height)/2}}},t.ToggleButton=class extends ns{constructor(t,e={}){const i=e.onClick;super(t,{...e,onClick:()=>{this.toggled=!this.toggled,"function"==typeof e.onToggle&&e.onToggle(this.toggled),"function"==typeof i&&i(),this.refreshToggleVisual()}}),this.colorActiveBg=e.colorActiveBg||ss.button.active.bg,this.colorActiveStroke=e.colorActiveStroke||ss.button.active.stroke,this.colorActiveText=e.colorActiveText||ss.button.active.text,this.toggled=!!e.startToggled,this.refreshToggleVisual()}toggle(t){this.toggled=t,this.refreshToggleVisual()}refreshToggleVisual(){this.toggled?(this.bg.fillColor=this.colorActiveBg,this.bg.strokeColor=this.colorActiveStroke,this.label.color=this.colorActiveText):(this.bg.fillColor=this.colors.default.bg,this.bg.strokeColor=this.colors.default.stroke,this.label.color=this.colors.default.text)}setState(t){super.setState(t),this.toggled&&(this.bg.fillColor=this.colorActiveBg,this.bg.strokeColor=this.colorActiveStroke,this.label.color=this.colorActiveText)}},t.Tooltip=class extends Pi{constructor(t,e={}){super(t,{...e,zIndex:9999}),this.font=e.font||ss.fonts.small,this.textColor=e.textColor||ss.tooltip.text,this.bgColor=e.bgColor||ss.tooltip.bg,this.borderColor=e.borderColor||ss.tooltip.border,this.padding=e.padding??8,this.offsetX=e.offsetX??15,this.offsetY=e.offsetY??15,this.maxWidth=e.maxWidth??300,this.lineHeightMultiplier=e.lineHeight??1.4,this._text="",this._lines=[],this._visible=!1,this.bg=new Ve({width:100,height:30,color:this.bgColor,stroke:this.borderColor,lineWidth:1}),this.lineShapes=[],this.group=new Ge,this.group.add(this.bg),this.game.events.on("inputmove",t=>{this._visible&&this.updatePosition(t.x,t.y)})}wrapText(t){const e=this.game.ctx;e.font=this.font;const i=[],s=t.split("\n");for(const t of s){const s=t.split(" ");let n="";for(const t of s){const s=n?`${n} ${t}`:t;e.measureText(s).width>this.maxWidth&&n?(i.push(n),n=t):n=s}n?i.push(n):""===t&&i.push("")}return i}show(t,e,i){this._text=t,this._visible=!0,this._lines=this.wrapText(t),this.updateLineShapes(),this.updateSize(),void 0!==e&&void 0!==i&&this.updatePosition(e,i)}updateLineShapes(){for(const t of this.lineShapes)this.group.remove(t);this.lineShapes=this._lines.map(t=>new xi(t,{font:this.font,color:this.textColor,align:"left",baseline:"top"}));for(const t of this.lineShapes)this.group.add(t)}hide(){this._visible=!1}updatePosition(t,e){const i=this.bg.width,s=this.bg.height;let n=t+this.offsetX+i/2,o=e+this.offsetY+s/2;n+i/2>this.game.width&&(n=t-this.offsetX-i/2),o+s/2>this.game.height&&(o=e-this.offsetY-s/2),n-i/2<0&&(n=i/2+5),o-s/2<0&&(o=s/2+5),this.x=n,this.y=o}updateSize(){const t=this.game.ctx;t.font=this.font;let e=0;for(const i of this._lines){const s=t.measureText(i);e=Math.max(e,s.width)}const i=Math.min(e,this.maxWidth),s=parseInt(this.font)*this.lineHeightMultiplier,n=s*this._lines.length;this.bg.width=i+2*this.padding,this.bg.height=n+2*this.padding;const o=-this.bg.width/2+this.padding,r=-this.bg.height/2+this.padding;for(let t=0;t<this.lineShapes.length;t++)this.lineShapes[t].x=o,this.lineShapes[t].y=r+t*s}draw(){this._visible&&this.group.render()}},t.Touch=Ti,t.Traceable=Xe,t.Transform=Le,t.Transformable=He,t.Triangle=Qe,t.Tween=Fi,t.Tweenetik=ts,t.UI_THEME=ss,t.Updaters=as,t.VerticalLayout=class extends Ii{calculateLayout(){return At(this.children,{spacing:this.spacing,padding:this.padding,align:this.align,centerItems:!0})}getLayoutOffset(){return{offsetX:0,offsetY:-(this._contentHeight??this.height)/2}}},t.WebGLRenderer=ei,t.WrappedText=class extends Ne{constructor(t,e,i,s,n=20,o={}){super(t,e,o),this.text=i,this.maxWidth=s,this.lineHeight=n,this.centered=o.centered||!1,this.color=o.color||"#000000",this.font=o.font||null,this.align=o.align||"left",this.baseline=o.baseline||"top",this.outlineColor=o.outlineColor||null,this.outlineWidth=o.outlineWidth||1,this.calculateDimensions()}calculateDimensions(){if(!Be.ctx)return console.warn("Painter context not initialized. Cannot calculate text dimensions."),this.width=this.maxWidth,this.height=this.lineHeight,void(this.lines=[this.text]);const t=Be.text.font(),e=Be.text.textAlign(),i=Be.text.textBaseline();this.font&&Be.text.setFont(this.font),Be.text.setTextAlign("left"),Be.text.setTextBaseline("top");const s=this.text.split(" ");let n="",o="";this.lines=[],this.width=0;for(let t=0;t<s.length;t++)o=n+s[t]+" ",Be.text.measureText(o).width>this.maxWidth&&t>0?(this.lines.push(n),this.width=Math.max(this.width,Be.text.measureText(n).width),n=s[t]+" "):n=o;this.lines.push(n),this.width=Math.max(this.width,Be.text.measureText(n).width),this.height=this.lines.length*this.lineHeight,Be.text.setFont(t),Be.text.setTextAlign(e),Be.text.setTextBaseline(i)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Be.ctx)return void console.warn("Painter context not initialized. Cannot draw text.");let t=0,e=0;this.centered&&(t=-this.width/2,e=-this.height/2),this.font&&Be.text.setFont(this.font),Be.text.setTextAlign(this.align),Be.text.setTextBaseline(this.baseline);let i=t;"center"===this.align?i=0:"right"===this.align&&(i=t+this.width);for(let t=0;t<this.lines.length;t++){const s=e+t*this.lineHeight;this.outlineColor?Be.outlinedText(this.lines[t],i,s,this.color,this.outlineColor,this.outlineWidth,this.font):Be.text.fillText(this.lines[t],i,s,this.color,this.font)}}getBounds(){return this.centered?{x:this.x,y:this.y,width:this.width,height:this.height}:{x:this.x+this.width/2,y:this.y+this.height/2,width:this.width,height:this.height}}},t.ZOrderedCollection=Ct,t.applyAnchor=Ri,t.applyDraggable=function(t,e={}){const i=t.game;return t.dragging=!1,t.dragOffset={x:0,y:0},t._dragInputMoveHandler&&i.events.off("inputmove",t._dragInputMoveHandler),t._dragInputUpHandler&&i.events.off("inputup",t._dragInputUpHandler),"function"==typeof t.enableInteractivity?t.enableInteractivity(t):t.interactive=!0,t._dragInputDownHandler=i=>{t.dragging=!0,t.dragOffset.x=t.x-i.x,t.dragOffset.y=t.y-i.y,e.onDragStart&&e.onDragStart()},t._dragInputMoveHandler=e=>{t.dragging&&(t.x=e.x+t.dragOffset.x,t.y=e.y+t.dragOffset.y)},t._dragInputUpHandler=i=>{t.dragging&&(t.dragging=!1,e.onDragEnd&&e.onDragEnd())},t.on("inputdown",t._dragInputDownHandler),i.events.on("inputmove",t._dragInputMoveHandler),i.events.on("inputup",t._dragInputUpHandler),()=>{t.off("inputdown",t._dragInputDownHandler),i.events.off("inputmove",t._dragInputMoveHandler),i.events.off("inputup",t._dragInputUpHandler),delete t._dragInputDownHandler,delete t._dragInputMoveHandler,delete t._dragInputUpHandler,delete t.dragging,delete t.dragOffset}},t.applyGravitationalLensing=function(t,e,i,s,n,o=5){const r=Math.sqrt(t*t+e*e);if(r<=o||r>=i)return{x:t,y:e,displacement:0};const a=ee(r,i,s,n,o),h=(r+a)/r;return{x:t*h,y:e*h,displacement:a}},t.applyLayout=Rt,t.bezierV1=Qi,t.blendForces=me,t.bounceV1=Oi,t.cartesianToPolar=function(t,e){return{r:Math.sqrt(t*t+e*e),phi:Math.atan2(e,t)}},t.cartesianToSpherical=function(t,e,i){const s=Math.sqrt(t*t+e*e+i*i);return{r:s,theta:s>0?Math.acos(i/s):0,phi:Math.atan2(e,t)}},t.computeDensities=de,t.computeFluidForces=pe,t.computeGasForces=ge,t.computePressures=fe,t.computeThermalBuoyancy=function(t,e={}){var i;const s=ce(e),n=new Array(t.length),o=s.gas.neutralTemperature,r=s.gas.buoyancy;for(let e=0;e<t.length;e++){const a=t[e],h=((a.temperature??(null==(i=a.custom)?void 0:i.temperature)??s.gas.neutralTemperature)-o)*r;n[e]={x:0,y:-h}}return n},t.createTrailPoint=function(t,e,i={}){return{x:Math.cos(e)*t,z:Math.sin(e)*t,r:t,...i}},t.deBroglieWavelength=function(t){return 2*Math.PI/t},t.decayingOrbitalRadius=function(t,e,i){return t*Math.exp(-e*i)},t.flammEmbedding=te,t.flammEmbeddingHeight=function(t,e,i,s,n){const o=te(Math.max(t,e+.01),e,i),r=te(s,e,i);return(r-o)*n/r},t.floatV1=Xi,t.followPath=Yi,t.gaussianEnvelope=function(t,e,i,s=1){const n=t-e;return s*Math.exp(-n*n/(4*i*i))},t.gaussianWavePacket=function(t,e,{amplitude:i,sigma:s,k:n,omega:o,velocity:r}){const a=t-r*e,h=i*Math.exp(-a*a/(4*s*s)),l=n*t-o*e;return{psi:Et.fromPolar(h,l),envelope:h}},t.gcanvas=gs,t.generatePenroseTilingPixels=Yt,t.getDefaultFluidConfig=function(){return ce()},t.getTerminalTrajectory=function(t,e,i,s,n=null){const o=n?n(s):s;return{x:t*(1-o),y:e*(1-o),z:i*(1-o)}},t.gravitationalLensing=ee,t.gridLayout=It,t.groupVelocity=function(t,e,i=.01){return e/t},t.heatTransfer=function(t,e,i,s,n){return i>=s?0:(e-t)*n},t.heatTransferFalloff=function(t,e,i,s,n,o=1){return i>=s?0:(e-t)*n*Math.pow(1-i/s,o)},t.hopV1=qi,t.horizontalLayout=Pt,t.integrateEuler=function(t,e,i,s={}){const n=ce(s),o=new Array(t.length);for(let s=0;s<t.length;s++){const r=t[s],a=e[s],h=ye(r,n),l=a.x/h+n.external.gravity.x,c=a.y/h+n.external.gravity.y,u=r.vx+l*i,d=r.vy+c*i;o[s]={x:r.x+u*i,y:r.y+d*i,vx:u,vy:d}}return o},t.keplerianOmega=function(t,e,i=1,s=5){return t<=0?0:i*Math.sqrt(e)/Math.pow(t/s,1.5)},t.kerrPrecessionRate=function(t,e,i,s=1){const n=2*e;return t<=n?0:s*(n/t)*(1+i/e)},t.orbitV1=Wi,t.orbitalRadius=function(t,e,i){return e>=1?t:t*(1-e*e)/(1+e*Math.cos(i))},t.orbitalRadiusSimple=function(t,e,i,s=2){return t+e*Math.sin(2*i)*s},t.oscillateV1=Li,t.parabolicV1=Hi,t.patrolV1=Ni,t.pendulumV1=Gi,t.planeWavePhase=function(t,e,i,s){return i*t-s*e},t.polarToCartesian=function(t,e){return{x:t*Math.cos(e),z:t*Math.sin(e)}},t.probabilityDensity=function(t){return t.real*t.real+t.imag*t.imag},t.pulseV1=Ui,t.schwarzschildPrecessionRate=function(t,e,i=1){return t<=e?0:i*(e/t)},t.shakeV1=Zi,t.sketch=function(t=800,e=600,i="black"){const s=[];let n=null,o=null,r=null;const a={circle:(t,e,i,n="white")=>(s.push({type:"circle",x:t,y:e,radius:i,fill:n}),a),rect:(t,e,i,n,o="white")=>(s.push({type:"rect",x:t,y:e,width:i,height:n,fill:o}),a),square:(t,e,i,n="white")=>(s.push({type:"rect",x:t,y:e,width:i,height:i,fill:n}),a),star:(t,e,i,n,o="white")=>(s.push({type:"star",x:t,y:e,points:i,radius:n,fill:o}),a),triangle:(t,e,i,n="white")=>(s.push({type:"triangle",x:t,y:e,size:i,fill:n}),a),hexagon:(t,e,i,n="white")=>(s.push({type:"hexagon",x:t,y:e,radius:i,fill:n}),a),line:(t,e,i,n,o="white",r=1)=>(s.push({type:"line",x:t,y:e,x2:i,y2:n,stroke:o,lineWidth:r}),a),ring:(t,e,i,n,o="white")=>(s.push({type:"ring",x:t,y:e,innerRadius:i,outerRadius:n,fill:o}),a),text:(t,e,i,n={})=>(s.push({type:"text",content:t,x:e,y:i,...n}),a),grid:(t,e,i,s)=>{for(let n=0;n<t;n++)for(let t=0;t<e;t++)s(a,n*i+i/2,t*i+i/2,n,t);return a},repeat:(t,e)=>{for(let i=0;i<t;i++)e(a,i,t);return a},radial:(t,e,i,s,n)=>{for(let o=0;o<s;o++){const r=o/s*Math.PI*2,h=t+Math.cos(r)*i,l=e+Math.sin(r)*i;n(a,h,l,r,o)}return a},setup:t=>(o=t,a),update:t=>(n=t,a),start:()=>{const h=gs({width:t,height:e,bg:i});null==o||o(a);const l=[];let c=h.scene("default");if(s.forEach((t,e)=>{const i=c.go({x:t.x??0,y:t.y??0,name:`shape_${e}`});switch(t.type){case"circle":i.circle({radius:t.radius,fill:t.fill});break;case"rect":i.rect({width:t.width,height:t.height,fill:t.fill});break;case"star":i.star({points:t.points,radius:t.radius,fill:t.fill});break;case"triangle":i.triangle({size:t.size,fill:t.fill});break;case"hexagon":i.hexagon({radius:t.radius,fill:t.fill});break;case"line":i.line({x2:t.x2-t.x,y2:t.y2-t.y,stroke:t.stroke,lineWidth:t.lineWidth});break;case"ring":i.ring({innerRadius:t.innerRadius,outerRadius:t.outerRadius,fill:t.fill});break;case"text":i.text(t.content,{fill:t.fill??"white",font:t.font??"16px monospace"})}l.push(i.goInstance),c=i.end()}),n){let i=0,s=0;h.on("update",(o,r)=>{var a,h;i++,s+=o,n(o,{shapes:l,time:s,frame:i,width:t,height:e,mouse:{x:(null==(a=r.game.mouse)?void 0:a.x)??0,y:(null==(h=r.game.mouse)?void 0:h.y)??0},refs:r.refs,game:r.game})})}return r=h,h.start()},get width(){return t},get height(){return e},get game(){return r}};return a},t.sphericalToCartesian=function(t,e,i){const s=Math.sin(e);return{x:t*s*Math.cos(i),y:t*s*Math.sin(i),z:t*Math.cos(e)}},t.spiralV1=Vi,t.springV1=$i,t.swingV1=ji,t.thermalBuoyancy=function(t,e,i){return(t-e)*i},t.thermalGravity=function(t,e,i){return i*(t/e)},t.tileLayout=Dt,t.updateTrail=function(t,e,i=80){return t.unshift(e),t.length>i&&t.pop(),t},t.verticalLayout=At,t.waypointV1=Ki,t.zoneTemperature=ne,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).GCanvas={})}(this,function(t){"use strict";var e,i,s,n,o,r,a,h,l,c,u,d,f,p,g,m,v,y,_,x,b,w,M,S,C,T,k,P,R,A,z,D,B,I,E,F,O,L,Y,X,W,H,U,G,N,q,Z,V,$,j,K,J,Q,tt,et,it,st,nt,ot,rt,at,ht,lt,ct,ut,dt,ft,pt,gt,mt,vt=Object.defineProperty,yt=t=>{throw TypeError(t)},_t=(t,e,i)=>((t,e,i)=>e in t?vt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i)(t,"symbol"!=typeof e?e+"":e,i),xt=(t,e,i)=>e.has(t)||yt("Cannot "+i),bt=(t,e,i)=>(xt(t,e,"read from private field"),i?i.call(t):e.get(t)),wt=(t,e,i)=>e.has(t)?yt("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,i),Mt=(t,e,i,s)=>(xt(t,e,"write to private field"),s?s.call(t,i):e.set(t,i),i),St=(t,e,i)=>(xt(t,e,"access private method"),i);class Ct{constructor(t={}){this.children=[],this.sortByZIndex=t.sortByZIndex||!0,this._zOrderDirty=!1}add(t){return this.children.includes(t)?(console.warn("Object is already in this collection"),t):(this.children.push(t),t.parent=this._owner||this,this.sortByZIndex&&(this._zOrderDirty=!0,void 0!==t.zIndex&&null!==t.zIndex||(t.zIndex=this.children.length-1)),t)}remove(t){const e=this.children.indexOf(t);return-1!==e&&(this.children.splice(e,1),t.parent=null,!0)}clear(){this.children.forEach(t=>{t.parent=null}),this.children=[]}bringToFront(t){const e=this.children.indexOf(t);if(-1!==e)if(this.sortByZIndex){let e=!0;for(const i of this.children)if(i!==t&&(i.zIndex||0)>=(t.zIndex||0)){e=!1;break}e||(t.zIndex=Number.MAX_SAFE_INTEGER,this._zOrderDirty=!0,this._normalizeZIndices())}else e!==this.children.length-1&&(this.children.splice(e,1),this.children.push(t));else this.add(t)}sendToBack(t){const e=this.children.indexOf(t);if(-1===e)return this.children.unshift(t),void(t.parent=this._owner||this);if(this.sortByZIndex){let e=!0;for(const i of this.children)if(i!==t&&(i.zIndex||0)<=(t.zIndex||0)){e=!1;break}e||(t.zIndex=Number.MIN_SAFE_INTEGER,this._zOrderDirty=!0,this._normalizeZIndices())}else 0!==e&&(this.children.splice(e,1),this.children.unshift(t))}bringForward(t){const e=this.children.indexOf(t);if(-1!==e&&e!==this.children.length-1)if(this.sortByZIndex){const e=[...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),i=e.indexOf(t);if(i<e.length-1){const s=e[i+1],n=s.zIndex||0,o=t.zIndex||0;n-o>1?t.zIndex=o+Math.floor((n-o)/2):(t.zIndex=n,s.zIndex=o),this._zOrderDirty=!0,this._normalizeZIndices()}}else{const i=this.children[e+1];this.children[e+1]=t,this.children[e]=i}}sendBackward(t){const e=this.children.indexOf(t);if(!(e<=0))if(this.sortByZIndex){const e=[...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),i=e.indexOf(t);if(i>0){const s=e[i-1],n=s.zIndex||0,o=t.zIndex||0;o-n>1?t.zIndex=n+Math.floor((o-n)/2):(t.zIndex=n,s.zIndex=o),this._zOrderDirty=!0,this._normalizeZIndices()}}else{const i=this.children[e-1];this.children[e-1]=t,this.children[e]=i}}_normalizeZIndices(){this.children.length<=1||this.children.some(t=>(t.zIndex||0)>1e3||(t.zIndex||0)<-1e3)&&([...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)).forEach((t,e)=>{t.zIndex=10*e}),this._zOrderDirty=!0)}getSortedChildren(){return this.sortByZIndex&&this._zOrderDirty&&(this.children.sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),this._zOrderDirty=!1),this.children}}const Tt=class t{static calculate(e,i,s,n=10,o=0,r=0){const a=i.width||0,h=i.height||0,l=s.width||0,c=s.height||0,u=s.x||0,d=s.y||0;let f,p,g,m;switch(e){case t.TOP_LEFT:f=u-l/2+n+a/2,p=d-c/2+n+h/2,g="left",m="top";break;case t.TOP_CENTER:f=u,p=d-c/2+n+h/2,g="center",m="top";break;case t.TOP_RIGHT:f=u+l/2-n-a/2,p=d-c/2+n+h/2,g="right",m="top";break;case t.CENTER_LEFT:f=u-l/2+n+a/2,p=d,g="left",m="middle";break;case t.CENTER:f=u,p=d,g="center",m="middle";break;case t.CENTER_RIGHT:f=u+l/2-n-a/2,p=d,g="right",m="middle";break;case t.BOTTOM_LEFT:f=u-l/2+n+a/2,p=d+c/2-n-h/2,g="left",m="bottom";break;case t.BOTTOM_CENTER:f=u,p=d+c/2-n-h/2,g="center",m="bottom";break;case t.BOTTOM_RIGHT:f=u+l/2-n-a/2,p=d+c/2-n-h/2,g="right",m="bottom";break;default:f=u-l/2+n+a/2,p=d-c/2+n+h/2,g="left",m="top"}return f+=o,p+=r,{x:f,y:p,align:g,baseline:m}}static calculateAbsolute(e,i,s,n=10,o=0,r=0){const a={width:s.width,height:s.height,x:s.width/2,y:s.height/2};return t.calculate(e,i,a,n,o,r)}};_t(Tt,"TOP_LEFT","top-left"),_t(Tt,"TOP_CENTER","top-center"),_t(Tt,"TOP_RIGHT","top-right"),_t(Tt,"CENTER_LEFT","center-left"),_t(Tt,"CENTER","center"),_t(Tt,"CENTER_RIGHT","center-right"),_t(Tt,"BOTTOM_LEFT","bottom-left"),_t(Tt,"BOTTOM_CENTER","bottom-center"),_t(Tt,"BOTTOM_RIGHT","bottom-right");let kt=Tt;function Pt(t,e,i={}){const s=i.offsetX??0,n=i.offsetY??0,o=i.transform;return t.forEach((t,i)=>{if(i<e.length){const r=e[i];if(o){const e=o(r);t.x=e.x+s,t.y=e.y+n}else t.x=r.x+s,t.y=r.y+n}}),t}function Rt(t,e={}){const i=e.spacing??10,s=e.padding??0,n=e.align??"start",o=e.centerItems??!0;let r=s,a=0;const h=[];for(const e of t)a=Math.max(a,e.height??0);for(let e=0;e<t.length;e++){const s=t[e],l=s.width??0,c=s.height??0,u=o?r+l/2:r;let d;switch(n){case"center":d=(a-c)/2;break;case"end":d=a-c;break;default:d=0}h.push({x:u,y:d}),r+=l,e<t.length-1&&(r+=i)}return{positions:h,width:r+s,height:a+2*s}}function At(t,e={}){const i=e.spacing??10,s=e.padding??0,n=e.align??"start",o=e.centerItems??!0;let r=s,a=0;const h=[];for(const e of t)a=Math.max(a,e.width??0);for(let e=0;e<t.length;e++){const s=t[e],l=s.width??0,c=s.height??0,u=o?r+c/2:r;let d;switch(n){case"center":d=(a-l)/2;break;case"end":d=a-l;break;default:d=0}h.push({x:d,y:u}),r+=c,e<t.length-1&&(r+=i)}return{positions:h,width:a+2*s,height:r+s}}function zt(t,e={}){if(0===t.length)return{positions:[],width:0,height:0};const i=e.columns??4,s=e.spacing??10,n=e.padding??0,o=e.centerItems??!0,r=t[0].width??0,a=t[0].height??0,h=Math.ceil(t.length/i),l=[],c=i*r+(i-1)*s+2*n,u=h*a+(h-1)*s+2*n;let d=n,f=n,p=0;for(let e=0;e<t.length;e++){const t=o?d+r/2:d,e=o?f+a/2:f;l.push({x:t,y:e}),p++,p<i?d+=r+s:(p=0,d=n,f+=a+s)}return{positions:l,width:c,height:u}}function Dt(t,e={}){if(0===t.length)return{positions:[],width:0,height:0};const i=e.columns??4,s=e.spacing??10,n=e.padding??0,o=e.centerItems??!0,r=new Array(i).fill(0),a=[];t.forEach((t,e)=>{const s=e%i,n=Math.floor(e/i),o=t.width??0,h=t.height??0;r[s]=Math.max(r[s],o),void 0===a[n]?a[n]=h:a[n]=Math.max(a[n],h)});const h=[];let l=n,c=n,u=0;for(let e=0;e<t.length;e++){const d=t[e],f=d.width??0,p=d.height??0,g=a[Math.floor(e/i)],m=o?l+f/2:l,v=o?c+p/2:c;h.push({x:m,y:v}),u++,u<i?l+=r[u-1]+s:(u=0,l=n,c+=g+s)}return{positions:h,width:2*n+r.reduce((t,e)=>t+e,0)+s*(i-1),height:2*n+a.reduce((t,e)=>t+e,0)+s*(a.length-1),cols:i,rows:a.length}}class Bt{constructor(t={}){this.x=0,this.y=0,this.target=t.target??null,this.deadzone=t.deadzone??null,this.lerp=t.lerp??.1,this.zoom=t.zoom??1,this.bounds=t.bounds??null,this.viewportWidth=t.viewportWidth??800,this.viewportHeight=t.viewportHeight??600,this.offsetX=t.offsetX??0,this.offsetY=t.offsetY??0,this._shakeIntensity=0,this._shakeDuration=0,this._shakeTime=0,this._shakeOffsetX=0,this._shakeOffsetY=0,this._initialX=this.x,this._initialY=this.y}update(t){if(!this.target)return;const e=this.target.x+this.offsetX,i=this.target.y+this.offsetY,s=this.x+this.viewportWidth/2,n=this.y+this.viewportHeight/2;let o=this.x,r=this.y;if(this.deadzone){const t=this.deadzone.width/2,a=this.deadzone.height/2;e<s-t?o=e+t-this.viewportWidth/2:e>s+t&&(o=e-t-this.viewportWidth/2),i<n-a?r=i+a-this.viewportHeight/2:i>n+a&&(r=i-a-this.viewportHeight/2)}else o=e-this.viewportWidth/2,r=i-this.viewportHeight/2;if(this.x+=(o-this.x)*this.lerp,this.y+=(r-this.y)*this.lerp,this.bounds){const t=this.bounds.maxX-this.viewportWidth,e=this.bounds.maxY-this.viewportHeight;this.x=Math.max(this.bounds.minX,Math.min(this.x,t)),this.y=Math.max(this.bounds.minY,Math.min(this.y,e))}this._updateShake(t)}_updateShake(t){if(this._shakeDuration>0&&this._shakeTime<this._shakeDuration){this._shakeTime+=t;const e=1-this._shakeTime/this._shakeDuration;this._shakeOffsetX=2*(Math.random()-.5)*this._shakeIntensity*e,this._shakeOffsetY=2*(Math.random()-.5)*this._shakeIntensity*e,this._shakeTime>=this._shakeDuration&&(this._shakeOffsetX=0,this._shakeOffsetY=0,this._shakeDuration=0,this._shakeTime=0)}}getOffset(){return{x:this.x+this._shakeOffsetX,y:this.y+this._shakeOffsetY}}setPosition(t,e){return this.x=t,this.y=e,this}setTarget(t){return this.target=t,this}shake(t,e){return this._shakeIntensity=t,this._shakeDuration=e,this._shakeTime=0,this}stopShake(){return this._shakeIntensity=0,this._shakeDuration=0,this._shakeTime=0,this._shakeOffsetX=0,this._shakeOffsetY=0,this}isVisible(t){if(!t)return!1;const e=this.x+this.viewportWidth,i=this.y+this.viewportHeight,s=t.x+(t.width||0),n=t.y+(t.height||0);return!(t.x>e||s<this.x||t.y>i||n<this.y)}screenToWorld(t,e){return{x:t/this.zoom+this.x,y:e/this.zoom+this.y}}worldToScreen(t,e){return{x:(t-this.x)*this.zoom,y:(e-this.y)*this.zoom}}getWorldBounds(){return{x:this.x,y:this.y,width:this.viewportWidth/this.zoom,height:this.viewportHeight/this.zoom}}reset(){return this.x=this._initialX,this.y=this._initialY,this.stopShake(),this}isShaking(){return this._shakeDuration>0&&this._shakeTime<this._shakeDuration}}class It{static symmetric(t,e,i,s,n=1,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+(Math.random()-.5)*i*n,y:r+(Math.random()-.5)*s*n}}static pointInBox(t,e,i,s,n="topleft"){return"centered"===n?{x:t+(Math.random()-.5)*i,y:e+(Math.random()-.5)*s}:{x:t+Math.random()*i,y:e+Math.random()*s}}static centered(t,e,i,s,n=50,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+2*(Math.random()-.5)*n,y:r+2*(Math.random()-.5)*n}}static gaussian(t,e,i,s,n=40,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+It._gaussian(0,n),y:r+It._gaussian(0,n)}}static radial(t,e,i,s,n=100,o="topleft"){const r="centered"===o?t:t+i/2,a="centered"===o?e:e+s/2,h=Math.random()*Math.PI*2,l=Math.random()*n;return{x:r+Math.cos(h)*l,y:a+Math.sin(h)*l}}static pick(t){return t[Math.floor(Math.random()*t.length)]}static pickOther(t,e){const i=t.filter(t=>t!==e);if(0!==i.length)return It.pick(i)}static float(t,e){return t+Math.random()*(e-t)}static int(t,e){return Math.floor(It.float(t,e+1))}static chance(t=.5){return Math.random()<t}static coin(){return Math.random()<.5}static _gaussian(t=0,e=1){let i=1-Math.random(),s=1-Math.random();return t+e*Math.sqrt(-2*Math.log(i))*Math.cos(2*Math.PI*s)}}class Et{constructor(t,e=0){this.real=t,this.imag=e}static fromPolar(t,e){return new Et(t*Math.cos(e),t*Math.sin(e))}add(t){return new Et(this.real+t.real,this.imag+t.imag)}subtract(t){return new Et(this.real-t.real,this.imag-t.imag)}multiply(t){return new Et(this.real*t.real-this.imag*t.imag,this.real*t.imag+this.imag*t.real)}divide(t){return new Et(this.real/t,this.imag/t)}scale(t){return new Et(this.real*t,this.imag*t)}abs(){return Math.sqrt(this.real*this.real+this.imag*this.imag)}}class Ft{static applyColorScheme(t,e,i,s,n,o){const r=(null==e?void 0:e.data)||[];for(let e=0;e<t.length;e++){const a=t[e],h=4*e;switch(i){case"futuristic":{const i=t[e]/10,s={r:0,g:5,b:10},n={r:0,g:30,b:20};if(i>.7){const t=3.33*(i-.7);r[h]=Math.floor(s.r*(1-t)+n.r*t),r[h+1]=Math.floor(s.g*(1-t)+n.g*t),r[h+2]=Math.floor(s.b*(1-t)+n.b*t)}else{const t=1.43*i;r[h]=Math.floor(s.r*t),r[h+1]=Math.floor(s.g*t),r[h+2]=Math.floor(s.b*t)}r[h+3]=255}break;case"rainbow":if(0===a)r[h]=0,r[h+1]=0,r[h+2]=0,r[h+3]=255;else{const t=(10*a+n)%360,[e,i,s]=o(t,.8,.5);r[h]=e,r[h+1]=i,r[h+2]=s,r[h+3]=255}break;case"grayscale":{const t=0===a?0:255-255*a/s;r[h]=t,r[h+1]=t,r[h+2]=t,r[h+3]=255}break;case"binary":0!==a?(r[h]=0,r[h+1]=0,r[h+2]=0):(r[h]=255,r[h+1]=255,r[h+2]=255),r[h+3]=255;break;case"fire":if(0==a)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=a/s;if(t<.3){const e=t/.3;r[h]=Math.floor(255*e),r[h+1]=0,r[h+2]=0}else if(t<.6){const e=(t-.3)/.3;r[h]=255,r[h+1]=Math.floor(165*e),r[h+2]=0}else if(t<.9){const e=(t-.6)/.3;r[h]=255,r[h+1]=165+Math.floor(90*e),r[h+2]=Math.floor(255*e)}else r[h]=255,r[h+1]=255,r[h+2]=255}r[h+3]=255;break;case"ocean":if(0===a)r[h]=0,r[h+1]=20,r[h+2]=50;else{const t=a/s;r[h]=Math.floor(10+50*t),r[h+1]=Math.floor(50+150*t),r[h+2]=Math.floor(100+155*t)}r[h+3]=255;break;case"electric":if(0===a)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=(a+n)%3,e=a%20/20;0===t?(r[h]=Math.floor(255*(.5+.5*Math.sin(e*Math.PI*2))),r[h+1]=Math.floor(128*e),r[h+2]=Math.floor(255*e)):1===t?(r[h]=Math.floor(255*e),r[h+1]=Math.floor(255*(.5+.5*Math.sin(e*Math.PI*2))),r[h+2]=Math.floor(128*e)):(r[h]=Math.floor(128*e),r[h+1]=Math.floor(255*e),r[h+2]=Math.floor(255*(.5+.5*Math.sin(e*Math.PI*2))))}r[h+3]=255;break;case"topographic":if(0===a)r[h]=5,r[h+1]=15,r[h+2]=30;else{const t=a/s;if(t<.1){const e=t/.1;r[h]=Math.floor(5+20*e),r[h+1]=Math.floor(15+40*e),r[h+2]=Math.floor(30+50*e)}else if(t<.3){const e=(t-.1)/.2;r[h]=Math.floor(210+45*e),r[h+1]=Math.floor(180+40*e),r[h+2]=Math.floor(140+30*e)}else if(t<.7){const e=(t-.3)/.4;r[h]=Math.floor(50*(1-e)),r[h+1]=Math.floor(100+80*e),r[h+2]=Math.floor(50*(1-e))}else{const e=(t-.7)/.3;r[h]=Math.floor(150+105*e),r[h+1]=Math.floor(150+105*e),r[h+2]=Math.floor(150+105*e)}}r[h+3]=255;break;default:if(0===a)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=(a+n)%64;t<16?(r[h]=16*t,r[h+1]=0,r[h+2]=0):t<32?(r[h]=255,r[h+1]=16*(t-16),r[h+2]=0):t<48?(r[h]=255-16*(t-32),r[h+1]=255,r[h+2]=0):(r[h]=0,r[h+1]=255-16*(t-48),r[h+2]=16*(t-48))}r[h+3]=255}}return null!=e?e:r}static pythagorasTree(t,e,i=10,s=-2,n=2,o=-.5,r=3.5){const a=new Uint8Array(t*e),h=e=>Math.floor((e-s)*t/(n-s)),l=t=>Math.floor((t-o)*e/(r-o)),c=(i,s,n,o)=>{const r=h(i),c=l(s),u=h(n),d=l(o);let f=r,p=c;const g=Math.abs(u-r),m=Math.abs(d-c),v=r<u?1:-1,y=c<d?1:-1;let _=g-m;for(;f>=0&&f<t&&p>=0&&p<e&&(a[p*t+f]=255),f!==u||p!==d;){const t=2*_;t>-m&&(_-=m,f+=v),t<g&&(_+=g,p+=y)}},u=(t,e,i,s,n)=>{if(n<=0)return;const o=i-t,r=s-e,a=i+r,h=s-o,l=t+r,d=e-o;((t,e,i,s,n,o,r,a)=>{c(t,e,i,s),c(i,s,n,o),c(n,o,r,a),c(r,a,t,e)})(t,e,i,s,a,h,l,d);const f=Math.PI/4,p=.7*Math.sqrt(o*o+r*r),g=p*Math.cos(Math.atan2(r,o)-f),m=p*Math.sin(Math.atan2(r,o)-f),v=.7*Math.sqrt(o*o+r*r),y=l,_=d,x=y+v*Math.cos(Math.atan2(r,o)+f),b=_+v*Math.sin(Math.atan2(r,o)+f);u(a,h,a+g,h+m,n-1),u(y,_,x,b,n-1)},d=Math.min(i,12);return u(-.5,0,.5,0,d),a}static mandelbrot(t,e,i=100,s=-2.5,n=1,o=-1.5,r=1.5){const a=new Uint8Array(t*e),h=(n-s)/t,l=(r-o)/e;for(let n=0;n<e;n++){const e=n*t,r=o+n*l;for(let n=0;n<t;n++){const t=s+n*h;let o=0,l=0,c=0,u=0,d=0;do{l=2*o*l+r,o=c-u+t,c=o*o,u=l*l,d++}while(c+u<4&&d<i);a[e+n]=d<i?d%256:0}}return a}static julia(t,e,i=100,s=-.7,n=.27,o=1,r=0,a=0){const h=new Uint8Array(t*e),l=2/o,c=-l+r,u=-l+a,d=(l+r-c)/t,f=(l+a-u)/e;for(let o=0;o<e;o++){const e=o*t,r=u+o*f;for(let o=0;o<t;o++){let t=c+o*d,a=r,l=0,u=0,f=0;do{l=t*t,u=a*a,a=2*t*a+n,t=l-u+s,f++}while(l+u<4&&f<i);h[e+o]=f<i?f%256:0}}return h}static tricorn(t,e,i=100,s=-2.5,n=1.5,o=-1.5,r=1.5){const a=new Uint8Array(t*e),h=(n-s)/t,l=(r-o)/e;for(let n=0;n<e;n++){const e=n*t,r=o+n*l;for(let n=0;n<t;n++){const t=s+n*h;let o=0,l=0,c=0,u=0,d=0;do{l=-2*o*l+r,o=c-u+t,c=o*o,u=l*l,d++}while(c+u<4&&d<i);a[e+n]=d<i?d%256:0}}return a}static phoenix(t,e,i=100,s=.5,n=.5,o=-2,r=2,a=-2,h=2){const l=new Uint8Array(t*e),c=(r-o)/t,u=(h-a)/e;for(let r=0;r<e;r++){const e=r*t,h=a+r*u;for(let r=0;r<t;r++){const t=o+r*c;let a=0,u=0,d=0,f=0,p=0,g=0,m=0;do{const e=p-g+t+s*d+n,i=2*a*u+h+s*f;d=a,f=u,a=e,u=i,p=a*a,g=u*u,m++}while(p+g<4&&m<i);l[e+r]=m<i?m%256:0}}return l}static newton(t,e,i=100,s=1e-6,n=-2,o=2,r=-2,a=2){const h=new Uint8Array(t*e),l=s*s,c=o-n,u=a-r,d=new Float64Array(3),f=new Float64Array(3);for(let t=0;t<3;t++){const e=2*Math.PI*t/3;d[t]=Math.cos(e),f[t]=Math.sin(e)}const p=c/t,g=u/e;for(let s=0;s<e;s++){const e=s*t,o=r+s*g;for(let s=0;s<t;s++){let t=n+s*p,r=o,a=0,c=-1;for(;a<i&&c<0;){const e=t*t-r*r,i=2*t*r,s=e*t-i*r-1,n=e*r+i*t,o=3*e,h=3*i,u=o*o+h*h;if(u<l)break;const p=1/u,g=t-(s*o+n*h)*p,m=r-(n*o-s*h)*p;for(let t=0;t<3;t++){const e=g-d[t],i=m-f[t];if(e*e+i*i<l){c=t;break}}t=g,r=m,a++}if(c>=0){const t=1-Math.min(a/i,1),n=85*c;h[e+s]=Math.floor(n+85*t)}else h[e+s]=0}}return h}static sierpinski(t,e,i=6,s=0,n=1,o=0,r=1){const a=new Uint8Array(t*e).fill(1),h=Math.sqrt(3)/2,l=n-s,c=(r-o)/l;if(Math.abs(c-h)>1e-9){const t=(o+r)/2,e=l*h;o=t-e/2,r=t+e/2}const u=(1<<Math.min(i,32))-1,d=(n-s)/t,f=(r-o)/e,p=2/Math.sqrt(3);for(let i=0;i<e;++i){const e=o+i*f,n=Math.floor(e*p),r=.5*n;for(let e=0;e<t;++e){const o=s+e*d;0!==(Math.floor(o-r)&n&u)&&(a[i*t+e]=0)}}return a}static sierpinskiCarpet(t,e,i=5,s=0,n=1,o=0,r=1){const a=new Uint8Array(t*e).fill(1),h=n-s,l=r-o,c=Math.max(h,l),u=(s+n)/2,d=(o+r)/2;s=u-c/2,n=u+c/2,o=d-c/2,r=d+c/2;const f=Math.pow(3,i),p=(t,e)=>{let i=t,s=e;for(;i>0||s>0;){if(i%3==1&&s%3==1)return!0;i=Math.floor(i/3),s=Math.floor(s/3)}return!1};for(let i=0;i<e;++i){const h=(o+i/e*(r-o))*f,l=(Math.floor(h)%f+f)%f;for(let e=0;e<t;++e){const o=(s+e/t*(n-s))*f;p((Math.floor(o)%f+f)%f,l)&&(a[i*t+e]=0)}}return a}static barnsleyFern(t,e,i=1e5){const s=new Uint8Array(t*e).fill(0);let n=0,o=0;const r=Math.min(t,e)/10,a=t/2;for(let h=0;h<i;h++){const i=Math.random();let h,l;i<.01?(h=0,l=.16*o):i<.86?(h=.85*n+.04*o,l=-.04*n+.85*o+1.6):i<.93?(h=.2*n-.26*o,l=.23*n+.22*o+1.6):(h=-.15*n+.28*o,l=.26*n+.24*o+.44),n=h,o=l;const c=Math.floor(n*r+a),u=Math.floor(e-o*r);if(c>=0&&c<t&&u>=0&&u<e){const e=u*t+c;s[e]<255&&s[e]++}}return s}static lyapunov(t,e,i=1e3,s="AB",n=3.4,o=4,r=3.4,a=4){console.time("lyapunov");const h=(s=s.toUpperCase().replace(/[^AB]/g,"")||"AB").length,l=new Float32Array(t*e);let c=1/0,u=-1/0;for(let d=0;d<e;d++){const f=r+(a-r)*d/e;for(let e=0;e<t;e++){const r=n+(o-n)*e/t;let a=.5;for(let t=0;t<100;t++)a=("A"===s[t%h]?r:f)*a*(1-a);let p=0,g=0;for(;g<i;){const t="A"===s[g%h]?r:f;a=t*a*(1-a);const e=Math.abs(t*(1-2*a));if(p+=Math.log(Math.max(e,1e-10)),g++,Math.abs(p/g)>10)break}const m=p/g;l[d*t+e]=m,m>-10&&m<10&&(m<c&&(c=m),m>u&&(u=m))}}c===u&&(c-=1,u+=1);const d=u-c,f=new Uint8Array(t*e);for(let t=0;t<l.length;t++){let e=l[t];e=Math.max(-10,Math.min(10,e));let i=(e-c)/d;f[t]=Math.floor(255*i)}return console.timeEnd("lyapunov"),f}static koch(t,e,i=4,s=-2,n=2,o=-2,r=2){const a=new Uint8Array(t*e),h=e=>Math.floor((e-s)*t/(n-s)),l=t=>Math.floor((t-o)*e/(r-o)),c=(i,s,n,o,r)=>{if(r<=0)return void((i,s,n,o)=>{const r=h(i),c=l(s),u=h(n),d=l(o);let f=r,p=c;const g=Math.abs(u-r),m=Math.abs(d-c),v=r<u?1:-1,y=c<d?1:-1;let _=g-m;for(;f>=0&&f<t&&p>=0&&p<e&&(a[p*t+f]=255),f!==u||p!==d;){const t=2*_;t>-m&&(_-=m,f+=v),t<g&&(_+=g,p+=y)}})(i,s,n,o);const u=(n-i)/3,d=(o-s)/3,f=i+u,p=s+d,g=i+2*u,m=s+2*d,v=Math.PI/3,y=f+u*Math.cos(v)-d*Math.sin(v),_=p+u*Math.sin(v)+d*Math.cos(v);c(i,s,f,p,r-1),c(f,p,y,_,r-1),c(y,_,g,m,r-1),c(g,m,n,o,r-1)},u=Math.min(i,10),d=3*Math.sqrt(3)/2,f=[0,-d/2+.5],p=[-1.5,d/2+.5],g=[1.5,d/2+.5];return c(f[0],f[1],p[0],p[1],u),c(p[0],p[1],g[0],g[1],u),c(g[0],g[1],f[0],f[1],u),a}}_t(Ft,"types",{MANDELBROT:"mandelbrot",TRICORN:"tricorn",PHOENIX:"phoenix",JULIA:"julia",SIERPINSKI:"sierpinski",SCARPET:"sierpinskiCarpet",BARNSEY_FERN:"barnsleyFern",KOCH:"koch",PYTHAGORAS_TREE:"pythagorasTree",NEWTON:"newton",LYAPUNOV:"lyapunov"}),_t(Ft,"colors",{FUTURISTIC:"futuristic",RAINBOW:"rainbow",GRAYSCALE:"grayscale",TOPOGRAPHIC:"topographic",FIRE:"fire",OCEAN:"ocean",ELECTRIC:"electric",BINARY:"binary",HISTORIC:"historic"});const Ot=class{static seed(t){t>0&&t<1&&(t*=65536),(t=Math.floor(t))<256&&(t|=t<<8);for(let e=0;e<256;e++){let r;r=1&e?bt(this,s)[e]^255&t:bt(this,s)[e]^t>>8&255,bt(this,n)[e]=bt(this,n)[e+256]=r,bt(this,o)[e]=bt(this,o)[e+256]=bt(this,i)[r%12]}}static simplex2(t,e){let i,s,h;const l=(t+e)*bt(this,r),c=Math.floor(t+l),u=Math.floor(e+l),d=(c+u)*bt(this,a),f=t-c+d,p=e-u+d;let g,m;f>p?(g=1,m=0):(g=0,m=1);const v=f-g+bt(this,a),y=p-m+bt(this,a),_=f-1+2*bt(this,a),x=p-1+2*bt(this,a),b=255&c,w=255&u,M=bt(this,o)[b+bt(this,n)[w]],S=bt(this,o)[b+g+bt(this,n)[w+m]],C=bt(this,o)[b+1+bt(this,n)[w+1]];let T=.5-f*f-p*p;T<0?i=0:(T*=T,i=T*T*M.dot2(f,p));let k=.5-v*v-y*y;k<0?s=0:(k*=k,s=k*k*S.dot2(v,y));let P=.5-_*_-x*x;return P<0?h=0:(P*=P,h=P*P*C.dot2(_,x)),70*(i+s+h)}static simplex3(t,e,i){let s,r,a,c;const u=(t+e+i)*bt(this,h),d=Math.floor(t+u),f=Math.floor(e+u),p=Math.floor(i+u),g=(d+f+p)*bt(this,l),m=t-d+g,v=e-f+g,y=i-p+g;let _,x,b,w,M,S;m>=v?v>=y?(_=1,x=0,b=0,w=1,M=1,S=0):m>=y?(_=1,x=0,b=0,w=1,M=0,S=1):(_=0,x=0,b=1,w=1,M=0,S=1):v<y?(_=0,x=0,b=1,w=0,M=1,S=1):m<y?(_=0,x=1,b=0,w=0,M=1,S=1):(_=0,x=1,b=0,w=1,M=1,S=0);const C=m-_+bt(this,l),T=v-x+bt(this,l),k=y-b+bt(this,l),P=m-w+2*bt(this,l),R=v-M+2*bt(this,l),A=y-S+2*bt(this,l),z=m-1+3*bt(this,l),D=v-1+3*bt(this,l),B=y-1+3*bt(this,l),I=255&d,E=255&f,F=255&p,O=bt(this,o)[I+bt(this,n)[E+bt(this,n)[F]]],L=bt(this,o)[I+_+bt(this,n)[E+x+bt(this,n)[F+b]]],Y=bt(this,o)[I+w+bt(this,n)[E+M+bt(this,n)[F+S]]],X=bt(this,o)[I+1+bt(this,n)[E+1+bt(this,n)[F+1]]];let W=.6-m*m-v*v-y*y;W<0?s=0:(W*=W,s=W*W*O.dot3(m,v,y));let H=.6-C*C-T*T-k*k;H<0?r=0:(H*=H,r=H*H*L.dot3(C,T,k));let U=.6-P*P-R*R-A*A;U<0?a=0:(U*=U,a=U*U*Y.dot3(P,R,A));let G=.6-z*z-D*D-B*B;return G<0?c=0:(G*=G,c=G*G*X.dot3(z,D,B)),32*(s+r+a+c)}static perlin2(t,e){const i=Math.floor(t),s=Math.floor(e);t-=i,e-=s;const r=255&i,a=255&s,h=bt(this,o)[r+bt(this,n)[a]].dot2(t,e),l=bt(this,o)[r+bt(this,n)[a+1]].dot2(t,e-1),f=bt(this,o)[r+1+bt(this,n)[a]].dot2(t-1,e),p=bt(this,o)[r+1+bt(this,n)[a+1]].dot2(t-1,e-1),g=St(this,c,u).call(this,t);return St(this,c,d).call(this,St(this,c,d).call(this,h,f,g),St(this,c,d).call(this,l,p,g),St(this,c,u).call(this,e))}static perlin3(t,e,i){const s=Math.floor(t),r=Math.floor(e),a=Math.floor(i);t-=s,e-=r,i-=a;const h=255&s,l=255&r,f=255&a,p=bt(this,o)[h+bt(this,n)[l+bt(this,n)[f]]].dot3(t,e,i),g=bt(this,o)[h+bt(this,n)[l+bt(this,n)[f+1]]].dot3(t,e,i-1),m=bt(this,o)[h+bt(this,n)[l+1+bt(this,n)[f]]].dot3(t,e-1,i),v=bt(this,o)[h+bt(this,n)[l+1+bt(this,n)[f+1]]].dot3(t,e-1,i-1),y=bt(this,o)[h+1+bt(this,n)[l+bt(this,n)[f]]].dot3(t-1,e,i),_=bt(this,o)[h+1+bt(this,n)[l+bt(this,n)[f+1]]].dot3(t-1,e,i-1),x=bt(this,o)[h+1+bt(this,n)[l+1+bt(this,n)[f]]].dot3(t-1,e-1,i),b=bt(this,o)[h+1+bt(this,n)[l+1+bt(this,n)[f+1]]].dot3(t-1,e-1,i-1),w=St(this,c,u).call(this,t),M=St(this,c,u).call(this,e),S=St(this,c,u).call(this,i);return St(this,c,d).call(this,St(this,c,d).call(this,St(this,c,d).call(this,p,y,w),St(this,c,d).call(this,g,_,w),S),St(this,c,d).call(this,St(this,c,d).call(this,m,x,w),St(this,c,d).call(this,v,b,w),S),M)}};e=new WeakMap,i=new WeakMap,s=new WeakMap,n=new WeakMap,o=new WeakMap,r=new WeakMap,a=new WeakMap,h=new WeakMap,l=new WeakMap,c=new WeakSet,u=function(t){return t*t*t*(t*(6*t-15)+10)},d=function(t,e,i){return(1-i)*t+i*e},wt(Ot,c),wt(Ot,e,class{constructor(t,e,i){this.x=t,this.y=e,this.z=i}dot2(t,e){return this.x*t+this.y*e}dot3(t,e,i){return this.x*t+this.y*e+this.z*i}}),wt(Ot,i,[new(bt(Ot,e))(1,1,0),new(bt(Ot,e))(-1,1,0),new(bt(Ot,e))(1,-1,0),new(bt(Ot,e))(-1,-1,0),new(bt(Ot,e))(1,0,1),new(bt(Ot,e))(-1,0,1),new(bt(Ot,e))(1,0,-1),new(bt(Ot,e))(-1,0,-1),new(bt(Ot,e))(0,1,1),new(bt(Ot,e))(0,-1,1),new(bt(Ot,e))(0,1,-1),new(bt(Ot,e))(0,-1,-1)]),wt(Ot,s,[151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]),wt(Ot,n,new Array(512)),wt(Ot,o,new Array(512)),wt(Ot,r,.5*(Math.sqrt(3)-1)),wt(Ot,a,(3-Math.sqrt(3))/6),wt(Ot,h,1/3),wt(Ot,l,1/6),Ot.seed(0);let Lt=Ot;function Yt(t=800,e=800,i){const{divisions:s=5,zoomType:n="in",color1:o=[255,0,0,255],color2:r=[0,0,255,255],color3:a=[0,0,0,255],backgroundColor:h=[255,255,255,255]}=i||{},l=new Uint8ClampedArray(t*e*4);for(let t=0;t<l.length;t+=4)l[t]=h[0],l[t+1]=h[1],l[t+2]=h[2],l[t+3]=h[3]||255;const c="in"===n?1:2,u=Math.max(t,e),d=u/c,f=u/c,p=.5*c,g=.5*c,m=(Math.sqrt(5)+1)/2;let v=[];for(let t=0;t<10;t++){const e=Et.fromPolar(1,(2*t-1)*Math.PI/10),i=Et.fromPolar(1,(2*t+1)*Math.PI/10);t%2==0?v.push(["thin",new Et(0),i,e]):v.push(["thin",new Et(0),e,i])}for(let t=0;t<s;t++){const t=[];for(const[e,i,s,n]of v)if("thin"===e){const e=i.add(s.subtract(i).scale(1/m));t.push(["thin",n,e,s]),t.push(["thicc",e,n,i])}else{const e=s.add(i.subtract(s).scale(1/m)),o=s.add(n.subtract(s).scale(1/m));t.push(["thicc",o,n,i]),t.push(["thicc",e,o,s]),t.push(["thin",o,e,i])}v=t}function y(i){return{x:Math.floor((i.real*d+p*d)*t/u),y:Math.floor((i.imag*f+g*f)*e/u)}}for(const[i,s,n,a]of v)Xt(l,y(s),y(n),y(a),"thin"===i?o:r,t,e);if(a&&a[3]>0)for(const[i,s,n,o]of v){const i=y(s),r=y(n),h=y(o);Ut(l,i,r,a,t,e),Ut(l,r,h,a,t,e),Ut(l,h,i,a,t,e)}return l}function Xt(t,e,i,s,n,o,r){e.y>i.y&&([e,i]=[i,e]),e.y>s.y&&([e,s]=[s,e]),i.y>s.y&&([i,s]=[s,i]);const a=n[0],h=n[1],l=n[2],c=n[3]||255;if(i.y===s.y)Wt(t,e,i,s,a,h,l,c,o,r);else if(e.y===i.y)Ht(t,e,i,s,a,h,l,c,o,r);else{const n={x:Math.floor(e.x+(i.y-e.y)/(s.y-e.y)*(s.x-e.x)),y:i.y};Wt(t,e,i,n,a,h,l,c,o,r),Ht(t,i,n,s,a,h,l,c,o,r)}}function Wt(t,e,i,s,n,o,r,a,h,l){const c=(i.x-e.x)/(i.y-e.y||1),u=(s.x-e.x)/(s.y-e.y||1);let d=e.x,f=e.x;for(let s=e.y;s<=i.y;s++){if(s>=0&&s<l){const e=Math.max(0,Math.min(Math.floor(d),h-1)),i=Math.max(0,Math.min(Math.floor(f),h-1));for(let l=Math.min(e,i);l<=Math.max(e,i);l++){const e=4*(s*h+l);e>=0&&e<t.length-3&&(t[e]=n,t[e+1]=o,t[e+2]=r,t[e+3]=a)}}d+=c,f+=u}}function Ht(t,e,i,s,n,o,r,a,h,l){const c=(s.x-e.x)/(s.y-e.y||1),u=(s.x-i.x)/(s.y-i.y||1);let d=s.x,f=s.x;for(let i=s.y;i>e.y;i--)if(i>=0&&i<l){d-=c,f-=u;const e=Math.max(0,Math.min(Math.floor(d),h-1)),s=Math.max(0,Math.min(Math.floor(f),h-1));for(let l=Math.min(e,s);l<=Math.max(e,s);l++){const e=4*(i*h+l);e>=0&&e<t.length-3&&(t[e]=n,t[e+1]=o,t[e+2]=r,t[e+3]=a)}}}function Ut(t,e,i,s,n,o){const r=s[0],a=s[1],h=s[2],l=s[3]||255;let c=e.x,u=e.y,d=i.x,f=i.y;const p=Math.abs(d-c),g=Math.abs(f-u),m=c<d?1:-1,v=u<f?1:-1;let y=p-g;for(;;){if(c>=0&&c<n&&u>=0&&u<o){const e=4*(u*n+c);if(e>=0&&e<t.length-3){const i=l/255;t[e]=Math.round(t[e]*(1-i)+r*i),t[e+1]=Math.round(t[e+1]*(1-i)+a*i),t[e+2]=Math.round(t[e+2]*(1-i)+h*i),t[e+3]=255}}if(c===d&&u===f)break;const e=2*y;e>-g&&(y-=g,c+=m),e<p&&(y+=p,u+=v)}}f=new WeakMap,p=new WeakMap,g=new WeakMap,m=new WeakMap,v=new WeakMap;const Gt={tokens:{unaryNot:["!","~","¬","NOT"],and:["&","∧","AND"],nand:["NAND"],or:["|","∨","OR"],nor:["NOR"],xor:["^","⊕","XOR"],xnor:["XNOR"]},precedence:{OR:1,NOR:1,XOR:2,XNOR:2,AND:3,NAND:3,NOT:4},constants:{true:["1","TRUE"],false:["0","FALSE"]}};function Nt(t){return Boolean(t)}function qt(t){return String(t).toUpperCase()}function Zt(t){const e=qt(t);if(Gt.tokens.unaryNot.map(qt).includes(e))return"NOT";if(Gt.tokens.and.map(qt).includes(e))return"AND";if(Gt.tokens.nand.map(qt).includes(e))return"NAND";if(Gt.tokens.or.map(qt).includes(e))return"OR";if(Gt.tokens.nor.map(qt).includes(e))return"NOR";if(Gt.tokens.xor.map(qt).includes(e))return"XOR";if(Gt.tokens.xnor.map(qt).includes(e))return"XNOR";throw new Error(`[BooleanAlgebra] Unknown operator "${t}"`)}function Vt(t){return Gt.precedence[t]??0}function $t(t){let e=0;const i=()=>t[e],s=()=>t[e++];function n(){const t=s();if(!t)throw new Error("[BooleanAlgebra] Unexpected end of input");if("const"===t.type){const e=qt(t.value);return{type:"const",value:Gt.constants.true.includes(e)}}if("ident"===t.type)return{type:"var",name:t.value};if("lp"===t.type){const t=o(0),e=s();if(!e||"rp"!==e.type)throw new Error("[BooleanAlgebra] Missing closing ')'");return t}if("op"===t.type){if("NOT"!==Zt(t.value))throw new Error(`[BooleanAlgebra] Unexpected binary operator "${t.value}"`);return{type:"not",left:n()}}throw new Error(`[BooleanAlgebra] Unexpected token "${t.type}"`)}function o(t){let e=n();for(;;){const n=i();if(!n||"op"!==n.type)break;const r=Zt(n.value);if("NOT"===r)break;const a=Vt(r);if(a<t)break;s(),e={type:"AND"===r?"and":"OR"===r?"or":"XOR"===r?"xor":"NAND"===r?"nand":"NOR"===r?"nor":"xnor",left:e,right:o(a+1)}}return e}const r=o(0);if(e<t.length)throw new Error("[BooleanAlgebra] Unexpected trailing tokens");return r}function jt(t,e){switch(t.type){case"const":return Boolean(t.value);case"var":return Nt((null==e?void 0:e[t.name])??!1);case"not":return!jt(t.left,e);case"and":return jt(t.left,e)&&jt(t.right,e);case"nand":return!(jt(t.left,e)&&jt(t.right,e));case"or":return jt(t.left,e)||jt(t.right,e);case"nor":return!(jt(t.left,e)||jt(t.right,e));case"xor":{const i=jt(t.left,e),s=jt(t.right,e);return i&&!s||!i&&s}case"xnor":return jt(t.left,e)===jt(t.right,e);default:throw new Error(`[BooleanAlgebra] Unknown AST node type "${t.type}"`)}}function Kt(t,e){t&&("var"===t.type&&t.name&&e.add(t.name),t.left&&Kt(t.left,e),t.right&&Kt(t.right,e))}function Jt(t){const e=1<<t,i=new Array(e);for(let t=0;t<e;t++)i[t]=t^t>>1;return i}class Qt{static and(t,e){return Nt(t)&&Nt(e)}static nand(t,e){return!(Nt(t)&&Nt(e))}static or(t,e){return Nt(t)||Nt(e)}static nor(t,e){return!(Nt(t)||Nt(e))}static xor(t,e){const i=Nt(t),s=Nt(e);return i&&!s||!i&&s}static xnor(t,e){return Nt(t)===Nt(e)}static not(t){return!Nt(t)}static parse(t){return $t(function(t){const e=[],i=String(t??"");let s=0;const n=t=>" "===t||"\n"===t||"\t"===t||"\r"===t,o=t=>t>="A"&&t<="Z"||t>="a"&&t<="z"||"_"===t,r=t=>o(t)||t>="0"&&t<="9";for(;s<i.length;){const t=i[s];if(n(t))s++;else if("("!==t)if(")"!==t){if("!"!==t&&"~"!==t&&"¬"!==t&&"&"!==t&&"∧"!==t&&"|"!==t&&"∨"!==t&&"^"!==t&&"⊕"!==t){if(o(t)||t>="0"&&t<="9"){let t=s+1;for(;t<i.length&&r(i[t]);)t++;const n=i.slice(s,t),o=qt(n);Gt.constants.true.includes(o)||Gt.constants.false.includes(o)?e.push({type:"const",value:o}):Gt.tokens.unaryNot.includes(o)||Gt.tokens.and.includes(o)||Gt.tokens.nand.includes(o)||Gt.tokens.or.includes(o)||Gt.tokens.nor.includes(o)||Gt.tokens.xor.includes(o)||Gt.tokens.xnor.includes(o)?e.push({type:"op",value:o}):e.push({type:"ident",value:n}),s=t;continue}throw new Error(`[BooleanAlgebra] Unexpected character "${t}" at ${s}`)}e.push({type:"op",value:t}),s++}else e.push({type:"rp",value:t}),s++;else e.push({type:"lp",value:t}),s++}return e}(t))}static evaluate(t,e={}){return jt("string"==typeof t?Qt.parse(t):t,e)}static variables(t){const e="string"==typeof t?Qt.parse(t):t,i=new Set;return Kt(e,i),[...i].sort((t,e)=>t.localeCompare(e))}static grayCode(t){return Jt(t)}static truthTable(t,e,i={}){const s="string"==typeof t?Qt.parse(t):t,n=e&&e.length>0?[...e]:Qt.variables(s),o=n.length,r=1<<o,a="gray"===i.order?"gray":"binary",h=("gray"===a?Jt(o):Array.from({length:r},(t,e)=>e)).map(t=>{const e={};for(let i=0;i<o;i++){const s=1<<o-1-i;e[n[i]]=Boolean(t&s)}return{index:t,inputs:e,output:jt(s,e)}});return{variables:n,order:a,rows:h}}}const te={CONTINUOUS:"continuous",ITERATIVE:"iterative"},ee={TWO_D:2,THREE_D:3},ie={lorenz:{name:"Lorenz",type:te.CONTINUOUS,dimension:ee.THREE_D,equations:["dx/dt = σ(y - x)","dy/dt = x(ρ - z) - y","dz/dt = xy - βz"],defaultParams:{sigma:10,rho:28,beta:8/3},defaultDt:.01,derivatives(t,e=this.defaultParams){const{sigma:i,rho:s,beta:n}={...this.defaultParams,...e},{x:o,y:r,z:a}=t;return{dx:i*(r-o),dy:o*(s-a)-r,dz:o*r-n*a}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},dadras:{name:"Dadras",type:te.CONTINUOUS,dimension:ee.THREE_D,equations:["dx/dt = y - ax + byz","dy/dt = cy - xz + z","dz/dt = dxy - ez"],defaultParams:{a:3,b:2.7,c:1.7,d:2,e:9},defaultDt:.005,derivatives(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o,e:r}={...this.defaultParams,...e},{x:a,y:h,z:l}=t;return{dx:h-i*a+s*h*l,dy:n*h-a*l+l,dz:o*a*h-r*l}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},aizawa:{name:"Aizawa",type:te.CONTINUOUS,dimension:ee.THREE_D,equations:["dx/dt = (z - b)x - dy","dy/dt = dx + (z - b)y","dz/dt = c + az - z³/3 - (x² + y²)(1 + ez) + fzx³"],defaultParams:{a:.95,b:.7,c:.6,d:3.5,e:.25,f:.1},defaultDt:.01,derivatives(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o,e:r,f:a}={...this.defaultParams,...e},{x:h,y:l,z:c}=t;return{dx:(c-s)*h-o*l,dy:o*h+(c-s)*l,dz:n+i*c-c*c*c/3-(h*h+l*l)*(1+r*c)+a*c*h*h*h}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},thomas:{name:"Thomas",type:te.CONTINUOUS,dimension:ee.THREE_D,equations:["dx/dt = sin(y) - bx","dy/dt = sin(z) - by","dz/dt = sin(x) - bz"],defaultParams:{b:.208186},defaultDt:.1,derivatives(t,e=this.defaultParams){const{b:i}={...this.defaultParams,...e},{x:s,y:n,z:o}=t;return{dx:Math.sin(n)-i*s,dy:Math.sin(o)-i*n,dz:Math.sin(s)-i*o}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},clifford:{name:"Clifford",type:te.ITERATIVE,dimension:ee.TWO_D,equations:["x_{n+1} = sin(a·y_n) + c·cos(a·x_n)","y_{n+1} = sin(b·x_n) + d·cos(b·y_n)"],defaultParams:{a:-1.4,b:1.6,c:1,d:.7},next(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o}={...this.defaultParams,...e},{x:r,y:a}=t;return{x:Math.sin(i*a)+n*Math.cos(i*r),y:Math.sin(s*r)+o*Math.cos(s*a)}},step(t,e,i=this.defaultParams){const s=this.next(t,i),n=s.x-t.x,o=s.y-t.y;return{position:s,velocity:{dx:n,dy:o,dz:0},speed:Math.sqrt(n*n+o*o)}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i)=>this.step(t,i,e)}},rossler:{name:"Rössler",type:te.CONTINUOUS,dimension:ee.THREE_D,equations:["dx/dt = -y - z","dy/dt = x + ay","dz/dt = b + z(x - c)"],defaultParams:{a:.2,b:.2,c:5.7},defaultDt:.01,derivatives(t,e=this.defaultParams){const{a:i,b:s,c:n}={...this.defaultParams,...e},{x:o,y:r,z:a}=t;return{dx:-r-a,dy:o+i*r,dz:s+a*(o-n)}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},halvorsen:{name:"Halvorsen",type:te.CONTINUOUS,dimension:ee.THREE_D,equations:["dx/dt = -ax - 4y - 4z - y²","dy/dt = -ay - 4z - 4x - z²","dz/dt = -az - 4x - 4y - x²"],defaultParams:{a:1.89},defaultDt:.005,derivatives(t,e=this.defaultParams){const{a:i}={...this.defaultParams,...e},{x:s,y:n,z:o}=t;return{dx:-i*s-4*n-4*o-n*n,dy:-i*n-4*o-4*s-o*o,dz:-i*o-4*s-4*n-s*s}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},deJong:{name:"De Jong",type:te.ITERATIVE,dimension:ee.TWO_D,equations:["x_{n+1} = sin(a·y_n) - cos(b·x_n)","y_{n+1} = sin(c·x_n) - cos(d·y_n)"],defaultParams:{a:-2.24,b:-.65,c:-.43,d:-2.43},next(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o}={...this.defaultParams,...e},{x:r,y:a}=t;return{x:Math.sin(i*a)-Math.cos(s*r),y:Math.sin(n*r)-Math.cos(o*a)}},step(t,e,i=this.defaultParams){const s=this.next(t,i),n=s.x-t.x,o=s.y-t.y;return{position:s,velocity:{dx:n,dy:o,dz:0},speed:Math.sqrt(n*n+o*o)}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i)=>this.step(t,i,e)}}};function se(t,e,i){return t<=e?0:Math.sqrt(8*i*(t-e))}function ne(t,e,i,s,n=5){return t<=n||t>=e?0:Math.exp(-t*s)*i}class oe{static lerp(t,e,i){return t+(e-t)*i}static linear(t){return t}static smoothstep(t){return t*t*(3-2*t)}static smootherstep(t){return t*t*t*(t*(6*t-15)+10)}static easeInQuad(t){return t*t}static easeOutQuad(t){return t*(2-t)}static easeInOutQuad(t){return t<.5?2*t*t:(4-2*t)*t-1}static easeInCubic(t){return t*t*t}static easeOutCubic(t){return--t*t*t+1}static easeInOutCubic(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1}static easeInQuart(t){return t*t*t*t}static easeOutQuart(t){return 1- --t*t*t*t}static easeInOutQuart(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t}static easeInSine(t){return 1-Math.cos(t*Math.PI/2)}static easeOutSine(t){return Math.sin(t*Math.PI/2)}static easeInOutSine(t){return-(Math.cos(Math.PI*t)-1)/2}static easeInExpo(t){return 0===t?0:Math.pow(2,10*(t-1))}static easeOutExpo(t){return 1===t?1:1-Math.pow(2,-10*t)}static easeInOutExpo(t){return 0===t||1===t?t:t<.5?.5*Math.pow(2,20*t-10):.5*(2-Math.pow(2,-20*t+10))}static easeInCirc(t){return 1-Math.sqrt(1-t*t)}static easeOutCirc(t){return Math.sqrt(1- --t*t)}static easeInOutCirc(t){return t<.5?.5*(1-Math.sqrt(1-4*t*t)):.5*(Math.sqrt(-(2*t-3)*(2*t-1))+1)}static easeInElastic(t,e=1,i=.3){if(0===t||1===t)return t;const s=i/(2*Math.PI)*Math.asin(1/e);return-e*Math.pow(2,10*(t-1))*Math.sin((t-1-s)*(2*Math.PI)/i)}static easeOutElastic(t,e=1,i=.3){if(0===t||1===t)return t;const s=i/(2*Math.PI)*Math.asin(1/e);return e*Math.pow(2,-10*t)*Math.sin((t-s)*(2*Math.PI)/i)+1}static easeInOutElastic(t,e=1,i=.3){if(0===t||1===t)return t;const s=i/(2*Math.PI)*Math.asin(1/e);return t<.5?e*Math.pow(2,10*(2*t-1))*Math.sin((2*t-1-s)*(2*Math.PI)/i)*-.5:e*Math.pow(2,-10*(2*t-1))*Math.sin((2*t-1-s)*(2*Math.PI)/i)*.5+1}static easeInBack(t,e=1.70158){return t*t*((e+1)*t-e)}static easeOutBack(t,e=1.70158){return--t*t*((e+1)*t+e)+1}static easeInOutBack(t,e=1.70158){const i=1.525*e;return t<.5?2*t*.5*(2*t)*(2*(i+1)*t-i):.5*((2*t-2)*(2*t-2)*((i+1)*(2*t-2)+i)+2)}static easeOutBounce(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}static easeInBounce(t){return 1-oe.easeOutBounce(1-t)}static easeInOutBounce(t){return t<.5?.5*oe.easeInBounce(2*t):.5*oe.easeOutBounce(2*t-1)+.5}}function re(t,e,i){const s=Math.max(0,Math.min(1,(i-t)/(e-t)));return oe.smoothstep(s)}function ae(t,e,i){const{heatZone:s,coolZone:n,rate:o,heatMultiplier:r=1.5,coolMultiplier:a=1.5,middleMultiplier:h=.05,transitionWidth:l=.1}=i,c=re(s-l,s+.5*l,t),u=1-re(n-.5*l,n+l,t),d=1-c-u;let f=0;return c>0&&(f+=(1-e)*o*r*c),u>0&&(f+=(0-e)*o*a*u),d>0&&(f+=(t-e)*o*h*d),Math.max(0,Math.min(1,e+f))}function he(t,e,i,s,n,o=1){return i>=s?0:(e-t)*n*Math.pow(1-i/s,o)}const le={smoothingRadius:28},ce={restDensity:1.1,particleMass:1,pressureStiffness:1800,nearPressureStiffness:2.5,viscosity:.18,surfaceTension:0,maxForce:6e3},ue={interactionRadius:34,pressure:12,diffusion:.08,drag:.04,buoyancy:260,neutralTemperature:.5,turbulence:16},de={gravity:{x:0,y:820}},fe=1e-4;function pe(t={}){return{kernel:{...le,...t.kernel||{}},fluid:{...ce,...t.fluid||{}},gas:{...ue,...t.gas||{}},external:{...de,...t.external||{}}}}const ge={poly6(t,e){const i=e*e;if(t>=i)return 0;const s=i-t;return 4/(Math.PI*Math.pow(e,8))*s*s*s},spikyPow2(t,e){if(t>=e)return 0;const i=e-t;return 6/(Math.PI*Math.pow(e,4))*i*i},spikyPow3(t,e){if(t>=e)return 0;const i=e-t;return 10/(Math.PI*Math.pow(e,5))*i*i*i},spikyPow2Derivative:(t,e)=>0===t||t>=e?0:-12/(Math.PI*Math.pow(e,4))*(e-t),spikyPow3Derivative(t,e){if(0===t||t>=e)return 0;const i=e-t;return-30/(Math.PI*Math.pow(e,5))*i*i},spikyGradient:(t,e)=>0===t||t>=e?0:-30/(Math.PI*Math.pow(e,5))*((e-t)*(e-t)),viscosityLaplacian:(t,e)=>t>=e?0:40/(Math.PI*Math.pow(e,5))*(e-t)};function me(t,e={},i){const s=pe(e).kernel.smoothingRadius,n=s*s,o=i??Me(t,s),r=t.length,a=new Float32Array(r),h=new Float32Array(r);for(let e=0;e<r;e++)a[e]=ge.spikyPow2(0,s),h[e]=ge.spikyPow3(0,s),Se(e,t,o,n,(t,i,n,o)=>{const r=Math.sqrt(o);a[e]+=ge.spikyPow2(r,s),h[e]+=ge.spikyPow3(r,s)});return{densities:a,nearDensities:h}}function ve(t,e,i={}){const s=pe(i),n=t.length,o=new Float32Array(n),r=new Float32Array(n),{pressureStiffness:a,nearPressureStiffness:h,restDensity:l}=s.fluid;for(let i=0;i<n;i++)o[i]=(t[i]-l)*a,r[i]=e[i]*h;return{pressures:o,nearPressures:r}}function ye(t,e={}){const i=pe(e),s=i.kernel.smoothingRadius,n=s*s,o=t.length,r=Me(t,s),{densities:a,nearDensities:h}=me(t,i,r),{pressures:l,nearPressures:c}=ve(a,h,i),u=new Array(o);for(let t=0;t<o;t++)u[t]={x:0,y:0};for(let e=0;e<o;e++){const o=t[e];Math.max(a[e],fe),Se(e,t,r,n,(n,r,d,f)=>{if(n<=e)return;const p=Math.sqrt(f);if(p<fe||p>=s)return;const g=t[n],m=1/p,v=-r*m,y=-d*m,_=Math.max(a[n],fe),x=Math.max(h[n],fe),b=.5*(l[e]+l[n]),w=.5*(c[e]+c[n]),M=b*ge.spikyPow2Derivative(p,s)/_+w*ge.spikyPow3Derivative(p,s)/x,S=v*M,C=y*M;u[e].x+=S,u[e].y+=C,u[n].x-=S,u[n].y-=C;const T=ge.poly6(f,s),k=i.fluid.viscosity*T,P=(g.vx-o.vx)*k,R=(g.vy-o.vy)*k;u[e].x+=P,u[e].y+=R,u[n].x-=P,u[n].y-=R})}return we(u,i.fluid.maxForce),{forces:u,densities:a,pressures:l}}function _e(t,e={}){var i;const s=pe(e),n=s.gas.interactionRadius,o=n*n,r=t.length,a=Me(t,n),h=new Array(r);for(let t=0;t<r;t++)h[t]={x:0,y:0};for(let e=0;e<r;e++){const r=t[e],l=be(r,s),c=r.temperature??(null==(i=r.custom)?void 0:i.temperature)??s.gas.neutralTemperature;Se(e,t,a,o,(i,o,a,u)=>{var d;if(i<=e)return;if(0===u)return;const f=Math.sqrt(u),p=1/f,g=t[i],m=be(g,s),v=g.temperature??(null==(d=g.custom)?void 0:d.temperature)??s.gas.neutralTemperature,y=s.gas.pressure*(1-f/n),_=o*p*y,x=a*p*y;h[e].x+=_,h[e].y+=x,h[i].x-=_,h[i].y-=x;const b=s.gas.diffusion,w=(g.vx-r.vx)*b,M=(g.vy-r.vy)*b;h[e].x+=w*m,h[e].y+=M*m,h[i].x-=w*l,h[i].y-=M*l;const S=(c-v)*s.gas.buoyancy*.5;h[e].y-=S,h[i].y+=S})}for(let e=0;e<r;e++){const i=t[e],n=s.gas.drag;h[e].x+=-i.vx*n,h[e].y+=-i.vy*n,h[e].x+=(Math.random()-.5)*s.gas.turbulence,h[e].y+=(Math.random()-.5)*s.gas.turbulence}return we(h,s.fluid.maxForce),{forces:h}}function xe(t,e,i){const s=Math.min(t.length,e.length),n=new Array(s);for(let o=0;o<s;o++)n[o]={x:oe.lerp(t[o].x,e[o].x,i),y:oe.lerp(t[o].y,e[o].y,i)};return n}function be(t,e){return t.custom&&"number"==typeof t.custom.mass?t.custom.mass:t.mass?t.mass:t.size?.5*t.size+e.fluid.particleMass:e.fluid.particleMass}function we(t,e){const i=e*e;for(let s=0;s<t.length;s++){const n=t[s],o=n.x*n.x+n.y*n.y;if(o>i){const t=1/Math.sqrt(o);n.x*=e*t,n.y*=e*t}}}function Me(t,e){const i=e,s=new Map;for(let e=0;e<t.length;e++){const n=t[e],o=`${Math.floor(n.x/i)},${Math.floor(n.y/i)}`;let r=s.get(o);r||(r=[],s.set(o,r)),r.push(e)}return{cellSize:i,buckets:s}}function Se(t,e,i,s,n){const o=e[t],r=i.cellSize,a=Math.floor(o.x/r),h=Math.floor(o.y/r);for(let r=-1;r<=1;r++)for(let l=-1;l<=1;l++){const c=`${a+r},${h+l}`,u=i.buckets.get(c);if(u)for(let i=0;i<u.length;i++){const r=u[i];if(r===t)continue;const a=e[r],h=o.x-a.x,l=o.y-a.y,c=h*h+l*l;c<s&&n(r,h,l,c)}}}const Ce=class t{static disableAll(){t.enabledClasses=new Set,t.globalLevel=0}static disable(){t.enabled=!1}static enable(){t.enabled=!0}static setLevel(e){t.globalLevel=e}static enableFor(e){t.enabledClasses.add(e)}static disableFor(e){t.enabledClasses.delete(e)}static setOutput(e){t.output=e}constructor(t){this.className=t}static getLogger(e){return t.loggerz[e]||(t.loggerz[e]=new t(e)),t.loggerz[e]}_log(e,i,...s){t.enabled&&(t.globalLevel>=e||t.enabledClasses.has(this.className))&&t.output[i](`[${this.className}]`,...s)}log(...e){this._log(t.INFO,"log",...e)}warn(...e){this._log(t.WARN,"warn",...e)}error(...e){this._log(t.ERROR,"error",...e)}debug(...e){this._log(t.DEBUG,"log",...e)}table(...e){this._log(t.INFO,"table",...e)}groupCollapsed(e){t.enabled&&t.output.groupCollapsed(`[${this.className}] ${e}`)}groupEnd(){t.enabled&&t.output.groupEnd()}time(e){t.enabled&&t.output.time(`[${this.className}] ${e}`)}timeEnd(e){t.enabled&&t.output.timeEnd(`[${this.className}] ${e}`)}clear(){t.output.clear()}};_t(Ce,"ERROR",1),_t(Ce,"WARN",2),_t(Ce,"INFO",3),_t(Ce,"DEBUG",4),_t(Ce,"globalLevel",Ce.ERROR),_t(Ce,"enabledClasses",new Set),_t(Ce,"output",console),_t(Ce,"enabled",!0),_t(Ce,"loggerz",[]);let Te=Ce;class ke{constructor(t={}){this.name=t.name||this.constructor.name,this._logger=this.getLogger(t)}get logger(){return null==this._logger?this.getLogger():this._logger}trace(t="render"){this.logger.log(null==this.name?this.constructor.name:this.name,t,"x",this.x,"y",this.y,"w",this.width,"h",this.height,"opacity",this._opacity,"visible",this._visible,"active",this._active,"debug",this.debug)}getLogger(t){return Te.getLogger(t.name||this.constructor.name)}}const Pe=class t{static getInstance(){return t.instance||(t.instance=new t),t.instance}constructor(){this.createTab()}createTab(){this.tab=document.createElement("div"),Object.assign(this.tab.style,{position:"fixed",bottom:"0",left:"0",right:"0",height:"30px",backgroundColor:"#333",color:"#fff",padding:"5px",cursor:"pointer",fontFamily:"monospace",zIndex:"10000",display:"flex",justifyContent:"space-between",alignItems:"center"}),this.tab.innerText="Console";const t=document.createElement("div"),e=(t,e)=>{const i=document.createElement("button");return i.innerText=t,Object.assign(i.style,{marginLeft:"5px",padding:"2px 5px",fontFamily:"monospace",cursor:"pointer"}),i.onclick=e,i};this.paused=!1,this.scrollLock=!0,t.appendChild(e("Clear",()=>this.consoleArea.value="")),t.appendChild(e("Pause",()=>this.paused=!this.paused)),t.appendChild(e("Scroll Lock",()=>this.scrollLock=!this.scrollLock)),this.tab.appendChild(t),document.body.appendChild(this.tab),this.consoleArea=document.createElement("textarea"),Object.assign(this.consoleArea.style,{position:"fixed",bottom:"30px",left:"0",right:"0",height:"200px",display:"none",backgroundColor:"#111",color:"#0f0",fontFamily:"monospace",zIndex:"9999",padding:"10px",resize:"none"}),this.consoleArea.readOnly=!0,document.body.appendChild(this.consoleArea),this.tab.onclick=t=>{t.target===this.tab&&(this.consoleArea.style.display="none"===this.consoleArea.style.display?"block":"none")}}appendMessage(t,e,...i){if(this.paused)return;const s=`[${t.toUpperCase()}] ${e} ${i.join(" ")}\n`;this.consoleArea.value+=s,this.scrollLock&&(this.consoleArea.scrollTop=this.consoleArea.scrollHeight)}log(t,...e){this.appendMessage("log",t,...e)}warn(t,...e){this.appendMessage("warn",t,...e)}error(t,...e){this.appendMessage("error",t,...e)}table(t){const e=JSON.stringify(t,null,2);this.appendMessage("table",e)}groupCollapsed(t){this.appendMessage("group",`Group Start: ${t}`)}groupEnd(){this.appendMessage("group","Group End")}time(t){this[`time_${t}`]=performance.now()}timeEnd(t){const e=(performance.now()-this[`time_${t}`]).toFixed(2);this.appendMessage("time",`${t}: ${e} ms`)}};_t(Pe,"instance");let Re=Pe;const Ae=class t{static dropShadow(t,e,i=0,s=0){Le.ctx.shadowColor=t,Le.ctx.shadowBlur=e,Le.ctx.shadowOffsetX=i,Le.ctx.shadowOffsetY=s}static clearShadow(){Le.ctx.shadowColor="rgba(0, 0, 0, 0)",Le.ctx.shadowBlur=0,Le.ctx.shadowOffsetX=0,Le.ctx.shadowOffsetY=0}static setAlpha(t){Le.ctx.globalAlpha=t}static setBlendMode(t){Le.ctx.globalCompositeOperation=t}static clipRect(t,e,i,s){Le.ctx.beginPath(),Le.ctx.rect(t,e,i,s),Le.ctx.clip()}static clipCircle(t,e,i){Le.ctx.beginPath(),Le.shapes.arc(t,e,i,0,2*Math.PI),Le.ctx.clip()}static blurRegion(t,e,i,s,n){const o=Le.ctx.filter;Le.ctx.filter=`blur(${n}px)`;const r=Le.ctx.getImageData(t,e,i,s);Le.ctx.putImageData(r,t,e),Le.ctx.filter=o}static createGlow(e,i,s={}){const n="glow-"+Math.random().toString(36).substr(2,9),o={id:n,type:"glow",active:!0,time:0,color:e,blur:i,options:{pulseSpeed:0,pulseMin:.5*i,pulseMax:1.5*i,colorShift:0,...s},update(t){return Object.assign(this,t),this},stop(){return this.active=!1,t._activeEffects.delete(this.id),this},apply(){if(!this.active)return;let t=this.blur,e=this.color;if(this.options.pulseSpeed>0){const e=.5*Math.sin(this.time*this.options.pulseSpeed)+.5;t=this.options.pulseMin+e*(this.options.pulseMax-this.options.pulseMin)}return this.options.colorShift>0&&(e=e.replace("hue",this.time*this.options.colorShift%360)),Le.ctx.shadowColor=e,Le.ctx.shadowBlur=t,Le.ctx.shadowOffsetX=0,Le.ctx.shadowOffsetY=0,this.time+=1/60,this}};return t._activeEffects.set(n,o),t._startAnimationLoop(),o}static _startAnimationLoop(){if(null!==t._animationId)return;const e=()=>{if(t._activeEffects.forEach(t=>{t.active&&t.apply()}),0===t._activeEffects.size)return cancelAnimationFrame(t._animationId),void(t._animationId=null);t._animationId=requestAnimationFrame(e)};t._animationId=requestAnimationFrame(e)}static clearAllEffects(){t._activeEffects.forEach(t=>t.stop()),t._activeEffects.clear(),Le.ctx.shadowColor="rgba(0, 0, 0, 0)",Le.ctx.shadowBlur=0,Le.ctx.shadowOffsetX=0,Le.ctx.shadowOffsetY=0,Le.ctx.filter="none",Le.ctx.globalAlpha=1,Le.ctx.globalCompositeOperation="source-over"}};_t(Ae,"_activeEffects",new Map),_t(Ae,"_animationId",null);let ze=Ae;class De{static draw(t,e=0,i=0,{width:s,height:n,crop:o=null,anchor:r="top‑left",rotation:a=0,scaleX:h=1,scaleY:l=1,flipX:c=!1,flipY:u=!1,alpha:d=1,smoothing:f=!0}={}){const p=Le.ctx;if(!p||!t)return;const g=s??(o?o.sw:t.width??t.videoWidth),m=n??(o?o.sh:t.height??t.videoHeight),v=-g*({left:0,center:.5,right:1}[r.split("-").pop()]??0),y=-m*({top:0,center:.5,bottom:1}[r.split("-")[0]]??0);if(p.save(),p.imageSmoothingEnabled=f,p.globalAlpha*=d,p.translate(e,i),a&&p.rotate(a),(c||u)&&p.scale(c?-1:1,u?-1:1),p.scale(h,l),o){const{sx:e,sy:i,sw:s,sh:n}=o;p.drawImage(t,e,i,s,n,v,y,g,m)}else p.drawImage(t,v,y,g,m);p.restore()}static blit(t,e,i,s,n){this.draw(t,e,i,{width:s,height:n})}static createPattern(t,e="repeat"){return Le.ctx.createPattern(t,e)}static fillPattern(t,e,i,s,n){const o=Le.ctx;o.save(),o.fillStyle=t,o.fillRect(e,i,s,n),o.restore()}static createImageData(t,e){return Le.ctx.createImageData(t,e)}static cloneImageData(t){return new ImageData(new Uint8ClampedArray(t.data),t.width,t.height)}static getImageData(t,e,i,s){return Le.ctx.getImageData(t,e,i,s)}static putImageData(t,e,i,s=0,n=0,o=t.width,r=t.height){Le.ctx.putImageData(t,e,i,s,n,o,r)}static mapPixels(t,e){const i=t.data;for(let t=0;t<i.length;t+=4){const s=t>>2,n=e(i[t],i[t+1],i[t+2],i[t+3],s);n&&([i[t],i[t+1],i[t+2],i[t+3]]=n)}return t}static setPixel(t,e,i,s,n,o,r=255){const a=4*(i*t.width+e),h=t.data;h[a]=s,h[a+1]=n,h[a+2]=o,h[a+3]=r}static async toBitmap({type:t="image/png",quality:e=.92}={}){const i=Le.ctx.canvas,s=await i.convertToBlob({type:t,quality:e});return createImageBitmap(s)}static async createBitmap(t){return createImageBitmap(t)}static toImageData(t,e,i){if(t.length!==e*i*4)throw new Error("Invalid RGBA array size for given dimensions");return new ImageData(t,e,i)}static async createImageBitmapFromPixels(t,e,i){const s=this.toImageData(t,e,i);return await createImageBitmap(s)}static createPatternFromImageData(t,e="repeat"){const i=document.createElement("canvas");i.width=t.width,i.height=t.height;const s=i.getContext("2d");return s.putImageData(t,0,0),s.createPattern(i,e)}static createPatternFromPixels(t,e,i,s="repeat"){const n=this.toImageData(t,e,i);return this.createPatternFromImageData(n,s)}}class Be{static path(t,e,i,s=1){const n=Le.ctx;n.beginPath();for(const e of t){const[t,...i]=e;"M"===t?n.moveTo(...i):"L"===t?n.lineTo(...i):"C"===t?n.bezierCurveTo(...i):"Q"===t?n.quadraticCurveTo(...i):"Z"===t&&n.closePath()}e&&(n.fillStyle=e,Le.colors.fill(e)),i&&(n.strokeStyle=i,n.lineWidth=s,Le.colors.stroke())}static line(t,e,i,s,n,o){Le.ctx.beginPath(),Le.ctx.moveTo(t,e),Le.ctx.lineTo(i,s),Le.colors.stroke(n,o)}static beginPath(){Le.ctx.beginPath()}static closePath(){Le.ctx.closePath()}static moveTo(t,e){Le.ctx.moveTo(t,e)}static lineTo(t,e){Le.ctx.lineTo(t,e)}static bezierCurveTo(t,e,i,s,n,o){Le.ctx.bezierCurveTo(t,e,i,s,n,o)}static dashedLine(t,e,i,s,n,o,r){Le.ctx.beginPath(),o&&(Le.ctx.strokeStyle=o),void 0!==r&&(Le.ctx.lineWidth=r),Le.ctx.setLineDash(n),Le.ctx.moveTo(t,e),Le.ctx.lineTo(i,s),Le.colors.stroke(),Le.ctx.setLineDash([])}static dottedLine(t,e,i,s,n=2,o=5,r){return Le.lines.dashedLine(t,e,i,s,[n,o],r,n)}static setLineDash(t){Le.ctx.setLineDash(t)}static resetLineDash(){Le.ctx.setLineDash([])}static setLineWidth(t){Le.ctx.lineWidth=t}static quadraticCurve(t,e,i,s,n,o,r,a){Le.ctx.beginPath(),Le.ctx.moveTo(t,e),Le.ctx.quadraticCurveTo(i,s,n,o),r&&(Le.ctx.strokeStyle=r),void 0!==a&&(Le.ctx.lineWidth=a),Le.colors.stroke()}}class Ie{static pushOpacity(t){const e=this._opacityStack[this._opacityStack.length-1]*t;this._opacityStack.push(e),Le.logger.log("NEXT OPACITY WILL BE",e),Le.effects.setAlpha(e)}static popOpacity(){if(this._opacityStack.length>1){this._opacityStack.pop();const t=this._opacityStack[this._opacityStack.length-1];Le.logger.log("NEXT OPACITY WILL BE",t),Le.effects.setAlpha(t)}}static _clone(){this._opacityStack=[...this._opacityStack]}static saveOpacityState(){this._opacityStateBackup=[...this._opacityStack]}static restoreOpacityState(){this._opacityStateBackup&&(this._opacityStack=this._opacityStateBackup,delete this._opacityStateBackup)}}_t(Ie,"_opacityStack",[1]);class Ee{static rect(t,e,i,s,n){const o=Le.ctx.fillStyle;Le.colors.fill(n),Le.ctx.fillRect(t,e,i,s),Le.ctx.fillStyle=o}static outlineRect(t,e,i,s,n,o=1){const r=Le.ctx.strokeStyle,a=Le.ctx.lineWidth;Le.ctx.strokeStyle=n,Le.ctx.lineWidth=o,Le.ctx.strokeRect(t,e,i,s),Le.ctx.strokeStyle=r,Le.ctx.lineWidth=a}static roundRect(t,e,i,s,n=0,o,r,a){let h;h="number"==typeof n?[n,n,n,n]:Array.isArray(n)?4===n.length?n:[n[0]||0,n[1]||n[0]||0,n[2]||n[0]||0,n[3]||n[1]||n[0]||0]:[0,0,0,0];const[l,c,u,d]=h,f=t+i,p=e+s;Le.lines.beginPath(),Le.lines.moveTo(t+l,e),Le.lines.lineTo(f-c,e),this.arc(f-c,e+c,c,-Math.PI/2,0),Le.lines.lineTo(f,p-u),this.arc(f-u,p-u,u,0,Math.PI/2),Le.lines.lineTo(t+d,p),this.arc(t+d,p-d,d,Math.PI/2,Math.PI),Le.lines.lineTo(t,e+l),this.arc(t+l,e+l,l,Math.PI,-Math.PI/2),Le.lines.closePath(),o&&(Le.fillStyle=o,Le.colors.fill(o)),r&&Le.colors.stroke(r,a)}static fillRoundRect(t,e,i,s,n=0,o){this.roundRect(t,e,i,s,n,o,null)}static strokeRoundRect(t,e,i,s,n=0,o,r){this.roundRect(t,e,i,s,n,null,o,r)}static fillCircle(t,e,i,s){Le.logger.log("PainterShapes.fillCircle",t,e,i,s),Le.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Le.colors.fill(s)}static arc(t,e,i,s,n,o){Le.ctx.arc(t,e,i,s,n,o)}static strokeCircle(t,e,i,s,n){Le.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Le.colors.stroke(s,n)}static fillEllipse(t,e,i,s,n=0,o){Le.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Le.fillStyle=o),Le.colors.fill(o)}static strokeEllipse(t,e,i,s,n=0,o,r){Le.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Le.strokeStyle=o),void 0!==r&&(Le.lineWidth=r),Le.colors.stroke(o,r)}static ellipse(t,e,i,s,n,o,r,a){Le.ctx.ellipse(t,e,i,s,n,o,r,a)}static polygon(t,e,i,s,n){if(t.length<2)return;const o=Le.ctx;o.beginPath(),o.moveTo(t[0].x,t[0].y);for(let e=1;e<t.length;e++)o.lineTo(t[e].x,t[e].y);o.closePath(),e&&Le.colors.fill(e),i&&(n&&(o.lineJoin=n),Le.colors.stroke(i,s))}}class Fe{static font(){return Le.ctx.font}static setFont(t){Le.ctx.font=t}static setTextAlign(t){Le.ctx.textAlign=t}static setTextBaseline(t){Le.ctx.textBaseline=t}static fillText(t,e,i,s,n){s&&(Le.ctx.fillStyle=s),n&&(Le.ctx.font=n),Le.ctx.fillText(t,e,i)}static strokeText(t,e,i,s,n,o){s&&(Le.ctx.strokeStyle=s),void 0!==n&&(Le.ctx.lineWidth=n),o&&(Le.ctx.font=o),Le.ctx.strokeText(t,e,i)}static measureTextDimensions(t,e,i="start",s="alphabetic"){e&&(Le.ctx.font=e);const n=Le.ctx.measureText(t);let o=0;return"middle"===s&&(o=-1.5),{width:n.width,height:n.actualBoundingBoxAscent+n.actualBoundingBoxDescent,verticalAdjustment:o}}static measureTextWidth(t,e){return e&&(Le.ctx.font=e),Le.ctx.measureText(t).width}static outlinedText(t,e,i,s,n,o,r){r&&(Le.ctx.font=r),Le.ctx.strokeStyle=n,Le.ctx.lineWidth=o,Le.ctx.strokeText(t,e,i),Le.ctx.fillStyle=s,Le.ctx.fillText(t,e,i)}static wrappedText(t,e,i,s,n,o,r){o&&(Le.ctx.fillStyle=o),r&&(Le.ctx.font=r);const a=t.split(" ");let h="",l="",c=1;for(let t=0;t<a.length;t++)l=h+a[t]+" ",Le.ctx.measureText(l).width>s&&t>0?(Le.ctx.fillText(h,e,i),h=a[t]+" ",i+=n,c++):h=l;return Le.ctx.fillText(h,e,i),c*n}static textOnPath(t,e,i,s,n=!1){if(e.length<2)return;i&&(Le.ctx.fillStyle=i),s&&(Le.ctx.font=s);const o=t.split(""),r=o.map(t=>Le.ctx.measureText(t).width);n&&(o.reverse(),r.reverse(),e.reverse());let a=0;for(let t=1;t<e.length;t++){const i=e[t].x-e[t-1].x,s=e[t].y-e[t-1].y;a+=Math.sqrt(i*i+s*s)}let h=(a-r.reduce((t,e)=>t+e,0))/2;h<0&&(h=0);let l=h;for(let t=0;t<o.length;t++){const i=r[t],{x:s,y:n,angle:a}=getPositionOnPath(e,l);Le.ctx.save(),Le.ctx.translate(s,n),Le.ctx.rotate(a),Le.ctx.fillText(o[t],0,0),Le.ctx.restore(),l+=i}}static getPositionOnPath(t,e){let i=0;for(let s=1;s<t.length;s++){const n=t[s-1],o=t[s],r=o.x-n.x,a=o.y-n.y,h=Math.sqrt(r*r+a*a);if(i+h>=e){const t=(e-i)/h;return{x:n.x+r*t,y:n.y+a*t,angle:Math.atan2(a,r)}}i+=h}const s=t[t.length-1],n=t[t.length-2],o=Math.atan2(s.y-n.y,s.x-n.x);return{x:s.x,y:s.y,angle:o}}}const Oe=class t{static get colors(){return St(this,C,T).call(this,"colors",bt(this,y)),bt(this,y)}static get effects(){return St(this,C,T).call(this,"effects",bt(this,_)),bt(this,_)}static get img(){return St(this,C,T).call(this,"img",bt(this,x)),bt(this,x)}static get lines(){return St(this,C,T).call(this,"lines",bt(this,b)),bt(this,b)}static get opacity(){return St(this,C,T).call(this,"opacity",bt(this,w)),bt(this,w)}static get shapes(){return St(this,C,T).call(this,"shapes",bt(this,M)),bt(this,M)}static get text(){return St(this,C,T).call(this,"text",bt(this,S)),bt(this,S)}static set ctx(t){this._ctx=t}static get ctx(){if(!this._ctx)throw new Error("Cannot access Painter.ctx before initialization!");return this._ctx}static init(e){this._ctx=e,this.saveStack=[],Mt(this,y,Ye),Mt(this,_,ze),Mt(this,x,De),Mt(this,b,Be),Mt(this,w,Ie),Mt(this,M,Ee),Mt(this,S,Fe),t.logger=Te.getLogger("Painter"),t.saveStack=[]}static setContext(t){this._ctx=t}static save(){const e=((new Error).stack.split("\n")[2]||"").match(/at\s+(\w+)\.(\w+)/),i=e?`${e[1]}.${e[2]}`:"unknown";this.saveStack.push(i),this.logger.log(`Painter.save() by: ${i}`),this.ctx.save(),t.opacity.saveOpacityState()}static restore(){if(0===this.saveStack.length)return void console.error("PAINTER ERROR: restore() without matching save()!");const e=this.saveStack.pop();this.logger.log(`Painter.restore() balancing save from: ${e}`),this.ctx.restore(),t.opacity.restoreOpacityState()}static translateTo(t,e){(isNaN(t)||void 0===t)&&(t=0),(isNaN(e)||void 0===e)&&(e=0),this.logger.log("moveTo",t,e),this.ctx.translate(t,e)}static resetPosition(){this.logger.log("resetPosition");const t=this.ctx.getTransform();this.ctx.setTransform(t.a,t.b,t.c,t.d,0,0)}static withPosition(t,e,i){this.logger.log("withPosition",t,e),this.save(),this.translateTo(t,e),i(),this.restore()}static clear(e=0,i=0,s=t.ctx.canvas.width,n=t.ctx.canvas.height){t.ctx.clearRect(e,i,s,n)}static translate(e,i){t.ctx.translate(e,i)}static rotate(e){t.logger.log("Painter.rotate",e),t.ctx.rotate(e)}static scale(e,i){t.logger.log("Painter.scale",e,i),t.ctx.scale(e,i)}static useCtx(t,e={}){const i=this.ctx,{saveState:s=!1}=e;s&&this.save(),i.beginPath(),t(i),i.beginPath(),s&&this.restore()}};y=new WeakMap,_=new WeakMap,x=new WeakMap,b=new WeakMap,w=new WeakMap,M=new WeakMap,S=new WeakMap,C=new WeakSet,T=function(t,e){if(!e)throw new Error(`Painter.${t} is not initialized. Call Painter.init(ctx) first.`)},wt(Oe,C),wt(Oe,y,null),wt(Oe,_,null),wt(Oe,x,null),wt(Oe,b,null),wt(Oe,w,null),wt(Oe,M,null),wt(Oe,S,null),_t(Oe,"logger");let Le=Oe;class Ye{static fill(t){Le.logger.log("PainterColors.fill - before:",Le.ctx.fillStyle,"setting to:",t),Le.ctx.fillStyle,Le.ctx.fillStyle=t,Le.ctx.fill(),Le.logger.log("PainterColors.fill - after:",Le.ctx.fillStyle)}static strokeOptions(t){t.color&&(Le.ctx.strokeStyle=t.color),void 0!==t.lineWidth&&(Le.ctx.lineWidth=t.lineWidth),t.lineCap&&(Le.ctx.lineCap=t.lineCap),t.lineJoin&&(Le.ctx.lineJoin=t.lineJoin),t.strokeStyle&&(Le.ctx.strokeStyle=t.strokeStyle)}static stroke(t,e){t&&(Le.ctx.strokeStyle=t),void 0!==e&&(Le.ctx.lineWidth=e),Le.ctx.stroke()}static setFillColor(t){Le.ctx.fillStyle=t}static setStrokeColor(t){Le.ctx.strokeStyle=t}static randomColorRGB(){const t=Math.floor(360*Math.random()),e=70+Math.floor(30*Math.random()),i=50+Math.floor(20*Math.random());return Le.colors.hslToRgb(t,e,i)}static randomColorRGBA(t=255){const[e,i,s]=this.randomColorRGB();return[e,i,s,t]}static randomColorHSL(){return`hsl(${360*Math.random()}, 100%, 50%)`}static randomColorHSL_RGBA(t=255){const e=360*Math.random(),i=60+40*Math.random(),s=40+40*Math.random(),[n,o,r]=Le.colors.hslToRgb(e,i,s);return[n,o,r,t]}static randomColorHEX(){return"#"+(1048575*Math.random()*1e6).toString(16).slice(0,6)}static parseColorString(t){if((t=t.trim().toLowerCase()).startsWith("hsl")){const e=t.replace(/hsla?\(|\)/g,""),[i,s,n]=e.split(",").map(t=>t.trim()),o=parseFloat(i),r=parseFloat(s)/100,a=parseFloat(n)/100;return Le.colors.hslToRgb(o,r,a)}if(t.startsWith("#"))return hexToRgb(t);if(t.startsWith("rgb")){const e=t.replace(/rgba?\(|\)/g,""),[i,s,n]=e.split(",").map(t=>parseInt(t.trim()));return[i,s,n]}return[0,0,0]}static rgbArrayToCSS([t,e,i]){return`rgb(${Math.round(t)}, ${Math.round(e)}, ${Math.round(i)})`}static hslToRgb(t,e,i){i/=100;const s=e=>(e+t/30)%12,n=(e/=100)*Math.min(i,1-i),o=t=>i-n*Math.max(-1,Math.min(s(t)-3,Math.min(9-s(t),1)));return[Math.round(255*o(0)),Math.round(255*o(8)),Math.round(255*o(4))]}static rgbToHsl(t,e,i){t/=255,e/=255,i/=255;const s=Math.max(t,e,i),n=Math.min(t,e,i),o=s-n;let r=0,a=0,h=(s+n)/2;if(0!==o)switch(a=o/(1-Math.abs(2*h-1)),s){case t:r=((e-i)/o+6)%6*60;break;case e:r=60*((i-t)/o+2);break;case i:r=60*((t-e)/o+4)}return[r%360,a,h]}static hexToRgb(t){const e=t.replace("#","");return[parseInt(e.substring(0,2),16),parseInt(e.substring(2,4),16),parseInt(e.substring(4,6),16)]}static linearGradient(t,e,i,s,n){const o=Le.ctx.createLinearGradient(t,e,i,s);for(const t of n)o.addColorStop(t.offset,t.color);return o}static radialGradient(t,e,i,s,n,o,r){const a=Le.ctx.createRadialGradient(t,e,i,s,n,o);for(const t of r)a.addColorStop(t.offset,t.color);return a}static verticalGradient(t,e,i,s,n){return Le.colors.linearGradient(t,e,t,e+s,n)}static horizontalGradient(t,e,i,s,n){return Le.colors.linearGradient(t,e,t+i,e,n)}static conicGradient(t,e,i,s){if("function"==typeof Le.ctx.createConicGradient){const n=Le.ctx.createConicGradient(i,t,e);for(const t of s)n.addColorStop(t.offset,t.color);return n}return null}static rgba(t,e,i,s=1){return`rgba(${Math.round(t)}, ${Math.round(e)}, ${Math.round(i)}, ${s})`}static hsl(t,e,i){return`hsl(${t}, ${e}%, ${i}%)`}static hsla(t,e,i,s){return`hsla(${t}, ${e}%, ${i}%, ${s})`}}class Xe extends ke{constructor(t={}){super(t),this._x="number"==typeof t.x?t.x:0,this._y="number"==typeof t.y?t.y:0,this._width="number"==typeof t.width?t.width:0,this._height="number"==typeof t.height?t.height:0,this.logger.log("Euclidian",this._x,this._y,this._width,this._height)}get x(){return this._x}set x(t){this.validateProp(t,"x"),this._x=t}get y(){return this._y}set y(t){this.validateProp(t,"y"),this._y=t}get width(){return this._width}set width(t){this.validateProp(t,"width"),this._width=Math.max(0,t)}get height(){return this._height}set height(t){this.validateProp(t,"height"),this._height=Math.max(0,t)}get debug(){return this._debug}set debug(t){this.validateProp(t,"debug"),this._debug=Boolean(t)}get debugColor(){return this._debugColor}set debugColor(t){this.validateProp(t,"debugColor"),this._debugColor=t}validateProp(t,e){if(null==t)throw new Error("Invalid property value: "+e+" "+t)}}class We extends Xe{constructor(t={}){super(t),this._minX=t.minX,this._maxX=t.maxX,this._minY=t.minY,this._maxY=t.maxY,this._boundsDirty=!0,this._cachedBounds=null,this.crisp=t.crisp??!0,this.logger.log("Geometry2d",this.x,this.y,this.width,this.height)}update(){this.trace("Geometry2d.update"),this.applyConstraints(),this.getBounds()}get minX(){return this._minX}set minX(t){this._minX=t}get maxX(){return this._maxX}set maxX(t){this._maxX=t}get minY(){return this._minY}set minY(t){this._minY=t}get maxY(){return this._maxY}set maxY(t){this._maxY=t}get boundsDirty(){return this._boundsDirty}applyConstraints(){void 0!==this._minX&&(this.x=Math.max(this.x,this._minX)),void 0!==this._maxX&&(this.x=Math.min(this.x,this._maxX)),void 0!==this._minY&&(this.y=Math.max(this.y,this._minY)),void 0!==this._maxY&&(this.y=Math.min(this.y,this._maxY)),this.crisp&&(this.x=Math.round(this.x),this.y=Math.round(this.y),this.width=Math.round(this.width),this.height=Math.round(this.height))}getBounds(){return!this._boundsDirty&&this._cachedBounds||(this._cachedBounds=this.calculateBounds(),this._boundsDirty=!1),this._cachedBounds}calculateBounds(){return{width:this.width,height:this.height,x:this.x,y:this.y}}getLocalPosition(){let t=0,e=0;return this.parent&&(t=this.parent.x,e=this.parent.y),{x:this.x-t-this.width/2,y:this.y-e-this.height/2}}markBoundsDirty(){this._boundsDirty=!0}validateProp(t,e){super.validateProp(t,e),t!==this[e]&&this.markBoundsDirty()}setTopLeft(t,e){return this.x=t+this.width/2,this.y=e+this.height/2,this}setCenter(t,e){return this.x=t,this.y=e,this}}class He extends We{constructor(t={}){super(t),this._debug=Boolean(t.debug),this._debugColor="string"==typeof t.debugColor?t.debugColor:"#0f0",this.logger.log("Traceable",this.x,this.y,this.width,this.height)}drawDebug(){if(!this._debug)return;const t=this.getDebugBounds();this.logger.log(this.constructor.name,"drawDebug",t.x,t.y,t.width,t.height),Le.shapes.outlineRect(t.x,t.y,t.width,t.height,this._debugColor,2)}getDebugBounds(){return{width:this.width,height:this.height,x:-this.width/2,y:-this.height/2}}trace(t="render"){this.logger.log(null==this.name?this.constructor.name:this.name,t,"x",this.x,"y",this.y,"w",this.width,"h",this.height,"opacity",this._opacity,"visible",this._visible,"active",this._active,"debug",this.debug)}}class Ue extends He{constructor(t={}){super(t),this._visible=!1!==t.visible,this._opacity="number"==typeof t.opacity?t.opacity:1,this._active=!1!==t.active,this.zIndex=t.zIndex??0,this._shadowColor=t.shadowColor??void 0,this._shadowBlur=t.shadowBlur??0,this._shadowOffsetX=t.shadowOffsetX??0,this._shadowOffsetY=t.shadowOffsetY??0,this._cacheRendering=t.cacheRendering??!1,this._cacheCanvas=null,this._cacheDirty=!0,this._cachePadding=t.cachePadding??2,this._tick=0,this.logger.log("Renderable",this.x,this.y,this.width,this.height)}render(){if(this._visible&&!(this._opacity<=0)){if(Le.save(),Le.effects.setBlendMode(this._blendMode),this.crisp?Le.translateTo(Math.round(this.x),Math.round(this.y)):Le.translateTo(this.x,this.y),this.applyShadow(Le.ctx),this._cacheRendering&&"Renderable"!==this.constructor.name){const t="number"==typeof this.width?this.width:0,e="number"==typeof this.height?this.height:0,i=2*this._cachePadding,s=Math.ceil(t+i)||1,n=Math.ceil(e+i)||1;this._cacheCanvas&&this._cacheCanvas.width===s&&this._cacheCanvas.height===n||(this._cacheCanvas=document.createElement("canvas"),this._cacheCanvas.width=s,this._cacheCanvas.height=n,this._cacheDirty=!0),this._cacheDirty&&(this._renderToCache(s,n),this._cacheDirty=!1),Le.opacity.pushOpacity(this._opacity);const o=this.rotation??0,r=this.scaleX??1,a=this.scaleY??1;Le.img.draw(this._cacheCanvas,0,0,{width:s,height:n,rotation:o,scaleX:r,scaleY:a,anchor:"center"}),Le.opacity.popOpacity()}else Le.opacity.pushOpacity(this._opacity),this.draw(),Le.opacity.popOpacity();Le.restore()}}_renderToCache(t,e){const i=this._cacheCanvas.getContext("2d");i.clearRect(0,0,t,e);const s=Le.ctx;Le.ctx=i,this._isCaching=!0,i.save(),i.translate(t/2,e/2),this.draw(),i.restore(),this._isCaching=!1,Le.ctx=s}invalidateCache(){this._cacheDirty=!0}draw(){this.drawDebug()}update(t){this.trace("Renderable.update"),this._tick+=t,super.update(t)}applyShadow(t){this._shadowColor&&(t.shadowColor=this._shadowColor,t.shadowBlur=this._shadowBlur,t.shadowOffsetX=this._shadowOffsetX,t.shadowOffsetY=this._shadowOffsetY)}get visible(){return this._visible}set visible(t){this._visible=Boolean(t)}get width(){return super.width}set width(t){super.width=t,this.invalidateCache()}get height(){return super.height}set height(t){super.height=t,this.invalidateCache()}get active(){return this._active}set active(t){this._active=Boolean(t)}get opacity(){return this._opacity}set opacity(t){this._opacity=Math.min(1,Math.max(0,"number"==typeof t?t:1))}get shadowColor(){return this._shadowColor}set shadowColor(t){this._shadowColor=t,this.invalidateCache()}get shadowBlur(){return this._shadowBlur}set shadowBlur(t){this._shadowBlur=t,this.invalidateCache()}get shadowOffsetX(){return this._shadowOffsetX}set shadowOffsetX(t){this._shadowOffsetX=t,this.invalidateCache()}get shadowOffsetY(){return this._shadowOffsetY}set shadowOffsetY(t){this._shadowOffsetY=t,this.invalidateCache()}get tick(){return this._tick}get cacheRendering(){return this._cacheRendering}set cacheRendering(t){this._cacheRendering=Boolean(t),t&&this.invalidateCache()}}const Ge=class t{constructor(t){this._owner=t}get owner(){return this._owner}x(t){return this._owner._x=t,this._owner.markBoundsDirty(),this}y(t){return this._owner._y=t,this._owner.markBoundsDirty(),this}position(t,e){return this._owner._x=t,this._owner._y=e,this._owner.markBoundsDirty(),this}translateBy(t,e){return this._owner._x+=t,this._owner._y+=e,this._owner.markBoundsDirty(),this}width(t){var e,i;return this._owner._width=Math.max(0,t),this._owner.markBoundsDirty(),null==(i=(e=this._owner).invalidateCache)||i.call(e),this}height(t){var e,i;return this._owner._height=Math.max(0,t),this._owner.markBoundsDirty(),null==(i=(e=this._owner).invalidateCache)||i.call(e),this}size(t,e){var i,s;return this._owner._width=Math.max(0,t),this._owner._height=Math.max(0,e),this._owner.markBoundsDirty(),null==(s=(i=this._owner).invalidateCache)||s.call(i),this}rotation(t){return this._owner._rotation=t*Math.PI/180,this._owner.markBoundsDirty(),this}rotationRad(t){return this._owner._rotation=t,this._owner.markBoundsDirty(),this}rotateBy(t){return this._owner._rotation+=t*Math.PI/180,this._owner.markBoundsDirty(),this}scaleX(t){return this._owner._scaleX=t,this._owner.markBoundsDirty(),this}scaleY(t){return this._owner._scaleY=t,this._owner.markBoundsDirty(),this}scale(t){return this._owner._scaleX=t,this._owner._scaleY=t,this._owner.markBoundsDirty(),this}scaleBy(t){return this._owner._scaleX*=t,this._owner._scaleY*=t,this._owner.markBoundsDirty(),this}set(t){var e,i;let s=!1;return void 0!==t.x&&(this._owner._x=t.x),void 0!==t.y&&(this._owner._y=t.y),void 0!==t.width&&(this._owner._width=Math.max(0,t.width),s=!0),void 0!==t.height&&(this._owner._height=Math.max(0,t.height),s=!0),void 0!==t.rotation&&(this._owner._rotation=t.rotation*Math.PI/180),void 0!==t.scaleX&&(this._owner._scaleX=t.scaleX),void 0!==t.scaleY&&(this._owner._scaleY=t.scaleY),this._owner.markBoundsDirty(),s&&(null==(i=(e=this._owner).invalidateCache)||i.call(e)),this}reset(){return this._owner._rotation=0,this._owner._scaleX=1,this._owner._scaleY=1,this._owner.markBoundsDirty(),this}resetAll(){var t,e;return this._owner._x=0,this._owner._y=0,this._owner._width=0,this._owner._height=0,this._owner._rotation=0,this._owner._scaleX=1,this._owner._scaleY=1,this._owner.markBoundsDirty(),null==(e=(t=this._owner).invalidateCache)||e.call(t),this}toObject(){return{x:this._owner._x,y:this._owner._y,width:this._owner._width,height:this._owner._height,rotation:180*this._owner._rotation/Math.PI,scaleX:this._owner._scaleX,scaleY:this._owner._scaleY}}copyFrom(e){const i=e instanceof t?e.toObject():e;return this.set(i)}static handleDirectSet(e,i){if(t.strictMode)throw new Error(`Direct property assignment "${e} = ${i}" is disabled. Use shape.transform.${e}(${i}) instead. Set Transform.strictMode = false to allow direct assignment.`);console.warn(`[Deprecation] Direct assignment "${e} = ${i}" is deprecated. Use shape.transform.${e}(${i}) instead.`)}};_t(Ge,"strictMode",!1);let Ne=Ge;class qe extends Ue{constructor(t={}){super(t),this._rotation=t.rotation*Math.PI/180,this._scaleX=t.scaleX??1,this._scaleY=t.scaleY??1,this.transform=new Ne(this),this.logger.log("Transformable",this.x,this.y,this.width,this.height)}draw(){this.applyTransforms();const t=Le.ctx;t.beginPath(),t.fill(),this.drawDebug()}applyTransforms(){this._isCaching||(Le.rotate(this._rotation),Le.scale(this._scaleX,this._scaleY))}get rotation(){return this._rotation}set rotation(t){this._rotation=t*Math.PI/180,this.markBoundsDirty()}get scaleX(){return this._scaleX}set scaleX(t){this._scaleX=t,this.markBoundsDirty()}get scaleY(){return this._scaleY}set scaleY(t){this._scaleY=t,this.markBoundsDirty()}calculateBounds(){const t=this.width/2,e=this.height/2,i=[{x:-t,y:-e},{x:t,y:-e},{x:t,y:e},{x:-t,y:e}],s=Math.cos(this._rotation),n=Math.sin(this._rotation),o=i.map(({x:t,y:e})=>{t*=this._scaleX,e*=this._scaleY;const i=t*n+e*s;return{x:t*s-e*n+this.x,y:i+this.y}}),r=o.map(t=>t.x),a=o.map(t=>t.y),h=Math.min(...r),l=Math.max(...r),c=Math.min(...a),u=Math.max(...a);return{x:(h+l)/2,y:(c+u)/2,width:l-h,height:u-c}}}class Ze extends qe{constructor(t={}){super(t),this._color=t.color??null,this._stroke=t.stroke??null,this._lineWidth=t.lineWidth??1,this._lineJoin=t.lineJoin??"miter",this._lineCap=t.lineCap??"butt",this._miterLimit=t.miterLimit??10,this.logger.log("Shape",this.x,this.y,this.width,this.height)}get color(){return this._color}set color(t){this._color=t,this.invalidateCache()}get stroke(){return this._stroke}set stroke(t){this._stroke=t,this.invalidateCache()}get lineWidth(){return this._lineWidth}set lineWidth(t){this._lineWidth=Math.max(0,t),this.invalidateCache()}get lineJoin(){return this._lineJoin}set lineJoin(t){this._lineJoin=t,this.invalidateCache()}get lineCap(){return this._lineCap}set lineCap(t){this._lineCap=t,this.invalidateCache()}get miterLimit(){return this._miterLimit}set miterLimit(t){this._miterLimit=t,this.invalidateCache()}}class Ve extends qe{constructor(t={}){super(t),this._collection=new Ct({sortByZIndex:t.sortByZIndex||!0}),this._collection._owner=this,this._childrenVersion=0,this._cachedBounds=null,t.width=Math.max(0,t.width||0),t.height=Math.max(0,t.height||0),this.userDefinedWidth=t.width,this.userDefinedHeight=t.height,this.userDefinedDimensions=void 0!==t.width&&void 0!==t.height&&(t.width>0||t.height>0)}add(t){if(null==t||null==t)throw new Error("Object is null or undefined");if(!(t instanceof qe))throw new TypeError("Group can only add Transformable instances");return t.parent=this,this._collection.add(t),this._childrenVersion++,this.markBoundsDirty(),this.invalidateCache(),t}remove(t){const e=this._collection.remove(t);return e&&(t.parent=null,this._childrenVersion++,this.markBoundsDirty(),this.invalidateCache()),e}clear(){this._collection.clear(),this._childrenVersion++,this.markBoundsDirty(),this.invalidateCache()}bringToFront(t){return this._collection.bringToFront(t)}sendToBack(t){return this._collection.sendToBack(t)}bringForward(t){return this._collection.bringForward(t)}sendBackward(t){return this._collection.sendBackward(t)}draw(){super.draw(),this.logger.log("Group.draw children:",this.children.length),this._renderChildren()}_renderChildren(){const t=this._collection.getSortedChildren();for(let e=0;e<t.length;e++){const i=t[e];i.visible&&(Le.save(),i.render(),Le.restore())}}update(t){this.logger.groupCollapsed("Group.update");const e=this._collection.getSortedChildren();for(let i=0;i<e.length;i++){const s=e[i];s.active&&"function"==typeof s.update&&s.update(t)}super.update(t),this.logger.groupEnd()}get children(){var t;return(null==(t=this._collection)?void 0:t.children)||[]}get width(){return this.userDefinedDimensions?this._width:this.getBounds().width}set width(t){const e=Math.max(0,t);this._width=e,this.userDefinedWidth=e,this.userDefinedDimensions=(this.userDefinedWidth>0||this.userDefinedHeight>0)&&void 0!==this.userDefinedWidth&&void 0!==this.userDefinedHeight,this.markBoundsDirty()}get height(){return this.userDefinedDimensions?this._height:this.getBounds().height}set height(t){const e=Math.max(0,t);this._height=e,this.userDefinedHeight=e,this.userDefinedDimensions=(this.userDefinedWidth>0||this.userDefinedHeight>0)&&void 0!==this.userDefinedWidth&&void 0!==this.userDefinedHeight,this.markBoundsDirty()}calculateBounds(){var t;if(this.userDefinedDimensions)return{x:this.x,y:this.y,width:this._width,height:this._height};if(!(null==(t=this.children)?void 0:t.length))return{x:this.x,y:this.y,width:0,height:0};let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const t of this.children){const o=t.x,r=t.y,a=t.width,h=t.height,l=o-a/2,c=o+a/2,u=r-h/2,d=r+h/2;e=Math.min(e,l),s=Math.max(s,c),i=Math.min(i,u),n=Math.max(n,d)}const o=s-e,r=n-i;return{x:this.x,y:this.y,width:o,height:r}}getDebugBounds(){const t=this.calculateBounds();return{width:t.width,height:t.height,x:-t.width/2,y:-t.height/2}}forEachTransform(t){return this.children.forEach((e,i)=>{e.transform&&t(e.transform,e,i)}),this}translateChildren(t,e){return this.forEachTransform(i=>i.translateBy(t,e))}scaleChildren(t){return this.forEachTransform(e=>e.scaleBy(t))}rotateChildren(t){return this.forEachTransform(e=>e.rotateBy(t))}resetChildTransforms(){return this.forEachTransform(t=>t.reset())}}class $e extends Ze{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Le.lines.beginPath(),Le.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle,!1),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}getBounds(){const t=this.radius;return{x:this.x,y:this.y,width:2*t,height:2*t}}}class je extends Ze{constructor(t,e={}){super(e),this._radius=t,this.width=2*t,this.height=2*t}draw(){super.draw(),this.color&&Le.shapes.fillCircle(0,0,this._radius,this.color),this.stroke&&Le.shapes.strokeCircle(0,0,this._radius,this.stroke,this.lineWidth)}calculateBounds(){const t=2*this._radius;return this.trace("Circle.calculateBounds:"+t),{x:this.x,y:this.y,width:t,height:t}}get radius(){return this._radius}set radius(t){this.validateProp(t,"radius"),t!=this._radius&&(this._radius=t,this.width=2*t,this.height=2*t,this._boundsDirty=!0,this.calculateBounds())}}class Ke extends Ze{constructor(t=40,e={}){super(e),this.size=t,this.width=2*t,this.height=2*t}draw(){super.draw();const t=this.size,e=Le.ctx,i=[{x:.5*-t,y:0,r:.4*t},{x:.2*-t,y:.3*-t,r:.35*t},{x:.2*t,y:.35*-t,r:.4*t},{x:.5*t,y:0,r:.35*t},{x:0,y:.15*t,r:.5*t}];if(this.color){e.fillStyle=this.color;for(const t of i)e.beginPath(),e.arc(t.x,t.y,t.r,0,2*Math.PI),e.fill()}if(this.stroke){e.strokeStyle=this.stroke,e.lineWidth=this.lineWidth;for(const t of i)e.beginPath(),e.arc(t.x,t.y,t.r,0,2*Math.PI),e.stroke()}}getBounds(){const t=2*this.size;return{x:this.x,y:this.y,width:t,height:t}}}class Je extends Ze{constructor(t={}){super(t)}draw(){super.draw(),this.drawRect()}drawRect(){const t=-this.width/2,e=-this.height/2;this.color&&Le.shapes.rect(t,e,this.width,this.height,this.color),this.stroke&&Le.shapes.outlineRect(t,e,this.width,this.height,this.stroke,this.lineWidth)}}class Qe extends Ze{constructor(t=0,e={}){super(e),"number"==typeof t?this.radii=[t,t,t,t]:Array.isArray(t)?this.radii=4===t.length?t:[t[0]||0,t[1]||t[0]||0,t[2]||t[0]||0,t[3]||t[1]||t[0]||0]:this.radii=[0,0,0,0]}draw(){super.draw();const t=-this.width/2,e=-this.height/2;this.color&&this.stroke?Le.shapes.roundRect(t,e,this.width,this.height,this.radii,this.color,this.stroke,this.lineWidth):this.color?Le.shapes.fillRoundRect(t,e,this.width,this.height,this.radii,this.color):this.stroke&&Le.shapes.strokeRoundRect(t,e,this.width,this.height,this.radii,this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}}class ti extends Je{constructor(t,e={}){super(e),this.width=t,this.height=t}}class ei extends Ze{constructor(t={}){super(t)}draw(){super.draw();const t=this.width/2,e=this.height/2,i=[{x:0,y:-e},{x:t,y:0},{x:0,y:e},{x:-t,y:0}];Le.shapes.polygon(i,this.color,this.stroke,this.lineWidth)}}class ii extends Ze{constructor(t=40,e={}){super(e),this.length=t}draw(){super.draw();const t=this.length/2;Le.lines.line(-t,-t,t,t,this.stroke,this.lineWidth)}}class si extends Ze{constructor(t=50,e={}){super(e),this.size=t}draw(){super.draw();const t=this.size/2,e=[{x:0,y:-t},{x:t,y:t},{x:-t,y:t}];Le.shapes.polygon(e,this.color,this.stroke,this.lineWidth)}}class ni extends Ze{constructor(t=40,e=5,i=.5,s={}){super(s),this.radius=t,this.spikes=e,this.inset=i}draw(){super.draw();const t=Math.PI/this.spikes,e=-Math.PI/2;Le.lines.beginPath();for(let i=0;i<2*this.spikes;i++){const s=i%2==0?this.radius:this.radius*this.inset,n=i*t+e,o=Math.cos(n)*s,r=Math.sin(n)*s;0===i?Le.lines.moveTo(o,r):Le.lines.lineTo(o,r)}Le.lines.closePath(),this.color&&Le.colors.fill(this.color),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}}class oi{constructor(t,e){if(this.width=t,this.height=e,this.canvas=document.createElement("canvas"),this.canvas.width=t,this.canvas.height=e,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!0,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available, falling back to Canvas 2D"),void(this.available=!1);this.available=!0;const i=this.gl;i.enable(i.BLEND),i.blendFunc(i.ONE,i.ONE_MINUS_SRC_ALPHA),i.viewport(0,0,t,e),this.programs=new Map,this.currentProgram=null,this.uniformLocations=new Map,this._needsAttributeRebind=!1,this._createQuad()}isAvailable(){return this.available}resize(t,e){this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.gl&&(this.gl.viewport(0,0,t,e),this._needsAttributeRebind=!0)}_createQuad(){const t=this.gl,e=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),i=new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1]);this.positionBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),this.uvBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.uvBuffer),t.bufferData(t.ARRAY_BUFFER,i,t.STATIC_DRAW)}_compileShader(t,e){const i=this.gl,s=i.createShader(t);return i.shaderSource(s,e),i.compileShader(s),i.getShaderParameter(s,i.COMPILE_STATUS)?s:(console.error("Shader compile error:",i.getShaderInfoLog(s)),console.error("Source:",e),i.deleteShader(s),null)}useProgram(t,e,i){if(!this.available)return null;const s=this.gl;if(this.programs.has(t)){const e=this.programs.get(t);return s.useProgram(e),this.currentProgram=t,this._needsAttributeRebind&&(this._bindAttributes(e),this._needsAttributeRebind=!1),e}const n=this._compileShader(s.VERTEX_SHADER,e),o=this._compileShader(s.FRAGMENT_SHADER,i);if(!n||!o)return null;const r=s.createProgram();return s.attachShader(r,n),s.attachShader(r,o),s.linkProgram(r),s.getProgramParameter(r,s.LINK_STATUS)?(this.programs.set(t,r),this.uniformLocations.set(t,new Map),s.useProgram(r),this.currentProgram=t,this._bindAttributes(r),r):(console.error("Program link error:",s.getProgramInfoLog(r)),s.deleteProgram(r),null)}_bindAttributes(t){const e=this.gl,i=e.getAttribLocation(t,"aPosition"),s=e.getAttribLocation(t,"aUv");-1!==i&&(e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(i),e.vertexAttribPointer(i,2,e.FLOAT,!1,0,0)),-1!==s&&(e.bindBuffer(e.ARRAY_BUFFER,this.uvBuffer),e.enableVertexAttribArray(s),e.vertexAttribPointer(s,2,e.FLOAT,!1,0,0))}_getUniformLocation(t){const e=this.gl,i=this.programs.get(this.currentProgram),s=this.uniformLocations.get(this.currentProgram);return s.has(t)||s.set(t,e.getUniformLocation(i,t)),s.get(t)}setUniforms(t){if(!this.available||!this.currentProgram)return;const e=this.gl;for(const[i,s]of Object.entries(t)){const t=this._getUniformLocation(i);if(null!==t)if("number"==typeof s)e.uniform1f(t,s);else if(Array.isArray(s))switch(s.length){case 2:e.uniform2fv(t,s);break;case 3:e.uniform3fv(t,s);break;case 4:e.uniform4fv(t,s)}else s instanceof Float32Array&&(9===s.length?e.uniformMatrix3fv(t,!1,s):16===s.length&&e.uniformMatrix4fv(t,!1,s))}}setColorUniform(t,e){if(!this.available||!this.currentProgram)return;const i=e.replace("#",""),s=parseInt(i.substring(0,2),16)/255,n=parseInt(i.substring(2,4),16)/255,o=parseInt(i.substring(4,6),16)/255,r=this._getUniformLocation(t);null!==r&&this.gl.uniform3f(r,s,n,o)}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(){if(!this.available||!this.currentProgram)return;const t=this.gl;t.drawArrays(t.TRIANGLES,0,6)}compositeOnto(t,e,i,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}getCanvas(){return this.canvas}destroy(){if(!this.available)return;const t=this.gl;for(const e of this.programs.values())t.deleteProgram(e);t.deleteBuffer(this.positionBuffer),t.deleteBuffer(this.uvBuffer),this.programs.clear(),this.uniformLocations.clear()}}const ri="\nprecision highp float;\n\nvarying vec2 vUv;\n\n// Uniforms common to all sphere shaders\nuniform float uTime;\nuniform vec2 uResolution;\nuniform vec3 uCameraRotation; // rotationX, rotationY, rotationZ\n\n// =============================================================================\n// NOISE FUNCTIONS\n// =============================================================================\n\nfloat hash(float n) {\n return fract(sin(n) * 43758.5453123);\n}\n\nfloat hash2(vec2 p) {\n return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);\n}\n\nfloat hash3(vec3 p) {\n return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453123);\n}\n\n// 3D Value noise\nfloat noise3D(vec3 x) {\n vec3 i = floor(x);\n vec3 f = fract(x);\n f = f * f * (3.0 - 2.0 * f);\n\n float n = dot(i, vec3(1.0, 57.0, 113.0));\n\n return mix(\n mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),\n mix(hash(n + 57.0), hash(n + 58.0), f.x), f.y),\n mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),\n mix(hash(n + 170.0), hash(n + 171.0), f.x), f.y), f.z\n );\n}\n\n// FBM (Fractional Brownian Motion)\nfloat fbm(vec3 p, int octaves) {\n float value = 0.0;\n float amplitude = 0.5;\n float frequency = 1.0;\n\n for (int i = 0; i < 8; i++) {\n if (i >= octaves) break;\n value += amplitude * noise3D(p * frequency);\n frequency *= 2.0;\n amplitude *= 0.5;\n }\n\n return value;\n}\n\n// =============================================================================\n// RAY-SPHERE INTERSECTION\n// =============================================================================\n\n/**\n * Ray-sphere intersection\n * @param rayOrigin - Ray origin (camera position)\n * @param rayDir - Normalized ray direction\n * @param sphereCenter - Sphere center\n * @param sphereRadius - Sphere radius\n * @return t value for intersection, -1.0 if no hit\n */\nfloat raySphereIntersect(vec3 rayOrigin, vec3 rayDir, vec3 sphereCenter, float sphereRadius) {\n vec3 oc = rayOrigin - sphereCenter;\n float a = dot(rayDir, rayDir);\n float b = 2.0 * dot(oc, rayDir);\n float c = dot(oc, oc) - sphereRadius * sphereRadius;\n float discriminant = b * b - 4.0 * a * c;\n\n if (discriminant < 0.0) {\n return -1.0;\n }\n\n return (-b - sqrt(discriminant)) / (2.0 * a);\n}\n\n// =============================================================================\n// CAMERA AND ROTATION\n// =============================================================================\n\n/**\n * Create rotation matrix from Euler angles\n */\nmat3 rotationMatrix(vec3 rotation) {\n float cx = cos(rotation.x);\n float sx = sin(rotation.x);\n float cy = cos(rotation.y);\n float sy = sin(rotation.y);\n float cz = cos(rotation.z);\n float sz = sin(rotation.z);\n\n mat3 rx = mat3(\n 1.0, 0.0, 0.0,\n 0.0, cx, -sx,\n 0.0, sx, cx\n );\n\n mat3 ry = mat3(\n cy, 0.0, sy,\n 0.0, 1.0, 0.0,\n -sy, 0.0, cy\n );\n\n mat3 rz = mat3(\n cz, -sz, 0.0,\n sz, cz, 0.0,\n 0.0, 0.0, 1.0\n );\n\n return rz * ry * rx;\n}\n\n/**\n * Calculate ray direction from UV coordinates\n * Uses a simple pinhole camera model\n */\nvec3 getRayDirection(vec2 uv) {\n // Convert UV to normalized device coordinates (-1 to 1)\n vec2 ndc = uv * 2.0 - 1.0;\n // Field of view ~53 degrees (atan(0.5) * 2)\n return normalize(vec3(ndc * 0.5, 1.0));\n}\n\n// =============================================================================\n// LIGHTING\n// =============================================================================\n\n/**\n * Simple diffuse + ambient lighting\n */\nfloat lighting(vec3 normal, vec3 lightDir, float ambient) {\n float diffuse = max(0.0, dot(normal, lightDir));\n return ambient + (1.0 - ambient) * diffuse;\n}\n\n/**\n * Fresnel effect for rim lighting\n */\nfloat fresnel(vec3 normal, vec3 viewDir, float power) {\n return pow(1.0 - abs(dot(normal, viewDir)), power);\n}\n",ai={vertex:"\nprecision highp float;\n\nattribute vec2 aPosition;\nattribute vec2 aUv;\n\nvarying vec2 vUv;\n\nvoid main() {\n vUv = aUv;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n",common:ri,star:`\n${ri}\n\nuniform vec3 uStarColor;\nuniform float uTemperature; // Kelvin, affects color\nuniform float uActivityLevel; // 0-1, affects turbulence\nuniform float uRotationSpeed; // Self-rotation speed (radians/second)\n\n// Tidal disruption uniforms\nuniform float uTidalStretch; // 0 = sphere, 1+ = elongated toward BH\nuniform float uStretchDirX; // Direction to black hole (X component)\nuniform float uStretchDirZ; // Direction to black hole (Z component)\nuniform float uStressLevel; // 0-1, surface chaos from tidal forces\nuniform float uBaseRadius; // Dynamic base radius for proper sizing\nuniform float uTidalFlare; // 0-1, sudden brightness burst at disruption start\nuniform float uTidalWobble; // 0-1, violent geometry wobble during trauma\n\n// =============================================================================\n// TIDAL DISTORTION - True Spaghettification via Ellipsoid Deformation\n// Uses ray-ellipsoid intersection for physically correct stretching\n// =============================================================================\n\n/**\n * Ray-Ellipsoid intersection\n * Ellipsoid defined by semi-axes (a, b, c) where:\n * - a = stretch along BH direction (in XZ plane)\n * - b = Y axis (slight compression)\n * - c = perpendicular to BH direction in XZ plane (compression)\n *\n * Technique: Transform ray into "unit sphere space" via inverse scaling\n */\nfloat rayEllipsoidIntersect(vec3 rayOrigin, vec3 rayDir, vec3 center, vec3 semiAxes) {\n // Scale ray into unit sphere space\n vec3 scaledOrigin = (rayOrigin - center) / semiAxes;\n vec3 scaledDir = rayDir / semiAxes;\n\n // Standard ray-sphere intersection in scaled space\n float a = dot(scaledDir, scaledDir);\n float b = 2.0 * dot(scaledOrigin, scaledDir);\n float c = dot(scaledOrigin, scaledOrigin) - 1.0;\n float discriminant = b * b - 4.0 * a * c;\n\n if (discriminant < 0.0) {\n return -1.0;\n }\n\n return (-b - sqrt(discriminant)) / (2.0 * a);\n}\n\n/**\n * Calculate ellipsoid normal at hit point\n * Normal = gradient of ellipsoid equation = 2*(x/a², y/b², z/c²)\n */\nvec3 ellipsoidNormal(vec3 hitPoint, vec3 center, vec3 semiAxes) {\n vec3 localPos = hitPoint - center;\n // Gradient of (x/a)² + (y/b)² + (z/c)² = 1\n vec3 grad = localPos / (semiAxes * semiAxes);\n return normalize(grad);\n}\n\n/**\n * Build tidal stretch axes from BH direction\n * Returns semi-axes (stretchAxis, Y, perpAxis) for ellipsoid\n * Includes violent wobble effect during trauma\n */\nvec3 tidalSemiAxes(float stretch, vec2 stretchDir, float baseRadius, float wobble, float time) {\n // Stretch factor along BH direction (elongation toward/away from BH)\n float stretchFactor = 1.0 + stretch * 0.8; // Up to 1.8x longer\n\n // Compression factor perpendicular (volume roughly conserved)\n float compressFactor = 1.0 / sqrt(stretchFactor); // Compress to conserve volume\n\n // Y axis gets slight compression too\n float yFactor = 1.0 - stretch * 0.15;\n\n // === TRAUMA WOBBLE ===\n // Violent, chaotic geometry distortion during tidal shock\n if (wobble > 0.01) {\n // Multiple frequency wobbles for organic chaos\n float wobble1 = sin(time * 12.0) * cos(time * 7.3);\n float wobble2 = sin(time * 19.0 + 1.5) * cos(time * 11.0);\n float wobble3 = sin(time * 8.0 + 3.0);\n \n // Asymmetric wobble - more violent on stretch axis\n float stretchWobble = wobble * (0.3 + wobble1 * 0.2 + wobble2 * 0.15);\n float yWobble = wobble * (wobble2 * 0.25 + wobble3 * 0.15);\n float perpWobble = wobble * (wobble3 * 0.2 + wobble1 * 0.1);\n \n stretchFactor *= (1.0 + stretchWobble);\n yFactor *= (1.0 + yWobble);\n compressFactor *= (1.0 + perpWobble);\n }\n\n return vec3(\n baseRadius * stretchFactor, // Stretch along BH radial\n baseRadius * yFactor, // Slight Y compression\n baseRadius * compressFactor // Compress perpendicular\n );\n}\n\n// =============================================================================\n// PLASMA NOISE with flowing distortion\n// =============================================================================\n\nfloat plasmaNoise(vec3 p, float time) {\n float value = 0.0;\n float amplitude = 1.0;\n float frequency = 1.0;\n float totalAmp = 0.0;\n\n for (int i = 0; i < 5; i++) {\n vec3 offset = vec3(\n sin(time * 0.1 + float(i)) * 0.5,\n cos(time * 0.15 + float(i) * 0.7) * 0.5,\n time * 0.05\n );\n value += amplitude * noise3D((p + offset) * frequency);\n totalAmp += amplitude;\n amplitude *= 0.5;\n frequency *= 2.0;\n }\n\n return value / totalAmp;\n}\n\n// =============================================================================\n// HOT BUBBLES - bright spots that appear and pop\n// =============================================================================\n\nfloat hotBubbles(vec3 p, float time) {\n // Large slow bubbles\n vec3 p1 = p * 5.0 + vec3(0.0, time * 0.06, 0.0);\n float b1 = noise3D(p1);\n b1 = smoothstep(0.3, 0.6, b1);\n\n // Medium bubbles, faster\n vec3 p2 = p * 9.0 + vec3(time * 0.04, time * 0.08, 0.0);\n float b2 = noise3D(p2);\n b2 = smoothstep(0.35, 0.65, b2);\n\n // Small rapid bubbles\n vec3 p3 = p * 16.0 + vec3(time * 0.1, 0.0, time * 0.12);\n float b3 = noise3D(p3);\n b3 = smoothstep(0.4, 0.7, b3);\n\n float bubbles = b1 * 0.5 + b2 * 0.35 + b3 * 0.15;\n float pulse = sin(time * 2.0 + p.x * 10.0) * 0.3 + 0.7;\n\n return bubbles * pulse;\n}\n\n// =============================================================================\n// BOILING TURBULENCE - fast chaotic movement\n// =============================================================================\n\nfloat boilingTurbulence(vec3 p, float time) {\n float turb = 0.0;\n float amp = 1.0;\n float freq = 4.0;\n\n for (int i = 0; i < 4; i++) {\n vec3 offset = vec3(\n sin(time * 0.3 + float(i) * 1.7) * 0.5,\n cos(time * 0.25 + float(i) * 2.3) * 0.5,\n time * 0.15 * (1.0 + float(i) * 0.3)\n );\n turb += amp * abs(noise3D(p * freq + offset));\n amp *= 0.5;\n freq *= 2.1;\n }\n return turb;\n}\n\n// =============================================================================\n// CORONA FLAMES - structures around the edge\n// =============================================================================\n\nfloat coronaFlames(float angle, float rimFactor, float time, float activity) {\n // Multiple flame frequencies\n float flames = 0.0;\n\n // Large slow flames\n float f1 = sin(angle * 5.0 + time * 0.5) * 0.5 + 0.5;\n f1 *= noise3D(vec3(angle * 2.0, time * 0.3, 0.0));\n\n // Medium flames\n float f2 = sin(angle * 12.0 + time * 0.8) * 0.5 + 0.5;\n f2 *= noise3D(vec3(angle * 4.0, time * 0.5, 5.0));\n\n // Small rapid flames\n float f3 = sin(angle * 25.0 + time * 1.5) * 0.5 + 0.5;\n f3 *= noise3D(vec3(angle * 8.0, time * 0.8, 10.0));\n\n flames = f1 * 0.5 + f2 * 0.3 + f3 * 0.2;\n\n // Flames only visible at rim\n flames *= pow(rimFactor, 1.5);\n flames *= 0.5 + activity * 0.5;\n\n return flames;\n}\n\n// =============================================================================\n// SELF ROTATION - rotate normal around Y axis\n// =============================================================================\n\nvec3 rotateY(vec3 v, float angle) {\n float c = cos(angle);\n float s = sin(angle);\n return vec3(v.x * c + v.z * s, v.y, -v.x * s + v.z * c);\n}\n\nvoid main() {\n // === CIRCULAR MASK - prevents square canvas artifacts ===\n vec2 center = vUv - 0.5;\n float distFromCenter = length(center) * 2.0;\n\n // Wider cutoff for stretched ellipsoid\n if (distFromCenter > 1.6) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n float circularMask = 1.0 - smoothstep(1.3, 1.6, distFromCenter);\n\n // Setup ray - camera looking at sphere from fixed position\n vec3 rayOrigin = vec3(0.0, 0.0, -2.5);\n vec3 rayDir = getRayDirection(vUv);\n\n float time = uTime;\n float selfRotation = time * uRotationSpeed;\n\n // === TIDAL ELLIPSOID SETUP ===\n // Direction toward black hole in XZ plane\n vec2 stretchDir2D = normalize(vec2(uStretchDirX, uStretchDirZ) + 0.0001);\n float stretch = uTidalStretch;\n\n // Build rotation matrix to align ellipsoid X-axis with stretch direction\n // This rotates the ellipsoid so its long axis points toward the BH\n float stretchAngle = atan(stretchDir2D.y, stretchDir2D.x);\n float cs = cos(stretchAngle);\n float sn = sin(stretchAngle);\n\n // Rotation matrix around Y axis (to align stretch in XZ plane)\n mat3 stretchRot = mat3(\n cs, 0.0, -sn,\n 0.0, 1.0, 0.0,\n sn, 0.0, cs\n );\n mat3 stretchRotInv = mat3(\n cs, 0.0, sn,\n 0.0, 1.0, 0.0,\n -sn, 0.0, cs\n );\n\n // Transform ray into ellipsoid-aligned space\n vec3 rotatedRayDir = stretchRotInv * rayDir;\n vec3 rotatedRayOrigin = stretchRotInv * rayOrigin;\n\n // Calculate ellipsoid semi-axes based on stretch\n // Use dynamic base radius passed from JS (scales with render texture size)\n // Falls back to 0.4 if uniform not set\n float baseRadius = uBaseRadius > 0.0 ? uBaseRadius : 0.4;\n vec3 semiAxes = tidalSemiAxes(stretch, stretchDir2D, baseRadius, uTidalWobble, time);\n\n // Ray-ellipsoid intersection for SURFACE\n float t = rayEllipsoidIntersect(rotatedRayOrigin, rotatedRayDir, vec3(0.0), semiAxes);\n\n // === NO CORONA - just render solid ellipsoid ===\n // If ray doesn't hit the surface, render transparent\n if (t < 0.0) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n // === SURFACE RENDERING ===\n // Calculate hit point in rotated (ellipsoid-aligned) space\n vec3 rotatedHitPoint = rotatedRayOrigin + rotatedRayDir * t;\n\n // Calculate ellipsoid normal (gradient of implicit surface)\n vec3 rotatedNormalRaw = ellipsoidNormal(rotatedHitPoint, vec3(0.0), semiAxes);\n\n // Transform hit point and normal back to world space\n vec3 hitPoint = stretchRot * rotatedHitPoint;\n vec3 normal = normalize(stretchRot * rotatedNormalRaw);\n\n // Apply inverse camera rotation to the normal (camera orbit)\n mat3 camRotMat = rotationMatrix(-uCameraRotation);\n vec3 rotatedNormal = camRotMat * normal;\n\n // Apply self-rotation to surface features\n rotatedNormal = rotateY(rotatedNormal, selfRotation);\n\n // === SPHERICAL DISTORTION for boiling effect ===\n vec2 sp = normal.xy;\n float r = dot(sp, sp);\n\n float brightness = 0.15 + (uTemperature / 10000.0) * 0.1;\n float distortStrength = 2.0 - brightness;\n\n vec2 warpedUV;\n if (r < 0.0001) {\n // At pole - use alternative coords\n float poleAngle = atan(rotatedNormal.y, rotatedNormal.x) + time * 0.15;\n float poleElev = acos(clamp(rotatedNormal.z, -1.0, 1.0));\n warpedUV = vec2(cos(poleAngle), sin(poleAngle)) * (poleElev / 3.14159) * distortStrength;\n } else {\n sp *= distortStrength;\n r = dot(sp, sp);\n float f = (1.0 - sqrt(abs(1.0 - r))) / (r + 0.001) + brightness * 0.5;\n warpedUV = sp * f + vec2(time * 0.05, 0.0);\n }\n\n // === PLASMA TEXTURE ===\n vec3 plasmaCoord = vec3(warpedUV * 3.0, time * 0.12);\n float plasma1 = plasmaNoise(plasmaCoord, time);\n float plasma2 = plasmaNoise(plasmaCoord * 1.3 + vec3(50.0), time * 1.2);\n float plasma = plasma1 * 0.6 + plasma2 * 0.4;\n plasma = plasma * 0.5 + 0.5;\n\n // === VIEW GEOMETRY ===\n float viewAngle = dot(normal, -rayDir);\n float edgeDist = 1.0 - viewAngle;\n float limbDarkening = pow(max(0.0, viewAngle), 0.4);\n\n // === TIDAL FACE INTENSITY ===\n // The side facing the black hole experiences more violent tidal forces\n // Calculate how much this surface point faces the BH direction\n vec3 bhDir3D = normalize(vec3(uStretchDirX, 0.0, uStretchDirZ));\n float facingBH = dot(normal, bhDir3D); // -1 to 1, positive = facing BH\n float tidalFace = smoothstep(-0.2, 0.8, facingBH); // Gradual transition\n tidalFace = tidalFace * tidalFace; // More concentrated on BH side\n \n // Tidal face boost - up to 3x more violent on the BH-facing side\n float tidalFaceBoost = 1.0 + tidalFace * uStressLevel * 2.0;\n\n // === MULTI-LAYER EFFECTS (stress-enhanced) ===\n // Stress amplifies all turbulent effects - star is being torn apart!\n // Much more violent - up to 5x chaos at max stress\n float stressBoost = 1.0 + uStressLevel * 4.0;\n \n // Combined boost: general stress + extra violence on BH-facing side\n float combinedBoost = stressBoost * tidalFaceBoost;\n\n float turbIntensity = boilingTurbulence(rotatedNormal, time * combinedBoost) * 0.6;\n turbIntensity *= combinedBoost;\n\n float bubbles = hotBubbles(rotatedNormal, time * combinedBoost);\n bubbles *= combinedBoost * 1.5; // More dramatic bubbles on tidal face\n\n // Granulation becomes violent under stress - larger and faster\n float gran = noise3D(rotatedNormal * 15.0 + time * 0.5 * combinedBoost);\n gran *= combinedBoost * 1.2;\n\n // === TIDAL FRACTURING ===\n // Stress causes visible cracks/tears - concentrated on BH-facing side\n float fractures = 0.0;\n if (uStressLevel > 0.15) { // Start fractures earlier (was 0.3)\n // Fractures are more intense on the tidal face\n float fractureBoost = 1.0 + tidalFace * 2.0; // Up to 3x on BH side\n float fractureNoise = noise3D(rotatedNormal * 6.0 + time * 0.8 * fractureBoost);\n float fractureThreshold = 1.0 - (uStressLevel - 0.15) * 1.2 * fractureBoost;\n fractures = smoothstep(fractureThreshold, fractureThreshold + 0.08, fractureNoise);\n fractures *= uStressLevel * 1.2 * fractureBoost; // More intense on BH side\n }\n\n // === PULSATION (amplified by stress) ===\n float pulse1 = cos(time * 0.5) * 0.5;\n float pulse2 = sin(time * 0.25) * 0.5;\n float pulseAmp = uActivityLevel * (1.0 + uStressLevel);\n float pulse = (pulse1 + pulse2) * 0.3 * pulseAmp;\n\n // === TIDAL HOTSPOT ===\n // Bright glowing region on the BH-facing side - like matter being pulled off\n float tidalHotspot = pow(tidalFace, 3.0) * uStressLevel;\n // Add some flickering/chaos to the hotspot\n tidalHotspot *= 0.7 + 0.3 * noise3D(rotatedNormal * 8.0 + time * 2.0);\n\n // === COMBINED INTENSITY ===\n float totalIntensity = plasma * 0.35 + turbIntensity * 0.25 + gran * 0.2;\n totalIntensity += bubbles * 0.4;\n totalIntensity += fractures * 0.5; // Fractures glow hot\n totalIntensity += tidalHotspot * 0.8; // Bright tidal hotspot\n totalIntensity *= 1.0 + pulse;\n\n // === 4-TIER COLOR SYSTEM ===\n vec3 baseColor = uStarColor;\n float maxComp = max(baseColor.r, max(baseColor.g, baseColor.b));\n if (maxComp > 0.01) baseColor = baseColor / maxComp * 0.85;\n\n // Temperature-based color blending\n float tempBlend = smoothstep(5000.0, 7500.0, uTemperature);\n\n vec3 hotColor = baseColor * vec3(1.6, 1.35, 1.2);\n vec3 coolColor = mix(baseColor * vec3(0.5, 0.3, 0.2), baseColor * vec3(0.7, 0.8, 0.95), tempBlend);\n vec3 warmColor = mix(baseColor * vec3(1.2, 1.0, 0.85), baseColor * vec3(1.0, 1.05, 1.2), tempBlend);\n vec3 blazingColor = mix(baseColor * vec3(2.0, 1.6, 1.3), baseColor * vec3(1.4, 1.5, 1.8), tempBlend);\n\n // Map intensity to color\n vec3 surfaceColor;\n if (totalIntensity < 0.35) {\n surfaceColor = mix(coolColor, warmColor, totalIntensity / 0.35);\n } else if (totalIntensity < 0.65) {\n surfaceColor = mix(warmColor, hotColor, (totalIntensity - 0.35) / 0.3);\n } else if (totalIntensity < 1.0) {\n surfaceColor = mix(hotColor, blazingColor, (totalIntensity - 0.65) / 0.35);\n } else {\n surfaceColor = blazingColor * (1.0 + (totalIntensity - 1.0) * 0.8);\n }\n\n // Bubble highlights\n float bubbleHighlight = pow(bubbles, 1.5) * turbIntensity;\n surfaceColor += blazingColor * bubbleHighlight * 0.6;\n\n // === LIMB DARKENING ===\n surfaceColor *= 0.75 + limbDarkening * 0.25;\n\n // === ORGANIC RIM GLOW ===\n float rimAngle = atan(normal.y, normal.x) + selfRotation;\n float rimNoise = noise3D(vec3(rimAngle * 3.0, edgeDist * 2.0, time * 0.2));\n rimNoise = rimNoise * 0.5 + 0.5;\n\n float rimIntensity = pow(edgeDist, 2.0) * (0.4 + rimNoise * 0.6);\n vec3 rimColor = baseColor * vec3(1.3, 0.95, 0.6);\n surfaceColor += rimColor * rimIntensity * 0.6 * uActivityLevel;\n\n // === EDGE GLOW (corona bleeding into surface) ===\n float edgeGlow = pow(edgeDist, 0.5) * 0.3 * uActivityLevel;\n surfaceColor += warmColor * edgeGlow;\n\n // === CENTER BOOST ===\n float centerBoost = pow(viewAngle, 1.5) * 0.2;\n surfaceColor += baseColor * centerBoost;\n\n // === SHIMMER ===\n float shimmer = sin(turbIntensity * 10.0 + time * 3.0) * 0.05 + 1.0;\n surfaceColor *= shimmer;\n\n // === TIDAL FLARE ===\n // Sudden brightness burst when disruption begins\n // Concentrated on the BH-facing side with violent flickering\n if (uTidalFlare > 0.01) {\n // Flare is brightest on the BH-facing side\n float flareFace = 0.3 + tidalFace * 0.7;\n \n // Violent flickering during the flare\n float flareFlicker = 0.7 + 0.3 * noise3D(rotatedNormal * 10.0 + time * 8.0);\n \n // White-hot flare color\n vec3 flareColor = vec3(1.0, 0.95, 0.8);\n \n // Additive flare - makes entire star brighter\n float flareIntensity = uTidalFlare * flareFace * flareFlicker * 2.0;\n surfaceColor += flareColor * flareIntensity;\n \n // Extra bloom at the BH-facing tip\n float tipFlare = pow(tidalFace, 4.0) * uTidalFlare * 1.5;\n surfaceColor += vec3(1.0, 0.9, 0.7) * tipFlare;\n }\n\n surfaceColor = clamp(surfaceColor, 0.0, 3.5); // Allow brighter for flare\n\n gl_FragColor = vec4(surfaceColor, 1.0);\n}\n`,blackHole:`\n${ri}\n\nuniform float uAwakeningLevel; // 0 = dormant, 1 = fully active\nuniform float uFeedingPulse; // Temporary glow from feeding\nuniform float uRotation; // Black hole spin angle (Kerr rotation)\n\nvoid main() {\n vec2 uv = vUv;\n vec2 center = uv - 0.5;\n float dist = length(center) * 2.0; // 0 at center, 1 at edge\n float angle = atan(center.y, center.x);\n\n float time = uTime;\n float awakeFactor = uAwakeningLevel;\n float pulseFactor = uFeedingPulse;\n\n // Spin angle for rotating effects (frame dragging)\n // Using uTime since custom uniforms don't update properly\n float spinAngle = angle + uTime * 4.0; // Faster spin\n\n // === RADII (normalized to quad size) ===\n float eventHorizon = 0.42; // Slightly larger core\n float photonSphere = 0.54; // Tighten ring closer to horizon\n float shadowEdge = 0.5; // Shadow boundary\n\n // === CIRCULAR MASK ===\n if (dist > 1.5) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n // === NO INTERNAL STARFIELD ===\n // The real starfield is rendered separately in the scene\n // This shader just renders the dark void + subtle edge effects\n // True gravitational lensing would require render-to-texture of background\n\n // === EVENT HORIZON - Gradient from pure black to very dark edge ===\n // Edge color ~#110b06 = RGB(17,11,6) = vec3(0.067, 0.043, 0.024)\n if (dist < shadowEdge) {\n // Use shadowEdge (0.52) as outer boundary for smooth transition to ring\n float edgeT = dist / shadowEdge; // 0 at center, 1 at shadow edge\n\n // Very steep curve - stays pure black until very close to edge\n float glowFactor = pow(edgeT, 8.0);\n\n // Very dark brownish-black - NO yellow, matches #110b06\n vec3 edgeColor = vec3(0.067, 0.043, 0.024) * glowFactor;\n\n gl_FragColor = vec4(edgeColor, 1.0);\n return;\n }\n\n // === PHOTON SPHERE - Subtle ring with gentler spin asymmetry ===\n float photonRingWidth = 0.035;\n float photonDist = abs(dist - photonSphere);\n float photonRing = exp(-photonDist * photonDist / (photonRingWidth * photonRingWidth));\n\n // Softer Doppler asymmetry to avoid pointy highlights\n float doppler = 0.78 + 0.22 * cos(spinAngle); // narrower asymmetry\n photonRing *= 0.18 + doppler * 0.38; // 18%..56% brightness\n\n // Soft tip highlight to indicate spin without a spike\n float tipAlign = max(0.0, cos(spinAngle));\n float tipRadial = smoothstep(photonRingWidth * 1.2, 0.0, photonDist);\n float hotSpotGlow = tipAlign * tipAlign * tipRadial * 0.25;\n\n // Scale with awakening - more visible when feeding\n photonRing *= 0.15 + awakeFactor * 0.35;\n\n // === FEEDING PULSE - Subtle ripple when consuming ===\n float pulseRipple = 0.0;\n if (pulseFactor > 0.01) {\n float ripplePhase = fract(time * 1.5) * 0.3;\n float rippleRadius = shadowEdge + ripplePhase;\n float ripple = exp(-pow(dist - rippleRadius, 2.0) * 80.0);\n pulseRipple = ripple * pulseFactor * 0.15; // Subtle\n }\n\n // === EDGE GLOW - keep subtle; avoid wide smear\n float edgeGlow = 0.0;\n if (dist > shadowEdge && dist < photonSphere + 0.08) {\n float edgeFactor = smoothstep(shadowEdge, photonSphere, dist);\n edgeFactor *= smoothstep(photonSphere + 0.08, photonSphere, dist);\n edgeGlow = edgeFactor * pulseFactor * 0.06;\n }\n\n // === COMBINE EFFECTS ===\n vec3 color = vec3(0.0);\n\n // Photon sphere ring (warm orange-yellow)\n vec3 photonColor = vec3(1.0, 0.8, 0.45);\n color += photonColor * photonRing;\n\n // Soft tip highlight (spin indicator)\n vec3 hotSpotColor = vec3(1.0, 0.9, 0.65);\n color += hotSpotColor * hotSpotGlow;\n\n // Edge glow when feeding\n vec3 glowColor = vec3(1.0, 0.5, 0.2);\n color += glowColor * edgeGlow;\n\n // Feeding pulse ripple\n vec3 pulseColor = vec3(1.0, 0.6, 0.3);\n color += pulseColor * pulseRipple;\n\n // === OUTER FADE ===\n float outerFade = 1.0 - smoothstep(0.9, 1.25, dist);\n color *= outerFade;\n\n // === ALPHA ===\n // Event horizon and photon sphere are fully opaque to occlude background\n float alpha;\n if (dist < photonSphere) {\n alpha = 1.0;\n color = (dist < shadowEdge) ? vec3(0.0) : color; // keep core solid black\n } else {\n // Alpha based on visible content\n float contentBrightness = max(max(color.r, color.g), color.b);\n alpha = smoothstep(0.01, 0.06, contentBrightness);\n alpha = max(alpha, smoothstep(photonSphere + 0.12, shadowEdge, dist) * 0.25);\n alpha *= outerFade;\n }\n\n gl_FragColor = vec4(color, alpha);\n}\n`,rockyPlanet:`\n${ri}\n\nuniform vec3 uBaseColor;\nuniform float uHasAtmosphere; // 0-1\nuniform float uSeed;\n\nvoid main() {\n // Setup ray - camera looking at sphere from fixed position\n vec3 rayOrigin = vec3(0.0, 0.0, -2.5);\n vec3 rayDir = getRayDirection(vUv);\n\n // Ray-sphere intersection (sphere at origin with radius 0.5)\n float t = raySphereIntersect(rayOrigin, rayDir, vec3(0.0), 0.5);\n\n if (t < 0.0) {\n // Atmosphere halo\n if (uHasAtmosphere > 0.0) {\n vec2 center = vUv - 0.5;\n float dist = length(center) * 2.0;\n float atmo = smoothstep(0.6, 0.5, dist) * smoothstep(0.45, 0.52, dist);\n atmo *= uHasAtmosphere * 0.4;\n vec3 atmoColor = vec3(0.5, 0.7, 1.0) * atmo;\n // Premultiplied alpha\n gl_FragColor = vec4(atmoColor * atmo, atmo);\n } else {\n gl_FragColor = vec4(0.0);\n }\n return;\n }\n\n // Calculate hit point and normal\n vec3 hitPoint = rayOrigin + rayDir * t;\n vec3 normal = normalize(hitPoint);\n\n // Apply inverse camera rotation for surface features\n mat3 rotMat = rotationMatrix(-uCameraRotation);\n vec3 rotatedNormal = rotMat * normal;\n\n // Seeded noise for consistent terrain\n vec3 noiseCoord = rotatedNormal * 4.0 + uSeed * 100.0;\n float terrain = fbm(noiseCoord, 5);\n\n // Height-based coloring\n vec3 lowColor = uBaseColor * 0.6; // Valleys/lowlands\n vec3 highColor = uBaseColor * 1.2; // Mountains/highlands\n vec3 surfaceColor = mix(lowColor, highColor, terrain);\n\n // Add some variation\n float variation = noise3D(rotatedNormal * 10.0 + uSeed * 50.0);\n surfaceColor *= 0.9 + variation * 0.2;\n\n // Lighting\n vec3 lightDir = normalize(vec3(1.0, 1.0, 0.5));\n float light = lighting(normal, lightDir, 0.3);\n surfaceColor *= light;\n\n // Atmosphere scattering at edges\n if (uHasAtmosphere > 0.0) {\n float rim = fresnel(normal, -rayDir, 3.0);\n vec3 atmoColor = vec3(0.5, 0.7, 1.0);\n surfaceColor = mix(surfaceColor, atmoColor, rim * uHasAtmosphere * 0.4);\n }\n\n gl_FragColor = vec4(surfaceColor, 1.0);\n}\n`,gasGiant:`\n${ri}\n\nuniform vec3 uBaseColor;\nuniform float uSeed;\nuniform float uStormIntensity; // 0-1\nuniform float uRotationSpeed; // rotation speed multiplier (default ~0.1)\n\nvoid main() {\n // Setup ray - camera looking at sphere from fixed position\n vec3 rayOrigin = vec3(0.0, 0.0, -2.5);\n vec3 rayDir = getRayDirection(vUv);\n\n // Ray-sphere intersection (sphere at origin with radius 0.5)\n float t = raySphereIntersect(rayOrigin, rayDir, vec3(0.0), 0.5);\n\n if (t < 0.0) {\n gl_FragColor = vec4(0.0);\n return;\n }\n\n // Calculate hit point and normal\n vec3 hitPoint = rayOrigin + rayDir * t;\n vec3 normal = normalize(hitPoint);\n\n // Apply inverse camera rotation for surface features\n mat3 rotMat = rotationMatrix(-uCameraRotation);\n vec3 rotatedNormal = rotMat * normal;\n\n // Convert to spherical coordinates for banding (use rotated normal)\n float latitude = asin(rotatedNormal.y); // -PI/2 to PI/2\n float longitude = atan(rotatedNormal.z, rotatedNormal.x); // -PI to PI\n\n // Animated rotation (use uRotationSpeed, default to 0.1 if not set)\n float rotSpeed = uRotationSpeed > 0.0 ? uRotationSpeed : 0.1;\n float time = uTime * rotSpeed;\n\n // Create bands based on latitude\n float bands = sin(latitude * 15.0 + time) * 0.5 + 0.5;\n bands += sin(latitude * 25.0 - time * 0.5) * 0.25;\n bands += sin(latitude * 40.0 + time * 0.3) * 0.125;\n\n // Turbulent distortion of bands\n vec3 noiseCoord = vec3(longitude + time * 0.2, latitude * 3.0, uSeed);\n float turb = fbm(noiseCoord * 5.0, 4) * 0.3;\n bands += turb;\n\n // Color variation based on bands\n vec3 lightBand = uBaseColor * 1.3;\n vec3 darkBand = uBaseColor * 0.7;\n vec3 surfaceColor = mix(darkBand, lightBand, bands);\n\n // Add storm features\n if (uStormIntensity > 0.0) {\n // Great red spot style storm\n float stormLat = 0.3; // Storm latitude\n float stormLon = time * 0.5; // Storm drifts\n vec2 stormCenter = vec2(stormLon, stormLat);\n vec2 pos = vec2(longitude, latitude);\n float stormDist = length(pos - stormCenter);\n float storm = smoothstep(0.5, 0.2, stormDist);\n storm *= uStormIntensity;\n\n // Storm color and swirl\n vec3 stormColor = vec3(0.8, 0.3, 0.2);\n float swirl = sin(stormDist * 20.0 - time * 3.0) * 0.5 + 0.5;\n surfaceColor = mix(surfaceColor, stormColor * swirl, storm);\n }\n\n // Lighting with some subsurface scattering effect\n vec3 lightDir = normalize(vec3(1.0, 0.5, 0.3));\n float light = lighting(normal, lightDir, 0.4);\n surfaceColor *= light;\n\n // Limb darkening\n float viewAngle = dot(normal, -rayDir);\n surfaceColor *= 0.7 + max(0.0, viewAngle) * 0.3;\n\n gl_FragColor = vec4(surfaceColor, 1.0);\n}\n`},hi=class t extends Ze{static _getGLRenderer(e,i){return t._glRenderer?t._glRendererSize.width===e&&t._glRendererSize.height===i||(t._glRenderer.resize(e,i),t._glRendererSize={width:e,height:i}):(t._glRenderer=new oi(e,i),t._glRendererSize={width:e,height:i}),t._glRenderer}constructor(t,e={}){super(e),this.radius=t,this.camera=e.camera??null,this.debug=e.debug??!1,this.segments=e.segments??20,this.useShader=e.useShader??!1,this.shaderType=e.shaderType??"star",this.shaderUniforms=e.shaderUniforms??{},this._shaderInitialized=!1,this.selfRotationX=e.selfRotationX??0,this.selfRotationY=e.selfRotationY??0,this.selfRotationZ=e.selfRotationZ??0,this._generateGeometry()}setCamera(t){return this.camera=t,this}setShaderUniforms(t){return Object.assign(this.shaderUniforms,t),this}_getFragmentShader(){switch(this.shaderType){case"star":default:return ai.star;case"blackHole":return ai.blackHole;case"rockyPlanet":return ai.rockyPlanet;case"gasGiant":return ai.gasGiant}}_initShader(e,i){const s=t._getGLRenderer(e,i);if(!s||!s.isAvailable())return void(this.useShader=!1);const n=`sphere_${this.shaderType}`;s.useProgram(n,ai.vertex,this._getFragmentShader()),this._shaderInitialized=!0}_renderWithShader(e,i,s,n){var o,r,a,h;const l=n*(1+((null==(o=this.shaderUniforms)?void 0:o.uTidalStretch)??0)),c=Math.ceil(2*(n+l)),u=t._getGLRenderer(c,c);if(!u||!u.isAvailable())return!1;this._shaderInitialized||this._initShader(c,c);const d=`sphere_${this.shaderType}`;u.useProgram(d,ai.vertex,this._getFragmentShader()),u.clear(0,0,0,0);const f=1.25*n/(c/2);u.setUniforms({uTime:performance.now()/1e3,uResolution:[c,c],uBaseRadius:f,uCameraRotation:[(null==(r=this.camera)?void 0:r.rotationX)??0,(null==(a=this.camera)?void 0:a.rotationY)??0,(null==(h=this.camera)?void 0:h.rotationZ)??0]}),u.setUniforms(this.shaderUniforms);for(const[t,e]of Object.entries(this.shaderUniforms))"string"==typeof e&&e.startsWith("#")&&u.setColorUniform(t,e);u.render();const p=i-c/2,g=s-c/2;return u.compositeOnto(e,p,g,c,c),!0}_generateGeometry(){this.vertices=[],this.faces=[];const t=this.segments,e=2*this.segments;for(let i=0;i<=t;i++){const s=i*Math.PI/t,n=Math.sin(s),o=Math.cos(s);for(let t=0;t<=e;t++){const i=2*t*Math.PI/e,s=Math.sin(i),r=Math.cos(i),a=this.radius*n*r,h=this.radius*o,l=this.radius*n*s;this.vertices.push({x:a,y:h,z:l,nx:n*r,ny:o,nz:n*s})}}for(let i=0;i<t;i++)for(let t=0;t<e;t++){const s=i*(e+1)+t,n=s+e+1;this.faces.push([s,n,s+1]),this.faces.push([n,n+1,s+1])}}_applySelfRotation(t,e,i){if(0!==this.selfRotationY){const e=Math.cos(this.selfRotationY),s=Math.sin(this.selfRotationY),n=t*s+i*e;t=t*e-i*s,i=n}if(0!==this.selfRotationX){const t=Math.cos(this.selfRotationX),s=Math.sin(this.selfRotationX),n=e*s+i*t;e=e*t-i*s,i=n}if(0!==this.selfRotationZ){const i=Math.cos(this.selfRotationZ),s=Math.sin(this.selfRotationZ),n=t*s+e*i;t=t*i-e*s,e=n}return{x:t,y:e,z:i}}_calculateLighting(t,e,i){const s=Math.sqrt(.99);let n=t*(.5/s)+e*(.7/s)+i*(.5/s);return n=.7*Math.max(0,n)+.3,n}_applyLighting(t,e){if(!t||"string"!=typeof t||!t.startsWith("#"))return t;const i=t.replace("#",""),s=parseInt(i.substring(0,2),16),n=parseInt(i.substring(2,4),16),o=parseInt(i.substring(4,6),16);return`rgb(${Math.round(s*e)}, ${Math.round(n*e)}, ${Math.round(o*e)})`}draw(){if(super.draw(),!this.camera)return this.color&&Le.shapes.fillCircle(0,0,this.radius,this.color),void(this.debug&&this.stroke&&Le.shapes.strokeCircle(0,0,this.radius,this.stroke,this.lineWidth));if(this.useShader&&!this.debug){const t=this.camera.project(this.x||0,this.y||0,this.z||0),e=this.camera.perspective/(this.camera.perspective+t.z),i=this.radius*e,s=Le.ctx,n=s.getTransform(),o=n.e,r=n.f;s.save(),s.setTransform(1,0,0,1,0,0);const a=this._renderWithShader(s,o+t.x,r+t.y,i);if(s.restore(),a)return}const t=0!==this.selfRotationX||0!==this.selfRotationY||0!==this.selfRotationZ,e=this.vertices.map(e=>{let i=e.x,s=e.y,n=e.z,o=e.nx,r=e.ny,a=e.nz;if(t){const t=this._applySelfRotation(i,s,n);i=t.x,s=t.y,n=t.z;const e=this._applySelfRotation(o,r,a);o=e.x,r=e.y,a=e.z}const h=this.camera.project(i+(this.x||0),s+(this.y||0),n+(this.z||0));if(0!==this.camera.rotationZ){const t=Math.cos(this.camera.rotationZ),e=Math.sin(this.camera.rotationZ),i=o;o=i*t-r*e,r=i*e+r*t}const l=Math.cos(this.camera.rotationY),c=Math.sin(this.camera.rotationY),u=o*l-a*c,d=o*c+a*l,f=Math.cos(this.camera.rotationX),p=Math.sin(this.camera.rotationX);return{...h,nx:u,ny:r*f-d*p,nz:r*p+d*f}});this.debug&&this.trace("Sphere3D.draw: projected vertices",e.length);const i=[];for(const t of this.faces){const s=e[t[0]],n=e[t[1]],o=e[t[2]];if(s.z<10-this.camera.perspective||n.z<10-this.camera.perspective||o.z<10-this.camera.perspective)continue;const r=(s.z+n.z+o.z)/3,a=(s.nx+n.nx+o.nx)/3,h=(s.ny+n.ny+o.ny)/3,l=(s.nz+n.nz+o.nz)/3;if(l>.1)continue;const c=this._calculateLighting(a,h,l);i.push({vertices:[s,n,o],avgZ:r,intensity:c})}i.sort((t,e)=>e.avgZ-t.avgZ);for(const t of i){const e=t.vertices.map(t=>({x:t.x,y:t.y}));if(this.debug)Le.ctx.beginPath(),Le.ctx.moveTo(e[0].x,e[0].y),Le.ctx.lineTo(e[1].x,e[1].y),Le.ctx.lineTo(e[2].x,e[2].y),Le.ctx.closePath(),this.stroke&&(Le.ctx.strokeStyle=this.stroke,Le.ctx.lineWidth=this.lineWidth??1,Le.ctx.stroke());else if(this.color){const i=this._applyLighting(this.color,t.intensity);Le.ctx.beginPath(),Le.ctx.moveTo(e[0].x,e[0].y),Le.ctx.lineTo(e[1].x,e[1].y),Le.ctx.lineTo(e[2].x,e[2].y),Le.ctx.closePath(),Le.ctx.fillStyle=i,Le.ctx.fill()}}}calculateBounds(){const t=2*this.radius;return{x:this.x,y:this.y,width:t,height:t}}};_t(hi,"_glRenderer",null),_t(hi,"_glRendererSize",{width:0,height:0});let li=hi;const ci="\nprecision highp float;\n\nvarying vec2 vUv;\n\nuniform float uTime;\nuniform vec2 uResolution;\n\n// =============================================================================\n// NOISE FUNCTIONS\n// =============================================================================\n\nfloat hash(float n) {\n return fract(sin(n) * 43758.5453123);\n}\n\nfloat hash2(vec2 p) {\n return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);\n}\n\n// 2D Value noise\nfloat noise2D(vec2 x) {\n vec2 i = floor(x);\n vec2 f = fract(x);\n f = f * f * (3.0 - 2.0 * f);\n\n float a = hash2(i);\n float b = hash2(i + vec2(1.0, 0.0));\n float c = hash2(i + vec2(0.0, 1.0));\n float d = hash2(i + vec2(1.0, 1.0));\n\n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\n\n// FBM (Fractional Brownian Motion)\nfloat fbm2D(vec2 p, int octaves) {\n float value = 0.0;\n float amplitude = 0.5;\n float frequency = 1.0;\n\n for (int i = 0; i < 8; i++) {\n if (i >= octaves) break;\n value += amplitude * noise2D(p * frequency);\n frequency *= 2.0;\n amplitude *= 0.5;\n }\n\n return value;\n}\n",ui={vertex:"\nprecision highp float;\n\nattribute vec2 aPosition;\nattribute vec2 aUv;\n\nvarying vec2 vUv;\n\nvoid main() {\n vUv = aUv;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n",gradient:`\n${ci}\n\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uAngle;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Calculate gradient direction from angle\n vec2 dir = vec2(cos(uAngle), sin(uAngle));\n\n // Project UV onto gradient direction\n // Center at 0.5 so gradient goes through middle\n float t = dot(uv - 0.5, dir) + 0.5;\n t = clamp(t, 0.0, 1.0);\n\n // Interpolate colors\n vec3 color = mix(uColor1, uColor2, t);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`,grid:`\n${ci}\n\nuniform vec3 uLineColor;\nuniform vec3 uBackgroundColor;\nuniform float uGridSize;\nuniform float uLineWidth;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Scale UV to grid space\n vec2 grid = fract(uv * uGridSize);\n\n // Calculate distance to nearest grid line\n float lineX = min(grid.x, 1.0 - grid.x);\n float lineY = min(grid.y, 1.0 - grid.y);\n\n // Smoothstep for anti-aliased lines\n float halfWidth = uLineWidth * 0.5;\n float edgeSmooth = 0.01;\n\n float lineAlphaX = 1.0 - smoothstep(halfWidth - edgeSmooth, halfWidth + edgeSmooth, lineX);\n float lineAlphaY = 1.0 - smoothstep(halfWidth - edgeSmooth, halfWidth + edgeSmooth, lineY);\n float lineAlpha = max(lineAlphaX, lineAlphaY);\n\n // Mix colors\n vec3 color = mix(uBackgroundColor, uLineColor, lineAlpha);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`,checkerboard:`\n${ci}\n\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uSize;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Calculate which square we're in\n vec2 cell = floor(uv * uSize);\n\n // Alternating pattern based on cell coordinates\n float checker = mod(cell.x + cell.y, 2.0);\n\n // Select color\n vec3 color = mix(uColor1, uColor2, checker);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`,noise:`\n${ci}\n\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uNoiseScale;\nuniform float uAnimSpeed;\n\nvoid main() {\n vec2 uv = vUv;\n\n // Animated noise\n float n = fbm2D(uv * uNoiseScale + uTime * uAnimSpeed, 4);\n\n // Map noise to colors\n vec3 color = mix(uColor1, uColor2, n);\n\n gl_FragColor = vec4(color, 1.0);\n}\n`},di=class t extends Ze{static _getGLRenderer(e,i){return t._glRenderer?t._glRendererSize.width===e&&t._glRendererSize.height===i||(t._glRenderer.resize(e,i),t._glRendererSize={width:e,height:i}):(t._glRenderer=new oi(e,i),t._glRendererSize={width:e,height:i}),t._glRenderer}constructor(t,e,i={}){super(i),this.planeWidth=t,this.planeHeight=e,this.x=i.x??0,this.y=i.y??0,this.z=i.z??0,this.camera=i.camera??null,this.debug=i.debug??!1,this.doubleSided=i.doubleSided??!0,this.texture=i.texture??null,this.selfRotationX=i.selfRotationX??0,this.selfRotationY=i.selfRotationY??0,this.selfRotationZ=i.selfRotationZ??0,this.useShader=i.useShader??!1,this.shaderType=i.shaderType??"gradient",this.shaderUniforms=i.shaderUniforms??{},this._shaderInitialized=!1,this._generateGeometry()}setCamera(t){return this.camera=t,this}setTexture(t){return this.texture=t,this}setShaderUniforms(t){return Object.assign(this.shaderUniforms,t),this}_generateGeometry(){const t=this.planeWidth/2,e=this.planeHeight/2;this.vertices=[{x:-t,y:-e,z:0,nx:0,ny:0,nz:-1,u:0,v:0},{x:t,y:-e,z:0,nx:0,ny:0,nz:-1,u:1,v:0},{x:t,y:e,z:0,nx:0,ny:0,nz:-1,u:1,v:1},{x:-t,y:e,z:0,nx:0,ny:0,nz:-1,u:0,v:1}],this.faces=[[0,1,2],[0,2,3]]}_getFragmentShader(){switch(this.shaderType){case"gradient":default:return ui.gradient;case"grid":return ui.grid;case"checkerboard":return ui.checkerboard;case"noise":return ui.noise}}_initShader(e,i){const s=t._getGLRenderer(e,i);if(!s||!s.isAvailable())return!1;const n=`plane_${this.shaderType}`,o=ui.vertex,r=this._getFragmentShader();try{return s.useProgram(n,o,r),this._shaderInitialized=!0,!0}catch(t){return console.warn("Plane3D shader init failed:",t),!1}}_renderWithShader(e,i,s,n,o){const r=Math.max(Math.ceil(Math.max(n,o)),16);if(!this._shaderInitialized&&!this._initShader(r,r))return!1;const a=t._getGLRenderer(r,r);if(!a||!a.isAvailable())return!1;const h=`plane_${this.shaderType}`;a.useProgram(h,ui.vertex,this._getFragmentShader());const l=performance.now()/1e3;a.setUniforms({uTime:l,uResolution:[r,r]}),a.setUniforms(this.shaderUniforms),a.render();const c=i-n/2,u=s-o/2;return a.compositeOnto(e,c,u,n,o),!0}_applySelfRotation(t,e,i){if(0!==this.selfRotationY){const e=Math.cos(this.selfRotationY),s=Math.sin(this.selfRotationY),n=t*s+i*e;t=t*e-i*s,i=n}if(0!==this.selfRotationX){const t=Math.cos(this.selfRotationX),s=Math.sin(this.selfRotationX),n=e*s+i*t;e=e*t-i*s,i=n}if(0!==this.selfRotationZ){const i=Math.cos(this.selfRotationZ),s=Math.sin(this.selfRotationZ),n=t*s+e*i;t=t*i-e*s,e=n}return{x:t,y:e,z:i}}_calculateLighting(t,e,i){const s=Math.sqrt(.99);let n=t*(.5/s)+e*(.7/s)+i*(.5/s);return n=.7*Math.max(0,n)+.3,n}_applyLighting(t,e){if(!t||"string"!=typeof t||!t.startsWith("#"))return t;const i=t.replace("#",""),s=parseInt(i.substring(0,2),16),n=parseInt(i.substring(2,4),16),o=parseInt(i.substring(4,6),16);return`rgb(${Math.round(s*e)}, ${Math.round(n*e)}, ${Math.round(o*e)})`}draw(){if(super.draw(),!this.camera)return void(this.color&&Le.shapes.fillRect(-this.planeWidth/2,-this.planeHeight/2,this.planeWidth,this.planeHeight,this.color));const t=0!==this.selfRotationX||0!==this.selfRotationY||0!==this.selfRotationZ,e=this.vertices.map(e=>{let i=e.x,s=e.y,n=e.z,o=e.nx,r=e.ny,a=e.nz;if(t){const t=this._applySelfRotation(i,s,n);i=t.x,s=t.y,n=t.z;const e=this._applySelfRotation(o,r,a);o=e.x,r=e.y,a=e.z}const h=this.camera.project(i+this.x,s+this.y,n+this.z);if(0!==this.camera.rotationZ){const t=Math.cos(this.camera.rotationZ),e=Math.sin(this.camera.rotationZ),i=o;o=i*t-r*e,r=i*e+r*t}const l=Math.cos(this.camera.rotationY),c=Math.sin(this.camera.rotationY),u=o*l-a*c,d=o*c+a*l,f=Math.cos(this.camera.rotationX),p=Math.sin(this.camera.rotationX);return{...h,nx:u,ny:r*f-d*p,nz:r*p+d*f,u:e.u,v:e.v}}),i=(e[0].nz+e[1].nz+e[2].nz+e[3].nz)/4;if(!this.doubleSided&&i>.1)return;if(e[0].z,e[1].z,e[2].z,e[3].z,e.some(t=>t.z<10-this.camera.perspective))return;if(this.useShader&&!this.debug){const t=e.map(t=>t.x),i=e.map(t=>t.y),s=Math.min(...t),n=Math.max(...t),o=Math.min(...i),r=Math.max(...i),a=n-s,h=r-o,l=(s+n)/2,c=(o+r)/2,u=Le.ctx,d=u.getTransform(),f=d.e,p=d.f;u.save(),u.setTransform(1,0,0,1,0,0);const g=this._renderWithShader(u,f+l,p+c,a,h);if(u.restore(),g)return}const s=Le.ctx;let n=(e[0].nx+e[1].nx+e[2].nx+e[3].nx)/4,o=(e[0].ny+e[1].ny+e[2].ny+e[3].ny)/4,r=n,a=o,h=i;this.doubleSided&&i>0&&(r=-n,a=-o,h=-i);const l=this._calculateLighting(r,a,h);for(const t of this.faces){const i=e[t[0]],n=e[t[1]],o=e[t[2]];if(this.debug)s.beginPath(),s.moveTo(i.x,i.y),s.lineTo(n.x,n.y),s.lineTo(o.x,o.y),s.closePath(),this.stroke&&(s.strokeStyle=this.stroke,s.lineWidth=this.lineWidth??1,s.stroke());else if(this.texture)this._renderTexturedTriangle(s,i,n,o);else if(this.color){const t=this._applyLighting(this.color,l);s.beginPath(),s.moveTo(i.x,i.y),s.lineTo(n.x,n.y),s.lineTo(o.x,o.y),s.closePath(),s.fillStyle=t,s.fill()}}}_renderTexturedTriangle(t,e,i,s){if(!this.texture||!this.texture.complete)return;const n=this.texture,o=n.width,r=n.height,a=e.u*o,h=e.v*r,l=i.u*o,c=i.v*r,u=s.u*o,d=s.v*r,f=e.x,p=e.y,g=i.x,m=i.y,v=s.x,y=s.y,_=(l-a)*(d-h)-(u-a)*(c-h);if(Math.abs(_)<1e-4)return;const x=((g-f)*(d-h)-(v-f)*(c-h))/_,b=((v-f)*(l-a)-(g-f)*(u-a))/_,w=f-x*a-b*h,M=((m-p)*(d-h)-(y-p)*(c-h))/_,S=((y-p)*(l-a)-(m-p)*(u-a))/_,C=p-M*a-S*h;t.save(),t.beginPath(),t.moveTo(f,p),t.lineTo(g,m),t.lineTo(v,y),t.closePath(),t.clip(),t.setTransform(x,M,b,S,w,C),t.drawImage(n,0,0),t.restore()}getCenter(){return{x:this.x,y:this.y,z:this.z}}getBounds(){return{x:this.x-this.planeWidth/2,y:this.y-this.planeHeight/2,width:this.planeWidth,height:this.planeHeight}}};_t(di,"_glRenderer",null),_t(di,"_glRendererSize",{width:0,height:0});let fi=di;class pi extends Ze{static async fromURL(t,e={}){const i=await fetch(t),s=await i.text(),n=(new DOMParser).parseFromString(s,"image/svg+xml").querySelector("path");if(!n)throw new Error("No path element found in SVG");const o=n.getAttribute("d");if(!o)throw new Error("Path element has no d attribute");return new pi(o,e)}constructor(t,e={}){super(e),this.scale=e.scale||1,this.centerPath=void 0===e.centerPath||e.centerPath,this.animationProgress=void 0!==e.animationProgress?e.animationProgress:1,this.svgPathData=t,this.pathCommands=this.parseSVGPath(t),this.centerPath?this.pathCommands=this.centerAndScalePath(this.pathCommands,this.scale):this.pathCommands=this.scalePath(this.pathCommands,this.scale),this.prevX=0,this.prevY=0,this.currentPoint={x:0,y:0}}parseSVGPath(t){const e=[];let i=0,s=0,n=0,o=0;const r=/([MLHVCSQTAZmlhvcsqtaz])([^MLHVCSQTAZmlhvcsqtaz]*)/g;let a;for(;null!==(a=r.exec(t));){const t=a[1],r=a[2].trim(),h=r.length>0?r.split(/[\s,]+/).map(parseFloat).filter(t=>!isNaN(t)):[];switch(t){case"M":for(let t=0;t<h.length;t+=2)i=h[t],s=h[t+1],0===t?(n=i,o=s,e.push(["M",i,s])):e.push(["L",i,s]);break;case"m":for(let t=0;t<h.length;t+=2)i+=h[t],s+=h[t+1],0===t?(n=i,o=s,e.push(["M",i,s])):e.push(["L",i,s]);break;case"L":for(let t=0;t<h.length;t+=2){const n=h[t],o=h[t+1];e.push(["L",n,o]),i=n,s=o}break;case"l":for(let t=0;t<h.length;t+=2)i+=h[t],s+=h[t+1],e.push(["L",i,s]);break;case"H":for(let t=0;t<h.length;t++)i=h[t],e.push(["L",i,s]);break;case"h":for(let t=0;t<h.length;t++)i+=h[t],e.push(["L",i,s]);break;case"V":for(let t=0;t<h.length;t++)s=h[t],e.push(["L",i,s]);break;case"v":for(let t=0;t<h.length;t++)s+=h[t],e.push(["L",i,s]);break;case"C":for(let t=0;t<h.length;t+=6)e.push(["C",h[t],h[t+1],h[t+2],h[t+3],h[t+4],h[t+5]]),i=h[t+4],s=h[t+5];break;case"c":for(let t=0;t<h.length;t+=6)e.push(["C",i+h[t],s+h[t+1],i+h[t+2],s+h[t+3],i+h[t+4],s+h[t+5]]),i+=h[t+4],s+=h[t+5];break;case"S":for(let t=0;t<h.length;t+=4){const n=e[e.length-1];let o=i,r=s;n&&"C"===n[0]&&(o=2*i-n[3],r=2*s-n[4]),e.push(["C",o,r,h[t],h[t+1],h[t+2],h[t+3]]),i=h[t+2],s=h[t+3]}break;case"s":for(let t=0;t<h.length;t+=4){const n=e[e.length-1];let o=i,r=s;n&&"C"===n[0]&&(o=2*i-n[3],r=2*s-n[4]),e.push(["C",o,r,i+h[t],s+h[t+1],i+h[t+2],s+h[t+3]]),i+=h[t+2],s+=h[t+3]}break;case"Q":for(let t=0;t<h.length;t+=4){const n=h[t],o=h[t+1],r=h[t+2],a=h[t+3],l=i+2/3*(n-i),c=s+2/3*(o-s),u=r+2/3*(n-r),d=a+2/3*(o-a);e.push(["C",l,c,u,d,r,a]),i=r,s=a}break;case"q":for(let t=0;t<h.length;t+=4){const n=i+h[t],o=s+h[t+1],r=i+h[t+2],a=s+h[t+3],l=i+2/3*(n-i),c=s+2/3*(o-s),u=r+2/3*(n-r),d=a+2/3*(o-a);e.push(["C",l,c,u,d,r,a]),i=r,s=a}break;case"Z":case"z":e.push(["Z"]),i=n,s=o}}return e}centerAndScalePath(t,e){let i=1/0,s=1/0,n=-1/0,o=-1/0;for(const e of t)"M"===e[0]||"L"===e[0]?(i=Math.min(i,e[1]),s=Math.min(s,e[2]),n=Math.max(n,e[1]),o=Math.max(o,e[2])):"C"===e[0]&&(i=Math.min(i,e[1],e[3],e[5]),s=Math.min(s,e[2],e[4],e[6]),n=Math.max(n,e[1],e[3],e[5]),o=Math.max(o,e[2],e[4],e[6]));const r=(i+n)/2,a=(s+o)/2;return this.originalWidth=(n-i)*e,this.originalHeight=(o-s)*e,t.map(t=>"M"===t[0]||"L"===t[0]?[t[0],(t[1]-r)*e,(t[2]-a)*e]:"C"===t[0]?["C",(t[1]-r)*e,(t[2]-a)*e,(t[3]-r)*e,(t[4]-a)*e,(t[5]-r)*e,(t[6]-a)*e]:[...t])}scalePath(t,e){let i=1/0,s=1/0,n=-1/0,o=-1/0;for(const e of t)"M"===e[0]||"L"===e[0]?(i=Math.min(i,e[1]),s=Math.min(s,e[2]),n=Math.max(n,e[1]),o=Math.max(o,e[2])):"C"===e[0]&&(i=Math.min(i,e[1],e[3],e[5]),s=Math.min(s,e[2],e[4],e[6]),n=Math.max(n,e[1],e[3],e[5]),o=Math.max(o,e[2],e[4],e[6]));return this.originalWidth=(n-i)*e,this.originalHeight=(o-s)*e,t.map(t=>"M"===t[0]||"L"===t[0]?[t[0],t[1]*e,t[2]*e]:"C"===t[0]?["C",t[1]*e,t[2]*e,t[3]*e,t[4]*e,t[5]*e,t[6]*e]:[...t])}getPointOnSegment(t,e){if("M"===t[0])return{x:t[1],y:t[2]};if("L"===t[0])return{x:this.prevX+(t[1]-this.prevX)*e,y:this.prevY+(t[2]-this.prevY)*e};if("C"===t[0]){const i=this.prevX,s=this.prevY,n=t[1],o=t[2],r=t[3],a=t[4],h=t[5],l=t[6];return{x:Math.pow(1-e,3)*i+3*Math.pow(1-e,2)*e*n+3*(1-e)*Math.pow(e,2)*r+Math.pow(e,3)*h,y:Math.pow(1-e,3)*s+3*Math.pow(1-e,2)*e*o+3*(1-e)*Math.pow(e,2)*a+Math.pow(e,3)*l}}return{x:0,y:0}}getBezierPoint(t,e){return this.getPointOnSegment(t,e)}getPartialPath(){const t=[];let e=this.pathCommands.length,i=Math.floor(this.animationProgress*e),s=this.animationProgress*e%1,n=!1;this.prevX=0,this.prevY=0;for(let e=0;e<i;e++){const i=this.pathCommands[e];t.push([...i]),"M"===i[0]||"L"===i[0]?(this.prevX=i[1],this.prevY=i[2],n=!0):"C"===i[0]&&(this.prevX=i[5],this.prevY=i[6],n=!0)}if(i<e){const e=this.pathCommands[i];if("M"===e[0])t.push([...e]),this.prevX=e[1],this.prevY=e[2],this.currentPoint={x:e[1],y:e[2]};else if("L"===e[0]){n||this.findPreviousPoint(i);const o=this.getPointOnSegment(e,s);t.push(["L",o.x,o.y]),this.currentPoint=o}else if("C"===e[0]){n||this.findPreviousPoint(i);const o=this.getPointOnSegment(e,s);t.push(["C",e[1],e[2],e[3],e[4],o.x,o.y]),this.currentPoint=o}else"Z"===e[0]&&(s>.5&&t.push(["Z"]),this.currentPoint={x:this.prevX,y:this.prevY})}return t}findPreviousPoint(t){for(let e=t-1;e>=0;e--){const t=this.pathCommands[e];if("M"===t[0]||"L"===t[0])return this.prevX=t[1],void(this.prevY=t[2]);if("C"===t[0])return this.prevX=t[5],void(this.prevY=t[6])}this.prevX=0,this.prevY=0}draw(){super.draw();const t=this.getPartialPath();Le.lines.path(t,this.color,this.stroke,this.lineWidth)}getCurrentPoint(){return{x:this.currentPoint.x,y:this.currentPoint.y}}setAnimationProgress(t){this.animationProgress=Math.max(0,Math.min(1,t))}calculateBounds(){return{x:this.x,y:this.y,width:this.originalWidth||100,height:this.originalHeight||100}}}class gi extends Ze{constructor(t,e,i={}){super(i),this.outerRadius=t,this.innerRadius=e}draw(){super.draw(),Le.lines.beginPath(),Le.shapes.arc(0,0,this.outerRadius,0,2*Math.PI),Le.shapes.arc(0,0,this.innerRadius,0,2*Math.PI,!0),Le.lines.closePath(),this.color&&Le.colors.fill(this.color),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}}class mi extends Ze{constructor(t=6,e=40,i={}){super(i),this.sides=t,this.radius=e}draw(){super.draw();const t=[],e=2*Math.PI/this.sides;for(let i=0;i<this.sides;i++){const s=i*e;t.push({x:Math.cos(s)*this.radius,y:Math.sin(s)*this.radius})}Le.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class vi extends Ze{constructor(t,e={}){super(e),this.length=t}draw(){super.draw();const t=this.width/2,e=.4*this.length,i=this.length-e;Le.lines.beginPath(),Le.lines.moveTo(-i/2,-t),Le.lines.lineTo(i/2,-t),Le.lines.lineTo(i/2,-this.width),Le.lines.lineTo(this.length/2,0),Le.lines.lineTo(i/2,this.width),Le.lines.lineTo(i/2,t),Le.lines.lineTo(-i/2,t),Le.lines.closePath(),this.color&&Le.colors.fill(this.color),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}}class yi extends Ze{constructor(t=20,e={}){super(e),this.radius=t}draw(){super.draw();const t=this.radius,e=2.5*t;Le.lines.beginPath(),Le.shapes.arc(0,0,t,Math.PI,0),Le.lines.lineTo(t,0),Le.lines.lineTo(0,e),Le.lines.lineTo(-t,0),Le.lines.closePath(),this.color&&Le.colors.fill(this.color),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y+.98*this.radius,width:2*this.radius,height:2.5*this.radius}}}class _i extends Ze{constructor(t,e={}){super(e),this.radius=t}draw(){super.draw();const t=Array.from({length:6},(t,e)=>{const i=Math.PI/3*e;return{x:Math.cos(i)*this.radius,y:Math.sin(i)*this.radius}});Le.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class xi extends Ze{constructor(t={}){super(t)}draw(){super.draw();const t=this.width,e=this.height,i=.3*e,s=Le.lines;s.beginPath(),s.moveTo(0,i),s.bezierCurveTo(0,0,-t/2,0,-t/2,i),s.bezierCurveTo(-t/2,.8*e,0,e,0,e),s.bezierCurveTo(0,e,t/2,.8*e,t/2,i),s.bezierCurveTo(t/2,0,0,0,0,i),s.closePath(),this.color&&Le.colors.fill(this.color),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y+this.height/2,width:this.width,height:this.height}}}class bi extends Ze{constructor(t,e,i={}){super(i),this.size=t,this.thickness=e,this.diagonal=i.diagonal||!1}draw(){super.draw();const t=this.size/2,e=this.thickness/2;this.diagonal?(Le.lines.beginPath(),Le.lines.moveTo(-t,-t+e),Le.lines.lineTo(-t+e,-t),Le.lines.lineTo(0,-e),Le.lines.lineTo(t-e,-t),Le.lines.lineTo(t,-t+e),Le.lines.lineTo(e,0),Le.lines.lineTo(t,t-e),Le.lines.lineTo(t-e,t),Le.lines.lineTo(0,e),Le.lines.lineTo(-t+e,t),Le.lines.lineTo(-t,t-e),Le.lines.lineTo(-e,0),Le.lines.closePath()):(Le.lines.beginPath(),Le.lines.moveTo(-e,-t),Le.lines.lineTo(e,-t),Le.lines.lineTo(e,-e),Le.lines.lineTo(t,-e),Le.lines.lineTo(t,e),Le.lines.lineTo(e,e),Le.lines.lineTo(e,t),Le.lines.lineTo(-e,t),Le.lines.lineTo(-e,e),Le.lines.lineTo(-t,e),Le.lines.lineTo(-t,-e),Le.lines.lineTo(-e,-e),Le.lines.closePath()),this.color&&Le.colors.fill(this.color),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}}class wi extends Ze{constructor(t,e={}){super(e),this._text=t,this._font=e.font||"12px monospace",this._color=e.color||"yellow",this._align=e.align||"center",this._baseline=e.baseline||"middle",this._calculateBounds(),this._calculateAlignmentOffsets()}draw(){super.draw(),this.logger.log("draw",this.font,this.color,this.opacity),Le.text.setFont(this.font),Le.text.setTextAlign(this.align),Le.text.setTextBaseline(this.baseline),Le.text.fillText(this.text,-this._centerOffsetX,-this._centerOffsetY,this.color)}_calculateAlignmentOffsets(){if(!Le.text)return;const t=Le.text.measureTextDimensions(this.text,this.font);switch(this._align){case"left":this._centerOffsetX=t.width/2;break;case"center":this._centerOffsetX=0;break;case"right":this._centerOffsetX=-t.width/2}switch(this._baseline){case"top":this._centerOffsetY=t.height/2;break;case"middle":this._centerOffsetY=0;break;case"bottom":this._centerOffsetY=-t.height/2}}getTextBounds(){if(Le.text){const t=Le.text.measureTextDimensions(this.text,this.font),e=2;return{x:this._centerOffsetX-t.width/2,y:this._centerOffsetY-t.height/2,width:t.width+2*e,height:t.height+2*e}}return{x:this._centerOffsetX,y:this._centerOffsetY,width:this._width,height:this._height}}_calculateBounds(){if(Le.text){const t=Le.text.measureTextDimensions(this.text,this.font);this._width=t.width,this._height=t.height,this._calculateAlignmentOffsets()}else this._width=this.text?8*this.text.length:0,this._height=16;this.trace("TextShape.calculateBounds: "+this._width+"x"+this._height)}getDebugBounds(){const t=this.getTextBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}checkDirty(t,e){t!==e&&(this._boundsDirty=!0,this._calculateBounds())}get text(){return this._text}set text(t){this.checkDirty(t,this._text),this._text=t}get font(){return this._font}set font(t){this.checkDirty(t,this._font),this._font=t}get color(){return this._color}set color(t){this._color=t}get align(){return this._align}set align(t){this.checkDirty(t,this._align),this._align=t}get baseline(){return this._baseline}set baseline(t){this.checkDirty(t,this._baseline),this._baseline=t}}class Mi extends Ze{constructor(t,e={}){if(!t&&!e.width&&!e.height)throw new Error("ImageShape must be initialized with either a bitmap or width and height");super(e),this._bitmap=t??Le.img.createImageData(e.width,e.height),this._width=e.width??(null==t?void 0:t.width)??0,this._height=e.height??(null==t?void 0:t.height)??0,this.anchor=e.anchor??"center",this._anchorX=.5,this._anchorY=.5,this._updateAnchorOffsets(),this.smoothing=!1!==e.smoothing,t instanceof ImageData&&this.buffer(t)}_updateAnchorOffsets(){var t;const e=(null==(t=this.anchor)?void 0:t.toLowerCase())??"center";e.includes("left")?this._anchorX=0:e.includes("right")?this._anchorX=1:this._anchorX=.5,e.includes("top")?this._anchorY=0:e.includes("bottom")?this._anchorY=1:this._anchorY=.5}get bitmap(){return this._bitmap}set bitmap(t){t&&(this._bitmap=t,!this._width&&t.width&&(this._width=t.width),!this._height&&t.height&&(this._height=t.height),t instanceof ImageData&&this.buffer(t))}buffer(t){t&&(this._buffer||(this._buffer=document.createElement("canvas")),this._buffer.width===t.width&&this._buffer.height===t.height||(this._buffer.width=t.width,this._buffer.height=t.height),this._buffer.getContext("2d").putImageData(t,0,0))}reset(){this._buffer=null,this._bitmap=Le.img.createImageData(this.width,this.height)}setAnchor(t){this.anchor=t,this._updateAnchorOffsets()}draw(){if(!this.visible)return;if(!this._bitmap&&!this._buffer)return;super.draw();let t=this._bitmap instanceof ImageData?this._buffer:this._bitmap;(!t||this._bitmap instanceof ImageData&&!this._buffer)&&(this._bitmap instanceof ImageData&&(this.buffer(this._bitmap),t=this._buffer),!t)||Le.img.draw(t,0,0,{width:this.width,height:this.height,anchor:this.anchor,rotation:this.rotation,scaleX:this.scaleX,scaleY:this.scaleY,alpha:this.opacity,smoothing:this.smoothing,flipX:this.scaleX<0,flipY:this.scaleY<0})}calculateBounds(){return{x:-this._anchorX*this.width,y:-this._anchorY*this.height,width:this.width,height:this.height}}}class Si{constructor(){this.listeners={}}on(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)}off(t,e){this.listeners[t]&&(this.listeners[t]=this.listeners[t].filter(t=>t!==e))}emit(t,e){this.listeners[t]&&this.listeners[t].forEach(t=>t(e))}}class Ci{static init(t){Ci.game=t,Ci.x=0,Ci.y=0,Ci.down=!1,t.events.on("mousedown",e=>Ci._onDown(e,t)),t.events.on("mouseup",e=>Ci._onUp(e,t)),t.events.on("mousemove",e=>Ci._onMove(e,t)),t.events.on("touchstart",e=>Ci._onTouchStart(e,t)),t.events.on("touchend",e=>Ci._onTouchEnd(e,t)),t.events.on("touchmove",e=>Ci._onTouchMove(e,t))}static _scaleToCanvas(t,e,i){const s=t.canvas,n=s.getBoundingClientRect();return{x:e*(s.width/n.width),y:i*(s.height/n.height)}}static _setPosition(t,e){Ci.x=t,Ci.y=e}static _onDown(t,e){Ci.down=!0;const i=Ci._scaleToCanvas(e,t.offsetX,t.offsetY);Ci._setPosition(i.x,i.y),Object.defineProperty(t,"x",{value:i.x,configurable:!0}),Object.defineProperty(t,"y",{value:i.y,configurable:!0}),e.events.emit("inputdown",t)}static _onUp(t,e){Ci.down=!1;const i=Ci._scaleToCanvas(e,t.offsetX,t.offsetY);Ci._setPosition(i.x,i.y),Object.defineProperty(t,"x",{value:i.x,configurable:!0}),Object.defineProperty(t,"y",{value:i.y,configurable:!0}),e.events.emit("inputup",t)}static _onMove(t,e){const i=Ci._scaleToCanvas(e,t.offsetX,t.offsetY);Ci._setPosition(i.x,i.y),Object.defineProperty(t,"x",{value:i.x,configurable:!0}),Object.defineProperty(t,"y",{value:i.y,configurable:!0}),e.events.emit("inputmove",t)}static _onTouchStart(t,e){const i=t.touches[0],s=e.canvas.getBoundingClientRect();Ci.down=!0;const n=i.clientX-s.left,o=i.clientY-s.top,r=Ci._scaleToCanvas(e,n,o);Ci._setPosition(r.x,r.y),Object.defineProperty(t,"x",{value:r.x,configurable:!0}),Object.defineProperty(t,"y",{value:r.y,configurable:!0}),e.events.emit("inputdown",t)}static _onTouchEnd(t,e){Ci.down=!1,e.events.emit("inputup",t)}static _onTouchMove(t,e){const i=t.touches[0],s=e.canvas.getBoundingClientRect(),n=i.clientX-s.left,o=i.clientY-s.top,r=Ci._scaleToCanvas(e,n,o);Ci._setPosition(r.x,r.y),Object.defineProperty(t,"x",{value:r.x,configurable:!0}),Object.defineProperty(t,"y",{value:r.y,configurable:!0}),e.events.emit("inputmove",t)}}const Ti=class t{static init(e){t._gameMap.set(e.canvas,e),t.game=e,t.canvas=e.canvas,t.x=0,t.y=0,t.leftDown=!1,t.middleDown=!1,t.rightDown=!1,e.canvas.addEventListener("mousemove",t._onMove),e.canvas.addEventListener("mousedown",t._onDown),e.canvas.addEventListener("mouseup",t._onUp),e.canvas.addEventListener("click",t._onClick),e.canvas.addEventListener("wheel",t._onWheel)}static _getGameForEvent(e){const i=e.currentTarget;return t._gameMap.get(i)||t.game}static _updatePosition(e,i){const s=i.canvas,n=s.getBoundingClientRect(),o=e.clientX-n.left,r=e.clientY-n.top,a=s.width/n.width,h=s.height/n.height;t.x=o*a,t.y=r*h}};_t(Ti,"_gameMap",new Map),_t(Ti,"_onMove",t=>{const e=Ti._getGameForEvent(t);Ti._updatePosition(t,e),e.events.emit("mousemove",t)}),_t(Ti,"_onDown",t=>{const e=Ti._getGameForEvent(t);Ti._updatePosition(t,e),0===t.button&&(Ti.leftDown=!0),1===t.button&&(Ti.middleDown=!0),2===t.button&&(Ti.rightDown=!0),e.events.emit("mousedown",t)}),_t(Ti,"_onUp",t=>{const e=Ti._getGameForEvent(t);Ti._updatePosition(t,e),0===t.button&&(Ti.leftDown=!1),1===t.button&&(Ti.middleDown=!1),2===t.button&&(Ti.rightDown=!1),e.events.emit("mouseup",t)}),_t(Ti,"_onClick",t=>{const e=Ti._getGameForEvent(t);Ti._updatePosition(t,e),t.canvasX=Ti.x,t.canvasY=Ti.y,Object.defineProperty(t,"x",{value:Ti.x,writable:!1}),Object.defineProperty(t,"y",{value:Ti.y,writable:!1}),e.events.emit("click",t)}),_t(Ti,"_onWheel",t=>{const e=Ti._getGameForEvent(t);Ti._updatePosition(t,e),e.events.emit("wheel",t)});let ki=Ti;const Pi=class t{static init(e){t.game=e,window.addEventListener("keydown",t._onKeyDown),window.addEventListener("keyup",t._onKeyUp)}static isDown(e){return t._down.has(e)}static _onKeyDown(e){const i=t._codeMap[e.code];i&&(t._down.has(i)||(t._down.add(i),t.game.events.emit(i,e))),t.game.events.emit(e.type,e)}static _onKeyUp(e){const i=t._codeMap[e.code];i&&t._down.has(i)&&(t._down.delete(i),t.game.events.emit(i+"_up",e)),t.game.events.emit(e.type,e)}};_t(Pi,"W","W"),_t(Pi,"A","A"),_t(Pi,"S","S"),_t(Pi,"D","D"),_t(Pi,"Q","Q"),_t(Pi,"E","E"),_t(Pi,"R","R"),_t(Pi,"F","F"),_t(Pi,"G","G"),_t(Pi,"J","J"),_t(Pi,"K","K"),_t(Pi,"L","L"),_t(Pi,"Z","Z"),_t(Pi,"C","C"),_t(Pi,"UP","UP"),_t(Pi,"DOWN","DOWN"),_t(Pi,"LEFT","LEFT"),_t(Pi,"RIGHT","RIGHT"),_t(Pi,"SPACE","SPACE"),_t(Pi,"SHIFT","SHIFT"),_t(Pi,"ENTER","ENTER"),_t(Pi,"ESC","ESC"),_t(Pi,"_codeMap",{KeyW:Pi.W,KeyA:Pi.A,KeyS:Pi.S,KeyD:Pi.D,KeyQ:Pi.Q,KeyE:Pi.E,KeyR:Pi.R,KeyF:Pi.F,KeyG:Pi.G,KeyJ:Pi.J,KeyK:Pi.K,KeyL:Pi.L,KeyZ:Pi.Z,KeyC:Pi.C,ArrowUp:Pi.UP,ArrowDown:Pi.DOWN,ArrowLeft:Pi.LEFT,ArrowRight:Pi.RIGHT,Space:Pi.SPACE,ShiftLeft:Pi.SHIFT,ShiftRight:Pi.SHIFT,Enter:Pi.ENTER,NumpadEnter:Pi.ENTER,Escape:Pi.ESC}),_t(Pi,"_down",new Set),_t(Pi,"game",null);let Ri=Pi;const Ai=class t{static init(e){t._gameMap.set(e.canvas,e),t.game=e,t.canvas=e.canvas,t.x=0,t.y=0,t.active=!1,e.canvas.addEventListener("touchstart",t._onStart),e.canvas.addEventListener("touchend",t._onEnd),e.canvas.addEventListener("touchmove",t._onMove)}static _getGameForEvent(e){const i=e.currentTarget;return t._gameMap.get(i)||t.game}static _updatePosition(e,i){const s=i.canvas,n=s.getBoundingClientRect(),o=e.clientX-n.left,r=e.clientY-n.top,a=s.width/n.width,h=s.height/n.height;t.x=o*a,t.y=r*h}};_t(Ai,"_gameMap",new Map),_t(Ai,"_onStart",t=>{if(t.touches.length>0){const e=Ai._getGameForEvent(t);Ai.active=!0,Ai._updatePosition(t.touches[0],e),e.events.emit("touchstart",t)}}),_t(Ai,"_onEnd",t=>{const e=Ai._getGameForEvent(t);Ai.active=!1,e.events.emit("touchend",t)}),_t(Ai,"_onMove",t=>{if(t.touches.length>0){const e=Ai._getGameForEvent(t);Ai._updatePosition(t.touches[0],e),e.events.emit("touchmove",t)}});let zi=Ai;const Di=class t{static init(e){if(t.game=e,t._detect(),!t._initialized){if(t._initialized=!0,window.addEventListener("resize",t._onResize),window.addEventListener("orientationchange",t._onOrientationChange),window.matchMedia){const e=window.matchMedia(`(max-width: ${t.MOBILE_BREAKPOINT}px)`),i=window.matchMedia(`(max-width: ${t.TABLET_BREAKPOINT}px)`);e.addEventListener&&(e.addEventListener("change",t._onMediaChange),i.addEventListener("change",t._onMediaChange))}document.addEventListener("visibilitychange",t._onVisibilityChange)}}static _detect(){t.width=window.innerWidth,t.height=window.innerHeight,t.pixelRatio=window.devicePixelRatio||1,t.isMobile=t.width<=t.MOBILE_BREAKPOINT,t.isTablet=t.width>t.MOBILE_BREAKPOINT&&t.width<=t.TABLET_BREAKPOINT,t.isDesktop=t.width>t.TABLET_BREAKPOINT,t.hasTouch="ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0,t.isPortrait=t.height>t.width,t.isLandscape=!t.isPortrait,t.orientation=t.isPortrait?"portrait":"landscape"}static responsive(e,i,s){return 0===t.width&&"undefined"!=typeof window&&t._detect(),void 0===i&&(i=e),void 0===s&&(s=i),t.isMobile?e:t.isTablet?i:s}static scaled(e){return e*t.pixelRatio}static isTouchPrimary(){return t.hasTouch&&(t.isMobile||t.isTablet)}static minDimension(){return Math.min(t.width,t.height)}static maxDimension(){return Math.max(t.width,t.height)}static aspectRatio(){return t.width/t.height}static matches(t){return!!window.matchMedia&&window.matchMedia(t).matches}static prefersReducedMotion(){return t.matches("(prefers-reduced-motion: reduce)")}static prefersDarkMode(){return t.matches("(prefers-color-scheme: dark)")}static async _acquireWakeLock(){if(!t.wakeLockSupported)return!1;try{return t._wakeLock=await navigator.wakeLock.request("screen"),t._wakeLock.addEventListener("release",()=>{t.game&&t.game.events.emit("wakelockrelease")}),t.game&&t.game.events.emit("wakelockacquire"),!0}catch(t){return console.warn("[Screen] Wake lock request failed:",t.message),!1}}static async requestWakeLock(){return t.wakeLockSupported?(t.wakeLockEnabled=!0,await t._acquireWakeLock()):(console.warn("[Screen] Wake Lock API not supported in this browser"),!1)}static async releaseWakeLock(){if(t.wakeLockEnabled=!1,t._wakeLock)try{await t._wakeLock.release(),t._wakeLock=null}catch(t){console.warn("[Screen] Wake lock release failed:",t.message)}}static isWakeLockActive(){return null!==t._wakeLock&&!t._wakeLock.released}};_t(Di,"MOBILE_BREAKPOINT",768),_t(Di,"TABLET_BREAKPOINT",1024),_t(Di,"game",null),_t(Di,"_initialized",!1),_t(Di,"width",0),_t(Di,"height",0),_t(Di,"pixelRatio",1),_t(Di,"isMobile",!1),_t(Di,"isTablet",!1),_t(Di,"isDesktop",!1),_t(Di,"hasTouch",!1),_t(Di,"orientation","landscape"),_t(Di,"isPortrait",!1),_t(Di,"isLandscape",!0),_t(Di,"_wakeLock",null),_t(Di,"wakeLockEnabled",!1),_t(Di,"wakeLockSupported",!1),"undefined"!=typeof window&&(Di._detect(),Di.wakeLockSupported="wakeLock"in navigator),_t(Di,"_onResize",()=>{const t=Di.isMobile,e=Di.isTablet,i=Di.orientation;Di._detect(),Di.game&&(Di.game.events.emit("screenresize",{width:Di.width,height:Di.height,isMobile:Di.isMobile,isTablet:Di.isTablet,isDesktop:Di.isDesktop}),t===Di.isMobile&&e===Di.isTablet||Di.game.events.emit("devicechange",{isMobile:Di.isMobile,isTablet:Di.isTablet,isDesktop:Di.isDesktop,previous:{isMobile:t,isTablet:e,isDesktop:!t&&!e}}),i!==Di.orientation&&Di.game.events.emit("orientationchange",{orientation:Di.orientation,isPortrait:Di.isPortrait,isLandscape:Di.isLandscape}))}),_t(Di,"_onOrientationChange",()=>{setTimeout(()=>{Di._onResize()},100)}),_t(Di,"_onMediaChange",()=>{Di._onResize()}),_t(Di,"_onVisibilityChange",async()=>{Di.wakeLockEnabled&&"visible"===document.visibilityState&&await Di._acquireWakeLock()});let Bi=Di;function Ii(t,e={}){var i;if(!(t&&t instanceof Ei))return console.warn("applyAnchor can only be applied to GameObject instances"),t;t._anchor={position:e.anchor??null,margin:e.anchorMargin??10,offsetX:e.anchorOffsetX??0,offsetY:e.anchorOffsetY??0,relative:e.anchorRelative??!1,setTextAlign:!1!==e.anchorSetTextAlign,lastUpdate:0};const s=null==(i=t.update)?void 0:i.bind(t);return t.update=function(e){const i=!0===t._anchor.relative&&t.parent?t.parent:t._anchor.relative;if(t._anchor.position&&(t.boundsDirty||i&&i.boundsDirty||t.parent&&t.parent.boundsDirty)){let e,s,o;if(i){const s={x:i.x,y:i.y,width:i.width,height:i.height};e=kt.calculate(t._anchor.position,t,s,t._anchor.margin,t._anchor.offsetX,t._anchor.offsetY)}else e=kt.calculateAbsolute(t._anchor.position,t,t.game,t._anchor.margin,t._anchor.offsetX,t._anchor.offsetY);!t.parent||(n=t).game&&n.game.pipeline&&n.game.pipeline.gameObjects&&n.game.pipeline.gameObjects.includes(n)?(s=e.x,o=e.y):i===t.parent?(s=e.x-i.x,o=e.y-i.y):(s=e.x-t.parent.x,o=e.y-t.parent.y),t.transform&&"function"==typeof t.transform.position?t.transform.position(s,o):(t.x=s,t.y=o),t._anchor.setTextAlign&&("align"in t&&(t.align=e.align),"baseline"in t&&(t.baseline=e.baseline)),t._anchor.lastUpdate=t.game?t.game.lastTime:Date.now()}var n;s&&s(e)},t}class Ei extends qe{constructor(t,e={}){super(e),this.game=t,this.parent=null,this.events=new Si,this._interactive=e.interactive??!1,this._hovered=!1,e.anchor&&Ii(this,e)}update(t){this.logger.groupCollapsed("GameObject.update: "+(null==this.name?this.constructor.name:this.name)),super.update(t),this.logger.groupEnd()}get interactive(){return this._interactive}set interactive(t){const e=Boolean(t);this._interactive!==e&&(this._interactive=e,!0===e?this._enableEvents():(this._disableEvents(),this._hovered&&(this._hovered=!1,this.events.emit("mouseout"))))}_enableEvents(){this.logger.log(`${this.constructor.name} is now interactive`)}_disableEvents(){this.logger.log(`${this.constructor.name} is no longer interactive`)}get hovered(){return this._hovered}set hovered(t){this._hovered=Boolean(t)}_setHovered(t){this._hovered=Boolean(t)}_hitTest(t,e){var i;if(!this._interactive)return!1;const s=null==(i=this.getBounds)?void 0:i.call(this);if(!s)return!1;let n=t,o=e;const r=[];let a=this;for(;a;)r.unshift(a),a=a.parent;for(const t of r){if(n-=t.x||0,o-=t.y||0,t.getHitTestOffset){const e=t.getHitTestOffset();n-=e.x||0,o-=e.y||0}if(t.rotation){const e=Math.cos(-t.rotation),i=Math.sin(-t.rotation),s=n;n=s*e-o*i,o=s*i+o*e}void 0!==t.scaleX&&0!==t.scaleX&&(n/=t.scaleX),void 0!==t.scaleY&&0!==t.scaleY&&(o/=t.scaleY)}const h=(s.width||this.width||0)/2,l=(s.height||this.height||0)/2;return n>=-h&&n<=h&&o>=-l&&o<=l}on(t,e){this.events.on(t,e)}off(t,e){this.events.off(t,e)}emit(t,...e){this.events.emit(t,...e)}}class Fi extends Ei{constructor(t,e,i={}){const{anchor:s,...n}=i;if(super(t,n),!e||null==e||null==e)throw new Error("GameObjectShapeWrapper requires a shape");this.shape=e,void 0!==i.color&&(e.color=i.color),void 0!==i.stroke&&(e.stroke=i.stroke),void 0!==i.lineWidth&&(e.lineWidth=i.lineWidth),void 0!==i.lineJoin&&(e.lineJoin=i.lineJoin),void 0!==i.lineCap&&(e.lineCap=i.lineCap),void 0!==i.miterLimit&&(e.miterLimit=i.miterLimit),this.syncPropertiesToShape(),this.logger.log(`Created GameObject(${this.constructor.name}):`,{x:this.x,y:this.y,width:this.width,height:this.height,color:this.color,stroke:this.stroke})}syncPropertiesToShape(){if(!this.shape)return;const t=["width","height","rotation","scaleX","scaleY","visible","debug","debugColor"];for(const e of t)e in this&&e in this.shape&&this[e]!==this.shape[e]&&(this.shape[e]=this[e])}get color(){return this.shape?this.shape.color:null}set color(t){this.shape&&(this.shape.color=t)}get stroke(){return this.shape?this.shape.stroke:null}set stroke(t){this.shape&&(this.shape.stroke=t)}get lineWidth(){return this.shape?this.shape.lineWidth:1}set lineWidth(t){this.shape&&(this.shape.lineWidth=t)}get lineJoin(){return this.shape?this.shape.lineJoin:"miter"}set lineJoin(t){this.shape&&(this.shape.lineJoin=t)}get lineCap(){return this.shape?this.shape.lineCap:"butt"}set lineCap(t){this.shape&&(this.shape.lineCap=t)}get miterLimit(){return this.shape?this.shape.miterLimit:10}set miterLimit(t){this.shape&&(this.shape.miterLimit=t)}update(t){var e;this.active&&(null==(e=this.onUpdate)||e.call(this,t),(this._boundsDirty||this.tweening)&&(this.syncPropertiesToShape(),this._boundsDirty=!1),super.update(t))}draw(){super.draw(),this.shape.draw()}}class Oi extends Ei{constructor(t,e={}){super(t,e),this._collection=new Ct({sortByZIndex:e.sortByZIndex||!0}),this._collection._owner=this,this._width=e.width??0,this._height=e.height??0,this.forceWidth=null,this.forceHeight=null,this._naturalWidth=null,this._naturalHeight=null,this.userDefinedDimensions=!1,null!=e.width&&null!=e.height&&(this.userDefinedWidth=e.width,this.userDefinedHeight=e.height,this.userDefinedDimensions=!0)}update(t){this.logger.groupCollapsed("Scene.update: "+(null==this.name?this.constructor.name:this.name));for(let e=0;e<this.children.length;e++){const i=this.children[e];i.active&&i.update&&i.update(t)}super.update(t),this.logger.groupEnd()}add(t){if(null==t||null==t)throw new Error("GameObject is null or undefined");return null!=t.parent&&console.warn("This GameObject already has a parent. Consider removing it first."),t.parent=this,this._collection.add(t),this.markBoundsDirty(),t.init&&t.init(),t}markBoundsDirty(){super.markBoundsDirty(),this.children.forEach(t=>{t.markBoundsDirty()})}remove(t){const e=this._collection.remove(t);return e&&(t.parent=null,this.markBoundsDirty()),e}draw(){super.draw(),this.logger.log("Scene.draw chilren:"),this._collection.getSortedChildren().filter(t=>t.visible).map(function(t){return Le.save(),t.render(),Le.restore(),t})}getDebugBounds(){return{width:this.width,height:this.height,x:-this.width/2,y:-this.height/2}}getBounds(){return{x:this.x,y:this.y,width:this._width||0,height:this._height||0}}bringToFront(t){return this._collection.bringToFront(t)}sendToBack(t){return this._collection.sendToBack(t)}bringForward(t){return this._collection.bringForward(t)}sendBackward(t){return this._collection.sendBackward(t)}clear(){return this._collection.children.forEach(t=>this.remove(t)),this._collection.clear()}get children(){return this._collection.children}getHitTestOffset(){return{x:0,y:0}}isChildHittable(t){return!0}}class Li extends Oi{constructor(t,e={}){super(t,e),this.spacing=e.spacing??10,this.padding=e.padding??0,this.autoSize=e.autoSize??!0,this.align=e.align??"start",this.debug=e.debug??!1,this._layoutDirty=!0,this.scrollable=e.scrollable??!1,this.scrollFriction=e.scrollFriction??.92,this.scrollBounce=e.scrollBounce??.3,this.scrollThreshold=e.scrollThreshold??.5,this._viewportWidth=e.viewportWidth??null,this._viewportHeight=e.viewportHeight??null,this._scrollOffset={x:0,y:0},this._scrollVelocity={x:0,y:0},this._scrollDragging=!1,this._scrollDragStart={x:0,y:0},this._scrollDragStartOffset={x:0,y:0},this._lastDragPosition={x:0,y:0},this._lastDragTime=0,this.scrollable&&this._setupScrollInteraction(),this._scrollInitialized=!1}calculateLayout(){throw new Error("Subclasses must implement calculateLayout()")}update(t){if(this._boundsDirty||this._layoutDirty){const t=this.width,e=this.height,i=this.calculateLayout();if(this.autoSize&&i){this._contentWidth=i.width,this._contentHeight=i.height;const t=this.getScrollAxis(),e=this._viewportWidth,s=this._viewportHeight;let n=i.width,o=i.height;this.scrollable&&null!==e&&t.horizontal&&(n=Math.min(i.width,e)),this.scrollable&&null!==s&&t.vertical&&(o=Math.min(i.height,s)),Math.abs(this.width-n)>.1&&(this.width=n),Math.abs(this.height-o)>.1&&(this.height=o)}if(i&&i.positions&&this.applyPositionsToChildren(i.positions),this.scrollable&&!this._scrollInitialized&&this._needsScrolling()){const t=this._getScrollBounds(),e=this.getScrollAxis();e.horizontal&&(this._scrollOffset.x=t.maxX),e.vertical&&(this._scrollOffset.y=t.maxY),this._scrollInitialized=!0}this._boundsDirty=!1,this._layoutDirty=!1,t===this.width&&e===this.height||this._updatingBoundsFromLayout||(this._updatingBoundsFromLayout=!0,Oi.prototype.markBoundsDirty.call(this),this._updatingBoundsFromLayout=!1)}this.scrollable&&!this._scrollDragging&&this._updateScrollMomentum(t),super.update(t)}markBoundsDirty(){this._updatingBoundsFromLayout?this._boundsDirty=!0:(super.markBoundsDirty(),this._layoutDirty=!0)}applyPositionsToChildren(t){Pt(this.children,t,this.getLayoutOffset())}getLayoutOffset(){return{offsetX:0,offsetY:0}}add(t){const e=super.add(t);return this._layoutDirty=!0,e}remove(t){const e=super.remove(t);return this._layoutDirty=!0,e}getScrollAxis(){return{horizontal:!1,vertical:!0}}calculateBounds(){if(this.scrollable&&(this._viewportWidth||this._viewportHeight)){const t=this._viewportWidth??this.width,e=this._viewportHeight??this.height;return{x:-t/2,y:-e/2,width:t,height:e}}return super.calculateBounds()}_getScrollBounds(){const t=this._contentWidth??this.width,e=this._contentHeight??this.height,i=this._viewportWidth??t,s=this._viewportHeight??e,n=Math.max(0,t-i),o=Math.max(0,e-s);return{minX:-n/2,maxX:n/2,minY:-o/2,maxY:o/2}}_clampScrollBounds(){const t=this._getScrollBounds(),e=this.getScrollAxis();e.horizontal&&(this._scrollOffset.x<t.minX?(this._scrollOffset.x+=(t.minX-this._scrollOffset.x)*this.scrollBounce,this._scrollVelocity.x=0):this._scrollOffset.x>t.maxX&&(this._scrollOffset.x+=(t.maxX-this._scrollOffset.x)*this.scrollBounce,this._scrollVelocity.x=0)),e.vertical&&(this._scrollOffset.y<t.minY?(this._scrollOffset.y+=(t.minY-this._scrollOffset.y)*this.scrollBounce,this._scrollVelocity.y=0):this._scrollOffset.y>t.maxY&&(this._scrollOffset.y+=(t.maxY-this._scrollOffset.y)*this.scrollBounce,this._scrollVelocity.y=0))}_updateScrollMomentum(t){const e=this.getScrollAxis();e.horizontal&&(this._scrollVelocity.x*=this.scrollFriction,Math.abs(this._scrollVelocity.x)<this.scrollThreshold&&(this._scrollVelocity.x=0),this._scrollOffset.x+=this._scrollVelocity.x*t*60),e.vertical&&(this._scrollVelocity.y*=this.scrollFriction,Math.abs(this._scrollVelocity.y)<this.scrollThreshold&&(this._scrollVelocity.y=0),this._scrollOffset.y+=this._scrollVelocity.y*t*60),this._clampScrollBounds()}_setupScrollInteraction(){this.interactive=!0,this._scrollInputDownHandler=t=>{this._isPointInViewport(t.x,t.y)&&this._onScrollDragStart(t)},this._scrollInputMoveHandler=t=>this._onScrollDragMove(t),this._scrollInputUpHandler=t=>this._onScrollDragEnd(t),this.game.events.on("inputdown",this._scrollInputDownHandler),this.game.events.on("inputmove",this._scrollInputMoveHandler),this.game.events.on("inputup",this._scrollInputUpHandler)}_isPointInViewport(t,e){let i=t-this.x,s=e-this.y,n=this.parent;for(;n;)i-=n.x||0,s-=n.y||0,n=n.parent;const o=(this._viewportWidth??this.width)/2,r=(this._viewportHeight??this.height)/2;return i>=-o&&i<=o&&s>=-r&&s<=r}_onScrollDragStart(t){this._scrollDragging=!0,this._scrollDragStart={x:t.x,y:t.y},this._scrollDragStartOffset={...this._scrollOffset},this._lastDragPosition={x:t.x,y:t.y},this._lastDragTime=performance.now(),this._scrollVelocity={x:0,y:0}}_onScrollDragMove(t){if(!this._scrollDragging)return;const e=this.getScrollAxis(),i=performance.now(),s=Math.max(1,i-this._lastDragTime)/1e3;if(e.horizontal){const e=t.x-this._scrollDragStart.x;this._scrollOffset.x=this._scrollDragStartOffset.x+e,this._scrollVelocity.x=(t.x-this._lastDragPosition.x)/(60*s)}if(e.vertical){const e=t.y-this._scrollDragStart.y;this._scrollOffset.y=this._scrollDragStartOffset.y+e,this._scrollVelocity.y=(t.y-this._lastDragPosition.y)/(60*s)}this._lastDragPosition={x:t.x,y:t.y},this._lastDragTime=i}_onScrollDragEnd(){this._scrollDragging=!1}_needsScrolling(){if(!this.scrollable)return!1;const t=this._contentWidth??this.width,e=this._contentHeight??this.height,i=this._viewportWidth??t,s=this._viewportHeight??e,n=this.getScrollAxis();return!!(n.horizontal&&t>i)||!!(n.vertical&&e>s)}draw(){this._needsScrolling()?this._drawScrollable():super.draw()}_drawScrollable(){this.applyTransforms(),this.drawDebug();const t=this.padding??0,e=(this._viewportWidth??this.width)-2*t,i=(this._viewportHeight??this.height)-2*t;Le.save(),Le.ctx.beginPath(),Le.ctx.rect(-e/2,-i/2,e,i),Le.ctx.clip(),Le.ctx.beginPath(),Le.ctx.translate(this._scrollOffset.x,this._scrollOffset.y),this._collection.getSortedChildren().filter(t=>t.visible).forEach(t=>{Le.save(),t.render(),Le.restore()}),Le.restore()}scrollTo(t,e){const i=this.getScrollAxis();i.horizontal&&(this._scrollOffset.x=t),i.vertical&&(this._scrollOffset.y=e),this._scrollVelocity={x:0,y:0}}scrollBy(t,e){const i=this.getScrollAxis();i.horizontal&&(this._scrollOffset.x+=t),i.vertical&&(this._scrollOffset.y+=e)}getScrollPosition(){return{...this._scrollOffset}}resetScroll(){this._scrollOffset={x:0,y:0},this._scrollVelocity={x:0,y:0}}getHitTestOffset(){var t,e;return this.scrollable?{x:(null==(t=this._scrollOffset)?void 0:t.x)||0,y:(null==(e=this._scrollOffset)?void 0:e.y)||0}:{x:0,y:0}}isChildHittable(t){var e,i;if(!this.scrollable||!this._needsScrolling())return!0;const s=this.getScrollAxis(),n=this._viewportWidth??this.width,o=this._viewportHeight??this.height,r=(null==(e=this._scrollOffset)?void 0:e.x)||0,a=(null==(i=this._scrollOffset)?void 0:i.y)||0,h=t.x+r,l=t.y+a,c=(t.width||0)/2,u=(t.height||0)/2;return!(s.horizontal&&(h+c<-n/2||h-c>n/2)||s.vertical&&(l+u<-o/2||l-u>o/2))}}class Yi extends Ei{constructor(t,e={}){super(t,e),this._frames=[],this._currentFrame=0,this._frameAccumulator=0,this._isPlaying=e.autoPlay||!1,this._loop=void 0===e.loop||e.loop,this._frameRate=e.frameRate||12,this._frameDuration=1/this._frameRate,this._animations=new Map,this._currentAnimation=null,e.frames&&Array.isArray(e.frames)&&e.frames.forEach(t=>this.addFrame(t))}addAnimation(t,e,i={}){if(!t||"string"!=typeof t)throw new Error("Sprite.addAnimation: name is required");if(!e||!Array.isArray(e)||0===e.length)throw new Error("Sprite.addAnimation: frames array is required");return e.forEach(t=>{t.parent=this}),this._animations.set(t,{frames:e,loop:void 0===i.loop||i.loop,frameRate:i.frameRate||null}),this}removeAnimation(t){const e=this._animations.get(t);return!!e&&(e.frames.forEach(t=>{t.parent=null}),this._animations.delete(t),this._currentAnimation===t&&(this._currentAnimation=null,this._frames=[]),!0)}playAnimation(t,e=!1){const i=this._animations.get(t);return i?(this._currentAnimation===t&&this._isPlaying&&!e||(this._currentAnimation=t,this._frames=i.frames,this._loop=i.loop,null!==i.frameRate&&(this._frameRate=i.frameRate,this._frameDuration=1/this._frameRate),this._currentFrame=0,this._frameAccumulator=0,this._isPlaying=!0),this):(console.warn(`Sprite.playAnimation: animation '${t}' not found`),this)}stopAnimation(t){const e=this._animations.get(t);return e?(this._currentAnimation=t,this._frames=e.frames,this._loop=e.loop,this._currentFrame=0,this._frameAccumulator=0,this._isPlaying=!1,this):(console.warn(`Sprite.stopAnimation: animation '${t}' not found`),this)}get currentAnimationName(){return this._currentAnimation}get animationNames(){return Array.from(this._animations.keys())}hasAnimation(t){return this._animations.has(t)}addFrame(t){if(!t)throw new Error("Sprite.addFrame: shape is required");return t.parent=this,this._frames.push(t),this.markBoundsDirty(),this._frames.length-1}removeFrame(t){if(t<0||t>=this._frames.length)return null;const e=this._frames.splice(t,1)[0];return e&&(e.parent=null,this.markBoundsDirty(),this._currentFrame>=this._frames.length&&this._frames.length>0&&(this._currentFrame=this._frames.length-1)),e}clearFrames(){this._frames.forEach(t=>{t.parent=null}),this._frames=[],this._currentFrame=0,this.markBoundsDirty()}get totalFrames(){return this._frames.length}get currentFrame(){return this._currentFrame}get currentShape(){return this._frames[this._currentFrame]||null}get frames(){return this._frames}get isPlaying(){return this._isPlaying}get loop(){return this._loop}set loop(t){this._loop=t}get frameRate(){return this._frameRate}set frameRate(t){if(t<=0)throw new Error("Sprite.frameRate must be greater than 0");this._frameRate=t,this._frameDuration=1/t}play(){return this._isPlaying=!0,this}pause(){return this._isPlaying=!1,this}stop(){return this._isPlaying=!1,this._currentFrame=0,this._frameAccumulator=0,this}rewind(){return this._currentFrame=0,this._frameAccumulator=0,this}goto(t){return 0===this._frames.length||(this._currentFrame=Math.max(0,Math.min(t,this._frames.length-1)),this._frameAccumulator=0),this}gotoAndStop(t){return this.goto(t),this.pause(),this}gotoAndPlay(t){return this.goto(t),this.play(),this}update(t){if(super.update(t),!this._isPlaying||0===this._frames.length)return;for(this._frameAccumulator+=t;this._frameAccumulator>=this._frameDuration;)this._frameAccumulator-=this._frameDuration,this._advanceFrame();const e=this.currentShape;e&&"function"==typeof e.update&&e.update(t)}_advanceFrame(){this._currentFrame++,this._currentFrame>=this._frames.length&&(this._loop?this._currentFrame=0:(this._currentFrame=this._frames.length-1,this._isPlaying=!1))}draw(){super.draw();const t=this.currentShape;t&&!1!==t.visible&&(Le.save(),t.render(),Le.restore())}calculateBounds(){if(0===this._frames.length)return{x:this.x,y:this.y,width:0,height:0};let t=1/0,e=1/0,i=-1/0,s=-1/0;return this._frames.forEach(n=>{const o=n.getBounds();t=Math.min(t,o.x),e=Math.min(e,o.y),i=Math.max(i,o.x+o.width),s=Math.max(s,o.y+o.height)}),{x:t+this.x,y:e+this.y,width:i-t,height:s-e}}toString(){return`[Sprite frames=${this.totalFrames} current=${this.currentFrame} playing=${this.isPlaying}]`}}class Xi extends Yi{constructor(t,e={}){super(t,{frameRate:e.frameRate||12,loop:void 0===e.loop||e.loop,autoPlay:!1,...e}),this._src=e.src,this._frameWidth=e.frameWidth,this._frameHeight=e.frameHeight,this._columns=e.columns,this._rows=e.rows,this._frameCount=e.frameCount||e.columns*e.rows,this._startFrame=e.startFrame||0,this._smoothing=void 0!==e.smoothing&&e.smoothing,this._autoPlayAfterLoad=e.autoPlay||!1,this._loaded=!1,this._loading=!1,this._image=null,this._frameCanvases=[],this.width=this._frameWidth,this.height=this._frameHeight}static async create(t,e){const i=new Xi(t,e);return await i.load(),i}async load(){if(this._loaded||this._loading)return this;this._loading=!0;try{return this._image=await this._loadImage(this._src),await this._sliceFrames(),this._loaded=!0,this._loading=!1,this._autoPlayAfterLoad&&this.play(),this}catch(t){throw this._loading=!1,console.error("SpriteSheet.load failed:",t),t}}_loadImage(t){return new Promise((e,i)=>{const s=new Image;s.onload=()=>e(s),s.onerror=e=>i(new Error(`Failed to load image: ${t}`)),s.src=t})}async _sliceFrames(){const{_image:t,_frameWidth:e,_frameHeight:i,_columns:s}=this;this.clearFrames(),this._frameCanvases=[];for(let n=this._startFrame;n<this._startFrame+this._frameCount;n++){const o=n%s*e,r=Math.floor(n/s)*i,a=document.createElement("canvas");a.width=e,a.height=i;const h=a.getContext("2d");h.imageSmoothingEnabled=this._smoothing,h.drawImage(t,o,r,e,i,0,0,e,i),this._frameCanvases.push(a);const l=new Mi(a,{width:e,height:i,anchor:"center",smoothing:this._smoothing});this.addFrame(l)}}get loaded(){return this._loaded}get loading(){return this._loading}get frameWidth(){return this._frameWidth}get frameHeight(){return this._frameHeight}get columns(){return this._columns}get rows(){return this._rows}update(t){this._loaded&&super.update(t)}draw(){this._loaded&&super.draw()}toString(){return`[SpriteSheet src="${this._src}" frames=${this._frameCount} loaded=${this._loaded}]`}}class Wi extends Fi{constructor(t,e,i={}){super(t,new wi(e,{font:i.font||"16px monospace",color:i.color||"yellow",align:i.align||"left",baseline:i.baseline||"top",strokeColor:i.strokeColor||"#000",lineWidth:i.lineWidth||1,debugColor:i.debugColor||"yellow"}),i),this._textOptions={font:i.font||"16px monospace",color:i.color||"yellow",align:i.align||"left",baseline:i.baseline||"top"}}get text(){return this.shape.text}set text(t){this.shape.text=t,this.markBoundsDirty()}get font(){return this.shape.font}set font(t){this.shape.font=t,this._textOptions.font=t,this.markBoundsDirty()}get color(){return this.shape.color}set color(t){this.shape.color=t,this._textOptions.color=t}get align(){return this.shape.align}set align(t){this.shape.align=t,this._textOptions.align=t,this.markBoundsDirty()}get baseline(){return this.shape.baseline}set baseline(t){this.shape.baseline=t,this._textOptions.baseline=t,this.markBoundsDirty()}measureWidth(){return Le.ctx?Le.text.measureTextWidth(this.text,this.font):0}measureHeight(){if(!this.font)return 16;const t=parseInt(this.font);return isNaN(t)?16:t}getBounds(){const t=super.getBounds();if(this.shape.getTextBounds){const t=this.shape.getTextBounds();return{x:this.x,y:this.y,width:t.width,height:t.height}}return t}update(t){super.update(t),this.shape&&(this.width=this.shape.width||this.measureWidth(),this.height=this.shape.height||this.measureHeight())}}class Hi{constructor(t={}){this.shape=t.shape||"circle",this.x=t.x??0,this.y=t.y??0,this.scaleX=t.scaleX??1,this.scaleY=t.scaleY??1,this.radius=t.radius??100,this.width=t.width??200,this.height=t.height??200,this.cornerRadius=t.cornerRadius??0,this.radiusX=t.radiusX??100,this.radiusY=t.radiusY??100,this.pathFn=t.pathFn??null,this.invert=t.invert??!1,this._applied=!1}apply(t){this._applied?console.warn("Mask already applied. Call remove() first."):(t.save(),t.beginPath(),this.invert?(t.rect(-1e4,-1e4,2e4,2e4),this._drawPath(t),t.clip("evenodd")):(this._drawPath(t),t.clip()),this._applied=!0)}remove(t){this._applied&&(t.restore(),this._applied=!1)}_drawPath(t){const e=this.scaleX,i=this.scaleY;switch(this.shape){case"circle":const s=(e+i)/2;t.arc(this.x,this.y,this.radius*s,0,2*Math.PI);break;case"rectangle":const n=this.width*e,o=this.height*i,r=this.cornerRadius*Math.min(e,i);r>0?this._roundedRect(t,this.x-n/2,this.y-o/2,n,o,r):t.rect(this.x-n/2,this.y-o/2,n,o);break;case"ellipse":t.ellipse(this.x,this.y,this.radiusX*e,this.radiusY*i,0,0,2*Math.PI);break;case"path":this.pathFn&&this.pathFn(t,this);break;default:console.warn(`Unknown mask shape: ${this.shape}`)}}_roundedRect(t,e,i,s,n,o){o=Math.min(o,s/2,n/2),t.moveTo(e+o,i),t.lineTo(e+s-o,i),t.arcTo(e+s,i,e+s,i+o,o),t.lineTo(e+s,i+n-o),t.arcTo(e+s,i+n,e+s-o,i+n,o),t.lineTo(e+o,i+n),t.arcTo(e,i+n,e,i+n-o,o),t.lineTo(e,i+o),t.arcTo(e,i,e+o,i,o),t.closePath()}setPosition(t,e){return this.x=t,this.y=e,this}setScale(t){return this.scaleX=t,this.scaleY=t,this}setScaleXY(t,e){return this.scaleX=t,this.scaleY=e,this}static circle(t,e,i){return new Hi({shape:"circle",x:t,y:e,radius:i})}static rectangle(t,e,i,s,n=0){return new Hi({shape:"rectangle",x:t,y:e,width:i,height:s,cornerRadius:n})}static ellipse(t,e,i,s){return new Hi({shape:"ellipse",x:t,y:e,radiusX:i,radiusY:s})}}class Ui{static lerp(t,e,i){return t+(e-t)*i}static lerpAngle(t,e,i){let s=e-t;for(;s<-Math.PI;)s+=2*Math.PI;for(;s>Math.PI;)s-=2*Math.PI;return t+s*i}static tweenColor(t,e,i){return t.map((t,s)=>Ui.lerp(t,e[s],i))}static tweenGradient(t,e,i){let s=t[0],n=e[0];return Math.abs(n-s)>180&&(s<n?s+=360:n+=360),[Ui.lerp(s,n,i)%360,Ui.lerp(t[1],e[1],i),Ui.lerp(t[2],e[2],i)]}}function Gi(t,e,i,s,n,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=os._frame(s,n,o,r,a,h),f=1/(i+1),p=Math.min(Math.floor(c/f),i),g=c%f/f,m=t*Math.pow(.6,p),v=e-Math.sin(g*Math.PI)*(e-m);return os.animationResult({y:v,segment:p,bounceHeight:m},l,o,u,d)}function Ni(t,e,i,s,n,o,r=!0,a=null,h={},l=null){if(i<=0)return os.animationResult({x:t.x,y:t.y,moving:!1},1,!1,!0);l||(l={initialX:t.x,initialY:t.y,started:!1,completed:!1,loopCount:0});const c=l.initialX,u=l.initialY,{t:d,easedT:f,completed:p,state:g}=os._frame(e,i,r,a,h,l);l={...l,...g};const m=e*s,v=Math.max(0,Math.min(1,n)),y=c+(Math.sin(.7*m)+.4*v*Math.sin(2.3*m+.5))*o,_=u+(Math.cos(.9*m)+.4*v*Math.cos(1.9*m+.7))*o,x=.7*Math.cos(.7*m)+.4*v*2.3*Math.cos(2.3*m+.5),b=-.9*Math.sin(.9*m)+.4*v*-1.9*Math.sin(1.9*m+.7),w=Math.sqrt(x*x+b*b),M=w>.8,S=Math.sqrt((y-c)*(y-c)+(_-u)*(_-u));return os.animationResult({x:y,y:_,centerX:c,centerY:u,offsetX:y-c,offsetY:_-u,distance:S,moving:M,velocity:w},d,r,p,l)}function qi(t,e=!1,i,s,n=!1,o=null,r={},a=null){if(!t||t.length<2)return this._createResult({x:0,y:0},0,n,!1);const{t:h,easedT:l,completed:c,state:u}=os._frame(i,s,n,o,r,a);if(!a||!a.pathData){const i={segmentLengths:[],totalLength:0,points:[...t]};for(let e=0;e<t.length-1;e++){const s=t[e],n=t[e+1],o=n[0]-s[0],r=n[1]-s[1],a=Math.sqrt(o*o+r*r);i.segmentLengths.push(a),i.totalLength+=a}if(e){const e=t[t.length-1],s=t[0],n=s[0]-e[0],o=s[1]-e[1],r=Math.sqrt(n*n+o*o);i.segmentLengths.push(r),i.totalLength+=r}u.pathData=i}const{segmentLengths:d,totalLength:f,points:p}=u.pathData,g=l*f;let m=0,v=0;for(let t=0;t<d.length;t++){if(m+d[t]>=g){v=t;break}m+=d[t]}const y=(g-m)/d[v],_=p[v],x=v<p.length-1?p[v+1]:p[0],b=Ui.lerp(_[0],x[0],y),w=Ui.lerp(_[1],x[1],y),M=Math.atan2(x[1]-_[1],x[0]-_[0]);return os.animationResult({x:b,y:w,angle:M,segmentIndex:v,segmentProgress:y,pathProgress:l},h,n,c,u)}function Zi(t,e,i,s,n,o,r,a=!0,h=!0,l=null,c={},u=null){const{t:d,easedT:f,completed:p,state:g}=os._frame(o,r,a,l,c,u),m=n+(h?1:-1)*f*Math.PI*2,v=t+i*Math.cos(m),y=e+s*Math.sin(m);return os.animationResult({x:v,y:y,angle:m},d,a,p,g)}function Vi(t,e,i,s,n=!0,o=null,r={},a=null){const{t:h,easedT:l,completed:c,state:u}=os._frame(i,s,n,o,r,a),d=(e-t)/2,f=t+d+d*Math.sin(l*Math.PI*2);return os.animationResult({value:f},h,n,c,u)}function $i(t,e,i,s,n,o=!1,r=!1,a=null,h={},l=null){l||(l={started:!1,loopCount:0,direction:1,lastDirection:1,completed:!1});let c=n>0?s/n:1,u=!1,d={...h};if(r||o)if(o)if(r){const t=2*n,e=s%t,i=Math.floor(s/t),o=e<n?1:-1;c=1===o?e/n:2-e/n,o!==l.direction&&(l.direction=o,1===l.direction&&d.onLoop&&d.onLoop(i)),i>l.loopCount&&(l.loopCount=i)}else{c%=1;const t=Math.floor(s/n);t>l.loopCount&&d.onLoop&&(d.onLoop(t),l.loopCount=t)}else r&&!o&&(c<=1?l.direction=1:c<=2?(c=2-c,l.direction=-1):(c=0,u=!0,l.direction=1));else c>=1&&(c=1,u=!0);!l.started&&d.onStart&&(d.onStart(),l.started=!0),u&&!l.completed&&d.onComplete&&(d.onComplete(),l.completed=!0);const f=a?a(c):c,p=(t+i-2*e)*f*f+2*(e-t)*f+t,g={...l,lastDirection:l.direction,completed:u||l.completed};return os.animationResult({value:p,direction:l.direction},c,o||r&&!u,u,g)}function ji(t,e,i,s,n,o,r=!0,a=null){a||(a={currentX:t,currentY:e,targetX:t,targetY:e,isWaiting:!0,waitStartTime:0,moveStartTime:0,moveCount:0,direction:"idle"});const h=()=>Math.random();let l=a.isWaiting,c=a.currentX,u=a.currentY,d=a.direction;if(l){if(i-a.waitStartTime>=n){l=!1,a.moveStartTime=i,d=["up","down","left","right"][Math.floor(4*h())];let s=a.currentX,n=a.currentY;const r=o*(.2+.6*h());switch(d){case"up":n=a.currentY-r;break;case"down":n=a.currentY+r;break;case"left":s=a.currentX-r;break;case"right":s=a.currentX+r}Math.pow(s-t,2)+Math.pow(n-e,2)>o*o&&("up"===d||"down"===d?(n=e,d=a.currentY>e?"up":"down"):(s=t,d=a.currentX>t?"left":"right")),a.targetX=s,a.targetY=n,a.direction=d,a.moveCount++}}else{const t=(i-a.moveStartTime)/s;t>=1?(l=!0,a.waitStartTime=i,a.currentX=a.targetX,a.currentY=a.targetY,d="idle"):(c=a.currentX+(a.targetX-a.currentX)*t,u=a.currentY+(a.targetY-a.currentY)*t)}a.isWaiting=l,a.direction=d,l||(a.currentX=c,a.currentY=u);const f=s+n,p=i%f/f,g=Math.sqrt(Math.pow(c-t,2)+Math.pow(u-e,2));return os.animationResult({x:c,y:u,moving:!l,direction:d,distanceFromCenter:g},p,r,!1,a)}function Ki(t,e,i,s,n=!0,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=os._frame(i,s,n,null,a,h),f=o&&!n?Math.exp(-4*l):1;let p=t+e*Math.cos(2*c*Math.PI)*f;return r&&(p=t+r(((p-t)/(e*f)+1)/2)*e*f*2-e*f),os.animationResult({angle:p},l,n,u,d)}function Ji(t,e,i,s,n=!0,o=!1,r=null,a={}){let h,l=i/s,c="forward";if(n){const t=Math.floor(l);l%=1,t>0&&a.onLoop&&a.onLoop(t)}else l>1&&(l=1);if(l>0&&i<=s&&a.onStart&&a.onStart(),o)if(l<.5){const i=2*l;h=t+(e-t)*(r?r(i):i),c="forward"}else{const i=2*(l-.5);h=e-(e-t)*(r?r(i):i),c="return",l>=.5&&l<.51&&a.onYoyoTurn&&a.onYoyoTurn()}else{const i=r?r(l):l;h=t+(e-t)*(i<.5?2*i:2-2*i)}const u=!n&&l>=1;return u&&a.onComplete&&a.onComplete(),os.animationResult({value:h,phase:c},l,n,u)}function Qi(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=os._frame(i,s,n,r,a,h,o);let f=0;f=n||o?o?Math.sin(c*Math.PI):Math.sin(Math.min(l,1)*Math.PI*.5):u?1:Math.sin(Math.min(l,1)*Math.PI*.5);const p=t-e*f;return os.animationResult({y:p},l,n,u,d)}function ts(t,e,i,s,n,o,r,a,h=!1,l=null,c={},u=null){const{t:d,easedT:f,completed:p,state:g}=os._frame(r,a,h,l,c,u),m=Math.pow(1-f,o),v=f*Math.PI*2*n,y=f*Math.PI*2*n*1.3,_=m*i*(.6*Math.sin(v)+.3*Math.sin(2.5*v)+.1*Math.sin(5.6*v)),x=m*s*(.6*Math.cos(y)+.3*Math.cos(2.7*y)+.1*Math.cos(6.3*y));let b=t+_,w=e+x;if(f>.9){const i=(f-.9)/.1;b=t+_*(1-i),w=e+x*(1-i)}return os.animationResult({x:b,y:w,intensity:m},d,h,p,g)}function es(t,e,i,s,n,o,r,a,h=!1,l=!1,c=null,u={},d=null){d||(d={started:!1,loopCount:0,direction:1,lastDirection:1});let f=a>0?r/a:1,p=!1,g={...u};if(l||h)if(h)if(l){const t=2*a,e=r%t,i=Math.floor(r/t),s=e<a?1:-1;f=1===s?e/a:2-e/a,s!==d.direction&&(d.direction=s,1===d.direction&&g.onLoop&&g.onLoop(i)),i>d.loopCount&&(d.loopCount=i)}else{f%=1;const t=Math.floor(r/a);t>d.loopCount&&g.onLoop&&(g.onLoop(t),d.loopCount=t)}else l&&!h&&(f<=1?d.direction=1:f<=2?(f=2-f,d.direction=-1):(f=0,p=!0,d.direction=1));else f>=1&&(f=1,p=!0);!d.started&&g.onStart&&(g.onStart(),d.started=!0),p&&!d.completed&&g.onComplete&&(g.onComplete(),d.completed=!0);const m=c?c(f):f,v=Ui.lerp(i,s,m),y=n+m*o*Math.PI*2,_=t+v*Math.cos(y),x=e+v*Math.sin(y),b={...d,lastDirection:d.direction};return os.animationResult({x:_,y:x,radius:v,angle:y,direction:d.direction},f,h||l&&!p,p,b)}function is(t,e,i,s,n=!1,o=!1,r={},a={}){if(s<=0)return this.animationResult({value:e,velocity:0,done:!0,phase:"complete"},1,!1,!0);let h,l,c,u=i/s,d="forward",f=0;n?(f=Math.floor(u),u%=1,f>0&&a.onLoop&&a.onLoop(f)):u>1&&(u=1),u>0&&i<=s&&a.onStart&&a.onStart(),o?u>=.5?(h=t,l=e,c=2*(u-.5),d="return",u>=.5&&u<.51&&a.onYoyoTurn&&a.onYoyoTurn()):(h=e,l=t,c=2*u,d="forward"):(h=e,l=t,c=u);const p=void 0!==r.stiffness?r.stiffness:.3,g=void 0!==r.damping?r.damping:.6,m=Math.max(.1,1/(1.5*g)),v=Math.max(.1,.8/(1.5*p+.5));let y;if(c<.99)y=oe.easeOutElastic(c,m,v);else{const t=(c-.99)/.01;y=oe.easeOutElastic(.99,m,v)*(1-t)+1*t}const _=Ui.lerp(l,h,y),x=Math.min(c+.01,1);let b;if(x<.99)b=oe.easeOutElastic(x,m,v);else{const t=(x-.99)/.01;b=oe.easeOutElastic(.99,m,v)*(1-t)+1*t}const w=(Ui.lerp(l,h,b)-_)/.01*s,M=!n&&u>=1;return M&&a.onComplete&&a.onComplete(),os.animationResult({value:_,velocity:w,delta:"forward"===d?e-_:t-_,done:M,phase:d},u,n,M)}function ss(t,e,i,s,n,o=!0,r=!0,a=null,h={},l=null){const{t:c,easedT:u,completed:d,state:f}=os._frame(s,n,o,a,h,l),p=(r?Math.sin(u*Math.PI*2):Math.sin(u*Math.PI))*i;return os.animationResult({angle:p},c,o,d,f)}function ns(t,e,i,s,n,o=!0,r={},a=null){if(!i||!Array.isArray(i)||i.length<2)return console.warn("Patrol animation requires at least 2 waypoints"),os._createResult({x:0,y:0,moving:!1,direction:"idle",waypoint:0},0,!1,!0);a||(a={currentWaypoint:0,nextWaypoint:1,isWaiting:!0,waitStartTime:0,lastWaypointTime:0,lastWaypointReached:-1,completed:!1});let h=0;for(let t=0;t<i.length;t++){const e=(t+1)%i.length;if(!o&&t===i.length-1)break;const s=i[e][0]-i[t][0],n=i[e][1]-i[t][1];h+=Math.abs(s)+Math.abs(n)}const l=h/s+n*i.length;let c=e;c=o?e%l:Math.min(e,l);const u=c/l;let d,f,p,g=c,m=0,v=1,y=!0,_=0,x=0,b=!1;if(g<n)_=g/n,m=0,v=1,y=!0;else{g-=n;for(let t=0;t<i.length;t++){if(!o&&t===i.length-1){m=t,v=t,y=!0,_=1,b=!0;break}const e=(t+1)%i.length,h=i[e][0]-i[t][0],l=i[e][1]-i[t][1],c=(Math.abs(h)+Math.abs(l))/s;if(g<c){m=t,v=e,y=!1,x=g/c;break}if(g-=c,g<n){m=e,v=(e+1)%i.length,y=!0,_=g/n,a.lastWaypointReached!==m&&(r.onWaypointReached&&r.onWaypointReached(m),r.onWaitStart&&r.onWaitStart(m),a.lastWaypointReached=m);break}g-=n}}if(y||b)d=i[m][0],f=i[m][1],p="idle",!a.isWaiting&&y&&r.onWaitEnd&&r.onWaitEnd(m);else{const t=i[m],e=i[v],s=e[0]-t[0],n=e[1]-t[1],o=Math.abs(s)+Math.abs(n),r=Math.abs(s)/o;if(x<=r&&0!==s){const e=x/r;d=t[0]+s*e,f=t[1],p=s>0?"right":"left"}else{const i=(x-r)/(1-r);d=e[0],f=t[1]+n*i,p=n>0?"down":"up"}}return a.currentWaypoint=m,a.nextWaypoint=v,a.isWaiting=y,!a.completed&&b&&r.onPatrolComplete&&(r.onPatrolComplete(),a.completed=!0),os.animationResult({x:d,y:f,moving:!y,waiting:y,waitProgress:y?_:0,direction:p,waypoint:m,nextWaypoint:v},u,o,b,a)}class os{static animationResult(t,e,i,s=!1,n=null){return{...t,t:e,progress:e,loop:i,completed:s,state:n}}static _step(t,e,i,s={},n={started:!1,loopCount:0}){let o=e>0?t/e:1,r=!1;if(!(n=n||{started:!1,loopCount:0}).started&&s.onStart&&(s.onStart(),n.started=!0),i){o%=1;const i=Math.floor(t/e);i>n.loopCount&&s.onLoop&&(s.onLoop(i),n.loopCount=i)}else o>=1&&(o=1,r=!0,!n.completed&&s.onComplete&&(s.onComplete(),n.completed=!0));return{t:o,completed:r,state:n}}static _frame(t,e,i,s=null,n={},o=null){const{t:r,completed:a,state:h}=this._step(t,e,i,n,o);return{t:r,easedT:s?s(r):r,completed:a,state:h}}static oscillate(t,e,i,s,n=!0,o=null,r={},a=null){return Vi(t,e,i,s,n,o,r,a)}static parabolic(t,e,i,s,n,o=!1,r=!1,a=null,h={},l=null){return $i(t,e,i,s,n,o,r,a,h,l)}static float(t,e,i,s,n,o,r=!0,a=null,h={},l=null){return Ni(t,e,i,s,n,o,r,a,h,l)}static spring(t,e,i,s,n=!1,o=!1,r={},a={}){return is(t,e,i,s,n,o,r,a)}static swing(t,e,i,s,n,o=!0,r=!0,a=null,h={},l=null){return ss(0,0,i,s,n,o,r,a,h,l)}static pendulum(t,e,i,s,n=!0,o=!1,r=null,a={},h=null){return Ki(t,e,i,s,n,o,r,a,h)}static pulse(t,e,i,s,n=!0,o=!1,r=null,a={}){return Ji(t,e,i,s,n,o,r,{})}static spiral(t,e,i,s,n,o,r,a,h=!1,l=!1,c=null,u={},d=null){return es(t,e,i,s,n,o,r,a,h,l,c,u,d)}static orbit(t,e,i,s,n,o,r,a=!0,h=!0,l=null,c={},u=null){return Zi(t,e,i,s,n,o,r,a,h,l,c,u)}static bezier(t,e,i,s,n,o,r=!1,a=!1,h=null,l={},c=null){return rs(t,e,i,s,n,o,r,a,h,l,c)}static bounce(t,e,i,s,n,o=!1,r=null,a={},h=null){return Gi(t,e,i,s,n,o,r,a,h)}static shake(t,e,i,s,n,o,r,a,h=!1,l=null,c={},u=null){return ts(t,e,i,s,n,o,r,a,h,l,c,u)}static follow(t,e=!1,i,s,n=!1,o=null,r={},a=null){return qi(t,e,i,s,n,o,r,a)}static waypoint(t,e,i,s,n,o=!0,r={},a=null){return ns(0,e,i,s,n,o,r,a)}static patrol(t,e,i,s,n,o,r=!0,a=null){return ji(t,e,i,s,n,o,r,a)}static hop(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){return Qi(t,e,i,s,n,o,r,a,h)}static group(t,e,i,s,n=!1,o=null,r={},a=null){a||(a={started:!1,loopCount:0,animationStates:Array(t.length).fill(null)});const{t:h,easedT:l,completed:c,state:u}=this._frame(i,s,n,o,r,a),d={};for(let a=0;a<t.length;a++){const h=t[a],l=[...e[a]];h===this.parabolic||h===this.oscillate||h===this.pulse?(l[3]=i,l[4]=s,l[5]=n,void 0===l[6]&&(l[6]=o)):h===this.spring?(l[2]=i,l[3]=s,l[4]=n):h===this.spiral||h===this.bezier?(l[6]=i,l[7]=s,l[8]=n,void 0===l[9]&&(l[9]=o)):h===this.orbit?(l[5]=i,l[6]=s,l[7]=n,void 0===l[9]&&(l[9]=o)):h===this.bounce||h===this.shake?(l[6]=i,l[7]=s,l[8]=n,void 0===l[9]&&(l[9]=o)):h===this.followPath&&(l[2]=i,l[3]=s,l[4]=n,void 0===l[5]&&(l[5]=o)),l.push(r),l.push(u.animationStates[a]);const c=h.apply(this,l);u.animationStates[a]=c.state,d[`anim${a}`]=c}return this.animationResult(d,h,n,c,u)}static sequence(t,e,i,s,n=!1,o=null,r={},a=null,h=null){if(!h){h={started:!1,loopCount:0,animationStates:Array(t.length).fill(null),currentAnim:0,animStartTimes:[0],totalDuration:0};let e=0;for(let t=0;t<i.length;t++)e+=i[t],t<i.length-1&&h.animStartTimes.push(e);h.totalDuration=e}let l=s;if(n&&h.totalDuration>0){l=s%h.totalDuration;const t=Math.floor(s/h.totalDuration);t>h.loopCount&&r.onLoop&&(r.onLoop(t),h.loopCount=t)}!h.started&&r.onStart&&(r.onStart(),h.started=!0);let c=0;for(let e=t.length-1;e>=0;e--)if(l>=h.animStartTimes[e]){c=e;break}h.currentAnim=c;const u=l-h.animStartTimes[c],d=i[c],f=t[c],p=[...e[c]];f===this.parabolic||f===this.oscillate||f===this.pulse?(p[3]=u,p[4]=d,p[5]=!1,o&&o[c]&&(p[6]=o[c])):f===this.spring?(p[2]=u,p[3]=d,p[4]=!1):f===this.spiral||f===this.bezier?(p[6]=u,p[7]=d,p[8]=!1,o&&o[c]&&(p[9]=o[c])):f===this.orbit?(p[5]=u,p[6]=d,p[7]=!1,o&&o[c]&&(p[9]=o[c])):f===this.bounce||f===this.shake?(p[6]=u,p[7]=d,p[8]=!1,o&&o[c]&&(p[9]=o[c])):f===this.followPath&&(p[2]=u,p[3]=d,p[4]=!1,o&&o[c]&&(p[5]=o[c]));const g=a&&a[c]?a[c]:{},m=f.apply(this,[...p,g,h.animationStates[c]]);h.animationStates[c]=m.state;const v=!n&&l>=h.totalDuration;return v&&!h.completed&&r.onComplete&&(r.onComplete(),h.completed=!0),this.animationResult({...m,currentAnim:c,totalAnimations:t.length,sequenceProgress:Math.min(l/h.totalDuration,1)},l/h.totalDuration,n,v,h)}}function rs(t,e,i,s,n,o,r=!1,a=!1,h=null,l={},c=null){if(o<=0)return os.animationResult({x:s[0],y:s[1],phase:"complete"},1,!1,!0);let u=n/o,d="forward",f=0;r?(f=Math.floor(u),u%=1,f>0&&l.onLoop&&l.onLoop(f)):u>1&&(u=1),u>0&&n<=o&&l.onStart&&l.onStart();let p=h?h(u):u;a&&(u>=.5?(p=1-2*(u-.5),d="return",u>=.5&&u<.51&&l.onYoyoTurn&&l.onYoyoTurn()):(p=2*u,d="forward"),p=h?h(p):p);const g=3*(e[0]-t[0]),m=3*(i[0]-e[0])-g,v=s[0]-t[0]-g-m,y=3*(e[1]-t[1]),_=3*(i[1]-e[1])-y,x=s[1]-t[1]-y-_,b=v*Math.pow(p,3)+m*Math.pow(p,2)+g*p+t[0],w=x*Math.pow(p,3)+_*Math.pow(p,2)+y*p+t[1],M=!r&&u>=1;return M&&l.onComplete&&l.onComplete(),os.animationResult({x:b,y:w,phase:d},u,r,M,c)}class as{constructor(t,e,i,s,n={}){this.target=t,this.toProps={...e},this.duration=i,this.easingFn=s||oe.easeOutQuad,this.delay=n.delay||0,this.onStart=n.onStart||null,this.onComplete=n.onComplete||null,this.onUpdate=n.onUpdate||null,this._elapsed=0,this._started=!1,this._finished=!1,this._startProps={};for(const t in this.toProps)t in this.target&&(this._startProps[t]=this.target[t])}static to(t,e,i,s,n){const o=new as(t,e,i,s,n);return as._active.push(o),o}update(t){if(this._finished)return;if(this._elapsed+=t,this._elapsed<this.delay)return;const e=this._elapsed-this.delay,i=Math.min(e/this.duration,1);!this._started&&i>0&&(this._started=!0,this.onStart&&this.onStart());const s=this.easingFn(i);for(const t in this._startProps){const e=this._startProps[t],i=this.toProps[t];this.target[t]=Ui.lerp(e,i,s)}this.onUpdate&&this.onUpdate(),i>=1&&(this._finished=!0,this.onComplete&&this.onComplete())}static updateAll(t){for(const e of as._active)e.update(t);as._active=as._active.filter(t=>!t._finished)}static killTarget(t){as._active=as._active.filter(e=>e.target!==t)}static killAll(){as._active=[]}}class hs extends ke{constructor(t){super(),this.game=t,this._collection=new Ct,this._collection._owner=this,["inputdown","inputup","inputmove","click"].forEach(t=>{this.game.events.on(t,e=>{this.dispatchInputEvent(t,e)})})}_hoverObject(t,e){if(!t.interactive||!t._hitTest)return;const i=t._hitTest(e.x,e.y);i&&!t._hovered?(t._hovered=!0,t.events.emit("mouseover",e)):!i&&t._hovered&&(t._hovered=!1,t.events.emit("mouseout",e))}_hoverScene(t,e){if(t.children&&t.children.length>0)for(let i=t.children.length-1;i>=0;i--){const s=t.children[i];!t.isChildHittable||t.isChildHittable(s)?s instanceof Oi?this._hoverScene(s,e):this._hoverObject(s,e):s._hovered&&(s._hovered=!1,s.events.emit("mouseout",e))}this._hoverObject(t,e)}dispatchInputEvent(t,e){var i;for(let s=this.gameObjects.length-1;s>=0;s--){const n=this.gameObjects[s];if(n instanceof Oi){if(this._dispatchToScene(n,t,e))break}else if(n.interactive&&(null==(i=n._hitTest)?void 0:i.call(n,e.x,e.y))){n.events.emit(t,e);break}}"inputmove"===t&&this._dispatchHover(e)}_dispatchHover(t){for(let e=this.gameObjects.length-1;e>=0;e--){const i=this.gameObjects[e];i instanceof Oi?this._hoverScene(i,t):this._hoverObject(i,t)}}_dispatchToScene(t,e,i){var s,n;for(let n=t.children.length-1;n>=0;n--){const o=t.children[n];if(!t.isChildHittable||t.isChildHittable(o))if(o instanceof Oi){if(this._dispatchToScene(o,e,i))return!0}else if(o.interactive&&(null==(s=o._hitTest)?void 0:s.call(o,i.x,i.y)))return o.events.emit(e,i),!0}return!(!t.interactive||!(null==(n=t._hitTest)?void 0:n.call(t,i.x,i.y))||(t.events.emit(e,i),0))}add(t){t.parent=this.game;const e=this._collection.add(t);return e.init&&e.init(),e}remove(t){null!=t?this._collection.remove(t):this.logger.warn("Cannot remove undefined or null object",t)}bringToFront(t){return this._collection.bringToFront(t)}sendToBack(t){return this._collection.sendToBack(t)}bringForward(t){return this._collection.bringForward(t)}sendBackward(t){return this._collection.sendBackward(t)}clear(){return this._collection.clear()}get gameObjects(){return this._collection.children}update(t){this.logger.groupCollapsed("Pipeline.update"),this._collection.children.filter(t=>t.active).forEach(e=>e.update(t)),as.updateAll(t),this.logger.groupEnd()}render(){this.logger.groupCollapsed("Pipeline.render"),this._collection.getSortedChildren().filter(t=>t.visible).filter(t=>t.active).forEach(t=>t.render()),this.logger.groupEnd()}}class ls{constructor(t){wt(this,k,0),wt(this,P,0),this.canvas=t,this.ctx=t.getContext("2d"),this.events=new Si,this._cursor=null,this.lastTime=0,this.dt=0,this.running=!1,this._frame=0,this.pipeline=new hs(this),Le.init(this.ctx),this.targetFPS=60,this._frameInterval=1e3/this.targetFPS,this._accumulator=0,this._pauseOnBlur=!1,this._isPaused=!1,this._init=!1,this.initLogging()}setFPS(t){this.targetFPS=t,this._frameInterval=1e3/t}init(){this.initIO(),this.initMotion(),this._init=!0,this.logger.log("[Game] Initialized")}initMouse(){ki.init(this)}initTouch(){zi.init(this)}initInput(){Ci.init(this)}initKeyboard(){Ri.init(this)}initIO(){this.initMouse(),this.initTouch(),this.initInput(),this.initKeyboard()}initMotion(){as._active=[]}initLogging(){this.logger=new Te("Game"),Te.setOutput(console),Te.disableAll(),Te.disable(),Te.setLevel(Te.INFO),this.logger.groupCollapsed("Initializing Game...")}enableLogging(){Te.enable()}disableLogging(){Te.disableAll(),Te.disable()}markBoundsDirty(){this._boundsDirty=!0}get boundsDirty(){return this._boundsDirty}set boundsDirty(t){this._boundsDirty=t}enableFluidSize(t=window,e={}){const{top:i=0,right:s=0,bottom:n=0,left:o=0}=e;if(t===window){const t=()=>{var t;this.canvas.width=window.innerWidth-o-s,this.canvas.height=window.innerHeight-i-n,bt(this,k)===this.canvas.width&&bt(this,P)===this.canvas.height||(this.markBoundsDirty(),null==(t=this.onResize)||t.call(this)),Mt(this,k,this.canvas.width),Mt(this,P,this.canvas.height)};t(),window.addEventListener("resize",t),this._fluidResizeCleanup=()=>{window.removeEventListener("resize",t)}}else{if(!("ResizeObserver"in window))return void console.warn("ResizeObserver not supported in this browser.");const e=()=>{const e=t.getBoundingClientRect();this.canvas.width=e.width-o-s,this.canvas.height=e.height-i-n},r=new ResizeObserver(()=>{e()});r.observe(t),e(),this._fluidResizeCleanup=()=>r.disconnect()}}disableFluidSize(){this._fluidResizeCleanup&&(this._fluidResizeCleanup(),this._fluidResizeCleanup=null)}start(){if(this.logger.groupCollapsed("[Game] Starting..."),this.init(),!this._init)throw new Error("Game not initialized. Did you call init()? Remember to call super.init() in your subclass.");this.running=!0,this.loop=this.loop.bind(this),requestAnimationFrame(this.loop),this.logger.log("[Game] Started"),this.logger.groupEnd()}stop(){this.running=!1,this.logger.log("[Game] Stopped")}restart(){this.pipeline.clear(),this.init(),this.start(),this.logger.log("[Game] Restarted")}loop(t){if(!this.running)return;const e=t-this.lastTime;if(this.lastTime=t,this._accumulator+=e,this.actualFps=1e3/e,this._accumulator>=this._frameInterval){const t=this._frameInterval/1e3;this.dt=t,this._frame++,this.logger.groupCollapsed(`Frame #${this._frame}`),this.logger.time("render time"),this.update(t),this.render(),this.logger.timeEnd("render time"),this.logger.groupEnd(),this._accumulator-=this._frameInterval}this.boundsDirty&&(this.boundsDirty=!1),requestAnimationFrame(this.loop)}update(t){this.pipeline.update(t)}render(){Le.setContext(this.ctx),this.running&&this.clear(),this.pipeline.render()}clear(){Le.clear()}get width(){return this.canvas.width}get height(){return this.canvas.height}set backgroundColor(t){this.canvas.style.backgroundColor=t}set cursor(t){this._cursor&&(this._cursor.destroy(),this.pipeline.remove(this._cursor)),this._cursor=t,this._cursor.activate(),this.pipeline.add(t)}get cursor(){return this._cursor}resetCursor(){this._cursor&&(this._cursor.destroy(),this.pipeline.remove(this._cursor),this._cursor=null)}enablePauseOnBlur(t){this._pauseOnBlur=t,t?window.addEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1):window.removeEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1)}_handleVisibilityChange(){this.logger.log("Visibility change detected"),document.hidden?this._pauseOnBlur&&this.running&&(this._isPaused=!0,this.stop(),this.logger.log("Paused due to tab visibility change")):this._isPaused&&(this._isPaused=!1,this.start(),this.logger.log("Resumed after tab visibility change"))}}k=new WeakMap,P=new WeakMap;const cs={colors:{neonGreen:"#0f0",terminalGreen:"#16F529",cyanAccent:"#0ff",darkBg:"rgba(0, 0, 0, 0.85)",darkerBg:"rgba(0, 0, 0, 0.92)",hoverBg:"#0f0",pressedBg:"#0c0",activeBg:"rgba(0, 255, 0, 0.15)",lightText:"#0f0",darkText:"#000",dimText:"rgba(0, 255, 0, 0.7)",subtleBorder:"rgba(0, 255, 0, 0.4)",activeBorder:"#0f0",glowBorder:"rgba(0, 255, 0, 0.5)"},fonts:{primary:"monospace",small:"11px monospace",medium:"14px monospace",large:"18px monospace",heading:"bold 24px monospace"},spacing:{xs:4,sm:8,md:12,lg:16,xl:24},button:{default:{bg:"rgba(0, 0, 0, 0.85)",stroke:"rgba(0, 255, 0, 0.4)",text:"#0f0"},hover:{bg:"#0f0",stroke:"#0f0",text:"#000"},pressed:{bg:"#0c0",stroke:"#0f0",text:"#000"},active:{bg:"rgba(0, 255, 0, 0.15)",stroke:"#0f0",text:"#0f0"}},tooltip:{bg:"rgba(0, 0, 0, 0.92)",border:"rgba(0, 255, 0, 0.5)",text:"#0f0"}};class us extends Ei{constructor(t,e={}){super(t,e);const{x:i=0,y:s=0,width:n=120,height:o=40,text:r="Button",font:a="14px monospace",textColor:h="#000",textAlign:l="center",textBaseline:c="middle",shape:u=null,label:d=null,onClick:f=null,onHover:p=null,onPressed:g=null,onRelease:m=null,padding:v=10,colorDefaultBg:y=cs.button.default.bg,colorDefaultStroke:_=cs.button.default.stroke,colorDefaultText:x=cs.button.default.text,colorHoverBg:b=cs.button.hover.bg,colorHoverStroke:w=cs.button.hover.stroke,colorHoverText:M=cs.button.hover.text,colorPressedBg:S=cs.button.pressed.bg,colorPressedStroke:C=cs.button.pressed.stroke,colorPressedText:T=cs.button.pressed.text}=e;this.x=i,this.y=s,this.width=Math.max(n,44),this.height=Math.max(o,44),this.padding=v,this.textAlign=l,this.textBaseline=c,this.initColorScheme({colorDefaultBg:y,colorDefaultStroke:_,colorDefaultText:x,colorHoverBg:b,colorHoverStroke:w,colorHoverText:M,colorPressedBg:S,colorPressedStroke:C,colorPressedText:T}),this.initBackground(u),this.initLabel(r,a,h,d),this.initGroup(),this.initEvents(f,p,g,m),this.setState("default")}initColorScheme(t){this.colors={default:{bg:t.colorDefaultBg,stroke:t.colorDefaultStroke,text:t.colorDefaultText},hover:{bg:t.colorHoverBg,stroke:t.colorHoverStroke,text:t.colorHoverText},pressed:{bg:t.colorPressedBg,stroke:t.colorPressedStroke,text:t.colorPressedText}}}initBackground(t){this.bg=t??new Je({width:this.width,height:this.height,color:this.colors.default.bg,stroke:this.colors.default.stroke,lineWidth:2})}initLabel(t,e,i,s){this.label=s??new wi(t,{font:e,color:i,align:this.textAlign,baseline:this.textBaseline}),this.alignText()}alignText(){if(!this.label)return;const t=this.width/2,e=this.height/2,i=(this.label._width||0)/2,s=(this.label._height||0)/2;switch(this.textAlign){case"left":this.label.x=-t+this.padding+i;break;case"right":this.label.x=t-this.padding-i;break;default:this.label.x=0}switch(this.textBaseline){case"top":this.label.y=-e+this.padding+s;break;case"bottom":this.label.y=e-this.padding-s;break;default:this.label.y=0}}initGroup(){this.group=new Ve,this.group.add(this.bg),this.group.add(this.label)}initEvents(t,e,i,s){this.interactive=!0,this.onHover=e,this.onPressed=i,this.onRelease=s,this._pointerOver=!1,this._isTouch=!1,this.on("mouseover",t=>{this._pointerOver=!0,this._isTouch||this.setState("hover")}),this.on("mouseout",t=>{this._pointerOver=!1,this._isTouch||this.setState("default")}),this.on("inputdown",t=>{(t.touches||t.nativeEvent&&"touchstart"===t.nativeEvent.type)&&(this._isTouch=!0,t.nativeEvent&&t.nativeEvent.preventDefault()),this._pointerOver=!0,this.setState("pressed")}),this.on("inputup",e=>{const i="pressed"===this.state;(e.touches||e.nativeEvent&&"touchend"===e.nativeEvent.type)&&(e.nativeEvent&&e.nativeEvent.preventDefault(),this._isTouch=!0);const s=this._hitTest&&this._hitTest(e.x,e.y);i&&s&&"function"==typeof t&&t(),s&&!this._isTouch?this.setState("hover"):(this.setState("default"),this._isTouch&&setTimeout(()=>{this._isTouch=!1},300))}),this.on("inputmove",t=>{this._hitTest&&this._hitTest(t.x,t.y)?this._pointerOver=!0:(this._pointerOver=!1,"hover"!==this.state||this._isTouch||this.setState("default"))})}setState(t){var e,i,s;if(this.state!==t)switch(this.state=t,t){case"default":this.game.cursor&&setTimeout(()=>{this.game.cursor.activate()},0),this.bg.color=this.colors.default.bg,this.bg.stroke=this.colors.default.stroke,this.label.color=this.colors.default.text,this.game.canvas.style.cursor="default",null==(e=this.onRelease)||e.call(this);break;case"hover":this.game.cursor&&this.game.cursor.deactivate(),this.bg.color=this.colors.hover.bg,this.bg.stroke=this.colors.hover.stroke,this.label.color=this.colors.hover.text,this.game.canvas.style.cursor="pointer",null==(i=this.onHover)||i.call(this);break;case"pressed":this.game.cursor&&this.game.cursor.deactivate(),this.bg.color=this.colors.pressed.bg,this.bg.stroke=this.colors.pressed.stroke,this.label.color=this.colors.pressed.text,this.game.canvas.style.cursor="pointer",null==(s=this.onPressed)||s.call(this)}}update(t){super.update(t),this._boundsDirty&&this.alignText()}get text(){return this.label.text}set text(t){this.label.text=t,this._boundsDirty=!0}setTextAlign(t){this.textAlign=t,this.label.align=t,this._boundsDirty=!0}setTextBaseline(t){this.textBaseline=t,this.label.baseline=t,this._boundsDirty=!0}setFont(t){this.label.font=t,this._boundsDirty=!0}resize(t,e){this.width=t,this.height=e,this.bg.width=t,this.bg.height=e,this._boundsDirty=!0}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}draw(){super.draw(),this.group.render()}}class ds{constructor(){this.x=0,this.y=0,this.z=0,this.vx=0,this.vy=0,this.vz=0,this.size=1,this.color={r:255,g:255,b:255,a:1},this.shape="circle",this.age=0,this.lifetime=1,this.alive=!0,this.custom={}}reset(){this.x=0,this.y=0,this.z=0,this.vx=0,this.vy=0,this.vz=0,this.size=1,this.color.r=255,this.color.g=255,this.color.b=255,this.color.a=1,this.shape="circle",this.age=0,this.lifetime=1,this.alive=!0;for(const t in this.custom)delete this.custom[t]}get progress(){return this.lifetime>0?this.age/this.lifetime:1}}class fs{constructor(t={}){this.rate=t.rate??10,this.position={x:0,y:0,z:0,...t.position},this.spread={x:0,y:0,z:0,...t.spread},this.velocity={x:0,y:0,z:0,...t.velocity},this.velocitySpread={x:0,y:0,z:0,...t.velocitySpread},this.lifetime={min:1,max:2,...t.lifetime},this.size={min:1,max:1,...t.size},this.color={r:255,g:255,b:255,a:1,...t.color},this.shape=t.shape??"circle",this.active=!1!==t.active,this._timer=0}_spread(t){return 2*(Math.random()-.5)*t}_range(t,e){return t+Math.random()*(e-t)}emit(t){t.x=this.position.x+this._spread(this.spread.x),t.y=this.position.y+this._spread(this.spread.y),t.z=this.position.z+this._spread(this.spread.z),t.vx=this.velocity.x+this._spread(this.velocitySpread.x),t.vy=this.velocity.y+this._spread(this.velocitySpread.y),t.vz=this.velocity.z+this._spread(this.velocitySpread.z),t.lifetime=this._range(this.lifetime.min,this.lifetime.max),t.age=0,t.alive=!0,t.size=this._range(this.size.min,this.size.max),t.color.r=this.color.r,t.color.g=this.color.g,t.color.b=this.color.b,t.color.a=this.color.a,t.shape=this.shape}update(t){if(!this.active||this.rate<=0)return 0;this._timer+=t;const e=1/this.rate;let i=0;for(;this._timer>=e;)this._timer-=e,i++;return i}reset(){this._timer=0}}const ps={velocity:(t,e)=>{t.x+=t.vx*e,t.y+=t.vy*e,t.z+=t.vz*e},lifetime:(t,e)=>{t.age+=e,t.age>=t.lifetime&&(t.alive=!1)},gravity:(t=200)=>(e,i)=>{e.vy+=t*i},rise:(t=100)=>(e,i)=>{e.vy-=t*i},damping:(t=.98)=>(e,i)=>{e.vx*=t,e.vy*=t,e.vz*=t},fadeOut:(t,e)=>{t.color.a=Math.max(0,1-t.progress)},fadeInOut:(t,e)=>{const i=t.progress;t.color.a=i<.5?2*i:2*(1-i)},shrink:(t=0)=>(e,i)=>{void 0===e.custom._initialSize&&(e.custom._initialSize=e.size),e.size=e.custom._initialSize*(1-e.progress*(1-t))},grow:(t=2)=>(e,i)=>{void 0===e.custom._initialSize&&(e.custom._initialSize=e.size),e.size=e.custom._initialSize*(1+e.progress*(t-1))},colorOverLife:(t,e)=>(i,s)=>{const n=i.progress;i.color.r=Math.floor(t.r+(e.r-t.r)*n),i.color.g=Math.floor(t.g+(e.g-t.g)*n),i.color.b=Math.floor(t.b+(e.b-t.b)*n)},wobble:(t=10)=>(e,i)=>{e.vx+=(Math.random()-.5)*t*i,e.vy+=(Math.random()-.5)*t*i},bounds:(t,e=.8)=>(i,s)=>{i.x<t.left?(i.x=t.left,i.vx=Math.abs(i.vx)*e):i.x>t.right&&(i.x=t.right,i.vx=-Math.abs(i.vx)*e),i.y<t.top?(i.y=t.top,i.vy=Math.abs(i.vy)*e):i.y>t.bottom&&(i.y=t.bottom,i.vy=-Math.abs(i.vy)*e)},attract:(t,e=100)=>(i,s)=>{const n=t.x-i.x,o=t.y-i.y,r=(t.z??0)-i.z,a=Math.sqrt(n*n+o*o+r*r);if(a>1){const t=e*s/a;i.vx+=n*t,i.vy+=o*t,i.vz+=r*t}}},gs="\nprecision highp float;\n\nattribute vec2 aPosition; // Screen position (pixels, already projected)\nattribute float aSize; // Point size in pixels\nattribute vec4 aColor; // RGBA color (0-1 range)\n\nvarying vec4 vColor;\n\nuniform vec2 uResolution; // Canvas dimensions\n\nvoid main() {\n // Convert from pixel coords to clip space (-1 to 1)\n vec2 clipPos = (aPosition / uResolution) * 2.0 - 1.0;\n clipPos.y = -clipPos.y; // Flip Y (canvas Y is down, GL Y is up)\n\n gl_Position = vec4(clipPos, 0.0, 1.0);\n gl_PointSize = aSize;\n vColor = aColor;\n}\n",ms="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n // gl_PointCoord is 0-1 UV within the point quad\n vec2 coord = gl_PointCoord - vec2(0.5);\n float dist = length(coord);\n\n // Discard pixels outside circle\n if (dist > 0.5) {\n discard;\n }\n\n // Soft edge for anti-aliasing\n float alpha = vColor.a * (1.0 - smoothstep(0.4, 0.5, dist));\n gl_FragColor = vec4(vColor.rgb, alpha);\n}\n",vs="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n vec2 coord = gl_PointCoord - vec2(0.5);\n float dist = length(coord);\n\n if (dist > 0.5) {\n discard;\n }\n\n // Radial falloff for glow effect\n float glow = 1.0 - (dist * 2.0);\n glow = glow * glow; // Quadratic falloff\n\n float alpha = vColor.a * glow;\n vec3 color = vColor.rgb * (0.5 + glow * 0.5); // Brighten center\n\n gl_FragColor = vec4(color, alpha);\n}\n",ys="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n gl_FragColor = vColor;\n}\n",_s="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n vec2 coord = abs(gl_PointCoord - vec2(0.5)) * 2.0; // 0 at center, 1 at edge\n float d = max(coord.x, coord.y);\n\n // Soft edge\n float alpha = vColor.a * (1.0 - smoothstep(0.8, 1.0, d));\n gl_FragColor = vec4(vColor.rgb, alpha);\n}\n",xs={circle:{vertex:gs,fragment:ms},glow:{vertex:gs,fragment:vs},square:{vertex:gs,fragment:ys},softSquare:{vertex:gs,fragment:_s}};class bs{constructor(t=1e4,e={}){if(this.maxParticles=t,this.width=e.width||800,this.height=e.height||600,this.shape=e.shape||"circle",this.blendMode=e.blendMode||"alpha",this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!1,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for particle rendering"),void(this.available=!1);this.available=!0,this._positions=new Float32Array(2*t),this._sizes=new Float32Array(t),this._colors=new Float32Array(4*t),this._initGL(),this._createBuffers(),this._compileShaders(),this._setupBlending()}isAvailable(){return this.available}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}_createBuffers(){const t=this.gl;this.positionBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this._positions,t.DYNAMIC_DRAW),this.sizeBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.sizeBuffer),t.bufferData(t.ARRAY_BUFFER,this._sizes,t.DYNAMIC_DRAW),this.colorBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.colorBuffer),t.bufferData(t.ARRAY_BUFFER,this._colors,t.DYNAMIC_DRAW)}_compileShaders(){const t=this.gl;let e;switch(this.shape){case"glow":e=vs;break;case"square":e=ys;break;case"softSquare":e=_s;break;default:e=ms}const i=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(i,gs),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))return console.error("Vertex shader error:",t.getShaderInfoLog(i)),void(this.available=!1);const s=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(s,e),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,i),t.attachShader(this.program,s),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.aSize=t.getAttribLocation(this.program,"aSize"),this.aColor=t.getAttribLocation(this.program,"aColor"),this.uResolution=t.getUniformLocation(this.program,"uResolution"),t.uniform2f(this.uResolution,this.width,this.height),t.deleteShader(i),void t.deleteShader(s)):(console.error("Program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("Fragment shader error:",t.getShaderInfoLog(s)),void(this.available=!1))}setShape(t){t!==this.shape&&(this.shape=t,this.available&&(this.program&&this.gl.deleteProgram(this.program),this._compileShaders()))}resize(t,e){if(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available){const i=this.gl;i.viewport(0,0,t,e),i.useProgram(this.program),i.uniform2f(this.uResolution,t,e)}}updateParticles(t){if(!this.available)return 0;const e=Math.min(t.length,this.maxParticles),i=this.gl;for(let i=0;i<e;i++){const e=t[i],s=2*i,n=4*i;this._positions[s]=e.x,this._positions[s+1]=e.y,this._sizes[i]=e.size;const o=e.color,r=void 0!==o.a?o.a:1,a=o.r/255*r,h=o.g/255*r,l=o.b/255*r;this._colors[n]=a,this._colors[n+1]=h,this._colors[n+2]=l,this._colors[n+3]=r}return i.bindBuffer(i.ARRAY_BUFFER,this.positionBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._positions.subarray(0,2*e)),i.bindBuffer(i.ARRAY_BUFFER,this.sizeBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._sizes.subarray(0,e)),i.bindBuffer(i.ARRAY_BUFFER,this.colorBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._colors.subarray(0,4*e)),e}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t){if(!this.available||0===t)return;const e=this.gl;e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.sizeBuffer),e.enableVertexAttribArray(this.aSize),e.vertexAttribPointer(this.aSize,1,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorBuffer),e.enableVertexAttribArray(this.aColor),e.vertexAttribPointer(this.aColor,4,e.FLOAT,!1,0,0),e.drawArrays(e.POINTS,0,t)}compositeOnto(t,e=0,i=0,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}getCanvas(){return this.canvas}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),t.deleteBuffer(this.positionBuffer),t.deleteBuffer(this.sizeBuffer),t.deleteBuffer(this.colorBuffer),this._positions=null,this._sizes=null,this._colors=null}}class ws extends Ei{constructor(t,e={}){super(t,e),this.particles=[],this.pool=[],this.maxParticles=e.maxParticles??5e3,this.emitters=new Map,this.camera=e.camera??null,this.depthSort=e.depthSort??!1,this.updaters=e.updaters??[ps.velocity,ps.lifetime],this.blendMode=e.blendMode??"source-over",this.worldSpace=e.worldSpace??!1,this.webglRenderer=null,e.webglRenderer?this.webglRenderer=e.webglRenderer:e.useWebGL&&(this.webglRenderer=new bs(this.maxParticles,{width:t.width,height:t.height,shape:e.webglShape??"circle",blendMode:e.webglBlendMode??"alpha"}),this.webglRenderer.isAvailable()||(console.warn("WebGL not available, falling back to Canvas 2D"),this.webglRenderer=null)),this.depthShading=e.depthShading??!1,this.depthShadingMin=e.depthShadingMin??.3,this.depthShadingMax=e.depthShadingMax??1,this.webglOffset=e.webglOffset??null,this._webglRenderList=[],this._particleCount=0}addEmitter(t,e){return this.emitters.set(t,e),this}removeEmitter(t){return this.emitters.delete(t),this}getEmitter(t){return this.emitters.get(t)}acquire(){return this.pool.length>0?this.pool.pop():new ds}release(t){t.reset(),this.pool.push(t)}emit(t,e){for(let i=0;i<t&&this.particles.length<this.maxParticles;i++){const t=this.acquire();e.emit(t),this.particles.push(t)}}burst(t,e){const i="string"==typeof e?this.emitters.get(e):e;i&&this.emit(t,i)}update(t){super.update(t);for(const e of this.emitters.values())if(e.active){const i=e.update(t);this.emit(i,e)}for(let e=this.particles.length-1;e>=0;e--){const i=this.particles[e];for(const e of this.updaters)e(i,t,this);i.alive||(this.release(i),this.particles.splice(e,1))}this._particleCount=this.particles.length}render(){super.render(),0!==this.particles.length&&(this.webglRenderer?this.renderWebGL():this.camera&&this.depthSort?this.renderWithDepthSort():this.renderSimple())}renderWebGL(){var t,e;const i=this.webglRenderer,s=this._webglRenderList;i.width===this.game.width&&i.height===this.game.height||i.resize(this.game.width,this.game.height),s.length=0;const n=this.game.width/2,o=this.game.height/2;if(this.camera&&this.depthSort){for(const t of this.particles){const e=this.camera.project(t.x,t.y,t.z);e.z<10-this.camera.perspective||s.push({x:n+e.x,y:o+e.y,z:e.z,size:t.size*e.scale,color:t.color})}if(s.sort((t,e)=>e.z-t.z),this.depthShading&&s.length>1){let t=1/0,e=-1/0;for(const i of s)i.z<t&&(t=i.z),i.z>e&&(e=i.z);const i=e-t;if(i>0){const t=this.depthShadingMax-this.depthShadingMin;for(const n of s){const s=(e-n.z)/i,o=this.depthShadingMin+s*t;n.color={r:n.color.r*o,g:n.color.g*o,b:n.color.b*o,a:n.color.a}}}}}else{const i=(null==(t=this.webglOffset)?void 0:t.x)??0,n=(null==(e=this.webglOffset)?void 0:e.y)??0;for(const t of this.particles)s.push({x:t.x+i,y:t.y+n,size:t.size,color:t.color})}i.clear();const r=i.updateParticles(s);i.render(r);const a=this.webglOffset?-this.webglOffset.x:0,h=this.webglOffset?-this.webglOffset.y:0;Le.useCtx(t=>{t.globalCompositeOperation=this.blendMode,i.compositeOnto(t,a,h),t.globalCompositeOperation="source-over"})}renderSimple(){Le.useCtx(t=>{t.globalCompositeOperation=this.blendMode;for(const e of this.particles)this.drawParticle(t,e,e.x,e.y,1);t.globalCompositeOperation="source-over"})}renderWithDepthSort(){const t=[];for(const e of this.particles){const i=this.camera.project(e.x,e.y,e.z);i.z<10-this.camera.perspective||t.push({p:e,x:i.x,y:i.y,z:i.z,scale:i.scale})}t.sort((t,e)=>e.z-t.z),Le.useCtx(e=>{e.globalCompositeOperation=this.blendMode;const i=this.parent&&"Scene3D"===this.parent.constructor.name;this.worldSpace||i||(e.save(),e.translate(this.game.width/2,this.game.height/2));for(const i of t)this.drawParticle(e,i.p,i.x,i.y,i.scale);this.worldSpace||i||e.restore(),e.globalCompositeOperation="source-over"})}drawParticle(t,e,i,s,n){const{r:o,g:r,b:a,a:h}=e.color,l=e.size*n;if(l<.5||h<=0)return;t.fillStyle=`rgba(${Math.floor(o)},${Math.floor(r)},${Math.floor(a)},${h})`;const c=e.shape??"circle",u=l/2;t.beginPath(),"circle"===c?t.arc(i,s,u,0,2*Math.PI):"square"===c?t.rect(i-u,s-u,l,l):"triangle"===c&&(t.moveTo(i,s-u),t.lineTo(i+u,s+u),t.lineTo(i-u,s+u),t.closePath()),t.fill()}clear(){for(const t of this.particles)this.release(t);this.particles=[],this._particleCount=0}destroy(){this.clear(),this.webglRenderer&&(this.webglRenderer.destroy(),this.webglRenderer=null),this.pool=[],this.emitters.clear()}get isWebGL(){return null!==this.webglRenderer&&this.webglRenderer.isAvailable()}get particleCount(){return this._particleCount}get poolSize(){return this.pool.length}}class Ms{static rectRect(t,e){return t.x<e.x+e.width&&t.x+t.width>e.x&&t.y<e.y+e.height&&t.y+t.height>e.y}static intersects(t,e){return Ms.rectRect(t,e)}static pointRect(t,e,i){return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}static circleCircle(t,e){const i=t.x-e.x,s=t.y-e.y,n=i*i+s*s,o=t.radius+e.radius;return n<=o*o}static getCircleOverlap(t,e){const i=t.x-e.x,s=t.y-e.y,n=i*i+s*s,o=t.radius+e.radius;if(n>=o*o||n<1e-4)return null;const r=Math.sqrt(n),a=1/r;return{overlap:o-r,nx:i*a,ny:s*a,dist:r}}static applyCircleSeparation(t,e,i={}){const s=i.strength??5e3,n=i.useSizeAsRadius??!0,o=t.length;for(let i=0;i<o;i++){const r=t[i],a=n?.5*r.size:r.radius??10;for(let h=i+1;h<o;h++){const o=t[h],l=n?.5*o.size:o.radius??10,c=Ms.getCircleOverlap({x:r.x,y:r.y,radius:a},{x:o.x,y:o.y,radius:l});if(c){const t=s*(c.overlap/(a+l)),n=c.nx*t,o=c.ny*t;e[i].x+=n,e[i].y+=o,e[h].x-=n,e[h].y-=o}}}}static pointCircle(t,e,i){const s=t-i.x,n=e-i.y;return s*s+n*n<=i.radius*i.radius}static circleRect(t,e){const i=Math.max(e.x,Math.min(t.x,e.x+e.width)),s=Math.max(e.y,Math.min(t.y,e.y+e.height)),n=t.x-i,o=t.y-s;return n*n+o*o<=t.radius*t.radius}static lineRect(t,e,i,s,n,o=0){const r=n.x-o/2,a=n.y-o/2,h=n.width+o,l=n.height+o;if(Ms.pointRect(t,e,{x:r,y:a,width:h,height:l})||Ms.pointRect(i,s,{x:r,y:a,width:h,height:l}))return!0;const c=Ms.lineLine(t,e,i,s,r,a,r,a+l),u=Ms.lineLine(t,e,i,s,r+h,a,r+h,a+l),d=Ms.lineLine(t,e,i,s,r,a,r+h,a),f=Ms.lineLine(t,e,i,s,r,a+l,r+h,a+l);return c||u||d||f}static lineLine(t,e,i,s,n,o,r,a){const h=(a-o)*(i-t)-(r-n)*(s-e);if(0===h)return!1;const l=((r-n)*(e-o)-(a-o)*(t-n))/h,c=((i-t)*(e-o)-(s-e)*(t-n))/h;return l>=0&&l<=1&&c>=0&&c<=1}static segmentsRect(t,e,i=0){for(const s of t)if(Ms.lineRect(s.x1,s.y1,s.x2,s.y2,e,i))return!0;return!1}static getOverlap(t,e){return Ms.rectRect(t,e)?{x:Math.min(t.x+t.width,e.x+e.width)-Math.max(t.x,e.x),y:Math.min(t.y+t.height,e.y+e.height)-Math.max(t.y,e.y)}:null}static getMTV(t,e){const i=Ms.getOverlap(t,e);if(!i)return null;const s=t.x+t.width/2,n=t.y+t.height/2,o=e.x+e.width/2,r=e.y+e.height/2,a=s<o?-i.x:i.x,h=n<r?-i.y:i.y;return Math.abs(i.x)<Math.abs(i.y)?{x:a,y:0}:{x:0,y:h}}static sweep(t,e,i,s){const n=s.x-t.width/2,o=s.y-t.height/2,r=s.width+t.width,a=s.height+t.height,h=t.x+t.width/2,l=t.y+t.height/2;let c,u,d,f;0!==e?(c=(n-h)/e,u=(n+r-h)/e,c>u&&([c,u]=[u,c])):(c=h>=n&&h<=n+r?-1/0:1/0,u=h>=n&&h<=n+r?1/0:-1/0),0!==i?(d=(o-l)/i,f=(o+a-l)/i,d>f&&([d,f]=[f,d])):(d=l>=o&&l<=o+a?-1/0:1/0,f=l>=o&&l<=o+a?1/0:-1/0);const p=Math.max(c,d);if(p>Math.min(u,f)||p<0||p>1)return null;let g=0,m=0;return c>d?g=e>0?-1:1:m=i>0?-1:1,{time:p,normalX:g,normalY:m}}}const Ss={maxParticles:500,particleSize:20,particleColor:{r:100,g:180,b:255,a:.9},physics:"liquid",gravity:200,damping:.98,bounce:.3,maxSpeed:400,fluid:{smoothingRadius:null,restDensity:3,pressureStiffness:80,nearPressureStiffness:3,viscosity:.005,maxForce:5e3},gas:{interactionRadius:null,pressure:150,diffusion:.15,drag:.02,turbulence:50,buoyancy:300,sinking:200,repulsion:300},heat:{enabled:!1,heatZone:.88,coolZone:.25,rate:.03,heatMultiplier:1.5,coolMultiplier:2,middleMultiplier:.005,transitionWidth:.08,neutralTemp:.5,deadZone:.15,buoyancy:300,sinking:200},collision:{enabled:!0,strength:5e3},boundary:{enabled:!0,strength:4e3,radius:null},shake:{enabled:!0,sensitivity:2,maxForce:2500,damping:.8},blendMode:"source-over"};class Cs extends ws{constructor(t,e={}){var i,s,n,o;const r=Cs._mergeConfig(e),a=(null==(i=e.bounds)?void 0:i.x)??0,h=(null==(s=e.bounds)?void 0:s.y)??0,l=e.width??(null==(n=e.bounds)?void 0:n.w)??0,c=e.height??(null==(o=e.bounds)?void 0:o.h)??0;super(t,{maxParticles:r.maxParticles,blendMode:r.blendMode,updaters:[ps.velocity,ps.lifetime],x:e.x??a+l/2,y:e.y??h+c/2,width:l,height:c,debug:e.debug??!1,debugColor:e.debugColor??"#0f0"}),this.config=r,this.bounds=e.bounds||null,this.gravityEnabled=e.gravityEnabled??!0,this.modeMix="gas"===r.physics?1:0,this._targetMode=this.modeMix,this._modeLerpSpeed=5,this._forces=[],this._shake={lastX:window.screenX,lastY:window.screenY,velocityX:0,velocityY:0,forceX:0,forceY:0},this._createEmitter()}static _mergeConfig(t){const e={...Ss,...t},i=e.particleSize;return e.fluid={...Ss.fluid,...t.fluid},e.gas={...Ss.gas,...t.gas},e.heat={...Ss.heat,...t.heat},e.collision={...Ss.collision,...t.collision},e.boundary={...Ss.boundary,...t.boundary},e.shake={...Ss.shake,...t.shake},null===e.fluid.smoothingRadius&&(e.fluid.smoothingRadius=2*i),null===e.gas.interactionRadius&&(e.gas.interactionRadius=4*i),null===e.boundary.radius&&(e.boundary.radius=.8*i),e}_createEmitter(){const{particleSize:t,particleColor:e}=this.config,i=new fs({rate:0,position:{x:0,y:0},spread:{x:100,y:100},velocity:{x:0,y:0},velocitySpread:{x:10,y:10},size:{min:t,max:t+2},lifetime:{min:99999,max:99999},color:e,shape:"circle"});this.addEmitter("fluid",i)}spawn(t,e={}){const i=this.emitters.get("fluid");if(!i)return;let s=e.x,n=e.y,o=e.spreadX??100,r=e.spreadY??100;this.bounds&&void 0===s&&(s=this.bounds.x+this.bounds.w/2,n=this.bounds.y+.6*this.bounds.h,o=Math.min(.8*this.bounds.w,400),r=Math.min(.5*this.bounds.h,250)),i.position.x=s??this.game.width/2,i.position.y=n??this.game.height/2,i.spread.x=o,i.spread.y=r,this.burst(t,"fluid");for(const t of this.particles)t.custom.initialized||(t.custom.initialized=!0,t.custom.mass=1,t.custom.temperature=.5,t.vx=20*(Math.random()-.5),t.vy=20*(Math.random()-.5))}setBounds(t){this.bounds=t,this.x=t.x+t.w/2,this.y=t.y+t.h/2,this.width=t.w,this.height=t.h}update(t){t=Math.min(t,.033),this.modeMix=oe.lerp(this.modeMix,this._targetMode,t*this._modeLerpSpeed);const e=this.particles;0!==e.length?(this._ensureForceArray(e.length),this._resetForces(),this._computePhysicsForces(e),this.modeMix>.5&&((this.config.heat.enabled||this.modeMix>.95)&&(this._updateTemperatures(e),this._applyThermalForces(e)),this.modeMix>.95&&this._applyGasRepulsion(e)),this.config.collision.enabled&&Ms.applyCircleSeparation(e,this._forces,{strength:this.config.collision.strength,useSizeAsRadius:!0}),this.bounds&&this.config.boundary.enabled&&this._applyBoundaryForces(e),this.config.shake.enabled&&(this._updateShakeForces(t),this._applyShakeForces()),this._integrateForces(e,t),super.update(t),this.bounds&&this._clampBounds(e)):super.update(t)}_ensureForceArray(t){for(;this._forces.length<t;)this._forces.push({x:0,y:0})}_resetForces(){for(let t=0;t<this._forces.length;t++)this._forces[t].x=0,this._forces[t].y=0}_computePhysicsForces(t){const{fluid:e,gas:i}=this.config;if(this.modeMix<.01){const i=ye(t,{kernel:{smoothingRadius:e.smoothingRadius},fluid:{restDensity:e.restDensity,pressureStiffness:e.pressureStiffness,nearPressureStiffness:e.nearPressureStiffness,viscosity:e.viscosity,maxForce:e.maxForce}});this._accumulateForces(i.forces)}else if(this.modeMix>.95){const e=_e(t,{gas:{interactionRadius:i.interactionRadius,pressure:i.pressure,diffusion:i.diffusion,drag:i.drag,turbulence:i.turbulence,buoyancy:i.buoyancy}});this._accumulateForces(e.forces)}else{const s=ye(t,{kernel:{smoothingRadius:e.smoothingRadius},fluid:e}),n=_e(t,{gas:i}),o=xe(s.forces,n.forces,this.modeMix);this._accumulateForces(o)}}_accumulateForces(t){const e=Math.min(t.length,this._forces.length);for(let i=0;i<e;i++)this._forces[i].x+=t[i].x,this._forces[i].y+=t[i].y}_applyBoundaryForces(t){const{x:e,y:i,w:s,h:n}=this.bounds,{radius:o,strength:r}=this.config.boundary,a=e,h=e+s,l=i,c=i+n;for(let e=0;e<t.length;e++){const i=t[e],s=.5*i.size,n=i.x-s-a,u=h-i.x-s,d=i.y-s-l,f=c-i.y-s;if(n<o){const t=Math.max(0,1-n/o);this._forces[e].x+=r*t*t}if(u<o){const t=Math.max(0,1-u/o);this._forces[e].x-=r*t*t}if(d<o){const t=Math.max(0,1-d/o);this._forces[e].y+=r*t*t}if(f<o){const t=Math.max(0,1-f/o);this._forces[e].y-=r*t*t}}}_updateTemperatures(t){if(!this.bounds)return;const{heat:e}=this.config,i=this.bounds.y,s=this.bounds.h;for(let n=0;n<t.length;n++){const o=t[n],r=o.custom.temperature??e.neutralTemp,a=ae(Math.min(1,Math.max(0,(o.y-i)/s)),r,e);o.custom.temperature=Math.min(1,Math.max(0,a))}}_applyThermalForces(t){const{heat:e}=this.config,i=e.neutralTemp,s=e.deadZone;for(let n=0;n<t.length;n++){const o=(t[n].custom.temperature??i)-i;if(Math.abs(o)>s){let t=0;t=o>0?-(o-s)*e.buoyancy*2:(-o-s)*e.sinking*2,this._forces[n].y+=t}}}_applyGasRepulsion(t){const{gas:e}=this.config,i=e.interactionRadius,s=i*i,n=e.repulsion||200,o=t.length;for(let e=0;e<o;e++){const r=t[e];for(let a=e+1;a<o;a++){const o=t[a],h=r.x-o.x,l=r.y-o.y,c=h*h+l*l;if(c>=s||c<1)continue;const u=Math.sqrt(c),d=1-u/i,f=n*d*d*d,p=h/u*f,g=l/u*f;this._forces[e].x+=p,this._forces[e].y+=g,this._forces[a].x-=p,this._forces[a].y-=g}}}_updateShakeForces(t){const{shake:e}=this.config;if(!e.enabled)return;const i=window.screenX,s=window.screenY,n=i-this._shake.lastX,o=s-this._shake.lastY;t>0&&t<.1&&(this._shake.velocityX=n/t,this._shake.velocityY=o/t),this._shake.lastX=i,this._shake.lastY=s;const r=-this._shake.velocityX*e.sensitivity,a=-this._shake.velocityY*e.sensitivity;this._shake.forceX=oe.lerp(this._shake.forceX,r,1-e.damping),this._shake.forceY=oe.lerp(this._shake.forceY,a,1-e.damping);const h=Math.sqrt(this._shake.forceX*this._shake.forceX+this._shake.forceY*this._shake.forceY);if(h>e.maxForce){const t=e.maxForce/h;this._shake.forceX*=t,this._shake.forceY*=t}}_applyShakeForces(){const t=this._shake.forceX,e=this._shake.forceY;if(!(Math.abs(t)<1&&Math.abs(e)<1))for(let i=0;i<this._forces.length;i++)this._forces[i].x+=t,this._forces[i].y+=e}_integrateForces(t,e){const{gravity:i,damping:s,maxSpeed:n,heat:o}=this.config,r=n*n,a=oe.lerp(s,.995,this.modeMix);for(let s=0;s<t.length;s++){const h=t[s],l=this._forces[s],c=h.custom.mass||1;let u,d;if(this.modeMix>.5){const t=h.custom.temperature??o.neutralTemp;u=c*oe.lerp(1.5,.3,t),d=this.gravityEnabled?i*oe.lerp(1.2,.6,t):0}else u=c,d=this.gravityEnabled?i:0;h.vx+=l.x/u*e,h.vy+=(l.y/u+d)*e,h.vx*=a,h.vy*=a;const f=h.vx*h.vx+h.vy*h.vy;if(f>r){const t=n/Math.sqrt(f);h.vx*=t,h.vy*=t}}}_clampBounds(t){const{x:e,y:i,w:s,h:n}=this.bounds,{bounce:o}=this.config;for(let r=0;r<t.length;r++){const a=t[r],h=.5*a.size,l=e+h,c=e+s-h,u=i+h,d=i+n-h;a.x<l?(a.x=l,a.vx=Math.abs(a.vx)*o):a.x>c&&(a.x=c,a.vx=-Math.abs(a.vx)*o),a.y<u?(a.y=u,a.vy=Math.abs(a.vy)*o):a.y>d&&(a.y=d,a.vy=-Math.abs(a.vy)*o)}}reset(){const t=this.particles.length;this.particles.length=0,this._forces.length=0,this.spawn(t)}toggleGravity(){return this.gravityEnabled=!this.gravityEnabled,this.gravityEnabled}setPhysicsMode(t,e=!1){let i;if("liquid"===t)i=0;else if("gas"===t)i=1;else{if("number"!=typeof t)return;i=Math.max(0,Math.min(1,t))}this._targetMode=i,e&&(this.modeMix=i)}getPhysicsMode(){return this.modeMix<.01?"liquid":this.modeMix>.99?"gas":"blending"}isHeatEnabled(){return this.config.heat.enabled||this.modeMix>.5}}R=new WeakMap,A=new WeakMap,z=new WeakMap,D=new WeakMap,B=new WeakMap,I=new WeakMap,E=new WeakSet,F=function(t){var e;if(bt(this,B).push(t),1===bt(this,B).length){bt(this,A)._fluentShape=t,bt(this,A).renderable=t;const i=(null==(e=bt(this,A).draw)?void 0:e.bind(bt(this,A)))||(()=>{});bt(this,A).draw=function(){i(),this._fluentShape&&this.visible&&this._fluentShape.render()};const s=bt(this,A);bt(this,A).getBounds=function(){return s._fluentShape&&s._fluentShape.getBounds?s._fluentShape.getBounds():null}}else{if(!(bt(this,A)._fluentShape instanceof Ve)){const t=bt(this,B)[0],e=new Ve;e.add(t),bt(this,A)._fluentShape=e,bt(this,A).renderable=e}bt(this,A)._fluentShape.add(t)}return this},O=function(t){const e={...t};return void 0!==t.fill&&(e.color=t.fill,e.fillColor=t.fill,delete e.fill),void 0!==t.stroke&&(e.strokeColor=t.stroke,delete e.stroke),e},L=function(t){for(const e of bt(this,A)._fluentMotions){const i=St(this,E,Y).call(this,e,t);e.state=null==i?void 0:i.state}},Y=function(t,e){const{type:i,opts:s,state:n}=t,o=bt(this,A)._motionTime,r=bt(this,A);switch(i){case"oscillate":{const{prop:t="y",min:e=-50,max:i=50,duration:n=2}=s,a=os.oscillate(e,i,o,n,!0),h=`_base_${t}`;return void 0===r[h]&&(r[h]=r[t]),r[t]=r[h]+a.value,a}case"pulse":{const{prop:t="scale",min:e=.8,max:i=1.2,duration:n=1}=s,a=os.pulse(e,i,o,n,!0);return"scale"===t?(r.scaleX=a.value,r.scaleY=a.value):"opacity"===t&&r.renderable?r.renderable.opacity=a.value:r[t]=a.value,a}case"orbit":{const{centerX:t=r._baseX,centerY:e=r._baseY,radiusX:i=100,radiusY:n=100,duration:a=3,clockwise:h=!0}=s;r._orbitCenter||(r._orbitCenter={x:t,y:e});const l=os.orbit(r._orbitCenter.x,r._orbitCenter.y,i,n,0,o,a,!0,h);return r.x=l.x,r.y=l.y,l}case"float":{const{radius:t=20,speed:e=.5,randomness:i=.3,duration:n=5}=s;r._floatState||(r._floatState={baseX:r._baseX,baseY:r._baseY});const a=os.float(r._floatState,o,n,e,i,t,!0);return r.x=a.x,r.y=a.y,a}case"shake":{const{intensity:t=5,frequency:e=20,decay:i=.9,duration:n=.5}=s,a=os.shake(r._baseX,r._baseY,t,t,e,i,o,n,!0);return r.x=a.x,r.y=a.y,a}case"bounce":{const{height:t=100,bounces:e=3,duration:i=2}=s,n=os.bounce(t,r._baseY,e,o,i,!0);return r.y=n.y,n}case"spiral":{const{startRadius:t=50,endRadius:e=150,revolutions:i=3,duration:n=4}=s;r._spiralCenter||(r._spiralCenter={x:r._baseX,y:r._baseY});const a=os.spiral(r._spiralCenter.x,r._spiralCenter.y,t,e,0,i,o,n,!0);return r.x=a.x,r.y=a.y,a}case"pendulum":{const{amplitude:t=45,duration:e=2,damped:i=!1}=s,n=os.pendulum(0,t,o,e,!0,i);return r.rotation=n.value*(Math.PI/180),n}case"waypoint":{const{waypoints:t=[],speed:e=100,waitTime:i=0}=s;if(0===t.length)return{state:null};const a=os.waypoint(r,o,t,e,i,!0,null,n);return r.x=a.x??r.x,r.y=a.y??r.y,a}default:return console.warn(`Unknown motion type: ${i}`),{state:null}}};let Ts=class t{constructor(t,e,i,s){wt(this,E),wt(this,R),wt(this,A),wt(this,z),wt(this,D),wt(this,B,[]),wt(this,I,[]),Mt(this,R,t),Mt(this,A,e),Mt(this,z,i),Mt(this,D,s)}circle(t={}){const e=St(this,E,O).call(this,t),{radius:i=30,...s}=e,n=new je(i,s);return St(this,E,F).call(this,n)}rect(t={}){const e=St(this,E,O).call(this,t),i=new Je(e);return St(this,E,F).call(this,i)}roundRect(t={}){const e=St(this,E,O).call(this,t),{radius:i=10,...s}=e,n=new Qe(i,s);return St(this,E,F).call(this,n)}square(t={}){const e=St(this,E,O).call(this,t),{size:i=50,...s}=e,n=new ti(i,s);return St(this,E,F).call(this,n)}star(t={}){const e=St(this,E,O).call(this,t),{radius:i=40,points:s=5,inset:n=.5,...o}=e,r=new ni(i,s,n,o);return St(this,E,F).call(this,r)}triangle(t={}){const e=St(this,E,O).call(this,t),{size:i=50,...s}=e,n=new si(i,s);return St(this,E,F).call(this,n)}poly(t={}){const e=St(this,E,O).call(this,t),i=new mi(e);return St(this,E,F).call(this,i)}line(t={}){const e=St(this,E,O).call(this,t),{length:i=40,...s}=e,n=new ii(i,s);return St(this,E,F).call(this,n)}hexagon(t={}){const e=St(this,E,O).call(this,t),{radius:i=30,...s}=e,n=new _i(i,s);return St(this,E,F).call(this,n)}diamond(t={}){const e=St(this,E,O).call(this,t),i=new ei(e);return St(this,E,F).call(this,i)}heart(t={}){const e=St(this,E,O).call(this,t),{size:i,...s}=e;i&&!s.width&&(s.width=i),i&&!s.height&&(s.height=i);const n=new xi(s);return St(this,E,F).call(this,n)}arc(t={}){const e=St(this,E,O).call(this,t),{radius:i=30,startAngle:s=0,endAngle:n=Math.PI,...o}=e,r=new $e(i,s,n,o);return St(this,E,F).call(this,r)}ring(t={}){const e=St(this,E,O).call(this,t),{outerRadius:i=40,innerRadius:s=20,...n}=e,o=new gi(i,s,n);return St(this,E,F).call(this,o)}arrow(t={}){const e=St(this,E,O).call(this,t),{length:i=50,...s}=e,n=new vi(i,s);return St(this,E,F).call(this,n)}cross(t={}){const e=St(this,E,O).call(this,t),{size:i=40,thickness:s=10,...n}=e,o=new bi(i,s,n);return St(this,E,F).call(this,o)}pin(t={}){const e=St(this,E,O).call(this,t),{radius:i=20,...s}=e,n=new yi(i,s);return St(this,E,F).call(this,n)}cloud(t={}){const e=St(this,E,O).call(this,t),{size:i,width:s,height:n,...o}=e,r=i||Math.min(s||40,n||40),a=new Ke(r,o);return St(this,E,F).call(this,a)}text(t,e={}){const i=St(this,E,O).call(this,e);i.fillColor&&(i.color=i.fillColor,delete i.fillColor);const s=new wi(t,i);return St(this,E,F).call(this,s)}image(t,e={}){const i=St(this,E,O).call(this,e);if("string"==typeof t){const s=new Image;s.src=t;const n=new Mi(s,i);return s.onload=()=>{n._bitmap=s,n._width=e.width??s.width,n._height=e.height??s.height},St(this,E,F).call(this,n)}{const e=new Mi(t,i);return St(this,E,F).call(this,e)}}svg(t,e={}){const i=St(this,E,O).call(this,e),s=new pi({path:t,...i});return St(this,E,F).call(this,s)}add(t,e={}){const i=new t(St(this,E,O).call(this,e));return St(this,E,F).call(this,i)}oscillate(t={}){return this.motion("oscillate",t)}pulse(t={}){return this.motion("pulse",t)}orbit(t={}){return this.motion("orbit",t)}float(t={}){return this.motion("float",t)}shake(t={}){return this.motion("shake",t)}bounce(t={}){return this.motion("bounce",t)}spring(t={}){return this.motion("spring",t)}spiral(t={}){return this.motion("spiral",t)}pendulum(t={}){return this.motion("pendulum",t)}waypoint(t={}){return this.motion("waypoint",t)}motion(t,e={}){var i;if(bt(this,I).push({type:t,opts:e}),!bt(this,A)._fluentMotions){bt(this,A)._fluentMotions=[],bt(this,A)._motionTime=0,bt(this,A)._baseX=bt(this,A).x,bt(this,A)._baseY=bt(this,A).y;const t=(null==(i=bt(this,A).update)?void 0:i.bind(bt(this,A)))||(()=>{}),e=this;bt(this,A).update=function(i){var s;t(i),this._motionTime+=i,St(s=e,E,L).call(s,i)}}return bt(this,A)._fluentMotions.push({type:t,opts:e,state:null}),this}tween(t,e={}){const{duration:i=1,easing:s="easeOutQuad",delay:n=0,onComplete:o}=e;return n>0?setTimeout(()=>{as.to(bt(this,A),t,i,s,{onComplete:o})},1e3*n):as.to(bt(this,A),t,i,s,{onComplete:o}),this}child(e,i,s){let n,o,r;"function"==typeof e&&e.prototype?(n=e,"function"==typeof i?(o={},r=i):(o=i||{},r=s)):(n=Ei,o=e||{},r=i);const a=new n(bt(this,A).game,o);bt(this,A).addChild(a),o.name&&(bt(this,z)[o.name]=a);const h=new t(this,a,bt(this,z),bt(this,D));return r?(r(h),this):h}on(t,e){const i={go:bt(this,A),shapes:bt(this,B),refs:bt(this,z),state:bt(this,D)};return["click","mousedown","mouseup","mousemove","mouseover","mouseout","inputdown","inputup","inputmove"].includes(t)&&(bt(this,A).interactive=!0),bt(this,A).events&&bt(this,A).events.on(t,t=>e(i,t)),this}update(t){var e;const i=(null==(e=bt(this,A).update)?void 0:e.bind(bt(this,A)))||(()=>{}),s=bt(this,B),n=bt(this,z),o=bt(this,D),r=bt(this,A);return bt(this,A).update=e=>{i(e),t(e,{go:r,shapes:s,refs:n,state:o})},this}pos(t,e){return bt(this,A).x=t,bt(this,A).y=e,this}scale(t,e){return bt(this,A).scaleX=t,bt(this,A).scaleY=e??t,this}rotate(t){return bt(this,A).rotation=t*(Math.PI/180),this}opacity(t){return bt(this,A).opacity=t,bt(this,A).renderable&&(bt(this,A).renderable.opacity=t),this}zIndex(t){return bt(this,A).zIndex=t,this}end(){return bt(this,R)}go(t){var e;let i=bt(this,R);for(;i&&!i.sceneInstance;)i=null==(e=i.end)?void 0:e.call(i);if(i&&i.go)return i.go(t);throw new Error("Cannot find scene context")}scene(t,e){var i;let s=bt(this,R);for(;s&&!s.sceneInstance;)s=null==(i=s.end)?void 0:i.call(s);if(s&&s.scene)return s.scene(t,e);throw new Error("Cannot find game context")}start(){let t=bt(this,R);for(;t&&t.end;){const e=t.end();if(e===t)break;t=e}return t.start()}get goInstance(){return bt(this,A)}get shapes(){return bt(this,B)}get refs(){return bt(this,z)}get state(){return bt(this,D)}};class ks{constructor(t,e,i,s,n){wt(this,X),wt(this,W),wt(this,H),wt(this,U),wt(this,G),Mt(this,X,t),Mt(this,W,e),Mt(this,H,i),Mt(this,U,s),Mt(this,G,n)}go(t={},e){var i;const{name:s,x:n=0,y:o=0,visible:r=!0,...a}=t,h=new Ei({x:n,y:o,visible:r,...a});(null==(i=bt(this,X).parent)?void 0:i.game)&&(h.game=bt(this,X).parent.game),bt(this,H).add(h),s&&(h.name=s,bt(this,U)[s]=h);const l=new Ts(this,h,bt(this,U),bt(this,G));return e?(e(l),this):l}visible(t){return bt(this,W).visible=t,this}opacity(t){return bt(this,H).opacity=t,this}endLayer(){return bt(this,X)}end(){return bt(this,X)}scene(t,e){return bt(this,X).scene(t,e)}start(){return bt(this,X).start()}get layerGO(){return bt(this,W)}get group(){return bt(this,H)}get refs(){return bt(this,U)}get state(){return bt(this,G)}}X=new WeakMap,W=new WeakMap,H=new WeakMap,U=new WeakMap,G=new WeakMap;class Ps{constructor(t,e,i,s){wt(this,N),wt(this,q),wt(this,Z),wt(this,V),wt(this,$,null),Mt(this,N,t),Mt(this,q,e),Mt(this,Z,i),Mt(this,V,s)}go(t,e,i){let s,n,o;"function"==typeof t&&t.prototype?(s=t,"function"==typeof e?(n={},o=e):(n=e||{},o=i)):(s=Ei,n=t||{},o=e);const{name:r,x:a=0,y:h=0,visible:l=!0,...c}=n,u=new s(bt(this,N).game,{x:a,y:h,visible:l,...c});bt(this,q).add(u),Mt(this,$,u),r&&(u.name=r,bt(this,Z)[r]=u);const d=new Ts(this,u,bt(this,Z),bt(this,V));return o?(o(d),this):d}group(t,e){const i="string"==typeof t?t:null,s=[];return("function"==typeof t?t:e)({go:t=>{const e=this.go(t);return s.push(e.goInstance),e}}),i&&(bt(this,Z)[i]=s),this}layer(t,e=0){var i;const s=new Ve({zIndex:e});s.name=t;const n=new Ei(bt(this,N).game,{x:0,y:0});n._fluentShape=s,n.renderable=s,n.zIndex=e;const o=(null==(i=n.draw)?void 0:i.bind(n))||(()=>{});return n.draw=function(){o(),this._fluentShape&&this.visible&&this._fluentShape.render()},bt(this,q).add(n),t&&(bt(this,Z)[`${bt(this,q).name}_${t}`]=n),new ks(this,n,s,bt(this,Z),bt(this,V))}onEnter(t){return bt(this,q)._onEnter=t,this}onExit(t){return bt(this,q)._onExit=t,this}scene(t,e){return bt(this,N).scene(t,e)}end(){return bt(this,N)}start(){return bt(this,N).start()}stop(){return bt(this,N).stop()}on(t,e){return bt(this,N).on(t,e)}use(t){return bt(this,N).use(t)}state(t){return bt(this,N).state(t)}get sceneInstance(){return bt(this,q)}get refs(){return bt(this,Z)}get state(){return bt(this,V)}get parent(){return bt(this,N)}}function Rs(t={}){return new As(t)}N=new WeakMap,q=new WeakMap,Z=new WeakMap,V=new WeakMap,$=new WeakMap;class As{constructor(t={}){wt(this,st),wt(this,j),wt(this,K,new Map),wt(this,J,null),wt(this,Q,{}),wt(this,tt,{}),wt(this,et,[]),wt(this,it,null);const{canvas:e,width:i=800,height:s=600,bg:n,fluid:o,container:r,fps:a=60,pixelRatio:h=("undefined"!=typeof window?window.devicePixelRatio:1)}=t;Mt(this,it,e||St(this,st,nt).call(this,i,s,r)),Mt(this,j,new ls(bt(this,it))),bt(this,j).init(),n&&(bt(this,j).backgroundColor=n),(void 0!==o?o:!e)&&bt(this,j).enableFluidSize(),60!==a&&(bt(this,j).targetFPS=a),bt(this,j)._pixelRatio=h}scene(t,e,i){let s,n,o;"function"==typeof t?(n=t,s=n.name||"custom_scene",o=e||{}):"function"==typeof e?(s=t,n=e,o=i||{}):(s=t,n=Oi,o=e||{});const{zIndex:r=0,active:a=!0,onEnter:h,onExit:l,...c}=o;let u=bt(this,K).get(s);return u||(u=new n(bt(this,j),c),u.name=s,u.zIndex=r,u.visible=a,u._onEnter=h,u._onExit=l,bt(this,K).set(s,u),bt(this,j).pipeline.add(u)),Mt(this,J,u),new Ps(this,u,bt(this,Q),bt(this,tt))}inScene(t){const e=bt(this,K).get(t);if(!e)throw new Error(`Scene '${t}' does not exist. Use .scene('${t}') to create it.`);return Mt(this,J,e),new Ps(this,e,bt(this,Q),bt(this,tt))}go(t,e){return bt(this,J)||this.scene("default"),new Ps(this,bt(this,J),bt(this,Q),bt(this,tt)).go(t,e)}showScene(t){var e;const i=bt(this,K).get(t);return i&&(i.visible=!0,null==(e=i._onEnter)||e.call(i,St(this,st,ot).call(this))),this}hideScene(t){var e;const i=bt(this,K).get(t);return i&&(null==(e=i._onExit)||e.call(i,St(this,st,ot).call(this)),i.visible=!1),this}transition(t,e,i={}){const{fade:s=0,onComplete:n}=i;return this.hideScene(t),this.showScene(e),null==n||n(),this}state(t){return Object.assign(bt(this,tt),t),this}getState(t){return bt(this,tt)[t]}setState(t,e){return bt(this,tt)[t]=e,this}on(t,e){const i=St(this,st,ot).call(this);if("update"===t){const t=bt(this,j).update.bind(bt(this,j));bt(this,j).update=s=>{t(s),e(s,i)}}else if(t.startsWith("keydown:")){const s=t.split(":")[1];bt(this,j).events.on("keydown",t=>{var n,o;(null==(n=t.key)?void 0:n.toLowerCase())!==s.toLowerCase()&&(null==(o=t.code)?void 0:o.toLowerCase())!==s.toLowerCase()||e(i,t)})}else if(t.startsWith("keyup:")){const s=t.split(":")[1];bt(this,j).events.on("keyup",t=>{var n;(null==(n=t.key)?void 0:n.toLowerCase())===s.toLowerCase()&&e(i,t)})}else bt(this,j).events.on(t,t=>e(i,t));return this}use(t){return t(this),bt(this,et).push(t),this}start(){return bt(this,j).start(),this}stop(){return bt(this,j).stop(),this}restart(){return bt(this,j).restart(),this}get game(){return bt(this,j)}get refs(){return bt(this,Q)}get scenes(){return bt(this,K)}get canvas(){return bt(this,it)}get width(){return bt(this,it).width}get height(){return bt(this,it).height}}j=new WeakMap,K=new WeakMap,J=new WeakMap,Q=new WeakMap,tt=new WeakMap,et=new WeakMap,it=new WeakMap,st=new WeakSet,nt=function(t,e,i){const s=document.createElement("canvas");return s.width=t,s.height=e,s.style.display="block",(i||document.body).appendChild(s),s},ot=function(){return{refs:bt(this,Q),state:bt(this,tt),scenes:Object.fromEntries(bt(this,K)),game:bt(this,j),width:bt(this,it).width,height:bt(this,it).height,showScene:t=>this.showScene(t),hideScene:t=>this.hideScene(t),transition:(t,e,i)=>this.transition(t,e,i)}};class zs{static applyADSR(t,e={}){const{attack:i=.01,decay:s=.1,sustain:n=.7,release:o=.2,startTime:r=0,duration:a=1,peakVolume:h=1}=e,l=h*n,c=Math.max(0,a-i-s);t.setValueAtTime(0,r),t.linearRampToValueAtTime(h,r+i),t.linearRampToValueAtTime(l,r+i+s),t.setValueAtTime(l,r+i+s+c),t.linearRampToValueAtTime(0,r+a+o)}static get presets(){return{pluck:{attack:.001,decay:.2,sustain:0,release:.1},pad:{attack:.5,decay:.3,sustain:.8,release:1},organ:{attack:.01,decay:0,sustain:1,release:.05},perc:{attack:.001,decay:.1,sustain:0,release:.05},string:{attack:.1,decay:.2,sustain:.7,release:.3},brass:{attack:.05,decay:.1,sustain:.8,release:.2},blip:{attack:.001,decay:.05,sustain:0,release:.02},laser:{attack:.001,decay:.15,sustain:0,release:.05},explosion:{attack:.001,decay:.3,sustain:.2,release:.5}}}}class Ds{static init(t,e){Mt(this,rt,t),Mt(this,at,e)}static get ctx(){return bt(this,rt)}static get now(){return bt(this,rt).currentTime}static tone(t,e,i={}){const{type:s="sine",volume:n=.5,attack:o=.01,decay:r=.1,sustain:a=.7,release:h=.2,detune:l=0,startTime:c=bt(this,rt).currentTime}=i,u=bt(this,rt).createOscillator(),d=bt(this,rt).createGain();return u.type=s,u.frequency.setValueAtTime(t,c),u.detune.setValueAtTime(l,c),zs.applyADSR(d.gain,{attack:o,decay:r,sustain:a,release:h,startTime:c,duration:e,peakVolume:n}),u.connect(d),d.connect(bt(this,at)),u.start(c),u.stop(c+e+h),u}static continuous(t={}){const{type:e="sine",frequency:i=440,volume:s=.5}=t,n=bt(this,rt).createOscillator(),o=bt(this,rt).createGain();n.type=e,n.frequency.value=i,o.gain.value=s,n.connect(o),o.connect(bt(this,at)),n.start();const r=bt(this,rt);return{osc:n,gain:o,setFrequency:(t,e=0)=>{e>0?n.frequency.linearRampToValueAtTime(t,r.currentTime+e):n.frequency.setValueAtTime(t,r.currentTime)},setVolume:(t,e=0)=>{e>0?o.gain.linearRampToValueAtTime(t,r.currentTime+e):o.gain.setValueAtTime(t,r.currentTime)},stop:(t=0)=>{t>0?(o.gain.linearRampToValueAtTime(0,r.currentTime+t),n.stop(r.currentTime+t+.01)):n.stop()}}}static fm(t,e,i,s,n={}){const{volume:o=.5,startTime:r=bt(this,rt).currentTime}=n,a=bt(this,rt).createOscillator(),h=bt(this,rt).createOscillator(),l=bt(this,rt).createGain(),c=bt(this,rt).createGain();return h.frequency.value=e,l.gain.value=i,a.frequency.value=t,c.gain.value=o,h.connect(l),l.connect(a.frequency),a.connect(c),c.connect(bt(this,at)),c.gain.setValueAtTime(o,r),c.gain.linearRampToValueAtTime(0,r+s),h.start(r),a.start(r),h.stop(r+s+.1),a.stop(r+s+.1),{carrier:a,modulator:h,outputGain:c}}static additive(t,e,i,s={}){const{volume:n=.5,startTime:o=bt(this,rt).currentTime}=s,r=[],a=bt(this,rt).createGain();return a.gain.value=n/e.length,a.connect(bt(this,at)),a.gain.setValueAtTime(n/e.length,o),a.gain.linearRampToValueAtTime(0,o+i),e.forEach((e,s)=>{if(e>0){const n=bt(this,rt).createOscillator(),h=bt(this,rt).createGain();n.frequency.value=t*(s+1),h.gain.value=e,n.connect(h),h.connect(a),n.start(o),n.stop(o+i+.1),r.push(n)}}),r}static sweep(t,e,i,s={}){const{type:n="sine",volume:o=.5,exponential:r=!0,startTime:a=bt(this,rt).currentTime}=s,h=bt(this,rt).createOscillator(),l=bt(this,rt).createGain();return h.type=n,h.frequency.setValueAtTime(t,a),r&&e>0?h.frequency.exponentialRampToValueAtTime(e,a+i):h.frequency.linearRampToValueAtTime(e,a+i),l.gain.setValueAtTime(o,a),l.gain.linearRampToValueAtTime(0,a+i),h.connect(l),l.connect(bt(this,at)),h.start(a),h.stop(a+i+.01),h}static pulse(t,e,i=.5,s={}){const{volume:n=.5,startTime:o=bt(this,rt).currentTime}=s,r=bt(this,rt).createOscillator(),a=bt(this,rt).createOscillator(),h=bt(this,rt).createGain(),l=bt(this,rt).createGain(),c=bt(this,rt).createGain();return r.type="sawtooth",a.type="sawtooth",r.frequency.value=t,a.frequency.value=t,h.gain.value=.5,l.gain.value=-.5,c.gain.setValueAtTime(n,o),c.gain.linearRampToValueAtTime(0,o+e),r.connect(h),a.connect(l),h.connect(c),l.connect(c),c.connect(bt(this,at)),r.start(o),a.start(o),r.stop(o+e+.01),a.stop(o+e+.01),{osc1:r,osc2:a,output:c}}}rt=new WeakMap,at=new WeakMap,wt(Ds,rt,null),wt(Ds,at,null);class Bs{static init(t,e){Mt(this,ht,t),Mt(this,lt,e)}static get ctx(){return bt(this,ht)}static filter(t="lowpass",e=1e3,i=1){const s=bt(this,ht).createBiquadFilter();return s.type=t,s.frequency.value=e,s.Q.value=i,s}static delay(t=.3,e=.4,i=.5){const s=bt(this,ht).createDelay(5),n=bt(this,ht).createGain(),o=bt(this,ht).createGain(),r=bt(this,ht).createGain(),a=bt(this,ht).createGain(),h=bt(this,ht).createGain();return s.delayTime.value=t,n.gain.value=e,o.gain.value=i,r.gain.value=1-i,a.connect(s),a.connect(r),s.connect(n),n.connect(s),s.connect(o),o.connect(h),r.connect(h),{input:a,output:h,setTime:t=>s.delayTime.setValueAtTime(t,bt(this,ht).currentTime),setFeedback:t=>n.gain.setValueAtTime(t,bt(this,ht).currentTime),setMix:t=>{o.gain.setValueAtTime(t,bt(this,ht).currentTime),r.gain.setValueAtTime(1-t,bt(this,ht).currentTime)}}}static reverb(t=2,e=2){const i=bt(this,ht).createConvolver(),s=bt(this,ht).sampleRate,n=s*t,o=bt(this,ht).createBuffer(2,n,s);for(let t=0;t<2;t++){const i=o.getChannelData(t);for(let t=0;t<n;t++)i[t]=(2*Math.random()-1)*Math.pow(1-t/n,e)}return i.buffer=o,i}static distortion(t=50){const e=bt(this,ht).createWaveShaper(),i=t,s=44100,n=new Float32Array(s);for(let t=0;t<s;t++){const e=2*t/s-1;n[t]=(3+i)*e*20*(Math.PI/180)/(Math.PI+i*Math.abs(e))}return e.curve=n,e.oversample="4x",e}static tremolo(t=5,e=.5){const i=bt(this,ht).createOscillator(),s=bt(this,ht).createGain(),n=bt(this,ht).createGain();return i.frequency.value=t,s.gain.value=.5*e,n.gain.value=1-.5*e,i.connect(s),s.connect(n.gain),i.start(),{input:n,output:n,lfo:i,setRate:t=>i.frequency.setValueAtTime(t,bt(this,ht).currentTime),setDepth:t=>s.gain.setValueAtTime(.5*t,bt(this,ht).currentTime),stop:()=>i.stop()}}static compressor(t={}){const{threshold:e=-24,knee:i=30,ratio:s=12,attack:n=.003,release:o=.25}=t,r=bt(this,ht).createDynamicsCompressor();return r.threshold.value=e,r.knee.value=i,r.ratio.value=s,r.attack.value=n,r.release.value=o,r}static panner(t=0){const e=bt(this,ht).createStereoPanner();return e.pan.value=t,e}static gain(t=1){const e=bt(this,ht).createGain();return e.gain.value=t,e}}ht=new WeakMap,lt=new WeakMap,wt(Bs,ht,null),wt(Bs,lt,null);class Is{static white(t,e){const i=t.sampleRate*e,s=t.createBuffer(1,i,t.sampleRate),n=s.getChannelData(0);for(let t=0;t<i;t++)n[t]=2*Math.random()-1;const o=t.createBufferSource();return o.buffer=s,o}static pink(t,e){const i=t.sampleRate*e,s=t.createBuffer(1,i,t.sampleRate),n=s.getChannelData(0);let o=0,r=0,a=0,h=0,l=0,c=0,u=0;for(let t=0;t<i;t++){const e=2*Math.random()-1;o=.99886*o+.0555179*e,r=.99332*r+.0750759*e,a=.969*a+.153852*e,h=.8665*h+.3104856*e,l=.55*l+.5329522*e,c=-.7616*c-.016898*e,n[t]=.11*(o+r+a+h+l+c+u+.5362*e),u=.115926*e}const d=t.createBufferSource();return d.buffer=s,d}static brown(t,e){const i=t.sampleRate*e,s=t.createBuffer(1,i,t.sampleRate),n=s.getChannelData(0);let o=0;for(let t=0;t<i;t++){const e=2*Math.random()-1;n[t]=(o+.02*e)/1.02,o=n[t],n[t]*=3.5}const r=t.createBufferSource();return r.buffer=s,r}}class Es{static noteToFreq(t){const e=t.match(/^([A-G][#b]?)(\d+)$/);if(!e)throw new Error(`Invalid note: ${t}`);const[,i,s]=e,n=this.NOTE_FREQUENCIES[i];if(void 0===n)throw new Error(`Unknown note: ${i}`);return n*Math.pow(2,parseInt(s))}static scale(t,e="major",i=1){const s=this.noteToFreq(t),n=this.SCALES[e];if(!n)throw new Error(`Unknown scale: ${e}`);const o=[];for(let t=0;t<i;t++)for(const e of n)o.push(s*Math.pow(2,(e+12*t)/12));return o}static chord(t,e="major"){const i=this.noteToFreq(t),s=this.CHORDS[e];if(!s)throw new Error(`Unknown chord type: ${e}`);return s.map(t=>i*Math.pow(2,t/12))}static mapToScale(t,e="C4",i="pentatonic",s=2){const n=this.scale(e,i,s),o=Math.max(0,Math.min(1,t));return n[Math.floor(o*n.length)%n.length]}static midiToFreq(t){return 440*Math.pow(2,(t-69)/12)}static freqToMidi(t){return Math.round(12*Math.log2(t/440)+69)}static randomNote(t="C4",e="pentatonic",i=2){const s=this.scale(t,e,i);return s[Math.floor(Math.random()*s.length)]}static detune(t,e){return t*Math.pow(2,e/1200)}}_t(Es,"NOTE_FREQUENCIES",{C:16.35,"C#":17.32,Db:17.32,D:18.35,"D#":19.45,Eb:19.45,E:20.6,F:21.83,"F#":23.12,Gb:23.12,G:24.5,"G#":25.96,Ab:25.96,A:27.5,"A#":29.14,Bb:29.14,B:30.87}),_t(Es,"SCALES",{major:[0,2,4,5,7,9,11],minor:[0,2,3,5,7,8,10],pentatonic:[0,2,4,7,9],pentatonicMinor:[0,3,5,7,10],blues:[0,3,5,6,7,10],dorian:[0,2,3,5,7,9,10],mixolydian:[0,2,4,5,7,9,10],chromatic:[0,1,2,3,4,5,6,7,8,9,10,11],wholeTone:[0,2,4,6,8,10],diminished:[0,2,3,5,6,8,9,11]}),_t(Es,"CHORDS",{major:[0,4,7],minor:[0,3,7],diminished:[0,3,6],augmented:[0,4,8],sus2:[0,2,7],sus4:[0,5,7],major7:[0,4,7,11],minor7:[0,3,7,10],dom7:[0,4,7,10],dim7:[0,3,6,9],add9:[0,4,7,14],power:[0,7]});class Fs{static init(t,e){Mt(this,ct,t),Mt(this,ut,t.createAnalyser()),bt(this,ut).fftSize=2048,e.connect(bt(this,ut)),bt(this,ut).connect(t.destination),Mt(this,dt,new Uint8Array(bt(this,ut).frequencyBinCount)),Mt(this,ft,new Uint8Array(bt(this,ut).frequencyBinCount))}static get isInitialized(){return null!==bt(this,ut)}static get node(){return bt(this,ut)}static setFFTSize(t){bt(this,ut)&&(bt(this,ut).fftSize=t,Mt(this,dt,new Uint8Array(bt(this,ut).frequencyBinCount)),Mt(this,ft,new Uint8Array(bt(this,ut).frequencyBinCount)))}static getWaveform(){return bt(this,ut)?(bt(this,ut).getByteTimeDomainData(bt(this,dt)),bt(this,dt)):new Uint8Array(0)}static getFrequency(){return bt(this,ut)?(bt(this,ut).getByteFrequencyData(bt(this,ft)),bt(this,ft)):new Uint8Array(0)}static getBands(t=8){const e=this.getFrequency();if(0===e.length)return new Array(t).fill(0);const i=Math.floor(e.length/t),s=[];for(let n=0;n<t;n++){let t=0;for(let s=0;s<i;s++)t+=e[n*i+s];s.push(t/(255*i))}return s}static getAmplitude(){const t=this.getWaveform();if(0===t.length)return 0;let e=0;for(let i=0;i<t.length;i++){const s=(t[i]-128)/128;e+=s*s}return Math.sqrt(e/t.length)}static getPeakFrequency(){if(!bt(this,ut)||!bt(this,ct))return 0;const t=this.getFrequency();let e=0,i=0;for(let s=0;s<t.length;s++)t[s]>i&&(i=t[s],e=s);return e*(bt(this,ct).sampleRate/2)/bt(this,ut).frequencyBinCount}static dispose(){bt(this,ut)&&(bt(this,ut).disconnect(),Mt(this,ut,null)),Mt(this,dt,null),Mt(this,ft,null)}}ct=new WeakMap,ut=new WeakMap,dt=new WeakMap,ft=new WeakMap,wt(Fs,ct,null),wt(Fs,ut,null),wt(Fs,dt,null),wt(Fs,ft,null);class Os{static init(t={}){if(bt(this,mt))return void console.warn("[Synth] Already initialized");const{masterVolume:e=.5,sampleRate:i=44100,enableAnalyzer:s=!1}=t;try{Mt(this,pt,new(window.AudioContext||window.webkitAudioContext)({sampleRate:i})),Mt(this,gt,bt(this,pt).createGain()),bt(this,gt).gain.value=e,bt(this,gt).connect(bt(this,pt).destination),Ds.init(bt(this,pt),bt(this,gt)),Bs.init(bt(this,pt),bt(this,gt)),s&&Fs.init(bt(this,pt),bt(this,gt)),Mt(this,mt,!0),console.log("[Synth] Audio system initialized")}catch(t){console.error("[Synth] Failed to initialize audio:",t)}}static get isInitialized(){return bt(this,mt)}static get ctx(){return bt(this,pt)}static get master(){return bt(this,gt)}static get osc(){return Ds}static get fx(){return Bs}static get env(){return zs}static get noise(){return Is}static get music(){return Es}static get analyzer(){return Fs}static async resume(){bt(this,pt)&&"suspended"===bt(this,pt).state&&(await bt(this,pt).resume(),console.log("[Synth] Audio context resumed"))}static async suspend(){bt(this,pt)&&"running"===bt(this,pt).state&&await bt(this,pt).suspend()}static get now(){return bt(this,pt)?bt(this,pt).currentTime:0}static get state(){return bt(this,pt)?bt(this,pt).state:"closed"}static set volume(t){bt(this,gt)&&bt(this,gt).gain.setValueAtTime(Math.max(0,Math.min(1,t)),bt(this,pt).currentTime)}static get volume(){return bt(this,gt)?bt(this,gt).gain.value:0}static chain(...t){for(let e=0;e<t.length-1;e++)t[e].connect(t[e+1]);return{first:t[0],last:t[t.length-1],connectTo:e=>t[t.length-1].connect(e)}}static schedule(t,e){const i=Math.max(0,1e3*(e-this.now));return setTimeout(t,i)}static async close(){bt(this,pt)&&(Fs.dispose(),await bt(this,pt).close(),Mt(this,pt,null),Mt(this,gt,null),Mt(this,mt,!1),console.log("[Synth] Audio system closed"))}}pt=new WeakMap,gt=new WeakMap,mt=new WeakMap,wt(Os,pt,null),wt(Os,gt,null),wt(Os,mt,!1);class Ls{constructor(t={}){this.states=t.states||{},this.currentState=null,this.previousState=null,this.stateTime=0,this.context=t.context||null,this.paused=!1,this.onStateChange=null,t.initial&&this.setState(t.initial)}get state(){return this.currentState}get currentStateConfig(){return this.currentState?this.states[this.currentState]:null}is(t){return this.currentState===t}isAny(...t){return t.includes(this.currentState)}addState(t,e){return this.states[t]=e,this}removeState(t){return delete this.states[t],this}setState(t,e){if(!this.states[t])return console.warn(`StateMachine: Unknown state '${t}'`),!1;if(this.currentState){const t=this.states[this.currentState];(null==t?void 0:t.exit)&&this._call(t.exit,e)}this.previousState=this.currentState,this.currentState=t,this.stateTime=0;const i=this.states[t];return(null==i?void 0:i.enter)&&this._call(i.enter,e),this.onStateChange&&this.onStateChange(t,this.previousState,e),!0}trigger(t,e){const i=this.currentStateConfig;if(!(null==i?void 0:i.on))return!1;const s=i.on[t];return!!s&&("string"==typeof s?this.setState(s,e):!(s.guard&&!this._call(s.guard,e))&&(s.action&&this._call(s.action,e),!!s.target&&this.setState(s.target,e)))}update(t){if(this.paused||!this.currentState)return;this.stateTime+=t;const e=this.states[this.currentState];e&&(e.update&&this._call(e.update,t),void 0!==e.duration&&this.stateTime>=e.duration&&(e.next?this.setState(e.next):e.onComplete&&this._call(e.onComplete)))}get progress(){const t=this.currentStateConfig;return(null==t?void 0:t.duration)?Math.min(1,this.stateTime/t.duration):0}get remaining(){const t=this.currentStateConfig;return(null==t?void 0:t.duration)?Math.max(0,t.duration-this.stateTime):1/0}get isTimed(){var t;return void 0!==(null==(t=this.currentStateConfig)?void 0:t.duration)}pause(){this.paused=!0}resume(){this.paused=!1}reset(t){if(this.stateTime=0,this.previousState=null,t)this.setState(t);else{const t=Object.keys(this.states)[0];t&&this.setState(t)}}_call(t,...e){if("function"==typeof t)return this.context?t.call(this.context,...e):t(...e)}static fromSequence(t,e={}){var i;const s={};for(let i=0;i<t.length;i++){const n=t[i],o=i===t.length-1,r=o?e.loop?t[0].name:null:t[i+1].name;s[n.name]={duration:n.duration,next:r,enter:n.enter,update:n.update,exit:n.exit,onComplete:o&&!e.loop?e.onComplete:void 0}}return new Ls({initial:null==(i=t[0])?void 0:i.name,states:s,context:e.context})}}class Ys{static attract(t,e,i=100,s=1){const n=e.x-t.x,o=e.y-t.y,r=(e.z||0)-(t.z||0),a=n*n+o*o+r*r,h=Math.sqrt(a)||s,l=Math.max(h,s),c=i/(l*l);return{fx:n/h*c,fy:o/h*c,fz:r/h*c,dist:h}}static attractLinear(t,e,i=100){const s=e.x-t.x,n=e.y-t.y,o=(e.z||0)-(t.z||0),r=Math.sqrt(s*s+n*n+o*o)||1;return{fx:s/r*i,fy:n/r*i,fz:o/r*i,dist:r}}static checkCollision(t,e,i=1){const s=e.x-t.x,n=e.y-t.y,o=(e.z||0)-(t.z||0),r=Math.sqrt(s*s+n*n+o*o),a=((t.size||t.radius||1)+(e.size||e.radius||1))*i;return r<a&&r>0?{dist:r,overlap:a-r,dx:s,dy:n,dz:o}:null}static elasticCollision(t,e,i,s=.9){var n,o;const r=t.mass??(null==(n=t.custom)?void 0:n.mass)??1,a=e.mass??(null==(o=e.custom)?void 0:o.mass)??1,h=r+a,l=i.dist||1,c=i.dx/l,u=i.dy/l,d=i.dz/l,f=(t.vx-e.vx)*c+(t.vy-e.vy)*u+((t.vz||0)-(e.vz||0))*d;if(f<0)return null;const p=-(1+s)*f/h;return{v1:{vx:t.vx+p*a*c,vy:t.vy+p*a*u,vz:(t.vz||0)+p*a*d},v2:{vx:e.vx-p*r*c,vy:e.vy-p*r*u,vz:(e.vz||0)-p*r*d}}}static separate(t,e,i,s=.5){var n,o;const r=t.mass??(null==(n=t.custom)?void 0:n.mass)??1,a=e.mass??(null==(o=e.custom)?void 0:o.mass)??1,h=r+a,l=i.dist||1,c=i.dx/l,u=i.dy/l,d=i.dz/l,f=i.overlap*s,p=f*(a/h),g=f*(r/h);t.x-=c*p,t.y-=u*p,void 0!==t.z&&(t.z-=d*p),e.x+=c*g,e.y+=u*g,void 0!==e.z&&(e.z+=d*g)}static boundsCollision(t,e,i=.9){const s=(t.size||t.radius||1)/2;let n=!1;if(void 0!==e.minX){const o=e.minX+s,r=e.maxX-s;t.x<o?(t.x=o,t.vx<0&&(t.vx=-t.vx*i),n=!0):t.x>r&&(t.x=r,t.vx>0&&(t.vx=-t.vx*i),n=!0)}if(void 0!==e.minY){const o=e.minY+s,r=e.maxY-s;t.y<o?(t.y=o,t.vy<0&&(t.vy=-t.vy*i),n=!0):t.y>r&&(t.y=r,t.vy>0&&(t.vy=-t.vy*i),n=!0)}if(void 0!==e.minZ&&void 0!==t.z){const o=e.minZ+s,r=e.maxZ-s;t.z<o?(t.z=o,t.vz<0&&(t.vz=-t.vz*i),n=!0):t.z>r&&(t.z=r,t.vz>0&&(t.vz=-t.vz*i),n=!0)}return n}static sphereBoundsCollision(t,e,i=.9,s=!0){const n=t.x-e.x,o=t.y-e.y,r=(t.z||0)-(e.z||0),a=Math.sqrt(n*n+o*o+r*r),h=(t.size||t.radius||1)/2,l=e.radius-h;if(s&&a>l){const s=n/a,h=o/a,c=r/a;t.x=e.x+s*l,t.y=e.y+h*l,void 0!==t.z&&(t.z=e.z+c*l);const u=t.vx*s+t.vy*h+(t.vz||0)*c;return u>0&&(t.vx-=2*u*s*i,t.vy-=2*u*h*i,void 0!==t.vz&&(t.vz-=2*u*c*i)),!0}return!1}static kineticEnergy(t){var e;const i=t.vx||0,s=t.vy||0,n=t.vz||0;return.5*(t.mass??(null==(e=t.custom)?void 0:e.mass)??1)*(i*i+s*s+n*n)}static speed(t){const e=t.vx||0,i=t.vy||0,s=t.vz||0;return Math.sqrt(e*e+i*i+s*s)}static distance(t,e){const i=e.x-t.x,s=e.y-t.y,n=(e.z||0)-(t.z||0);return Math.sqrt(i*i+s*s+n*n)}static distanceSquared(t,e){const i=e.x-t.x,s=e.y-t.y,n=(e.z||0)-(t.z||0);return i*i+s*s+n*n}static clampVelocity(t,e){const i=Ys.speed(t);if(i>e){const s=e/i;t.vx*=s,t.vy*=s,void 0!==t.vz&&(t.vz*=s)}}static applyForce(t,e,i,s,n){var o;const r=t.mass??(null==(o=t.custom)?void 0:o.mass)??1,a=r>0?1/r:0;t.vx+=e*a*n,t.vy+=i*a*n,void 0!==t.vz&&(t.vz+=(s||0)*a*n)}}const Xs={mutualAttraction:(t=100,e=200,i=5)=>{const s=e*e;return(e,n,o)=>{var r,a;if(!e.alive)return;const h=o.particles,l=e.mass??(null==(r=e.custom)?void 0:r.mass)??1;for(let o=0;o<h.length;o++){const r=h[o];if(r===e||!r.alive)continue;const c=r.x-e.x,u=r.y-e.y,d=(r.z||0)-(e.z||0),f=c*c+u*u+d*d;if(f>s||f<.01)continue;const p=Math.sqrt(f),g=Math.max(p,i),m=r.mass??(null==(a=r.custom)?void 0:a.mass)??1,v=t*l*m/(g*g)*n/p;e.vx+=c*v,e.vy+=u*v,void 0!==e.vz&&(e.vz+=d*v)}}},mutualAttractionLinear:(t=50,e=100)=>{const i=e*e;return(e,s,n)=>{if(e.alive)for(const o of n.particles){if(o===e||!o.alive)continue;const n=o.x-e.x,r=o.y-e.y,a=(o.z||0)-(e.z||0),h=n*n+r*r+a*a;if(h>i||h<.01)continue;const l=Math.sqrt(h),c=t*s/l;e.vx+=n*c,e.vy+=r*c,void 0!==e.vz&&(e.vz+=a*c)}}},particleCollisions:(t=.9,e=1)=>{const i=new Set;return(s,n,o)=>{if(!s.alive)return;0===o.particles.indexOf(s)&&i.clear();const r=o.particles.indexOf(s);for(let n=r+1;n<o.particles.length;n++){const a=o.particles[n];if(!a.alive)continue;const h=`${r}-${n}`;if(i.has(h))continue;const l=Ys.checkCollision(s,a,e);if(l){i.add(h),Ys.separate(s,a,l,.5);const e=Ys.elasticCollision(s,a,l,t);e&&(s.vx=e.v1.vx,s.vy=e.v1.vy,s.vz=e.v1.vz,a.vx=e.v2.vx,a.vy=e.v2.vy,a.vz=e.v2.vz)}}}},bounds3D:(t,e=.9)=>(i,s)=>{i.alive&&Ys.boundsCollision(i,t,e)},sphereBounds:(t,e=.9)=>(i,s)=>{i.alive&&Ys.sphereBoundsCollision(i,t,e,!0)},attractToPoint:(t,e=100,i=10)=>(s,n)=>{if(!s.alive)return;const o="function"==typeof t?t():t,r=Ys.attract(s,o,e,i);s.vx+=r.fx*n,s.vy+=r.fy*n,void 0!==s.vz&&(s.vz+=r.fz*n)},gravity:(t=0,e=200,i=0)=>(s,n)=>{s.alive&&(s.vx+=t*n,s.vy+=e*n,void 0!==s.vz&&(s.vz+=i*n))},maxSpeed:t=>(e,i)=>{e.alive&&Ys.clampVelocity(e,t)},drag:(t=.01)=>(e,i)=>{if(!e.alive)return;const s=Ys.speed(e);if(s>.01){const n=t*s*s,o=Math.max(0,1-n*i/s);e.vx*=o,e.vy*=o,void 0!==e.vz&&(e.vz*=o)}},separation:(t=100,e=1.2)=>(i,s,n)=>{if(i.alive)for(const o of n.particles){if(o===i||!o.alive)continue;const n=Ys.checkCollision(i,o,e);if(n){const e=t*n.overlap,o=-n.dx/n.dist,r=-n.dy/n.dist,a=-n.dz/n.dist;i.vx+=o*e*s,i.vy+=r*e*s,void 0!==i.vz&&(i.vz+=a*e*s)}}},thermal:(t,e=10)=>(i,s)=>{if(!i.alive)return;const n=("function"==typeof t?t():t)*e*s;i.vx+=(Math.random()-.5)*n,i.vy+=(Math.random()-.5)*n,void 0!==i.vz&&(i.vz+=(Math.random()-.5)*n)},orbital:(t,e=100)=>(i,s)=>{if(!i.alive)return;const n=t.x-i.x,o=t.y-i.y,r=(t.z||0)-(i.z||0),a=Math.sqrt(n*n+o*o+r*r)||1,h=e/a;i.vx+=n/a*h*s,i.vy+=o/a*h*s,void 0!==i.vz&&(i.vz+=r/a*h*s)}},Ws="\nprecision highp float;\n\nattribute vec2 aPosition; // random seed in [-1, 1]\n\nuniform float uTime;\nuniform vec4 uParams; // (a, b, c, d)\nuniform int uIterations; // 0..200\nuniform mat3 uTransform; // clip-space transform\nuniform float uZoom;\nuniform float uPointScale;\nuniform float uPointSize;\nuniform int uColorMode;\nuniform vec4 uColor; // non-premultiplied RGBA (0..1)\nuniform vec2 uHueRange; // (minHue, maxHue)\nuniform float uMaxSpeed;\nuniform float uSaturation; // 0..1\nuniform float uLightness; // 0..1\nuniform float uAlpha; // 0..1\nuniform float uHueOffset; // degrees\n\nvarying vec4 vColor;\n\n// HSL to RGB (all 0..1). Based on a compact shader formulation.\nvec3 hsl2rgb(vec3 hsl) {\n vec3 rgb = clamp(abs(mod(hsl.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);\n rgb = rgb * rgb * (3.0 - 2.0 * rgb);\n float c = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\n return (rgb - 0.5) * c + hsl.z;\n}\n\nvoid main() {\n vec2 p = aPosition;\n vec2 lastDelta = vec2(0.0);\n\n // De Jong iterative map\n // x' = sin(a*y) - cos(b*x)\n // y' = sin(c*x) - cos(d*y)\n for (int i = 0; i < 200; i++) {\n if (i >= uIterations) break;\n vec2 prev = p;\n float x = sin(uParams.x * p.y) - cos(uParams.y * p.x);\n float y = sin(uParams.z * p.x) - cos(uParams.w * p.y);\n p = vec2(x, y);\n lastDelta = p - prev;\n }\n\n // Map attractor space into clip space\n vec3 transformed = uTransform * vec3(p * uPointScale * uZoom, 1.0);\n gl_Position = vec4(transformed.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n\n // Color\n vec4 c;\n if (uColorMode == 1) {\n // Lorenz-like mapping: slow → maxHue, fast → minHue\n float speed = length(lastDelta);\n float speedNorm = clamp(speed / max(uMaxSpeed, 0.0001), 0.0, 1.0);\n float baseHue = uHueRange.y - speedNorm * (uHueRange.y - uHueRange.x);\n float hue = mod(baseHue + uHueOffset, 360.0);\n vec3 rgb = hsl2rgb(vec3(hue / 360.0, clamp(uSaturation, 0.0, 1.0), clamp(uLightness, 0.0, 1.0)));\n c = vec4(rgb, clamp(uAlpha, 0.0, 1.0));\n } else {\n c = uColor;\n }\n\n // Premultiply in shader (renderer uses premultipliedAlpha for compositing)\n c.rgb *= c.a;\n vColor = c;\n}\n",Hs={circle:ms,glow:vs,square:ys,softSquare:_s};class Us{constructor(t=1<<18,e={}){var i,s,n,o;if(this.seedCount=t,this.width=e.width??800,this.height=e.height??600,this.shape=e.shape??"glow",this.blendMode=e.blendMode??"additive",this.pointSize=e.pointSize??1,this.pointScale=e.pointScale??.5,this.iterations=Math.max(0,Math.min(200,e.iterations??100)),this.params={a:(null==(i=e.params)?void 0:i.a)??-2,b:(null==(s=e.params)?void 0:s.b)??-2,c:(null==(n=e.params)?void 0:n.c)??-1.2,d:(null==(o=e.params)?void 0:o.d)??2},this.zoom=1,this.transform=Us.identityMat3(),this.color=e.color??{r:1,g:1,b:1,a:.12},this.colorMode=e.colorMode??0,this.hueRange=e.hueRange??{minHue:30,maxHue:200},this.maxSpeed=e.maxSpeed??1,this.saturation=e.saturation??.85,this.lightness=e.lightness??.55,this.alpha=e.alpha??this.color.a??.12,this.hueShiftSpeed=e.hueShiftSpeed??0,this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!1,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for DeJong renderer"),void(this.available=!1);this.available=!0,this._initGL(),this._createSeedBuffer(t),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}isAvailable(){return Boolean(this.available)}static identityMat3(){return new Float32Array([1,0,0,0,1,0,0,0,1])}static rotationMat3(t){const e=Math.cos(t),i=Math.sin(t);return new Float32Array([e,i,0,-i,e,0,0,0,1])}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_createSeedBuffer(t){const e=this.gl;this._seeds=new Float32Array(2*t);for(let t=0;t<this._seeds.length;t++)this._seeds[t]=2*Math.random()-1;this.seedBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.bufferData(e.ARRAY_BUFFER,this._seeds,e.STATIC_DRAW)}regenerateSeeds(){if(!this.available)return;for(let t=0;t<this._seeds.length;t++)this._seeds[t]=2*Math.random()-1;const t=this.gl;t.bindBuffer(t.ARRAY_BUFFER,this.seedBuffer),t.bufferData(t.ARRAY_BUFFER,this._seeds,t.STATIC_DRAW)}setSeedCount(t){if(!this.available)return;if(t===this.seedCount)return;this.seedCount=t;const e=this.gl;this.seedBuffer&&e.deleteBuffer(this.seedBuffer),this._createSeedBuffer(t)}_compileProgram(){const t=this.gl,e=Hs[this.shape]??Hs.glow,i=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(i,Ws),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))return console.error("DeJong vertex shader error:",t.getShaderInfoLog(i)),void(this.available=!1);const s=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(s,e),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,i),t.attachShader(this.program,s),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.uTime=t.getUniformLocation(this.program,"uTime"),this.uParams=t.getUniformLocation(this.program,"uParams"),this.uIterations=t.getUniformLocation(this.program,"uIterations"),this.uTransform=t.getUniformLocation(this.program,"uTransform"),this.uZoom=t.getUniformLocation(this.program,"uZoom"),this.uPointScale=t.getUniformLocation(this.program,"uPointScale"),this.uPointSize=t.getUniformLocation(this.program,"uPointSize"),this.uColorMode=t.getUniformLocation(this.program,"uColorMode"),this.uColor=t.getUniformLocation(this.program,"uColor"),this.uHueRange=t.getUniformLocation(this.program,"uHueRange"),this.uMaxSpeed=t.getUniformLocation(this.program,"uMaxSpeed"),this.uSaturation=t.getUniformLocation(this.program,"uSaturation"),this.uLightness=t.getUniformLocation(this.program,"uLightness"),this.uAlpha=t.getUniformLocation(this.program,"uAlpha"),this.uHueOffset=t.getUniformLocation(this.program,"uHueOffset"),t.deleteShader(i),void t.deleteShader(s)):(console.error("DeJong program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("DeJong fragment shader error:",t.getShaderInfoLog(s)),void(this.available=!1))}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}setShape(t){if(t===this.shape)return;if(this.shape=t,!this.available)return;const e=this.gl;this.program&&e.deleteProgram(this.program),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}_applyStaticUniforms(){if(!this.available)return;const t=this.gl;t.useProgram(this.program),this.uPointScale&&t.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&t.uniform1f(this.uPointSize,this.pointSize)}setColorMode(t){this.colorMode=1===t?1:0}setColorRamp(t={}){void 0!==t.minHue&&(this.hueRange.minHue=t.minHue),void 0!==t.maxHue&&(this.hueRange.maxHue=t.maxHue),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed),void 0!==t.saturation&&(this.saturation=t.saturation),void 0!==t.lightness&&(this.lightness=t.lightness),void 0!==t.alpha&&(this.alpha=t.alpha),void 0!==t.hueShiftSpeed&&(this.hueShiftSpeed=t.hueShiftSpeed)}setParams(t){this.params={...this.params,...t}}setIterations(t){this.iterations=Math.max(0,Math.min(200,Math.floor(t)))}setZoom(t){this.zoom=t}setTransform(t){this.transform=t}setPointSize(t){this.pointSize=t,this.available&&this.uPointSize&&(this.gl.useProgram(this.program),this.gl.uniform1f(this.uPointSize,t))}setColor(t){this.color={...this.color,...t}}resize(t,e){this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available&&this.gl.viewport(0,0,t,e)}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t=0){if(!this.available)return;const e=this.gl;e.useProgram(this.program),this.uTime&&e.uniform1f(this.uTime,t),this.uParams&&e.uniform4f(this.uParams,this.params.a,this.params.b,this.params.c,this.params.d),this.uIterations&&e.uniform1i(this.uIterations,this.iterations),this.uTransform&&e.uniformMatrix3fv(this.uTransform,!1,this.transform),this.uZoom&&e.uniform1f(this.uZoom,this.zoom),this.uPointScale&&e.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&e.uniform1f(this.uPointSize,this.pointSize),this.uColor&&e.uniform4f(this.uColor,this.color.r,this.color.g,this.color.b,this.color.a),this.uColorMode&&e.uniform1i(this.uColorMode,this.colorMode),this.uHueRange&&e.uniform2f(this.uHueRange,this.hueRange.minHue,this.hueRange.maxHue),this.uMaxSpeed&&e.uniform1f(this.uMaxSpeed,this.maxSpeed),this.uSaturation&&e.uniform1f(this.uSaturation,this.saturation),this.uLightness&&e.uniform1f(this.uLightness,this.lightness),this.uAlpha&&e.uniform1f(this.uAlpha,this.alpha),this.uHueOffset&&e.uniform1f(this.uHueOffset,t*this.hueShiftSpeed%360),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.drawArrays(e.POINTS,0,this.seedCount)}compositeOnto(t,e=0,i=0,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),this.seedBuffer&&t.deleteBuffer(this.seedBuffer),this._seeds=null}}const Gs="\nprecision highp float;\n\nattribute vec2 aPosition; // random seed in [-1, 1]\n\nuniform float uTime;\nuniform vec4 uParams; // (a, b, c, d)\nuniform int uIterations; // 0..200\nuniform mat3 uTransform; // clip-space transform\nuniform float uZoom;\nuniform float uPointScale;\nuniform float uPointSize;\nuniform int uColorMode;\nuniform vec4 uColor; // non-premultiplied RGBA (0..1)\nuniform vec2 uHueRange; // (minHue, maxHue)\nuniform float uMaxSpeed;\nuniform float uSaturation; // 0..1\nuniform float uLightness; // 0..1\nuniform float uAlpha; // 0..1\nuniform float uHueOffset; // degrees\n\nvarying vec4 vColor;\n\n// HSL to RGB (all 0..1). Based on a compact shader formulation.\nvec3 hsl2rgb(vec3 hsl) {\n vec3 rgb = clamp(abs(mod(hsl.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);\n rgb = rgb * rgb * (3.0 - 2.0 * rgb);\n float c = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\n return (rgb - 0.5) * c + hsl.z;\n}\n\nvoid main() {\n vec2 p = aPosition;\n vec2 lastDelta = vec2(0.0);\n\n // Clifford iterative map\n // x' = sin(a*y) + c*cos(a*x)\n // y' = sin(b*x) + d*cos(b*y)\n for (int i = 0; i < 200; i++) {\n if (i >= uIterations) break;\n vec2 prev = p;\n float x = sin(uParams.x * p.y) + uParams.z * cos(uParams.x * p.x);\n float y = sin(uParams.y * p.x) + uParams.w * cos(uParams.y * p.y);\n p = vec2(x, y);\n lastDelta = p - prev;\n }\n\n // Map attractor space into clip space\n vec3 transformed = uTransform * vec3(p * uPointScale * uZoom, 1.0);\n gl_Position = vec4(transformed.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n\n // Color\n vec4 c;\n if (uColorMode == 1) {\n float speed = length(lastDelta);\n float speedNorm = clamp(speed / max(uMaxSpeed, 0.0001), 0.0, 1.0);\n float baseHue = uHueRange.y - speedNorm * (uHueRange.y - uHueRange.x);\n float hue = mod(baseHue + uHueOffset, 360.0);\n vec3 rgb = hsl2rgb(vec3(hue / 360.0, clamp(uSaturation, 0.0, 1.0), clamp(uLightness, 0.0, 1.0)));\n c = vec4(rgb, clamp(uAlpha, 0.0, 1.0));\n } else {\n c = uColor;\n }\n\n // Premultiply in shader (renderer uses premultipliedAlpha for compositing)\n c.rgb *= c.a;\n vColor = c;\n}\n",Ns={circle:ms,glow:vs,square:ys,softSquare:_s};class qs{constructor(t=1<<18,e={}){var i,s,n,o;if(this.seedCount=t,this.width=e.width??800,this.height=e.height??600,this.shape=e.shape??"glow",this.blendMode=e.blendMode??"additive",this.pointSize=e.pointSize??1,this.pointScale=e.pointScale??.5,this.iterations=Math.max(0,Math.min(200,e.iterations??120)),this.params={a:(null==(i=e.params)?void 0:i.a)??-1.4,b:(null==(s=e.params)?void 0:s.b)??1.6,c:(null==(n=e.params)?void 0:n.c)??1,d:(null==(o=e.params)?void 0:o.d)??.7},this.zoom=1,this.transform=qs.identityMat3(),this.color=e.color??{r:1,g:1,b:1,a:.12},this.colorMode=e.colorMode??0,this.hueRange=e.hueRange??{minHue:180,maxHue:300},this.maxSpeed=e.maxSpeed??1,this.saturation=e.saturation??.85,this.lightness=e.lightness??.55,this.alpha=e.alpha??this.color.a??.12,this.hueShiftSpeed=e.hueShiftSpeed??0,this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!1,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for Clifford renderer"),void(this.available=!1);this.available=!0,this._initGL(),this._createSeedBuffer(t),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}isAvailable(){return Boolean(this.available)}static identityMat3(){return new Float32Array([1,0,0,0,1,0,0,0,1])}static rotationMat3(t){const e=Math.cos(t),i=Math.sin(t);return new Float32Array([e,i,0,-i,e,0,0,0,1])}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_createSeedBuffer(t){const e=this.gl;this._seeds=new Float32Array(2*t);for(let t=0;t<this._seeds.length;t++)this._seeds[t]=2*Math.random()-1;this.seedBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.bufferData(e.ARRAY_BUFFER,this._seeds,e.STATIC_DRAW)}regenerateSeeds(){if(!this.available)return;for(let t=0;t<this._seeds.length;t++)this._seeds[t]=2*Math.random()-1;const t=this.gl;t.bindBuffer(t.ARRAY_BUFFER,this.seedBuffer),t.bufferData(t.ARRAY_BUFFER,this._seeds,t.STATIC_DRAW)}setSeedCount(t){if(!this.available)return;if(t===this.seedCount)return;this.seedCount=t;const e=this.gl;this.seedBuffer&&e.deleteBuffer(this.seedBuffer),this._createSeedBuffer(t)}_compileProgram(){const t=this.gl,e=Ns[this.shape]??Ns.glow,i=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(i,Gs),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))return console.error("Clifford vertex shader error:",t.getShaderInfoLog(i)),void(this.available=!1);const s=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(s,e),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,i),t.attachShader(this.program,s),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.uTime=t.getUniformLocation(this.program,"uTime"),this.uParams=t.getUniformLocation(this.program,"uParams"),this.uIterations=t.getUniformLocation(this.program,"uIterations"),this.uTransform=t.getUniformLocation(this.program,"uTransform"),this.uZoom=t.getUniformLocation(this.program,"uZoom"),this.uPointScale=t.getUniformLocation(this.program,"uPointScale"),this.uPointSize=t.getUniformLocation(this.program,"uPointSize"),this.uColorMode=t.getUniformLocation(this.program,"uColorMode"),this.uColor=t.getUniformLocation(this.program,"uColor"),this.uHueRange=t.getUniformLocation(this.program,"uHueRange"),this.uMaxSpeed=t.getUniformLocation(this.program,"uMaxSpeed"),this.uSaturation=t.getUniformLocation(this.program,"uSaturation"),this.uLightness=t.getUniformLocation(this.program,"uLightness"),this.uAlpha=t.getUniformLocation(this.program,"uAlpha"),this.uHueOffset=t.getUniformLocation(this.program,"uHueOffset"),t.deleteShader(i),void t.deleteShader(s)):(console.error("Clifford program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("Clifford fragment shader error:",t.getShaderInfoLog(s)),void(this.available=!1))}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}setShape(t){if(t===this.shape)return;if(this.shape=t,!this.available)return;const e=this.gl;this.program&&e.deleteProgram(this.program),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}_applyStaticUniforms(){if(!this.available)return;const t=this.gl;t.useProgram(this.program),this.uPointScale&&t.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&t.uniform1f(this.uPointSize,this.pointSize)}setColorMode(t){this.colorMode=1===t?1:0}setColorRamp(t={}){void 0!==t.minHue&&(this.hueRange.minHue=t.minHue),void 0!==t.maxHue&&(this.hueRange.maxHue=t.maxHue),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed),void 0!==t.saturation&&(this.saturation=t.saturation),void 0!==t.lightness&&(this.lightness=t.lightness),void 0!==t.alpha&&(this.alpha=t.alpha),void 0!==t.hueShiftSpeed&&(this.hueShiftSpeed=t.hueShiftSpeed)}setParams(t){this.params={...this.params,...t}}setIterations(t){this.iterations=Math.max(0,Math.min(200,Math.floor(t)))}setZoom(t){this.zoom=t}setTransform(t){this.transform=t}setPointSize(t){this.pointSize=t,this.available&&this.uPointSize&&(this.gl.useProgram(this.program),this.gl.uniform1f(this.uPointSize,t))}setColor(t){this.color={...this.color,...t}}resize(t,e){this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available&&this.gl.viewport(0,0,t,e)}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t=0){if(!this.available)return;const e=this.gl;e.useProgram(this.program),this.uTime&&e.uniform1f(this.uTime,t),this.uParams&&e.uniform4f(this.uParams,this.params.a,this.params.b,this.params.c,this.params.d),this.uIterations&&e.uniform1i(this.uIterations,this.iterations),this.uTransform&&e.uniformMatrix3fv(this.uTransform,!1,this.transform),this.uZoom&&e.uniform1f(this.uZoom,this.zoom),this.uPointScale&&e.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&e.uniform1f(this.uPointSize,this.pointSize),this.uColor&&e.uniform4f(this.uColor,this.color.r,this.color.g,this.color.b,this.color.a),this.uColorMode&&e.uniform1i(this.uColorMode,this.colorMode),this.uHueRange&&e.uniform2f(this.uHueRange,this.hueRange.minHue,this.hueRange.maxHue),this.uMaxSpeed&&e.uniform1f(this.uMaxSpeed,this.maxSpeed),this.uSaturation&&e.uniform1f(this.uSaturation,this.saturation),this.uLightness&&e.uniform1f(this.uLightness,this.lightness),this.uAlpha&&e.uniform1f(this.uAlpha,this.alpha),this.uHueOffset&&e.uniform1f(this.uHueOffset,t*this.hueShiftSpeed%360),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.drawArrays(e.POINTS,0,this.seedCount)}compositeOnto(t,e=0,i=0,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),this.seedBuffer&&t.deleteBuffer(this.seedBuffer),this._seeds=null}}t.AdvancedDelay=class{constructor(t,e={}){this.audioContext=t;const{delayTime:i=.15,maxDelay:s=.5,feedback:n=.2,wet:o=.15,dry:r=.85}=e;this.delay=t.createDelay(s),this.delay.delayTime.value=i,this.feedbackGain=t.createGain(),this.feedbackGain.gain.value=n,this.wetGain=t.createGain(),this.wetGain.gain.value=o,this.dryGain=t.createGain(),this.dryGain.gain.value=r,this.output=t.createGain(),this.output.gain.value=1,this.delay.connect(this.feedbackGain),this.feedbackGain.connect(this.delay),this.input=t.createGain()}connect(t){t.connect(this.dryGain),this.dryGain.connect(this.output),t.connect(this.delay),this.delay.connect(this.wetGain),this.wetGain.connect(this.output)}setDelayTime(t){this.delay.delayTime.value=t}setMix(t,e){this.wetGain.gain.value=t,this.dryGain.gain.value=e}setFeedback(t){this.feedbackGain.gain.value=t}getOutput(){return this.output}disconnect(){try{this.delay.disconnect(),this.feedbackGain.disconnect(),this.wetGain.disconnect(),this.dryGain.disconnect(),this.input.disconnect(),this.output.disconnect()}catch(t){}}},t.AdvancedDistortion=class{constructor(t,e={}){this.audioContext=t;const{amount:i=0,oversample:s="4x"}=e;this.shaper=t.createWaveShaper(),this.shaper.oversample=s,this.amount=i,this.updateCurve(i)}updateCurve(t){const e=44100,i=new Float32Array(e),s=Math.PI/180,n=400*t;for(let t=0;t<e;t++){const o=2*t/e-1;i[t]=0===n?o:(3+n)*o*20*s/(Math.PI+n*Math.abs(o))}this.shaper.curve=i,this.amount=t}connect(t){t.connect(this.shaper)}setAmount(t){this.updateCurve(t)}getNode(){return this.shaper}disconnect(){try{this.shaper.disconnect()}catch(t){}}},t.AdvancedTremolo=class{constructor(t,e={}){this.audioContext=t;const{rate:i=4,depth:s=0,lfoType:n="sine"}=e;this.gain=t.createGain(),this.gain.gain.value=1,this.lfo=t.createOscillator(),this.lfo.type=n,this.lfo.frequency.value=i,this.depthGain=t.createGain(),this.depthGain.gain.value=s,this.lfo.connect(this.depthGain),this.depthGain.connect(this.gain.gain),this.lfo.start()}connect(t){t.connect(this.gain)}setRate(t){this.lfo.frequency.value=t}setDepth(t){this.depthGain.gain.value=t}getNode(){return this.gain}disconnect(){try{this.lfo.stop(),this.lfo.disconnect(),this.depthGain.disconnect(),this.gain.disconnect()}catch(t){}}},t.Arc=$e,t.Arrow=vi,t.AttractorDimension=ee,t.AttractorType=te,t.Attractors=ie,t.BezierShape=class extends Ze{constructor(t=[],e={}){super(e),this.path=t}draw(){super.draw(),Le.lines.path(this.path,this.color,this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:100,height:100}}},t.BooleanAlgebra=Qt,t.Button=us,t.CLIFFORD_MAX_ITERATIONS=200,t.CLIFFORD_POINT_FRAGMENTS=Ns,t.CLIFFORD_POINT_VERTEX=Gs,t.Camera2D=Bt,t.Camera3D=class{constructor(t={}){this.rotationX=t.rotationX??0,this.rotationY=t.rotationY??0,this.rotationZ=t.rotationZ??0,this.x=t.x??0,this.y=t.y??0,this.z=t.z??0,this._initialRotationX=this.rotationX,this._initialRotationY=this.rotationY,this._initialRotationZ=this.rotationZ,this._initialX=this.x,this._initialY=this.y,this._initialZ=this.z,this.perspective=t.perspective??800,this.sensitivity=t.sensitivity??.005,this.minRotationX=t.minRotationX??-1.5,this.maxRotationX=t.maxRotationX??1.5,this.clampX=t.clampX??!0,this.autoRotate=t.autoRotate??!1,this.autoRotateSpeed=t.autoRotateSpeed??.5,this.autoRotateAxis=t.autoRotateAxis??"y",this.inertia=t.inertia??!1,this.friction=t.friction??.92,this.velocityScale=t.velocityScale??1,this._velocityX=0,this._velocityY=0,this._lastDeltaX=0,this._lastDeltaY=0,this._lastMoveTime=0,this._isDragging=!1,this._lastMouseX=0,this._lastMouseY=0,this._canvas=null,this._boundHandlers=null,this._followTarget=null,this._followOffset={x:0,y:0,z:0},this._followLookAt=!0,this._followLerp=.1,this._targetX=null,this._targetY=null,this._targetZ=null,this._targetRotationX=null,this._targetRotationY=null,this._positionLerp=.05}project(t,e,i){if(t-=this.x,e-=this.y,i-=this.z,0!==this.rotationZ){const i=Math.cos(this.rotationZ),s=Math.sin(this.rotationZ),n=t;t=n*i-e*s,e=n*s+e*i}const s=Math.cos(this.rotationY),n=Math.sin(this.rotationY),o=t*s-i*n,r=t*n+i*s,a=Math.cos(this.rotationX),h=Math.sin(this.rotationX),l=e*a-r*h,c=e*h+r*a,u=this.perspective/(this.perspective+c);return{x:o*u,y:l*u,z:c,scale:u}}projectAll(t){return t.map(t=>this.project(t.x,t.y,t.z))}update(t){var e,i,s;if(this._followTarget){const t=this._followTarget,n=(t.x??0)+this._followOffset.x,o=(t.y??0)+this._followOffset.y,r=(t.z??0)+this._followOffset.z;if(this.x+=(n-this.x)*this._followLerp,this.y+=(o-this.y)*this._followLerp,this.z+=(r-this.z)*this._followLerp,this._followLookAt){const t=(null==(e=this._followLookAtTarget)?void 0:e.x)??0,n=(null==(i=this._followLookAtTarget)?void 0:i.y)??0,o=(null==(s=this._followLookAtTarget)?void 0:s.z)??0,r=t-this.x,a=n-this.y,h=o-this.z,l=Math.sqrt(r*r+h*h),c=Math.atan2(r,h),u=Math.atan2(-a,l);this.rotationY+=this._angleDiff(this.rotationY,c)*this._followLerp,this.rotationX+=(u-this.rotationX)*this._followLerp}}else if(null!==this._targetX){const t=this._positionLerp;this.x+=(this._targetX-this.x)*t,this.y+=(this._targetY-this.y)*t,this.z+=(this._targetZ-this.z)*t,null!==this._targetRotationX&&(this.rotationX+=(this._targetRotationX-this.rotationX)*t),null!==this._targetRotationY&&(this.rotationY+=this._angleDiff(this.rotationY,this._targetRotationY)*t),Math.abs(this._targetX-this.x)+Math.abs(this._targetY-this.y)+Math.abs(this._targetZ-this.z)<.1&&(this.x=this._targetX,this.y=this._targetY,this.z=this._targetZ,this._targetX=null,this._targetY=null,this._targetZ=null,this._targetRotationX=null,this._targetRotationY=null)}if(!this.inertia||this._isDragging||this._followTarget||(Math.abs(this._velocityX)>1e-4||Math.abs(this._velocityY)>1e-4)&&(this.rotationY+=this._velocityY,this.rotationX+=this._velocityX,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this._velocityX*=this.friction,this._velocityY*=this.friction,Math.abs(this._velocityX)<1e-4&&(this._velocityX=0),Math.abs(this._velocityY)<1e-4&&(this._velocityY=0)),this.autoRotate&&!this._isDragging&&!this._followTarget&&!(Math.abs(this._velocityX)>.001||Math.abs(this._velocityY)>.001)){const e=this.autoRotateSpeed*t;switch(this.autoRotateAxis){case"x":this.rotationX+=e;break;case"y":this.rotationY+=e;break;case"z":this.rotationZ+=e}}}_angleDiff(t,e){let i=e-t;for(;i>Math.PI;)i-=2*Math.PI;for(;i<-Math.PI;)i+=2*Math.PI;return i}enableMouseControl(t,e={}){this._canvas&&this.disableMouseControl(),this._canvas=t;const i=e.invertX?-1:1,s=e.invertY?-1:1;return this._boundHandlers={mousedown:t=>{this._isDragging=!0,this._lastMouseX=t.clientX,this._lastMouseY=t.clientY,this._lastMoveTime=performance.now(),this._velocityX=0,this._velocityY=0},mousemove:t=>{if(!this._isDragging)return;const e=t.clientX-this._lastMouseX,n=t.clientY-this._lastMouseY,o=e*this.sensitivity*i,r=n*this.sensitivity*s;this.rotationY+=o,this.rotationX+=r,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this.inertia&&(this._lastDeltaX=r,this._lastDeltaY=o,this._lastMoveTime=performance.now()),this._lastMouseX=t.clientX,this._lastMouseY=t.clientY},mouseup:()=>{this.inertia&&this._isDragging&&performance.now()-this._lastMoveTime<50&&(this._velocityX=this._lastDeltaX*this.velocityScale,this._velocityY=this._lastDeltaY*this.velocityScale),this._isDragging=!1},mouseleave:()=>{this.inertia&&this._isDragging&&performance.now()-this._lastMoveTime<50&&(this._velocityX=this._lastDeltaX*this.velocityScale,this._velocityY=this._lastDeltaY*this.velocityScale),this._isDragging=!1},touchstart:t=>{1===t.touches.length&&(this._isDragging=!0,this._lastMouseX=t.touches[0].clientX,this._lastMouseY=t.touches[0].clientY,this._lastMoveTime=performance.now(),this._velocityX=0,this._velocityY=0)},touchmove:t=>{if(!this._isDragging||1!==t.touches.length)return;t.preventDefault();const e=t.touches[0].clientX-this._lastMouseX,n=t.touches[0].clientY-this._lastMouseY,o=e*this.sensitivity*i,r=n*this.sensitivity*s;this.rotationY+=o,this.rotationX+=r,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this.inertia&&(this._lastDeltaX=r,this._lastDeltaY=o,this._lastMoveTime=performance.now()),this._lastMouseX=t.touches[0].clientX,this._lastMouseY=t.touches[0].clientY},touchend:()=>{this.inertia&&this._isDragging&&performance.now()-this._lastMoveTime<50&&(this._velocityX=this._lastDeltaX*this.velocityScale,this._velocityY=this._lastDeltaY*this.velocityScale),this._isDragging=!1},dblclick:()=>{this.reset()}},t.addEventListener("mousedown",this._boundHandlers.mousedown),t.addEventListener("mousemove",this._boundHandlers.mousemove),t.addEventListener("mouseup",this._boundHandlers.mouseup),t.addEventListener("mouseleave",this._boundHandlers.mouseleave),t.addEventListener("touchstart",this._boundHandlers.touchstart),t.addEventListener("touchmove",this._boundHandlers.touchmove,{passive:!1}),t.addEventListener("touchend",this._boundHandlers.touchend),t.addEventListener("dblclick",this._boundHandlers.dblclick),this}disableMouseControl(){return this._canvas&&this._boundHandlers&&(this._canvas.removeEventListener("mousedown",this._boundHandlers.mousedown),this._canvas.removeEventListener("mousemove",this._boundHandlers.mousemove),this._canvas.removeEventListener("mouseup",this._boundHandlers.mouseup),this._canvas.removeEventListener("mouseleave",this._boundHandlers.mouseleave),this._canvas.removeEventListener("touchstart",this._boundHandlers.touchstart),this._canvas.removeEventListener("touchmove",this._boundHandlers.touchmove),this._canvas.removeEventListener("touchend",this._boundHandlers.touchend),this._canvas.removeEventListener("dblclick",this._boundHandlers.dblclick)),this._canvas=null,this._boundHandlers=null,this}reset(){return this.rotationX=this._initialRotationX,this.rotationY=this._initialRotationY,this.rotationZ=this._initialRotationZ,this.x=this._initialX,this.y=this._initialY,this.z=this._initialZ,this._velocityX=0,this._velocityY=0,this._followTarget=null,this._targetX=null,this._targetY=null,this._targetZ=null,this}stopInertia(){return this._velocityX=0,this._velocityY=0,this}setPosition(t,e,i){return this.x=t,this.y=e,this.z=i,this}moveTo(t,e,i,s={}){return this._targetX=t,this._targetY=e,this._targetZ=i,this._targetRotationX=s.rotationX??null,this._targetRotationY=s.rotationY??null,this._positionLerp=s.lerp??.05,this}follow(t,e={}){return this._followTarget=t,this._followOffset={x:e.offsetX??0,y:e.offsetY??0,z:e.offsetZ??0},this._followLookAt=e.lookAt??!0,this._followLookAtTarget=e.lookAtTarget??null,this._followLerp=e.lerp??.1,this}unfollow(t=!1){return this._followTarget=null,t&&this.moveTo(this._initialX,this._initialY,this._initialZ,{rotationX:this._initialRotationX,rotationY:this._initialRotationY,lerp:.05}),this}isFollowing(){return null!==this._followTarget}setRotation(t,e,i=0){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i=0){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this}isDragging(){return this._isDragging}lookAt(t,e,i){const s=t-this.x,n=e-this.y,o=i-this.z,r=Math.sqrt(s*s+o*o);return this.rotationY=Math.atan2(s,o),this.rotationX=Math.atan2(-n,r),this}},t.Circle=je,t.Cloud=Ke,t.Collision=Ms,t.CollisionSystem=class{constructor(){this.groups=new Map,this.pairs=[],this.useQuadtree=!1}createGroup(t){return this.groups.has(t)||this.groups.set(t,new Set),this}add(t,e){const i=this.groups.get(t);if(!i)throw new Error(`Collision group '${t}' does not exist. Call createGroup('${t}') first.`);return i.add(e),this}remove(t,e){const i=this.groups.get(t);return!!i&&i.delete(e)}removeFromAll(t){for(const e of this.groups.values())e.delete(t)}clearGroup(t){const e=this.groups.get(t);e&&e.clear()}clearAll(){for(const t of this.groups.values())t.clear()}getGroup(t){const e=this.groups.get(t);return e?Array.from(e):[]}onCollision(t,e,i,s={}){return this.pairs.push({groupA:t,groupB:e,callback:i,once:s.once??!1}),this}offCollision(t,e){this.pairs=this.pairs.filter(i=>!(i.groupA===t&&i.groupB===e))}update(){for(const t of this.pairs)this._checkPair(t)}check(t,e){const i=this.groups.get(t),s=this.groups.get(e);if(!i||!s)return[];const n=[];for(const t of i){if(!this._isActive(t))continue;const e=this._getBounds(t);if(e)for(const i of s){if(t===i)continue;if(!this._isActive(i))continue;const s=this._getBounds(i);s&&Ms.rectRect(e,s)&&n.push([t,i])}}return n}checkAgainstGroup(t,e){const i=this.groups.get(e);if(!i)return null;const s=this._getBounds(t);if(!s)return null;for(const e of i){if(t===e)continue;if(!this._isActive(e))continue;const i=this._getBounds(e);if(i&&Ms.rectRect(s,i))return e}return null}checkAllAgainstGroup(t,e){const i=this.groups.get(e);if(!i)return[];const s=this._getBounds(t);if(!s)return[];const n=[];for(const e of i){if(t===e)continue;if(!this._isActive(e))continue;const i=this._getBounds(e);i&&Ms.rectRect(s,i)&&n.push(e)}return n}_checkPair(t){const e=this.groups.get(t.groupA),i=this.groups.get(t.groupB);if(e&&i)for(const s of e){if(!this._isActive(s))continue;const e=this._getBounds(s);if(e)for(const n of i){if(s===n)continue;if(!this._isActive(n))continue;const i=this._getBounds(n);if(i&&Ms.rectRect(e,i)&&(t.callback(s,n),t.once))break}}}_getBounds(t){return"function"==typeof t.getBounds?t.getBounds():t.bounds?t.bounds:void 0!==t.x&&void 0!==t.y?{x:t.x-(t.width||0)/2,y:t.y-(t.height||0)/2,width:t.width||0,height:t.height||0}:null}_isActive(t){return!1!==t.active&&!0!==t.destroyed&&!1!==t.alive}},t.Complex=Et,t.Cone=class extends Ze{constructor(t=50,e=100,i={}){super(i),this.radius=t,this.height=e||i.height||100,this.segments=i.segments||24,this.bottomColor=i.bottomColor||"#eee",this.sideColor=i.sideColor||"#aaa",this.stroke=i.stroke||null,this.lineWidth=i.lineWidth||1,this.rotationX=i.rotationX||0,this.rotationY=i.rotationY||0,this.rotationZ=i.rotationZ||0,this.visibleFaces=i.visibleFaces||["bottom","side"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.radius,e=this.height/2,i=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},s=(t,e,s)=>{const n=i(t,e,s);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z,z:n.z}},n=s(0,0,e),o=[],r=2*Math.PI/this.segments;for(let i=0;i<this.segments;i++){const n=i*r,a=Math.cos(n)*t,h=Math.sin(n)*t;o.push(s(a,h,-e))}const a=[];for(let t=0;t<this.segments;t++){const e=(t+1)%this.segments;a.push({points:[n,o[t],o[e]],z:(n.z+o[t].z+o[e].z)/3})}const h=[];this.visibleFaces.includes("bottom")&&h.push({type:"bottom",points:[...o].reverse(),z:-e}),this.visibleFaces.includes("side")&&h.push(...a.map(t=>({type:"side",points:t.points,z:t.z}))),h.sort((t,e)=>e.z-t.z);for(const t of h){const e="bottom"===t.type?this.bottomColor:this.sideColor;Le.shapes.polygon(t.points,e,this.stroke,this.lineWidth)}}getBounds(){const t=1.5*Math.max(2*this.radius,this.height);return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Cross=bi,t.Cube=class extends Ze{constructor(t=50,e={}){super(e),this.size=t,this.faceTopColor=e.faceTopColor||"#eee",this.faceBottomColor=e.faceBottomColor||"#ccc",this.faceLeftColor=e.faceLeftColor||"#aaa",this.faceRightColor=e.faceRightColor||"#888",this.faceFrontColor=e.faceFrontColor||"#666",this.faceBackColor=e.faceBackColor||"#444",this.strokeColor=e.strokeColor||null,this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0,this.visibleFaces=e.visibleFaces||["top","left","right","front","back","bottom"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.size/2,e=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},i=(t,i,s)=>{const n=e(t,i,s);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z}},s={p0:i(-t,-t,-t),p1:i(t,-t,-t),p2:i(t,t,-t),p3:i(-t,t,-t),p4:i(-t,-t,t),p5:i(t,-t,t),p6:i(t,t,t),p7:i(-t,t,t)},n={top:{points:[s.p4,s.p5,s.p6,s.p7],color:this.faceTopColor,normal:[0,0,1]},bottom:{points:[s.p0,s.p1,s.p2,s.p3],color:this.faceBottomColor,normal:[0,0,-1]},left:{points:[s.p0,s.p4,s.p7,s.p3],color:this.faceLeftColor,normal:[-1,0,0]},right:{points:[s.p1,s.p5,s.p6,s.p2],color:this.faceRightColor,normal:[1,0,0]},front:{points:[s.p0,s.p1,s.p5,s.p4],color:this.faceFrontColor,normal:[0,-1,0]},back:{points:[s.p3,s.p2,s.p6,s.p7],color:this.faceBackColor,normal:[0,1,0]}};this.visibleFaces.map(t=>{const e=n[t];if(!e)return null;const i=e.points.reduce((t,e)=>({x:t.x+e.x,y:t.y+e.y}),{x:0,y:0});return i.x/=e.points.length,i.y/=e.points.length,{key:t,face:e,depth:i.x*i.x+i.y*i.y}}).filter(t=>null!==t).sort((t,e)=>e.depth-t.depth).forEach(({key:t,face:e})=>{(null==e?void 0:e.color)&&Le.shapes.polygon(e.points,e.color,this.strokeColor,this.lineWidth)})}getBounds(){const t=1.5*this.size;return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Cube3D=class extends Ze{constructor(t,e={}){var i,s,n,o,r,a;super(e),this.size=t,this.x=e.x??0,this.y=e.y??0,this.z=e.z??0,this.camera=e.camera??null,this.debug=e.debug??!1,this.selfRotationX=e.selfRotationX??0,this.selfRotationY=e.selfRotationY??0,this.selfRotationZ=e.selfRotationZ??0,this.faceColors={front:(null==(i=e.faceColors)?void 0:i.front)??"#B71234",back:(null==(s=e.faceColors)?void 0:s.back)??"#FF5800",top:(null==(n=e.faceColors)?void 0:n.top)??"#FFFFFF",bottom:(null==(o=e.faceColors)?void 0:o.bottom)??"#FFD500",left:(null==(r=e.faceColors)?void 0:r.left)??"#009B48",right:(null==(a=e.faceColors)?void 0:a.right)??"#0046AD"},this.stroke=e.stroke??null,this.lineWidth=e.lineWidth??1,this.stickerMode=e.stickerMode??!1,this.stickerMargin=e.stickerMargin??.15,this.stickerBackgroundColor=e.stickerBackgroundColor??"#0A0A0A",this._faceConfigs=this._createFaceConfigs()}_createFaceConfigs(){const t=this.size/2;return{front:{localPos:{x:0,y:0,z:-t},faceRotX:0,faceRotY:0,color:this.faceColors.front},back:{localPos:{x:0,y:0,z:t},faceRotX:0,faceRotY:Math.PI,color:this.faceColors.back},top:{localPos:{x:0,y:-t,z:0},faceRotX:-Math.PI/2,faceRotY:0,color:this.faceColors.top},bottom:{localPos:{x:0,y:t,z:0},faceRotX:Math.PI/2,faceRotY:0,color:this.faceColors.bottom},left:{localPos:{x:-t,y:0,z:0},faceRotX:0,faceRotY:Math.PI/2,color:this.faceColors.left},right:{localPos:{x:t,y:0,z:0},faceRotX:0,faceRotY:-Math.PI/2,color:this.faceColors.right}}}setCamera(t){return this.camera=t,this}setFaceColors(t){Object.assign(this.faceColors,t);for(const[e,i]of Object.entries(this._faceConfigs))t[e]&&(i.color=t[e]);return this}_applySelfRotation(t,e,i){if(0!==this.selfRotationY){const e=Math.cos(this.selfRotationY),s=Math.sin(this.selfRotationY),n=t*s+i*e;t=t*e-i*s,i=n}if(0!==this.selfRotationX){const t=Math.cos(this.selfRotationX),s=Math.sin(this.selfRotationX),n=e*s+i*t;e=e*t-i*s,i=n}if(0!==this.selfRotationZ){const i=Math.cos(this.selfRotationZ),s=Math.sin(this.selfRotationZ),n=t*s+e*i;t=t*i-e*s,e=n}return{x:t,y:e,z:i}}_calculateLighting(t,e,i){const s=Math.sqrt(.99);let n=t*(.5/s)+e*(.7/s)+i*(.5/s);return n=.7*Math.max(0,n)+.3,n}_applyLighting(t,e){if(!t||"string"!=typeof t||!t.startsWith("#"))return t;const i=t.replace("#",""),s=parseInt(i.substring(0,2),16),n=parseInt(i.substring(2,4),16),o=parseInt(i.substring(4,6),16);return`rgb(${Math.round(s*e)}, ${Math.round(n*e)}, ${Math.round(o*e)})`}draw(){if(super.draw(),!this.camera){const t=this.size/2;return void(this.faceColors.front&&Le.shapes.fillRect(-t,-t,this.size,this.size,this.faceColors.front))}const t=Le.ctx;this.size;const e=0!==this.selfRotationX||0!==this.selfRotationY||0!==this.selfRotationZ,i=[];for(const[t,s]of Object.entries(this._faceConfigs)){let{x:n,y:o,z:r}=s.localPos;if(e){const t=this._applySelfRotation(n,o,r);n=t.x,o=t.y,r=t.z}const a=this.x+n,h=this.y+o,l=this.z+r;let c=0,u=0,d=0;if("front"===t?(c=0,u=0,d=-1):"back"===t?(c=0,u=0,d=1):"top"===t?(c=0,u=-1,d=0):"bottom"===t?(c=0,u=1,d=0):"left"===t?(c=-1,u=0,d=0):"right"===t&&(c=1,u=0,d=0),e){const t=this._applySelfRotation(c,u,d);c=t.x,u=t.y,d=t.z}let f=c,p=u,g=d;if(0!==this.camera.rotationZ){const t=Math.cos(this.camera.rotationZ),e=Math.sin(this.camera.rotationZ),i=f;f=i*t-p*e,p=i*e+p*t}const m=Math.cos(this.camera.rotationY),v=Math.sin(this.camera.rotationY),y=f*m-g*v,_=f*v+g*m,x=Math.cos(this.camera.rotationX),b=Math.sin(this.camera.rotationX),w=p*x-_*b,M=p*b+_*x;if(M>.01)continue;const S=this.camera.project(a,h,l);if(S.z<10-this.camera.perspective)continue;const C=this._calculateLighting(y,w,M),T=this._getFaceVertices(t,s,e);i.push({name:t,config:s,projected:S,vertices:T,depth:S.z,intensity:C,nx:y,ny:w,nz:M})}i.sort((t,e)=>e.depth-t.depth);for(const e of i)this._renderFace(t,e)}_getFaceVertices(t,e,i){const s=this.size/2;let n;switch(t){case"front":n=[{x:-s,y:-s,z:-s},{x:s,y:-s,z:-s},{x:s,y:s,z:-s},{x:-s,y:s,z:-s}];break;case"back":n=[{x:s,y:-s,z:s},{x:-s,y:-s,z:s},{x:-s,y:s,z:s},{x:s,y:s,z:s}];break;case"top":n=[{x:-s,y:-s,z:s},{x:s,y:-s,z:s},{x:s,y:-s,z:-s},{x:-s,y:-s,z:-s}];break;case"bottom":n=[{x:-s,y:s,z:-s},{x:s,y:s,z:-s},{x:s,y:s,z:s},{x:-s,y:s,z:s}];break;case"left":n=[{x:-s,y:-s,z:s},{x:-s,y:-s,z:-s},{x:-s,y:s,z:-s},{x:-s,y:s,z:s}];break;case"right":n=[{x:s,y:-s,z:-s},{x:s,y:-s,z:s},{x:s,y:s,z:s},{x:s,y:s,z:-s}]}return n.map(t=>{let{x:e,y:s,z:n}=t;if(i){const t=this._applySelfRotation(e,s,n);e=t.x,s=t.y,n=t.z}return e+=this.x,s+=this.y,n+=this.z,this.camera.project(e,s,n)})}_renderFace(t,e){const{vertices:i,config:s,intensity:n}=e,o=this._applyLighting(s.color,n);t.beginPath(),t.moveTo(i[0].x,i[0].y);for(let e=1;e<i.length;e++)t.lineTo(i[e].x,i[e].y);if(t.closePath(),this.debug)t.strokeStyle=this.stroke||"#fff",t.lineWidth=this.lineWidth??1,t.stroke();else if(this.stickerMode){const e=this._applyLighting(this.stickerBackgroundColor,n);t.fillStyle=e,t.fill(),this.stroke&&(t.strokeStyle=this.stroke,t.lineWidth=this.lineWidth??1,t.stroke());const s=this._getInsetVertices(i,this.stickerMargin);t.beginPath(),t.moveTo(s[0].x,s[0].y);for(let e=1;e<s.length;e++)t.lineTo(s[e].x,s[e].y);t.closePath(),t.fillStyle=o,t.fill()}else t.fillStyle=o,t.fill(),this.stroke&&(t.strokeStyle=this.stroke,t.lineWidth=this.lineWidth??1,t.stroke())}_getInsetVertices(t,e){let i=0,s=0;for(const e of t)i+=e.x,s+=e.y;i/=t.length,s/=t.length;const n=1-2*e;return t.map(t=>({x:i+(t.x-i)*n,y:s+(t.y-s)*n}))}getCenter(){return{x:this.x,y:this.y,z:this.z}}getBounds(){const t=this.size/2;return{x:this.x-t,y:this.y-t,width:this.size,height:this.size}}},t.Cursor=class extends Ei{constructor(t,e,i=null,s={}){super(t,s),this.normalShape=e,this.pressedShape=i||e,this.active=!1,this.offsetX=0,this.offsetY=0,this.isDown=!1,this.game.events.on("inputmove",t=>{this.x=t.x,this.y=t.y}),this.game.events.on("inputdown",()=>{this.isDown=!0}),this.game.events.on("inputup",()=>{this.isDown=!1}),this.game.events.on("mouseover",()=>{this.visible=!1}),this.game.events.on("mouseout",()=>{this.visible=!0})}activate(){this.active=!0,this.game.canvas.style.cursor="none"}deactivate(){this.active=!1,this.game.canvas.style.cursor="default"}draw(){if(super.draw(),!this.active)return;const t=this.isDown&&this.pressedShape?this.pressedShape:this.normalShape;t&&t.render()}},t.Cylinder=class extends Ze{constructor(t=40,e={}){super(e),this.radius=t,this.height=e.height||80,this.segments=e.segments||24,this.topColor=e.topColor||"#FF00FF",this.bottomColor=e.bottomColor||"#FF0FFF",this.sideColor=e.sideColor||"#00FF00",this.stroke=e.stroke||"#000000",this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0,this.visibleFaces=e.visibleFaces||["top","bottom","side"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.radius,e=this.height/2,i=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},s=(t,e,s)=>{const n=i(t,e,s);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z,z:n.z}},n=[],o=[],r=2*Math.PI/this.segments;for(let i=0;i<this.segments;i++){const a=i*r,h=Math.cos(a)*t,l=Math.sin(a)*t;n.push(s(h,l,e)),o.push(s(h,l,-e))}const a=[];for(let t=0;t<this.segments;t++){const e=(t+1)%this.segments;a.push({points:[o[t],o[e],n[e],n[t]],z:(n[t].z+n[e].z+o[t].z+o[e].z)/4})}const h=[];this.visibleFaces.includes("top")&&h.push({type:"top",points:n,z:e}),this.visibleFaces.includes("bottom")&&h.push({type:"bottom",points:[...o].reverse(),z:-e}),this.visibleFaces.includes("side")&&h.push(...a.map(t=>({type:"side",points:t.points,z:t.z}))),h.sort((t,e)=>e.z-t.z);for(const t of h){let e;switch(t.type){case"top":e=this.topColor;break;case"bottom":e=this.bottomColor;break;case"side":e=this.sideColor}Le.shapes.polygon(t.points,e,this.stroke,this.lineWidth)}}getBounds(){const t=1.5*Math.max(2*this.radius,this.height);return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.DEJONG_MAX_ITERATIONS=200,t.DEJONG_POINT_FRAGMENTS=Hs,t.DEJONG_POINT_VERTEX=Ws,t.DJFilter=class{constructor(t,e={}){this.audioContext=t;const{type:i="lowpass",frequency:s=2e4,Q:n=1}=e;this.filter=t.createBiquadFilter(),this.filter.type=i,this.filter.frequency.value=s,this.filter.Q.value=n}connect(t){t.connect(this.filter)}setFrequency(t){this.filter.frequency.value=t}setQ(t){this.filter.Q.value=t}setType(t){this.filter.type=t}getNode(){return this.filter}disconnect(){try{this.filter.disconnect()}catch(t){}}},t.DebugTab=Re,t.Diamond=ei,t.EQFilterBank=class{constructor(t,e={}){this.audioContext=t;const{numBands:i=16,minFreq:s=40,maxFreq:n=12e3,Q:o=4}=e;this.filters=[],this.numBands=i;for(let e=0;e<i;e++){const r=t.createBiquadFilter();r.type="peaking";const a=i>1?s*Math.pow(n/s,e/(i-1)):(s+n)/2;r.frequency.value=a,r.Q.value=o,r.gain.value=0,this.filters.push(r)}}connect(t){let e=t;for(const t of this.filters)e.connect(t),e=t}setBandGain(t,e){t>=0&&t<this.filters.length&&(this.filters[t].gain.value=e)}setBandGains(t){for(let e=0;e<Math.min(t.length,this.filters.length);e++)this.filters[e].gain.value=t[e]}getFilter(t){return this.filters[t]}getFilters(){return this.filters}disconnect(){for(const t of this.filters)try{t.disconnect()}catch(t){}}},t.Easing=oe,t.Euclidian=Xe,t.EventEmitter=Si,t.FPSCounter=class extends Wi{constructor(t,e={}){super(t,"0 FPS",{x:0,y:0,font:cs.fonts.small,color:cs.colors.neonGreen,align:"center",baseline:"middle",debug:!1,...e}),this.fps=0,this._frames=0,this._accum=0}update(t){const e=this.game.actualFps;e&&(this._frames++,this._accum+=t,this._accum>=.5&&(this.fps=Math.round(e),this.text=`${this.fps} FPS`,this._accum=0,this._frames=0),super.update(t))}getBounds(){if(this.shape&&this.shape.getTextBounds){const t=this.shape.getTextBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}return super.getBounds()}getDebugBounds(){if(this.shape&&this.shape.getDebugBounds){const t=this.shape.getDebugBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}return super.getDebugBounds()}},t.Flanger=class{constructor(t,e={}){this.audioContext=t;const{baseDelay:i=.005,maxDelay:s=.02,lfoFrequency:n=.5,lfoDepth:o=.002,feedback:r=.5,wet:a=0,dry:h=1}=e;this.delay=t.createDelay(s),this.delay.delayTime.value=i,this.lfo=t.createOscillator(),this.lfo.type="sine",this.lfo.frequency.value=n,this.lfoDepth=t.createGain(),this.lfoDepth.gain.value=o,this.feedback=t.createGain(),this.feedback.gain.value=r,this.wetGain=t.createGain(),this.wetGain.gain.value=a,this.dryGain=t.createGain(),this.dryGain.gain.value=h,this.output=t.createGain(),this.output.gain.value=1,this.lfo.connect(this.lfoDepth),this.lfoDepth.connect(this.delay.delayTime),this.delay.connect(this.feedback),this.feedback.connect(this.delay),this.lfo.start(),this.input=t.createGain()}connect(t){t.connect(this.dryGain),this.dryGain.connect(this.output),t.connect(this.delay),this.delay.connect(this.wetGain),this.wetGain.connect(this.output)}setMix(t,e){this.wetGain.gain.value=t,this.dryGain.gain.value=e}setLFOFrequency(t){this.lfo.frequency.value=t}setFeedback(t){this.feedback.gain.value=t}disconnect(){try{this.lfo.stop(),this.lfo.disconnect(),this.delay.disconnect(),this.feedback.disconnect(),this.wetGain.disconnect(),this.dryGain.disconnect(),this.lfoDepth.disconnect(),this.input.disconnect(),this.output.disconnect()}catch(t){}}},t.FluentGO=Ts,t.FluentGame=As,t.FluentLayer=ks,t.FluentScene=Ps,t.FluidSystem=Cs,t.Fractals=Ft,t.Game=ls,t.GameObject=Ei,t.GameObjectShapeWrapper=Fi,t.Geometry2d=We,t.Gesture=class{constructor(t,e={}){this.canvas=t,this.onZoom=e.onZoom||null,this.onPan=e.onPan||null,this.onTap=e.onTap||null,this.onDragStart=e.onDragStart||null,this.onDragEnd=e.onDragEnd||null,this.wheelZoomFactor=e.wheelZoomFactor??.1,this.pinchZoomFactor=e.pinchZoomFactor??1,this.panScale=e.panScale??1,this.tapThreshold=e.tapThreshold??10,this.tapTimeout=e.tapTimeout??300,this.preventDefault=e.preventDefault??!0,this._isDragging=!1,this._hasMoved=!1,this._startTime=0,this._startX=0,this._startY=0,this._lastX=0,this._lastY=0,this._touches=new Map,this._lastPinchDist=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0,this._onMouseDown=this._onMouseDown.bind(this),this._onMouseMove=this._onMouseMove.bind(this),this._onMouseUp=this._onMouseUp.bind(this),this._onMouseLeave=this._onMouseLeave.bind(this),this._onWheel=this._onWheel.bind(this),this._onTouchStart=this._onTouchStart.bind(this),this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this._onTouchCancel=this._onTouchCancel.bind(this),this._attachListeners()}get isDragging(){return this._isDragging}_attachListeners(){const t=this.canvas,e=!this.preventDefault;t.addEventListener("mousedown",this._onMouseDown),t.addEventListener("mousemove",this._onMouseMove),t.addEventListener("mouseup",this._onMouseUp),t.addEventListener("mouseleave",this._onMouseLeave),t.addEventListener("wheel",this._onWheel,{passive:e}),t.addEventListener("touchstart",this._onTouchStart,{passive:e}),t.addEventListener("touchmove",this._onTouchMove,{passive:e}),t.addEventListener("touchend",this._onTouchEnd,{passive:e}),t.addEventListener("touchcancel",this._onTouchCancel)}destroy(){const t=this.canvas;t.removeEventListener("mousedown",this._onMouseDown),t.removeEventListener("mousemove",this._onMouseMove),t.removeEventListener("mouseup",this._onMouseUp),t.removeEventListener("mouseleave",this._onMouseLeave),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("touchstart",this._onTouchStart),t.removeEventListener("touchmove",this._onTouchMove),t.removeEventListener("touchend",this._onTouchEnd),t.removeEventListener("touchcancel",this._onTouchCancel),this._touches.clear()}_getMousePos(t){const e=this.canvas.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_getTouchPos(t){const e=this.canvas.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_onMouseDown(t){const e=this._getMousePos(t);this._isDragging=!0,this._hasMoved=!1,this._startTime=Date.now(),this._startX=e.x,this._startY=e.y,this._lastX=e.x,this._lastY=e.y,this.onDragStart&&this.onDragStart(e.x,e.y)}_onMouseMove(t){if(!this._isDragging)return;const e=this._getMousePos(t),i=e.x-this._lastX,s=e.y-this._lastY,n=Math.abs(e.x-this._startX),o=Math.abs(e.y-this._startY);(n>this.tapThreshold||o>this.tapThreshold)&&(this._hasMoved=!0),this.onPan&&this._hasMoved&&this.onPan(i*this.panScale,s*this.panScale),this._lastX=e.x,this._lastY=e.y}_onMouseUp(t){if(!this._isDragging)return;const e=Date.now()-this._startTime;if(!this._hasMoved&&e<this.tapTimeout&&this.onTap){const e=this._getMousePos(t);this.onTap(e.x,e.y)}this._isDragging=!1,this.onDragEnd&&this.onDragEnd()}_onMouseLeave(){this._isDragging&&(this._isDragging=!1,this.onDragEnd&&this.onDragEnd())}_onWheel(t){if(this.preventDefault&&t.preventDefault(),this.onZoom){const e=this._getMousePos(t),i=t.deltaY>0?-this.wheelZoomFactor:this.wheelZoomFactor;this.onZoom(i,e.x,e.y)}}_onTouchStart(t){this.preventDefault&&t.preventDefault(),this._startTime=Date.now(),this._hasMoved=!1;for(const e of t.changedTouches){const t=this._getTouchPos(e);this._touches.set(e.identifier,{x:t.x,y:t.y})}if(2===this._touches.size){const[t,e]=Array.from(this._touches.values());this._lastPinchDist=Math.hypot(e.x-t.x,e.y-t.y),this._lastPinchCenterX=(t.x+e.x)/2,this._lastPinchCenterY=(t.y+e.y)/2,this._isDragging=!1}if(1===this._touches.size){const e=t.touches[0],i=this._getTouchPos(e);this._isDragging=!0,this._startX=i.x,this._startY=i.y,this._lastX=i.x,this._lastY=i.y,this.onDragStart&&this.onDragStart(i.x,i.y)}}_onTouchMove(t){this.preventDefault&&t.preventDefault();for(const e of t.changedTouches)if(this._touches.has(e.identifier)){const t=this._getTouchPos(e);this._touches.set(e.identifier,{x:t.x,y:t.y})}if(2===this._touches.size){const[t,e]=Array.from(this._touches.values()),i=Math.hypot(e.x-t.x,e.y-t.y),s=(t.x+e.x)/2,n=(t.y+e.y)/2;if(this._lastPinchDist>0){if(this.onZoom){const t=(i/this._lastPinchDist-1)*this.pinchZoomFactor;this.onZoom(t,s,n)}if(this.onPan){const t=s-this._lastPinchCenterX,e=n-this._lastPinchCenterY;this.onPan(t*this.panScale,e*this.panScale)}this._hasMoved=!0}this._lastPinchDist=i,this._lastPinchCenterX=s,this._lastPinchCenterY=n}else if(1===this._touches.size&&this._isDragging){const e=t.touches[0],i=this._getTouchPos(e),s=i.x-this._lastX,n=i.y-this._lastY,o=Math.abs(i.x-this._startX),r=Math.abs(i.y-this._startY);(o>this.tapThreshold||r>this.tapThreshold)&&(this._hasMoved=!0),this.onPan&&this._hasMoved&&this.onPan(s*this.panScale,n*this.panScale),this._lastX=i.x,this._lastY=i.y}}_onTouchEnd(t){this.preventDefault&&t.preventDefault();for(const e of t.changedTouches)this._touches.delete(e.identifier);if(this._touches.size<2&&(this._lastPinchDist=0),0===this._touches.size){const t=Date.now()-this._startTime;!this._hasMoved&&t<this.tapTimeout&&this.onTap&&this.onTap(this._startX,this._startY),this._isDragging=!1,this.onDragEnd&&this.onDragEnd()}}_onTouchCancel(){this._touches.clear(),this._lastPinchDist=0,this._isDragging=!1,this.onDragEnd&&this.onDragEnd()}},t.GridLayout=class extends Li{constructor(t,e={}){super(t,e),this.columns=e.columns??4,this.debug=e.debug??!1}calculateLayout(){return this.children.length?Dt(this.children,{columns:this.columns,spacing:this.spacing,padding:this.padding,centerItems:this.centerItems,width:this.autoSize?void 0:this.width,height:this.autoSize?void 0:this.height}):null}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:-(this._contentHeight??this.height)/2}}},t.Group=Ve,t.Heart=xi,t.Hexagon=_i,t.HighShelf=class{constructor(t,e={}){this.audioContext=t;const{frequency:i=4e3,gain:s=3}=e;this.filter=t.createBiquadFilter(),this.filter.type="highshelf",this.filter.frequency.value=i,this.filter.gain.value=s}connect(t){t.connect(this.filter)}setFrequency(t){this.filter.frequency.value=t}setGain(t){this.filter.gain.value=t}getNode(){return this.filter}disconnect(){try{this.filter.disconnect()}catch(t){}}},t.HorizontalLayout=class extends Li{getScrollAxis(){return{horizontal:!0,vertical:!1}}calculateLayout(){return Rt(this.children,{spacing:this.spacing,padding:this.padding,align:this.align,centerItems:!0})}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:0}}},t.ImageGo=class extends Fi{constructor(t,e,i={}){super(t,e instanceof Mi?e:new Mi(e,i),i)}reset(){this.shape.reset()}},t.ImageShape=Mi,t.Input=Ci,t.IsometricCamera=class{constructor(t={}){this.angle=t.angle??0,this._targetAngle=this.angle,this.rotationStep=t.rotationStep??Math.PI/2,this.animationDuration=t.animationDuration??.4,this.easingType=t.easing??"easeInOutCubic",this._animating=!1,this._animationProgress=0,this._startAngle=0,this._onRotationStart=null,this._onRotationEnd=null}rotateRight(){return this._animating||this._startRotation(this._targetAngle+this.rotationStep),this}rotateLeft(){return this._animating||this._startRotation(this._targetAngle-this.rotationStep),this}rotateTo(t){return this._animating||this._startRotation(t),this}setAngle(t){return this.angle=t,this._targetAngle=t,this._animating=!1,this}_startRotation(t){this._startAngle=this.angle,this._targetAngle=t,this._animationProgress=0,this._animating=!0,this._onRotationStart&&this._onRotationStart(this._startAngle,this._targetAngle)}update(t){if(this._animating)if(this._animationProgress+=t/this.animationDuration,this._animationProgress>=1)this._animationProgress=1,this.angle=this._targetAngle,this._animating=!1,this._onRotationEnd&&this._onRotationEnd(this.angle);else{const t=this._ease(this._animationProgress);this.angle=this._startAngle+(this._targetAngle-this._startAngle)*t}}_ease(t){switch(this.easingType){case"linear":return t;case"easeInQuad":return t*t;case"easeOutQuad":return t*(2-t);case"easeInOutQuad":return t<.5?2*t*t:(4-2*t)*t-1;case"easeInCubic":return t*t*t;case"easeOutCubic":return--t*t*t+1;case"easeInOutCubic":default:return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1;case"easeOutBack":const e=1.70158;return 1+(e+1)*Math.pow(t-1,3)+e*Math.pow(t-1,2)}}isAnimating(){return this._animating}getAngleDegrees(){return 180*this.angle/Math.PI%360}getNormalizedAngle(){let t=this.angle%(2*Math.PI);return t<0&&(t+=2*Math.PI),t}onRotationStart(t){return this._onRotationStart=t,this}onRotationEnd(t){return this._onRotationEnd=t,this}reset(){return this.setAngle(0),this}},t.IsometricScene=class extends Oi{constructor(t,e={}){super(t,e),this.tileWidth=e.tileWidth??64,this.tileHeight=e.tileHeight??this.tileWidth/2,this.depthSort=e.depthSort??!0,this.scaleByDepth=e.scaleByDepth??!1,this.gridSize=e.gridSize??10,this.elevationScale=e.elevationScale??1,this.camera=e.camera??null}setCamera(t){return this.camera=t,this}toIsometric(t,e,i=0){let s=t,n=e;if(this.camera){const i=this.camera.angle,o=Math.cos(i),r=Math.sin(i);s=t*o-e*r,n=t*r+e*o}return{x:(s-n)*(this.tileWidth/2),y:(s+n)*(this.tileHeight/2)-i*this.elevationScale,depth:s+n-.01*i}}fromIsometric(t,e){const i=this.tileWidth/2,s=this.tileHeight/2;let n=(t/i+e/s)/2,o=(e/s-t/i)/2;if(this.camera){const t=-this.camera.angle,e=Math.cos(t),i=Math.sin(t);return{x:n*e-o*i,y:n*i+o*e}}return{x:n,y:o}}update(t){super.update(t),this.camera&&this.camera.update(t)}getTileAt(t,e){const i=this.fromIsometric(t,e);return{x:Math.floor(i.x),y:Math.floor(i.y)}}getRotatedDepth(t,e=0){const i=this.camera?this.camera.angle:0,s=Math.cos(i),n=Math.sin(i);let o=-1/0;for(const e of t){const t=e.x*s-e.y*n+(e.x*n+e.y*s);t>o&&(o=t)}return o+.5*e}getDepthScale(t){return.7+Math.abs(t)/this.gridSize*.6}render(){if(!this.visible)return;Le.save(),Le.translateTo(this.x,this.y);const t=[];for(const e of this._collection.getSortedChildren()){if(!e.visible)continue;let i;if(void 0!==e.isoDepth)i=e.isoDepth;else{let t=e.x,s=e.y;if(this.camera){const i=this.camera.angle,n=Math.cos(i),o=Math.sin(i);t=e.x*n-e.y*o,s=e.x*o+e.y*n}i=t+s+.05*(e.z??0)}t.push({child:e,depth:i})}this.depthSort&&t.sort((t,e)=>{const i=t.child.zIndex??0,s=e.child.zIndex??0;return i!==s?i-s:t.depth-e.depth});for(const e of t)Le.save(),e.child.render(),Le.restore();Le.restore()}},t.Kernels=ge,t.Keys=Ri,t.LayoutScene=Li,t.Limiter=class{constructor(t,e={}){this.audioContext=t;const{threshold:i=-3,knee:s=0,ratio:n=20,attack:o=.001,release:r=.1}=e;this.compressor=t.createDynamicsCompressor(),this.compressor.threshold.value=i,this.compressor.knee.value=s,this.compressor.ratio.value=n,this.compressor.attack.value=o,this.compressor.release.value=r}connect(t){t.connect(this.compressor)}setThreshold(t){this.compressor.threshold.value=t}getNode(){return this.compressor}disconnect(){try{this.compressor.disconnect()}catch(t){}}},t.Line=ii,t.Loggable=ke,t.Logger=Te,t.Mask=Hi,t.MasterGain=class{constructor(t,e=1){this.audioContext=t,this.gain=t.createGain(),this.gain.gain.value=e}connect(t){t.connect(this.gain)}setVolume(t){this.gain.gain.value=t}getNode(){return this.gain}disconnect(){try{this.gain.disconnect()}catch(t){}}},t.Motion=os,t.Mouse=ki,t.Noise=Lt,t.OutlinedText=class extends Ze{constructor(t,e,i,s={}){super(t,e,s),this.text=i,this.centered=s.centered||!1,this.color=s.color||"#000000",this.stroke=s.stroke||"#FFFFFF",this.lineWidth=s.lineWidth||1,this.font=s.font||null,this.align=s.align||"left",this.baseline=s.baseline||"alphabetic",this.calculateDimensions()}calculateDimensions(){if(!Le.ctx)return console.warn("Painter context not initialized. Cannot calculate text dimensions."),this.width=0,void(this.height=0);const t=Le.text.font();this.font&&Le.text.setFont(this.font);const e=Le.text.measureText(this.text);if(this.width=e.width,this.font){const t=parseInt(this.font);this.height=isNaN(t)?20:t}else this.height=e.actualBoundingBoxAscent+e.actualBoundingBoxDescent||20;this.width+=2*this.lineWidth,this.height+=2*this.lineWidth,Le.text.setFont(t)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Le.ctx)return void console.warn("Painter context not initialized. Cannot draw text.");let t=0;this.font&&Le.text.setFont(this.font),Le.text.setTextAlign(this.align),Le.text.setTextBaseline(this.baseline),this.centered&&("middle"===this.baseline||"alphabetic"===this.baseline?t=0:"top"===this.baseline?t=this.height/2:"bottom"===this.baseline&&(t=-this.height/2)),Le.outlinedText(this.text,0,t,this.color,this.stroke,this.lineWidth,this.font)}getBounds(){if(!Le.ctx)return super.getBounds();const t=Le.text.font();Le.text.setFont(this.font);const e=Le.text.measureText(this.text),i=e.width,s=e.actualBoundingBoxAscent+e.actualBoundingBoxDescent||parseInt(this.font)||20;return Le.text.setFont(t),this.width=i,this.height=s,{x:this.x,y:this.y,width:i,height:s}}},t.POINT_SPRITE_CIRCLE_FRAGMENT=ms,t.POINT_SPRITE_GLOW_FRAGMENT=vs,t.POINT_SPRITE_PRESETS=xs,t.POINT_SPRITE_SOFT_SQUARE_FRAGMENT=_s,t.POINT_SPRITE_SQUARE_FRAGMENT=ys,t.POINT_SPRITE_VERTEX=gs,t.Painter=Le,t.PainterColors=Ye,t.PainterEffects=ze,t.PainterImages=De,t.PainterLines=Be,t.PainterOpacity=Ie,t.PainterShapes=Ee,t.PainterText=Fe,t.Parallelogram=class extends Ze{constructor(t={}){super(t),this._pgWidth=t.width??100,this._pgHeight=t.height??50,this._slant=t.slant??this._pgHeight,this._flipX=t.flipX??!1,this._updateDimensions()}get pgWidth(){return this._pgWidth}set pgWidth(t){this._pgWidth=t,this._updateDimensions(),this.invalidateCache()}get pgHeight(){return this._pgHeight}set pgHeight(t){this._pgHeight=t,this._updateDimensions(),this.invalidateCache()}get slant(){return this._slant}set slant(t){this._slant=t,this._updateDimensions(),this.invalidateCache()}get flipX(){return this._flipX}set flipX(t){this._flipX=t,this.invalidateCache()}_updateDimensions(){this._width=this._pgWidth+Math.abs(this._slant),this._height=this._pgHeight}getVertices(){const t=this._pgWidth,e=this._pgHeight;let i=this._slant;this._flipX&&(i=-i);const s=-(t+Math.abs(i))/2+(i<0?-i:0);return[{x:s,y:e/2},{x:s+t,y:e/2},{x:s+t+i,y:-e/2},{x:s+i,y:-e/2}]}draw(){super.draw();const t=this.getVertices();Le.shapes.polygon(t,this.color,this.stroke,this.lineWidth,this.lineJoin)}calculateBounds(){return{x:this.x,y:this.y,width:this._width,height:this._height}}},t.Particle=ds,t.ParticleEmitter=fs,t.ParticleSystem=ws,t.PatternRectangle=class extends Ze{constructor(t=null,e="repeat",i={}){super(i),this.image=t,this.repetition=e,this.pattern=null,t&&this._tryCreatePattern(t)}_tryCreatePattern(t){t instanceof HTMLImageElement||"boolean"==typeof t.complete?t.complete?this._createPattern():t.addEventListener("load",()=>this._createPattern(),{once:!0}):this._createPattern()}_createPattern(){this.pattern=Le.img.createPattern(this.image,this.repetition)}setImage(t,e){this.image=t,e&&(this.repetition=e),this.pattern=null,this._tryCreatePattern(t)}draw(){super.draw(),!this.pattern&&this.image&&this._tryCreatePattern(this.image);const t=-this.width/2,e=-this.height/2;this.pattern?Le.img.fillPattern(this.pattern,t,e,this.width,this.height):this.strokeColor&&Le.shapes.outlineRect(t,e,this.width,this.height,this.strokeColor,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},t.Patterns=class{static void(t,e,i={}){const{background:s=[255,255,255,255],foreground:n=[0,0,200,255]}=i,o=new Uint8ClampedArray(t*e*4);for(let t=0;t<o.length;t+=4)o[t]=s[0],o[t+1]=s[1],o[t+2]=s[2],o[t+3]=s[3];return o}static solidGrid(t,e,i={}){const{spacing:s=8,background:n=[0,0,0,0],foreground:o=[128,128,128,255]}=i,r=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++){const e=i%s===0;for(let a=0;a<t;a++){const h=4*(i*t+a),l=a%s===0||e?o:n;r[h]=l[0],r[h+1]=l[1],r[h+2]=l[2],r[h+3]=l[3]}}return r}static checkerboard(t,e,i={}){const{cellSize:s=8,color1:n=[0,0,0,255],color2:o=[255,255,255,255]}=i,r=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++){const e=Math.floor(i/s);for(let a=0;a<t;a++){const h=(Math.floor(a/s)+e)%2==0?n:o,l=4*(i*t+a);r.set(h,l)}}return r}static stripes(t,e,i={}){const{spacing:s=4,thickness:n=1,background:o=[0,0,0,0],foreground:r=[255,255,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++)for(let e=0;e<t;e++){const h=(e+i)%s<n,l=4*(i*t+e);a.set(h?r:o,l)}return a}static honeycomb(t,e,i={}){const{radius:s=10,lineWidth:n=1,foreground:o=[255,255,255,255],background:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=r[0],a[t+1]=r[1],a[t+2]=r[2],a[t+3]=r[3];const h=Math.floor(t/2),l=Math.floor(e/2),c=(t,e,i,s,n)=>{const o=Math.abs(t-i),r=Math.abs(e-s),a=n*Math.sqrt(3)/2;return!(r>a)&&!(o>n)&&n*a*2>=n*r*2+a*o},u=s-n,d=s*Math.sqrt(3),f=Math.max(0,Math.floor(h-s-1)),p=Math.min(t-1,Math.ceil(h+s+1)),g=Math.max(0,Math.floor(l-d/2-1)),m=Math.min(e-1,Math.ceil(l+d/2+1));for(let e=g;e<=m;e++)for(let i=f;i<=p;i++){const n=c(i,e,h,l,s),r=u>0&&c(i,e,h,l,u);if(n&&!r){const s=4*(e*t+i);a[s]=o[0],a[s+1]=o[1],a[s+2]=o[2],a[s+3]=o[3]}}return a}static harlequin(t,e,i={}){const{size:s=20,spacing:n=0,background:o=[255,255,255,255],foreground:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];const h=2*s,l=2*s,c=h+n,u=l+n,d=(t,e,i,s)=>Math.abs(t-i)/(h/2)+Math.abs(e-s)/(l/2)<=1;for(let i=-1;i<e/u+1;i++)for(let s=-1;s<t/c+1;s++){const n=s*c+c/2,o=i*u+u/2;if((i+s)%2!=0)continue;const f=Math.max(0,Math.floor(n-h/2)),p=Math.min(t-1,Math.ceil(n+h/2)),g=Math.max(0,Math.floor(o-l/2)),m=Math.min(e-1,Math.ceil(o+l/2));for(let e=g;e<=m;e++)for(let i=f;i<=p;i++)if(d(i,e,n,o)){const s=4*(e*t+i);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static circles(t,e,i={}){const{radius:s=10,lineWidth:n=2,spacing:o=5,background:r=[0,0,0,255],foreground:a=[255,255,255,255]}=i,h=new Uint8ClampedArray(t*e*4);for(let t=0;t<h.length;t+=4)h[t]=r[0],h[t+1]=r[1],h[t+2]=r[2],h[t+3]=r[3];const l=2*s+o,c=(t,e,i,s,n)=>{const o=t-i,r=e-s;return o*o+r*r<=n*n};for(let i=0;i<Math.ceil(e/l)+1;i++)for(let o=0;o<Math.ceil(t/l)+1;o++){const r=o*l+s,u=i*l+s;if(r<-s||r>t+s||u<-s||u>e+s)continue;const d=Math.max(0,Math.floor(r-s)),f=Math.min(t-1,Math.ceil(r+s)),p=Math.max(0,Math.floor(u-s)),g=Math.min(e-1,Math.ceil(u+s)),m=s-n;for(let e=p;e<=g;e++)for(let i=d;i<=f;i++){const n=c(i,e,r,u,s),o=c(i,e,r,u,m);if(n&&!o){const s=4*(e*t+i);h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]}}}return h}static diamonds(t,e,i={}){const{size:s=16,squareSize:n=6,background:o=[255,255,255,255],foreground:r=[0,0,0,255],innerColor:a=[255,255,255,255]}=i,h=new Uint8ClampedArray(t*e*4);for(let t=0;t<h.length;t+=4)h[t]=o[0],h[t+1]=o[1],h[t+2]=o[2],h[t+3]=o[3];const l=s,c=(t,e,i,s,n)=>Math.abs(t-i)+Math.abs(e-s)<=n/2,u=(t,e,i,s,n)=>Math.abs(t-i)<=n/2&&Math.abs(e-s)<=n/2;for(let i=-1;i<e/l+1;i++)for(let s=-1;s<t/l+1;s++){const o=s*l+l/2,d=i*l+l/2;if(o<-l||o>t+l||d<-l||d>e+l)continue;const f=Math.max(0,Math.floor(o-l/2)),p=Math.min(t-1,Math.ceil(o+l/2)),g=Math.max(0,Math.floor(d-l/2)),m=Math.min(e-1,Math.ceil(d+l/2));for(let e=g;e<=m;e++)for(let i=f;i<=p;i++){const s=c(i,e,o,d,l),f=u(i,e,o,d,n);if(s){const s=4*(e*t+i);f?(h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]):(h[s]=r[0],h[s+1]=r[1],h[s+2]=r[2],h[s+3]=r[3])}}}return h}static cubes(t,e,i={}){const{size:s=10,spacing:n=2,background:o=[0,0,0,255],foreground:r=[255,100,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];const h=s+n;for(let i=0;i<Math.ceil(e/h)+1;i++)for(let n=0;n<Math.ceil(t/h)+1;n++){const o=n*h,l=i*h;if(!(o>=t||l>=e))for(let i=l;i<Math.min(l+s,e);i++)for(let e=o;e<Math.min(o+s,t);e++){const s=4*(i*t+e);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static cross(t,e,i={}){const{size:s=8,thickness:n=2,spacing:o=16,background:r=[255,255,255,255],foreground:a=[80,80,80,255]}=i,h=new Uint8ClampedArray(t*e*4);for(let t=0;t<h.length;t+=4)h[t]=r[0],h[t+1]=r[1],h[t+2]=r[2],h[t+3]=r[3];for(let i=0;i<Math.ceil(e/o)+1;i++)for(let r=0;r<Math.ceil(t/o)+1;r++){const l=r*o,c=i*o;if(l<-s||l>t+s||c<-s||c>e+s)continue;const u=l-s/2,d=l+s/2,f=c-n/2,p=c+n/2;for(let i=Math.max(0,Math.floor(f));i<Math.min(e,Math.ceil(p));i++)for(let e=Math.max(0,Math.floor(u));e<Math.min(t,Math.ceil(d));e++){const s=4*(i*t+e);h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]}const g=l-n/2,m=l+n/2,v=c-s/2,y=c+s/2;for(let i=Math.max(0,Math.floor(v));i<Math.min(e,Math.ceil(y));i++)for(let e=Math.max(0,Math.floor(g));e<Math.min(t,Math.ceil(m));e++){const s=4*(i*t+e);h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]}}return h}static mesh(t,e,i={}){const{spacing:s=20,lineWidth:n=2,background:o=[255,255,255,0],foreground:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];for(let i=0;i<e;i++)for(let o=0;o<t;o++){const h=(o+i)%s,l=(o-i+e)%s;if(h<n||h>s-n||l<n||l>s-n){const e=4*(i*t+o);a[e]=r[0],a[e+1]=r[1],a[e+2]=r[2],a[e+3]=r[3]}}return a}static isometric(t,e,i={}){const{cellSize:s=20,lineWidth:n=1,background:o=[0,0,0,0],foreground:r=[0,255,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];const h=s,l=s/2;for(let i=0;i<e;i++)for(let e=0;e<t;e++){const s=e%h,o=i%l,c=o-s/2,u=o+s/2-l,d=Math.abs(c)<n/2,f=Math.abs(u)<n/2;if(d||f){const s=4*(i*t+e);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static weave(t,e,i={}){const{tileSize:s=40,lineWidth:n=2,background:o=[255,255,255,255],foreground:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let t=0;t<a.length;t+=4)a[t]=o[0],a[t+1]=o[1],a[t+2]=o[2],a[t+3]=o[3];for(let i=0;i<e;i++)for(let e=0;e<t;e++){const o=e%s,h=i%s,l=Math.abs((h+s/2)%s-s/2)<n/2,c=Math.abs((o+2*h+1.5*s)%s-s/2)<n/2,u=Math.abs((o-2*h+1.5*s)%s-s/2)<n/2;if(l||c||u){const s=4*(i*t+e);a[s]=r[0],a[s+1]=r[1],a[s+2]=r[2],a[s+3]=r[3]}}return a}static perlinNoise(t,e,i={}){const{background:s=[0,0,0,0],foreground:n=[255,255,255,255],scale:o=.1,octaves:r=4,persistence:a=.5,lacunarity:h=2,seed:l=65536*Math.random()}=i,c=new Uint8ClampedArray(t*e*4);Lt.seed(l);for(let i=0;i<e;i++)for(let e=0;e<t;e++){let l=1,u=1,d=0,f=0;for(let t=0;t<r;t++){const t=e*o*u,s=i*o*u;d+=Lt.perlin2(t,s)*l,f+=l,l*=a,u*=h}d/=f;const p=.5*(d+1),g=[Math.floor(s[0]+p*(n[0]-s[0])),Math.floor(s[1]+p*(n[1]-s[1])),Math.floor(s[2]+p*(n[2]-s[2])),Math.floor(s[3]+p*(n[3]-s[3]))],m=4*(i*t+e);c.set(g,m)}return c}static circularGradient(t,e,i={}){const{innerColor:s=[255,255,255,255],outerColor:n=[0,0,0,255],centerX:o=t/2,centerY:r=e/2,radius:a=Math.min(t,e)/2,fadeExponent:h=1}=i,l=new Uint8ClampedArray(t*e*4);for(let i=0;i<e;i++)for(let e=0;e<t;e++){const c=4*(i*t+e),u=e-o,d=i-r,f=Math.sqrt(u*u+d*d);let p=Math.min(f/a,1);p=Math.pow(p,h);const g=[Math.floor(s[0]+p*(n[0]-s[0])),Math.floor(s[1]+p*(n[1]-s[1])),Math.floor(s[2]+p*(n[2]-s[2])),Math.floor(s[3]+p*(n[3]-s[3]))];l.set(g,c)}return l}static noiseDisplacement(t,e,i={}){const{gridSpacing:s=16,gridColor:n=[255,255,255,255],background:o=[0,0,0,0],displacementScale:r=8,noiseScale:a=.05,gridThickness:h=1,seed:l=65536*Math.random()}=i,c=new Uint8ClampedArray(t*e*4);Lt.seed(l);for(let t=0;t<c.length;t+=4)c.set(o,t);for(let i=0;i<e;i++)for(let e=0;e<t;e++){const o=e+Lt.perlin2(e*a,i*a)*r,l=i+Lt.perlin2((e+31.416)*a,(i+27.182)*a)*r;if(o%s<h||o%s>s-h||l%s<h||l%s>s-h){const s=4*(i*t+e);c.set(n,s)}}return c}static dotPattern(t,e,i={}){const{dotSize:s=3,spacing:n=12,dotColor:o=[0,0,0,255],background:r=[255,255,255,255],useNoise:a=!1,noiseScale:h=.1,noiseDensity:l=.4,seed:c=65536*Math.random()}=i,u=new Uint8ClampedArray(t*e*4);a&&Lt.seed(c);for(let t=0;t<u.length;t+=4)u.set(r,t);if(a){for(let i=0;i<e;i++)for(let n=0;n<t;n++)if(.5*(Lt.perlin2(n*h,i*h)+1)>l)for(let r=-s;r<=s;r++)for(let a=-s;a<=s;a++){const h=n+a,l=i+r;if(h>=0&&h<t&&l>=0&&l<e&&a*a+r*r<=s*s){const e=4*(l*t+h);u.set(o,e)}}}else for(let i=Math.floor(n/2);i<e;i+=n)for(let r=Math.floor(n/2);r<t;r+=n)for(let n=-s;n<=s;n++)for(let a=-s;a<=s;a++){const h=r+a,l=i+n;if(h>=0&&h<t&&l>=0&&l<e&&a*a+n*n<=s*s){const e=4*(l*t+h);u.set(o,e)}}return u}static voronoi(t,e,i={}){const{cellCount:s=20,cellColors:n=null,edgeColor:o=[0,0,0,255],edgeThickness:r=1.5,seed:a=1e3*Math.random(),jitter:h=.5,baseColor:l=null,colorVariation:c=.3}=i,u=new Uint8ClampedArray(t*e*4);Lt.seed(a);const d=[],f=[],p=()=>{let t=1e4*Math.sin(.167*a+.423*d.length);return t-Math.floor(t)},g=Math.sqrt(s),m=t/g,v=e/g,y=t=>{if(l){const[e,i,s,n]=l,o=Math.max(e,i,s)/255,r=Math.min(e,i,s)/255,a=(o+r)/2;let h,u;if(o===r)h=u=0;else{const t=o-r;u=a>.5?t/(2-o-r):t/(o+r),h=o===e/255?(i/255-s/255)/t+(i/255<s/255?6:0):o===i/255?(s/255-e/255)/t+2:(e/255-i/255)/t+4,h/=6}const d=Lt.perlin2(.15*t,0)*c*.3,f=Lt.perlin2(0,.15*t)*c,g=Lt.perlin2(.15*t,.15*t)*c*.5;h=(h+d)%1,u=Math.min(1,Math.max(0,u*(1+f)));const m=Math.min(.9,Math.max(.1,a*(1+g)));let v,y,_;if(0===u)v=y=_=m;else{const t=(t,e,i)=>(i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t),e=m<.5?m*(1+u):m+u-m*u,i=2*m-e;v=t(i,e,h+1/3),y=t(i,e,h),_=t(i,e,h-1/3)}const x=.05,b=()=>(2*p()-1)*x;return[Math.min(255,Math.max(0,Math.floor(255*v*(1+b())))),Math.min(255,Math.max(0,Math.floor(255*y*(1+b())))),Math.min(255,Math.max(0,Math.floor(255*_*(1+b())))),n]}{let e,i,s;const n=.618033988749895*t%1*6,o=Math.floor(n),r=n-o,a=.5,h=.5*(1-r),l=.5*(1-(1-r));switch(o%6){case 0:e=.5,i=l,s=a;break;case 1:e=h,i=.5,s=a;break;case 2:e=a,i=.5,s=l;break;case 3:e=a,i=h,s=.5;break;case 4:e=l,i=a,s=.5;break;case 5:e=.5,i=a,s=h}return[Math.floor(255*e+50+100*p()),Math.floor(255*i+50+100*p()),Math.floor(255*s+50+100*p()),255]}};for(let t=0;t<g;t++)for(let e=0;e<g&&!(d.length>=s);e++){const i=e*m+m/2,s=t*v+v/2,o=(2*p()-1)*h*m,r=(2*p()-1)*h*v;d.push({x:Math.floor(i+o),y:Math.floor(s+r)}),n&&d.length-1<n.length?f.push(n[d.length-1]):f.push(y(d.length-1))}const _=(i,s,n,o)=>{let r=Math.abs(i-n),a=Math.abs(s-o);return r=Math.min(r,t-r),a=Math.min(a,e-a),.8*Math.sqrt(r*r+a*a)+.2*(r+a)};for(let i=0;i<e;i++)for(let s=0;s<t;s++){const n=4*(i*t+s);let a=1/0,h=1/0,l=0;for(let t=0;t<d.length;t++){const e=_(s,i,d[t].x,d[t].y);e<a?(h=a,a=e,l=t):e<h&&(h=e)}for(let n=0;n<d.length;n++)for(let o=-1;o<=1;o++)for(let r=-1;r<=1;r++){if(0===o&&0===r)continue;const c=d[n].x+o*t,u=d[n].y+r*e,f=Math.sqrt(Math.pow(s-c,2)+Math.pow(i-u,2));f<a?(h=a,a=f,l=n):f<h&&(h=f)}h-a<r?u.set(o,n):u.set(f[l],n)}return u}static penrose(t,e,i={}){return Yt(t,e,i)}},t.Physics=Ys,t.PhysicsUpdaters=Xs,t.PieSlice=class extends Ze{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Le.lines.beginPath(),Le.lines.moveTo(0,0),Le.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle),Le.lines.closePath(),this.color&&Le.colors.fill(this.color),this.stroke&&Le.colors.stroke(this.stroke,this.lineWidth)}},t.Pin=yi,t.Pipeline=hs,t.Plane3D=fi,t.PlatformerScene=class extends Oi{constructor(t,e={}){super(t,e),this.player=e.player??null,this._layers=[],this.gravity=e.gravity??1200,this.groundY=e.groundY??null,this.moveSpeed=e.moveSpeed??300,this.jumpVelocity=e.jumpVelocity??-500,this.autoInput=e.autoInput??!0,this.autoGravity=e.autoGravity??!0,this._viewportWidth=e.viewportWidth??null,this._viewportHeight=e.viewportHeight??null,this.player&&(void 0===this.player.vx&&(this.player.vx=0),void 0===this.player.vy&&(this.player.vy=0),void 0===this.player._grounded&&(this.player._grounded=!0)),e.camera?this.camera=e.camera:this.player?this.camera=new Bt({target:this.player,viewportWidth:this._viewportWidth??t.width,viewportHeight:this._viewportHeight??t.height,lerp:.1}):this.camera=null}addLayer(t,e={}){const i={gameObject:t,speed:e.speed??1,offsetX:e.offsetX??0,offsetY:e.offsetY??0};return this._layers.push(i),this.add(t),t}removeLayer(t){const e=this._layers.findIndex(e=>e.gameObject===t);return-1!==e&&(this._layers.splice(e,1),this.remove(t),!0)}getLayers(){return[...this._layers]}isLayer(t){return this._layers.some(e=>e.gameObject===t)}applyGravity(t,e){t.vy=(t.vy||0)+this.gravity*e}applyInput(t,e){let i=0;Ri.isDown(Ri.LEFT)||Ri.isDown(Ri.A)?i=-1:(Ri.isDown(Ri.RIGHT)||Ri.isDown(Ri.D))&&(i=1),t.vx=i*this.moveSpeed,(Ri.isDown(Ri.SPACE)||Ri.isDown(Ri.W)||Ri.isDown(Ri.UP))&&this.isPlayerGrounded()&&(t.vy=this.jumpVelocity,t._grounded=!1)}updateCamera(t){this.camera&&this.camera.update(t)}getCameraOffset(){return this.camera?this.camera.getOffset():{x:0,y:0}}isPlayerGrounded(){var t;return!0===(null==(t=this.player)?void 0:t._grounded)}applyVelocity(t,e){t.x+=(t.vx||0)*e,t.y+=(t.vy||0)*e}handleGroundCollision(t){null!==this.groundY&&t.y>=this.groundY&&(t.y=this.groundY,t.vy=0,t._grounded=!0)}update(t){this.player&&(this.autoGravity&&this.applyGravity(this.player,t),this.autoInput&&this.applyInput(this.player,t),this.applyVelocity(this.player,t),this.handleGroundCollision(this.player)),this.updateCamera(t),super.update(t)}draw(){this.applyTransforms(),this.drawDebug();const t=this._viewportWidth??this.game.width,e=this._viewportHeight??this.game.height,i=this.getCameraOffset();Le.save(),Le.ctx.beginPath(),Le.ctx.rect(-this.x,-this.y,t,e),Le.ctx.clip(),Le.ctx.beginPath(),Le.ctx.translate(-this.x,-this.y);for(const t of this._layers){if(!t.gameObject.visible)continue;Le.save();const e=i.x*t.speed+(t.offsetX||0),s=i.y*t.speed+(t.offsetY||0);Le.ctx.translate(-e,-s),t.gameObject.render(),Le.restore()}for(const t of this._collection.getSortedChildren())t.visible&&(this._layers.some(e=>e.gameObject===t)||(Le.save(),Le.ctx.translate(-i.x,-i.y),t.render(),Le.restore()));Le.restore()}shakeCamera(t,e){return this.camera&&this.camera.shake(t,e),this}setViewport(t,e){return this._viewportWidth=t,this._viewportHeight=e,this.camera&&(this.camera.viewportWidth=t,this.camera.viewportHeight=e),this}getViewport(){return{width:this._viewportWidth??this.game.width,height:this._viewportHeight??this.game.height}}},t.Polygon=mi,t.Position=kt,t.Prism=class extends Ze{constructor(t=100,e={}){super(e),this.depth=t,this.faceTopColor=e.faceTopColor||"#eee",this.faceBottomColor=e.faceBottomColor||"#ccc",this.faceLeftColor=e.faceLeftColor||"#aaa",this.faceRightColor=e.faceRightColor||"#888",this.faceFrontColor=e.faceFrontColor||"#666",this.faceBackColor=e.faceBackColor||"#444",this.stroke=e.stroke||null,this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0,this.visibleFaces=e.visibleFaces||["top","left","right","front","back","bottom"]}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}draw(){super.draw();const t=this.width/2,e=this.height/2,i=this.depth/2,s=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},n=(t,e,i)=>{const n=s(t,e,i);return{x:(n.x-n.y)*Math.cos(Math.PI/6),y:(n.x+n.y)*Math.sin(Math.PI/6)-n.z,z:n.z}},o={p0:n(-t,-i,-e),p1:n(t,-i,-e),p2:n(0,-i,e),p3:n(-t,i,-e),p4:n(t,i,-e),p5:n(0,i,e)},r={front:{points:[o.p0,o.p1,o.p2],color:this.faceFrontColor},back:{points:[o.p3,o.p4,o.p5],color:this.faceBackColor},bottom:{points:[o.p0,o.p1,o.p4,o.p3],color:this.faceBottomColor},right:{points:[o.p1,o.p2,o.p5,o.p4],color:this.faceRightColor},left:{points:[o.p0,o.p2,o.p5,o.p3],color:this.faceLeftColor}};this.visibleFaces.filter(t=>r[t]).map(t=>{const e=r[t],i=e.points.reduce((t,e)=>t+e.x,0)/e.points.length,s=e.points.reduce((t,e)=>t+e.y,0)/e.points.length,n=e.points.reduce((t,e)=>t+(e.z||0),0)/e.points.length;return{key:t,face:e,depth:i*i+s*s+n*n}}).sort((t,e)=>e.depth-t.depth).forEach(({key:t,face:e})=>{(null==e?void 0:e.color)&&Le.shapes.polygon(e.points,e.color,this.stroke,this.lineWidth)})}getBounds(){const t=1.5*Math.max(this.width,this.height,this.depth);return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Random=It,t.Rectangle=Je,t.Renderable=Ue,t.RightTriangle=class extends Ze{constructor(t=50,e={}){super(e),this._leg=t,this._updateDimensions()}get leg(){return this._leg}set leg(t){this._leg=t,this._updateDimensions(),this.invalidateCache()}get hypotenuse(){return this._leg*Math.SQRT2}_updateDimensions(){this._width=this._leg,this._height=this._leg}getVertices(){const t=this._leg,e=t/3,i=t/3;return[{x:-e,y:-i},{x:t-e,y:-i},{x:-e,y:t-i}]}draw(){super.draw();const t=this.getVertices();Le.shapes.polygon(t,this.color,this.stroke,this.lineWidth,this.lineJoin)}calculateBounds(){return{x:this.x,y:this.y,width:this._width,height:this._height}}},t.Ring=gi,t.RoundedRectangle=Qe,t.SPHERE_SHADERS=ai,t.SVGShape=pi,t.Scene=Oi,t.Scene3D=class extends Oi{constructor(t,e={}){if(super(t,e),!e.camera)throw new Error("Scene3D requires a camera option");this.camera=e.camera,this.depthSort=e.depthSort??!0,this.scaleByDepth=e.scaleByDepth??!0}render(){if(!this.visible)return;Le.save(),Le.translateTo(this.x,this.y);const t=[];for(const e of this._collection.getSortedChildren()){if(!e.visible)continue;const i=e.z??0,s=this.camera.project(e.x,e.y,i);s.z<10-this.camera.perspective||t.push({child:e,x:s.x,y:s.y,z:s.z,scale:s.scale})}this.depthSort&&t.sort((t,e)=>{const i=t.child.zIndex??0,s=e.child.zIndex??0;return i!==s?i-s:e.z-t.z});for(const e of t)Le.save(),Le.translateTo(e.x,e.y),this.scaleByDepth&&Le.ctx.scale(e.scale,e.scale),Le.translateTo(-e.child.x,-e.child.y),e.child.render(),Le.restore();Le.restore()}},t.Screen=Bi,t.Shape=Ze,t.ShapeGOFactory=class{static create(t,e,i={}){const s={x:(null==e?void 0:e.x)??0,y:(null==e?void 0:e.y)??0,width:(null==e?void 0:e.width)??0,height:(null==e?void 0:e.height)??0,rotation:(null==e?void 0:e.rotation)??0,scaleX:(null==e?void 0:e.scaleX)??1,scaleY:(null==e?void 0:e.scaleY)??1,opacity:(null==e?void 0:e.opacity)??1,visible:(null==e?void 0:e.visible)??!0,active:!0,debug:(null==e?void 0:e.debug)??!1,color:(null==e?void 0:e.color)??null,stroke:(null==e?void 0:e.stroke)??null,lineWidth:(null==e?void 0:e.lineWidth)??1,lineJoin:(null==e?void 0:e.lineJoin)??"miter",lineCap:(null==e?void 0:e.lineCap)??"butt",miterLimit:(null==e?void 0:e.miterLimit)??10,...i,name:i.name??(null==e?void 0:e.constructor.name)??"ShapeWrapper"};return new Fi(t,e,s)}},t.Sound=class{static beep(t=440,e=.1,i={}){if(!Os.isInitialized)return;const{volume:s=.3,type:n="sine"}=i;Os.osc.tone(t,e,{type:n,volume:s,attack:.001,decay:.8*e,sustain:0,release:.2*e})}static click(t=.3){Os.isInitialized&&Os.osc.tone(1e3,.01,{type:"square",volume:t,attack:.001,decay:.009,sustain:0,release:.001})}static sweep(t,e,i,s={}){if(!Os.isInitialized)return;const{volume:n=.3,type:o="sine"}=s;Os.osc.sweep(t,e,i,{type:o,volume:n})}static fromValue(t,e={}){if(!Os.isInitialized)return;const{root:i="C4",scale:s="pentatonic",octaves:n=2,duration:o=.2,volume:r=.3,type:a="sine"}=e,h=Os.music.mapToScale(t,i,s,n);Os.osc.tone(h,o,{volume:r,type:a})}static impact(t=.5){if(!Os.isInitialized)return;const e=80+200*t,i=.05+.15*t;Os.osc.tone(e,i,{type:"sine",volume:.4*t,attack:.001,decay:i,sustain:0,release:.02});const s=Os.noise.white(Os.ctx,.08),n=Os.ctx.createGain();n.gain.setValueAtTime(.25*t,Os.now),n.gain.exponentialRampToValueAtTime(.001,Os.now+.08),s.connect(n),n.connect(Os.master),s.start(),s.stop(Os.now+.1)}static explosion(t=.7){if(!Os.isInitialized)return;const e=.3+.4*t;Os.osc.tone(50+30*t,e,{type:"sine",volume:.4*t,attack:.001,decay:.3*e,sustain:.3,release:.7*e});const i=Os.noise.brown(Os.ctx,e),s=Os.ctx.createGain(),n=Os.fx.filter("lowpass",800+400*t,1);s.gain.setValueAtTime(.5*t,Os.now),s.gain.exponentialRampToValueAtTime(.001,Os.now+e),i.connect(n),n.connect(s),s.connect(Os.master),i.start(),i.stop(Os.now+e+.1)}static laser(t={}){if(!Os.isInitialized)return;const{startFreq:e=1200,endFreq:i=200,duration:s=.15,volume:n=.25,type:o="sawtooth"}=t;Os.osc.sweep(e,i,s,{type:o,volume:n})}static powerUp(t={}){if(!Os.isInitialized)return;const{startFreq:e=300,endFreq:i=1200,duration:s=.3,volume:n=.3}=t;Os.osc.sweep(e,i,s,{type:"square",volume:n}),Os.osc.sweep(1.5*e,1.5*i,s,{type:"sine",volume:.5*n})}static hurt(t=.5){Os.isInitialized&&(Os.osc.tone(80+40*t,.1,{type:"sine",volume:.4*t,attack:.001,decay:.08,sustain:0,release:.02}),Os.osc.tone(200+100*t,.08,{type:"sawtooth",volume:.2*t,attack:.001,decay:.06,sustain:0,release:.02}))}static coin(t={}){if(!Os.isInitialized)return;const{baseFreq:e=987.77,volume:i=.25}=t;Os.osc.tone(e,.08,{type:"square",volume:i,attack:.001,decay:.05,sustain:.3,release:.02}),setTimeout(()=>{Os.isInitialized&&Os.osc.tone(1.5*e,.12,{type:"square",volume:i,attack:.001,decay:.08,sustain:.2,release:.04})},80)}static jump(t={}){if(!Os.isInitialized)return;const{startFreq:e=150,endFreq:i=400,duration:s=.15,volume:n=.25}=t;Os.osc.sweep(e,i,s,{type:"square",volume:n})}static select(t={}){if(!Os.isInitialized)return;const{frequency:e=660,volume:i=.2}=t;Os.osc.tone(e,.08,{type:"sine",volume:i,attack:.001,decay:.05,sustain:.3,release:.03})}static error(t={}){if(!Os.isInitialized)return;const{volume:e=.25}=t;Os.osc.tone(400,.1,{type:"square",volume:e,attack:.001,decay:.08,sustain:0,release:.02}),setTimeout(()=>{Os.isInitialized&&Os.osc.tone(300,.15,{type:"square",volume:e,attack:.001,decay:.12,sustain:0,release:.03})},100)}static drone(t="C2",e={}){if(!Os.isInitialized)return null;const{volume:i=.2,richness:s=.5}=e,n=Os.music.noteToFreq(t),o=[],r=[],a=[1,.5*s,.3*s,.2*s];return[n,1.5*n,2*n,3*n].forEach((t,e)=>{const s=Os.ctx.createOscillator(),n=Os.ctx.createGain();s.type="sine",s.frequency.value=t,n.gain.value=a[e]*i,s.connect(n),n.connect(Os.master),s.start(),o.push(s),r.push(n)}),{stop:(t=.5)=>{const e=Os.now;r.forEach(i=>{i.gain.linearRampToValueAtTime(0,e+t)}),setTimeout(()=>{o.forEach(t=>{try{t.stop()}catch(t){}})},1e3*t+100)},setVolume:t=>{r.forEach((e,i)=>{e.gain.linearRampToValueAtTime(a[i]*t,Os.now+.1)})}}}static note(t,e=.5,i={}){if(!Os.isInitialized)return;const{volume:s=.3,type:n="sine",envelope:o={}}=i,r=Os.music.noteToFreq(t);Os.osc.tone(r,e,{type:n,volume:s,...Os.env.presets.pluck,...o})}static chord(t,e="major",i=.5,s={}){if(!Os.isInitialized)return;const{volume:n=.2,type:o="sine",strum:r=0}=s,a=Os.music.chord(t,e);a.forEach((t,e)=>{const s=r*e;Os.osc.tone(t,i,{type:o,volume:n/a.length,attack:.01,decay:.1,sustain:.6,release:.2,startTime:Os.now+s})})}static sequence(t,e=.2,i=0,s={}){if(!Os.isInitialized)return;const{volume:n=.3,type:o="sine"}=s,r=e+i;t.forEach((t,i)=>{const s=Os.now+i*r,a=Os.music.noteToFreq(t);Os.osc.tone(a,e,{type:o,volume:n,attack:.01,decay:.05,sustain:.5,release:.1,startTime:s})})}static win(){Os.isInitialized&&this.sequence(["C5","E5","G5","C6"],.15,.05,{volume:.25,type:"square"})}static lose(){Os.isInitialized&&this.sequence(["E4","D4","C4"],.25,0,{volume:.25,type:"sawtooth"})}},t.Sphere=class extends Ze{constructor(t=50,e={}){super(e),this.radius=t,this.hSegments=e.hSegments||16,this.vSegments=e.vSegments||12,this.color=e.color||"#6495ED",this.highlightColor=e.highlightColor||"#FFFFFF",this.wireframe=e.wireframe||!1,this.stroke=e.stroke||"#333333",this.lineWidth=e.lineWidth||1,this.rotationX=e.rotationX||0,this.rotationY=e.rotationY||0,this.rotationZ=e.rotationZ||0}setRotation(t,e,i){return this.rotationX=t,this.rotationY=e,this.rotationZ=i,this}rotate(t,e,i){return this.rotationX+=t,this.rotationY+=e,this.rotationZ+=i,this}calculateSurfaceColor(t,e,i){let s=t*(1/Math.sqrt(3))+e*(1/Math.sqrt(3))+i*(1/Math.sqrt(3));if(s=Math.max(.3,s),this.highlightColor){const t=this.hexToRgb(this.color),e=this.hexToRgb(this.highlightColor);return`rgb(${Math.round(t.r*(1-s)+e.r*s)}, ${Math.round(t.g*(1-s)+e.g*s)}, ${Math.round(t.b*(1-s)+e.b*s)})`}const n=this.hexToRgb(this.color);return`rgb(${Math.min(255,Math.round(n.r*s))}, ${Math.min(255,Math.round(n.g*s))}, ${Math.min(255,Math.round(n.b*s))})`}hexToRgb(t){const e={r:100,g:100,b:255};if(!t||"string"!=typeof t)return e;const i=t.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,(t,e,i,s)=>e+e+i+i+s+s),s=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(i);return s?{r:parseInt(s[1],16),g:parseInt(s[2],16),b:parseInt(s[3],16)}:e}draw(){super.draw();const t=this.radius,e=(t,e,i)=>{let s=e,n=i;e=s*Math.cos(this.rotationX)-n*Math.sin(this.rotationX);let o=t;return n=i=s*Math.sin(this.rotationX)+n*Math.cos(this.rotationX),t=o*Math.cos(this.rotationY)+n*Math.sin(this.rotationY),i=-o*Math.sin(this.rotationY)+n*Math.cos(this.rotationY),o=t,s=e,{x:t=o*Math.cos(this.rotationZ)-s*Math.sin(this.rotationZ),y:e=o*Math.sin(this.rotationZ)+s*Math.cos(this.rotationZ),z:i}},i=(i,s,n)=>{const o=e(i,s,n);return{x:(o.x-o.y)*Math.cos(Math.PI/6),y:(o.x+o.y)*Math.sin(Math.PI/6)-o.z,z:o.z,nx:o.x/t,ny:o.y/t,nz:o.z/t}},s=[];for(let e=0;e<=this.vSegments;e++){const n=[],o=e/this.vSegments,r=Math.PI*o-Math.PI/2;for(let e=0;e<=this.hSegments;e++){const s=e/this.hSegments,o=2*Math.PI*s,a=t*Math.cos(r)*Math.cos(o),h=t*Math.cos(r)*Math.sin(o),l=t*Math.sin(r);n.push(i(a,h,l))}s.push(n)}const n=[];for(let t=0;t<this.vSegments;t++)for(let e=0;e<this.hSegments;e++){const i=s[t][e],o=s[t][e+1],r=s[t+1][e],a=s[t+1][e+1],h=(i.z+o.z+r.z+a.z)/4,l=(i.nx+o.nx+r.nx+a.nx)/4,c=(i.ny+o.ny+r.ny+a.ny)/4,u=(i.nz+o.nz+r.nz+a.nz)/4;n.push({points:[i,o,a,r],z:h,color:this.calculateSurfaceColor(l,c,u)})}if(n.sort((t,e)=>e.z-t.z),this.wireframe)for(const t of n){const e=t.points;for(let t=0;t<e.length;t++){const i=(t+1)%e.length;Le.lines.line(e[t].x,e[t].y,e[i].x,e[i].y,this.stroke,this.lineWidth)}}for(const t of n)Le.shapes.polygon(t.points,t.color,this.stroke,this.lineWidth)}getBounds(){const t=2*this.radius*1.5;return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Sphere3D=li,t.Sprite=Yi,t.SpriteSheet=Xi,t.Square=ti,t.Star=ni,t.StateMachine=Ls,t.Stepper=class extends Ei{constructor(t,e={}){super(t,e);const{x:i=0,y:s=0,value:n=0,min:o=-1/0,max:r=1/0,step:a=1,buttonSize:h=32,valueWidth:l=60,height:c=32,gap:u=4,font:d=cs.fonts.medium,onChange:f=null,formatValue:p=null,label:g=""}=e;this.x=i,this.y=s,this.buttonSize=h,this.valueWidth=l,this.stepperHeight=c,this.gap=u,this.font=d,this._value=this.clamp(n,o,r),this.min=o,this.max=r,this.step=a,this.onChange=f,this.formatValue=p||(t=>String(t)),this.labelText=g,this.width=h+u+l+u+h,this.height=g?c+20:c,this.initComponents(),this.initEvents()}clamp(t,e,i){return Math.max(e,Math.min(i,t))}initComponents(){this.group=new Ve;const t=this.width/2,e=this.buttonSize/2;this.valueWidth;const i=-t+e,s=t-e,n=this.labelText?8:0,o=this.labelText?-(this.stepperHeight/2+4):0;this.labelText&&(this.label=new wi(this.labelText,{font:cs.fonts.small,color:cs.colors.dimText,align:"center",baseline:"middle"}),this.label.y=o,this.group.add(this.label)),this.decrementBg=new Je({width:this.buttonSize,height:this.stepperHeight,color:cs.button.default.bg,stroke:cs.button.default.stroke,lineWidth:1}),this.decrementBg.x=i,this.decrementBg.y=n,this.decrementText=new wi("−",{font:this.font,color:cs.button.default.text,align:"center",baseline:"middle"}),this.decrementText.x=i,this.decrementText.y=n,this.valueBg=new Je({width:this.valueWidth,height:this.stepperHeight,color:cs.colors.darkerBg,stroke:cs.colors.subtleBorder,lineWidth:1}),this.valueBg.x=0,this.valueBg.y=n,this.valueText=new wi(this.formatValue(this._value),{font:this.font,color:cs.colors.neonGreen,align:"center",baseline:"middle"}),this.valueText.x=0,this.valueText.y=n,this.incrementBg=new Je({width:this.buttonSize,height:this.stepperHeight,color:cs.button.default.bg,stroke:cs.button.default.stroke,lineWidth:1}),this.incrementBg.x=s,this.incrementBg.y=n,this.incrementText=new wi("+",{font:this.font,color:cs.button.default.text,align:"center",baseline:"middle"}),this.incrementText.x=s,this.incrementText.y=n,this.group.add(this.decrementBg),this.group.add(this.decrementText),this.group.add(this.valueBg),this.group.add(this.valueText),this.group.add(this.incrementBg),this.group.add(this.incrementText),this._decrementBounds={x:i-this.buttonSize/2,y:n-this.stepperHeight/2,width:this.buttonSize,height:this.stepperHeight},this._incrementBounds={x:s-this.buttonSize/2,y:n-this.stepperHeight/2,width:this.buttonSize,height:this.stepperHeight},this._decrementHover=!1,this._incrementHover=!1,this._decrementPressed=!1,this._incrementPressed=!1}initEvents(){this.interactive=!0,this._isMouseOver=!1,this.on("mouseover",()=>{this._isMouseOver=!0}),this.on("mouseout",()=>{this._isMouseOver=!1,this.handleMouseOut()}),this.game.events.on("inputmove",t=>{this._isMouseOver&&this.handleMouseMove(t)}),this.on("inputdown",t=>this.handleInputDown(t)),this.on("inputup",()=>this.handleInputUp())}screenToLocal(t,e){let i=t,s=e;const n=[];let o=this;for(;o;)n.unshift(o),o=o.parent;for(const t of n){if(i-=t.x||0,s-=t.y||0,t.rotation){const e=Math.cos(-t.rotation),n=Math.sin(-t.rotation),o=i;i=o*e-s*n,s=o*n+s*e}void 0!==t.scaleX&&0!==t.scaleX&&(i/=t.scaleX),void 0!==t.scaleY&&0!==t.scaleY&&(s/=t.scaleY)}return{x:i,y:s}}isPointInBounds(t,e,i){return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}handleMouseMove(t){const e=this.screenToLocal(t.x,t.y),i=this._decrementHover,s=this._incrementHover;this._decrementHover=this.isPointInBounds(e.x,e.y,this._decrementBounds),this._incrementHover=this.isPointInBounds(e.x,e.y,this._incrementBounds),i===this._decrementHover&&s===this._incrementHover||this.updateButtonStates(),this._decrementHover||this._incrementHover?this.game.canvas.style.cursor="pointer":this.game.canvas.style.cursor="default"}handleMouseOut(){this._decrementHover=!1,this._incrementHover=!1,this._decrementPressed=!1,this._incrementPressed=!1,this.updateButtonStates(),this.game.canvas.style.cursor="default"}handleInputDown(t){const e=this.screenToLocal(t.x,t.y);this.isPointInBounds(e.x,e.y,this._decrementBounds)?(this._decrementPressed=!0,this.decrement()):this.isPointInBounds(e.x,e.y,this._incrementBounds)&&(this._incrementPressed=!0,this.increment()),this.updateButtonStates()}handleInputUp(){this._decrementPressed=!1,this._incrementPressed=!1,this.updateButtonStates()}updateButtonStates(){this._decrementPressed?(this.decrementBg.color=cs.button.pressed.bg,this.decrementBg.stroke=cs.button.pressed.stroke,this.decrementText.color=cs.button.pressed.text):this._decrementHover?(this.decrementBg.color=cs.button.hover.bg,this.decrementBg.stroke=cs.button.hover.stroke,this.decrementText.color=cs.button.hover.text):(this.decrementBg.color=cs.button.default.bg,this.decrementBg.stroke=cs.button.default.stroke,this.decrementText.color=cs.button.default.text),this._value<=this.min&&(this.decrementBg.stroke=cs.colors.subtleBorder,this.decrementText.color=cs.colors.dimText),this._incrementPressed?(this.incrementBg.color=cs.button.pressed.bg,this.incrementBg.stroke=cs.button.pressed.stroke,this.incrementText.color=cs.button.pressed.text):this._incrementHover?(this.incrementBg.color=cs.button.hover.bg,this.incrementBg.stroke=cs.button.hover.stroke,this.incrementText.color=cs.button.hover.text):(this.incrementBg.color=cs.button.default.bg,this.incrementBg.stroke=cs.button.default.stroke,this.incrementText.color=cs.button.default.text),this._value>=this.max&&(this.incrementBg.stroke=cs.colors.subtleBorder,this.incrementText.color=cs.colors.dimText)}increment(){this.value=this._value+this.step}decrement(){this.value=this._value-this.step}get value(){return this._value}set value(t){const e=this.clamp(t,this.min,this.max);e!==this._value&&(this._value=e,this.valueText.text=this.formatValue(this._value),this.updateButtonStates(),"function"==typeof this.onChange&&this.onChange(this._value))}setBounds(t,e){this.min=t,this.max=e,this.value=this._value}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}draw(){super.draw(),this.group.render()}},t.StickFigure=class extends Ze{constructor(t=1,e={}){super(e),this.scale=t,this.stroke=e.stroke||"#000",this.headColor=e.headColor||this.stroke,this.jointColor=e.jointColor||this.stroke,this.lineWidth=e.lineWidth||2,this.showJoints=!1!==e.showJoints}draw(){super.draw();const t=this.scale,e=10*t,i=-30*t,s=i+e,n=s+40*t,o=s+10*t,r=15*t,a=10*t,h=n+40*t,l=3*t;Le.shapes.fillCircle(0,i,e,this.headColor),Le.shapes.strokeCircle(0,i,e,this.stroke,this.lineWidth),Le.lines.line(0,s,0,n,this.stroke,this.lineWidth),Le.lines.line(-r,o,r,o,this.stroke,this.lineWidth),Le.lines.line(0,n,-a,h,this.stroke,this.lineWidth),Le.lines.line(0,n,a,h,this.stroke,this.lineWidth),this.showJoints&&[[0,s],[-r,o],[r,o],[0,n],[-a,h],[a,h]].forEach(([t,e])=>Le.shapes.fillCircle(t,e,l,this.jointColor))}getBounds(){const t=100*this.scale,e=40*this.scale;return{x:this.x,y:this.y,width:e,height:t}}},t.Synth=Os,t.SynthAnalyzer=Fs,t.SynthEffects=Bs,t.SynthEnvelope=zs,t.SynthMusical=Es,t.SynthNoise=Is,t.SynthOscillators=Ds,t.TaskManager=class{constructor(t){this.worker=new Worker(t),this.nextTaskId=1,this.pendingTasks=new Map,this.worker.onmessage=this.handleMessage.bind(this)}handleMessage(t){const{taskId:e,status:i,result:s,error:n}=t.data;if(this.pendingTasks.has(e)){const{resolve:t,reject:o}=this.pendingTasks.get(e);"complete"===i?t(s):"error"===i&&o(new Error(n)),this.pendingTasks.delete(e)}}runTask(t,e){return new Promise((i,s)=>{const n=this.nextTaskId++;this.pendingTasks.set(n,{resolve:i,reject:s}),this.worker.postMessage({taskId:n,taskName:t,params:e})})}terminate(){this.worker.terminate()}},t.Tensor=class t{constructor(t,e={}){wt(this,f),wt(this,p),wt(this,g),wt(this,m),wt(this,v),Mt(this,f,t.map(t=>[...t])),Mt(this,p,t.length),Mt(this,g,e.name||""),Mt(this,m,e.signature||null),Mt(this,v,e.coordinates||null)}static minkowski(){return new t([[-1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],{name:"Minkowski",signature:[-1,1,1,1],coordinates:["t","x","y","z"]})}static schwarzschild(e,i,s=Math.PI/2){e<=i&&(e=1.001*i);const n=1-i/e,o=Math.sin(s);return new t([[-n,0,0,0],[0,1/n,0,0],[0,0,e*e,0],[0,0,0,e*e*o*o]],{name:"Schwarzschild",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static schwarzschildContravariant(e,i,s=Math.PI/2){e<=i&&(e=1.001*i);const n=1-i/e,o=Math.sin(s);return new t([[-1/n,0,0,0],[0,n,0,0],[0,0,1/(e*e),0],[0,0,0,1/(e*e*o*o)]],{name:"Schwarzschild (Contravariant)",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static kerr(e,i,s,n){const o=(n=Math.min(Math.abs(n),s))*n,r=e*e,a=Math.cos(i),h=Math.sin(i),l=h*h,c=a*a,u=r+o*c,d=r-2*s*e+o,f=s+Math.sqrt(Math.max(0,s*s-o));if(e<=f){const r=(e=1.001*f)*e,a=r+o*c,h=r-2*s*e+o;return t._buildKerrMetric(e,i,s,n,a,h,l)}return t._buildKerrMetric(e,i,s,n,u,d,l)}static kerrContravariant(e,i,s,n){const o=(n=Math.min(Math.abs(n),s))*n,r=e*e,a=Math.cos(i),h=Math.sin(i),l=h*h,c=r+o*a*a,u=r-2*s*e+o,d=s+Math.sqrt(Math.max(0,s*s-o));e<=d&&(e=1.001*d);const f=-(Math.pow(r+o,2)-o*u*l)/(c*u),p=-2*s*n*e/(c*u);return new t([[f,0,0,p],[0,u/c,0,0],[0,0,1/c,0],[p,0,0,(u-o*l)/(c*u*l)]],{name:"Kerr (Contravariant)",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static _buildKerrMetric(e,i,s,n,o,r,a){const h=n*n,l=-2*s*n*e*a/o;return new t([[-(1-2*s*e/o),0,0,l],[0,o/r,0,0],[0,0,o,0],[l,0,0,(e*e+h+2*s*h*e*a/o)*a]],{name:"Kerr",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static kerrHorizonRadius(t,e,i=!1){const s=t*t-e*e;if(s<0)return NaN;const n=Math.sqrt(s);return i?t-n:t+n}static kerrErgosphereRadius(t,e,i){const s=Math.cos(i),n=t*t-e*e*s*s;return n<0?NaN:t+Math.sqrt(n)}static kerrISCO(t,e,i=!0){const s=e/t,n=i?1:-1,o=1+Math.cbrt(1-s*s)*(Math.cbrt(1+s)+Math.cbrt(1-s)),r=Math.sqrt(3*s*s+o*o);return t*(3+r-n*Math.sqrt((3-o)*(3+o+2*r)))}static kerrFrameDraggingOmega(e,i,s,n){const o=t.kerr(e,i,s,n),r=o.get(0,3),a=o.get(3,3);return Math.abs(a)<1e-10?0:-r/a}static kerrEffectivePotential(t,e,i,s,n){if(n<=0)return 1/0;const o=n*n;return-t/n+(s*s-e*e*(i*i-1))/(2*o)+-t*Math.pow(s-e*i,2)/(o*n)}static diagonal(e,i={}){const s=e.length,n=[];for(let t=0;t<s;t++){n[t]=[];for(let i=0;i<s;i++)n[t][i]=t===i?e[t]:0}return new t(n,i)}static identity(e=4){const i=new Array(e).fill(1);return t.diagonal(i,{name:"Identity"})}static zero(e=4){const i=[];for(let t=0;t<e;t++)i[t]=new Array(e).fill(0);return new t(i,{name:"Zero"})}get(t,e){return bt(this,f)[t][e]}set(e,i,s){const n=bt(this,f).map(t=>[...t]);return n[e][i]=s,new t(n,{name:bt(this,g),signature:bt(this,m),coordinates:bt(this,v)})}getDiagonal(){const t=[];for(let e=0;e<bt(this,p);e++)t.push(bt(this,f)[e][e]);return t}get dimension(){return bt(this,p)}get name(){return bt(this,g)}get signature(){return bt(this,m)}get coordinates(){return bt(this,v)}add(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++)i[t][s]=bt(this,f)[t][s]+e.get(t,s)}return new t(i)}subtract(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++)i[t][s]=bt(this,f)[t][s]-e.get(t,s)}return new t(i)}scale(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++)i[t][s]=bt(this,f)[t][s]*e}return new t(i)}multiply(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++){let n=0;for(let i=0;i<bt(this,p);i++)n+=bt(this,f)[t][i]*e.get(i,s);i[t][s]=n}}return new t(i)}transpose(){const e=[];for(let t=0;t<bt(this,p);t++){e[t]=[];for(let i=0;i<bt(this,p);i++)e[t][i]=bt(this,f)[i][t]}return new t(e,{name:bt(this,g)?`${bt(this,g)}ᵀ`:"",signature:bt(this,m),coordinates:bt(this,v)})}inverse(){const e=bt(this,p);if(this.isDiagonal()){const e=this.getDiagonal().map(t=>{if(Math.abs(t)<1e-15)throw new Error("Diagonal matrix is singular, cannot compute inverse");return 1/t});return t.diagonal(e,{name:bt(this,g)?`${bt(this,g)}⁻¹`:"",signature:bt(this,m),coordinates:bt(this,v)})}const i=[];for(let t=0;t<e;t++){i[t]=[];for(let s=0;s<e;s++)i[t][s]=bt(this,f)[t][s];for(let s=0;s<e;s++)i[t][e+s]=t===s?1:0}for(let t=0;t<e;t++){let s=t;for(let n=t+1;n<e;n++)Math.abs(i[n][t])>Math.abs(i[s][t])&&(s=n);if([i[t],i[s]]=[i[s],i[t]],Math.abs(i[t][t])<1e-10)throw new Error("Matrix is singular, cannot compute inverse");const n=i[t][t];for(let s=0;s<2*e;s++)i[t][s]/=n;for(let s=0;s<e;s++)if(s!==t){const n=i[s][t];for(let o=0;o<2*e;o++)i[s][o]-=n*i[t][o]}}const s=[];for(let t=0;t<e;t++){s[t]=[];for(let n=0;n<e;n++)s[t][n]=i[t][e+n]}return new t(s,{name:bt(this,g)?`${bt(this,g)}⁻¹`:"",signature:bt(this,m),coordinates:bt(this,v)})}determinant(){const t=bt(this,p);if(this.isDiagonal())return this.getDiagonal().reduce((t,e)=>t*e,1);if(2===t)return bt(this,f)[0][0]*bt(this,f)[1][1]-bt(this,f)[0][1]*bt(this,f)[1][0];if(3===t){const t=bt(this,f);return t[0][0]*(t[1][1]*t[2][2]-t[1][2]*t[2][1])-t[0][1]*(t[1][0]*t[2][2]-t[1][2]*t[2][0])+t[0][2]*(t[1][0]*t[2][1]-t[1][1]*t[2][0])}const e=bt(this,f).map(t=>[...t]);let i=1,s=0;for(let n=0;n<t;n++){let o=n;for(let i=n+1;i<t;i++)Math.abs(e[i][n])>Math.abs(e[o][n])&&(o=i);if(o!==n&&([e[n],e[o]]=[e[o],e[n]],s++),Math.abs(e[n][n])<1e-10)return 0;i*=e[n][n];for(let i=n+1;i<t;i++){e[i][n]/=e[n][n];for(let s=n+1;s<t;s++)e[i][s]-=e[i][n]*e[n][s]}}return s%2==0?i:-i}trace(){let t=0;for(let e=0;e<bt(this,p);e++)t+=bt(this,f)[e][e];return t}isDiagonal(t=1e-10){for(let e=0;e<bt(this,p);e++)for(let i=0;i<bt(this,p);i++)if(e!==i&&Math.abs(bt(this,f)[e][i])>t)return!1;return!0}isSymmetric(t=1e-10){for(let e=0;e<bt(this,p);e++)for(let i=e+1;i<bt(this,p);i++)if(Math.abs(bt(this,f)[e][i]-bt(this,f)[i][e])>t)return!1;return!0}static christoffel(e,i,s=.001){const n=e(i);if("Schwarzschild"===n.name){const e=i._rs||2;return t.schwarzschildChristoffel(i[1],e,i[2])}const o=[],r=n.inverse(),a=[];for(let t=0;t<4;t++){const n=[...i],o=[...i];n[t]+=s,o[t]-=s;const r=e(n),h=e(o);a[t]=[];for(let e=0;e<4;e++){a[t][e]=[];for(let i=0;i<4;i++)a[t][e][i]=(r.get(e,i)-h.get(e,i))/(2*s)}}for(let t=0;t<4;t++){o[t]=[];for(let e=0;e<4;e++){o[t][e]=[];for(let i=0;i<4;i++){let s=0;for(let n=0;n<4;n++){const o=r.get(t,n);Math.abs(o)<1e-15||(s+=o*(a[e][i][n]+a[i][e][n]-a[n][e][i])/2)}o[t][e][i]=s}}}return o}static schwarzschildChristoffel(t,e,i){const s=[];for(let t=0;t<4;t++){s[t]=[];for(let e=0;e<4;e++)s[t][e]=new Array(4).fill(0)}const n=1-e/t;if(Math.abs(n)<1e-10)return s;const o=e/(2*t*t),r=1/Math.tan(i),a=Math.sin(i),h=Math.cos(i);return s[0][0][1]=s[0][1][0]=o/n,s[1][0][0]=e*n/(2*t*t),s[1][1][1]=-o/n,s[1][2][2]=-(t-e),s[1][3][3]=-(t-e)*a*a,s[2][1][2]=s[2][2][1]=1/t,s[2][3][3]=-a*h,s[3][1][3]=s[3][3][1]=1/t,s[3][2][3]=s[3][3][2]=r,s}static effectivePotential(t,e,i){if(i<=0)return 1/0;const s=e*e;return-t/i+s/(2*i*i)-t*s/(i*i*i)}static iscoRadius(t){return 3*t}static photonSphereRadius(t){return 1.5*t}toArray(){const t=[];for(let e=0;e<bt(this,p);e++)for(let i=0;i<bt(this,p);i++)t.push(bt(this,f)[e][i]);return t}toMatrix(){return bt(this,f).map(t=>[...t])}toString(t=3){return(bt(this,g)?`${bt(this,g)} Tensor:\n`:"")+bt(this,f).map(e=>`[ ${e.map(e=>e.toFixed(t).padStart(10)).join(" ")} ]`).join("\n")}toLatex(t=3){return`\\begin{pmatrix}\n${bt(this,f).map(e=>e.map(e=>e.toFixed(t)).join(" & ")).join(" \\\\\n")}\n\\end{pmatrix}`}},t.Text=Wi,t.TextShape=wi,t.TileLayout=class extends Li{constructor(t,e={}){super(t,e),this.columns=e.columns??4}calculateLayout(){return this.children.length?zt(this.children,{columns:this.columns,spacing:this.spacing,padding:this.padding,centerItems:!0}):null}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:-(this._contentHeight??this.height)/2}}},t.ToggleButton=class extends us{constructor(t,e={}){const i=e.onClick;super(t,{...e,onClick:()=>{this.toggled=!this.toggled,"function"==typeof e.onToggle&&e.onToggle(this.toggled),"function"==typeof i&&i();const t=this.state;this.refreshToggleVisual(),t&&this.setState(t)}}),this.colorActiveBg=e.colorActiveBg||cs.button.active.bg,this.colorActiveStroke=e.colorActiveStroke||cs.button.active.stroke,this.colorActiveText=e.colorActiveText||cs.button.active.text,this.toggled=!!e.startToggled,this.refreshToggleVisual()}toggle(t){const e=this.state;this.toggled=t,this.refreshToggleVisual(),e&&this.setState(e)}refreshToggleVisual(){this.toggled?(this.bg.color=this.colorActiveBg,this.bg.stroke=this.colorActiveStroke,this.label.color=this.colorActiveText):(this.bg.color=this.colors.default.bg,this.bg.stroke=this.colors.default.stroke,this.label.color=this.colors.default.text)}setState(t){super.setState(t),this.toggled&&(this.bg.color=this.colorActiveBg,this.bg.stroke=this.colorActiveStroke,this.label.color=this.colorActiveText)}},t.Tooltip=class extends Ei{constructor(t,e={}){super(t,{...e,zIndex:9999}),this.font=e.font||cs.fonts.small,this.textColor=e.textColor||cs.tooltip.text,this.bgColor=e.bgColor||cs.tooltip.bg,this.borderColor=e.borderColor||cs.tooltip.border,this.padding=e.padding??8,this.offsetX=e.offsetX??15,this.offsetY=e.offsetY??15,this.maxWidth=e.maxWidth??300,this.lineHeightMultiplier=e.lineHeight??1.4,this._text="",this._lines=[],this._visible=!1,this.bg=new Je({width:100,height:30,color:this.bgColor,stroke:this.borderColor,lineWidth:1}),this.lineShapes=[],this.group=new Ve,this.group.add(this.bg),this.game.events.on("inputmove",t=>{this._visible&&this.updatePosition(t.x,t.y)})}wrapText(t){const e=this.game.ctx;e.font=this.font;const i=[],s=t.split("\n");for(const t of s){const s=t.split(" ");let n="";for(const t of s){const s=n?`${n} ${t}`:t;e.measureText(s).width>this.maxWidth&&n?(i.push(n),n=t):n=s}n?i.push(n):""===t&&i.push("")}return i}show(t,e,i){this._text=t,this._visible=!0,this._lines=this.wrapText(t),this.updateLineShapes(),this.updateSize(),void 0!==e&&void 0!==i&&this.updatePosition(e,i)}updateLineShapes(){for(const t of this.lineShapes)this.group.remove(t);this.lineShapes=this._lines.map(t=>new wi(t,{font:this.font,color:this.textColor,align:"left",baseline:"top"}));for(const t of this.lineShapes)this.group.add(t)}hide(){this._visible=!1}updatePosition(t,e){const i=this.bg.width,s=this.bg.height;let n=t+this.offsetX+i/2,o=e+this.offsetY+s/2;n+i/2>this.game.width&&(n=t-this.offsetX-i/2),o+s/2>this.game.height&&(o=e-this.offsetY-s/2),n-i/2<0&&(n=i/2+5),o-s/2<0&&(o=s/2+5),this.x=n,this.y=o}updateSize(){const t=this.game.ctx;t.font=this.font;let e=0;for(const i of this._lines){const s=t.measureText(i);e=Math.max(e,s.width)}const i=Math.min(e,this.maxWidth),s=parseInt(this.font)*this.lineHeightMultiplier,n=s*this._lines.length;this.bg.width=i+2*this.padding,this.bg.height=n+2*this.padding;const o=-this.bg.width/2;for(let t=0;t<this.lineShapes.length;t++){const e=this.lineShapes[t],i=(e._width||0)/2,n=(e._height||s)/2;e.x=o+this.padding+i,e.y=-this.bg.height/2+this.padding+t*s+n}}draw(){this._visible&&this.group.render()}},t.Touch=zi,t.Traceable=He,t.Transform=Ne,t.Transformable=qe,t.Triangle=si,t.Tween=Ui,t.Tweenetik=as,t.UI_THEME=cs,t.Updaters=ps,t.VerticalLayout=class extends Li{calculateLayout(){return At(this.children,{spacing:this.spacing,padding:this.padding,align:this.align,centerItems:!0})}getLayoutOffset(){return{offsetX:0,offsetY:-(this._contentHeight??this.height)/2}}},t.WebGLCliffordRenderer=qs,t.WebGLDeJongRenderer=Us,t.WebGLLineRenderer=class{constructor(t=1e4,e={}){if(this.maxSegments=t,this.width=e.width||800,this.height=e.height||600,this.blendMode=e.blendMode||"additive",this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!0,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for line rendering"),void(this.available=!1);this.available=!0,this._positions=new Float32Array(4*t),this._colors=new Float32Array(8*t),this._initGL(),this._createBuffers(),this._compileShaders(),this._setupBlending()}isAvailable(){return this.available}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}_createBuffers(){const t=this.gl;this.positionBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this._positions,t.DYNAMIC_DRAW),this.colorBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.colorBuffer),t.bufferData(t.ARRAY_BUFFER,this._colors,t.DYNAMIC_DRAW)}_compileShaders(){const t=this.gl,e=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(e,"\nprecision highp float;\n\nattribute vec2 aPosition; // Screen position (pixels)\nattribute vec4 aColor; // RGBA color (0-1 range, premultiplied)\n\nvarying vec4 vColor;\n\nuniform vec2 uResolution; // Canvas dimensions\n\nvoid main() {\n // Convert from pixel coords to clip space (-1 to 1)\n vec2 clipPos = (aPosition / uResolution) * 2.0 - 1.0;\n clipPos.y = -clipPos.y; // Flip Y (canvas Y is down, GL Y is up)\n\n gl_Position = vec4(clipPos, 0.0, 1.0);\n vColor = aColor;\n}\n"),t.compileShader(e),!t.getShaderParameter(e,t.COMPILE_STATUS))return console.error("Line vertex shader error:",t.getShaderInfoLog(e)),void(this.available=!1);const i=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(i,"\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n gl_FragColor = vColor;\n}\n"),t.compileShader(i),t.getShaderParameter(i,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,e),t.attachShader(this.program,i),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.aColor=t.getAttribLocation(this.program,"aColor"),this.uResolution=t.getUniformLocation(this.program,"uResolution"),t.uniform2f(this.uResolution,this.width,this.height),t.deleteShader(e),void t.deleteShader(i)):(console.error("Line program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("Line fragment shader error:",t.getShaderInfoLog(i)),void(this.available=!1))}resize(t,e){if(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available){const i=this.gl;i.viewport(0,0,t,e),i.useProgram(this.program),i.uniform2f(this.uResolution,t,e)}}updateLines(t){if(!this.available)return 0;const e=Math.min(t.length,this.maxSegments),i=this.gl;for(let i=0;i<e;i++){const e=t[i],s=4*i,n=8*i;if(this._positions[s]=e.x1,this._positions[s+1]=e.y1,this._positions[s+2]=e.x2,this._positions[s+3]=e.y2,void 0!==e.r1){const t=void 0!==e.a1?e.a1:1,i=void 0!==e.a2?e.a2:1;this._colors[n]=e.r1/255*t,this._colors[n+1]=e.g1/255*t,this._colors[n+2]=e.b1/255*t,this._colors[n+3]=t,this._colors[n+4]=e.r2/255*i,this._colors[n+5]=e.g2/255*i,this._colors[n+6]=e.b2/255*i,this._colors[n+7]=i}else{const t=void 0!==e.a?e.a:1,i=e.r/255*t,s=e.g/255*t,o=e.b/255*t;this._colors[n]=i,this._colors[n+1]=s,this._colors[n+2]=o,this._colors[n+3]=t,this._colors[n+4]=i,this._colors[n+5]=s,this._colors[n+6]=o,this._colors[n+7]=t}}return i.bindBuffer(i.ARRAY_BUFFER,this.positionBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._positions.subarray(0,4*e)),i.bindBuffer(i.ARRAY_BUFFER,this.colorBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._colors.subarray(0,8*e)),e}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t){if(!this.available||0===t)return;const e=this.gl;e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorBuffer),e.enableVertexAttribArray(this.aColor),e.vertexAttribPointer(this.aColor,4,e.FLOAT,!1,0,0),e.drawArrays(e.LINES,0,2*t)}compositeOnto(t,e=0,i=0){this.available&&t.drawImage(this.canvas,e,i)}getCanvas(){return this.canvas}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),t.deleteBuffer(this.positionBuffer),t.deleteBuffer(this.colorBuffer),this._positions=null,this._colors=null}},t.WebGLParticleRenderer=bs,t.WebGLRenderer=oi,t.WrappedText=class extends Ze{constructor(t,e,i,s,n=20,o={}){super(t,e,o),this.text=i,this.maxWidth=s,this.lineHeight=n,this.centered=o.centered||!1,this.color=o.color||"#000000",this.font=o.font||null,this.align=o.align||"left",this.baseline=o.baseline||"top",this.outlineColor=o.outlineColor||null,this.outlineWidth=o.outlineWidth||1,this.calculateDimensions()}calculateDimensions(){if(!Le.ctx)return console.warn("Painter context not initialized. Cannot calculate text dimensions."),this.width=this.maxWidth,this.height=this.lineHeight,void(this.lines=[this.text]);const t=Le.text.font(),e=Le.text.textAlign(),i=Le.text.textBaseline();this.font&&Le.text.setFont(this.font),Le.text.setTextAlign("left"),Le.text.setTextBaseline("top");const s=this.text.split(" ");let n="",o="";this.lines=[],this.width=0;for(let t=0;t<s.length;t++)o=n+s[t]+" ",Le.text.measureText(o).width>this.maxWidth&&t>0?(this.lines.push(n),this.width=Math.max(this.width,Le.text.measureText(n).width),n=s[t]+" "):n=o;this.lines.push(n),this.width=Math.max(this.width,Le.text.measureText(n).width),this.height=this.lines.length*this.lineHeight,Le.text.setFont(t),Le.text.setTextAlign(e),Le.text.setTextBaseline(i)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Le.ctx)return void console.warn("Painter context not initialized. Cannot draw text.");let t=0,e=0;this.centered&&(t=-this.width/2,e=-this.height/2),this.font&&Le.text.setFont(this.font),Le.text.setTextAlign(this.align),Le.text.setTextBaseline(this.baseline);let i=t;"center"===this.align?i=0:"right"===this.align&&(i=t+this.width);for(let t=0;t<this.lines.length;t++){const s=e+t*this.lineHeight;this.outlineColor?Le.outlinedText(this.lines[t],i,s,this.color,this.outlineColor,this.outlineWidth,this.font):Le.text.fillText(this.lines[t],i,s,this.color,this.font)}}getBounds(){return this.centered?{x:this.x,y:this.y,width:this.width,height:this.height}:{x:this.x+this.width/2,y:this.y+this.height/2,width:this.width,height:this.height}}},t.ZOrderedCollection=Ct,t.applyAnchor=Ii,t.applyDraggable=function(t,e={}){const i=t.game;return t.dragging=!1,t.dragOffset={x:0,y:0},t._dragInputMoveHandler&&i.events.off("inputmove",t._dragInputMoveHandler),t._dragInputUpHandler&&i.events.off("inputup",t._dragInputUpHandler),t.interactive=!0,t._dragInputDownHandler=i=>{t.dragging=!0,t.dragOffset.x=t.x-i.x,t.dragOffset.y=t.y-i.y,e.onDragStart&&e.onDragStart()},t._dragInputMoveHandler=e=>{t.dragging&&(t.x=e.x+t.dragOffset.x,t.y=e.y+t.dragOffset.y)},t._dragInputUpHandler=i=>{t.dragging&&(t.dragging=!1,e.onDragEnd&&e.onDragEnd())},t.on("inputdown",t._dragInputDownHandler),i.events.on("inputmove",t._dragInputMoveHandler),i.events.on("inputup",t._dragInputUpHandler),()=>{t.off("inputdown",t._dragInputDownHandler),i.events.off("inputmove",t._dragInputMoveHandler),i.events.off("inputup",t._dragInputUpHandler),delete t._dragInputDownHandler,delete t._dragInputMoveHandler,delete t._dragInputUpHandler,delete t.dragging,delete t.dragOffset}},t.applyGravitationalLensing=function(t,e,i,s,n,o=5){const r=Math.sqrt(t*t+e*e);if(r<=o||r>=i)return{x:t,y:e,displacement:0};const a=ne(r,i,s,n,o),h=(r+a)/r;return{x:t*h,y:e*h,displacement:a}},t.applyLayout=Pt,t.applyParticleHeatTransfer=function(t,e={}){const{maxDistance:i=50,rate:s=.01,falloff:n=1,temperatureKey:o="temperature",filter:r=null,useSizeAsRadius:a=!0}=e,h=t.length,l=i*i;for(let e=0;e<h;e++){const a=t[e];if(!r||r(a)){void 0===a.custom[o]&&(a.custom[o]=.5);for(let c=e+1;c<h;c++){const e=t[c];if(r&&!r(e))continue;void 0===e.custom[o]&&(e.custom[o]=.5);const h=a.x-e.x,u=a.y-e.y,d=h*h+u*u;if(d>=l||d<1e-4)continue;const f=Math.sqrt(d),p=he(a.custom[o],e.custom[o],f,i,s,n);a.custom[o]+=p,e.custom[o]-=p,a.custom[o]=Math.max(0,Math.min(1,a.custom[o])),e.custom[o]=Math.max(0,Math.min(1,e.custom[o]))}}}},t.bezierV1=rs,t.blendForces=xe,t.bounceV1=Gi,t.cartesianToPolar=function(t,e){return{r:Math.sqrt(t*t+e*e),phi:Math.atan2(e,t)}},t.cartesianToSpherical=function(t,e,i){const s=Math.sqrt(t*t+e*e+i*i);return{r:s,theta:s>0?Math.acos(i/s):0,phi:Math.atan2(e,t)}},t.computeDensities=me,t.computeFluidForces=ye,t.computeGasForces=_e,t.computePressures=ve,t.computeThermalBuoyancy=function(t,e={}){var i;const s=pe(e),n=new Array(t.length),o=s.gas.neutralTemperature,r=s.gas.buoyancy;for(let e=0;e<t.length;e++){const a=t[e],h=((a.temperature??(null==(i=a.custom)?void 0:i.temperature)??s.gas.neutralTemperature)-o)*r;n[e]={x:0,y:-h}}return n},t.createTrailPoint=function(t,e,i={}){return{x:Math.cos(e)*t,z:Math.sin(e)*t,r:t,...i}},t.deBroglieWavelength=function(t){return 2*Math.PI/t},t.decayingOrbitalRadius=function(t,e,i){return t*Math.exp(-e*i)},t.flammEmbedding=se,t.flammEmbeddingHeight=function(t,e,i,s,n){const o=se(Math.max(t,e+.01),e,i),r=se(s,e,i);return(r-o)*n/r},t.floatV1=Ni,t.followPath=qi,t.gaussianEnvelope=function(t,e,i,s=1){const n=t-e;return s*Math.exp(-n*n/(4*i*i))},t.gaussianWavePacket=function(t,e,{amplitude:i,sigma:s,k:n,omega:o,velocity:r}){const a=t-r*e,h=i*Math.exp(-a*a/(4*s*s)),l=n*t-o*e;return{psi:Et.fromPolar(h,l),envelope:h}},t.gcanvas=Rs,t.generatePenroseTilingPixels=Yt,t.get2DAttractors=function(){return Object.fromEntries(Object.entries(ie).filter(([,t])=>t.dimension===ee.TWO_D))},t.get3DAttractors=function(){return Object.fromEntries(Object.entries(ie).filter(([,t])=>t.dimension===ee.THREE_D))},t.getAttractor=function(t){return ie[t]||null},t.getAttractorNames=function(){return Object.keys(ie)},t.getDefaultFluidConfig=function(){return pe()},t.getTerminalTrajectory=function(t,e,i,s,n=null){const o=n?n(s):s;return{x:t*(1-o),y:e*(1-o),z:i*(1-o)}},t.gravitationalLensing=ne,t.gridLayout=Dt,t.groupVelocity=function(t,e,i=.01){return e/t},t.heatTransfer=function(t,e,i,s,n){return i>=s?0:(e-t)*n},t.heatTransferFalloff=he,t.hopV1=Qi,t.horizontalLayout=Rt,t.integrateEuler=function(t,e,i,s={}){const n=pe(s),o=new Array(t.length);for(let s=0;s<t.length;s++){const r=t[s],a=e[s],h=be(r,n),l=a.x/h+n.external.gravity.x,c=a.y/h+n.external.gravity.y,u=r.vx+l*i,d=r.vy+c*i;o[s]={x:r.x+u*i,y:r.y+d*i,vx:u,vy:d}}return o},t.keplerianOmega=function(t,e,i=1,s=5){return t<=0?0:i*Math.sqrt(e)/Math.pow(t/s,1.5)},t.kerrPrecessionRate=function(t,e,i,s=1){const n=2*e;return t<=n?0:s*(n/t)*(1+i/e)},t.orbitV1=Zi,t.orbitalRadius=function(t,e,i){return e>=1?t:t*(1-e*e)/(1+e*Math.cos(i))},t.orbitalRadiusSimple=function(t,e,i,s=2){return t+e*Math.sin(2*i)*s},t.oscillateV1=Vi,t.parabolicV1=$i,t.patrolV1=ji,t.pendulumV1=Ki,t.planeWavePhase=function(t,e,i,s){return i*t-s*e},t.polarToCartesian=function(t,e){return{x:t*Math.cos(e),z:t*Math.sin(e)}},t.probabilityDensity=function(t){return t.real*t.real+t.imag*t.imag},t.pulseV1=Ji,t.schwarzschildPrecessionRate=function(t,e,i=1){return t<=e?0:i*(e/t)},t.shakeV1=ts,t.sketch=function(t=800,e=600,i="black"){const s=[];let n=null,o=null,r=null;const a={circle:(t,e,i,n="white")=>(s.push({type:"circle",x:t,y:e,radius:i,fill:n}),a),rect:(t,e,i,n,o="white")=>(s.push({type:"rect",x:t,y:e,width:i,height:n,fill:o}),a),square:(t,e,i,n="white")=>(s.push({type:"rect",x:t,y:e,width:i,height:i,fill:n}),a),star:(t,e,i,n,o="white")=>(s.push({type:"star",x:t,y:e,points:i,radius:n,fill:o}),a),triangle:(t,e,i,n="white")=>(s.push({type:"triangle",x:t,y:e,size:i,fill:n}),a),hexagon:(t,e,i,n="white")=>(s.push({type:"hexagon",x:t,y:e,radius:i,fill:n}),a),line:(t,e,i,n,o="white",r=1)=>(s.push({type:"line",x:t,y:e,x2:i,y2:n,stroke:o,lineWidth:r}),a),ring:(t,e,i,n,o="white")=>(s.push({type:"ring",x:t,y:e,innerRadius:i,outerRadius:n,fill:o}),a),text:(t,e,i,n={})=>(s.push({type:"text",content:t,x:e,y:i,...n}),a),grid:(t,e,i,s)=>{for(let n=0;n<t;n++)for(let t=0;t<e;t++)s(a,n*i+i/2,t*i+i/2,n,t);return a},repeat:(t,e)=>{for(let i=0;i<t;i++)e(a,i,t);return a},radial:(t,e,i,s,n)=>{for(let o=0;o<s;o++){const r=o/s*Math.PI*2,h=t+Math.cos(r)*i,l=e+Math.sin(r)*i;n(a,h,l,r,o)}return a},setup:t=>(o=t,a),update:t=>(n=t,a),start:()=>{const h=Rs({width:t,height:e,bg:i});null==o||o(a);const l=[];let c=h.scene("default");if(s.forEach((t,e)=>{const i=c.go({x:t.x??0,y:t.y??0,name:`shape_${e}`});switch(t.type){case"circle":i.circle({radius:t.radius,fill:t.fill});break;case"rect":i.rect({width:t.width,height:t.height,fill:t.fill});break;case"star":i.star({points:t.points,radius:t.radius,fill:t.fill});break;case"triangle":i.triangle({size:t.size,fill:t.fill});break;case"hexagon":i.hexagon({radius:t.radius,fill:t.fill});break;case"line":i.line({x2:t.x2-t.x,y2:t.y2-t.y,stroke:t.stroke,lineWidth:t.lineWidth});break;case"ring":i.ring({innerRadius:t.innerRadius,outerRadius:t.outerRadius,fill:t.fill});break;case"text":i.text(t.content,{fill:t.fill??"white",font:t.font??"16px monospace"})}l.push(i.goInstance),c=i.end()}),n){let i=0,s=0;h.on("update",(o,r)=>{var a,h;i++,s+=o,n(o,{shapes:l,time:s,frame:i,width:t,height:e,mouse:{x:(null==(a=r.game.mouse)?void 0:a.x)??0,y:(null==(h=r.game.mouse)?void 0:h.y)??0},refs:r.refs,game:r.game})})}return r=h,h.start()},get width(){return t},get height(){return e},get game(){return r}};return a},t.sphericalToCartesian=function(t,e,i){const s=Math.sin(e);return{x:t*s*Math.cos(i),y:t*s*Math.sin(i),z:t*Math.cos(e)}},t.spiralV1=es,t.springV1=is,t.swingV1=ss,t.thermalBuoyancy=function(t,e,i){return(t-e)*i},t.thermalGravity=function(t,e,i){return i*(t/e)},t.tileLayout=zt,t.updateTrail=function(t,e,i=80){return t.unshift(e),t.length>i&&t.pop(),t},t.verticalLayout=At,t.waypointV1=ns,t.zoneTemperature=ae,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});