@guinetik/gcanvas 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/dist/gcanvas.es.js +25656 -0
  2. package/dist/gcanvas.es.min.js +1 -0
  3. package/dist/gcanvas.umd.js +1 -0
  4. package/dist/gcanvas.umd.min.js +1 -0
  5. package/package.json +23 -6
  6. package/src/game/objects/index.js +1 -0
  7. package/src/game/objects/spritesheet.js +260 -0
  8. package/src/game/ui/theme.js +6 -0
  9. package/src/io/keys.js +9 -1
  10. package/src/math/boolean.js +481 -0
  11. package/src/math/index.js +1 -0
  12. package/.github/workflows/release.yaml +0 -70
  13. package/.jshintrc +0 -4
  14. package/.vscode/settings.json +0 -22
  15. package/CLAUDE.md +0 -310
  16. package/blackhole.jpg +0 -0
  17. package/demo.png +0 -0
  18. package/demos/CNAME +0 -1
  19. package/demos/animations.html +0 -31
  20. package/demos/basic.html +0 -38
  21. package/demos/baskara.html +0 -31
  22. package/demos/bezier.html +0 -35
  23. package/demos/beziersignature.html +0 -29
  24. package/demos/blackhole.html +0 -28
  25. package/demos/blob.html +0 -35
  26. package/demos/coordinates.html +0 -698
  27. package/demos/cube3d.html +0 -23
  28. package/demos/demos.css +0 -303
  29. package/demos/dino.html +0 -42
  30. package/demos/easing.html +0 -28
  31. package/demos/events.html +0 -195
  32. package/demos/fluent.html +0 -647
  33. package/demos/fluid-simple.html +0 -22
  34. package/demos/fluid.html +0 -37
  35. package/demos/fractals.html +0 -36
  36. package/demos/gameobjects.html +0 -626
  37. package/demos/genart.html +0 -26
  38. package/demos/gendream.html +0 -26
  39. package/demos/group.html +0 -36
  40. package/demos/home.html +0 -587
  41. package/demos/index.html +0 -376
  42. package/demos/isometric.html +0 -34
  43. package/demos/js/animations.js +0 -452
  44. package/demos/js/basic.js +0 -204
  45. package/demos/js/baskara.js +0 -751
  46. package/demos/js/bezier.js +0 -692
  47. package/demos/js/beziersignature.js +0 -241
  48. package/demos/js/blackhole/accretiondisk.obj.js +0 -379
  49. package/demos/js/blackhole/blackhole.obj.js +0 -318
  50. package/demos/js/blackhole/index.js +0 -409
  51. package/demos/js/blackhole/particle.js +0 -56
  52. package/demos/js/blackhole/starfield.obj.js +0 -218
  53. package/demos/js/blob.js +0 -2276
  54. package/demos/js/coordinates.js +0 -840
  55. package/demos/js/cube3d.js +0 -789
  56. package/demos/js/dino.js +0 -1420
  57. package/demos/js/easing.js +0 -477
  58. package/demos/js/fluent.js +0 -183
  59. package/demos/js/fluid-simple.js +0 -253
  60. package/demos/js/fluid.js +0 -527
  61. package/demos/js/fractals.js +0 -931
  62. package/demos/js/fractalworker.js +0 -93
  63. package/demos/js/gameobjects.js +0 -176
  64. package/demos/js/genart.js +0 -268
  65. package/demos/js/gendream.js +0 -209
  66. package/demos/js/group.js +0 -140
  67. package/demos/js/info-toggle.js +0 -25
  68. package/demos/js/isometric.js +0 -863
  69. package/demos/js/kerr.js +0 -1556
  70. package/demos/js/lavalamp.js +0 -590
  71. package/demos/js/layout.js +0 -354
  72. package/demos/js/mondrian.js +0 -285
  73. package/demos/js/opacity.js +0 -275
  74. package/demos/js/painter.js +0 -484
  75. package/demos/js/particles-showcase.js +0 -514
  76. package/demos/js/particles.js +0 -299
  77. package/demos/js/patterns.js +0 -397
  78. package/demos/js/penrose/artifact.js +0 -69
  79. package/demos/js/penrose/blackhole.js +0 -121
  80. package/demos/js/penrose/constants.js +0 -73
  81. package/demos/js/penrose/game.js +0 -943
  82. package/demos/js/penrose/lore.js +0 -278
  83. package/demos/js/penrose/penrosescene.js +0 -892
  84. package/demos/js/penrose/ship.js +0 -216
  85. package/demos/js/penrose/sounds.js +0 -211
  86. package/demos/js/penrose/voidparticle.js +0 -55
  87. package/demos/js/penrose/voidscene.js +0 -258
  88. package/demos/js/penrose/voidship.js +0 -144
  89. package/demos/js/penrose/wormhole.js +0 -46
  90. package/demos/js/pipeline.js +0 -555
  91. package/demos/js/plane3d.js +0 -256
  92. package/demos/js/platformer.js +0 -1579
  93. package/demos/js/scene.js +0 -304
  94. package/demos/js/scenes.js +0 -320
  95. package/demos/js/schrodinger.js +0 -410
  96. package/demos/js/schwarzschild.js +0 -1023
  97. package/demos/js/shapes.js +0 -628
  98. package/demos/js/space/alien.js +0 -171
  99. package/demos/js/space/boom.js +0 -98
  100. package/demos/js/space/boss.js +0 -353
  101. package/demos/js/space/buff.js +0 -73
  102. package/demos/js/space/bullet.js +0 -102
  103. package/demos/js/space/constants.js +0 -85
  104. package/demos/js/space/game.js +0 -1884
  105. package/demos/js/space/hud.js +0 -112
  106. package/demos/js/space/laserbeam.js +0 -179
  107. package/demos/js/space/lightning.js +0 -277
  108. package/demos/js/space/minion.js +0 -192
  109. package/demos/js/space/missile.js +0 -212
  110. package/demos/js/space/player.js +0 -430
  111. package/demos/js/space/powerup.js +0 -90
  112. package/demos/js/space/starfield.js +0 -58
  113. package/demos/js/space/starpower.js +0 -90
  114. package/demos/js/spacetime.js +0 -559
  115. package/demos/js/sphere3d.js +0 -229
  116. package/demos/js/sprite.js +0 -473
  117. package/demos/js/svgtween.js +0 -204
  118. package/demos/js/tde/accretiondisk.js +0 -471
  119. package/demos/js/tde/blackhole.js +0 -219
  120. package/demos/js/tde/blackholescene.js +0 -209
  121. package/demos/js/tde/config.js +0 -59
  122. package/demos/js/tde/index.js +0 -820
  123. package/demos/js/tde/jets.js +0 -290
  124. package/demos/js/tde/lensedstarfield.js +0 -154
  125. package/demos/js/tde/tdestar.js +0 -297
  126. package/demos/js/tde/tidalstream.js +0 -372
  127. package/demos/js/tde_old/blackhole.obj.js +0 -354
  128. package/demos/js/tde_old/debris.obj.js +0 -791
  129. package/demos/js/tde_old/flare.obj.js +0 -239
  130. package/demos/js/tde_old/index.js +0 -448
  131. package/demos/js/tde_old/star.obj.js +0 -812
  132. package/demos/js/tiles.js +0 -312
  133. package/demos/js/tweendemo.js +0 -79
  134. package/demos/js/visibility.js +0 -102
  135. package/demos/kerr.html +0 -28
  136. package/demos/lavalamp.html +0 -27
  137. package/demos/layouts.html +0 -37
  138. package/demos/logo.svg +0 -4
  139. package/demos/loop.html +0 -84
  140. package/demos/mondrian.html +0 -32
  141. package/demos/og_image.png +0 -0
  142. package/demos/opacity.html +0 -36
  143. package/demos/painter.html +0 -39
  144. package/demos/particles-showcase.html +0 -28
  145. package/demos/particles.html +0 -24
  146. package/demos/patterns.html +0 -33
  147. package/demos/penrose-game.html +0 -31
  148. package/demos/pipeline.html +0 -737
  149. package/demos/plane3d.html +0 -24
  150. package/demos/platformer.html +0 -43
  151. package/demos/scene.html +0 -33
  152. package/demos/scenes.html +0 -96
  153. package/demos/schrodinger.html +0 -27
  154. package/demos/schwarzschild.html +0 -27
  155. package/demos/shapes.html +0 -16
  156. package/demos/space.html +0 -85
  157. package/demos/spacetime.html +0 -27
  158. package/demos/sphere3d.html +0 -24
  159. package/demos/sprite.html +0 -18
  160. package/demos/svgtween.html +0 -29
  161. package/demos/tde.html +0 -28
  162. package/demos/tiles.html +0 -28
  163. package/demos/transforms.html +0 -400
  164. package/demos/tween.html +0 -45
  165. package/demos/visibility.html +0 -33
  166. package/docs/README.md +0 -230
  167. package/docs/api/FluidSystem.md +0 -173
  168. package/docs/concepts/architecture-overview.md +0 -204
  169. package/docs/concepts/coordinate-system.md +0 -384
  170. package/docs/concepts/lifecycle.md +0 -255
  171. package/docs/concepts/rendering-pipeline.md +0 -279
  172. package/docs/concepts/shapes-vs-gameobjects.md +0 -187
  173. package/docs/concepts/tde-zorder.md +0 -106
  174. package/docs/concepts/two-layer-architecture.md +0 -229
  175. package/docs/fluid-dynamics.md +0 -99
  176. package/docs/getting-started/first-game.md +0 -354
  177. package/docs/getting-started/hello-world.md +0 -269
  178. package/docs/getting-started/installation.md +0 -175
  179. package/docs/modules/collision/README.md +0 -453
  180. package/docs/modules/fluent/README.md +0 -1075
  181. package/docs/modules/game/README.md +0 -303
  182. package/docs/modules/isometric-camera.md +0 -210
  183. package/docs/modules/isometric.md +0 -275
  184. package/docs/modules/painter/README.md +0 -328
  185. package/docs/modules/particle/README.md +0 -559
  186. package/docs/modules/shapes/README.md +0 -221
  187. package/docs/modules/shapes/base/euclidian.md +0 -123
  188. package/docs/modules/shapes/base/geometry2d.md +0 -204
  189. package/docs/modules/shapes/base/renderable.md +0 -215
  190. package/docs/modules/shapes/base/shape.md +0 -262
  191. package/docs/modules/shapes/base/transformable.md +0 -243
  192. package/docs/modules/shapes/hierarchy.md +0 -218
  193. package/docs/modules/state/README.md +0 -577
  194. package/docs/modules/util/README.md +0 -99
  195. package/docs/modules/util/camera3d.md +0 -412
  196. package/docs/modules/util/scene3d.md +0 -395
  197. package/index.html +0 -17
  198. package/jsdoc.json +0 -50
  199. package/scripts/build-demo.js +0 -69
  200. package/scripts/bundle4llm.js +0 -276
  201. package/scripts/clearconsole.js +0 -48
  202. package/test/math/orbital.test.js +0 -61
  203. package/test/math/tensor.test.js +0 -114
  204. package/test/particle/emitter.test.js +0 -204
  205. package/test/particle/particle-system.test.js +0 -310
  206. package/test/particle/particle.test.js +0 -116
  207. package/test/particle/updaters.test.js +0 -386
  208. package/test/setup.js +0 -120
  209. package/test/shapes/euclidian.test.js +0 -44
  210. package/test/shapes/geometry.test.js +0 -86
  211. package/test/shapes/group.test.js +0 -86
  212. package/test/shapes/rectangle.test.js +0 -64
  213. package/test/shapes/transform.test.js +0 -379
  214. package/test/util/camera3d.test.js +0 -428
  215. package/test/util/scene3d.test.js +0 -352
  216. package/vite.config.js +0 -50
  217. package/vitest.config.js +0 -13
@@ -0,0 +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,D,z,I,A,B,E,F,O,X,Y,W,L,H,G,U,q,N,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(){if(this.children.length<=1)return;if(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 l of t)a=Math.max(a,l.height??0);for(let l=0;l<t.length;l++){const e=t[l],s=e.width??0,c=e.height??0,u=o?r+s/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+=s,l<t.length-1&&(r+=i)}return{positions:h,width:r+s,height:a+2*s}}function Dt(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 l of t)a=Math.max(a,l.width??0);for(let l=0;l<t.length;l++){const e=t[l],s=e.width??0,c=e.height??0,u=o?r+c/2:r;let d;switch(n){case"center":d=(a-s)/2;break;case"end":d=a-s;break;default:d=0}h.push({x:d,y:u}),r+=c,l<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 g=0;g<t.length;g++){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 d=0;d<t.length;d++){const e=t[d],f=e.width??0,p=e.height??0,g=a[Math.floor(d/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 At{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 a=0;a<t.length;a++){const e=t[a],h=4*a;switch(i){case"futuristic":{const e=t[a]/10,i={r:0,g:5,b:10},s={r:0,g:30,b:20};if(e>.7){const t=3.33*(e-.7);r[h]=Math.floor(i.r*(1-t)+s.r*t),r[h+1]=Math.floor(i.g*(1-t)+s.g*t),r[h+2]=Math.floor(i.b*(1-t)+s.b*t)}else{const t=1.43*e;r[h]=Math.floor(i.r*t),r[h+1]=Math.floor(i.g*t),r[h+2]=Math.floor(i.b*t)}r[h+3]=255}break;case"rainbow":if(0===e)r[h]=0,r[h+1]=0,r[h+2]=0,r[h+3]=255;else{const t=(10*e+n)%360,[i,s,a]=o(t,.8,.5);r[h]=i,r[h+1]=s,r[h+2]=a,r[h+3]=255}break;case"grayscale":{const t=0===e?0:255-255*e/s;r[h]=t,r[h+1]=t,r[h+2]=t,r[h+3]=255}break;case"binary":0!==e?(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==e)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=e/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===e)r[h]=0,r[h+1]=20,r[h+2]=50;else{const t=e/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===e)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=(e+n)%3,i=e%20/20;0===t?(r[h]=Math.floor(255*(.5+.5*Math.sin(i*Math.PI*2))),r[h+1]=Math.floor(128*i),r[h+2]=Math.floor(255*i)):1===t?(r[h]=Math.floor(255*i),r[h+1]=Math.floor(255*(.5+.5*Math.sin(i*Math.PI*2))),r[h+2]=Math.floor(128*i)):(r[h]=Math.floor(128*i),r[h+1]=Math.floor(255*i),r[h+2]=Math.floor(255*(.5+.5*Math.sin(i*Math.PI*2))))}r[h+3]=255;break;case"topographic":if(0===e)r[h]=5,r[h+1]=15,r[h+2]=30;else{const t=e/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===e)r[h]=0,r[h+1]=0,r[h+2]=0;else{const t=(e+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 c=0;c<e;c++){const e=c*t,n=o+c*l;for(let o=0;o<t;o++){const t=s+o*h;let r=0,l=0,c=0,u=0,d=0;do{l=2*r*l+n,r=c-u+t,c=r*r,u=l*l,d++}while(c+u<4&&d<i);a[e+o]=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 p=0;p<e;p++){const e=p*t,o=u+p*f;for(let r=0;r<t;r++){let t=c+r*d,a=o,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+r]=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 c=0;c<e;c++){const e=c*t,n=o+c*l;for(let o=0;o<t;o++){const t=s+o*h;let r=0,l=0,c=0,u=0,d=0;do{l=-2*r*l+n,r=c-u+t,c=r*r,u=l*l,d++}while(c+u<4&&d<i);a[e+o]=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 d=0;d<e;d++){const e=d*t,r=a+d*u;for(let a=0;a<t;a++){const t=o+a*c;let h=0,u=0,d=0,f=0,p=0,g=0,m=0;do{const e=p-g+t+s*d+n,i=2*h*u+r+s*f;d=h,f=u,h=e,u=i,p=h*h,g=u*u,m++}while(p+g<4&&m<i);l[e+a]=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 m=0;m<3;m++){const t=2*Math.PI*m/3;d[m]=Math.cos(t),f[m]=Math.sin(t)}const p=c/t,g=u/e;for(let m=0;m<e;m++){const e=m*t,s=r+m*g;for(let o=0;o<t;o++){let t=n+o*p,r=s,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),s=85*c;h[e+o]=Math.floor(s+85*t)}else h[e+o]=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 g=0;g<e;++g){const e=o+g*f,i=Math.floor(e*p),n=.5*i;for(let o=0;o<t;++o){const e=s+o*d;0!==(Math.floor(e-n)&i&u)&&(a[g*t+o]=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 g=0;g<e;++g){const i=(o+g/e*(r-o))*f,h=(Math.floor(i)%f+f)%f;for(let e=0;e<t;++e){const i=(s+e/t*(n-s))*f;p((Math.floor(i)%f+f)%f,h)&&(a[g*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 p=0;p<e;p++){const d=r+(a-r)*p/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:d)*a*(1-a)}let f=0,g=0;for(;g<i;){const t="A"===s[g%h]?r:d;a=t*a*(1-a);const e=Math.abs(t*(1-2*a));if(f+=Math.log(Math.max(e,1e-10)),g++,Math.abs(f/g)>10)break}const m=f/g;l[p*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 p=0;p<l.length;p++){let t=l[p];t=Math.max(-10,Math.min(10,t));let e=(t-c)/d;f[p]=Math.floor(255*e)}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),D=x-k+2*wt(this,l),z=m-1+3*wt(this,l),I=y-1+3*wt(this,l),A=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 G=.6-R*R-P*P-D*D;G<0?a=0:(G*=G,a=G*G*Y.dot3(R,P,D));let U=.6-z*z-I*I-A*A;return U<0?c=0:(U*=U,c=U*U*W.dot3(z,I,A)),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 v=0;v<l.length;v+=4)l[v]=h[0],l[v+1]=h[1],l[v+2]=h[2],l[v+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 v=0;v<10;v++){const t=Et.fromPolar(1,(2*v-1)*Math.PI/10),e=Et.fromPolar(1,(2*v+1)*Math.PI/10);v%2==0?y.push(["thin",new Et(0),e,t]):y.push(["thin",new Et(0),t,e])}for(let v=0;v<s;v++){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[v,_,w,b]of y){Wt(l,x(_),x(w),x(b),"thin"===v?o:r,t,e)}if(a&&a[3]>0)for(const[v,_,w,b]of y){const i=x(_),s=x(w),n=x(b);Gt(l,i,s,a,t,e),Gt(l,s,n,a,t,e),Gt(l,n,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 p=e.y;p<=i.y;p++){if(p>=0&&p<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 s=Math.min(e,i);s<=Math.max(e,i);s++){const e=4*(p*h+s);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 p=s.y;p>e.y;p--)if(p>=0&&p<l){d-=c,f-=u;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 s=Math.min(e,i);s<=Math.max(e,i);s++){const e=4*(p*h+s);e>=0&&e<t.length-3&&(t[e]=n,t[e+1]=o,t[e+2]=r,t[e+3]=a)}}}function Gt(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;let Ut=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 o=t+1;o<e;o++)Math.abs(i[o][t])>Math.abs(i[s][t])&&(s=o);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 o=0;o<2*e;o++)i[t][o]/=n;for(let o=0;o<e;o++)if(o!==t){const s=i[o][t];for(let n=0;n<2*e;n++)i[o][n]-=s*i[t][n]}}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 l=0;l<4;l++){s[l]=[];for(let t=0;t<4;t++)s[l][t]=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}`}};function qt(t,e,i){return t<=e?0:Math.sqrt(8*i*(t-e))}function Nt(t,e,i,s,n=5){if(t<=n||t>=e)return 0;return Math.exp(-t*s)*i}class Zt{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-Zt.easeOutBounce(1-t)}static easeInOutBounce(t){return t<.5?.5*Zt.easeInBounce(2*t):.5*Zt.easeOutBounce(2*t-1)+.5}}function Vt(t,e,i){const s=Math.max(0,Math.min(1,(i-t)/(e-t)));return Zt.smoothstep(s)}function $t(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=Vt(s-l,s+.5*l,t),u=1-Vt(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 jt={smoothingRadius:28},Kt={restDensity:1.1,particleMass:1,pressureStiffness:1800,nearPressureStiffness:2.5,viscosity:.18,surfaceTension:0,maxForce:6e3},Jt={interactionRadius:34,pressure:12,diffusion:.08,drag:.04,buoyancy:260,neutralTemperature:.5,turbulence:16},Qt={gravity:{x:0,y:820}},te=1e-4;function ee(t={}){return{kernel:{...jt,...t.kernel||{}},fluid:{...Kt,...t.fluid||{}},gas:{...Jt,...t.gas||{}},external:{...Qt,...t.external||{}}}}const ie={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){if(0===t||t>=e)return 0;return-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){if(0===t||t>=e)return 0;return-30/(Math.PI*Math.pow(e,5))*((e-t)*(e-t))},viscosityLaplacian(t,e){if(t>=e)return 0;return 40/(Math.PI*Math.pow(e,5))*(e-t)}};function se(t,e={},i){const s=ee(e).kernel.smoothingRadius,n=s*s,o=i??ce(t,s),r=t.length,a=new Float32Array(r),h=new Float32Array(r);for(let l=0;l<r;l++)a[l]=ie.spikyPow2(0,s),h[l]=ie.spikyPow3(0,s),ue(l,t,o,n,(t,e,i,n)=>{const o=Math.sqrt(n);a[l]+=ie.spikyPow2(o,s),h[l]+=ie.spikyPow3(o,s)});return{densities:a,nearDensities:h}}function ne(t,e,i={}){const s=ee(i),n=t.length,o=new Float32Array(n),r=new Float32Array(n),{pressureStiffness:a,nearPressureStiffness:h,restDensity:l}=s.fluid;for(let c=0;c<n;c++)o[c]=(t[c]-l)*a,r[c]=e[c]*h;return{pressures:o,nearPressures:r}}function oe(t,e={}){const i=ee(e),s=i.kernel.smoothingRadius,n=s*s,o=t.length,r=ce(t,s),{densities:a,nearDensities:h}=se(t,i,r),{pressures:l,nearPressures:c}=ne(a,h,i),u=new Array(o);for(let d=0;d<o;d++)u[d]={x:0,y:0};for(let d=0;d<o;d++){const e=t[d];Math.max(a[d],te),ue(d,t,r,n,(n,o,r,f)=>{if(n<=d)return;const p=Math.sqrt(f);if(p<te||p>=s)return;const g=t[n],m=1/p,y=-o*m,x=-r*m,v=Math.max(a[n],te),_=Math.max(h[n],te),w=.5*(l[d]+l[n]),b=.5*(c[d]+c[n]),M=w*ie.spikyPow2Derivative(p,s)/v+b*ie.spikyPow3Derivative(p,s)/_,k=y*M,C=x*M;u[d].x+=k,u[d].y+=C,u[n].x-=k,u[n].y-=C;const S=ie.poly6(f,s),T=i.fluid.viscosity*S,R=(g.vx-e.vx)*T,P=(g.vy-e.vy)*T;u[d].x+=R,u[d].y+=P,u[n].x-=R,u[n].y-=P})}return le(u,i.fluid.maxForce),{forces:u,densities:a,pressures:l}}function re(t,e={}){var i;const s=ee(e),n=s.gas.interactionRadius,o=n*n,r=t.length,a=ce(t,n),h=new Array(r);for(let l=0;l<r;l++)h[l]={x:0,y:0};for(let l=0;l<r;l++){const e=t[l],r=he(e,s),c=e.temperature??(null==(i=e.custom)?void 0:i.temperature)??s.gas.neutralTemperature;ue(l,t,a,o,(i,o,a,u)=>{var d;if(i<=l)return;if(0===u)return;const f=Math.sqrt(u),p=1/f,g=t[i],m=he(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[l].x+=v,h[l].y+=_,h[i].x-=v,h[i].y-=_;const w=s.gas.diffusion,b=(g.vx-e.vx)*w,M=(g.vy-e.vy)*w;h[l].x+=b*m,h[l].y+=M*m,h[i].x-=b*r,h[i].y-=M*r;const k=(c-y)*s.gas.buoyancy*.5;h[l].y-=k,h[i].y+=k})}for(let l=0;l<r;l++){const e=t[l],i=s.gas.drag;h[l].x+=-e.vx*i,h[l].y+=-e.vy*i,h[l].x+=(Math.random()-.5)*s.gas.turbulence,h[l].y+=(Math.random()-.5)*s.gas.turbulence}return le(h,s.fluid.maxForce),{forces:h}}function ae(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:Zt.lerp(t[o].x,e[o].x,i),y:Zt.lerp(t[o].y,e[o].y,i)};return n}function he(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 le(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 ce(t,e){const i=e,s=new Map;for(let n=0;n<t.length;n++){const e=t[n],o=`${Math.floor(e.x/i)},${Math.floor(e.y/i)}`;let r=s.get(o);r||(r=[],s.set(o,r)),r.push(n)}return{cellSize:i,buckets:s}}function ue(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 l=-1;l<=1;l++)for(let r=-1;r<=1;r++){const c=`${a+l},${h+r}`,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 de=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(de,"ERROR",1),vt(de,"WARN",2),vt(de,"INFO",3),vt(de,"DEBUG",4),vt(de,"globalLevel",de.ERROR),vt(de,"enabledClasses",new Set),vt(de,"output",console),vt(de,"enabled",!0),vt(de,"loggerz",[]);let fe=de;class pe{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 fe.getLogger(t.name||this.constructor.name)}}const ge=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(ge,"instance");let me=ge;const ye=class t{static dropShadow(t,e,i=0,s=0){Ce.ctx.shadowColor=t,Ce.ctx.shadowBlur=e,Ce.ctx.shadowOffsetX=i,Ce.ctx.shadowOffsetY=s}static clearShadow(){Ce.ctx.shadowColor="rgba(0, 0, 0, 0)",Ce.ctx.shadowBlur=0,Ce.ctx.shadowOffsetX=0,Ce.ctx.shadowOffsetY=0}static setAlpha(t){Ce.ctx.globalAlpha=t}static setBlendMode(t){Ce.ctx.globalCompositeOperation=t}static clipRect(t,e,i,s){Ce.ctx.beginPath(),Ce.ctx.rect(t,e,i,s),Ce.ctx.clip()}static clipCircle(t,e,i){Ce.ctx.beginPath(),Ce.shapes.arc(t,e,i,0,2*Math.PI),Ce.ctx.clip()}static blurRegion(t,e,i,s,n){const o=Ce.ctx.filter;Ce.ctx.filter=`blur(${n}px)`;const r=Ce.ctx.getImageData(t,e,i,s);Ce.ctx.putImageData(r,t,e),Ce.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)),Ce.ctx.shadowColor=e,Ce.ctx.shadowBlur=t,Ce.ctx.shadowOffsetX=0,Ce.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(),Ce.ctx.shadowColor="rgba(0, 0, 0, 0)",Ce.ctx.shadowBlur=0,Ce.ctx.shadowOffsetX=0,Ce.ctx.shadowOffsetY=0,Ce.ctx.filter="none",Ce.ctx.globalAlpha=1,Ce.ctx.globalCompositeOperation="source-over"}};vt(ye,"_activeEffects",new Map),vt(ye,"_animationId",null);let xe=ye;class ve{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=Ce.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 Ce.ctx.createPattern(t,e)}static fillPattern(t,e,i,s,n){const o=Ce.ctx;o.save(),o.fillStyle=t,o.fillRect(e,i,s,n),o.restore()}static createImageData(t,e){return Ce.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 Ce.ctx.getImageData(t,e,i,s)}static putImageData(t,e,i,s=0,n=0,o=t.width,r=t.height){Ce.ctx.putImageData(t,e,i,s,n,o,r)}static mapPixels(t,e){const i=t.data;for(let s=0;s<i.length;s+=4){const t=s>>2,n=e(i[s],i[s+1],i[s+2],i[s+3],t);n&&([i[s],i[s+1],i[s+2],i[s+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=Ce.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 _e{static path(t,e,i,s=1){const n=Ce.ctx;n.beginPath();for(const o of t){const[t,...e]=o;"M"===t?n.moveTo(...e):"L"===t?n.lineTo(...e):"C"===t?n.bezierCurveTo(...e):"Q"===t?n.quadraticCurveTo(...e):"Z"===t&&n.closePath()}e&&(n.fillStyle=e,Ce.colors.fill(e)),i&&(n.strokeStyle=i,n.lineWidth=s,Ce.colors.stroke())}static line(t,e,i,s,n,o){Ce.ctx.beginPath(),Ce.ctx.moveTo(t,e),Ce.ctx.lineTo(i,s),Ce.colors.stroke(n,o)}static beginPath(){Ce.ctx.beginPath()}static closePath(){Ce.ctx.closePath()}static moveTo(t,e){Ce.ctx.moveTo(t,e)}static lineTo(t,e){Ce.ctx.lineTo(t,e)}static bezierCurveTo(t,e,i,s,n,o){Ce.ctx.bezierCurveTo(t,e,i,s,n,o)}static dashedLine(t,e,i,s,n,o,r){Ce.ctx.beginPath(),o&&(Ce.ctx.strokeStyle=o),void 0!==r&&(Ce.ctx.lineWidth=r),Ce.ctx.setLineDash(n),Ce.ctx.moveTo(t,e),Ce.ctx.lineTo(i,s),Ce.colors.stroke(),Ce.ctx.setLineDash([])}static dottedLine(t,e,i,s,n=2,o=5,r){return Ce.lines.dashedLine(t,e,i,s,[n,o],r,n)}static setLineDash(t){Ce.ctx.setLineDash(t)}static resetLineDash(){Ce.ctx.setLineDash([])}static setLineWidth(t){Ce.ctx.lineWidth=t}static quadraticCurve(t,e,i,s,n,o,r,a){Ce.ctx.beginPath(),Ce.ctx.moveTo(t,e),Ce.ctx.quadraticCurveTo(i,s,n,o),r&&(Ce.ctx.strokeStyle=r),void 0!==a&&(Ce.ctx.lineWidth=a),Ce.colors.stroke()}}class we{static pushOpacity(t){const e=this._opacityStack[this._opacityStack.length-1]*t;this._opacityStack.push(e),Ce.logger.log("NEXT OPACITY WILL BE",e),Ce.effects.setAlpha(e)}static popOpacity(){if(this._opacityStack.length>1){this._opacityStack.pop();const t=this._opacityStack[this._opacityStack.length-1];Ce.logger.log("NEXT OPACITY WILL BE",t),Ce.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(we,"_opacityStack",[1]);class be{static rect(t,e,i,s,n){const o=Ce.ctx.fillStyle;Ce.colors.fill(n),Ce.ctx.fillRect(t,e,i,s),Ce.ctx.fillStyle=o}static outlineRect(t,e,i,s,n,o=1){const r=Ce.ctx.strokeStyle,a=Ce.ctx.lineWidth;Ce.ctx.strokeStyle=n,Ce.ctx.lineWidth=o,Ce.ctx.strokeRect(t,e,i,s),Ce.ctx.strokeStyle=r,Ce.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;Ce.lines.beginPath(),Ce.lines.moveTo(t+l,e),Ce.lines.lineTo(f-c,e),this.arc(f-c,e+c,c,-Math.PI/2,0),Ce.lines.lineTo(f,p-u),this.arc(f-u,p-u,u,0,Math.PI/2),Ce.lines.lineTo(t+d,p),this.arc(t+d,p-d,d,Math.PI/2,Math.PI),Ce.lines.lineTo(t,e+l),this.arc(t+l,e+l,l,Math.PI,-Math.PI/2),Ce.lines.closePath(),o&&(Ce.fillStyle=o,Ce.colors.fill(o)),r&&Ce.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){Ce.logger.log("PainterShapes.fillCircle",t,e,i,s),Ce.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Ce.colors.fill(s)}static arc(t,e,i,s,n,o){Ce.ctx.arc(t,e,i,s,n,o)}static strokeCircle(t,e,i,s,n){Ce.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Ce.colors.stroke(s,n)}static fillEllipse(t,e,i,s,n=0,o){Ce.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Ce.fillStyle=o),Ce.colors.fill(o)}static strokeEllipse(t,e,i,s,n=0,o,r){Ce.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Ce.strokeStyle=o),void 0!==r&&(Ce.lineWidth=r),Ce.colors.stroke(o,r)}static ellipse(t,e,i,s,n,o,r,a){Ce.ctx.ellipse(t,e,i,s,n,o,r,a)}static polygon(t,e,i,s){if(!(t.length<2)){Ce.lines.beginPath(),Ce.lines.moveTo(t[0].x,t[0].y);for(let e=1;e<t.length;e++)Ce.lines.lineTo(t[e].x,t[e].y);Ce.lines.closePath(),e&&Ce.colors.fill(e),i&&Ce.colors.stroke(i,s)}}}class Me{static font(){return Ce.ctx.font}static setFont(t){Ce.ctx.font=t}static setTextAlign(t){Ce.ctx.textAlign=t}static setTextBaseline(t){Ce.ctx.textBaseline=t}static fillText(t,e,i,s,n){s&&(Ce.ctx.fillStyle=s),n&&(Ce.ctx.font=n),Ce.ctx.fillText(t,e,i)}static strokeText(t,e,i,s,n,o){s&&(Ce.ctx.strokeStyle=s),void 0!==n&&(Ce.ctx.lineWidth=n),o&&(Ce.ctx.font=o),Ce.ctx.strokeText(t,e,i)}static measureTextDimensions(t,e,i="start",s="alphabetic"){e&&(Ce.ctx.font=e);const n=Ce.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&&(Ce.ctx.font=e),Ce.ctx.measureText(t).width}static outlinedText(t,e,i,s,n,o,r){r&&(Ce.ctx.font=r),Ce.ctx.strokeStyle=n,Ce.ctx.lineWidth=o,Ce.ctx.strokeText(t,e,i),Ce.ctx.fillStyle=s,Ce.ctx.fillText(t,e,i)}static wrappedText(t,e,i,s,n,o,r){o&&(Ce.ctx.fillStyle=o),r&&(Ce.ctx.font=r);const a=t.split(" ");let h="",l="",c=1;for(let u=0;u<a.length;u++){l=h+a[u]+" ";Ce.ctx.measureText(l).width>s&&u>0?(Ce.ctx.fillText(h,e,i),h=a[u]+" ",i+=n,c++):h=l}return Ce.ctx.fillText(h,e,i),c*n}static textOnPath(t,e,i,s,n=!1){if(e.length<2)return;i&&(Ce.ctx.fillStyle=i),s&&(Ce.ctx.font=s);const o=t.split(""),r=o.map(t=>Ce.ctx.measureText(t).width);n&&(o.reverse(),r.reverse(),e.reverse());let a=0;for(let c=1;c<e.length;c++){const t=e[c].x-e[c-1].x,i=e[c].y-e[c-1].y;a+=Math.sqrt(t*t+i*i)}let h=(a-r.reduce((t,e)=>t+e,0))/2;h<0&&(h=0);let l=h;for(let c=0;c<o.length;c++){const t=r[c],{x:i,y:s,angle:n}=getPositionOnPath(e,l);Ce.ctx.save(),Ce.ctx.translate(i,s),Ce.ctx.rotate(n),Ce.ctx.fillText(o[c],0,0),Ce.ctx.restore(),l+=t}}static getPositionOnPath(t,e){let i=0;for(let r=1;r<t.length;r++){const s=t[r-1],n=t[r],o=n.x-s.x,a=n.y-s.y,h=Math.sqrt(o*o+a*a);if(i+h>=e){const t=(e-i)/h;return{x:s.x+o*t,y:s.y+a*t,angle:Math.atan2(a,o)}}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 ke=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,Se),Mt(this,v,xe),Mt(this,_,ve),Mt(this,w,_e),Mt(this,b,we),Mt(this,M,be),Mt(this,k,Me),t.logger=fe.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(ke,C),bt(ke,x,null),bt(ke,v,null),bt(ke,_,null),bt(ke,w,null),bt(ke,b,null),bt(ke,M,null),bt(ke,k,null),vt(ke,"logger");let Ce=ke;class Se{static fill(t){Ce.logger.log("PainterColors.fill - before:",Ce.ctx.fillStyle,"setting to:",t),Ce.ctx.fillStyle,Ce.ctx.fillStyle=t,Ce.ctx.fill(),Ce.logger.log("PainterColors.fill - after:",Ce.ctx.fillStyle)}static strokeOptions(t){t.color&&(Ce.ctx.strokeStyle=t.color),void 0!==t.lineWidth&&(Ce.ctx.lineWidth=t.lineWidth),t.lineCap&&(Ce.ctx.lineCap=t.lineCap),t.lineJoin&&(Ce.ctx.lineJoin=t.lineJoin),t.strokeStyle&&(Ce.ctx.strokeStyle=t.strokeStyle)}static stroke(t,e){t&&(Ce.ctx.strokeStyle=t),void 0!==e&&(Ce.ctx.lineWidth=e),Ce.ctx.stroke()}static setFillColor(t){Ce.ctx.fillStyle=t}static setStrokeColor(t){Ce.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 Ce.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]=Ce.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 Ce.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=Ce.ctx.createLinearGradient(t,e,i,s);for(const r of n)o.addColorStop(r.offset,r.color);return o}static radialGradient(t,e,i,s,n,o,r){const a=Ce.ctx.createRadialGradient(t,e,i,s,n,o);for(const h of r)a.addColorStop(h.offset,h.color);return a}static verticalGradient(t,e,i,s,n){return Ce.colors.linearGradient(t,e,t,e+s,n)}static horizontalGradient(t,e,i,s,n){return Ce.colors.linearGradient(t,e,t+i,e,n)}static conicGradient(t,e,i,s){if("function"==typeof Ce.ctx.createConicGradient){const n=Ce.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 Te extends pe{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 Re extends Te{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 Pe extends Re{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),Ce.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 De extends Pe{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(Ce.save(),Ce.effects.setBlendMode(this._blendMode),this.crisp?Ce.translateTo(Math.round(this.x),Math.round(this.y)):Ce.translateTo(this.x,this.y),this.applyShadow(Ce.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),Ce.opacity.pushOpacity(this._opacity);const o=this.rotation??0,r=this.scaleX??1,a=this.scaleY??1;Ce.img.draw(this._cacheCanvas,0,0,{width:s,height:n,rotation:o,scaleX:r,scaleY:a,anchor:"center"}),Ce.opacity.popOpacity()}else Ce.opacity.pushOpacity(this._opacity),this.draw(),Ce.opacity.popOpacity();Ce.restore()}}_renderToCache(t,e){const i=this._cacheCanvas.getContext("2d");i.clearRect(0,0,t,e);const s=Ce.ctx;Ce.ctx=i,this._isCaching=!0,i.save(),i.translate(t/2,e/2),this.draw(),i.restore(),this._isCaching=!1,Ce.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 ze=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(ze,"strictMode",!1);let Ie=ze;class Ae extends De{constructor(t={}){super(t),this._rotation=t.rotation*Math.PI/180,this._scaleX=t.scaleX??1,this._scaleY=t.scaleY??1,this.transform=new Ie(this),this.logger.log("Transformable",this.x,this.y,this.width,this.height)}draw(){this.applyTransforms(),this.drawDebug()}applyTransforms(){this._isCaching||(Ce.rotate(this._rotation),Ce.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 Be extends Ae{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 Ee extends Ae{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 Ae))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&&(Ce.save(),i.render(),Ce.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 a of this.children){const t=a.x,o=a.y,r=a.width,h=a.height,l=t-r/2,c=t+r/2,u=o-h/2,d=o+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 Fe extends Be{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Ce.lines.beginPath(),Ce.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle,!1),this.stroke&&Ce.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 Oe extends Be{constructor(t,e={}){super(e),this._radius=t,this.width=2*t,this.height=2*t}draw(){super.draw(),this.color&&Ce.shapes.fillCircle(0,0,this._radius,this.color),this.stroke&&Ce.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 Xe extends Be{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=Ce.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 Ye extends Be{constructor(t={}){super(t)}draw(){super.draw(),this.drawRect()}drawRect(){const t=-this.width/2,e=-this.height/2;this.color&&Ce.shapes.rect(t,e,this.width,this.height,this.color),this.stroke&&Ce.shapes.outlineRect(t,e,this.width,this.height,this.stroke,this.lineWidth)}}class We extends Be{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?Ce.shapes.roundRect(t,e,this.width,this.height,this.radii,this.color,this.stroke,this.lineWidth):this.color?Ce.shapes.fillRoundRect(t,e,this.width,this.height,this.radii,this.color):this.stroke&&Ce.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 Le extends Ye{constructor(t,e={}){super(e),this.width=t,this.height=t}}class He extends Be{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}];Ce.shapes.polygon(i,this.color,this.stroke,this.lineWidth)}}class Ge extends Be{constructor(t=40,e={}){super(e),this.length=t}draw(){super.draw();const t=this.length/2;Ce.lines.line(-t,-t,t,t,this.stroke,this.lineWidth)}}class Ue extends Be{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}];Ce.shapes.polygon(e,this.color,this.stroke,this.lineWidth)}}class qe extends Be{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;Ce.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?Ce.lines.moveTo(o,r):Ce.lines.lineTo(o,r)}Ce.lines.closePath(),this.color&&Ce.colors.fill(this.color),this.stroke&&Ce.colors.stroke(this.stroke,this.lineWidth)}}class Ne{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 Ze="\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",Ve={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:Ze,star:`\n${Ze}\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${Ze}\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${Ze}\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${Ze}\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`},$e=class t extends Be{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 Ne(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 Ve.star;case"blackHole":return Ve.blackHole;case"rockyPlanet":return Ve.rockyPlanet;case"gasGiant":return Ve.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,Ve.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,Ve.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,m]of Object.entries(this.shaderUniforms))"string"==typeof m&&m.startsWith("#")&&u.setColorUniform(t,m);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&&Ce.shapes.fillCircle(0,0,this.radius,this.color),void(this.debug&&this.stroke&&Ce.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=Ce.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 s of this.faces){const t=e[s[0]],n=e[s[1]],o=e[s[2]];if(t.z<10-this.camera.perspective||n.z<10-this.camera.perspective||o.z<10-this.camera.perspective)continue;const r=(t.z+n.z+o.z)/3,a=(t.nx+n.nx+o.nx)/3,h=(t.ny+n.ny+o.ny)/3,l=(t.nz+n.nz+o.nz)/3;if(l>.1)continue;const c=this._calculateLighting(a,h,l);i.push({vertices:[t,n,o],avgZ:r,intensity:c})}i.sort((t,e)=>e.avgZ-t.avgZ);for(const s of i){const t=s.vertices.map(t=>({x:t.x,y:t.y}));if(this.debug)Ce.ctx.beginPath(),Ce.ctx.moveTo(t[0].x,t[0].y),Ce.ctx.lineTo(t[1].x,t[1].y),Ce.ctx.lineTo(t[2].x,t[2].y),Ce.ctx.closePath(),this.stroke&&(Ce.ctx.strokeStyle=this.stroke,Ce.ctx.lineWidth=this.lineWidth??1,Ce.ctx.stroke());else if(this.color){const e=this._applyLighting(this.color,s.intensity);Ce.ctx.beginPath(),Ce.ctx.moveTo(t[0].x,t[0].y),Ce.ctx.lineTo(t[1].x,t[1].y),Ce.ctx.lineTo(t[2].x,t[2].y),Ce.ctx.closePath(),Ce.ctx.fillStyle=e,Ce.ctx.fill()}}}calculateBounds(){const t=2*this.radius;return{x:this.x,y:this.y,width:t,height:t}}};vt($e,"_glRenderer",null),vt($e,"_glRendererSize",{width:0,height:0});let je=$e;const Ke="\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",Je={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${Ke}\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${Ke}\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${Ke}\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${Ke}\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`},Qe=class t extends Be{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 Ne(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 Je.gradient;case"grid":return Je.grid;case"checkerboard":return Je.checkerboard;case"noise":return Je.noise}}_initShader(e,i){const s=t._getGLRenderer(e,i);if(!s||!s.isAvailable())return!1;const n=`plane_${this.shaderType}`,o=Je.vertex,r=this._getFragmentShader();try{return s.useProgram(n,o,r),this._shaderInitialized=!0,!0}catch(a){return console.warn("Plane3D shader init failed:",a),!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,Je.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&&Ce.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;e[0].z,e[1].z,e[2].z,e[3].z;if(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=Ce.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=Ce.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 c of this.faces){const t=e[c[0]],i=e[c[1]],n=e[c[2]];if(this.debug)s.beginPath(),s.moveTo(t.x,t.y),s.lineTo(i.x,i.y),s.lineTo(n.x,n.y),s.closePath(),this.stroke&&(s.strokeStyle=this.stroke,s.lineWidth=this.lineWidth??1,s.stroke());else if(this.texture)this._renderTexturedTriangle(s,t,i,n);else if(this.color){const e=this._applyLighting(this.color,l);s.beginPath(),s.moveTo(t.x,t.y),s.lineTo(i.x,i.y),s.lineTo(n.x,n.y),s.closePath(),s.fillStyle=e,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(Qe,"_glRenderer",null),vt(Qe,"_glRendererSize",{width:0,height:0});let ti=Qe;class ei extends Be{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 o=n.length-1;o>=0;o--){const t=n[o];if("M"===t[0]){i=t[1],s=t[2];break}if("C"===t[0]){i=t[5],s=t[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 h of t)"M"===h[0]?(i=Math.min(i,h[1]),s=Math.min(s,h[2]),n=Math.max(n,h[1]),o=Math.max(o,h[2])):"C"===h[0]&&(i=Math.min(i,h[1],h[3],h[5]),s=Math.min(s,h[2],h[4],h[6]),n=Math.max(n,h[1],h[3],h[5]),o=Math.max(o,h[2],h[4],h[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 r of t)"M"===r[0]?(i=Math.min(i,r[1]),s=Math.min(s,r[2]),n=Math.max(n,r[1]),o=Math.max(o,r[2])):"C"===r[0]&&(i=Math.min(i,r[1],r[3],r[5]),s=Math.min(s,r[2],r[4],r[6]),n=Math.max(n,r[1],r[3],r[5]),o=Math.max(o,r[2],r[4],r[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 o=0;o<i;o++){const e=this.pathCommands[o];t.push([...e]),"M"===e[0]?(this.prevX=e[1],this.prevY=e[2],n=!0):"C"===e[0]&&(this.prevX=e[5],this.prevY=e[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();Ce.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 ii extends Be{constructor(t,e,i={}){super(i),this.outerRadius=t,this.innerRadius=e}draw(){super.draw(),Ce.lines.beginPath(),Ce.shapes.arc(0,0,this.outerRadius,0,2*Math.PI),Ce.shapes.arc(0,0,this.innerRadius,0,2*Math.PI,!0),Ce.lines.closePath(),this.color&&Ce.colors.fill(this.color),this.stroke&&Ce.colors.stroke(this.stroke,this.lineWidth)}}class si extends Be{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})}Ce.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class ni extends Be{constructor(t,e={}){super(e),this.length=t}draw(){super.draw();const t=this.width/2,e=.4*this.length,i=this.length-e;Ce.lines.beginPath(),Ce.lines.moveTo(-i/2,-t),Ce.lines.lineTo(i/2,-t),Ce.lines.lineTo(i/2,-this.width),Ce.lines.lineTo(this.length/2,0),Ce.lines.lineTo(i/2,this.width),Ce.lines.lineTo(i/2,t),Ce.lines.lineTo(-i/2,t),Ce.lines.closePath(),this.color&&Ce.colors.fill(this.color),this.stroke&&Ce.colors.stroke(this.stroke,this.lineWidth)}}class oi extends Be{constructor(t=20,e={}){super(e),this.radius=t}draw(){super.draw();const t=this.radius,e=2.5*t;Ce.lines.beginPath(),Ce.shapes.arc(0,0,t,Math.PI,0),Ce.lines.lineTo(t,0),Ce.lines.lineTo(0,e),Ce.lines.lineTo(-t,0),Ce.lines.closePath(),this.color&&Ce.colors.fill(this.color),this.stroke&&Ce.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 ri extends Be{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}});Ce.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class ai extends Be{constructor(t={}){super(t)}draw(){super.draw();const t=this.width,e=this.height,i=.3*e,s=Ce.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&&Ce.colors.fill(this.color),this.stroke&&Ce.colors.stroke(this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y+this.height/2,width:this.width,height:this.height}}}class hi extends Be{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?(Ce.lines.beginPath(),Ce.lines.moveTo(-t,-t+e),Ce.lines.lineTo(-t+e,-t),Ce.lines.lineTo(0,-e),Ce.lines.lineTo(t-e,-t),Ce.lines.lineTo(t,-t+e),Ce.lines.lineTo(e,0),Ce.lines.lineTo(t,t-e),Ce.lines.lineTo(t-e,t),Ce.lines.lineTo(0,e),Ce.lines.lineTo(-t+e,t),Ce.lines.lineTo(-t,t-e),Ce.lines.lineTo(-e,0),Ce.lines.closePath()):(Ce.lines.beginPath(),Ce.lines.moveTo(-e,-t),Ce.lines.lineTo(e,-t),Ce.lines.lineTo(e,-e),Ce.lines.lineTo(t,-e),Ce.lines.lineTo(t,e),Ce.lines.lineTo(e,e),Ce.lines.lineTo(e,t),Ce.lines.lineTo(-e,t),Ce.lines.lineTo(-e,e),Ce.lines.lineTo(-t,e),Ce.lines.lineTo(-t,-e),Ce.lines.lineTo(-e,-e),Ce.lines.closePath()),this.color&&Ce.colors.fill(this.color),this.stroke&&Ce.colors.stroke(this.stroke,this.lineWidth)}}class li extends Be{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),Ce.text.setFont(this.font),Ce.text.setTextAlign(this.align),Ce.text.setTextBaseline(this.baseline),Ce.text.fillText(this.text,0,0,this.color)}_calculateAlignmentOffsets(){if(!Ce.text)return;const t=Ce.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(Ce.text){const t=Ce.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(Ce.text){const t=Ce.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 ci extends Be{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??Ce.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){if(!t)return;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=Ce.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)||Ce.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 ui{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 di{static init(t){di.game=t,di.x=0,di.y=0,di.down=!1,t.events.on("mousedown",e=>di._onDown(e,t)),t.events.on("mouseup",e=>di._onUp(e,t)),t.events.on("mousemove",e=>di._onMove(e,t)),t.events.on("touchstart",e=>di._onTouchStart(e,t)),t.events.on("touchend",e=>di._onTouchEnd(e,t)),t.events.on("touchmove",e=>di._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){di.x=t,di.y=e}static _onDown(t,e){di.down=!0;const i=di._scaleToCanvas(e,t.offsetX,t.offsetY);di._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){di.down=!1;const i=di._scaleToCanvas(e,t.offsetX,t.offsetY);di._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=di._scaleToCanvas(e,t.offsetX,t.offsetY);di._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();di.down=!0;const n=i.clientX-s.left,o=i.clientY-s.top,r=di._scaleToCanvas(e,n,o);di._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){di.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=di._scaleToCanvas(e,n,o);di._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 fi=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(fi,"_gameMap",new Map),vt(fi,"_onMove",t=>{const e=fi._getGameForEvent(t);fi._updatePosition(t,e),e.events.emit("mousemove",t)}),vt(fi,"_onDown",t=>{const e=fi._getGameForEvent(t);fi._updatePosition(t,e),0===t.button&&(fi.leftDown=!0),1===t.button&&(fi.middleDown=!0),2===t.button&&(fi.rightDown=!0),e.events.emit("mousedown",t)}),vt(fi,"_onUp",t=>{const e=fi._getGameForEvent(t);fi._updatePosition(t,e),0===t.button&&(fi.leftDown=!1),1===t.button&&(fi.middleDown=!1),2===t.button&&(fi.rightDown=!1),e.events.emit("mouseup",t)}),vt(fi,"_onClick",t=>{const e=fi._getGameForEvent(t);fi._updatePosition(t,e),t.canvasX=fi.x,t.canvasY=fi.y,Object.defineProperty(t,"x",{value:fi.x,writable:!1}),Object.defineProperty(t,"y",{value:fi.y,writable:!1}),e.events.emit("click",t)}),vt(fi,"_onWheel",t=>{const e=fi._getGameForEvent(t);fi._updatePosition(t,e),e.events.emit("wheel",t)});let pi=fi;const gi=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(gi,"W","W"),vt(gi,"A","A"),vt(gi,"S","S"),vt(gi,"D","D"),vt(gi,"Q","Q"),vt(gi,"E","E"),vt(gi,"R","R"),vt(gi,"F","F"),vt(gi,"Z","Z"),vt(gi,"C","C"),vt(gi,"UP","UP"),vt(gi,"DOWN","DOWN"),vt(gi,"LEFT","LEFT"),vt(gi,"RIGHT","RIGHT"),vt(gi,"SPACE","SPACE"),vt(gi,"SHIFT","SHIFT"),vt(gi,"ENTER","ENTER"),vt(gi,"ESC","ESC"),vt(gi,"_codeMap",{KeyW:gi.W,KeyA:gi.A,KeyS:gi.S,KeyD:gi.D,KeyQ:gi.Q,KeyE:gi.E,KeyR:gi.R,KeyF:gi.F,KeyZ:gi.Z,KeyC:gi.C,ArrowUp:gi.UP,ArrowDown:gi.DOWN,ArrowLeft:gi.LEFT,ArrowRight:gi.RIGHT,Space:gi.SPACE,ShiftLeft:gi.SHIFT,ShiftRight:gi.SHIFT,Enter:gi.ENTER,NumpadEnter:gi.ENTER,Escape:gi.ESC}),vt(gi,"_down",new Set),vt(gi,"game",null);let mi=gi;const yi=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(yi,"_gameMap",new Map),vt(yi,"_onStart",t=>{if(t.touches.length>0){const e=yi._getGameForEvent(t);yi.active=!0,yi._updatePosition(t.touches[0],e),e.events.emit("touchstart",t)}}),vt(yi,"_onEnd",t=>{const e=yi._getGameForEvent(t);yi.active=!1,e.events.emit("touchend",t)}),vt(yi,"_onMove",t=>{if(t.touches.length>0){const e=yi._getGameForEvent(t);yi._updatePosition(t.touches[0],e),e.events.emit("touchmove",t)}});let xi=yi;function vi(t,e={}){var i;if(!(t&&t instanceof _i))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 _i extends Ae{constructor(t,e={}){super(e),this.game=t,this.parent=null,this.events=new ui,this._interactive=e.interactive??!1,this._hovered=!1,e.anchor&&vi(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 c of r){if(n-=c.x||0,o-=c.y||0,c.rotation){const t=Math.cos(-c.rotation),e=Math.sin(-c.rotation),i=n;n=i*t-o*e,o=i*e+o*t}void 0!==c.scaleX&&0!==c.scaleX&&(n/=c.scaleX),void 0!==c.scaleY&&0!==c.scaleY&&(o/=c.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 wi extends _i{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 bi extends _i{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 Ce.save(),t.render(),Ce.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 Mi extends bi{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,bi.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;Ce.save(),Ce.ctx.beginPath(),Ce.ctx.rect(-e/2,-i/2,e,i),Ce.ctx.clip(),Ce.ctx.beginPath(),Ce.ctx.translate(this._scrollOffset.x,this._scrollOffset.y),this._collection.getSortedChildren().filter(t=>t.visible).forEach(t=>{Ce.save(),t.render(),Ce.restore()}),Ce.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 ki extends wi{constructor(t,e,i={}){super(t,new li(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(){if(!Ce.ctx)return 0;return Ce.text.measureTextWidth(this.text,this.font)}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 Ci{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)=>Ci.lerp(t,e[s],i))}static tweenGradient(t,e,i){let s=t[0],n=e[0];Math.abs(n-s)>180&&(s<n?s+=360:n+=360);return[Ci.lerp(s,n,i)%360,Ci.lerp(t[1],e[1],i),Ci.lerp(t[2],e[2],i)]}}function Si(t,e,i,s,n,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=Li._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 Li.animationResult({y:y,segment:p,bounceHeight:m},l,o,u,d)}function Ti(t,e,i,s,n,o,r=!0,a=null,h={},l=null){if(i<=0)return Li.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}=Li._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 Li.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 Ri(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}=Li._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 k=0;k<d.length;k++){if(m+d[k]>=g){y=k;break}m+=d[k]}const x=(g-m)/d[y],v=p[y],_=y<p.length-1?p[y+1]:p[0],w=Ci.lerp(v[0],_[0],x),b=Ci.lerp(v[1],_[1],x),M=Math.atan2(_[1]-v[1],_[0]-v[0]);return Li.animationResult({x:w,y:b,angle:M,segmentIndex:y,segmentProgress:x,pathProgress:l},h,n,c,u)}function Pi(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}=Li._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 Li.animationResult({x:y,y:x,angle:m},d,a,p,g)}function Di(t,e,i,s,n=!0,o=null,r={},a=null){const{t:h,easedT:l,completed:c,state:u}=Li._frame(i,s,n,o,r,a),d=(e-t)/2,f=t+d+d*Math.sin(l*Math.PI*2);return Li.animationResult({value:f},h,n,c,u)}function zi(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 Li.animationResult({value:p,direction:l.direction},c,o||r&&!u,u,g)}function Ii(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 Li.animationResult({x:c,y:u,moving:!l,direction:d,distanceFromCenter:g},p,r,!1,a)}function Ai(t,e,i,s,n=!0,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=Li._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;if(r){p=t+r(((p-t)/(e*f)+1)/2)*e*f*2-e*f}return Li.animationResult({angle:p},l,n,u,d)}function Bi(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(),Li.animationResult({value:h,phase:c},l,n,u)}function Ei(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=Li._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 Li.animationResult({y:p},l,n,u,d)}function Fi(t,e,i,s,n,o,r,a,h=!1,l=null,c={},u=null){const{t:d,easedT:f,completed:p,state:g}=Li._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 Li.animationResult({x:w,y:b,intensity:m},d,h,p,g)}function Oi(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=Ci.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 Li.animationResult({x:v,y:_,radius:y,angle:x,direction:d.direction},f,h||l&&!p,p,w)}function Xi(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=Zt.easeOutElastic(c,m,y);else{const t=(c-.99)/.01;x=Zt.easeOutElastic(.99,m,y)*(1-t)+1*t}const v=Ci.lerp(l,h,x),_=Math.min(c+.01,1);let w;if(_<.99)w=Zt.easeOutElastic(_,m,y);else{const t=(_-.99)/.01;w=Zt.easeOutElastic(.99,m,y)*(1-t)+1*t}const b=(Ci.lerp(l,h,w)-v)/.01*s,M=!n&&u>=1;return M&&a.onComplete&&a.onComplete(),Li.animationResult({value:v,velocity:b,delta:"forward"===d?e-v:t-v,done:M,phase:d},u,n,M)}function Yi(t,e,i,s,n,o=!0,r=!0,a=null,h={},l=null){const{t:c,easedT:u,completed:d,state:f}=Li._frame(s,n,o,a,h,l),p=(r?Math.sin(u*Math.PI*2):Math.sin(u*Math.PI))*i;return Li.animationResult({angle:p},c,o,d,f)}function Wi(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"),Li._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 b=0;b<i.length;b++){const t=(b+1)%i.length;if(!o&&b===i.length-1)break;const e=i[t][0]-i[b][0],s=i[t][1]-i[b][1];h+=Math.abs(e)+Math.abs(s)}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),Li.animationResult({x:d,y:f,moving:!x,waiting:x,waitProgress:x?v:0,direction:p,waypoint:m,nextWaypoint:y},u,o,w,a)}class Li{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 Di(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 zi(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 Ti(t,e,i,s,n,o,r,a,h,l)}static spring(t,e,i,s,n=!1,o=!1,r={},a={}){return Xi(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 Yi(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 Ai(t,e,i,s,n,o,r,a,h)}static pulse(t,e,i,s,n=!0,o=!1,r=null,a={}){return Bi(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 Oi(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 Pi(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 Hi(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 Si(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 Fi(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 Ri(t,e,i,s,n,o,r,a)}static waypoint(t,e,i,s,n,o=!0,r={},a=null){return Wi(0,e,i,s,n,o,r,a)}static patrol(t,e,i,s,n,o,r=!0,a=null){return Ii(t,e,i,s,n,o,r,a)}static hop(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){return Ei(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 f=0;f<t.length;f++){const a=t[f],h=[...e[f]];a===this.parabolic||a===this.oscillate||a===this.pulse?(h[3]=i,h[4]=s,h[5]=n,void 0===h[6]&&(h[6]=o)):a===this.spring?(h[2]=i,h[3]=s,h[4]=n):a===this.spiral||a===this.bezier?(h[6]=i,h[7]=s,h[8]=n,void 0===h[9]&&(h[9]=o)):a===this.orbit?(h[5]=i,h[6]=s,h[7]=n,void 0===h[9]&&(h[9]=o)):a===this.bounce||a===this.shake?(h[6]=i,h[7]=s,h[8]=n,void 0===h[9]&&(h[9]=o)):a===this.followPath&&(h[2]=i,h[3]=s,h[4]=n,void 0===h[5]&&(h[5]=o)),h.push(r),h.push(u.animationStates[f]);const l=a.apply(this,h);u.animationStates[f]=l.state;d[`anim${f}`]=l}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 x=t.length-1;x>=0;x--)if(l>=h.animStartTimes[x]){c=x;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 Hi(t,e,i,s,n,o,r=!1,a=!1,h=null,l={},c=null){if(o<=0)return Li.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(),Li.animationResult({x:w,y:b,phase:d},u,r,M,c)}class Gi{constructor(t,e,i,s,n={}){this.target=t,this.toProps={...e},this.duration=i,this.easingFn=s||Zt.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 o in this.toProps)o in this.target&&(this._startProps[o]=this.target[o])}static to(t,e,i,s,n){const o=new Gi(t,e,i,s,n);return Gi._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 n in this._startProps){const t=this._startProps[n],e=this.toProps[n];this.target[n]=Ci.lerp(t,e,s)}this.onUpdate&&this.onUpdate(),i>=1&&(this._finished=!0,this.onComplete&&this.onComplete())}static updateAll(t){for(const e of Gi._active)e.update(t);Gi._active=Gi._active.filter(t=>!t._finished)}static killTarget(t){Gi._active=Gi._active.filter(e=>e.target!==t)}static killAll(){Gi._active=[]}}class Ui extends pe{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 bi?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 bi){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 bi?this._hoverScene(i,t):this._hoverObject(i,t)}}_dispatchToScene(t,e,i){var s,n;for(let o=t.children.length-1;o>=0;o--){const n=t.children[o];if(n instanceof bi){if(this._dispatchToScene(n,e,i))return!0}else if(n.interactive&&(null==(s=n._hitTest)?void 0:s.call(n,i.x,i.y)))return n.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)),Gi.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 qi{constructor(t){bt(this,T,0),bt(this,R,0),this.canvas=t,this.ctx=t.getContext("2d"),this.events=new ui,this._cursor=null,this.lastTime=0,this.dt=0,this.running=!1,this._frame=0,this.pipeline=new Ui(this),Ce.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(){pi.init(this)}initTouch(){xi.init(this)}initInput(){di.init(this)}initKeyboard(){mi.init(this)}initIO(){this.initMouse(),this.initTouch(),this.initInput(),this.initKeyboard()}initMotion(){Gi._active=[]}initLogging(){this.logger=new fe("Game"),fe.setOutput(console),fe.disableAll(),fe.disable(),fe.setLevel(fe.INFO),this.logger.groupCollapsed("Initializing Game...")}enableLogging(){fe.enable()}disableLogging(){fe.disableAll(),fe.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(){Ce.setContext(this.ctx),this.running&&this.clear(),this.pipeline.render()}clear(){Ce.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 Ni={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 Zi extends _i{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=Ni.button.default.bg,colorDefaultStroke:v=Ni.button.default.stroke,colorDefaultText:_=Ni.button.default.text,colorHoverBg:w=Ni.button.hover.bg,colorHoverStroke:b=Ni.button.hover.stroke,colorHoverText:M=Ni.button.hover.text,colorPressedBg:k=Ni.button.pressed.bg,colorPressedStroke:C=Ni.button.pressed.stroke,colorPressedText:S=Ni.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 Ye({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 li(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 Ee,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 Vi{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 $i{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 ji={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 Ki extends _i{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??[ji.velocity,ji.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 Vi}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(){Ce.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),Ce.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 s of t)this.drawParticle(e,s.p,s.x,s.y,s.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 Ji{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 Ji.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 r=0;r<o;r++){const i=t[r],a=n?.5*i.size:i.radius??10;for(let h=r+1;h<o;h++){const o=t[h],l=n?.5*o.size:o.radius??10,c=Ji.getCircleOverlap({x:i.x,y:i.y,radius:a},{x:o.x,y:o.y,radius:l});if(c){const t=s*(c.overlap/(a+l)),i=c.nx*t,n=c.ny*t;e[r].x+=i,e[r].y+=n,e[h].x-=i,e[h].y-=n}}}}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(Ji.pointRect(t,e,{x:r,y:a,width:h,height:l})||Ji.pointRect(i,s,{x:r,y:a,width:h,height:l}))return!0;const c=Ji.lineLine(t,e,i,s,r,a,r,a+l),u=Ji.lineLine(t,e,i,s,r+h,a,r+h,a+l),d=Ji.lineLine(t,e,i,s,r,a,r+h,a),f=Ji.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(Ji.lineRect(s.x1,s.y1,s.x2,s.y2,e,i))return!0;return!1}static getOverlap(t,e){if(!Ji.rectRect(t,e))return null;return{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)}}static getMTV(t,e){const i=Ji.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 Qi={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 ts extends Ki{constructor(t,e={}){var i,s,n,o;const r=ts._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:[ji.velocity,ji.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={...Qi,...t},i=e.particleSize;return e.fluid={...Qi.fluid,...t.fluid},e.gas={...Qi.gas,...t.gas},e.heat={...Qi.heat,...t.heat},e.collision={...Qi.collision,...t.collision},e.boundary={...Qi.boundary,...t.boundary},e.shake={...Qi.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 $i({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 a of this.particles)a.custom.initialized||(a.custom.initialized=!0,a.custom.mass=1,a.custom.temperature=.5,a.vx=20*(Math.random()-.5),a.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=Zt.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&&Ji.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=oe(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=re(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=oe(t,{kernel:{smoothingRadius:e.smoothingRadius},fluid:e}),n=re(t,{gas:i}),o=ae(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 u=0;u<t.length;u++){const e=t[u],i=.5*e.size,s=e.x-i-a,n=h-e.x-i,d=e.y-i-l,f=c-e.y-i;if(s<o){const t=Math.max(0,1-s/o);this._forces[u].x+=r*t*t}if(n<o){const t=Math.max(0,1-n/o);this._forces[u].x-=r*t*t}if(d<o){const t=Math.max(0,1-d/o);this._forces[u].y+=r*t*t}if(f<o){const t=Math.max(0,1-f/o);this._forces[u].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=$t(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;if(o>0){t=-(o-s)*e.buoyancy*2}else{t=(-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 r=0;r<o;r++){const e=t[r];for(let a=r+1;a<o;a++){const o=t[a],h=e.x-o.x,l=e.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[r].x+=p,this._forces[r].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=Zt.lerp(this._shake.forceX,r,1-e.damping),this._shake.forceY=Zt.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=Zt.lerp(s,.995,this.modeMix);for(let h=0;h<t.length;h++){const s=t[h],l=this._forces[h],c=s.custom.mass||1;let u,d;if(this.modeMix>.5){const t=s.custom.temperature??o.neutralTemp;u=c*Zt.lerp(1.5,.3,t),d=this.gravityEnabled?i*Zt.lerp(1.2,.6,t):0}else u=c,d=this.gravityEnabled?i:0;s.vx+=l.x/u*e,s.vy+=(l.y/u+d)*e,s.vx*=a,s.vy*=a;const f=s.vx*s.vx+s.vy*s.vy;if(f>r){const t=n/Math.sqrt(f);s.vx*=t,s.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,D=new WeakMap,z=new WeakMap,I=new WeakMap,A=new WeakMap,B=new WeakMap,E=new WeakSet,F=function(t){var e;if(wt(this,A).push(t),1===wt(this,A).length){wt(this,D)._fluentShape=t,wt(this,D).renderable=t;const i=(null==(e=wt(this,D).draw)?void 0:e.bind(wt(this,D)))||(()=>{});wt(this,D).draw=function(){i(),this._fluentShape&&this.visible&&this._fluentShape.render()};const s=wt(this,D);wt(this,D).getBounds=function(){return s._fluentShape&&s._fluentShape.getBounds?s._fluentShape.getBounds():null}}else{if(!(wt(this,D)._fluentShape instanceof Ee)){const t=wt(this,A)[0],e=new Ee;e.add(t),wt(this,D)._fluentShape=e,wt(this,D).renderable=e}wt(this,D)._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,D)._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,D)._motionTime,r=wt(this,D);switch(i){case"oscillate":{const{prop:t="y",min:e=-50,max:i=50,duration:n=2}=s,a=Li.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=Li.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=Li.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=Li.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=Li.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=Li.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=Li.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=Li.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=Li.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 es=class t{constructor(t,e,i,s){bt(this,E),bt(this,P),bt(this,D),bt(this,z),bt(this,I),bt(this,A,[]),bt(this,B,[]),Mt(this,P,t),Mt(this,D,e),Mt(this,z,i),Mt(this,I,s)}circle(t={}){const e=kt(this,E,O).call(this,t),{radius:i=30,...s}=e,n=new Oe(i,s);return kt(this,E,F).call(this,n)}rect(t={}){const e=kt(this,E,O).call(this,t),i=new Ye(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 We(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 Le(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 qe(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 Ue(i,s);return kt(this,E,F).call(this,n)}poly(t={}){const e=kt(this,E,O).call(this,t),i=new si(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 Ge(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 ri(i,s);return kt(this,E,F).call(this,n)}diamond(t={}){const e=kt(this,E,O).call(this,t),i=new He(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 ai(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 Fe(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 ii(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 ni(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 hi(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 oi(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 Xe(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 li(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 ci(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 ci(t,i);return kt(this,E,F).call(this,e)}}svg(t,e={}){const i=kt(this,E,O).call(this,e),s=new ei({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,D)._fluentMotions){wt(this,D)._fluentMotions=[],wt(this,D)._motionTime=0,wt(this,D)._baseX=wt(this,D).x,wt(this,D)._baseY=wt(this,D).y;const t=(null==(i=wt(this,D).update)?void 0:i.bind(wt(this,D)))||(()=>{}),e=this;wt(this,D).update=function(i){var s;t(i),this._motionTime+=i,kt(s=e,E,X).call(s,i)}}return wt(this,D)._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(()=>{Gi.to(wt(this,D),t,i,s,{onComplete:o})},1e3*n):Gi.to(wt(this,D),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=_i,o=e||{},r=i);const a=new n(wt(this,D).game,o);wt(this,D).addChild(a),o.name&&(wt(this,z)[o.name]=a);const h=new t(this,a,wt(this,z),wt(this,I));return r?(r(h),this):h}on(t,e){const i={go:wt(this,D),shapes:wt(this,A),refs:wt(this,z),state:wt(this,I)};return["click","mousedown","mouseup","mousemove","mouseover","mouseout","inputdown","inputup","inputmove"].includes(t)&&(wt(this,D).interactive=!0),wt(this,D).events&&wt(this,D).events.on(t,t=>e(i,t)),this}update(t){var e;const i=(null==(e=wt(this,D).update)?void 0:e.bind(wt(this,D)))||(()=>{}),s=wt(this,A),n=wt(this,z),o=wt(this,I),r=wt(this,D);return wt(this,D).update=e=>{i(e),t(e,{go:r,shapes:s,refs:n,state:o})},this}pos(t,e){return wt(this,D).x=t,wt(this,D).y=e,this}scale(t,e){return wt(this,D).scaleX=t,wt(this,D).scaleY=e??t,this}rotate(t){return wt(this,D).rotation=t*(Math.PI/180),this}opacity(t){return wt(this,D).opacity=t,wt(this,D).renderable&&(wt(this,D).renderable.opacity=t),this}zIndex(t){return wt(this,D).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,D)}get shapes(){return wt(this,A)}get refs(){return wt(this,z)}get state(){return wt(this,I)}};class is{constructor(t,e,i,s,n){bt(this,W),bt(this,L),bt(this,H),bt(this,G),bt(this,U),Mt(this,W,t),Mt(this,L,e),Mt(this,H,i),Mt(this,G,s),Mt(this,U,n)}go(t={},e){var i;const{name:s,x:n=0,y:o=0,visible:r=!0,...a}=t,h=new _i({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,G)[s]=h);const l=new es(this,h,wt(this,G),wt(this,U));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,G)}get state(){return wt(this,U)}}W=new WeakMap,L=new WeakMap,H=new WeakMap,G=new WeakMap,U=new WeakMap;class ss{constructor(t,e,i,s){bt(this,q),bt(this,N),bt(this,Z),bt(this,V),bt(this,$,null),Mt(this,q,t),Mt(this,N,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=_i,n=t||{},o=e);const{name:r,x:a=0,y:h=0,visible:l=!0,...c}=n,u=new s(wt(this,q).game,{x:a,y:h,visible:l,...c});wt(this,N).add(u),Mt(this,$,u),r&&(u.name=r,wt(this,Z)[r]=u);const d=new es(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 Ee({zIndex:e});s.name=t;const n=new _i(wt(this,q).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,N).add(n),t&&(wt(this,Z)[`${wt(this,N).name}_${t}`]=n),new is(this,n,s,wt(this,Z),wt(this,V))}onEnter(t){return wt(this,N)._onEnter=t,this}onExit(t){return wt(this,N)._onExit=t,this}scene(t,e){return wt(this,q).scene(t,e)}end(){return wt(this,q)}start(){return wt(this,q).start()}stop(){return wt(this,q).stop()}on(t,e){return wt(this,q).on(t,e)}use(t){return wt(this,q).use(t)}state(t){return wt(this,q).state(t)}get sceneInstance(){return wt(this,N)}get refs(){return wt(this,Z)}get state(){return wt(this,V)}get parent(){return wt(this,q)}}function ns(t={}){return new os(t)}q=new WeakMap,N=new WeakMap,Z=new WeakMap,V=new WeakMap,$=new WeakMap;class os{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 qi(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=bi,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 ss(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 ss(this,e,wt(this,Q),wt(this,tt))}go(t,e){return wt(this,J)||this.scene("default"),new ss(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");s.width=t,s.height=e,s.style.display="block";return(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 rs{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 as{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),rs.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(as,rt,null),bt(as,at,null);class hs{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 r=0;r<2;r++){const t=o.getChannelData(r);for(let i=0;i<n;i++)t[i]=(2*Math.random()-1)*Math.pow(1-i/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 o=0;o<s;o++){const t=2*o/s-1;n[o]=(3+i)*t*20*(Math.PI/180)/(Math.PI+i*Math.abs(t))}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(hs,ht,null),bt(hs,lt,null);class ls{static white(t,e){const i=t.sampleRate*e,s=t.createBuffer(1,i,t.sampleRate),n=s.getChannelData(0);for(let r=0;r<i;r++)n[r]=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 f=0;f<i;f++){const t=2*Math.random()-1;o=.99886*o+.0555179*t,r=.99332*r+.0750759*t,a=.969*a+.153852*t,h=.8665*h+.3104856*t,l=.55*l+.5329522*t,c=-.7616*c-.016898*t,n[f]=.11*(o+r+a+h+l+c+u+.5362*t),u=.115926*t}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 a=0;a<i;a++){const t=2*Math.random()-1;n[a]=(o+.02*t)/1.02,o=n[a],n[a]*=3.5}const r=t.createBufferSource();return r.buffer=s,r}}class cs{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 r=0;r<i;r++)for(const t of n)o.push(s*Math.pow(2,(t+12*r)/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(cs,"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(cs,"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(cs,"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 us{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(us,ct,null),bt(us,ut,null),bt(us,dt,null),bt(us,ft,null);class ds{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),as.init(wt(this,pt),wt(this,gt)),hs.init(wt(this,pt),wt(this,gt)),s&&us.init(wt(this,pt),wt(this,gt)),Mt(this,mt,!0),console.log("[Synth] Audio system initialized")}catch(n){console.error("[Synth] Failed to initialize audio:",n)}}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 as}static get fx(){return hs}static get env(){return rs}static get noise(){return ls}static get music(){return cs}static get analyzer(){return us}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)&&(us.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(ds,pt,null),bt(ds,gt,null),bt(ds,mt,!1);class fs{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 n=0;n<t.length;n++){const i=t[n],o=n===t.length-1,r=o?e.loop?t[0].name:null:t[n+1].name;s[i.name]={duration:i.duration,next:r,enter:i.enter,update:i.update,exit:i.exit,onComplete:o&&!e.loop?e.onComplete:void 0}}return new fs({initial:null==(i=t[0])?void 0:i.name,states:s,context:e.context})}}t.Arc=Fe,t.Arrow=ni,t.BezierShape=class extends Be{constructor(t=[],e={}){super(e),this.path=t}draw(){super.draw(),Ce.lines.path(this.path,this.color,this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:100,height:100}}},t.Button=Zi,t.Camera2D=At,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){if(!(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:()=>{if(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:()=>{if(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:()=>{if(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=Oe,t.Cloud=Xe,t.Collision=Ji,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 o of i){if(!this._isActive(o))continue;const t=this._getBounds(o);if(t)for(const e of s){if(o===e)continue;if(!this._isActive(e))continue;const i=this._getBounds(e);i&&(Ji.rectRect(t,i)&&n.push([o,e]))}}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 n of i){if(t===n)continue;if(!this._isActive(n))continue;const e=this._getBounds(n);if(e&&Ji.rectRect(s,e))return n}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 o of i){if(t===o)continue;if(!this._isActive(o))continue;const e=this._getBounds(o);e&&(Ji.rectRect(s,e)&&n.push(o))}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&&(Ji.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 Be{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 l=0;l<this.segments;l++){const i=l*r,n=Math.cos(i)*t,a=Math.sin(i)*t;o.push(s(n,a,-e))}const a=[];for(let l=0;l<this.segments;l++){const t=(l+1)%this.segments;a.push({points:[n,o[l],o[t]],z:(n.z+o[l].z+o[t].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 l of h){const t="bottom"===l.type?this.bottomColor:this.sideColor;Ce.shapes.polygon(l.points,t,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=hi,t.Cube=class extends Be{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});i.x/=e.points.length,i.y/=e.points.length;return{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)&&Ce.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 Be{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&&Ce.shapes.fillRect(-t,-t,this.size,this.size,this.faceColors.front))}const t=Ce.ctx;this.size;const e=0!==this.selfRotationX||0!==this.selfRotationY||0!==this.selfRotationZ,i=[];for(const[s,n]of Object.entries(this._faceConfigs)){let{x:t,y:o,z:r}=n.localPos;if(e){const e=this._applySelfRotation(t,o,r);t=e.x,o=e.y,r=e.z}const a=this.x+t,h=this.y+o,l=this.z+r;let c=0,u=0,d=0;if("front"===s?(c=0,u=0,d=-1):"back"===s?(c=0,u=0,d=1):"top"===s?(c=0,u=-1,d=0):"bottom"===s?(c=0,u=1,d=0):"left"===s?(c=-1,u=0,d=0):"right"===s&&(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(s,n,e);i.push({name:s,config:n,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 s of i)this._renderFace(t,s)}_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 r=1;r<i.length;r++)t.lineTo(i[r].x,i[r].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 i=1;i<s.length;i++)t.lineTo(s[i].x,s[i].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 o of t)i+=o.x,s+=o.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 _i{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 Be{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 l=0;l<this.segments;l++){const i=l*r,a=Math.cos(i)*t,h=Math.sin(i)*t;n.push(s(a,h,e)),o.push(s(a,h,-e))}const a=[];for(let l=0;l<this.segments;l++){const t=(l+1)%this.segments;a.push({points:[o[l],o[t],n[t],n[l]],z:(n[l].z+n[t].z+o[l].z+o[t].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 l of h){let t;switch(l.type){case"top":t=this.topColor;break;case"bottom":t=this.bottomColor;break;case"side":t=this.sideColor}Ce.shapes.polygon(l.points,t,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=me,t.Diamond=He,t.Easing=Zt,t.Euclidian=Te,t.EventEmitter=ui,t.FPSCounter=class extends ki{constructor(t,e={}){super(t,"0 FPS",{x:0,y:0,font:Ni.fonts.small,color:Ni.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=es,t.FluentGame=os,t.FluentLayer=is,t.FluentScene=ss,t.FluidSystem=ts,t.Fractals=Ft,t.Game=qi,t.GameObject=_i,t.GameObjectShapeWrapper=wi,t.Geometry2d=Re,t.GridLayout=class extends Mi{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=Ee,t.Heart=ai,t.Hexagon=ri,t.HorizontalLayout=class extends Mi{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 wi{constructor(t,e,i={}){super(t,e instanceof ci?e:new ci(e,i),i)}reset(){this.shape.reset()}},t.ImageShape=ci,t.Input=di,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 bi{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;Ce.save(),Ce.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)Ce.save(),e.child.render(),Ce.restore();Ce.restore()}},t.Kernels=ie,t.Keys=mi,t.LayoutScene=Mi,t.Line=Ge,t.Loggable=pe,t.Logger=fe,t.Motion=Li,t.Mouse=pi,t.Noise=Xt,t.OutlinedText=class extends Be{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(!Ce.ctx)return console.warn("Painter context not initialized. Cannot calculate text dimensions."),this.width=0,void(this.height=0);const t=Ce.text.font();this.font&&Ce.text.setFont(this.font);const e=Ce.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,Ce.text.setFont(t)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Ce.ctx)return void console.warn("Painter context not initialized. Cannot draw text.");let t=0;this.font&&Ce.text.setFont(this.font),Ce.text.setTextAlign(this.align),Ce.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)),Ce.outlinedText(this.text,0,t,this.color,this.stroke,this.lineWidth,this.font)}getBounds(){if(!Ce.ctx)return super.getBounds();const t=Ce.text.font();Ce.text.setFont(this.font);const e=Ce.text.measureText(this.text),i=e.width,s=e.actualBoundingBoxAscent+e.actualBoundingBoxDescent||parseInt(this.font)||20;return Ce.text.setFont(t),this.width=i,this.height=s,{x:this.x,y:this.y,width:i,height:s}}},t.Painter=Ce,t.PainterColors=Se,t.PainterEffects=xe,t.PainterImages=ve,t.PainterLines=_e,t.PainterOpacity=we,t.PainterShapes=be,t.PainterText=Me,t.Particle=Vi,t.ParticleEmitter=$i,t.ParticleSystem=Ki,t.PatternRectangle=class extends Be{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=Ce.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?Ce.img.fillPattern(this.pattern,t,e,this.width,this.height):this.strokeColor&&Ce.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 r=0;r<o.length;r+=4)o[r]=s[0],o[r+1]=s[1],o[r+2]=s[2],o[r+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 a=0;a<e;a++){const e=a%s===0;for(let i=0;i<t;i++){const h=4*(a*t+i),l=i%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 a=0;a<e;a++){const e=Math.floor(a/s);for(let i=0;i<t;i++){const h=(Math.floor(i/s)+e)%2==0?n:o,l=4*(a*t+i);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 h=0;h<e;h++)for(let e=0;e<t;e++){const i=(e+h)%s<n,l=4*(h*t+e);a.set(i?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 y=0;y<a.length;y+=4)a[y]=r[0],a[y+1]=r[1],a[y+2]=r[2],a[y+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 y=g;y<=m;y++)for(let e=f;e<=p;e++){const i=c(e,y,h,l,s),n=u>0&&c(e,y,h,l,u);if(i&&!n){const i=4*(y*t+e);a[i]=o[0],a[i+1]=o[1],a[i+2]=o[2],a[i+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 f=0;f<a.length;f+=4)a[f]=o[0],a[f+1]=o[1],a[f+2]=o[2],a[f+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 f=-1;f<e/u+1;f++)for(let i=-1;i<t/c+1;i++){const s=i*c+c/2,n=f*u+u/2;if(!((f+i)%2==0))continue;const o=Math.max(0,Math.floor(s-h/2)),p=Math.min(t-1,Math.ceil(s+h/2)),g=Math.max(0,Math.floor(n-l/2)),m=Math.min(e-1,Math.ceil(n+l/2));for(let e=g;e<=m;e++)for(let i=o;i<=p;i++)if(d(i,e,s,n)){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 u=0;u<h.length;u+=4)h[u]=r[0],h[u+1]=r[1],h[u+2]=r[2],h[u+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 u=0;u<Math.ceil(e/l)+1;u++)for(let i=0;i<Math.ceil(t/l)+1;i++){const o=i*l+s,r=u*l+s;if(o<-s||o>t+s||r<-s||r>e+s)continue;const d=Math.max(0,Math.floor(o-s)),f=Math.min(t-1,Math.ceil(o+s)),p=Math.max(0,Math.floor(r-s)),g=Math.min(e-1,Math.ceil(r+s)),m=s-n;for(let e=p;e<=g;e++)for(let i=d;i<=f;i++){const n=c(i,e,o,r,s),l=c(i,e,o,r,m);if(n&&!l){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 d=0;d<h.length;d+=4)h[d]=o[0],h[d+1]=o[1],h[d+2]=o[2],h[d+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 d=-1;d<e/l+1;d++)for(let i=-1;i<t/l+1;i++){const s=i*l+l/2,o=d*l+l/2;if(s<-l||s>t+l||o<-l||o>e+l)continue;const f=Math.max(0,Math.floor(s-l/2)),p=Math.min(t-1,Math.ceil(s+l/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++){const d=c(i,e,s,o,l),f=u(i,e,s,o,n);if(d){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 l=0;l<a.length;l+=4)a[l]=o[0],a[l+1]=o[1],a[l+2]=o[2],a[l+3]=o[3];const h=s+n;for(let l=0;l<Math.ceil(e/h)+1;l++)for(let i=0;i<Math.ceil(t/h)+1;i++){const n=i*h,o=l*h;if(!(n>=t||o>=e))for(let i=o;i<Math.min(o+s,e);i++)for(let e=n;e<Math.min(n+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 l=0;l<h.length;l+=4)h[l]=r[0],h[l+1]=r[1],h[l+2]=r[2],h[l+3]=r[3];for(let l=0;l<Math.ceil(e/o)+1;l++)for(let i=0;i<Math.ceil(t/o)+1;i++){const r=i*o,c=l*o;if(r<-s||r>t+s||c<-s||c>e+s)continue;const u=r-s/2,d=r+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=r-n/2,m=r+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 h=0;h<a.length;h+=4)a[h]=o[0],a[h+1]=o[1],a[h+2]=o[2],a[h+3]=o[3];for(let h=0;h<e;h++)for(let i=0;i<t;i++){const o=(i+h)%s,l=(i-h+e)%s;if(o<n||o>s-n||(l<n||l>s-n)){const e=4*(h*t+i);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 c=0;c<a.length;c+=4)a[c]=o[0],a[c+1]=o[1],a[c+2]=o[2],a[c+3]=o[3];const h=s,l=s/2;for(let c=0;c<e;c++)for(let e=0;e<t;e++){const i=e%h,s=c%l,o=s-i/2,u=s+i/2-l,d=Math.abs(o)<n/2,f=Math.abs(u)<n/2;if(d||f){const i=4*(c*t+e);a[i]=r[0],a[i+1]=r[1],a[i+2]=r[2],a[i+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 h=0;h<a.length;h+=4)a[h]=o[0],a[h+1]=o[1],a[h+2]=o[2],a[h+3]=o[3];for(let h=0;h<e;h++)for(let e=0;e<t;e++){const i=e%s,o=h%s,l=Math.abs((o+s/2)%s-s/2)<n/2,c=Math.abs((i+2*o+1.5*s)%s-s/2)<n/2,u=Math.abs((i-2*o+1.5*s)%s-s/2)<n/2;if(l||c||u){const i=4*(h*t+e);a[i]=r[0],a[i+1]=r[1],a[i+2]=r[2],a[i+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 u=0;u<e;u++)for(let e=0;e<t;e++){let i=1,l=1,d=0,f=0;for(let t=0;t<r;t++){const t=e*o*l,s=u*o*l;d+=Xt.perlin2(t,s)*i,f+=i,i*=a,l*=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*(u*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 c=0;c<e;c++)for(let e=0;e<t;e++){const i=4*(c*t+e),u=e-o,d=c-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,i)}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 u=0;u<c.length;u+=4)c.set(o,u);for(let u=0;u<e;u++)for(let e=0;e<t;e++){const i=e+Xt.perlin2(e*a,u*a)*r,o=u+Xt.perlin2((e+31.416)*a,(u+27.182)*a)*r;if(i%s<h||i%s>s-h||(o%s<h||o%s>s-h)){const i=4*(u*t+e);c.set(n,i)}}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 d=0;d<u.length;d+=4)u.set(r,d);if(a)for(let d=0;d<e;d++)for(let i=0;i<t;i++){if(.5*(Xt.perlin2(i*h,d*h)+1)>l)for(let n=-s;n<=s;n++)for(let r=-s;r<=s;r++){const a=i+r,h=d+n;if(a>=0&&a<t&&h>=0&&h<e){if(r*r+n*n<=s*s){const e=4*(h*t+a);u.set(o,e)}}}}else for(let d=Math.floor(n/2);d<e;d+=n)for(let i=Math.floor(n/2);i<t;i+=n)for(let n=-s;n<=s;n++)for(let r=-s;r<=s;r++){const a=i+r,h=d+n;if(a>=0&&a<t&&h>=0&&h<e){if(r*r+n*n<=s*s){const e=4*(h*t+a);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=6*(.618033988749895*t%1),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 _=0;_<g;_++)for(let t=0;t<g&&!(d.length>=s);t++){const e=t*m+m/2,i=_*y+y/2,s=(2*p()-1)*h*m,o=(2*p()-1)*h*y;d.push({x:Math.floor(e+s),y:Math.floor(i+o)}),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);r=Math.min(r,t-r),a=Math.min(a,e-a);return.8*Math.sqrt(r*r+a*a)+.2*(r+a)};for(let _=0;_<e;_++)for(let i=0;i<t;i++){const s=4*(_*t+i);let n=1/0,a=1/0,h=0;for(let t=0;t<d.length;t++){const e=v(i,_,d[t].x,d[t].y);e<n?(a=n,n=e,h=t):e<a&&(a=e)}for(let o=0;o<d.length;o++)for(let s=-1;s<=1;s++)for(let r=-1;r<=1;r++){if(0===s&&0===r)continue;const l=d[o].x+s*t,c=d[o].y+r*e,u=Math.sqrt(Math.pow(i-l,2)+Math.pow(_-c,2));u<n?(a=n,n=u,h=o):u<a&&(a=u)}a-n<r?u.set(o,s):u.set(f[h],s)}return u}static penrose(t,e,i={}){return Yt(t,e,i)}},t.PieSlice=class extends Be{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Ce.lines.beginPath(),Ce.lines.moveTo(0,0),Ce.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle),Ce.lines.closePath(),this.color&&Ce.colors.fill(this.color),this.stroke&&Ce.colors.stroke(this.stroke,this.lineWidth)}},t.Pin=oi,t.Pipeline=Ui,t.Plane3D=ti,t.PlatformerScene=class extends bi{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 At({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;mi.isDown(mi.LEFT)||mi.isDown(mi.A)?i=-1:(mi.isDown(mi.RIGHT)||mi.isDown(mi.D))&&(i=1),t.vx=i*this.moveSpeed;(mi.isDown(mi.SPACE)||mi.isDown(mi.W)||mi.isDown(mi.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();Ce.save(),Ce.ctx.beginPath(),Ce.ctx.rect(-this.x,-this.y,t,e),Ce.ctx.clip(),Ce.ctx.beginPath(),Ce.ctx.translate(-this.x,-this.y);for(const s of this._layers){if(!s.gameObject.visible)continue;Ce.save();const t=i.x*s.speed+(s.offsetX||0),e=i.y*s.speed+(s.offsetY||0);Ce.ctx.translate(-t,-e),s.gameObject.render(),Ce.restore()}for(const s of this._collection.getSortedChildren())s.visible&&(this._layers.some(t=>t.gameObject===s)||(Ce.save(),Ce.ctx.translate(-i.x,-i.y),s.render(),Ce.restore()));Ce.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=si,t.Position=Tt,t.Prism=class extends Be{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)&&Ce.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=Ye,t.Renderable=De,t.Ring=ii,t.RoundedRectangle=We,t.SPHERE_SHADERS=Ve,t.SVGShape=ei,t.Scene=bi,t.Scene3D=class extends bi{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;Ce.save(),Ce.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)Ce.save(),Ce.translateTo(e.x,e.y),this.scaleByDepth&&Ce.ctx.scale(e.scale,e.scale),Ce.translateTo(-e.child.x,-e.child.y),e.child.render(),Ce.restore();Ce.restore()}},t.Shape=Be,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 wi(t,e,s)}},t.Sound=class{static beep(t=440,e=.1,i={}){if(!ds.isInitialized)return;const{volume:s=.3,type:n="sine"}=i;ds.osc.tone(t,e,{type:n,volume:s,attack:.001,decay:.8*e,sustain:0,release:.2*e})}static click(t=.3){ds.isInitialized&&ds.osc.tone(1e3,.01,{type:"square",volume:t,attack:.001,decay:.009,sustain:0,release:.001})}static sweep(t,e,i,s={}){if(!ds.isInitialized)return;const{volume:n=.3,type:o="sine"}=s;ds.osc.sweep(t,e,i,{type:o,volume:n})}static fromValue(t,e={}){if(!ds.isInitialized)return;const{root:i="C4",scale:s="pentatonic",octaves:n=2,duration:o=.2,volume:r=.3,type:a="sine"}=e,h=ds.music.mapToScale(t,i,s,n);ds.osc.tone(h,o,{volume:r,type:a})}static impact(t=.5){if(!ds.isInitialized)return;const e=80+200*t,i=.05+.15*t;ds.osc.tone(e,i,{type:"sine",volume:.4*t,attack:.001,decay:i,sustain:0,release:.02});const s=ds.noise.white(ds.ctx,.08),n=ds.ctx.createGain();n.gain.setValueAtTime(.25*t,ds.now),n.gain.exponentialRampToValueAtTime(.001,ds.now+.08),s.connect(n),n.connect(ds.master),s.start(),s.stop(ds.now+.1)}static explosion(t=.7){if(!ds.isInitialized)return;const e=.3+.4*t;ds.osc.tone(50+30*t,e,{type:"sine",volume:.4*t,attack:.001,decay:.3*e,sustain:.3,release:.7*e});const i=ds.noise.brown(ds.ctx,e),s=ds.ctx.createGain(),n=ds.fx.filter("lowpass",800+400*t,1);s.gain.setValueAtTime(.5*t,ds.now),s.gain.exponentialRampToValueAtTime(.001,ds.now+e),i.connect(n),n.connect(s),s.connect(ds.master),i.start(),i.stop(ds.now+e+.1)}static laser(t={}){if(!ds.isInitialized)return;const{startFreq:e=1200,endFreq:i=200,duration:s=.15,volume:n=.25,type:o="sawtooth"}=t;ds.osc.sweep(e,i,s,{type:o,volume:n})}static powerUp(t={}){if(!ds.isInitialized)return;const{startFreq:e=300,endFreq:i=1200,duration:s=.3,volume:n=.3}=t;ds.osc.sweep(e,i,s,{type:"square",volume:n}),ds.osc.sweep(1.5*e,1.5*i,s,{type:"sine",volume:.5*n})}static hurt(t=.5){ds.isInitialized&&(ds.osc.tone(80+40*t,.1,{type:"sine",volume:.4*t,attack:.001,decay:.08,sustain:0,release:.02}),ds.osc.tone(200+100*t,.08,{type:"sawtooth",volume:.2*t,attack:.001,decay:.06,sustain:0,release:.02}))}static coin(t={}){if(!ds.isInitialized)return;const{baseFreq:e=987.77,volume:i=.25}=t;ds.osc.tone(e,.08,{type:"square",volume:i,attack:.001,decay:.05,sustain:.3,release:.02}),setTimeout(()=>{ds.isInitialized&&ds.osc.tone(1.5*e,.12,{type:"square",volume:i,attack:.001,decay:.08,sustain:.2,release:.04})},80)}static jump(t={}){if(!ds.isInitialized)return;const{startFreq:e=150,endFreq:i=400,duration:s=.15,volume:n=.25}=t;ds.osc.sweep(e,i,s,{type:"square",volume:n})}static select(t={}){if(!ds.isInitialized)return;const{frequency:e=660,volume:i=.2}=t;ds.osc.tone(e,.08,{type:"sine",volume:i,attack:.001,decay:.05,sustain:.3,release:.03})}static error(t={}){if(!ds.isInitialized)return;const{volume:e=.25}=t;ds.osc.tone(400,.1,{type:"square",volume:e,attack:.001,decay:.08,sustain:0,release:.02}),setTimeout(()=>{ds.isInitialized&&ds.osc.tone(300,.15,{type:"square",volume:e,attack:.001,decay:.12,sustain:0,release:.03})},100)}static drone(t="C2",e={}){if(!ds.isInitialized)return null;const{volume:i=.2,richness:s=.5}=e,n=ds.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=ds.ctx.createOscillator(),n=ds.ctx.createGain();s.type="sine",s.frequency.value=t,n.gain.value=a[e]*i,s.connect(n),n.connect(ds.master),s.start(),o.push(s),r.push(n)}),{stop:(t=.5)=>{const e=ds.now;r.forEach(i=>{i.gain.linearRampToValueAtTime(0,e+t)}),setTimeout(()=>{o.forEach(t=>{try{t.stop()}catch(e){}})},1e3*t+100)},setVolume:t=>{r.forEach((e,i)=>{e.gain.linearRampToValueAtTime(a[i]*t,ds.now+.1)})}}}static note(t,e=.5,i={}){if(!ds.isInitialized)return;const{volume:s=.3,type:n="sine",envelope:o={}}=i,r=ds.music.noteToFreq(t);ds.osc.tone(r,e,{type:n,volume:s,...ds.env.presets.pluck,...o})}static chord(t,e="major",i=.5,s={}){if(!ds.isInitialized)return;const{volume:n=.2,type:o="sine",strum:r=0}=s,a=ds.music.chord(t,e);a.forEach((t,e)=>{const s=r*e;ds.osc.tone(t,i,{type:o,volume:n/a.length,attack:.01,decay:.1,sustain:.6,release:.2,startTime:ds.now+s})})}static sequence(t,e=.2,i=0,s={}){if(!ds.isInitialized)return;const{volume:n=.3,type:o="sine"}=s,r=e+i;t.forEach((t,i)=>{const s=ds.now+i*r,a=ds.music.noteToFreq(t);ds.osc.tone(a,e,{type:o,volume:n,attack:.01,decay:.05,sustain:.5,release:.1,startTime:s})})}static win(){if(!ds.isInitialized)return;this.sequence(["C5","E5","G5","C6"],.15,.05,{volume:.25,type:"square"})}static lose(){if(!ds.isInitialized)return;this.sequence(["E4","D4","C4"],.25,0,{volume:.25,type:"sawtooth"})}},t.Sphere=class extends Be{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 o=0;o<=this.vSegments;o++){const e=[],n=o/this.vSegments,r=Math.PI*n-Math.PI/2;for(let s=0;s<=this.hSegments;s++){const n=s/this.hSegments,o=2*Math.PI*n,a=t*Math.cos(r)*Math.cos(o),h=t*Math.cos(r)*Math.sin(o),l=t*Math.sin(r);e.push(i(a,h,l))}s.push(e)}const n=[];for(let o=0;o<this.vSegments;o++)for(let t=0;t<this.hSegments;t++){const e=s[o][t],i=s[o][t+1],r=s[o+1][t],a=s[o+1][t+1],h=(e.z+i.z+r.z+a.z)/4,l=(e.nx+i.nx+r.nx+a.nx)/4,c=(e.ny+i.ny+r.ny+a.ny)/4,u=(e.nz+i.nz+r.nz+a.nz)/4;n.push({points:[e,i,a,r],z:h,color:this.calculateSurfaceColor(l,c,u)})}if(n.sort((t,e)=>e.z-t.z),this.wireframe)for(const o of n){const t=o.points;for(let e=0;e<t.length;e++){const i=(e+1)%t.length;Ce.lines.line(t[e].x,t[e].y,t[i].x,t[i].y,this.stroke,this.lineWidth)}}for(const o of n)Ce.shapes.polygon(o.points,o.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=je,t.Sprite=class extends _i{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&&(Ce.save(),t.render(),Ce.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}]`}},t.Square=Le,t.Star=qe,t.StateMachine=fs,t.Stepper=class extends _i{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=Ni.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 Ee;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 li(this.labelText,{font:Ni.fonts.small,color:Ni.colors.dimText,align:"center",baseline:"middle"}),this.label.y=o,this.group.add(this.label)),this.decrementBg=new Ye({width:this.buttonSize,height:this.stepperHeight,color:Ni.button.default.bg,stroke:Ni.button.default.stroke,lineWidth:1}),this.decrementBg.x=i,this.decrementBg.y=n,this.decrementText=new li("−",{font:this.font,color:Ni.button.default.text,align:"center",baseline:"middle"}),this.decrementText.x=i,this.decrementText.y=n,this.valueBg=new Ye({width:this.valueWidth,height:this.stepperHeight,color:Ni.colors.darkerBg,stroke:Ni.colors.subtleBorder,lineWidth:1}),this.valueBg.x=0,this.valueBg.y=n,this.valueText=new li(this.formatValue(this._value),{font:this.font,color:Ni.colors.neonGreen,align:"center",baseline:"middle"}),this.valueText.x=0,this.valueText.y=n,this.incrementBg=new Ye({width:this.buttonSize,height:this.stepperHeight,color:Ni.button.default.bg,stroke:Ni.button.default.stroke,lineWidth:1}),this.incrementBg.x=s,this.incrementBg.y=n,this.incrementText=new li("+",{font:this.font,color:Ni.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 r of n){if(i-=r.x||0,s-=r.y||0,r.rotation){const t=Math.cos(-r.rotation),e=Math.sin(-r.rotation),n=i;i=n*t-s*e,s=n*e+s*t}void 0!==r.scaleX&&0!==r.scaleX&&(i/=r.scaleX),void 0!==r.scaleY&&0!==r.scaleY&&(s/=r.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=Ni.button.pressed.bg,this.decrementBg.stroke=Ni.button.pressed.stroke,this.decrementText.color=Ni.button.pressed.text):this._decrementHover?(this.decrementBg.color=Ni.button.hover.bg,this.decrementBg.stroke=Ni.button.hover.stroke,this.decrementText.color=Ni.button.hover.text):(this.decrementBg.color=Ni.button.default.bg,this.decrementBg.stroke=Ni.button.default.stroke,this.decrementText.color=Ni.button.default.text),this._value<=this.min&&(this.decrementBg.stroke=Ni.colors.subtleBorder,this.decrementText.color=Ni.colors.dimText),this._incrementPressed?(this.incrementBg.color=Ni.button.pressed.bg,this.incrementBg.stroke=Ni.button.pressed.stroke,this.incrementText.color=Ni.button.pressed.text):this._incrementHover?(this.incrementBg.color=Ni.button.hover.bg,this.incrementBg.stroke=Ni.button.hover.stroke,this.incrementText.color=Ni.button.hover.text):(this.incrementBg.color=Ni.button.default.bg,this.incrementBg.stroke=Ni.button.default.stroke,this.incrementText.color=Ni.button.default.text),this._value>=this.max&&(this.incrementBg.stroke=Ni.colors.subtleBorder,this.incrementText.color=Ni.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 Be{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;if(Ce.shapes.fillCircle(0,i,e,this.headColor),Ce.shapes.strokeCircle(0,i,e,this.stroke,this.lineWidth),Ce.lines.line(0,s,0,n,this.stroke,this.lineWidth),Ce.lines.line(-r,o,r,o,this.stroke,this.lineWidth),Ce.lines.line(0,n,-a,h,this.stroke,this.lineWidth),Ce.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])=>Ce.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=ds,t.SynthAnalyzer=us,t.SynthEffects=hs,t.SynthEnvelope=rs,t.SynthMusical=cs,t.SynthNoise=ls,t.SynthOscillators=as,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=Ut,t.Text=ki,t.TextShape=li,t.TileLayout=class extends Mi{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 Zi{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||Ni.button.active.bg,this.colorActiveStroke=e.colorActiveStroke||Ni.button.active.stroke,this.colorActiveText=e.colorActiveText||Ni.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 _i{constructor(t,e={}){super(t,{...e,zIndex:9999}),this.font=e.font||Ni.fonts.small,this.textColor=e.textColor||Ni.tooltip.text,this.bgColor=e.bgColor||Ni.tooltip.bg,this.borderColor=e.borderColor||Ni.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 Ye({width:100,height:30,color:this.bgColor,stroke:this.borderColor,lineWidth:1}),this.lineShapes=[],this.group=new Ee,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 n of s){const t=n.split(" ");let s="";for(const n of t){const t=s?`${s} ${n}`:n;e.measureText(t).width>this.maxWidth&&s?(i.push(s),s=n):s=t}s?i.push(s):""===n&&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 li(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 a of this._lines){const i=t.measureText(a);e=Math.max(e,i.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 a=0;a<this.lineShapes.length;a++)this.lineShapes[a].x=o,this.lineShapes[a].y=r+a*s}draw(){this._visible&&this.group.render()}},t.Touch=xi,t.Traceable=Pe,t.Transform=Ie,t.Transformable=Ae,t.Triangle=Ue,t.Tween=Ci,t.Tweenetik=Gi,t.UI_THEME=Ni,t.Updaters=ji,t.VerticalLayout=class extends Mi{calculateLayout(){return Dt(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=Ne,t.WrappedText=class extends Be{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(!Ce.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=Ce.text.font(),e=Ce.text.textAlign(),i=Ce.text.textBaseline();this.font&&Ce.text.setFont(this.font),Ce.text.setTextAlign("left"),Ce.text.setTextBaseline("top");const s=this.text.split(" ");let n="",o="";this.lines=[],this.width=0;for(let r=0;r<s.length;r++){o=n+s[r]+" ";Ce.text.measureText(o).width>this.maxWidth&&r>0?(this.lines.push(n),this.width=Math.max(this.width,Ce.text.measureText(n).width),n=s[r]+" "):n=o}this.lines.push(n),this.width=Math.max(this.width,Ce.text.measureText(n).width),this.height=this.lines.length*this.lineHeight,Ce.text.setFont(t),Ce.text.setTextAlign(e),Ce.text.setTextBaseline(i)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Ce.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&&Ce.text.setFont(this.font),Ce.text.setTextAlign(this.align),Ce.text.setTextBaseline(this.baseline);let i=t;"center"===this.align?i=0:"right"===this.align&&(i=t+this.width);for(let s=0;s<this.lines.length;s++){const t=e+s*this.lineHeight;this.outlineColor?Ce.outlinedText(this.lines[s],i,t,this.color,this.outlineColor,this.outlineWidth,this.font):Ce.text.fillText(this.lines[s],i,t,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=vi,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=Nt(r,i,s,n,o),h=(r+a)/r;return{x:t*h,y:e*h,displacement:a}},t.applyLayout=Rt,t.bezierV1=Hi,t.blendForces=ae,t.bounceV1=Si,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=se,t.computeFluidForces=oe,t.computeGasForces=re,t.computePressures=ne,t.computeThermalBuoyancy=function(t,e={}){var i;const s=ee(e),n=new Array(t.length),o=s.gas.neutralTemperature,r=s.gas.buoyancy;for(let a=0;a<t.length;a++){const e=t[a],h=((e.temperature??(null==(i=e.custom)?void 0:i.temperature)??s.gas.neutralTemperature)-o)*r;n[a]={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=qt,t.flammEmbeddingHeight=function(t,e,i,s,n){const o=qt(Math.max(t,e+.01),e,i),r=qt(s,e,i);return(r-o)*n/r},t.floatV1=Ti,t.followPath=Ri,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=ns,t.generatePenroseTilingPixels=Yt,t.getDefaultFluidConfig=function(){return ee()},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=Nt,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=Ei,t.horizontalLayout=Pt,t.integrateEuler=function(t,e,i,s={}){const n=ee(s),o=new Array(t.length);for(let r=0;r<t.length;r++){const s=t[r],a=e[r],h=he(s,n),l=a.x/h+n.external.gravity.x,c=a.y/h+n.external.gravity.y,u=s.vx+l*i,d=s.vy+c*i;o[r]={x:s.x+u*i,y:s.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=Pi,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=Di,t.parabolicV1=zi,t.patrolV1=Ii,t.pendulumV1=Ai,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=Bi,t.schwarzschildPrecessionRate=function(t,e,i=1){return t<=e?0:i*(e/t)},t.shakeV1=Fi,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=ns({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=Oi,t.springV1=Xi,t.swingV1=Yi,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=Dt,t.waypointV1=Wi,t.zoneTemperature=$t,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});