@guinetik/gcanvas 1.0.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/dist/CNAME +1 -0
  2. package/dist/aizawa.html +27 -0
  3. package/dist/animations.html +31 -0
  4. package/dist/basic.html +38 -0
  5. package/dist/baskara.html +31 -0
  6. package/dist/bezier.html +35 -0
  7. package/dist/beziersignature.html +29 -0
  8. package/dist/blackhole.html +28 -0
  9. package/dist/blob.html +35 -0
  10. package/dist/clifford.html +25 -0
  11. package/dist/cmb.html +24 -0
  12. package/dist/coordinates.html +698 -0
  13. package/dist/cube3d.html +23 -0
  14. package/dist/dadras.html +26 -0
  15. package/dist/dejong.html +25 -0
  16. package/dist/demos.css +303 -0
  17. package/dist/dino.html +42 -0
  18. package/dist/easing.html +28 -0
  19. package/dist/events.html +195 -0
  20. package/dist/fluent.html +647 -0
  21. package/dist/fluid-simple.html +22 -0
  22. package/dist/fluid.html +37 -0
  23. package/dist/fractals.html +36 -0
  24. package/dist/gameobjects.html +626 -0
  25. package/dist/gcanvas.es.js +14368 -9093
  26. package/dist/gcanvas.es.min.js +1 -1
  27. package/dist/gcanvas.umd.js +1 -1
  28. package/dist/gcanvas.umd.min.js +1 -1
  29. package/dist/genart.html +26 -0
  30. package/dist/gendream.html +26 -0
  31. package/dist/group.html +36 -0
  32. package/dist/halvorsen.html +27 -0
  33. package/dist/home.html +587 -0
  34. package/dist/hyperbolic001.html +23 -0
  35. package/dist/hyperbolic002.html +23 -0
  36. package/dist/hyperbolic003.html +23 -0
  37. package/dist/hyperbolic004.html +23 -0
  38. package/dist/hyperbolic005.html +22 -0
  39. package/dist/index.html +446 -0
  40. package/dist/isometric.html +34 -0
  41. package/dist/js/aizawa.js +425 -0
  42. package/dist/js/animations.js +452 -0
  43. package/dist/js/basic.js +204 -0
  44. package/dist/js/baskara.js +751 -0
  45. package/dist/js/bezier.js +692 -0
  46. package/dist/js/beziersignature.js +241 -0
  47. package/dist/js/blackhole/accretiondisk.obj.js +379 -0
  48. package/dist/js/blackhole/blackhole.obj.js +318 -0
  49. package/dist/js/blackhole/index.js +409 -0
  50. package/dist/js/blackhole/particle.js +56 -0
  51. package/dist/js/blackhole/starfield.obj.js +218 -0
  52. package/dist/js/blob.js +2276 -0
  53. package/dist/js/clifford.js +236 -0
  54. package/dist/js/cmb.js +594 -0
  55. package/dist/js/coordinates.js +840 -0
  56. package/dist/js/cube3d.js +789 -0
  57. package/dist/js/dadras.js +405 -0
  58. package/dist/js/dejong.js +257 -0
  59. package/dist/js/dino.js +1420 -0
  60. package/dist/js/easing.js +477 -0
  61. package/dist/js/fluent.js +183 -0
  62. package/dist/js/fluid-simple.js +253 -0
  63. package/dist/js/fluid.js +527 -0
  64. package/dist/js/fractals.js +932 -0
  65. package/dist/js/fractalworker.js +93 -0
  66. package/dist/js/gameobjects.js +176 -0
  67. package/dist/js/genart.js +268 -0
  68. package/dist/js/gendream.js +209 -0
  69. package/dist/js/group.js +140 -0
  70. package/dist/js/halvorsen.js +405 -0
  71. package/dist/js/hyperbolic001.js +310 -0
  72. package/dist/js/hyperbolic002.js +388 -0
  73. package/dist/js/hyperbolic003.js +319 -0
  74. package/dist/js/hyperbolic004.js +345 -0
  75. package/dist/js/hyperbolic005.js +340 -0
  76. package/dist/js/info-toggle.js +25 -0
  77. package/dist/js/isometric.js +851 -0
  78. package/dist/js/kerr.js +1547 -0
  79. package/dist/js/lavalamp.js +590 -0
  80. package/dist/js/layout.js +354 -0
  81. package/dist/js/lorenz.js +425 -0
  82. package/dist/js/mondrian.js +285 -0
  83. package/dist/js/opacity.js +275 -0
  84. package/dist/js/painter.js +484 -0
  85. package/dist/js/particles-showcase.js +514 -0
  86. package/dist/js/particles.js +299 -0
  87. package/dist/js/patterns.js +397 -0
  88. package/dist/js/penrose/artifact.js +69 -0
  89. package/dist/js/penrose/blackhole.js +121 -0
  90. package/dist/js/penrose/constants.js +73 -0
  91. package/dist/js/penrose/game.js +943 -0
  92. package/dist/js/penrose/lore.js +278 -0
  93. package/dist/js/penrose/penrosescene.js +892 -0
  94. package/dist/js/penrose/ship.js +216 -0
  95. package/dist/js/penrose/sounds.js +211 -0
  96. package/dist/js/penrose/voidparticle.js +55 -0
  97. package/dist/js/penrose/voidscene.js +258 -0
  98. package/dist/js/penrose/voidship.js +144 -0
  99. package/dist/js/penrose/wormhole.js +46 -0
  100. package/dist/js/pipeline.js +555 -0
  101. package/dist/js/plane3d.js +256 -0
  102. package/dist/js/platformer.js +1579 -0
  103. package/dist/js/rossler.js +480 -0
  104. package/dist/js/scene.js +304 -0
  105. package/dist/js/scenes.js +320 -0
  106. package/dist/js/schrodinger.js +706 -0
  107. package/dist/js/schwarzschild.js +1015 -0
  108. package/dist/js/shapes.js +628 -0
  109. package/dist/js/space/alien.js +171 -0
  110. package/dist/js/space/boom.js +98 -0
  111. package/dist/js/space/boss.js +353 -0
  112. package/dist/js/space/buff.js +73 -0
  113. package/dist/js/space/bullet.js +102 -0
  114. package/dist/js/space/constants.js +85 -0
  115. package/dist/js/space/game.js +1884 -0
  116. package/dist/js/space/hud.js +112 -0
  117. package/dist/js/space/laserbeam.js +179 -0
  118. package/dist/js/space/lightning.js +277 -0
  119. package/dist/js/space/minion.js +192 -0
  120. package/dist/js/space/missile.js +212 -0
  121. package/dist/js/space/player.js +430 -0
  122. package/dist/js/space/powerup.js +90 -0
  123. package/dist/js/space/starfield.js +58 -0
  124. package/dist/js/space/starpower.js +90 -0
  125. package/dist/js/spacetime.js +559 -0
  126. package/dist/js/sphere3d.js +229 -0
  127. package/dist/js/sprite.js +473 -0
  128. package/dist/js/starfaux/config.js +118 -0
  129. package/dist/js/starfaux/enemy.js +353 -0
  130. package/dist/js/starfaux/hud.js +78 -0
  131. package/dist/js/starfaux/index.js +482 -0
  132. package/dist/js/starfaux/laser.js +182 -0
  133. package/dist/js/starfaux/player.js +468 -0
  134. package/dist/js/starfaux/terrain.js +560 -0
  135. package/dist/js/study001.js +275 -0
  136. package/dist/js/study002.js +366 -0
  137. package/dist/js/study003.js +331 -0
  138. package/dist/js/study004.js +389 -0
  139. package/dist/js/study005.js +209 -0
  140. package/dist/js/study006.js +194 -0
  141. package/dist/js/study007.js +192 -0
  142. package/dist/js/study008.js +413 -0
  143. package/dist/js/svgtween.js +204 -0
  144. package/dist/js/tde/accretiondisk.js +471 -0
  145. package/dist/js/tde/blackhole.js +219 -0
  146. package/dist/js/tde/blackholescene.js +209 -0
  147. package/dist/js/tde/config.js +59 -0
  148. package/dist/js/tde/index.js +820 -0
  149. package/dist/js/tde/jets.js +290 -0
  150. package/dist/js/tde/lensedstarfield.js +154 -0
  151. package/dist/js/tde/tdestar.js +297 -0
  152. package/dist/js/tde/tidalstream.js +372 -0
  153. package/dist/js/tde_old/blackhole.obj.js +354 -0
  154. package/dist/js/tde_old/debris.obj.js +791 -0
  155. package/dist/js/tde_old/flare.obj.js +239 -0
  156. package/dist/js/tde_old/index.js +448 -0
  157. package/dist/js/tde_old/star.obj.js +812 -0
  158. package/dist/js/tetris/config.js +157 -0
  159. package/dist/js/tetris/grid.js +286 -0
  160. package/dist/js/tetris/index.js +1195 -0
  161. package/dist/js/tetris/renderer.js +634 -0
  162. package/dist/js/tetris/tetrominos.js +280 -0
  163. package/dist/js/thomas.js +394 -0
  164. package/dist/js/tiles.js +312 -0
  165. package/dist/js/tweendemo.js +79 -0
  166. package/dist/js/visibility.js +102 -0
  167. package/dist/kerr.html +28 -0
  168. package/dist/lavalamp.html +27 -0
  169. package/dist/layouts.html +37 -0
  170. package/dist/logo.svg +4 -0
  171. package/dist/loop.html +84 -0
  172. package/dist/lorenz.html +27 -0
  173. package/dist/mondrian.html +32 -0
  174. package/dist/og_image.png +0 -0
  175. package/dist/opacity.html +36 -0
  176. package/dist/painter.html +39 -0
  177. package/dist/particles-showcase.html +28 -0
  178. package/dist/particles.html +24 -0
  179. package/dist/patterns.html +33 -0
  180. package/dist/penrose-game.html +31 -0
  181. package/dist/pipeline.html +737 -0
  182. package/dist/plane3d.html +24 -0
  183. package/dist/platformer.html +43 -0
  184. package/dist/rossler.html +27 -0
  185. package/dist/scene-interactivity-test.html +220 -0
  186. package/dist/scene.html +33 -0
  187. package/dist/scenes.html +96 -0
  188. package/dist/schrodinger.html +27 -0
  189. package/dist/schwarzschild.html +27 -0
  190. package/dist/shapes.html +16 -0
  191. package/dist/space.html +85 -0
  192. package/dist/spacetime.html +27 -0
  193. package/dist/sphere3d.html +24 -0
  194. package/dist/sprite.html +18 -0
  195. package/dist/starfaux.html +22 -0
  196. package/dist/study001.html +23 -0
  197. package/dist/study002.html +23 -0
  198. package/dist/study003.html +23 -0
  199. package/dist/study004.html +23 -0
  200. package/dist/study005.html +22 -0
  201. package/dist/study006.html +24 -0
  202. package/dist/study007.html +24 -0
  203. package/dist/study008.html +22 -0
  204. package/dist/svgtween.html +29 -0
  205. package/dist/tde.html +28 -0
  206. package/dist/tetris3d.html +25 -0
  207. package/dist/thomas.html +27 -0
  208. package/dist/tiles.html +28 -0
  209. package/dist/transforms.html +400 -0
  210. package/dist/tween.html +45 -0
  211. package/dist/visibility.html +33 -0
  212. package/package.json +1 -1
  213. package/readme.md +30 -22
  214. package/src/game/objects/go.js +7 -0
  215. package/src/game/objects/index.js +2 -0
  216. package/src/game/objects/isometric-scene.js +53 -3
  217. package/src/game/objects/layoutscene.js +57 -0
  218. package/src/game/objects/mask.js +241 -0
  219. package/src/game/objects/scene.js +19 -0
  220. package/src/game/objects/wrapper.js +14 -2
  221. package/src/game/pipeline.js +17 -0
  222. package/src/game/ui/button.js +101 -16
  223. package/src/game/ui/theme.js +0 -6
  224. package/src/game/ui/togglebutton.js +25 -14
  225. package/src/game/ui/tooltip.js +12 -4
  226. package/src/index.js +3 -0
  227. package/src/io/gesture.js +409 -0
  228. package/src/io/index.js +4 -1
  229. package/src/io/keys.js +9 -1
  230. package/src/io/screen.js +476 -0
  231. package/src/math/attractors.js +664 -0
  232. package/src/math/heat.js +106 -0
  233. package/src/math/index.js +1 -0
  234. package/src/mixins/draggable.js +15 -19
  235. package/src/painter/painter.shapes.js +11 -5
  236. package/src/particle/particle-system.js +165 -1
  237. package/src/physics/index.js +26 -0
  238. package/src/physics/physics-updaters.js +333 -0
  239. package/src/physics/physics.js +375 -0
  240. package/src/shapes/image.js +5 -5
  241. package/src/shapes/index.js +2 -0
  242. package/src/shapes/parallelogram.js +147 -0
  243. package/src/shapes/righttriangle.js +115 -0
  244. package/src/shapes/svg.js +281 -100
  245. package/src/shapes/text.js +22 -6
  246. package/src/shapes/transformable.js +5 -0
  247. package/src/sound/effects.js +807 -0
  248. package/src/sound/index.js +13 -0
  249. package/src/webgl/index.js +7 -0
  250. package/src/webgl/shaders/clifford-point-shaders.js +131 -0
  251. package/src/webgl/shaders/dejong-point-shaders.js +131 -0
  252. package/src/webgl/shaders/point-sprite-shaders.js +152 -0
  253. package/src/webgl/webgl-clifford-renderer.js +477 -0
  254. package/src/webgl/webgl-dejong-renderer.js +472 -0
  255. package/src/webgl/webgl-line-renderer.js +391 -0
  256. package/src/webgl/webgl-particle-renderer.js +410 -0
  257. package/types/index.d.ts +30 -2
  258. package/types/io.d.ts +217 -0
  259. package/types/physics.d.ts +299 -0
  260. package/types/shapes.d.ts +8 -0
  261. package/types/webgl.d.ts +188 -109
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).GCanvas={})}(this,function(t){"use strict";var e,i,s,n,o,r,a,h,l,c,u,d,f,p,g,m,y,x,v,_,w,b,M,k,C,S,T,R,P,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"})});
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).GCanvas={})}(this,function(t){"use strict";var e,i,s,n,o,r,a,h,l,c,u,d,f,p,g,m,v,y,_,x,b,w,M,S,C,T,k,P,R,A,z,D,B,I,E,F,O,L,Y,X,W,H,U,G,N,q,Z,V,$,j,K,J,Q,tt,et,it,st,nt,ot,rt,at,ht,lt,ct,ut,dt,ft,pt,gt,mt,vt=Object.defineProperty,yt=t=>{throw TypeError(t)},_t=(t,e,i)=>((t,e,i)=>e in t?vt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i)(t,"symbol"!=typeof e?e+"":e,i),xt=(t,e,i)=>e.has(t)||yt("Cannot "+i),bt=(t,e,i)=>(xt(t,e,"read from private field"),i?i.call(t):e.get(t)),wt=(t,e,i)=>e.has(t)?yt("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,i),Mt=(t,e,i,s)=>(xt(t,e,"write to private field"),s?s.call(t,i):e.set(t,i),i),St=(t,e,i)=>(xt(t,e,"access private method"),i);class Ct{constructor(t={}){this.children=[],this.sortByZIndex=t.sortByZIndex||!0,this._zOrderDirty=!1}add(t){return this.children.includes(t)?(console.warn("Object is already in this collection"),t):(this.children.push(t),t.parent=this._owner||this,this.sortByZIndex&&(this._zOrderDirty=!0,void 0!==t.zIndex&&null!==t.zIndex||(t.zIndex=this.children.length-1)),t)}remove(t){const e=this.children.indexOf(t);return-1!==e&&(this.children.splice(e,1),t.parent=null,!0)}clear(){this.children.forEach(t=>{t.parent=null}),this.children=[]}bringToFront(t){const e=this.children.indexOf(t);if(-1!==e)if(this.sortByZIndex){let e=!0;for(const i of this.children)if(i!==t&&(i.zIndex||0)>=(t.zIndex||0)){e=!1;break}e||(t.zIndex=Number.MAX_SAFE_INTEGER,this._zOrderDirty=!0,this._normalizeZIndices())}else e!==this.children.length-1&&(this.children.splice(e,1),this.children.push(t));else this.add(t)}sendToBack(t){const e=this.children.indexOf(t);if(-1===e)return this.children.unshift(t),void(t.parent=this._owner||this);if(this.sortByZIndex){let e=!0;for(const i of this.children)if(i!==t&&(i.zIndex||0)<=(t.zIndex||0)){e=!1;break}e||(t.zIndex=Number.MIN_SAFE_INTEGER,this._zOrderDirty=!0,this._normalizeZIndices())}else 0!==e&&(this.children.splice(e,1),this.children.unshift(t))}bringForward(t){const e=this.children.indexOf(t);if(-1!==e&&e!==this.children.length-1)if(this.sortByZIndex){const e=[...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),i=e.indexOf(t);if(i<e.length-1){const s=e[i+1],n=s.zIndex||0,o=t.zIndex||0;n-o>1?t.zIndex=o+Math.floor((n-o)/2):(t.zIndex=n,s.zIndex=o),this._zOrderDirty=!0,this._normalizeZIndices()}}else{const i=this.children[e+1];this.children[e+1]=t,this.children[e]=i}}sendBackward(t){const e=this.children.indexOf(t);if(!(e<=0))if(this.sortByZIndex){const e=[...this.children].sort((t,e)=>(t.zIndex||0)-(e.zIndex||0)),i=e.indexOf(t);if(i>0){const s=e[i-1],n=s.zIndex||0,o=t.zIndex||0;o-n>1?t.zIndex=n+Math.floor((o-n)/2):(t.zIndex=n,s.zIndex=o),this._zOrderDirty=!0,this._normalizeZIndices()}}else{const i=this.children[e-1];this.children[e-1]=t,this.children[e]=i}}_normalizeZIndices(){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 Tt=class t{static calculate(e,i,s,n=10,o=0,r=0){const a=i.width||0,h=i.height||0,l=s.width||0,c=s.height||0,u=s.x||0,d=s.y||0;let f,p,g,m;switch(e){case t.TOP_LEFT:f=u-l/2+n+a/2,p=d-c/2+n+h/2,g="left",m="top";break;case t.TOP_CENTER:f=u,p=d-c/2+n+h/2,g="center",m="top";break;case t.TOP_RIGHT:f=u+l/2-n-a/2,p=d-c/2+n+h/2,g="right",m="top";break;case t.CENTER_LEFT:f=u-l/2+n+a/2,p=d,g="left",m="middle";break;case t.CENTER:f=u,p=d,g="center",m="middle";break;case t.CENTER_RIGHT:f=u+l/2-n-a/2,p=d,g="right",m="middle";break;case t.BOTTOM_LEFT:f=u-l/2+n+a/2,p=d+c/2-n-h/2,g="left",m="bottom";break;case t.BOTTOM_CENTER:f=u,p=d+c/2-n-h/2,g="center",m="bottom";break;case t.BOTTOM_RIGHT:f=u+l/2-n-a/2,p=d+c/2-n-h/2,g="right",m="bottom";break;default:f=u-l/2+n+a/2,p=d-c/2+n+h/2,g="left",m="top"}return f+=o,p+=r,{x:f,y:p,align:g,baseline:m}}static calculateAbsolute(e,i,s,n=10,o=0,r=0){const a={width:s.width,height:s.height,x:s.width/2,y:s.height/2};return t.calculate(e,i,a,n,o,r)}};_t(Tt,"TOP_LEFT","top-left"),_t(Tt,"TOP_CENTER","top-center"),_t(Tt,"TOP_RIGHT","top-right"),_t(Tt,"CENTER_LEFT","center-left"),_t(Tt,"CENTER","center"),_t(Tt,"CENTER_RIGHT","center-right"),_t(Tt,"BOTTOM_LEFT","bottom-left"),_t(Tt,"BOTTOM_CENTER","bottom-center"),_t(Tt,"BOTTOM_RIGHT","bottom-right");let kt=Tt;function Pt(t,e,i={}){const s=i.offsetX??0,n=i.offsetY??0,o=i.transform;return t.forEach((t,i)=>{if(i<e.length){const r=e[i];if(o){const e=o(r);t.x=e.x+s,t.y=e.y+n}else t.x=r.x+s,t.y=r.y+n}}),t}function Rt(t,e={}){const i=e.spacing??10,s=e.padding??0,n=e.align??"start",o=e.centerItems??!0;let r=s,a=0;const h=[];for(const 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 At(t,e={}){const i=e.spacing??10,s=e.padding??0,n=e.align??"start",o=e.centerItems??!0;let r=s,a=0;const h=[];for(const 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 Dt(t,e={}){if(0===t.length)return{positions:[],width:0,height:0};const i=e.columns??4,s=e.spacing??10,n=e.padding??0,o=e.centerItems??!0,r=new Array(i).fill(0),a=[];t.forEach((t,e)=>{const s=e%i,n=Math.floor(e/i),o=t.width??0,h=t.height??0;r[s]=Math.max(r[s],o),void 0===a[n]?a[n]=h:a[n]=Math.max(a[n],h)});const h=[];let l=n,c=n,u=0;for(let 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,v=o?c+p/2:c;h.push({x:m,y:v}),u++,u<i?l+=r[u-1]+s:(u=0,l=n,c+=g+s)}return{positions:h,width:2*n+r.reduce((t,e)=>t+e,0)+s*(i-1),height:2*n+a.reduce((t,e)=>t+e,0)+s*(a.length-1),cols:i,rows:a.length}}class Bt{constructor(t={}){this.x=0,this.y=0,this.target=t.target??null,this.deadzone=t.deadzone??null,this.lerp=t.lerp??.1,this.zoom=t.zoom??1,this.bounds=t.bounds??null,this.viewportWidth=t.viewportWidth??800,this.viewportHeight=t.viewportHeight??600,this.offsetX=t.offsetX??0,this.offsetY=t.offsetY??0,this._shakeIntensity=0,this._shakeDuration=0,this._shakeTime=0,this._shakeOffsetX=0,this._shakeOffsetY=0,this._initialX=this.x,this._initialY=this.y}update(t){if(!this.target)return;const e=this.target.x+this.offsetX,i=this.target.y+this.offsetY,s=this.x+this.viewportWidth/2,n=this.y+this.viewportHeight/2;let o=this.x,r=this.y;if(this.deadzone){const t=this.deadzone.width/2,a=this.deadzone.height/2;e<s-t?o=e+t-this.viewportWidth/2:e>s+t&&(o=e-t-this.viewportWidth/2),i<n-a?r=i+a-this.viewportHeight/2:i>n+a&&(r=i-a-this.viewportHeight/2)}else o=e-this.viewportWidth/2,r=i-this.viewportHeight/2;if(this.x+=(o-this.x)*this.lerp,this.y+=(r-this.y)*this.lerp,this.bounds){const t=this.bounds.maxX-this.viewportWidth,e=this.bounds.maxY-this.viewportHeight;this.x=Math.max(this.bounds.minX,Math.min(this.x,t)),this.y=Math.max(this.bounds.minY,Math.min(this.y,e))}this._updateShake(t)}_updateShake(t){if(this._shakeDuration>0&&this._shakeTime<this._shakeDuration){this._shakeTime+=t;const e=1-this._shakeTime/this._shakeDuration;this._shakeOffsetX=2*(Math.random()-.5)*this._shakeIntensity*e,this._shakeOffsetY=2*(Math.random()-.5)*this._shakeIntensity*e,this._shakeTime>=this._shakeDuration&&(this._shakeOffsetX=0,this._shakeOffsetY=0,this._shakeDuration=0,this._shakeTime=0)}}getOffset(){return{x:this.x+this._shakeOffsetX,y:this.y+this._shakeOffsetY}}setPosition(t,e){return this.x=t,this.y=e,this}setTarget(t){return this.target=t,this}shake(t,e){return this._shakeIntensity=t,this._shakeDuration=e,this._shakeTime=0,this}stopShake(){return this._shakeIntensity=0,this._shakeDuration=0,this._shakeTime=0,this._shakeOffsetX=0,this._shakeOffsetY=0,this}isVisible(t){if(!t)return!1;const e=this.x+this.viewportWidth,i=this.y+this.viewportHeight,s=t.x+(t.width||0),n=t.y+(t.height||0);return!(t.x>e||s<this.x||t.y>i||n<this.y)}screenToWorld(t,e){return{x:t/this.zoom+this.x,y:e/this.zoom+this.y}}worldToScreen(t,e){return{x:(t-this.x)*this.zoom,y:(e-this.y)*this.zoom}}getWorldBounds(){return{x:this.x,y:this.y,width:this.viewportWidth/this.zoom,height:this.viewportHeight/this.zoom}}reset(){return this.x=this._initialX,this.y=this._initialY,this.stopShake(),this}isShaking(){return this._shakeDuration>0&&this._shakeTime<this._shakeDuration}}class It{static symmetric(t,e,i,s,n=1,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+(Math.random()-.5)*i*n,y:r+(Math.random()-.5)*s*n}}static pointInBox(t,e,i,s,n="topleft"){return"centered"===n?{x:t+(Math.random()-.5)*i,y:e+(Math.random()-.5)*s}:{x:t+Math.random()*i,y:e+Math.random()*s}}static centered(t,e,i,s,n=50,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+2*(Math.random()-.5)*n,y:r+2*(Math.random()-.5)*n}}static gaussian(t,e,i,s,n=40,o="topleft"){const r="centered"===o?e:e+s/2;return{x:("centered"===o?t:t+i/2)+It._gaussian(0,n),y:r+It._gaussian(0,n)}}static radial(t,e,i,s,n=100,o="topleft"){const r="centered"===o?t:t+i/2,a="centered"===o?e:e+s/2,h=Math.random()*Math.PI*2,l=Math.random()*n;return{x:r+Math.cos(h)*l,y:a+Math.sin(h)*l}}static pick(t){return t[Math.floor(Math.random()*t.length)]}static pickOther(t,e){const i=t.filter(t=>t!==e);if(0!==i.length)return It.pick(i)}static float(t,e){return t+Math.random()*(e-t)}static int(t,e){return Math.floor(It.float(t,e+1))}static chance(t=.5){return Math.random()<t}static coin(){return Math.random()<.5}static _gaussian(t=0,e=1){let i=1-Math.random(),s=1-Math.random();return t+e*Math.sqrt(-2*Math.log(i))*Math.cos(2*Math.PI*s)}}class Et{constructor(t,e=0){this.real=t,this.imag=e}static fromPolar(t,e){return new Et(t*Math.cos(e),t*Math.sin(e))}add(t){return new Et(this.real+t.real,this.imag+t.imag)}subtract(t){return new Et(this.real-t.real,this.imag-t.imag)}multiply(t){return new Et(this.real*t.real-this.imag*t.imag,this.real*t.imag+this.imag*t.real)}divide(t){return new Et(this.real/t,this.imag/t)}scale(t){return new Et(this.real*t,this.imag*t)}abs(){return Math.sqrt(this.real*this.real+this.imag*this.imag)}}class Ft{static applyColorScheme(t,e,i,s,n,o){const r=(null==e?void 0:e.data)||[];for(let 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),v=r<u?1:-1,y=c<d?1:-1;let _=g-m;for(;f>=0&&f<t&&p>=0&&p<e&&(a[p*t+f]=255),f!==u||p!==d;){const t=2*_;t>-m&&(_-=m,f+=v),t<g&&(_+=g,p+=y)}},u=(t,e,i,s,n)=>{if(n<=0)return;const o=i-t,r=s-e,a=i+r,h=s-o,l=t+r,d=e-o;((t,e,i,s,n,o,r,a)=>{c(t,e,i,s),c(i,s,n,o),c(n,o,r,a),c(r,a,t,e)})(t,e,i,s,a,h,l,d);const f=Math.PI/4,p=.7*Math.sqrt(o*o+r*r),g=p*Math.cos(Math.atan2(r,o)-f),m=p*Math.sin(Math.atan2(r,o)-f),v=.7*Math.sqrt(o*o+r*r),y=l,_=d,x=y+v*Math.cos(Math.atan2(r,o)+f),b=_+v*Math.sin(Math.atan2(r,o)+f);u(a,h,a+g,h+m,n-1),u(y,_,x,b,n-1)},d=Math.min(i,12);return u(-.5,0,.5,0,d),a}static mandelbrot(t,e,i=100,s=-2.5,n=1,o=-1.5,r=1.5){const a=new Uint8Array(t*e),h=(n-s)/t,l=(r-o)/e;for(let 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),v=r<u?1:-1,y=c<d?1:-1;let _=g-m;for(;f>=0&&f<t&&p>=0&&p<e&&(a[p*t+f]=255),f!==u||p!==d;){const t=2*_;t>-m&&(_-=m,f+=v),t<g&&(_+=g,p+=y)}})(i,s,n,o);const u=(n-i)/3,d=(o-s)/3,f=i+u,p=s+d,g=i+2*u,m=s+2*d,v=Math.PI/3,y=f+u*Math.cos(v)-d*Math.sin(v),_=p+u*Math.sin(v)+d*Math.cos(v);c(i,s,f,p,r-1),c(f,p,y,_,r-1),c(y,_,g,m,r-1),c(g,m,n,o,r-1)},u=Math.min(i,10),d=3*Math.sqrt(3)/2,f=[0,-d/2+.5],p=[-1.5,d/2+.5],g=[1.5,d/2+.5];return c(f[0],f[1],p[0],p[1],u),c(p[0],p[1],g[0],g[1],u),c(g[0],g[1],f[0],f[1],u),a}}_t(Ft,"types",{MANDELBROT:"mandelbrot",TRICORN:"tricorn",PHOENIX:"phoenix",JULIA:"julia",SIERPINSKI:"sierpinski",SCARPET:"sierpinskiCarpet",BARNSEY_FERN:"barnsleyFern",KOCH:"koch",PYTHAGORAS_TREE:"pythagorasTree",NEWTON:"newton",LYAPUNOV:"lyapunov"}),_t(Ft,"colors",{FUTURISTIC:"futuristic",RAINBOW:"rainbow",GRAYSCALE:"grayscale",TOPOGRAPHIC:"topographic",FIRE:"fire",OCEAN:"ocean",ELECTRIC:"electric",BINARY:"binary",HISTORIC:"historic"});const Ot=class{static seed(t){t>0&&t<1&&(t*=65536),(t=Math.floor(t))<256&&(t|=t<<8);for(let e=0;e<256;e++){let r;r=1&e?bt(this,s)[e]^255&t:bt(this,s)[e]^t>>8&255,bt(this,n)[e]=bt(this,n)[e+256]=r,bt(this,o)[e]=bt(this,o)[e+256]=bt(this,i)[r%12]}}static simplex2(t,e){let i,s,h;const l=(t+e)*bt(this,r),c=Math.floor(t+l),u=Math.floor(e+l),d=(c+u)*bt(this,a),f=t-c+d,p=e-u+d;let g,m;f>p?(g=1,m=0):(g=0,m=1);const v=f-g+bt(this,a),y=p-m+bt(this,a),_=f-1+2*bt(this,a),x=p-1+2*bt(this,a),b=255&c,w=255&u,M=bt(this,o)[b+bt(this,n)[w]],S=bt(this,o)[b+g+bt(this,n)[w+m]],C=bt(this,o)[b+1+bt(this,n)[w+1]];let T=.5-f*f-p*p;T<0?i=0:(T*=T,i=T*T*M.dot2(f,p));let k=.5-v*v-y*y;k<0?s=0:(k*=k,s=k*k*S.dot2(v,y));let P=.5-_*_-x*x;return P<0?h=0:(P*=P,h=P*P*C.dot2(_,x)),70*(i+s+h)}static simplex3(t,e,i){let s,r,a,c;const u=(t+e+i)*bt(this,h),d=Math.floor(t+u),f=Math.floor(e+u),p=Math.floor(i+u),g=(d+f+p)*bt(this,l),m=t-d+g,v=e-f+g,y=i-p+g;let _,x,b,w,M,S;m>=v?v>=y?(_=1,x=0,b=0,w=1,M=1,S=0):m>=y?(_=1,x=0,b=0,w=1,M=0,S=1):(_=0,x=0,b=1,w=1,M=0,S=1):v<y?(_=0,x=0,b=1,w=0,M=1,S=1):m<y?(_=0,x=1,b=0,w=0,M=1,S=1):(_=0,x=1,b=0,w=1,M=1,S=0);const C=m-_+bt(this,l),T=v-x+bt(this,l),k=y-b+bt(this,l),P=m-w+2*bt(this,l),R=v-M+2*bt(this,l),A=y-S+2*bt(this,l),z=m-1+3*bt(this,l),D=v-1+3*bt(this,l),B=y-1+3*bt(this,l),I=255&d,E=255&f,F=255&p,O=bt(this,o)[I+bt(this,n)[E+bt(this,n)[F]]],L=bt(this,o)[I+_+bt(this,n)[E+x+bt(this,n)[F+b]]],Y=bt(this,o)[I+w+bt(this,n)[E+M+bt(this,n)[F+S]]],X=bt(this,o)[I+1+bt(this,n)[E+1+bt(this,n)[F+1]]];let W=.6-m*m-v*v-y*y;W<0?s=0:(W*=W,s=W*W*O.dot3(m,v,y));let H=.6-C*C-T*T-k*k;H<0?r=0:(H*=H,r=H*H*L.dot3(C,T,k));let U=.6-P*P-R*R-A*A;U<0?a=0:(U*=U,a=U*U*Y.dot3(P,R,A));let G=.6-z*z-D*D-B*B;return G<0?c=0:(G*=G,c=G*G*X.dot3(z,D,B)),32*(s+r+a+c)}static perlin2(t,e){const i=Math.floor(t),s=Math.floor(e);t-=i,e-=s;const r=255&i,a=255&s,h=bt(this,o)[r+bt(this,n)[a]].dot2(t,e),l=bt(this,o)[r+bt(this,n)[a+1]].dot2(t,e-1),f=bt(this,o)[r+1+bt(this,n)[a]].dot2(t-1,e),p=bt(this,o)[r+1+bt(this,n)[a+1]].dot2(t-1,e-1),g=St(this,c,u).call(this,t);return St(this,c,d).call(this,St(this,c,d).call(this,h,f,g),St(this,c,d).call(this,l,p,g),St(this,c,u).call(this,e))}static perlin3(t,e,i){const s=Math.floor(t),r=Math.floor(e),a=Math.floor(i);t-=s,e-=r,i-=a;const h=255&s,l=255&r,f=255&a,p=bt(this,o)[h+bt(this,n)[l+bt(this,n)[f]]].dot3(t,e,i),g=bt(this,o)[h+bt(this,n)[l+bt(this,n)[f+1]]].dot3(t,e,i-1),m=bt(this,o)[h+bt(this,n)[l+1+bt(this,n)[f]]].dot3(t,e-1,i),v=bt(this,o)[h+bt(this,n)[l+1+bt(this,n)[f+1]]].dot3(t,e-1,i-1),y=bt(this,o)[h+1+bt(this,n)[l+bt(this,n)[f]]].dot3(t-1,e,i),_=bt(this,o)[h+1+bt(this,n)[l+bt(this,n)[f+1]]].dot3(t-1,e,i-1),x=bt(this,o)[h+1+bt(this,n)[l+1+bt(this,n)[f]]].dot3(t-1,e-1,i),b=bt(this,o)[h+1+bt(this,n)[l+1+bt(this,n)[f+1]]].dot3(t-1,e-1,i-1),w=St(this,c,u).call(this,t),M=St(this,c,u).call(this,e),S=St(this,c,u).call(this,i);return St(this,c,d).call(this,St(this,c,d).call(this,St(this,c,d).call(this,p,y,w),St(this,c,d).call(this,g,_,w),S),St(this,c,d).call(this,St(this,c,d).call(this,m,x,w),St(this,c,d).call(this,v,b,w),S),M)}};e=new WeakMap,i=new WeakMap,s=new WeakMap,n=new WeakMap,o=new WeakMap,r=new WeakMap,a=new WeakMap,h=new WeakMap,l=new WeakMap,c=new WeakSet,u=function(t){return t*t*t*(t*(6*t-15)+10)},d=function(t,e,i){return(1-i)*t+i*e},wt(Ot,c),wt(Ot,e,class{constructor(t,e,i){this.x=t,this.y=e,this.z=i}dot2(t,e){return this.x*t+this.y*e}dot3(t,e,i){return this.x*t+this.y*e+this.z*i}}),wt(Ot,i,[new(bt(Ot,e))(1,1,0),new(bt(Ot,e))(-1,1,0),new(bt(Ot,e))(1,-1,0),new(bt(Ot,e))(-1,-1,0),new(bt(Ot,e))(1,0,1),new(bt(Ot,e))(-1,0,1),new(bt(Ot,e))(1,0,-1),new(bt(Ot,e))(-1,0,-1),new(bt(Ot,e))(0,1,1),new(bt(Ot,e))(0,-1,1),new(bt(Ot,e))(0,1,-1),new(bt(Ot,e))(0,-1,-1)]),wt(Ot,s,[151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]),wt(Ot,n,new Array(512)),wt(Ot,o,new Array(512)),wt(Ot,r,.5*(Math.sqrt(3)-1)),wt(Ot,a,(3-Math.sqrt(3))/6),wt(Ot,h,1/3),wt(Ot,l,1/6),Ot.seed(0);let Lt=Ot;function Yt(t=800,e=800,i){const{divisions:s=5,zoomType:n="in",color1:o=[255,0,0,255],color2:r=[0,0,255,255],color3:a=[0,0,0,255],backgroundColor:h=[255,255,255,255]}=i||{},l=new Uint8ClampedArray(t*e*4);for(let _=0;_<l.length;_+=4)l[_]=h[0],l[_+1]=h[1],l[_+2]=h[2],l[_+3]=h[3]||255;const c="in"===n?1:2,u=Math.max(t,e),d=u/c,f=u/c,p=.5*c,g=.5*c,m=(Math.sqrt(5)+1)/2;let v=[];for(let _=0;_<10;_++){const t=Et.fromPolar(1,(2*_-1)*Math.PI/10),e=Et.fromPolar(1,(2*_+1)*Math.PI/10);_%2==0?v.push(["thin",new Et(0),e,t]):v.push(["thin",new Et(0),t,e])}for(let _=0;_<s;_++){const t=[];for(const[e,i,s,n]of v)if("thin"===e){const e=i.add(s.subtract(i).scale(1/m));t.push(["thin",n,e,s]),t.push(["thicc",e,n,i])}else{const e=s.add(i.subtract(s).scale(1/m)),o=s.add(n.subtract(s).scale(1/m));t.push(["thicc",o,n,i]),t.push(["thicc",e,o,s]),t.push(["thin",o,e,i])}v=t}function y(i){return{x:Math.floor((i.real*d+p*d)*t/u),y:Math.floor((i.imag*f+g*f)*e/u)}}for(const[_,x,b,w]of v){Xt(l,y(x),y(b),y(w),"thin"===_?o:r,t,e)}if(a&&a[3]>0)for(const[_,x,b,w]of v){const i=y(x),s=y(b),n=y(w);Ut(l,i,s,a,t,e),Ut(l,s,n,a,t,e),Ut(l,n,i,a,t,e)}return l}function Xt(t,e,i,s,n,o,r){e.y>i.y&&([e,i]=[i,e]),e.y>s.y&&([e,s]=[s,e]),i.y>s.y&&([i,s]=[s,i]);const a=n[0],h=n[1],l=n[2],c=n[3]||255;if(i.y===s.y)Wt(t,e,i,s,a,h,l,c,o,r);else if(e.y===i.y)Ht(t,e,i,s,a,h,l,c,o,r);else{const n={x:Math.floor(e.x+(i.y-e.y)/(s.y-e.y)*(s.x-e.x)),y:i.y};Wt(t,e,i,n,a,h,l,c,o,r),Ht(t,i,n,s,a,h,l,c,o,r)}}function Wt(t,e,i,s,n,o,r,a,h,l){const c=(i.x-e.x)/(i.y-e.y||1),u=(s.x-e.x)/(s.y-e.y||1);let d=e.x,f=e.x;for(let 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 Ut(t,e,i,s,n,o){const r=s[0],a=s[1],h=s[2],l=s[3]||255;let c=e.x,u=e.y,d=i.x,f=i.y;const p=Math.abs(d-c),g=Math.abs(f-u),m=c<d?1:-1,v=u<f?1:-1;let y=p-g;for(;;){if(c>=0&&c<n&&u>=0&&u<o){const e=4*(u*n+c);if(e>=0&&e<t.length-3){const i=l/255;t[e]=Math.round(t[e]*(1-i)+r*i),t[e+1]=Math.round(t[e+1]*(1-i)+a*i),t[e+2]=Math.round(t[e+2]*(1-i)+h*i),t[e+3]=255}}if(c===d&&u===f)break;const e=2*y;e>-g&&(y-=g,c+=m),e<p&&(y+=p,u+=v)}}f=new WeakMap,p=new WeakMap,g=new WeakMap,m=new WeakMap,v=new WeakMap;let Gt=class t{constructor(t,e={}){wt(this,f),wt(this,p),wt(this,g),wt(this,m),wt(this,v),Mt(this,f,t.map(t=>[...t])),Mt(this,p,t.length),Mt(this,g,e.name||""),Mt(this,m,e.signature||null),Mt(this,v,e.coordinates||null)}static minkowski(){return new t([[-1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],{name:"Minkowski",signature:[-1,1,1,1],coordinates:["t","x","y","z"]})}static schwarzschild(e,i,s=Math.PI/2){e<=i&&(e=1.001*i);const n=1-i/e,o=Math.sin(s);return new t([[-n,0,0,0],[0,1/n,0,0],[0,0,e*e,0],[0,0,0,e*e*o*o]],{name:"Schwarzschild",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static schwarzschildContravariant(e,i,s=Math.PI/2){e<=i&&(e=1.001*i);const n=1-i/e,o=Math.sin(s);return new t([[-1/n,0,0,0],[0,n,0,0],[0,0,1/(e*e),0],[0,0,0,1/(e*e*o*o)]],{name:"Schwarzschild (Contravariant)",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static kerr(e,i,s,n){const o=(n=Math.min(Math.abs(n),s))*n,r=e*e,a=Math.cos(i),h=Math.sin(i),l=h*h,c=a*a,u=r+o*c,d=r-2*s*e+o,f=s+Math.sqrt(Math.max(0,s*s-o));if(e<=f){const r=(e=1.001*f)*e,a=r+o*c,h=r-2*s*e+o;return t._buildKerrMetric(e,i,s,n,a,h,l)}return t._buildKerrMetric(e,i,s,n,u,d,l)}static kerrContravariant(e,i,s,n){const o=(n=Math.min(Math.abs(n),s))*n,r=e*e,a=Math.cos(i),h=Math.sin(i),l=h*h,c=r+o*a*a,u=r-2*s*e+o,d=s+Math.sqrt(Math.max(0,s*s-o));e<=d&&(e=1.001*d);const f=-(Math.pow(r+o,2)-o*u*l)/(c*u),p=-2*s*n*e/(c*u);return new t([[f,0,0,p],[0,u/c,0,0],[0,0,1/c,0],[p,0,0,(u-o*l)/(c*u*l)]],{name:"Kerr (Contravariant)",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static _buildKerrMetric(e,i,s,n,o,r,a){const h=n*n,l=-2*s*n*e*a/o;return new t([[-(1-2*s*e/o),0,0,l],[0,o/r,0,0],[0,0,o,0],[l,0,0,(e*e+h+2*s*h*e*a/o)*a]],{name:"Kerr",signature:[-1,1,1,1],coordinates:["t","r","θ","φ"]})}static kerrHorizonRadius(t,e,i=!1){const s=t*t-e*e;if(s<0)return NaN;const n=Math.sqrt(s);return i?t-n:t+n}static kerrErgosphereRadius(t,e,i){const s=Math.cos(i),n=t*t-e*e*s*s;return n<0?NaN:t+Math.sqrt(n)}static kerrISCO(t,e,i=!0){const s=e/t,n=i?1:-1,o=1+Math.cbrt(1-s*s)*(Math.cbrt(1+s)+Math.cbrt(1-s)),r=Math.sqrt(3*s*s+o*o);return t*(3+r-n*Math.sqrt((3-o)*(3+o+2*r)))}static kerrFrameDraggingOmega(e,i,s,n){const o=t.kerr(e,i,s,n),r=o.get(0,3),a=o.get(3,3);return Math.abs(a)<1e-10?0:-r/a}static kerrEffectivePotential(t,e,i,s,n){if(n<=0)return 1/0;const o=n*n;return-t/n+(s*s-e*e*(i*i-1))/(2*o)+-t*Math.pow(s-e*i,2)/(o*n)}static diagonal(e,i={}){const s=e.length,n=[];for(let t=0;t<s;t++){n[t]=[];for(let i=0;i<s;i++)n[t][i]=t===i?e[t]:0}return new t(n,i)}static identity(e=4){const i=new Array(e).fill(1);return t.diagonal(i,{name:"Identity"})}static zero(e=4){const i=[];for(let t=0;t<e;t++)i[t]=new Array(e).fill(0);return new t(i,{name:"Zero"})}get(t,e){return bt(this,f)[t][e]}set(e,i,s){const n=bt(this,f).map(t=>[...t]);return n[e][i]=s,new t(n,{name:bt(this,g),signature:bt(this,m),coordinates:bt(this,v)})}getDiagonal(){const t=[];for(let e=0;e<bt(this,p);e++)t.push(bt(this,f)[e][e]);return t}get dimension(){return bt(this,p)}get name(){return bt(this,g)}get signature(){return bt(this,m)}get coordinates(){return bt(this,v)}add(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++)i[t][s]=bt(this,f)[t][s]+e.get(t,s)}return new t(i)}subtract(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++)i[t][s]=bt(this,f)[t][s]-e.get(t,s)}return new t(i)}scale(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++)i[t][s]=bt(this,f)[t][s]*e}return new t(i)}multiply(e){const i=[];for(let t=0;t<bt(this,p);t++){i[t]=[];for(let s=0;s<bt(this,p);s++){let n=0;for(let i=0;i<bt(this,p);i++)n+=bt(this,f)[t][i]*e.get(i,s);i[t][s]=n}}return new t(i)}transpose(){const e=[];for(let t=0;t<bt(this,p);t++){e[t]=[];for(let i=0;i<bt(this,p);i++)e[t][i]=bt(this,f)[i][t]}return new t(e,{name:bt(this,g)?`${bt(this,g)}ᵀ`:"",signature:bt(this,m),coordinates:bt(this,v)})}inverse(){const e=bt(this,p);if(this.isDiagonal()){const e=this.getDiagonal().map(t=>{if(Math.abs(t)<1e-15)throw new Error("Diagonal matrix is singular, cannot compute inverse");return 1/t});return t.diagonal(e,{name:bt(this,g)?`${bt(this,g)}⁻¹`:"",signature:bt(this,m),coordinates:bt(this,v)})}const i=[];for(let t=0;t<e;t++){i[t]=[];for(let s=0;s<e;s++)i[t][s]=bt(this,f)[t][s];for(let s=0;s<e;s++)i[t][e+s]=t===s?1:0}for(let t=0;t<e;t++){let s=t;for(let 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:bt(this,g)?`${bt(this,g)}⁻¹`:"",signature:bt(this,m),coordinates:bt(this,v)})}determinant(){const t=bt(this,p);if(this.isDiagonal())return this.getDiagonal().reduce((t,e)=>t*e,1);if(2===t)return bt(this,f)[0][0]*bt(this,f)[1][1]-bt(this,f)[0][1]*bt(this,f)[1][0];if(3===t){const t=bt(this,f);return t[0][0]*(t[1][1]*t[2][2]-t[1][2]*t[2][1])-t[0][1]*(t[1][0]*t[2][2]-t[1][2]*t[2][0])+t[0][2]*(t[1][0]*t[2][1]-t[1][1]*t[2][0])}const e=bt(this,f).map(t=>[...t]);let i=1,s=0;for(let n=0;n<t;n++){let o=n;for(let i=n+1;i<t;i++)Math.abs(e[i][n])>Math.abs(e[o][n])&&(o=i);if(o!==n&&([e[n],e[o]]=[e[o],e[n]],s++),Math.abs(e[n][n])<1e-10)return 0;i*=e[n][n];for(let i=n+1;i<t;i++){e[i][n]/=e[n][n];for(let s=n+1;s<t;s++)e[i][s]-=e[i][n]*e[n][s]}}return s%2==0?i:-i}trace(){let t=0;for(let e=0;e<bt(this,p);e++)t+=bt(this,f)[e][e];return t}isDiagonal(t=1e-10){for(let e=0;e<bt(this,p);e++)for(let i=0;i<bt(this,p);i++)if(e!==i&&Math.abs(bt(this,f)[e][i])>t)return!1;return!0}isSymmetric(t=1e-10){for(let e=0;e<bt(this,p);e++)for(let i=e+1;i<bt(this,p);i++)if(Math.abs(bt(this,f)[e][i]-bt(this,f)[i][e])>t)return!1;return!0}static christoffel(e,i,s=.001){const n=e(i);if("Schwarzschild"===n.name){const e=i._rs||2;return t.schwarzschildChristoffel(i[1],e,i[2])}const o=[],r=n.inverse(),a=[];for(let t=0;t<4;t++){const n=[...i],o=[...i];n[t]+=s,o[t]-=s;const r=e(n),h=e(o);a[t]=[];for(let e=0;e<4;e++){a[t][e]=[];for(let i=0;i<4;i++)a[t][e][i]=(r.get(e,i)-h.get(e,i))/(2*s)}}for(let t=0;t<4;t++){o[t]=[];for(let e=0;e<4;e++){o[t][e]=[];for(let i=0;i<4;i++){let s=0;for(let n=0;n<4;n++){const o=r.get(t,n);Math.abs(o)<1e-15||(s+=o*(a[e][i][n]+a[i][e][n]-a[n][e][i])/2)}o[t][e][i]=s}}}return o}static schwarzschildChristoffel(t,e,i){const s=[];for(let 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<bt(this,p);e++)for(let i=0;i<bt(this,p);i++)t.push(bt(this,f)[e][i]);return t}toMatrix(){return bt(this,f).map(t=>[...t])}toString(t=3){return(bt(this,g)?`${bt(this,g)} Tensor:\n`:"")+bt(this,f).map(e=>`[ ${e.map(e=>e.toFixed(t).padStart(10)).join(" ")} ]`).join("\n")}toLatex(t=3){return`\\begin{pmatrix}\n${bt(this,f).map(e=>e.map(e=>e.toFixed(t)).join(" & ")).join(" \\\\\n")}\n\\end{pmatrix}`}};const Nt={tokens:{unaryNot:["!","~","¬","NOT"],and:["&","∧","AND"],nand:["NAND"],or:["|","∨","OR"],nor:["NOR"],xor:["^","⊕","XOR"],xnor:["XNOR"]},precedence:{OR:1,NOR:1,XOR:2,XNOR:2,AND:3,NAND:3,NOT:4},constants:{true:["1","TRUE"],false:["0","FALSE"]}};function qt(t){return Boolean(t)}function Zt(t){return String(t).toUpperCase()}function Vt(t){const e=Zt(t);if(Nt.tokens.unaryNot.map(Zt).includes(e))return"NOT";if(Nt.tokens.and.map(Zt).includes(e))return"AND";if(Nt.tokens.nand.map(Zt).includes(e))return"NAND";if(Nt.tokens.or.map(Zt).includes(e))return"OR";if(Nt.tokens.nor.map(Zt).includes(e))return"NOR";if(Nt.tokens.xor.map(Zt).includes(e))return"XOR";if(Nt.tokens.xnor.map(Zt).includes(e))return"XNOR";throw new Error(`[BooleanAlgebra] Unknown operator "${t}"`)}function $t(t){return Nt.precedence[t]??0}function jt(t){let e=0;const i=()=>t[e],s=()=>t[e++];function n(){const t=s();if(!t)throw new Error("[BooleanAlgebra] Unexpected end of input");if("const"===t.type){const e=Zt(t.value);return{type:"const",value:Nt.constants.true.includes(e)}}if("ident"===t.type)return{type:"var",name:t.value};if("lp"===t.type){const t=o(0),e=s();if(!e||"rp"!==e.type)throw new Error("[BooleanAlgebra] Missing closing ')'");return t}if("op"===t.type){if("NOT"!==Vt(t.value))throw new Error(`[BooleanAlgebra] Unexpected binary operator "${t.value}"`);return{type:"not",left:n()}}throw new Error(`[BooleanAlgebra] Unexpected token "${t.type}"`)}function o(t){let e=n();for(;;){const n=i();if(!n||"op"!==n.type)break;const r=Vt(n.value);if("NOT"===r)break;const a=$t(r);if(a<t)break;s();e={type:"AND"===r?"and":"OR"===r?"or":"XOR"===r?"xor":"NAND"===r?"nand":"NOR"===r?"nor":"xnor",left:e,right:o(a+1)}}return e}const r=o(0);if(e<t.length)throw new Error("[BooleanAlgebra] Unexpected trailing tokens");return r}function Kt(t,e){switch(t.type){case"const":return Boolean(t.value);case"var":return qt((null==e?void 0:e[t.name])??!1);case"not":return!Kt(t.left,e);case"and":return Kt(t.left,e)&&Kt(t.right,e);case"nand":return!(Kt(t.left,e)&&Kt(t.right,e));case"or":return Kt(t.left,e)||Kt(t.right,e);case"nor":return!(Kt(t.left,e)||Kt(t.right,e));case"xor":{const i=Kt(t.left,e),s=Kt(t.right,e);return i&&!s||!i&&s}case"xnor":return Kt(t.left,e)===Kt(t.right,e);default:throw new Error(`[BooleanAlgebra] Unknown AST node type "${t.type}"`)}}function Jt(t,e){t&&("var"===t.type&&t.name&&e.add(t.name),t.left&&Jt(t.left,e),t.right&&Jt(t.right,e))}function Qt(t){const e=1<<t,i=new Array(e);for(let s=0;s<e;s++)i[s]=s^s>>1;return i}class te{static and(t,e){return qt(t)&&qt(e)}static nand(t,e){return!(qt(t)&&qt(e))}static or(t,e){return qt(t)||qt(e)}static nor(t,e){return!(qt(t)||qt(e))}static xor(t,e){const i=qt(t),s=qt(e);return i&&!s||!i&&s}static xnor(t,e){return qt(t)===qt(e)}static not(t){return!qt(t)}static parse(t){return jt(function(t){const e=[],i=String(t??"");let s=0;const n=t=>" "===t||"\n"===t||"\t"===t||"\r"===t,o=t=>t>="A"&&t<="Z"||t>="a"&&t<="z"||"_"===t,r=t=>o(t)||t>="0"&&t<="9";for(;s<i.length;){const t=i[s];if(n(t))s++;else if("("!==t)if(")"!==t){if("!"!==t&&"~"!==t&&"¬"!==t&&"&"!==t&&"∧"!==t&&"|"!==t&&"∨"!==t&&"^"!==t&&"⊕"!==t){if(o(t)||t>="0"&&t<="9"){let t=s+1;for(;t<i.length&&r(i[t]);)t++;const n=i.slice(s,t),o=Zt(n);Nt.constants.true.includes(o)||Nt.constants.false.includes(o)?e.push({type:"const",value:o}):Nt.tokens.unaryNot.includes(o)||Nt.tokens.and.includes(o)||Nt.tokens.nand.includes(o)||Nt.tokens.or.includes(o)||Nt.tokens.nor.includes(o)||Nt.tokens.xor.includes(o)||Nt.tokens.xnor.includes(o)?e.push({type:"op",value:o}):e.push({type:"ident",value:n}),s=t;continue}throw new Error(`[BooleanAlgebra] Unexpected character "${t}" at ${s}`)}e.push({type:"op",value:t}),s++}else e.push({type:"rp",value:t}),s++;else e.push({type:"lp",value:t}),s++}return e}(t))}static evaluate(t,e={}){return Kt("string"==typeof t?te.parse(t):t,e)}static variables(t){const e="string"==typeof t?te.parse(t):t,i=new Set;return Jt(e,i),[...i].sort((t,e)=>t.localeCompare(e))}static grayCode(t){return Qt(t)}static truthTable(t,e,i={}){const s="string"==typeof t?te.parse(t):t,n=e&&e.length>0?[...e]:te.variables(s),o=n.length,r=1<<o,a="gray"===i.order?"gray":"binary",h=("gray"===a?Qt(o):Array.from({length:r},(t,e)=>e)).map(t=>{const e={};for(let i=0;i<o;i++){const s=1<<o-1-i;e[n[i]]=Boolean(t&s)}return{index:t,inputs:e,output:Kt(s,e)}});return{variables:n,order:a,rows:h}}}const ee={CONTINUOUS:"continuous",ITERATIVE:"iterative"},ie={TWO_D:2,THREE_D:3},se={lorenz:{name:"Lorenz",type:ee.CONTINUOUS,dimension:ie.THREE_D,equations:["dx/dt = σ(y - x)","dy/dt = x(ρ - z) - y","dz/dt = xy - βz"],defaultParams:{sigma:10,rho:28,beta:8/3},defaultDt:.01,derivatives(t,e=this.defaultParams){const{sigma:i,rho:s,beta:n}={...this.defaultParams,...e},{x:o,y:r,z:a}=t;return{dx:i*(r-o),dy:o*(s-a)-r,dz:o*r-n*a}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},dadras:{name:"Dadras",type:ee.CONTINUOUS,dimension:ie.THREE_D,equations:["dx/dt = y - ax + byz","dy/dt = cy - xz + z","dz/dt = dxy - ez"],defaultParams:{a:3,b:2.7,c:1.7,d:2,e:9},defaultDt:.005,derivatives(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o,e:r}={...this.defaultParams,...e},{x:a,y:h,z:l}=t;return{dx:h-i*a+s*h*l,dy:n*h-a*l+l,dz:o*a*h-r*l}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},aizawa:{name:"Aizawa",type:ee.CONTINUOUS,dimension:ie.THREE_D,equations:["dx/dt = (z - b)x - dy","dy/dt = dx + (z - b)y","dz/dt = c + az - z³/3 - (x² + y²)(1 + ez) + fzx³"],defaultParams:{a:.95,b:.7,c:.6,d:3.5,e:.25,f:.1},defaultDt:.01,derivatives(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o,e:r,f:a}={...this.defaultParams,...e},{x:h,y:l,z:c}=t;return{dx:(c-s)*h-o*l,dy:o*h+(c-s)*l,dz:n+i*c-c*c*c/3-(h*h+l*l)*(1+r*c)+a*c*h*h*h}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},thomas:{name:"Thomas",type:ee.CONTINUOUS,dimension:ie.THREE_D,equations:["dx/dt = sin(y) - bx","dy/dt = sin(z) - by","dz/dt = sin(x) - bz"],defaultParams:{b:.208186},defaultDt:.1,derivatives(t,e=this.defaultParams){const{b:i}={...this.defaultParams,...e},{x:s,y:n,z:o}=t;return{dx:Math.sin(n)-i*s,dy:Math.sin(o)-i*n,dz:Math.sin(s)-i*o}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},clifford:{name:"Clifford",type:ee.ITERATIVE,dimension:ie.TWO_D,equations:["x_{n+1} = sin(a·y_n) + c·cos(a·x_n)","y_{n+1} = sin(b·x_n) + d·cos(b·y_n)"],defaultParams:{a:-1.4,b:1.6,c:1,d:.7},next(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o}={...this.defaultParams,...e},{x:r,y:a}=t;return{x:Math.sin(i*a)+n*Math.cos(i*r),y:Math.sin(s*r)+o*Math.cos(s*a)}},step(t,e,i=this.defaultParams){const s=this.next(t,i),n=s.x-t.x,o=s.y-t.y;return{position:s,velocity:{dx:n,dy:o,dz:0},speed:Math.sqrt(n*n+o*o)}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i)=>this.step(t,i,e)}},rossler:{name:"Rössler",type:ee.CONTINUOUS,dimension:ie.THREE_D,equations:["dx/dt = -y - z","dy/dt = x + ay","dz/dt = b + z(x - c)"],defaultParams:{a:.2,b:.2,c:5.7},defaultDt:.01,derivatives(t,e=this.defaultParams){const{a:i,b:s,c:n}={...this.defaultParams,...e},{x:o,y:r,z:a}=t;return{dx:-r-a,dy:o+i*r,dz:s+a*(o-n)}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},halvorsen:{name:"Halvorsen",type:ee.CONTINUOUS,dimension:ie.THREE_D,equations:["dx/dt = -ax - 4y - 4z - y²","dy/dt = -ay - 4z - 4x - z²","dz/dt = -az - 4x - 4y - x²"],defaultParams:{a:1.89},defaultDt:.005,derivatives(t,e=this.defaultParams){const{a:i}={...this.defaultParams,...e},{x:s,y:n,z:o}=t;return{dx:-i*s-4*n-4*o-n*n,dy:-i*n-4*o-4*s-o*o,dz:-i*o-4*s-4*n-s*s}},step(t,e=this.defaultDt,i=this.defaultParams){const s=this.derivatives(t,i),n=Math.sqrt(s.dx*s.dx+s.dy*s.dy+s.dz*s.dz);return{position:{x:t.x+s.dx*e,y:t.y+s.dy*e,z:t.z+s.dz*e},velocity:s,speed:n}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i=this.defaultDt)=>this.step(t,i,e)}},deJong:{name:"De Jong",type:ee.ITERATIVE,dimension:ie.TWO_D,equations:["x_{n+1} = sin(a·y_n) - cos(b·x_n)","y_{n+1} = sin(c·x_n) - cos(d·y_n)"],defaultParams:{a:-2.24,b:-.65,c:-.43,d:-2.43},next(t,e=this.defaultParams){const{a:i,b:s,c:n,d:o}={...this.defaultParams,...e},{x:r,y:a}=t;return{x:Math.sin(i*a)-Math.cos(s*r),y:Math.sin(n*r)-Math.cos(o*a)}},step(t,e,i=this.defaultParams){const s=this.next(t,i),n=s.x-t.x,o=s.y-t.y;return{position:s,velocity:{dx:n,dy:o,dz:0},speed:Math.sqrt(n*n+o*o)}},createStepper(t=this.defaultParams){const e={...this.defaultParams,...t};return(t,i)=>this.step(t,i,e)}}};function ne(t,e,i){return t<=e?0:Math.sqrt(8*i*(t-e))}function oe(t,e,i,s,n=5){if(t<=n||t>=e)return 0;return Math.exp(-t*s)*i}class re{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-re.easeOutBounce(1-t)}static easeInOutBounce(t){return t<.5?.5*re.easeInBounce(2*t):.5*re.easeOutBounce(2*t-1)+.5}}function ae(t,e,i){const s=Math.max(0,Math.min(1,(i-t)/(e-t)));return re.smoothstep(s)}function he(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=ae(s-l,s+.5*l,t),u=1-ae(n-.5*l,n+l,t),d=1-c-u;let f=0;return c>0&&(f+=(1-e)*o*r*c),u>0&&(f+=(0-e)*o*a*u),d>0&&(f+=(t-e)*o*h*d),Math.max(0,Math.min(1,e+f))}function le(t,e,i,s,n,o=1){if(i>=s)return 0;return(e-t)*n*Math.pow(1-i/s,o)}const ce={smoothingRadius:28},ue={restDensity:1.1,particleMass:1,pressureStiffness:1800,nearPressureStiffness:2.5,viscosity:.18,surfaceTension:0,maxForce:6e3},de={interactionRadius:34,pressure:12,diffusion:.08,drag:.04,buoyancy:260,neutralTemperature:.5,turbulence:16},fe={gravity:{x:0,y:820}},pe=1e-4;function ge(t={}){return{kernel:{...ce,...t.kernel||{}},fluid:{...ue,...t.fluid||{}},gas:{...de,...t.gas||{}},external:{...fe,...t.external||{}}}}const me={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 ve(t,e={},i){const s=ge(e).kernel.smoothingRadius,n=s*s,o=i??Se(t,s),r=t.length,a=new Float32Array(r),h=new Float32Array(r);for(let l=0;l<r;l++)a[l]=me.spikyPow2(0,s),h[l]=me.spikyPow3(0,s),Ce(l,t,o,n,(t,e,i,n)=>{const o=Math.sqrt(n);a[l]+=me.spikyPow2(o,s),h[l]+=me.spikyPow3(o,s)});return{densities:a,nearDensities:h}}function ye(t,e,i={}){const s=ge(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 _e(t,e={}){const i=ge(e),s=i.kernel.smoothingRadius,n=s*s,o=t.length,r=Se(t,s),{densities:a,nearDensities:h}=ve(t,i,r),{pressures:l,nearPressures:c}=ye(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],pe),Ce(d,t,r,n,(n,o,r,f)=>{if(n<=d)return;const p=Math.sqrt(f);if(p<pe||p>=s)return;const g=t[n],m=1/p,v=-o*m,y=-r*m,_=Math.max(a[n],pe),x=Math.max(h[n],pe),b=.5*(l[d]+l[n]),w=.5*(c[d]+c[n]),M=b*me.spikyPow2Derivative(p,s)/_+w*me.spikyPow3Derivative(p,s)/x,S=v*M,C=y*M;u[d].x+=S,u[d].y+=C,u[n].x-=S,u[n].y-=C;const T=me.poly6(f,s),k=i.fluid.viscosity*T,P=(g.vx-e.vx)*k,R=(g.vy-e.vy)*k;u[d].x+=P,u[d].y+=R,u[n].x-=P,u[n].y-=R})}return Me(u,i.fluid.maxForce),{forces:u,densities:a,pressures:l}}function xe(t,e={}){var i;const s=ge(e),n=s.gas.interactionRadius,o=n*n,r=t.length,a=Se(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=we(e,s),c=e.temperature??(null==(i=e.custom)?void 0:i.temperature)??s.gas.neutralTemperature;Ce(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=we(g,s),v=g.temperature??(null==(d=g.custom)?void 0:d.temperature)??s.gas.neutralTemperature,y=s.gas.pressure*(1-f/n),_=o*p*y,x=a*p*y;h[l].x+=_,h[l].y+=x,h[i].x-=_,h[i].y-=x;const b=s.gas.diffusion,w=(g.vx-e.vx)*b,M=(g.vy-e.vy)*b;h[l].x+=w*m,h[l].y+=M*m,h[i].x-=w*r,h[i].y-=M*r;const S=(c-v)*s.gas.buoyancy*.5;h[l].y-=S,h[i].y+=S})}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 Me(h,s.fluid.maxForce),{forces:h}}function be(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:re.lerp(t[o].x,e[o].x,i),y:re.lerp(t[o].y,e[o].y,i)};return n}function we(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 Me(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 Se(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 Ce(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 Te=class t{static disableAll(){t.enabledClasses=new Set,t.globalLevel=0}static disable(){t.enabled=!1}static enable(){t.enabled=!0}static setLevel(e){t.globalLevel=e}static enableFor(e){t.enabledClasses.add(e)}static disableFor(e){t.enabledClasses.delete(e)}static setOutput(e){t.output=e}constructor(t){this.className=t}static getLogger(e){return t.loggerz[e]||(t.loggerz[e]=new t(e)),t.loggerz[e]}_log(e,i,...s){t.enabled&&(t.globalLevel>=e||t.enabledClasses.has(this.className))&&t.output[i](`[${this.className}]`,...s)}log(...e){this._log(t.INFO,"log",...e)}warn(...e){this._log(t.WARN,"warn",...e)}error(...e){this._log(t.ERROR,"error",...e)}debug(...e){this._log(t.DEBUG,"log",...e)}table(...e){this._log(t.INFO,"table",...e)}groupCollapsed(e){t.enabled&&t.output.groupCollapsed(`[${this.className}] ${e}`)}groupEnd(){t.enabled&&t.output.groupEnd()}time(e){t.enabled&&t.output.time(`[${this.className}] ${e}`)}timeEnd(e){t.enabled&&t.output.timeEnd(`[${this.className}] ${e}`)}clear(){t.output.clear()}};_t(Te,"ERROR",1),_t(Te,"WARN",2),_t(Te,"INFO",3),_t(Te,"DEBUG",4),_t(Te,"globalLevel",Te.ERROR),_t(Te,"enabledClasses",new Set),_t(Te,"output",console),_t(Te,"enabled",!0),_t(Te,"loggerz",[]);let ke=Te;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 ke.getLogger(t.name||this.constructor.name)}}const Re=class t{static getInstance(){return t.instance||(t.instance=new t),t.instance}constructor(){this.createTab()}createTab(){this.tab=document.createElement("div"),Object.assign(this.tab.style,{position:"fixed",bottom:"0",left:"0",right:"0",height:"30px",backgroundColor:"#333",color:"#fff",padding:"5px",cursor:"pointer",fontFamily:"monospace",zIndex:"10000",display:"flex",justifyContent:"space-between",alignItems:"center"}),this.tab.innerText="Console";const t=document.createElement("div"),e=(t,e)=>{const i=document.createElement("button");return i.innerText=t,Object.assign(i.style,{marginLeft:"5px",padding:"2px 5px",fontFamily:"monospace",cursor:"pointer"}),i.onclick=e,i};this.paused=!1,this.scrollLock=!0,t.appendChild(e("Clear",()=>this.consoleArea.value="")),t.appendChild(e("Pause",()=>this.paused=!this.paused)),t.appendChild(e("Scroll Lock",()=>this.scrollLock=!this.scrollLock)),this.tab.appendChild(t),document.body.appendChild(this.tab),this.consoleArea=document.createElement("textarea"),Object.assign(this.consoleArea.style,{position:"fixed",bottom:"30px",left:"0",right:"0",height:"200px",display:"none",backgroundColor:"#111",color:"#0f0",fontFamily:"monospace",zIndex:"9999",padding:"10px",resize:"none"}),this.consoleArea.readOnly=!0,document.body.appendChild(this.consoleArea),this.tab.onclick=t=>{t.target===this.tab&&(this.consoleArea.style.display="none"===this.consoleArea.style.display?"block":"none")}}appendMessage(t,e,...i){if(this.paused)return;const s=`[${t.toUpperCase()}] ${e} ${i.join(" ")}\n`;this.consoleArea.value+=s,this.scrollLock&&(this.consoleArea.scrollTop=this.consoleArea.scrollHeight)}log(t,...e){this.appendMessage("log",t,...e)}warn(t,...e){this.appendMessage("warn",t,...e)}error(t,...e){this.appendMessage("error",t,...e)}table(t){const e=JSON.stringify(t,null,2);this.appendMessage("table",e)}groupCollapsed(t){this.appendMessage("group",`Group Start: ${t}`)}groupEnd(){this.appendMessage("group","Group End")}time(t){this[`time_${t}`]=performance.now()}timeEnd(t){const e=(performance.now()-this[`time_${t}`]).toFixed(2);this.appendMessage("time",`${t}: ${e} ms`)}};_t(Re,"instance");let Ae=Re;const ze=class t{static dropShadow(t,e,i=0,s=0){Ye.ctx.shadowColor=t,Ye.ctx.shadowBlur=e,Ye.ctx.shadowOffsetX=i,Ye.ctx.shadowOffsetY=s}static clearShadow(){Ye.ctx.shadowColor="rgba(0, 0, 0, 0)",Ye.ctx.shadowBlur=0,Ye.ctx.shadowOffsetX=0,Ye.ctx.shadowOffsetY=0}static setAlpha(t){Ye.ctx.globalAlpha=t}static setBlendMode(t){Ye.ctx.globalCompositeOperation=t}static clipRect(t,e,i,s){Ye.ctx.beginPath(),Ye.ctx.rect(t,e,i,s),Ye.ctx.clip()}static clipCircle(t,e,i){Ye.ctx.beginPath(),Ye.shapes.arc(t,e,i,0,2*Math.PI),Ye.ctx.clip()}static blurRegion(t,e,i,s,n){const o=Ye.ctx.filter;Ye.ctx.filter=`blur(${n}px)`;const r=Ye.ctx.getImageData(t,e,i,s);Ye.ctx.putImageData(r,t,e),Ye.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)),Ye.ctx.shadowColor=e,Ye.ctx.shadowBlur=t,Ye.ctx.shadowOffsetX=0,Ye.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(),Ye.ctx.shadowColor="rgba(0, 0, 0, 0)",Ye.ctx.shadowBlur=0,Ye.ctx.shadowOffsetX=0,Ye.ctx.shadowOffsetY=0,Ye.ctx.filter="none",Ye.ctx.globalAlpha=1,Ye.ctx.globalCompositeOperation="source-over"}};_t(ze,"_activeEffects",new Map),_t(ze,"_animationId",null);let De=ze;class Be{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=Ye.ctx;if(!p||!t)return;const g=s??(o?o.sw:t.width??t.videoWidth),m=n??(o?o.sh:t.height??t.videoHeight),v=-g*({left:0,center:.5,right:1}[r.split("-").pop()]??0),y=-m*({top:0,center:.5,bottom:1}[r.split("-")[0]]??0);if(p.save(),p.imageSmoothingEnabled=f,p.globalAlpha*=d,p.translate(e,i),a&&p.rotate(a),(c||u)&&p.scale(c?-1:1,u?-1:1),p.scale(h,l),o){const{sx:e,sy:i,sw:s,sh:n}=o;p.drawImage(t,e,i,s,n,v,y,g,m)}else p.drawImage(t,v,y,g,m);p.restore()}static blit(t,e,i,s,n){this.draw(t,e,i,{width:s,height:n})}static createPattern(t,e="repeat"){return Ye.ctx.createPattern(t,e)}static fillPattern(t,e,i,s,n){const o=Ye.ctx;o.save(),o.fillStyle=t,o.fillRect(e,i,s,n),o.restore()}static createImageData(t,e){return Ye.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 Ye.ctx.getImageData(t,e,i,s)}static putImageData(t,e,i,s=0,n=0,o=t.width,r=t.height){Ye.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=Ye.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 Ie{static path(t,e,i,s=1){const n=Ye.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,Ye.colors.fill(e)),i&&(n.strokeStyle=i,n.lineWidth=s,Ye.colors.stroke())}static line(t,e,i,s,n,o){Ye.ctx.beginPath(),Ye.ctx.moveTo(t,e),Ye.ctx.lineTo(i,s),Ye.colors.stroke(n,o)}static beginPath(){Ye.ctx.beginPath()}static closePath(){Ye.ctx.closePath()}static moveTo(t,e){Ye.ctx.moveTo(t,e)}static lineTo(t,e){Ye.ctx.lineTo(t,e)}static bezierCurveTo(t,e,i,s,n,o){Ye.ctx.bezierCurveTo(t,e,i,s,n,o)}static dashedLine(t,e,i,s,n,o,r){Ye.ctx.beginPath(),o&&(Ye.ctx.strokeStyle=o),void 0!==r&&(Ye.ctx.lineWidth=r),Ye.ctx.setLineDash(n),Ye.ctx.moveTo(t,e),Ye.ctx.lineTo(i,s),Ye.colors.stroke(),Ye.ctx.setLineDash([])}static dottedLine(t,e,i,s,n=2,o=5,r){return Ye.lines.dashedLine(t,e,i,s,[n,o],r,n)}static setLineDash(t){Ye.ctx.setLineDash(t)}static resetLineDash(){Ye.ctx.setLineDash([])}static setLineWidth(t){Ye.ctx.lineWidth=t}static quadraticCurve(t,e,i,s,n,o,r,a){Ye.ctx.beginPath(),Ye.ctx.moveTo(t,e),Ye.ctx.quadraticCurveTo(i,s,n,o),r&&(Ye.ctx.strokeStyle=r),void 0!==a&&(Ye.ctx.lineWidth=a),Ye.colors.stroke()}}class Ee{static pushOpacity(t){const e=this._opacityStack[this._opacityStack.length-1]*t;this._opacityStack.push(e),Ye.logger.log("NEXT OPACITY WILL BE",e),Ye.effects.setAlpha(e)}static popOpacity(){if(this._opacityStack.length>1){this._opacityStack.pop();const t=this._opacityStack[this._opacityStack.length-1];Ye.logger.log("NEXT OPACITY WILL BE",t),Ye.effects.setAlpha(t)}}static _clone(){this._opacityStack=[...this._opacityStack]}static saveOpacityState(){this._opacityStateBackup=[...this._opacityStack]}static restoreOpacityState(){this._opacityStateBackup&&(this._opacityStack=this._opacityStateBackup,delete this._opacityStateBackup)}}_t(Ee,"_opacityStack",[1]);class Fe{static rect(t,e,i,s,n){const o=Ye.ctx.fillStyle;Ye.colors.fill(n),Ye.ctx.fillRect(t,e,i,s),Ye.ctx.fillStyle=o}static outlineRect(t,e,i,s,n,o=1){const r=Ye.ctx.strokeStyle,a=Ye.ctx.lineWidth;Ye.ctx.strokeStyle=n,Ye.ctx.lineWidth=o,Ye.ctx.strokeRect(t,e,i,s),Ye.ctx.strokeStyle=r,Ye.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;Ye.lines.beginPath(),Ye.lines.moveTo(t+l,e),Ye.lines.lineTo(f-c,e),this.arc(f-c,e+c,c,-Math.PI/2,0),Ye.lines.lineTo(f,p-u),this.arc(f-u,p-u,u,0,Math.PI/2),Ye.lines.lineTo(t+d,p),this.arc(t+d,p-d,d,Math.PI/2,Math.PI),Ye.lines.lineTo(t,e+l),this.arc(t+l,e+l,l,Math.PI,-Math.PI/2),Ye.lines.closePath(),o&&(Ye.fillStyle=o,Ye.colors.fill(o)),r&&Ye.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){Ye.logger.log("PainterShapes.fillCircle",t,e,i,s),Ye.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Ye.colors.fill(s)}static arc(t,e,i,s,n,o){Ye.ctx.arc(t,e,i,s,n,o)}static strokeCircle(t,e,i,s,n){Ye.lines.beginPath(),this.arc(t,e,i,0,2*Math.PI),Ye.colors.stroke(s,n)}static fillEllipse(t,e,i,s,n=0,o){Ye.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Ye.fillStyle=o),Ye.colors.fill(o)}static strokeEllipse(t,e,i,s,n=0,o,r){Ye.lines.beginPath(),this.ellipse(t,e,i,s,n,0,2*Math.PI),o&&(Ye.strokeStyle=o),void 0!==r&&(Ye.lineWidth=r),Ye.colors.stroke(o,r)}static ellipse(t,e,i,s,n,o,r,a){Ye.ctx.ellipse(t,e,i,s,n,o,r,a)}static polygon(t,e,i,s,n){if(t.length<2)return;const o=Ye.ctx;o.beginPath(),o.moveTo(t[0].x,t[0].y);for(let r=1;r<t.length;r++)o.lineTo(t[r].x,t[r].y);o.closePath(),e&&Ye.colors.fill(e),i&&(n&&(o.lineJoin=n),Ye.colors.stroke(i,s))}}class Oe{static font(){return Ye.ctx.font}static setFont(t){Ye.ctx.font=t}static setTextAlign(t){Ye.ctx.textAlign=t}static setTextBaseline(t){Ye.ctx.textBaseline=t}static fillText(t,e,i,s,n){s&&(Ye.ctx.fillStyle=s),n&&(Ye.ctx.font=n),Ye.ctx.fillText(t,e,i)}static strokeText(t,e,i,s,n,o){s&&(Ye.ctx.strokeStyle=s),void 0!==n&&(Ye.ctx.lineWidth=n),o&&(Ye.ctx.font=o),Ye.ctx.strokeText(t,e,i)}static measureTextDimensions(t,e,i="start",s="alphabetic"){e&&(Ye.ctx.font=e);const n=Ye.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&&(Ye.ctx.font=e),Ye.ctx.measureText(t).width}static outlinedText(t,e,i,s,n,o,r){r&&(Ye.ctx.font=r),Ye.ctx.strokeStyle=n,Ye.ctx.lineWidth=o,Ye.ctx.strokeText(t,e,i),Ye.ctx.fillStyle=s,Ye.ctx.fillText(t,e,i)}static wrappedText(t,e,i,s,n,o,r){o&&(Ye.ctx.fillStyle=o),r&&(Ye.ctx.font=r);const a=t.split(" ");let h="",l="",c=1;for(let u=0;u<a.length;u++){l=h+a[u]+" ";Ye.ctx.measureText(l).width>s&&u>0?(Ye.ctx.fillText(h,e,i),h=a[u]+" ",i+=n,c++):h=l}return Ye.ctx.fillText(h,e,i),c*n}static textOnPath(t,e,i,s,n=!1){if(e.length<2)return;i&&(Ye.ctx.fillStyle=i),s&&(Ye.ctx.font=s);const o=t.split(""),r=o.map(t=>Ye.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);Ye.ctx.save(),Ye.ctx.translate(i,s),Ye.ctx.rotate(n),Ye.ctx.fillText(o[c],0,0),Ye.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 Le=class t{static get colors(){return St(this,C,T).call(this,"colors",bt(this,y)),bt(this,y)}static get effects(){return St(this,C,T).call(this,"effects",bt(this,_)),bt(this,_)}static get img(){return St(this,C,T).call(this,"img",bt(this,x)),bt(this,x)}static get lines(){return St(this,C,T).call(this,"lines",bt(this,b)),bt(this,b)}static get opacity(){return St(this,C,T).call(this,"opacity",bt(this,w)),bt(this,w)}static get shapes(){return St(this,C,T).call(this,"shapes",bt(this,M)),bt(this,M)}static get text(){return St(this,C,T).call(this,"text",bt(this,S)),bt(this,S)}static set ctx(t){this._ctx=t}static get ctx(){if(!this._ctx)throw new Error("Cannot access Painter.ctx before initialization!");return this._ctx}static init(e){this._ctx=e,this.saveStack=[],Mt(this,y,Xe),Mt(this,_,De),Mt(this,x,Be),Mt(this,b,Ie),Mt(this,w,Ee),Mt(this,M,Fe),Mt(this,S,Oe),t.logger=ke.getLogger("Painter"),t.saveStack=[]}static setContext(t){this._ctx=t}static save(){const e=((new Error).stack.split("\n")[2]||"").match(/at\s+(\w+)\.(\w+)/),i=e?`${e[1]}.${e[2]}`:"unknown";this.saveStack.push(i),this.logger.log(`Painter.save() by: ${i}`),this.ctx.save(),t.opacity.saveOpacityState()}static restore(){if(0===this.saveStack.length)return void console.error("PAINTER ERROR: restore() without matching save()!");const e=this.saveStack.pop();this.logger.log(`Painter.restore() balancing save from: ${e}`),this.ctx.restore(),t.opacity.restoreOpacityState()}static translateTo(t,e){(isNaN(t)||void 0===t)&&(t=0),(isNaN(e)||void 0===e)&&(e=0),this.logger.log("moveTo",t,e),this.ctx.translate(t,e)}static resetPosition(){this.logger.log("resetPosition");const t=this.ctx.getTransform();this.ctx.setTransform(t.a,t.b,t.c,t.d,0,0)}static withPosition(t,e,i){this.logger.log("withPosition",t,e),this.save(),this.translateTo(t,e),i(),this.restore()}static clear(e=0,i=0,s=t.ctx.canvas.width,n=t.ctx.canvas.height){t.ctx.clearRect(e,i,s,n)}static translate(e,i){t.ctx.translate(e,i)}static rotate(e){t.logger.log("Painter.rotate",e),t.ctx.rotate(e)}static scale(e,i){t.logger.log("Painter.scale",e,i),t.ctx.scale(e,i)}static useCtx(t,e={}){const i=this.ctx,{saveState:s=!1}=e;s&&this.save(),i.beginPath(),t(i),i.beginPath(),s&&this.restore()}};y=new WeakMap,_=new WeakMap,x=new WeakMap,b=new WeakMap,w=new WeakMap,M=new WeakMap,S=new WeakMap,C=new WeakSet,T=function(t,e){if(!e)throw new Error(`Painter.${t} is not initialized. Call Painter.init(ctx) first.`)},wt(Le,C),wt(Le,y,null),wt(Le,_,null),wt(Le,x,null),wt(Le,b,null),wt(Le,w,null),wt(Le,M,null),wt(Le,S,null),_t(Le,"logger");let Ye=Le;class Xe{static fill(t){Ye.logger.log("PainterColors.fill - before:",Ye.ctx.fillStyle,"setting to:",t),Ye.ctx.fillStyle,Ye.ctx.fillStyle=t,Ye.ctx.fill(),Ye.logger.log("PainterColors.fill - after:",Ye.ctx.fillStyle)}static strokeOptions(t){t.color&&(Ye.ctx.strokeStyle=t.color),void 0!==t.lineWidth&&(Ye.ctx.lineWidth=t.lineWidth),t.lineCap&&(Ye.ctx.lineCap=t.lineCap),t.lineJoin&&(Ye.ctx.lineJoin=t.lineJoin),t.strokeStyle&&(Ye.ctx.strokeStyle=t.strokeStyle)}static stroke(t,e){t&&(Ye.ctx.strokeStyle=t),void 0!==e&&(Ye.ctx.lineWidth=e),Ye.ctx.stroke()}static setFillColor(t){Ye.ctx.fillStyle=t}static setStrokeColor(t){Ye.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 Ye.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]=Ye.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 Ye.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=Ye.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=Ye.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 Ye.colors.linearGradient(t,e,t,e+s,n)}static horizontalGradient(t,e,i,s,n){return Ye.colors.linearGradient(t,e,t+i,e,n)}static conicGradient(t,e,i,s){if("function"==typeof Ye.ctx.createConicGradient){const n=Ye.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 We 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 He extends We{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 Ue extends He{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),Ye.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 Ge extends Ue{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(Ye.save(),Ye.effects.setBlendMode(this._blendMode),this.crisp?Ye.translateTo(Math.round(this.x),Math.round(this.y)):Ye.translateTo(this.x,this.y),this.applyShadow(Ye.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),Ye.opacity.pushOpacity(this._opacity);const o=this.rotation??0,r=this.scaleX??1,a=this.scaleY??1;Ye.img.draw(this._cacheCanvas,0,0,{width:s,height:n,rotation:o,scaleX:r,scaleY:a,anchor:"center"}),Ye.opacity.popOpacity()}else Ye.opacity.pushOpacity(this._opacity),this.draw(),Ye.opacity.popOpacity();Ye.restore()}}_renderToCache(t,e){const i=this._cacheCanvas.getContext("2d");i.clearRect(0,0,t,e);const s=Ye.ctx;Ye.ctx=i,this._isCaching=!0,i.save(),i.translate(t/2,e/2),this.draw(),i.restore(),this._isCaching=!1,Ye.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 Ne=class t{constructor(t){this._owner=t}get owner(){return this._owner}x(t){return this._owner._x=t,this._owner.markBoundsDirty(),this}y(t){return this._owner._y=t,this._owner.markBoundsDirty(),this}position(t,e){return this._owner._x=t,this._owner._y=e,this._owner.markBoundsDirty(),this}translateBy(t,e){return this._owner._x+=t,this._owner._y+=e,this._owner.markBoundsDirty(),this}width(t){var e,i;return this._owner._width=Math.max(0,t),this._owner.markBoundsDirty(),null==(i=(e=this._owner).invalidateCache)||i.call(e),this}height(t){var e,i;return this._owner._height=Math.max(0,t),this._owner.markBoundsDirty(),null==(i=(e=this._owner).invalidateCache)||i.call(e),this}size(t,e){var i,s;return this._owner._width=Math.max(0,t),this._owner._height=Math.max(0,e),this._owner.markBoundsDirty(),null==(s=(i=this._owner).invalidateCache)||s.call(i),this}rotation(t){return this._owner._rotation=t*Math.PI/180,this._owner.markBoundsDirty(),this}rotationRad(t){return this._owner._rotation=t,this._owner.markBoundsDirty(),this}rotateBy(t){return this._owner._rotation+=t*Math.PI/180,this._owner.markBoundsDirty(),this}scaleX(t){return this._owner._scaleX=t,this._owner.markBoundsDirty(),this}scaleY(t){return this._owner._scaleY=t,this._owner.markBoundsDirty(),this}scale(t){return this._owner._scaleX=t,this._owner._scaleY=t,this._owner.markBoundsDirty(),this}scaleBy(t){return this._owner._scaleX*=t,this._owner._scaleY*=t,this._owner.markBoundsDirty(),this}set(t){var e,i;let s=!1;return void 0!==t.x&&(this._owner._x=t.x),void 0!==t.y&&(this._owner._y=t.y),void 0!==t.width&&(this._owner._width=Math.max(0,t.width),s=!0),void 0!==t.height&&(this._owner._height=Math.max(0,t.height),s=!0),void 0!==t.rotation&&(this._owner._rotation=t.rotation*Math.PI/180),void 0!==t.scaleX&&(this._owner._scaleX=t.scaleX),void 0!==t.scaleY&&(this._owner._scaleY=t.scaleY),this._owner.markBoundsDirty(),s&&(null==(i=(e=this._owner).invalidateCache)||i.call(e)),this}reset(){return this._owner._rotation=0,this._owner._scaleX=1,this._owner._scaleY=1,this._owner.markBoundsDirty(),this}resetAll(){var t,e;return this._owner._x=0,this._owner._y=0,this._owner._width=0,this._owner._height=0,this._owner._rotation=0,this._owner._scaleX=1,this._owner._scaleY=1,this._owner.markBoundsDirty(),null==(e=(t=this._owner).invalidateCache)||e.call(t),this}toObject(){return{x:this._owner._x,y:this._owner._y,width:this._owner._width,height:this._owner._height,rotation:180*this._owner._rotation/Math.PI,scaleX:this._owner._scaleX,scaleY:this._owner._scaleY}}copyFrom(e){const i=e instanceof t?e.toObject():e;return this.set(i)}static handleDirectSet(e,i){if(t.strictMode)throw new Error(`Direct property assignment "${e} = ${i}" is disabled. Use shape.transform.${e}(${i}) instead. Set Transform.strictMode = false to allow direct assignment.`);console.warn(`[Deprecation] Direct assignment "${e} = ${i}" is deprecated. Use shape.transform.${e}(${i}) instead.`)}};_t(Ne,"strictMode",!1);let qe=Ne;class Ze extends Ge{constructor(t={}){super(t),this._rotation=t.rotation*Math.PI/180,this._scaleX=t.scaleX??1,this._scaleY=t.scaleY??1,this.transform=new qe(this),this.logger.log("Transformable",this.x,this.y,this.width,this.height)}draw(){this.applyTransforms();const t=Ye.ctx;t.beginPath(),t.fill(),this.drawDebug()}applyTransforms(){this._isCaching||(Ye.rotate(this._rotation),Ye.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 Ve extends Ze{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 $e extends Ze{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 Ze))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&&(Ye.save(),i.render(),Ye.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 je extends Ve{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Ye.lines.beginPath(),Ye.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle,!1),this.stroke&&Ye.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 Ke extends Ve{constructor(t,e={}){super(e),this._radius=t,this.width=2*t,this.height=2*t}draw(){super.draw(),this.color&&Ye.shapes.fillCircle(0,0,this._radius,this.color),this.stroke&&Ye.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 Je extends Ve{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=Ye.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 Qe extends Ve{constructor(t={}){super(t)}draw(){super.draw(),this.drawRect()}drawRect(){const t=-this.width/2,e=-this.height/2;this.color&&Ye.shapes.rect(t,e,this.width,this.height,this.color),this.stroke&&Ye.shapes.outlineRect(t,e,this.width,this.height,this.stroke,this.lineWidth)}}class ti extends Ve{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?Ye.shapes.roundRect(t,e,this.width,this.height,this.radii,this.color,this.stroke,this.lineWidth):this.color?Ye.shapes.fillRoundRect(t,e,this.width,this.height,this.radii,this.color):this.stroke&&Ye.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 ei extends Qe{constructor(t,e={}){super(e),this.width=t,this.height=t}}class ii extends Ve{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}];Ye.shapes.polygon(i,this.color,this.stroke,this.lineWidth)}}class si extends Ve{constructor(t=40,e={}){super(e),this.length=t}draw(){super.draw();const t=this.length/2;Ye.lines.line(-t,-t,t,t,this.stroke,this.lineWidth)}}class ni extends Ve{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}];Ye.shapes.polygon(e,this.color,this.stroke,this.lineWidth)}}class oi extends Ve{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;Ye.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?Ye.lines.moveTo(o,r):Ye.lines.lineTo(o,r)}Ye.lines.closePath(),this.color&&Ye.colors.fill(this.color),this.stroke&&Ye.colors.stroke(this.stroke,this.lineWidth)}}class ri{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 ai="\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",hi={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:ai,star:`\n${ai}\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${ai}\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${ai}\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${ai}\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`},li=class t extends Ve{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 ri(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 hi.star;case"blackHole":return hi.blackHole;case"rockyPlanet":return hi.rockyPlanet;case"gasGiant":return hi.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,hi.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,hi.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&&Ye.shapes.fillCircle(0,0,this.radius,this.color),void(this.debug&&this.stroke&&Ye.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=Ye.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)Ye.ctx.beginPath(),Ye.ctx.moveTo(t[0].x,t[0].y),Ye.ctx.lineTo(t[1].x,t[1].y),Ye.ctx.lineTo(t[2].x,t[2].y),Ye.ctx.closePath(),this.stroke&&(Ye.ctx.strokeStyle=this.stroke,Ye.ctx.lineWidth=this.lineWidth??1,Ye.ctx.stroke());else if(this.color){const e=this._applyLighting(this.color,s.intensity);Ye.ctx.beginPath(),Ye.ctx.moveTo(t[0].x,t[0].y),Ye.ctx.lineTo(t[1].x,t[1].y),Ye.ctx.lineTo(t[2].x,t[2].y),Ye.ctx.closePath(),Ye.ctx.fillStyle=e,Ye.ctx.fill()}}}calculateBounds(){const t=2*this.radius;return{x:this.x,y:this.y,width:t,height:t}}};_t(li,"_glRenderer",null),_t(li,"_glRendererSize",{width:0,height:0});let ci=li;const ui="\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",di={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${ui}\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${ui}\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${ui}\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${ui}\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`},fi=class t extends Ve{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 ri(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 di.gradient;case"grid":return di.grid;case"checkerboard":return di.checkerboard;case"noise":return di.noise}}_initShader(e,i){const s=t._getGLRenderer(e,i);if(!s||!s.isAvailable())return!1;const n=`plane_${this.shaderType}`,o=di.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,di.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&&Ye.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=Ye.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=Ye.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,v=s.x,y=s.y,_=(l-a)*(d-h)-(u-a)*(c-h);if(Math.abs(_)<1e-4)return;const x=((g-f)*(d-h)-(v-f)*(c-h))/_,b=((v-f)*(l-a)-(g-f)*(u-a))/_,w=f-x*a-b*h,M=((m-p)*(d-h)-(y-p)*(c-h))/_,S=((y-p)*(l-a)-(m-p)*(u-a))/_,C=p-M*a-S*h;t.save(),t.beginPath(),t.moveTo(f,p),t.lineTo(g,m),t.lineTo(v,y),t.closePath(),t.clip(),t.setTransform(x,M,b,S,w,C),t.drawImage(n,0,0),t.restore()}getCenter(){return{x:this.x,y:this.y,z:this.z}}getBounds(){return{x:this.x-this.planeWidth/2,y:this.y-this.planeHeight/2,width:this.planeWidth,height:this.planeHeight}}};_t(fi,"_glRenderer",null),_t(fi,"_glRendererSize",{width:0,height:0});let pi=fi;class gi extends Ve{static async fromURL(t,e={}){const i=await fetch(t),s=await i.text(),n=(new DOMParser).parseFromString(s,"image/svg+xml").querySelector("path");if(!n)throw new Error("No path element found in SVG");const o=n.getAttribute("d");if(!o)throw new Error("Path element has no d attribute");return new gi(o,e)}constructor(t,e={}){super(e),this.scale=e.scale||1,this.centerPath=void 0===e.centerPath||e.centerPath,this.animationProgress=void 0!==e.animationProgress?e.animationProgress:1,this.svgPathData=t,this.pathCommands=this.parseSVGPath(t),this.centerPath?this.pathCommands=this.centerAndScalePath(this.pathCommands,this.scale):this.pathCommands=this.scalePath(this.pathCommands,this.scale),this.prevX=0,this.prevY=0,this.currentPoint={x:0,y:0}}parseSVGPath(t){const e=[];let i=0,s=0,n=0,o=0;const r=/([MLHVCSQTAZmlhvcsqtaz])([^MLHVCSQTAZmlhvcsqtaz]*)/g;let a;for(;null!==(a=r.exec(t));){const t=a[1],r=a[2].trim(),h=r.length>0?r.split(/[\s,]+/).map(parseFloat).filter(t=>!isNaN(t)):[];switch(t){case"M":for(let t=0;t<h.length;t+=2)i=h[t],s=h[t+1],0===t?(n=i,o=s,e.push(["M",i,s])):e.push(["L",i,s]);break;case"m":for(let t=0;t<h.length;t+=2)i+=h[t],s+=h[t+1],0===t?(n=i,o=s,e.push(["M",i,s])):e.push(["L",i,s]);break;case"L":for(let t=0;t<h.length;t+=2){const n=h[t],o=h[t+1];e.push(["L",n,o]),i=n,s=o}break;case"l":for(let t=0;t<h.length;t+=2)i+=h[t],s+=h[t+1],e.push(["L",i,s]);break;case"H":for(let t=0;t<h.length;t++)i=h[t],e.push(["L",i,s]);break;case"h":for(let t=0;t<h.length;t++)i+=h[t],e.push(["L",i,s]);break;case"V":for(let t=0;t<h.length;t++)s=h[t],e.push(["L",i,s]);break;case"v":for(let t=0;t<h.length;t++)s+=h[t],e.push(["L",i,s]);break;case"C":for(let t=0;t<h.length;t+=6)e.push(["C",h[t],h[t+1],h[t+2],h[t+3],h[t+4],h[t+5]]),i=h[t+4],s=h[t+5];break;case"c":for(let t=0;t<h.length;t+=6)e.push(["C",i+h[t],s+h[t+1],i+h[t+2],s+h[t+3],i+h[t+4],s+h[t+5]]),i+=h[t+4],s+=h[t+5];break;case"S":for(let t=0;t<h.length;t+=4){const n=e[e.length-1];let o=i,r=s;n&&"C"===n[0]&&(o=2*i-n[3],r=2*s-n[4]),e.push(["C",o,r,h[t],h[t+1],h[t+2],h[t+3]]),i=h[t+2],s=h[t+3]}break;case"s":for(let t=0;t<h.length;t+=4){const n=e[e.length-1];let o=i,r=s;n&&"C"===n[0]&&(o=2*i-n[3],r=2*s-n[4]),e.push(["C",o,r,i+h[t],s+h[t+1],i+h[t+2],s+h[t+3]]),i+=h[t+2],s+=h[t+3]}break;case"Q":for(let t=0;t<h.length;t+=4){const n=h[t],o=h[t+1],r=h[t+2],a=h[t+3],l=i+2/3*(n-i),c=s+2/3*(o-s),u=r+2/3*(n-r),d=a+2/3*(o-a);e.push(["C",l,c,u,d,r,a]),i=r,s=a}break;case"q":for(let t=0;t<h.length;t+=4){const n=i+h[t],o=s+h[t+1],r=i+h[t+2],a=s+h[t+3],l=i+2/3*(n-i),c=s+2/3*(o-s),u=r+2/3*(n-r),d=a+2/3*(o-a);e.push(["C",l,c,u,d,r,a]),i=r,s=a}break;case"Z":case"z":e.push(["Z"]),i=n,s=o}}return e}centerAndScalePath(t,e){let i=1/0,s=1/0,n=-1/0,o=-1/0;for(const h of t)"M"===h[0]||"L"===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]||"L"===t[0]?[t[0],(t[1]-r)*e,(t[2]-a)*e]:"C"===t[0]?["C",(t[1]-r)*e,(t[2]-a)*e,(t[3]-r)*e,(t[4]-a)*e,(t[5]-r)*e,(t[6]-a)*e]:[...t])}scalePath(t,e){let i=1/0,s=1/0,n=-1/0,o=-1/0;for(const r of t)"M"===r[0]||"L"===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]||"L"===t[0]?[t[0],t[1]*e,t[2]*e]:"C"===t[0]?["C",t[1]*e,t[2]*e,t[3]*e,t[4]*e,t[5]*e,t[6]*e]:[...t])}getPointOnSegment(t,e){if("M"===t[0])return{x:t[1],y:t[2]};if("L"===t[0]){return{x:this.prevX+(t[1]-this.prevX)*e,y:this.prevY+(t[2]-this.prevY)*e}}if("C"===t[0]){const i=this.prevX,s=this.prevY,n=t[1],o=t[2],r=t[3],a=t[4],h=t[5],l=t[6];return{x:Math.pow(1-e,3)*i+3*Math.pow(1-e,2)*e*n+3*(1-e)*Math.pow(e,2)*r+Math.pow(e,3)*h,y:Math.pow(1-e,3)*s+3*Math.pow(1-e,2)*e*o+3*(1-e)*Math.pow(e,2)*a+Math.pow(e,3)*l}}return{x:0,y:0}}getBezierPoint(t,e){return this.getPointOnSegment(t,e)}getPartialPath(){const t=[];let e=this.pathCommands.length,i=Math.floor(this.animationProgress*e),s=this.animationProgress*e%1,n=!1;this.prevX=0,this.prevY=0;for(let o=0;o<i;o++){const e=this.pathCommands[o];t.push([...e]),"M"===e[0]||"L"===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]};else if("L"===e[0]){n||this.findPreviousPoint(i);const o=this.getPointOnSegment(e,s);t.push(["L",o.x,o.y]),this.currentPoint=o}else if("C"===e[0]){n||this.findPreviousPoint(i);const o=this.getPointOnSegment(e,s);t.push(["C",e[1],e[2],e[3],e[4],o.x,o.y]),this.currentPoint=o}else"Z"===e[0]&&(s>.5&&t.push(["Z"]),this.currentPoint={x:this.prevX,y:this.prevY})}return t}findPreviousPoint(t){for(let e=t-1;e>=0;e--){const t=this.pathCommands[e];if("M"===t[0]||"L"===t[0])return this.prevX=t[1],void(this.prevY=t[2]);if("C"===t[0])return this.prevX=t[5],void(this.prevY=t[6])}this.prevX=0,this.prevY=0}draw(){super.draw();const t=this.getPartialPath();Ye.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 mi extends Ve{constructor(t,e,i={}){super(i),this.outerRadius=t,this.innerRadius=e}draw(){super.draw(),Ye.lines.beginPath(),Ye.shapes.arc(0,0,this.outerRadius,0,2*Math.PI),Ye.shapes.arc(0,0,this.innerRadius,0,2*Math.PI,!0),Ye.lines.closePath(),this.color&&Ye.colors.fill(this.color),this.stroke&&Ye.colors.stroke(this.stroke,this.lineWidth)}}class vi extends Ve{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})}Ye.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class yi extends Ve{constructor(t,e={}){super(e),this.length=t}draw(){super.draw();const t=this.width/2,e=.4*this.length,i=this.length-e;Ye.lines.beginPath(),Ye.lines.moveTo(-i/2,-t),Ye.lines.lineTo(i/2,-t),Ye.lines.lineTo(i/2,-this.width),Ye.lines.lineTo(this.length/2,0),Ye.lines.lineTo(i/2,this.width),Ye.lines.lineTo(i/2,t),Ye.lines.lineTo(-i/2,t),Ye.lines.closePath(),this.color&&Ye.colors.fill(this.color),this.stroke&&Ye.colors.stroke(this.stroke,this.lineWidth)}}class _i extends Ve{constructor(t=20,e={}){super(e),this.radius=t}draw(){super.draw();const t=this.radius,e=2.5*t;Ye.lines.beginPath(),Ye.shapes.arc(0,0,t,Math.PI,0),Ye.lines.lineTo(t,0),Ye.lines.lineTo(0,e),Ye.lines.lineTo(-t,0),Ye.lines.closePath(),this.color&&Ye.colors.fill(this.color),this.stroke&&Ye.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 xi extends Ve{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}});Ye.shapes.polygon(t,this.color,this.stroke,this.lineWidth)}}class bi extends Ve{constructor(t={}){super(t)}draw(){super.draw();const t=this.width,e=this.height,i=.3*e,s=Ye.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&&Ye.colors.fill(this.color),this.stroke&&Ye.colors.stroke(this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y+this.height/2,width:this.width,height:this.height}}}class wi extends Ve{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?(Ye.lines.beginPath(),Ye.lines.moveTo(-t,-t+e),Ye.lines.lineTo(-t+e,-t),Ye.lines.lineTo(0,-e),Ye.lines.lineTo(t-e,-t),Ye.lines.lineTo(t,-t+e),Ye.lines.lineTo(e,0),Ye.lines.lineTo(t,t-e),Ye.lines.lineTo(t-e,t),Ye.lines.lineTo(0,e),Ye.lines.lineTo(-t+e,t),Ye.lines.lineTo(-t,t-e),Ye.lines.lineTo(-e,0),Ye.lines.closePath()):(Ye.lines.beginPath(),Ye.lines.moveTo(-e,-t),Ye.lines.lineTo(e,-t),Ye.lines.lineTo(e,-e),Ye.lines.lineTo(t,-e),Ye.lines.lineTo(t,e),Ye.lines.lineTo(e,e),Ye.lines.lineTo(e,t),Ye.lines.lineTo(-e,t),Ye.lines.lineTo(-e,e),Ye.lines.lineTo(-t,e),Ye.lines.lineTo(-t,-e),Ye.lines.lineTo(-e,-e),Ye.lines.closePath()),this.color&&Ye.colors.fill(this.color),this.stroke&&Ye.colors.stroke(this.stroke,this.lineWidth)}}class Mi extends Ve{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),Ye.text.setFont(this.font),Ye.text.setTextAlign(this.align),Ye.text.setTextBaseline(this.baseline),Ye.text.fillText(this.text,-this._centerOffsetX,-this._centerOffsetY,this.color)}_calculateAlignmentOffsets(){if(!Ye.text)return;const t=Ye.text.measureTextDimensions(this.text,this.font);switch(this._align){case"left":this._centerOffsetX=t.width/2;break;case"center":this._centerOffsetX=0;break;case"right":this._centerOffsetX=-t.width/2}switch(this._baseline){case"top":this._centerOffsetY=t.height/2;break;case"middle":this._centerOffsetY=0;break;case"bottom":this._centerOffsetY=-t.height/2}}getTextBounds(){if(Ye.text){const t=Ye.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(Ye.text){const t=Ye.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 Si extends Ve{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??Ye.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=Ye.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)||Ye.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 Ci{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 Ti{static init(t){Ti.game=t,Ti.x=0,Ti.y=0,Ti.down=!1,t.events.on("mousedown",e=>Ti._onDown(e,t)),t.events.on("mouseup",e=>Ti._onUp(e,t)),t.events.on("mousemove",e=>Ti._onMove(e,t)),t.events.on("touchstart",e=>Ti._onTouchStart(e,t)),t.events.on("touchend",e=>Ti._onTouchEnd(e,t)),t.events.on("touchmove",e=>Ti._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){Ti.x=t,Ti.y=e}static _onDown(t,e){Ti.down=!0;const i=Ti._scaleToCanvas(e,t.offsetX,t.offsetY);Ti._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){Ti.down=!1;const i=Ti._scaleToCanvas(e,t.offsetX,t.offsetY);Ti._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=Ti._scaleToCanvas(e,t.offsetX,t.offsetY);Ti._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();Ti.down=!0;const n=i.clientX-s.left,o=i.clientY-s.top,r=Ti._scaleToCanvas(e,n,o);Ti._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){Ti.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=Ti._scaleToCanvas(e,n,o);Ti._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 ki=class t{static init(e){t._gameMap.set(e.canvas,e),t.game=e,t.canvas=e.canvas,t.x=0,t.y=0,t.leftDown=!1,t.middleDown=!1,t.rightDown=!1,e.canvas.addEventListener("mousemove",t._onMove),e.canvas.addEventListener("mousedown",t._onDown),e.canvas.addEventListener("mouseup",t._onUp),e.canvas.addEventListener("click",t._onClick),e.canvas.addEventListener("wheel",t._onWheel)}static _getGameForEvent(e){const i=e.currentTarget;return t._gameMap.get(i)||t.game}static _updatePosition(e,i){const s=i.canvas,n=s.getBoundingClientRect(),o=e.clientX-n.left,r=e.clientY-n.top,a=s.width/n.width,h=s.height/n.height;t.x=o*a,t.y=r*h}};_t(ki,"_gameMap",new Map),_t(ki,"_onMove",t=>{const e=ki._getGameForEvent(t);ki._updatePosition(t,e),e.events.emit("mousemove",t)}),_t(ki,"_onDown",t=>{const e=ki._getGameForEvent(t);ki._updatePosition(t,e),0===t.button&&(ki.leftDown=!0),1===t.button&&(ki.middleDown=!0),2===t.button&&(ki.rightDown=!0),e.events.emit("mousedown",t)}),_t(ki,"_onUp",t=>{const e=ki._getGameForEvent(t);ki._updatePosition(t,e),0===t.button&&(ki.leftDown=!1),1===t.button&&(ki.middleDown=!1),2===t.button&&(ki.rightDown=!1),e.events.emit("mouseup",t)}),_t(ki,"_onClick",t=>{const e=ki._getGameForEvent(t);ki._updatePosition(t,e),t.canvasX=ki.x,t.canvasY=ki.y,Object.defineProperty(t,"x",{value:ki.x,writable:!1}),Object.defineProperty(t,"y",{value:ki.y,writable:!1}),e.events.emit("click",t)}),_t(ki,"_onWheel",t=>{const e=ki._getGameForEvent(t);ki._updatePosition(t,e),e.events.emit("wheel",t)});let Pi=ki;const Ri=class t{static init(e){t.game=e,window.addEventListener("keydown",t._onKeyDown),window.addEventListener("keyup",t._onKeyUp)}static isDown(e){return t._down.has(e)}static _onKeyDown(e){const i=t._codeMap[e.code];i&&(t._down.has(i)||(t._down.add(i),t.game.events.emit(i,e))),t.game.events.emit(e.type,e)}static _onKeyUp(e){const i=t._codeMap[e.code];i&&t._down.has(i)&&(t._down.delete(i),t.game.events.emit(i+"_up",e)),t.game.events.emit(e.type,e)}};_t(Ri,"W","W"),_t(Ri,"A","A"),_t(Ri,"S","S"),_t(Ri,"D","D"),_t(Ri,"Q","Q"),_t(Ri,"E","E"),_t(Ri,"R","R"),_t(Ri,"F","F"),_t(Ri,"G","G"),_t(Ri,"J","J"),_t(Ri,"K","K"),_t(Ri,"L","L"),_t(Ri,"Z","Z"),_t(Ri,"C","C"),_t(Ri,"UP","UP"),_t(Ri,"DOWN","DOWN"),_t(Ri,"LEFT","LEFT"),_t(Ri,"RIGHT","RIGHT"),_t(Ri,"SPACE","SPACE"),_t(Ri,"SHIFT","SHIFT"),_t(Ri,"ENTER","ENTER"),_t(Ri,"ESC","ESC"),_t(Ri,"_codeMap",{KeyW:Ri.W,KeyA:Ri.A,KeyS:Ri.S,KeyD:Ri.D,KeyQ:Ri.Q,KeyE:Ri.E,KeyR:Ri.R,KeyF:Ri.F,KeyG:Ri.G,KeyJ:Ri.J,KeyK:Ri.K,KeyL:Ri.L,KeyZ:Ri.Z,KeyC:Ri.C,ArrowUp:Ri.UP,ArrowDown:Ri.DOWN,ArrowLeft:Ri.LEFT,ArrowRight:Ri.RIGHT,Space:Ri.SPACE,ShiftLeft:Ri.SHIFT,ShiftRight:Ri.SHIFT,Enter:Ri.ENTER,NumpadEnter:Ri.ENTER,Escape:Ri.ESC}),_t(Ri,"_down",new Set),_t(Ri,"game",null);let Ai=Ri;const zi=class t{static init(e){t._gameMap.set(e.canvas,e),t.game=e,t.canvas=e.canvas,t.x=0,t.y=0,t.active=!1,e.canvas.addEventListener("touchstart",t._onStart),e.canvas.addEventListener("touchend",t._onEnd),e.canvas.addEventListener("touchmove",t._onMove)}static _getGameForEvent(e){const i=e.currentTarget;return t._gameMap.get(i)||t.game}static _updatePosition(e,i){const s=i.canvas,n=s.getBoundingClientRect(),o=e.clientX-n.left,r=e.clientY-n.top,a=s.width/n.width,h=s.height/n.height;t.x=o*a,t.y=r*h}};_t(zi,"_gameMap",new Map),_t(zi,"_onStart",t=>{if(t.touches.length>0){const e=zi._getGameForEvent(t);zi.active=!0,zi._updatePosition(t.touches[0],e),e.events.emit("touchstart",t)}}),_t(zi,"_onEnd",t=>{const e=zi._getGameForEvent(t);zi.active=!1,e.events.emit("touchend",t)}),_t(zi,"_onMove",t=>{if(t.touches.length>0){const e=zi._getGameForEvent(t);zi._updatePosition(t.touches[0],e),e.events.emit("touchmove",t)}});let Di=zi;const Bi=class t{static init(e){if(t.game=e,t._detect(),!t._initialized){if(t._initialized=!0,window.addEventListener("resize",t._onResize),window.addEventListener("orientationchange",t._onOrientationChange),window.matchMedia){const e=window.matchMedia(`(max-width: ${t.MOBILE_BREAKPOINT}px)`),i=window.matchMedia(`(max-width: ${t.TABLET_BREAKPOINT}px)`);e.addEventListener&&(e.addEventListener("change",t._onMediaChange),i.addEventListener("change",t._onMediaChange))}document.addEventListener("visibilitychange",t._onVisibilityChange)}}static _detect(){t.width=window.innerWidth,t.height=window.innerHeight,t.pixelRatio=window.devicePixelRatio||1,t.isMobile=t.width<=t.MOBILE_BREAKPOINT,t.isTablet=t.width>t.MOBILE_BREAKPOINT&&t.width<=t.TABLET_BREAKPOINT,t.isDesktop=t.width>t.TABLET_BREAKPOINT,t.hasTouch="ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0,t.isPortrait=t.height>t.width,t.isLandscape=!t.isPortrait,t.orientation=t.isPortrait?"portrait":"landscape"}static responsive(e,i,s){return 0===t.width&&"undefined"!=typeof window&&t._detect(),void 0===i&&(i=e),void 0===s&&(s=i),t.isMobile?e:t.isTablet?i:s}static scaled(e){return e*t.pixelRatio}static isTouchPrimary(){return t.hasTouch&&(t.isMobile||t.isTablet)}static minDimension(){return Math.min(t.width,t.height)}static maxDimension(){return Math.max(t.width,t.height)}static aspectRatio(){return t.width/t.height}static matches(t){return!!window.matchMedia&&window.matchMedia(t).matches}static prefersReducedMotion(){return t.matches("(prefers-reduced-motion: reduce)")}static prefersDarkMode(){return t.matches("(prefers-color-scheme: dark)")}static async _acquireWakeLock(){if(!t.wakeLockSupported)return!1;try{return t._wakeLock=await navigator.wakeLock.request("screen"),t._wakeLock.addEventListener("release",()=>{t.game&&t.game.events.emit("wakelockrelease")}),t.game&&t.game.events.emit("wakelockacquire"),!0}catch(e){return console.warn("[Screen] Wake lock request failed:",e.message),!1}}static async requestWakeLock(){return t.wakeLockSupported?(t.wakeLockEnabled=!0,await t._acquireWakeLock()):(console.warn("[Screen] Wake Lock API not supported in this browser"),!1)}static async releaseWakeLock(){if(t.wakeLockEnabled=!1,t._wakeLock)try{await t._wakeLock.release(),t._wakeLock=null}catch(e){console.warn("[Screen] Wake lock release failed:",e.message)}}static isWakeLockActive(){return null!==t._wakeLock&&!t._wakeLock.released}};_t(Bi,"MOBILE_BREAKPOINT",768),_t(Bi,"TABLET_BREAKPOINT",1024),_t(Bi,"game",null),_t(Bi,"_initialized",!1),_t(Bi,"width",0),_t(Bi,"height",0),_t(Bi,"pixelRatio",1),_t(Bi,"isMobile",!1),_t(Bi,"isTablet",!1),_t(Bi,"isDesktop",!1),_t(Bi,"hasTouch",!1),_t(Bi,"orientation","landscape"),_t(Bi,"isPortrait",!1),_t(Bi,"isLandscape",!0),_t(Bi,"_wakeLock",null),_t(Bi,"wakeLockEnabled",!1),_t(Bi,"wakeLockSupported",!1),"undefined"!=typeof window&&(Bi._detect(),Bi.wakeLockSupported="wakeLock"in navigator),_t(Bi,"_onResize",()=>{const t=Bi.isMobile,e=Bi.isTablet,i=Bi.orientation;Bi._detect(),Bi.game&&(Bi.game.events.emit("screenresize",{width:Bi.width,height:Bi.height,isMobile:Bi.isMobile,isTablet:Bi.isTablet,isDesktop:Bi.isDesktop}),t===Bi.isMobile&&e===Bi.isTablet||Bi.game.events.emit("devicechange",{isMobile:Bi.isMobile,isTablet:Bi.isTablet,isDesktop:Bi.isDesktop,previous:{isMobile:t,isTablet:e,isDesktop:!t&&!e}}),i!==Bi.orientation&&Bi.game.events.emit("orientationchange",{orientation:Bi.orientation,isPortrait:Bi.isPortrait,isLandscape:Bi.isLandscape}))}),_t(Bi,"_onOrientationChange",()=>{setTimeout(()=>{Bi._onResize()},100)}),_t(Bi,"_onMediaChange",()=>{Bi._onResize()}),_t(Bi,"_onVisibilityChange",async()=>{Bi.wakeLockEnabled&&"visible"===document.visibilityState&&await Bi._acquireWakeLock()});let Ii=Bi;function Ei(t,e={}){var i;if(!(t&&t instanceof Fi))return console.warn("applyAnchor can only be applied to GameObject instances"),t;t._anchor={position:e.anchor??null,margin:e.anchorMargin??10,offsetX:e.anchorOffsetX??0,offsetY:e.anchorOffsetY??0,relative:e.anchorRelative??!1,setTextAlign:!1!==e.anchorSetTextAlign,lastUpdate:0};const s=null==(i=t.update)?void 0:i.bind(t);return t.update=function(e){const i=!0===t._anchor.relative&&t.parent?t.parent:t._anchor.relative;if(t._anchor.position&&(t.boundsDirty||i&&i.boundsDirty||t.parent&&t.parent.boundsDirty)){let e,s,o;if(i){const s={x:i.x,y:i.y,width:i.width,height:i.height};e=kt.calculate(t._anchor.position,t,s,t._anchor.margin,t._anchor.offsetX,t._anchor.offsetY)}else e=kt.calculateAbsolute(t._anchor.position,t,t.game,t._anchor.margin,t._anchor.offsetX,t._anchor.offsetY);!t.parent||(n=t).game&&n.game.pipeline&&n.game.pipeline.gameObjects&&n.game.pipeline.gameObjects.includes(n)?(s=e.x,o=e.y):i===t.parent?(s=e.x-i.x,o=e.y-i.y):(s=e.x-t.parent.x,o=e.y-t.parent.y),t.transform&&"function"==typeof t.transform.position?t.transform.position(s,o):(t.x=s,t.y=o),t._anchor.setTextAlign&&("align"in t&&(t.align=e.align),"baseline"in t&&(t.baseline=e.baseline)),t._anchor.lastUpdate=t.game?t.game.lastTime:Date.now()}var n;s&&s(e)},t}class Fi extends Ze{constructor(t,e={}){super(e),this.game=t,this.parent=null,this.events=new Ci,this._interactive=e.interactive??!1,this._hovered=!1,e.anchor&&Ei(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.getHitTestOffset){const t=c.getHitTestOffset();n-=t.x||0,o-=t.y||0}if(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 Oi extends Fi{constructor(t,e,i={}){const{anchor:s,...n}=i;if(super(t,n),!e||null==e||null==e)throw new Error("GameObjectShapeWrapper requires a shape");this.shape=e,void 0!==i.color&&(e.color=i.color),void 0!==i.stroke&&(e.stroke=i.stroke),void 0!==i.lineWidth&&(e.lineWidth=i.lineWidth),void 0!==i.lineJoin&&(e.lineJoin=i.lineJoin),void 0!==i.lineCap&&(e.lineCap=i.lineCap),void 0!==i.miterLimit&&(e.miterLimit=i.miterLimit),this.syncPropertiesToShape(),this.logger.log(`Created GameObject(${this.constructor.name}):`,{x:this.x,y:this.y,width:this.width,height:this.height,color:this.color,stroke:this.stroke})}syncPropertiesToShape(){if(!this.shape)return;const t=["width","height","rotation","scaleX","scaleY","visible","debug","debugColor"];for(const e of t)e in this&&e in this.shape&&this[e]!==this.shape[e]&&(this.shape[e]=this[e])}get color(){return this.shape?this.shape.color:null}set color(t){this.shape&&(this.shape.color=t)}get stroke(){return this.shape?this.shape.stroke:null}set stroke(t){this.shape&&(this.shape.stroke=t)}get lineWidth(){return this.shape?this.shape.lineWidth:1}set lineWidth(t){this.shape&&(this.shape.lineWidth=t)}get lineJoin(){return this.shape?this.shape.lineJoin:"miter"}set lineJoin(t){this.shape&&(this.shape.lineJoin=t)}get lineCap(){return this.shape?this.shape.lineCap:"butt"}set lineCap(t){this.shape&&(this.shape.lineCap=t)}get miterLimit(){return this.shape?this.shape.miterLimit:10}set miterLimit(t){this.shape&&(this.shape.miterLimit=t)}update(t){var e;this.active&&(null==(e=this.onUpdate)||e.call(this,t),(this._boundsDirty||this.tweening)&&(this.syncPropertiesToShape(),this._boundsDirty=!1),super.update(t))}draw(){super.draw(),this.shape.draw()}}class Li extends Fi{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 Ye.save(),t.render(),Ye.restore(),t})}getDebugBounds(){return{width:this.width,height:this.height,x:-this.width/2,y:-this.height/2}}getBounds(){return{x:this.x,y:this.y,width:this._width||0,height:this._height||0}}bringToFront(t){return this._collection.bringToFront(t)}sendToBack(t){return this._collection.sendToBack(t)}bringForward(t){return this._collection.bringForward(t)}sendBackward(t){return this._collection.sendBackward(t)}clear(){return this._collection.children.forEach(t=>this.remove(t)),this._collection.clear()}get children(){return this._collection.children}getHitTestOffset(){return{x:0,y:0}}isChildHittable(t){return!0}}class Yi extends Li{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,Li.prototype.markBoundsDirty.call(this),this._updatingBoundsFromLayout=!1)}this.scrollable&&!this._scrollDragging&&this._updateScrollMomentum(t),super.update(t)}markBoundsDirty(){this._updatingBoundsFromLayout?this._boundsDirty=!0:(super.markBoundsDirty(),this._layoutDirty=!0)}applyPositionsToChildren(t){Pt(this.children,t,this.getLayoutOffset())}getLayoutOffset(){return{offsetX:0,offsetY:0}}add(t){const e=super.add(t);return this._layoutDirty=!0,e}remove(t){const e=super.remove(t);return this._layoutDirty=!0,e}getScrollAxis(){return{horizontal:!1,vertical:!0}}calculateBounds(){if(this.scrollable&&(this._viewportWidth||this._viewportHeight)){const t=this._viewportWidth??this.width,e=this._viewportHeight??this.height;return{x:-t/2,y:-e/2,width:t,height:e}}return super.calculateBounds()}_getScrollBounds(){const t=this._contentWidth??this.width,e=this._contentHeight??this.height,i=this._viewportWidth??t,s=this._viewportHeight??e,n=Math.max(0,t-i),o=Math.max(0,e-s);return{minX:-n/2,maxX:n/2,minY:-o/2,maxY:o/2}}_clampScrollBounds(){const t=this._getScrollBounds(),e=this.getScrollAxis();e.horizontal&&(this._scrollOffset.x<t.minX?(this._scrollOffset.x+=(t.minX-this._scrollOffset.x)*this.scrollBounce,this._scrollVelocity.x=0):this._scrollOffset.x>t.maxX&&(this._scrollOffset.x+=(t.maxX-this._scrollOffset.x)*this.scrollBounce,this._scrollVelocity.x=0)),e.vertical&&(this._scrollOffset.y<t.minY?(this._scrollOffset.y+=(t.minY-this._scrollOffset.y)*this.scrollBounce,this._scrollVelocity.y=0):this._scrollOffset.y>t.maxY&&(this._scrollOffset.y+=(t.maxY-this._scrollOffset.y)*this.scrollBounce,this._scrollVelocity.y=0))}_updateScrollMomentum(t){const e=this.getScrollAxis();e.horizontal&&(this._scrollVelocity.x*=this.scrollFriction,Math.abs(this._scrollVelocity.x)<this.scrollThreshold&&(this._scrollVelocity.x=0),this._scrollOffset.x+=this._scrollVelocity.x*t*60),e.vertical&&(this._scrollVelocity.y*=this.scrollFriction,Math.abs(this._scrollVelocity.y)<this.scrollThreshold&&(this._scrollVelocity.y=0),this._scrollOffset.y+=this._scrollVelocity.y*t*60),this._clampScrollBounds()}_setupScrollInteraction(){this.interactive=!0,this._scrollInputDownHandler=t=>{this._isPointInViewport(t.x,t.y)&&this._onScrollDragStart(t)},this._scrollInputMoveHandler=t=>this._onScrollDragMove(t),this._scrollInputUpHandler=t=>this._onScrollDragEnd(t),this.game.events.on("inputdown",this._scrollInputDownHandler),this.game.events.on("inputmove",this._scrollInputMoveHandler),this.game.events.on("inputup",this._scrollInputUpHandler)}_isPointInViewport(t,e){let i=t-this.x,s=e-this.y,n=this.parent;for(;n;)i-=n.x||0,s-=n.y||0,n=n.parent;const o=(this._viewportWidth??this.width)/2,r=(this._viewportHeight??this.height)/2;return i>=-o&&i<=o&&s>=-r&&s<=r}_onScrollDragStart(t){this._scrollDragging=!0,this._scrollDragStart={x:t.x,y:t.y},this._scrollDragStartOffset={...this._scrollOffset},this._lastDragPosition={x:t.x,y:t.y},this._lastDragTime=performance.now(),this._scrollVelocity={x:0,y:0}}_onScrollDragMove(t){if(!this._scrollDragging)return;const e=this.getScrollAxis(),i=performance.now(),s=Math.max(1,i-this._lastDragTime)/1e3;if(e.horizontal){const e=t.x-this._scrollDragStart.x;this._scrollOffset.x=this._scrollDragStartOffset.x+e,this._scrollVelocity.x=(t.x-this._lastDragPosition.x)/(60*s)}if(e.vertical){const e=t.y-this._scrollDragStart.y;this._scrollOffset.y=this._scrollDragStartOffset.y+e,this._scrollVelocity.y=(t.y-this._lastDragPosition.y)/(60*s)}this._lastDragPosition={x:t.x,y:t.y},this._lastDragTime=i}_onScrollDragEnd(){this._scrollDragging=!1}_needsScrolling(){if(!this.scrollable)return!1;const t=this._contentWidth??this.width,e=this._contentHeight??this.height,i=this._viewportWidth??t,s=this._viewportHeight??e,n=this.getScrollAxis();return!!(n.horizontal&&t>i)||!!(n.vertical&&e>s)}draw(){this._needsScrolling()?this._drawScrollable():super.draw()}_drawScrollable(){this.applyTransforms(),this.drawDebug();const t=this.padding??0,e=(this._viewportWidth??this.width)-2*t,i=(this._viewportHeight??this.height)-2*t;Ye.save(),Ye.ctx.beginPath(),Ye.ctx.rect(-e/2,-i/2,e,i),Ye.ctx.clip(),Ye.ctx.beginPath(),Ye.ctx.translate(this._scrollOffset.x,this._scrollOffset.y),this._collection.getSortedChildren().filter(t=>t.visible).forEach(t=>{Ye.save(),t.render(),Ye.restore()}),Ye.restore()}scrollTo(t,e){const i=this.getScrollAxis();i.horizontal&&(this._scrollOffset.x=t),i.vertical&&(this._scrollOffset.y=e),this._scrollVelocity={x:0,y:0}}scrollBy(t,e){const i=this.getScrollAxis();i.horizontal&&(this._scrollOffset.x+=t),i.vertical&&(this._scrollOffset.y+=e)}getScrollPosition(){return{...this._scrollOffset}}resetScroll(){this._scrollOffset={x:0,y:0},this._scrollVelocity={x:0,y:0}}getHitTestOffset(){var t,e;return this.scrollable?{x:(null==(t=this._scrollOffset)?void 0:t.x)||0,y:(null==(e=this._scrollOffset)?void 0:e.y)||0}:{x:0,y:0}}isChildHittable(t){var e,i;if(!this.scrollable||!this._needsScrolling())return!0;const s=this.getScrollAxis(),n=this._viewportWidth??this.width,o=this._viewportHeight??this.height,r=(null==(e=this._scrollOffset)?void 0:e.x)||0,a=(null==(i=this._scrollOffset)?void 0:i.y)||0,h=t.x+r,l=t.y+a,c=(t.width||0)/2,u=(t.height||0)/2;return(!s.horizontal||!(h+c<-n/2||h-c>n/2))&&(!s.vertical||!(l+u<-o/2||l-u>o/2))}}class Xi extends Fi{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&&(Ye.save(),t.render(),Ye.restore())}calculateBounds(){if(0===this._frames.length)return{x:this.x,y:this.y,width:0,height:0};let t=1/0,e=1/0,i=-1/0,s=-1/0;return this._frames.forEach(n=>{const o=n.getBounds();t=Math.min(t,o.x),e=Math.min(e,o.y),i=Math.max(i,o.x+o.width),s=Math.max(s,o.y+o.height)}),{x:t+this.x,y:e+this.y,width:i-t,height:s-e}}toString(){return`[Sprite frames=${this.totalFrames} current=${this.currentFrame} playing=${this.isPlaying}]`}}class Wi extends Xi{constructor(t,e={}){super(t,{frameRate:e.frameRate||12,loop:void 0===e.loop||e.loop,autoPlay:!1,...e}),this._src=e.src,this._frameWidth=e.frameWidth,this._frameHeight=e.frameHeight,this._columns=e.columns,this._rows=e.rows,this._frameCount=e.frameCount||e.columns*e.rows,this._startFrame=e.startFrame||0,this._smoothing=void 0!==e.smoothing&&e.smoothing,this._autoPlayAfterLoad=e.autoPlay||!1,this._loaded=!1,this._loading=!1,this._image=null,this._frameCanvases=[],this.width=this._frameWidth,this.height=this._frameHeight}static async create(t,e){const i=new Wi(t,e);return await i.load(),i}async load(){if(this._loaded||this._loading)return this;this._loading=!0;try{return this._image=await this._loadImage(this._src),await this._sliceFrames(),this._loaded=!0,this._loading=!1,this._autoPlayAfterLoad&&this.play(),this}catch(t){throw this._loading=!1,console.error("SpriteSheet.load failed:",t),t}}_loadImage(t){return new Promise((e,i)=>{const s=new Image;s.onload=()=>e(s),s.onerror=e=>i(new Error(`Failed to load image: ${t}`)),s.src=t})}async _sliceFrames(){const{_image:t,_frameWidth:e,_frameHeight:i,_columns:s}=this;this.clearFrames(),this._frameCanvases=[];for(let n=this._startFrame;n<this._startFrame+this._frameCount;n++){const o=n%s*e,r=Math.floor(n/s)*i,a=document.createElement("canvas");a.width=e,a.height=i;const h=a.getContext("2d");h.imageSmoothingEnabled=this._smoothing,h.drawImage(t,o,r,e,i,0,0,e,i),this._frameCanvases.push(a);const l=new Si(a,{width:e,height:i,anchor:"center",smoothing:this._smoothing});this.addFrame(l)}}get loaded(){return this._loaded}get loading(){return this._loading}get frameWidth(){return this._frameWidth}get frameHeight(){return this._frameHeight}get columns(){return this._columns}get rows(){return this._rows}update(t){this._loaded&&super.update(t)}draw(){this._loaded&&super.draw()}toString(){return`[SpriteSheet src="${this._src}" frames=${this._frameCount} loaded=${this._loaded}]`}}class Hi extends Oi{constructor(t,e,i={}){super(t,new Mi(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(!Ye.ctx)return 0;return Ye.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 Ui{constructor(t={}){this.shape=t.shape||"circle",this.x=t.x??0,this.y=t.y??0,this.scaleX=t.scaleX??1,this.scaleY=t.scaleY??1,this.radius=t.radius??100,this.width=t.width??200,this.height=t.height??200,this.cornerRadius=t.cornerRadius??0,this.radiusX=t.radiusX??100,this.radiusY=t.radiusY??100,this.pathFn=t.pathFn??null,this.invert=t.invert??!1,this._applied=!1}apply(t){this._applied?console.warn("Mask already applied. Call remove() first."):(t.save(),t.beginPath(),this.invert?(t.rect(-1e4,-1e4,2e4,2e4),this._drawPath(t),t.clip("evenodd")):(this._drawPath(t),t.clip()),this._applied=!0)}remove(t){this._applied&&(t.restore(),this._applied=!1)}_drawPath(t){const e=this.scaleX,i=this.scaleY;switch(this.shape){case"circle":const s=(e+i)/2;t.arc(this.x,this.y,this.radius*s,0,2*Math.PI);break;case"rectangle":const n=this.width*e,o=this.height*i,r=this.cornerRadius*Math.min(e,i);r>0?this._roundedRect(t,this.x-n/2,this.y-o/2,n,o,r):t.rect(this.x-n/2,this.y-o/2,n,o);break;case"ellipse":t.ellipse(this.x,this.y,this.radiusX*e,this.radiusY*i,0,0,2*Math.PI);break;case"path":this.pathFn&&this.pathFn(t,this);break;default:console.warn(`Unknown mask shape: ${this.shape}`)}}_roundedRect(t,e,i,s,n,o){o=Math.min(o,s/2,n/2),t.moveTo(e+o,i),t.lineTo(e+s-o,i),t.arcTo(e+s,i,e+s,i+o,o),t.lineTo(e+s,i+n-o),t.arcTo(e+s,i+n,e+s-o,i+n,o),t.lineTo(e+o,i+n),t.arcTo(e,i+n,e,i+n-o,o),t.lineTo(e,i+o),t.arcTo(e,i,e+o,i,o),t.closePath()}setPosition(t,e){return this.x=t,this.y=e,this}setScale(t){return this.scaleX=t,this.scaleY=t,this}setScaleXY(t,e){return this.scaleX=t,this.scaleY=e,this}static circle(t,e,i){return new Ui({shape:"circle",x:t,y:e,radius:i})}static rectangle(t,e,i,s,n=0){return new Ui({shape:"rectangle",x:t,y:e,width:i,height:s,cornerRadius:n})}static ellipse(t,e,i,s){return new Ui({shape:"ellipse",x:t,y:e,radiusX:i,radiusY:s})}}class Gi{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)=>Gi.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[Gi.lerp(s,n,i)%360,Gi.lerp(t[1],e[1],i),Gi.lerp(t[2],e[2],i)]}}function Ni(t,e,i,s,n,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=rs._frame(s,n,o,r,a,h),f=1/(i+1),p=Math.min(Math.floor(c/f),i),g=c%f/f,m=t*Math.pow(.6,p),v=e-Math.sin(g*Math.PI)*(e-m);return rs.animationResult({y:v,segment:p,bounceHeight:m},l,o,u,d)}function qi(t,e,i,s,n,o,r=!0,a=null,h={},l=null){if(i<=0)return rs.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}=rs._frame(e,i,r,a,h,l);l={...l,...g};const m=e*s,v=Math.max(0,Math.min(1,n)),y=c+(Math.sin(.7*m)+.4*v*Math.sin(2.3*m+.5))*o,_=u+(Math.cos(.9*m)+.4*v*Math.cos(1.9*m+.7))*o,x=.7*Math.cos(.7*m)+.4*v*2.3*Math.cos(2.3*m+.5),b=-.9*Math.sin(.9*m)+.4*v*-1.9*Math.sin(1.9*m+.7),w=Math.sqrt(x*x+b*b),M=w>.8,S=Math.sqrt((y-c)*(y-c)+(_-u)*(_-u));return rs.animationResult({x:y,y:_,centerX:c,centerY:u,offsetX:y-c,offsetY:_-u,distance:S,moving:M,velocity:w},d,r,p,l)}function Zi(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}=rs._frame(i,s,n,o,r,a);if(!a||!a.pathData){const i={segmentLengths:[],totalLength:0,points:[...t]};for(let e=0;e<t.length-1;e++){const s=t[e],n=t[e+1],o=n[0]-s[0],r=n[1]-s[1],a=Math.sqrt(o*o+r*r);i.segmentLengths.push(a),i.totalLength+=a}if(e){const e=t[t.length-1],s=t[0],n=s[0]-e[0],o=s[1]-e[1],r=Math.sqrt(n*n+o*o);i.segmentLengths.push(r),i.totalLength+=r}u.pathData=i}const{segmentLengths:d,totalLength:f,points:p}=u.pathData,g=l*f;let m=0,v=0;for(let S=0;S<d.length;S++){if(m+d[S]>=g){v=S;break}m+=d[S]}const y=(g-m)/d[v],_=p[v],x=v<p.length-1?p[v+1]:p[0],b=Gi.lerp(_[0],x[0],y),w=Gi.lerp(_[1],x[1],y),M=Math.atan2(x[1]-_[1],x[0]-_[0]);return rs.animationResult({x:b,y:w,angle:M,segmentIndex:v,segmentProgress:y,pathProgress:l},h,n,c,u)}function Vi(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}=rs._frame(o,r,a,l,c,u),m=n+(h?1:-1)*f*Math.PI*2,v=t+i*Math.cos(m),y=e+s*Math.sin(m);return rs.animationResult({x:v,y:y,angle:m},d,a,p,g)}function $i(t,e,i,s,n=!0,o=null,r={},a=null){const{t:h,easedT:l,completed:c,state:u}=rs._frame(i,s,n,o,r,a),d=(e-t)/2,f=t+d+d*Math.sin(l*Math.PI*2);return rs.animationResult({value:f},h,n,c,u)}function ji(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 rs.animationResult({value:p,direction:l.direction},c,o||r&&!u,u,g)}function Ki(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 rs.animationResult({x:c,y:u,moving:!l,direction:d,distanceFromCenter:g},p,r,!1,a)}function Ji(t,e,i,s,n=!0,o=!1,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=rs._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 rs.animationResult({angle:p},l,n,u,d)}function Qi(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(),rs.animationResult({value:h,phase:c},l,n,u)}function ts(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){const{t:l,easedT:c,completed:u,state:d}=rs._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 rs.animationResult({y:p},l,n,u,d)}function es(t,e,i,s,n,o,r,a,h=!1,l=null,c={},u=null){const{t:d,easedT:f,completed:p,state:g}=rs._frame(r,a,h,l,c,u),m=Math.pow(1-f,o),v=f*Math.PI*2*n,y=f*Math.PI*2*n*1.3,_=m*i*(.6*Math.sin(v)+.3*Math.sin(2.5*v)+.1*Math.sin(5.6*v)),x=m*s*(.6*Math.cos(y)+.3*Math.cos(2.7*y)+.1*Math.cos(6.3*y));let b=t+_,w=e+x;if(f>.9){const i=(f-.9)/.1;b=t+_*(1-i),w=e+x*(1-i)}return rs.animationResult({x:b,y:w,intensity:m},d,h,p,g)}function is(t,e,i,s,n,o,r,a,h=!1,l=!1,c=null,u={},d=null){d||(d={started:!1,loopCount:0,direction:1,lastDirection:1});let f=a>0?r/a:1,p=!1,g={...u};if(l||h)if(h)if(l){const t=2*a,e=r%t,i=Math.floor(r/t),s=e<a?1:-1;f=1===s?e/a:2-e/a,s!==d.direction&&(d.direction=s,1===d.direction&&g.onLoop&&g.onLoop(i)),i>d.loopCount&&(d.loopCount=i)}else{f%=1;const t=Math.floor(r/a);t>d.loopCount&&g.onLoop&&(g.onLoop(t),d.loopCount=t)}else l&&!h&&(f<=1?d.direction=1:f<=2?(f=2-f,d.direction=-1):(f=0,p=!0,d.direction=1));else f>=1&&(f=1,p=!0);!d.started&&g.onStart&&(g.onStart(),d.started=!0),p&&!d.completed&&g.onComplete&&(g.onComplete(),d.completed=!0);const m=c?c(f):f,v=Gi.lerp(i,s,m),y=n+m*o*Math.PI*2,_=t+v*Math.cos(y),x=e+v*Math.sin(y),b={...d,lastDirection:d.direction};return rs.animationResult({x:_,y:x,radius:v,angle:y,direction:d.direction},f,h||l&&!p,p,b)}function ss(t,e,i,s,n=!1,o=!1,r={},a={}){if(s<=0)return this.animationResult({value:e,velocity:0,done:!0,phase:"complete"},1,!1,!0);let h,l,c,u=i/s,d="forward",f=0;n?(f=Math.floor(u),u%=1,f>0&&a.onLoop&&a.onLoop(f)):u>1&&(u=1),u>0&&i<=s&&a.onStart&&a.onStart(),o?u>=.5?(h=t,l=e,c=2*(u-.5),d="return",u>=.5&&u<.51&&a.onYoyoTurn&&a.onYoyoTurn()):(h=e,l=t,c=2*u,d="forward"):(h=e,l=t,c=u);const p=void 0!==r.stiffness?r.stiffness:.3,g=void 0!==r.damping?r.damping:.6,m=Math.max(.1,1/(1.5*g)),v=Math.max(.1,.8/(1.5*p+.5));let y;if(c<.99)y=re.easeOutElastic(c,m,v);else{const t=(c-.99)/.01;y=re.easeOutElastic(.99,m,v)*(1-t)+1*t}const _=Gi.lerp(l,h,y),x=Math.min(c+.01,1);let b;if(x<.99)b=re.easeOutElastic(x,m,v);else{const t=(x-.99)/.01;b=re.easeOutElastic(.99,m,v)*(1-t)+1*t}const w=(Gi.lerp(l,h,b)-_)/.01*s,M=!n&&u>=1;return M&&a.onComplete&&a.onComplete(),rs.animationResult({value:_,velocity:w,delta:"forward"===d?e-_:t-_,done:M,phase:d},u,n,M)}function ns(t,e,i,s,n,o=!0,r=!0,a=null,h={},l=null){const{t:c,easedT:u,completed:d,state:f}=rs._frame(s,n,o,a,h,l),p=(r?Math.sin(u*Math.PI*2):Math.sin(u*Math.PI))*i;return rs.animationResult({angle:p},c,o,d,f)}function os(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"),rs._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 w=0;w<i.length;w++){const t=(w+1)%i.length;if(!o&&w===i.length-1)break;const e=i[t][0]-i[w][0],s=i[t][1]-i[w][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,v=1,y=!0,_=0,x=0,b=!1;if(g<n)_=g/n,m=0,v=1,y=!0;else{g-=n;for(let t=0;t<i.length;t++){if(!o&&t===i.length-1){m=t,v=t,y=!0,_=1,b=!0;break}const e=(t+1)%i.length,h=i[e][0]-i[t][0],l=i[e][1]-i[t][1],c=(Math.abs(h)+Math.abs(l))/s;if(g<c){m=t,v=e,y=!1,x=g/c;break}if(g-=c,g<n){m=e,v=(e+1)%i.length,y=!0,_=g/n,a.lastWaypointReached!==m&&(r.onWaypointReached&&r.onWaypointReached(m),r.onWaitStart&&r.onWaitStart(m),a.lastWaypointReached=m);break}g-=n}}if(y||b)d=i[m][0],f=i[m][1],p="idle",!a.isWaiting&&y&&r.onWaitEnd&&r.onWaitEnd(m);else{const t=i[m],e=i[v],s=e[0]-t[0],n=e[1]-t[1],o=Math.abs(s)+Math.abs(n),r=Math.abs(s)/o;if(x<=r&&0!==s){const e=x/r;d=t[0]+s*e,f=t[1],p=s>0?"right":"left"}else{const i=(x-r)/(1-r);d=e[0],f=t[1]+n*i,p=n>0?"down":"up"}}return a.currentWaypoint=m,a.nextWaypoint=v,a.isWaiting=y,!a.completed&&b&&r.onPatrolComplete&&(r.onPatrolComplete(),a.completed=!0),rs.animationResult({x:d,y:f,moving:!y,waiting:y,waitProgress:y?_:0,direction:p,waypoint:m,nextWaypoint:v},u,o,b,a)}class rs{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 $i(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 ji(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 qi(t,e,i,s,n,o,r,a,h,l)}static spring(t,e,i,s,n=!1,o=!1,r={},a={}){return ss(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 ns(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 Ji(t,e,i,s,n,o,r,a,h)}static pulse(t,e,i,s,n=!0,o=!1,r=null,a={}){return Qi(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 is(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 Vi(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 as(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 Ni(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 es(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 Zi(t,e,i,s,n,o,r,a)}static waypoint(t,e,i,s,n,o=!0,r={},a=null){return os(0,e,i,s,n,o,r,a)}static patrol(t,e,i,s,n,o,r=!0,a=null){return Ki(t,e,i,s,n,o,r,a)}static hop(t,e,i,s,n=!0,o=!0,r=null,a={},h=null){return ts(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 y=t.length-1;y>=0;y--)if(l>=h.animStartTimes[y]){c=y;break}h.currentAnim=c;const u=l-h.animStartTimes[c],d=i[c],f=t[c],p=[...e[c]];f===this.parabolic||f===this.oscillate||f===this.pulse?(p[3]=u,p[4]=d,p[5]=!1,o&&o[c]&&(p[6]=o[c])):f===this.spring?(p[2]=u,p[3]=d,p[4]=!1):f===this.spiral||f===this.bezier?(p[6]=u,p[7]=d,p[8]=!1,o&&o[c]&&(p[9]=o[c])):f===this.orbit?(p[5]=u,p[6]=d,p[7]=!1,o&&o[c]&&(p[9]=o[c])):f===this.bounce||f===this.shake?(p[6]=u,p[7]=d,p[8]=!1,o&&o[c]&&(p[9]=o[c])):f===this.followPath&&(p[2]=u,p[3]=d,p[4]=!1,o&&o[c]&&(p[5]=o[c]));const g=a&&a[c]?a[c]:{},m=f.apply(this,[...p,g,h.animationStates[c]]);h.animationStates[c]=m.state;const v=!n&&l>=h.totalDuration;return v&&!h.completed&&r.onComplete&&(r.onComplete(),h.completed=!0),this.animationResult({...m,currentAnim:c,totalAnimations:t.length,sequenceProgress:Math.min(l/h.totalDuration,1)},l/h.totalDuration,n,v,h)}}function as(t,e,i,s,n,o,r=!1,a=!1,h=null,l={},c=null){if(o<=0)return rs.animationResult({x:s[0],y:s[1],phase:"complete"},1,!1,!0);let u=n/o,d="forward",f=0;r?(f=Math.floor(u),u%=1,f>0&&l.onLoop&&l.onLoop(f)):u>1&&(u=1),u>0&&n<=o&&l.onStart&&l.onStart();let p=h?h(u):u;a&&(u>=.5?(p=1-2*(u-.5),d="return",u>=.5&&u<.51&&l.onYoyoTurn&&l.onYoyoTurn()):(p=2*u,d="forward"),p=h?h(p):p);const g=3*(e[0]-t[0]),m=3*(i[0]-e[0])-g,v=s[0]-t[0]-g-m,y=3*(e[1]-t[1]),_=3*(i[1]-e[1])-y,x=s[1]-t[1]-y-_,b=v*Math.pow(p,3)+m*Math.pow(p,2)+g*p+t[0],w=x*Math.pow(p,3)+_*Math.pow(p,2)+y*p+t[1],M=!r&&u>=1;return M&&l.onComplete&&l.onComplete(),rs.animationResult({x:b,y:w,phase:d},u,r,M,c)}class hs{constructor(t,e,i,s,n={}){this.target=t,this.toProps={...e},this.duration=i,this.easingFn=s||re.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 hs(t,e,i,s,n);return hs._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]=Gi.lerp(t,e,s)}this.onUpdate&&this.onUpdate(),i>=1&&(this._finished=!0,this.onComplete&&this.onComplete())}static updateAll(t){for(const e of hs._active)e.update(t);hs._active=hs._active.filter(t=>!t._finished)}static killTarget(t){hs._active=hs._active.filter(e=>e.target!==t)}static killAll(){hs._active=[]}}class ls 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];!t.isChildHittable||t.isChildHittable(s)?s instanceof Li?this._hoverScene(s,e):this._hoverObject(s,e):s._hovered&&(s._hovered=!1,s.events.emit("mouseout",e))}this._hoverObject(t,e)}dispatchInputEvent(t,e){var i;for(let s=this.gameObjects.length-1;s>=0;s--){const n=this.gameObjects[s];if(n instanceof Li){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 Li?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(!t.isChildHittable||t.isChildHittable(n))if(n instanceof Li){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)),hs.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 cs{constructor(t){wt(this,k,0),wt(this,P,0),this.canvas=t,this.ctx=t.getContext("2d"),this.events=new Ci,this._cursor=null,this.lastTime=0,this.dt=0,this.running=!1,this._frame=0,this.pipeline=new ls(this),Ye.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(){Di.init(this)}initInput(){Ti.init(this)}initKeyboard(){Ai.init(this)}initIO(){this.initMouse(),this.initTouch(),this.initInput(),this.initKeyboard()}initMotion(){hs._active=[]}initLogging(){this.logger=new ke("Game"),ke.setOutput(console),ke.disableAll(),ke.disable(),ke.setLevel(ke.INFO),this.logger.groupCollapsed("Initializing Game...")}enableLogging(){ke.enable()}disableLogging(){ke.disableAll(),ke.disable()}markBoundsDirty(){this._boundsDirty=!0}get boundsDirty(){return this._boundsDirty}set boundsDirty(t){this._boundsDirty=t}enableFluidSize(t=window,e={}){const{top:i=0,right:s=0,bottom:n=0,left:o=0}=e;if(t===window){const t=()=>{var t;this.canvas.width=window.innerWidth-o-s,this.canvas.height=window.innerHeight-i-n,bt(this,k)===this.canvas.width&&bt(this,P)===this.canvas.height||(this.markBoundsDirty(),null==(t=this.onResize)||t.call(this)),Mt(this,k,this.canvas.width),Mt(this,P,this.canvas.height)};t(),window.addEventListener("resize",t),this._fluidResizeCleanup=()=>{window.removeEventListener("resize",t)}}else{if(!("ResizeObserver"in window))return void console.warn("ResizeObserver not supported in this browser.");const e=()=>{const e=t.getBoundingClientRect();this.canvas.width=e.width-o-s,this.canvas.height=e.height-i-n},r=new ResizeObserver(()=>{e()});r.observe(t),e(),this._fluidResizeCleanup=()=>r.disconnect()}}disableFluidSize(){this._fluidResizeCleanup&&(this._fluidResizeCleanup(),this._fluidResizeCleanup=null)}start(){if(this.logger.groupCollapsed("[Game] Starting..."),this.init(),!this._init)throw new Error("Game not initialized. Did you call init()? Remember to call super.init() in your subclass.");this.running=!0,this.loop=this.loop.bind(this),requestAnimationFrame(this.loop),this.logger.log("[Game] Started"),this.logger.groupEnd()}stop(){this.running=!1,this.logger.log("[Game] Stopped")}restart(){this.pipeline.clear(),this.init(),this.start(),this.logger.log("[Game] Restarted")}loop(t){if(!this.running)return;const e=t-this.lastTime;if(this.lastTime=t,this._accumulator+=e,this.actualFps=1e3/e,this._accumulator>=this._frameInterval){const t=this._frameInterval/1e3;this.dt=t,this._frame++,this.logger.groupCollapsed(`Frame #${this._frame}`),this.logger.time("render time"),this.update(t),this.render(),this.logger.timeEnd("render time"),this.logger.groupEnd(),this._accumulator-=this._frameInterval}this.boundsDirty&&(this.boundsDirty=!1),requestAnimationFrame(this.loop)}update(t){this.pipeline.update(t)}render(){Ye.setContext(this.ctx),this.running&&this.clear(),this.pipeline.render()}clear(){Ye.clear()}get width(){return this.canvas.width}get height(){return this.canvas.height}set backgroundColor(t){this.canvas.style.backgroundColor=t}set cursor(t){this._cursor&&(this._cursor.destroy(),this.pipeline.remove(this._cursor)),this._cursor=t,this._cursor.activate(),this.pipeline.add(t)}get cursor(){return this._cursor}resetCursor(){this._cursor&&(this._cursor.destroy(),this.pipeline.remove(this._cursor),this._cursor=null)}enablePauseOnBlur(t){this._pauseOnBlur=t,t?window.addEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1):window.removeEventListener("visibilitychange",this._handleVisibilityChange.bind(this),!1)}_handleVisibilityChange(){this.logger.log("Visibility change detected"),document.hidden?this._pauseOnBlur&&this.running&&(this._isPaused=!0,this.stop(),this.logger.log("Paused due to tab visibility change")):this._isPaused&&(this._isPaused=!1,this.start(),this.logger.log("Resumed after tab visibility change"))}}k=new WeakMap,P=new WeakMap;const us={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 ds extends Fi{constructor(t,e={}){super(t,e);const{x:i=0,y:s=0,width:n=120,height:o=40,text:r="Button",font:a="14px monospace",textColor:h="#000",textAlign:l="center",textBaseline:c="middle",shape:u=null,label:d=null,onClick:f=null,onHover:p=null,onPressed:g=null,onRelease:m=null,padding:v=10,colorDefaultBg:y=us.button.default.bg,colorDefaultStroke:_=us.button.default.stroke,colorDefaultText:x=us.button.default.text,colorHoverBg:b=us.button.hover.bg,colorHoverStroke:w=us.button.hover.stroke,colorHoverText:M=us.button.hover.text,colorPressedBg:S=us.button.pressed.bg,colorPressedStroke:C=us.button.pressed.stroke,colorPressedText:T=us.button.pressed.text}=e;this.x=i,this.y=s,this.width=Math.max(n,44),this.height=Math.max(o,44),this.padding=v,this.textAlign=l,this.textBaseline=c,this.initColorScheme({colorDefaultBg:y,colorDefaultStroke:_,colorDefaultText:x,colorHoverBg:b,colorHoverStroke:w,colorHoverText:M,colorPressedBg:S,colorPressedStroke:C,colorPressedText:T}),this.initBackground(u),this.initLabel(r,a,h,d),this.initGroup(),this.initEvents(f,p,g,m),this.setState("default")}initColorScheme(t){this.colors={default:{bg:t.colorDefaultBg,stroke:t.colorDefaultStroke,text:t.colorDefaultText},hover:{bg:t.colorHoverBg,stroke:t.colorHoverStroke,text:t.colorHoverText},pressed:{bg:t.colorPressedBg,stroke:t.colorPressedStroke,text:t.colorPressedText}}}initBackground(t){this.bg=t??new Qe({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 Mi(t,{font:e,color:i,align:this.textAlign,baseline:this.textBaseline}),this.alignText()}alignText(){if(!this.label)return;const t=this.width/2,e=this.height/2,i=(this.label._width||0)/2,s=(this.label._height||0)/2;switch(this.textAlign){case"left":this.label.x=-t+this.padding+i;break;case"right":this.label.x=t-this.padding-i;break;default:this.label.x=0}switch(this.textBaseline){case"top":this.label.y=-e+this.padding+s;break;case"bottom":this.label.y=e-this.padding-s;break;default:this.label.y=0}}initGroup(){this.group=new $e,this.group.add(this.bg),this.group.add(this.label)}initEvents(t,e,i,s){this.interactive=!0,this.onHover=e,this.onPressed=i,this.onRelease=s,this._pointerOver=!1,this._isTouch=!1,this.on("mouseover",t=>{this._pointerOver=!0,this._isTouch||this.setState("hover")}),this.on("mouseout",t=>{this._pointerOver=!1,this._isTouch||this.setState("default")}),this.on("inputdown",t=>{(t.touches||t.nativeEvent&&"touchstart"===t.nativeEvent.type)&&(this._isTouch=!0,t.nativeEvent&&t.nativeEvent.preventDefault()),this._pointerOver=!0,this.setState("pressed")}),this.on("inputup",e=>{const i="pressed"===this.state;(e.touches||e.nativeEvent&&"touchend"===e.nativeEvent.type)&&(e.nativeEvent&&e.nativeEvent.preventDefault(),this._isTouch=!0);const s=this._hitTest&&this._hitTest(e.x,e.y);i&&s&&"function"==typeof t&&t(),s&&!this._isTouch?this.setState("hover"):(this.setState("default"),this._isTouch&&setTimeout(()=>{this._isTouch=!1},300))}),this.on("inputmove",t=>{this._hitTest&&this._hitTest(t.x,t.y)?this._pointerOver=!0:(this._pointerOver=!1,"hover"!==this.state||this._isTouch||this.setState("default"))})}setState(t){var e,i,s;if(this.state!==t)switch(this.state=t,t){case"default":this.game.cursor&&setTimeout(()=>{this.game.cursor.activate()},0),this.bg.color=this.colors.default.bg,this.bg.stroke=this.colors.default.stroke,this.label.color=this.colors.default.text,this.game.canvas.style.cursor="default",null==(e=this.onRelease)||e.call(this);break;case"hover":this.game.cursor&&this.game.cursor.deactivate(),this.bg.color=this.colors.hover.bg,this.bg.stroke=this.colors.hover.stroke,this.label.color=this.colors.hover.text,this.game.canvas.style.cursor="pointer",null==(i=this.onHover)||i.call(this);break;case"pressed":this.game.cursor&&this.game.cursor.deactivate(),this.bg.color=this.colors.pressed.bg,this.bg.stroke=this.colors.pressed.stroke,this.label.color=this.colors.pressed.text,this.game.canvas.style.cursor="pointer",null==(s=this.onPressed)||s.call(this)}}update(t){super.update(t),this._boundsDirty&&this.alignText()}get text(){return this.label.text}set text(t){this.label.text=t,this._boundsDirty=!0}setTextAlign(t){this.textAlign=t,this.label.align=t,this._boundsDirty=!0}setTextBaseline(t){this.textBaseline=t,this.label.baseline=t,this._boundsDirty=!0}setFont(t){this.label.font=t,this._boundsDirty=!0}resize(t,e){this.width=t,this.height=e,this.bg.width=t,this.bg.height=e,this._boundsDirty=!0}getBounds(){return{x:this.x,y:this.y,width:this.width,height:this.height}}draw(){super.draw(),this.group.render()}}class fs{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 ps{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 gs={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}}},ms="\nprecision highp float;\n\nattribute vec2 aPosition; // Screen position (pixels, already projected)\nattribute float aSize; // Point size in pixels\nattribute vec4 aColor; // RGBA color (0-1 range)\n\nvarying vec4 vColor;\n\nuniform vec2 uResolution; // Canvas dimensions\n\nvoid main() {\n // Convert from pixel coords to clip space (-1 to 1)\n vec2 clipPos = (aPosition / uResolution) * 2.0 - 1.0;\n clipPos.y = -clipPos.y; // Flip Y (canvas Y is down, GL Y is up)\n\n gl_Position = vec4(clipPos, 0.0, 1.0);\n gl_PointSize = aSize;\n vColor = aColor;\n}\n",vs="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n // gl_PointCoord is 0-1 UV within the point quad\n vec2 coord = gl_PointCoord - vec2(0.5);\n float dist = length(coord);\n\n // Discard pixels outside circle\n if (dist > 0.5) {\n discard;\n }\n\n // Soft edge for anti-aliasing\n float alpha = vColor.a * (1.0 - smoothstep(0.4, 0.5, dist));\n gl_FragColor = vec4(vColor.rgb, alpha);\n}\n",ys="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n vec2 coord = gl_PointCoord - vec2(0.5);\n float dist = length(coord);\n\n if (dist > 0.5) {\n discard;\n }\n\n // Radial falloff for glow effect\n float glow = 1.0 - (dist * 2.0);\n glow = glow * glow; // Quadratic falloff\n\n float alpha = vColor.a * glow;\n vec3 color = vColor.rgb * (0.5 + glow * 0.5); // Brighten center\n\n gl_FragColor = vec4(color, alpha);\n}\n",_s="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n gl_FragColor = vColor;\n}\n",xs="\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n vec2 coord = abs(gl_PointCoord - vec2(0.5)) * 2.0; // 0 at center, 1 at edge\n float d = max(coord.x, coord.y);\n\n // Soft edge\n float alpha = vColor.a * (1.0 - smoothstep(0.8, 1.0, d));\n gl_FragColor = vec4(vColor.rgb, alpha);\n}\n",bs={circle:{vertex:ms,fragment:vs},glow:{vertex:ms,fragment:ys},square:{vertex:ms,fragment:_s},softSquare:{vertex:ms,fragment:xs}};class ws{constructor(t=1e4,e={}){if(this.maxParticles=t,this.width=e.width||800,this.height=e.height||600,this.shape=e.shape||"circle",this.blendMode=e.blendMode||"alpha",this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!1,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for particle rendering"),void(this.available=!1);this.available=!0,this._positions=new Float32Array(2*t),this._sizes=new Float32Array(t),this._colors=new Float32Array(4*t),this._initGL(),this._createBuffers(),this._compileShaders(),this._setupBlending()}isAvailable(){return this.available}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}_createBuffers(){const t=this.gl;this.positionBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this._positions,t.DYNAMIC_DRAW),this.sizeBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.sizeBuffer),t.bufferData(t.ARRAY_BUFFER,this._sizes,t.DYNAMIC_DRAW),this.colorBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.colorBuffer),t.bufferData(t.ARRAY_BUFFER,this._colors,t.DYNAMIC_DRAW)}_compileShaders(){const t=this.gl;let e;switch(this.shape){case"glow":e=ys;break;case"square":e=_s;break;case"softSquare":e=xs;break;default:e=vs}const i=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(i,ms),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))return console.error("Vertex shader error:",t.getShaderInfoLog(i)),void(this.available=!1);const s=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(s,e),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,i),t.attachShader(this.program,s),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.aSize=t.getAttribLocation(this.program,"aSize"),this.aColor=t.getAttribLocation(this.program,"aColor"),this.uResolution=t.getUniformLocation(this.program,"uResolution"),t.uniform2f(this.uResolution,this.width,this.height),t.deleteShader(i),void t.deleteShader(s)):(console.error("Program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("Fragment shader error:",t.getShaderInfoLog(s)),void(this.available=!1))}setShape(t){t!==this.shape&&(this.shape=t,this.available&&(this.program&&this.gl.deleteProgram(this.program),this._compileShaders()))}resize(t,e){if(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available){const i=this.gl;i.viewport(0,0,t,e),i.useProgram(this.program),i.uniform2f(this.uResolution,t,e)}}updateParticles(t){if(!this.available)return 0;const e=Math.min(t.length,this.maxParticles),i=this.gl;for(let s=0;s<e;s++){const e=t[s],i=2*s,n=4*s;this._positions[i]=e.x,this._positions[i+1]=e.y,this._sizes[s]=e.size;const o=e.color,r=void 0!==o.a?o.a:1,a=o.r/255*r,h=o.g/255*r,l=o.b/255*r;this._colors[n]=a,this._colors[n+1]=h,this._colors[n+2]=l,this._colors[n+3]=r}return i.bindBuffer(i.ARRAY_BUFFER,this.positionBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._positions.subarray(0,2*e)),i.bindBuffer(i.ARRAY_BUFFER,this.sizeBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._sizes.subarray(0,e)),i.bindBuffer(i.ARRAY_BUFFER,this.colorBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._colors.subarray(0,4*e)),e}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t){if(!this.available||0===t)return;const e=this.gl;e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.sizeBuffer),e.enableVertexAttribArray(this.aSize),e.vertexAttribPointer(this.aSize,1,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorBuffer),e.enableVertexAttribArray(this.aColor),e.vertexAttribPointer(this.aColor,4,e.FLOAT,!1,0,0),e.drawArrays(e.POINTS,0,t)}compositeOnto(t,e=0,i=0,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}getCanvas(){return this.canvas}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),t.deleteBuffer(this.positionBuffer),t.deleteBuffer(this.sizeBuffer),t.deleteBuffer(this.colorBuffer),this._positions=null,this._sizes=null,this._colors=null}}class Ms extends Fi{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??[gs.velocity,gs.lifetime],this.blendMode=e.blendMode??"source-over",this.worldSpace=e.worldSpace??!1,this.webglRenderer=null,e.webglRenderer?this.webglRenderer=e.webglRenderer:e.useWebGL&&(this.webglRenderer=new ws(this.maxParticles,{width:t.width,height:t.height,shape:e.webglShape??"circle",blendMode:e.webglBlendMode??"alpha"}),this.webglRenderer.isAvailable()||(console.warn("WebGL not available, falling back to Canvas 2D"),this.webglRenderer=null)),this.depthShading=e.depthShading??!1,this.depthShadingMin=e.depthShadingMin??.3,this.depthShadingMax=e.depthShadingMax??1,this.webglOffset=e.webglOffset??null,this._webglRenderList=[],this._particleCount=0}addEmitter(t,e){return this.emitters.set(t,e),this}removeEmitter(t){return this.emitters.delete(t),this}getEmitter(t){return this.emitters.get(t)}acquire(){return this.pool.length>0?this.pool.pop():new fs}release(t){t.reset(),this.pool.push(t)}emit(t,e){for(let i=0;i<t&&this.particles.length<this.maxParticles;i++){const t=this.acquire();e.emit(t),this.particles.push(t)}}burst(t,e){const i="string"==typeof e?this.emitters.get(e):e;i&&this.emit(t,i)}update(t){super.update(t);for(const e of this.emitters.values())if(e.active){const i=e.update(t);this.emit(i,e)}for(let e=this.particles.length-1;e>=0;e--){const i=this.particles[e];for(const e of this.updaters)e(i,t,this);i.alive||(this.release(i),this.particles.splice(e,1))}this._particleCount=this.particles.length}render(){super.render(),0!==this.particles.length&&(this.webglRenderer?this.renderWebGL():this.camera&&this.depthSort?this.renderWithDepthSort():this.renderSimple())}renderWebGL(){var t,e;const i=this.webglRenderer,s=this._webglRenderList;i.width===this.game.width&&i.height===this.game.height||i.resize(this.game.width,this.game.height),s.length=0;const n=this.game.width/2,o=this.game.height/2;if(this.camera&&this.depthSort){for(const t of this.particles){const e=this.camera.project(t.x,t.y,t.z);e.z<10-this.camera.perspective||s.push({x:n+e.x,y:o+e.y,z:e.z,size:t.size*e.scale,color:t.color})}if(s.sort((t,e)=>e.z-t.z),this.depthShading&&s.length>1){let t=1/0,e=-1/0;for(const n of s)n.z<t&&(t=n.z),n.z>e&&(e=n.z);const i=e-t;if(i>0){const t=this.depthShadingMax-this.depthShadingMin;for(const n of s){const s=(e-n.z)/i,o=this.depthShadingMin+s*t;n.color={r:n.color.r*o,g:n.color.g*o,b:n.color.b*o,a:n.color.a}}}}}else{const i=(null==(t=this.webglOffset)?void 0:t.x)??0,n=(null==(e=this.webglOffset)?void 0:e.y)??0;for(const t of this.particles)s.push({x:t.x+i,y:t.y+n,size:t.size,color:t.color})}i.clear();const r=i.updateParticles(s);i.render(r);const a=this.webglOffset?-this.webglOffset.x:0,h=this.webglOffset?-this.webglOffset.y:0;Ye.useCtx(t=>{t.globalCompositeOperation=this.blendMode,i.compositeOnto(t,a,h),t.globalCompositeOperation="source-over"})}renderSimple(){Ye.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),Ye.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}destroy(){this.clear(),this.webglRenderer&&(this.webglRenderer.destroy(),this.webglRenderer=null),this.pool=[],this.emitters.clear()}get isWebGL(){return null!==this.webglRenderer&&this.webglRenderer.isAvailable()}get particleCount(){return this._particleCount}get poolSize(){return this.pool.length}}class Ss{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 Ss.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=Ss.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(Ss.pointRect(t,e,{x:r,y:a,width:h,height:l})||Ss.pointRect(i,s,{x:r,y:a,width:h,height:l}))return!0;const c=Ss.lineLine(t,e,i,s,r,a,r,a+l),u=Ss.lineLine(t,e,i,s,r+h,a,r+h,a+l),d=Ss.lineLine(t,e,i,s,r,a,r+h,a),f=Ss.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(Ss.lineRect(s.x1,s.y1,s.x2,s.y2,e,i))return!0;return!1}static getOverlap(t,e){if(!Ss.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=Ss.getOverlap(t,e);if(!i)return null;const s=t.x+t.width/2,n=t.y+t.height/2,o=e.x+e.width/2,r=e.y+e.height/2,a=s<o?-i.x:i.x,h=n<r?-i.y:i.y;return Math.abs(i.x)<Math.abs(i.y)?{x:a,y:0}:{x:0,y:h}}static sweep(t,e,i,s){const n=s.x-t.width/2,o=s.y-t.height/2,r=s.width+t.width,a=s.height+t.height,h=t.x+t.width/2,l=t.y+t.height/2;let c,u,d,f;0!==e?(c=(n-h)/e,u=(n+r-h)/e,c>u&&([c,u]=[u,c])):(c=h>=n&&h<=n+r?-1/0:1/0,u=h>=n&&h<=n+r?1/0:-1/0),0!==i?(d=(o-l)/i,f=(o+a-l)/i,d>f&&([d,f]=[f,d])):(d=l>=o&&l<=o+a?-1/0:1/0,f=l>=o&&l<=o+a?1/0:-1/0);const p=Math.max(c,d);if(p>Math.min(u,f)||p<0||p>1)return null;let g=0,m=0;return c>d?g=e>0?-1:1:m=i>0?-1:1,{time:p,normalX:g,normalY:m}}}const Cs={maxParticles:500,particleSize:20,particleColor:{r:100,g:180,b:255,a:.9},physics:"liquid",gravity:200,damping:.98,bounce:.3,maxSpeed:400,fluid:{smoothingRadius:null,restDensity:3,pressureStiffness:80,nearPressureStiffness:3,viscosity:.005,maxForce:5e3},gas:{interactionRadius:null,pressure:150,diffusion:.15,drag:.02,turbulence:50,buoyancy:300,sinking:200,repulsion:300},heat:{enabled:!1,heatZone:.88,coolZone:.25,rate:.03,heatMultiplier:1.5,coolMultiplier:2,middleMultiplier:.005,transitionWidth:.08,neutralTemp:.5,deadZone:.15,buoyancy:300,sinking:200},collision:{enabled:!0,strength:5e3},boundary:{enabled:!0,strength:4e3,radius:null},shake:{enabled:!0,sensitivity:2,maxForce:2500,damping:.8},blendMode:"source-over"};class Ts extends Ms{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:[gs.velocity,gs.lifetime],x:e.x??a+l/2,y:e.y??h+c/2,width:l,height:c,debug:e.debug??!1,debugColor:e.debugColor??"#0f0"}),this.config=r,this.bounds=e.bounds||null,this.gravityEnabled=e.gravityEnabled??!0,this.modeMix="gas"===r.physics?1:0,this._targetMode=this.modeMix,this._modeLerpSpeed=5,this._forces=[],this._shake={lastX:window.screenX,lastY:window.screenY,velocityX:0,velocityY:0,forceX:0,forceY:0},this._createEmitter()}static _mergeConfig(t){const e={...Cs,...t},i=e.particleSize;return e.fluid={...Cs.fluid,...t.fluid},e.gas={...Cs.gas,...t.gas},e.heat={...Cs.heat,...t.heat},e.collision={...Cs.collision,...t.collision},e.boundary={...Cs.boundary,...t.boundary},e.shake={...Cs.shake,...t.shake},null===e.fluid.smoothingRadius&&(e.fluid.smoothingRadius=2*i),null===e.gas.interactionRadius&&(e.gas.interactionRadius=4*i),null===e.boundary.radius&&(e.boundary.radius=.8*i),e}_createEmitter(){const{particleSize:t,particleColor:e}=this.config,i=new ps({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=re.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&&Ss.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=_e(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=xe(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=_e(t,{kernel:{smoothingRadius:e.smoothingRadius},fluid:e}),n=xe(t,{gas:i}),o=be(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=he(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=re.lerp(this._shake.forceX,r,1-e.damping),this._shake.forceY=re.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=re.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*re.lerp(1.5,.3,t),d=this.gravityEnabled?i*re.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}}R=new WeakMap,A=new WeakMap,z=new WeakMap,D=new WeakMap,B=new WeakMap,I=new WeakMap,E=new WeakSet,F=function(t){var e;if(bt(this,B).push(t),1===bt(this,B).length){bt(this,A)._fluentShape=t,bt(this,A).renderable=t;const i=(null==(e=bt(this,A).draw)?void 0:e.bind(bt(this,A)))||(()=>{});bt(this,A).draw=function(){i(),this._fluentShape&&this.visible&&this._fluentShape.render()};const s=bt(this,A);bt(this,A).getBounds=function(){return s._fluentShape&&s._fluentShape.getBounds?s._fluentShape.getBounds():null}}else{if(!(bt(this,A)._fluentShape instanceof $e)){const t=bt(this,B)[0],e=new $e;e.add(t),bt(this,A)._fluentShape=e,bt(this,A).renderable=e}bt(this,A)._fluentShape.add(t)}return this},O=function(t){const e={...t};return void 0!==t.fill&&(e.color=t.fill,e.fillColor=t.fill,delete e.fill),void 0!==t.stroke&&(e.strokeColor=t.stroke,delete e.stroke),e},L=function(t){for(const e of bt(this,A)._fluentMotions){const i=St(this,E,Y).call(this,e,t);e.state=null==i?void 0:i.state}},Y=function(t,e){const{type:i,opts:s,state:n}=t,o=bt(this,A)._motionTime,r=bt(this,A);switch(i){case"oscillate":{const{prop:t="y",min:e=-50,max:i=50,duration:n=2}=s,a=rs.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=rs.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=rs.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=rs.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=rs.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=rs.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=rs.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=rs.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=rs.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 ks=class t{constructor(t,e,i,s){wt(this,E),wt(this,R),wt(this,A),wt(this,z),wt(this,D),wt(this,B,[]),wt(this,I,[]),Mt(this,R,t),Mt(this,A,e),Mt(this,z,i),Mt(this,D,s)}circle(t={}){const e=St(this,E,O).call(this,t),{radius:i=30,...s}=e,n=new Ke(i,s);return St(this,E,F).call(this,n)}rect(t={}){const e=St(this,E,O).call(this,t),i=new Qe(e);return St(this,E,F).call(this,i)}roundRect(t={}){const e=St(this,E,O).call(this,t),{radius:i=10,...s}=e,n=new ti(i,s);return St(this,E,F).call(this,n)}square(t={}){const e=St(this,E,O).call(this,t),{size:i=50,...s}=e,n=new ei(i,s);return St(this,E,F).call(this,n)}star(t={}){const e=St(this,E,O).call(this,t),{radius:i=40,points:s=5,inset:n=.5,...o}=e,r=new oi(i,s,n,o);return St(this,E,F).call(this,r)}triangle(t={}){const e=St(this,E,O).call(this,t),{size:i=50,...s}=e,n=new ni(i,s);return St(this,E,F).call(this,n)}poly(t={}){const e=St(this,E,O).call(this,t),i=new vi(e);return St(this,E,F).call(this,i)}line(t={}){const e=St(this,E,O).call(this,t),{length:i=40,...s}=e,n=new si(i,s);return St(this,E,F).call(this,n)}hexagon(t={}){const e=St(this,E,O).call(this,t),{radius:i=30,...s}=e,n=new xi(i,s);return St(this,E,F).call(this,n)}diamond(t={}){const e=St(this,E,O).call(this,t),i=new ii(e);return St(this,E,F).call(this,i)}heart(t={}){const e=St(this,E,O).call(this,t),{size:i,...s}=e;i&&!s.width&&(s.width=i),i&&!s.height&&(s.height=i);const n=new bi(s);return St(this,E,F).call(this,n)}arc(t={}){const e=St(this,E,O).call(this,t),{radius:i=30,startAngle:s=0,endAngle:n=Math.PI,...o}=e,r=new je(i,s,n,o);return St(this,E,F).call(this,r)}ring(t={}){const e=St(this,E,O).call(this,t),{outerRadius:i=40,innerRadius:s=20,...n}=e,o=new mi(i,s,n);return St(this,E,F).call(this,o)}arrow(t={}){const e=St(this,E,O).call(this,t),{length:i=50,...s}=e,n=new yi(i,s);return St(this,E,F).call(this,n)}cross(t={}){const e=St(this,E,O).call(this,t),{size:i=40,thickness:s=10,...n}=e,o=new wi(i,s,n);return St(this,E,F).call(this,o)}pin(t={}){const e=St(this,E,O).call(this,t),{radius:i=20,...s}=e,n=new _i(i,s);return St(this,E,F).call(this,n)}cloud(t={}){const e=St(this,E,O).call(this,t),{size:i,width:s,height:n,...o}=e,r=i||Math.min(s||40,n||40),a=new Je(r,o);return St(this,E,F).call(this,a)}text(t,e={}){const i=St(this,E,O).call(this,e);i.fillColor&&(i.color=i.fillColor,delete i.fillColor);const s=new Mi(t,i);return St(this,E,F).call(this,s)}image(t,e={}){const i=St(this,E,O).call(this,e);if("string"==typeof t){const s=new Image;s.src=t;const n=new Si(s,i);return s.onload=()=>{n._bitmap=s,n._width=e.width??s.width,n._height=e.height??s.height},St(this,E,F).call(this,n)}{const e=new Si(t,i);return St(this,E,F).call(this,e)}}svg(t,e={}){const i=St(this,E,O).call(this,e),s=new gi({path:t,...i});return St(this,E,F).call(this,s)}add(t,e={}){const i=new t(St(this,E,O).call(this,e));return St(this,E,F).call(this,i)}oscillate(t={}){return this.motion("oscillate",t)}pulse(t={}){return this.motion("pulse",t)}orbit(t={}){return this.motion("orbit",t)}float(t={}){return this.motion("float",t)}shake(t={}){return this.motion("shake",t)}bounce(t={}){return this.motion("bounce",t)}spring(t={}){return this.motion("spring",t)}spiral(t={}){return this.motion("spiral",t)}pendulum(t={}){return this.motion("pendulum",t)}waypoint(t={}){return this.motion("waypoint",t)}motion(t,e={}){var i;if(bt(this,I).push({type:t,opts:e}),!bt(this,A)._fluentMotions){bt(this,A)._fluentMotions=[],bt(this,A)._motionTime=0,bt(this,A)._baseX=bt(this,A).x,bt(this,A)._baseY=bt(this,A).y;const t=(null==(i=bt(this,A).update)?void 0:i.bind(bt(this,A)))||(()=>{}),e=this;bt(this,A).update=function(i){var s;t(i),this._motionTime+=i,St(s=e,E,L).call(s,i)}}return bt(this,A)._fluentMotions.push({type:t,opts:e,state:null}),this}tween(t,e={}){const{duration:i=1,easing:s="easeOutQuad",delay:n=0,onComplete:o}=e;return n>0?setTimeout(()=>{hs.to(bt(this,A),t,i,s,{onComplete:o})},1e3*n):hs.to(bt(this,A),t,i,s,{onComplete:o}),this}child(e,i,s){let n,o,r;"function"==typeof e&&e.prototype?(n=e,"function"==typeof i?(o={},r=i):(o=i||{},r=s)):(n=Fi,o=e||{},r=i);const a=new n(bt(this,A).game,o);bt(this,A).addChild(a),o.name&&(bt(this,z)[o.name]=a);const h=new t(this,a,bt(this,z),bt(this,D));return r?(r(h),this):h}on(t,e){const i={go:bt(this,A),shapes:bt(this,B),refs:bt(this,z),state:bt(this,D)};return["click","mousedown","mouseup","mousemove","mouseover","mouseout","inputdown","inputup","inputmove"].includes(t)&&(bt(this,A).interactive=!0),bt(this,A).events&&bt(this,A).events.on(t,t=>e(i,t)),this}update(t){var e;const i=(null==(e=bt(this,A).update)?void 0:e.bind(bt(this,A)))||(()=>{}),s=bt(this,B),n=bt(this,z),o=bt(this,D),r=bt(this,A);return bt(this,A).update=e=>{i(e),t(e,{go:r,shapes:s,refs:n,state:o})},this}pos(t,e){return bt(this,A).x=t,bt(this,A).y=e,this}scale(t,e){return bt(this,A).scaleX=t,bt(this,A).scaleY=e??t,this}rotate(t){return bt(this,A).rotation=t*(Math.PI/180),this}opacity(t){return bt(this,A).opacity=t,bt(this,A).renderable&&(bt(this,A).renderable.opacity=t),this}zIndex(t){return bt(this,A).zIndex=t,this}end(){return bt(this,R)}go(t){var e;let i=bt(this,R);for(;i&&!i.sceneInstance;)i=null==(e=i.end)?void 0:e.call(i);if(i&&i.go)return i.go(t);throw new Error("Cannot find scene context")}scene(t,e){var i;let s=bt(this,R);for(;s&&!s.sceneInstance;)s=null==(i=s.end)?void 0:i.call(s);if(s&&s.scene)return s.scene(t,e);throw new Error("Cannot find game context")}start(){let t=bt(this,R);for(;t&&t.end;){const e=t.end();if(e===t)break;t=e}return t.start()}get goInstance(){return bt(this,A)}get shapes(){return bt(this,B)}get refs(){return bt(this,z)}get state(){return bt(this,D)}};class Ps{constructor(t,e,i,s,n){wt(this,X),wt(this,W),wt(this,H),wt(this,U),wt(this,G),Mt(this,X,t),Mt(this,W,e),Mt(this,H,i),Mt(this,U,s),Mt(this,G,n)}go(t={},e){var i;const{name:s,x:n=0,y:o=0,visible:r=!0,...a}=t,h=new Fi({x:n,y:o,visible:r,...a});(null==(i=bt(this,X).parent)?void 0:i.game)&&(h.game=bt(this,X).parent.game),bt(this,H).add(h),s&&(h.name=s,bt(this,U)[s]=h);const l=new ks(this,h,bt(this,U),bt(this,G));return e?(e(l),this):l}visible(t){return bt(this,W).visible=t,this}opacity(t){return bt(this,H).opacity=t,this}endLayer(){return bt(this,X)}end(){return bt(this,X)}scene(t,e){return bt(this,X).scene(t,e)}start(){return bt(this,X).start()}get layerGO(){return bt(this,W)}get group(){return bt(this,H)}get refs(){return bt(this,U)}get state(){return bt(this,G)}}X=new WeakMap,W=new WeakMap,H=new WeakMap,U=new WeakMap,G=new WeakMap;class Rs{constructor(t,e,i,s){wt(this,N),wt(this,q),wt(this,Z),wt(this,V),wt(this,$,null),Mt(this,N,t),Mt(this,q,e),Mt(this,Z,i),Mt(this,V,s)}go(t,e,i){let s,n,o;"function"==typeof t&&t.prototype?(s=t,"function"==typeof e?(n={},o=e):(n=e||{},o=i)):(s=Fi,n=t||{},o=e);const{name:r,x:a=0,y:h=0,visible:l=!0,...c}=n,u=new s(bt(this,N).game,{x:a,y:h,visible:l,...c});bt(this,q).add(u),Mt(this,$,u),r&&(u.name=r,bt(this,Z)[r]=u);const d=new ks(this,u,bt(this,Z),bt(this,V));return o?(o(d),this):d}group(t,e){const i="string"==typeof t?t:null,s=[];return("function"==typeof t?t:e)({go:t=>{const e=this.go(t);return s.push(e.goInstance),e}}),i&&(bt(this,Z)[i]=s),this}layer(t,e=0){var i;const s=new $e({zIndex:e});s.name=t;const n=new Fi(bt(this,N).game,{x:0,y:0});n._fluentShape=s,n.renderable=s,n.zIndex=e;const o=(null==(i=n.draw)?void 0:i.bind(n))||(()=>{});return n.draw=function(){o(),this._fluentShape&&this.visible&&this._fluentShape.render()},bt(this,q).add(n),t&&(bt(this,Z)[`${bt(this,q).name}_${t}`]=n),new Ps(this,n,s,bt(this,Z),bt(this,V))}onEnter(t){return bt(this,q)._onEnter=t,this}onExit(t){return bt(this,q)._onExit=t,this}scene(t,e){return bt(this,N).scene(t,e)}end(){return bt(this,N)}start(){return bt(this,N).start()}stop(){return bt(this,N).stop()}on(t,e){return bt(this,N).on(t,e)}use(t){return bt(this,N).use(t)}state(t){return bt(this,N).state(t)}get sceneInstance(){return bt(this,q)}get refs(){return bt(this,Z)}get state(){return bt(this,V)}get parent(){return bt(this,N)}}function As(t={}){return new zs(t)}N=new WeakMap,q=new WeakMap,Z=new WeakMap,V=new WeakMap,$=new WeakMap;class zs{constructor(t={}){wt(this,st),wt(this,j),wt(this,K,new Map),wt(this,J,null),wt(this,Q,{}),wt(this,tt,{}),wt(this,et,[]),wt(this,it,null);const{canvas:e,width:i=800,height:s=600,bg:n,fluid:o,container:r,fps:a=60,pixelRatio:h=("undefined"!=typeof window?window.devicePixelRatio:1)}=t;Mt(this,it,e||St(this,st,nt).call(this,i,s,r)),Mt(this,j,new cs(bt(this,it))),bt(this,j).init(),n&&(bt(this,j).backgroundColor=n);(void 0!==o?o:!e)&&bt(this,j).enableFluidSize(),60!==a&&(bt(this,j).targetFPS=a),bt(this,j)._pixelRatio=h}scene(t,e,i){let s,n,o;"function"==typeof t?(n=t,s=n.name||"custom_scene",o=e||{}):"function"==typeof e?(s=t,n=e,o=i||{}):(s=t,n=Li,o=e||{});const{zIndex:r=0,active:a=!0,onEnter:h,onExit:l,...c}=o;let u=bt(this,K).get(s);return u||(u=new n(bt(this,j),c),u.name=s,u.zIndex=r,u.visible=a,u._onEnter=h,u._onExit=l,bt(this,K).set(s,u),bt(this,j).pipeline.add(u)),Mt(this,J,u),new Rs(this,u,bt(this,Q),bt(this,tt))}inScene(t){const e=bt(this,K).get(t);if(!e)throw new Error(`Scene '${t}' does not exist. Use .scene('${t}') to create it.`);return Mt(this,J,e),new Rs(this,e,bt(this,Q),bt(this,tt))}go(t,e){return bt(this,J)||this.scene("default"),new Rs(this,bt(this,J),bt(this,Q),bt(this,tt)).go(t,e)}showScene(t){var e;const i=bt(this,K).get(t);return i&&(i.visible=!0,null==(e=i._onEnter)||e.call(i,St(this,st,ot).call(this))),this}hideScene(t){var e;const i=bt(this,K).get(t);return i&&(null==(e=i._onExit)||e.call(i,St(this,st,ot).call(this)),i.visible=!1),this}transition(t,e,i={}){const{fade:s=0,onComplete:n}=i;return this.hideScene(t),this.showScene(e),null==n||n(),this}state(t){return Object.assign(bt(this,tt),t),this}getState(t){return bt(this,tt)[t]}setState(t,e){return bt(this,tt)[t]=e,this}on(t,e){const i=St(this,st,ot).call(this);if("update"===t){const t=bt(this,j).update.bind(bt(this,j));bt(this,j).update=s=>{t(s),e(s,i)}}else if(t.startsWith("keydown:")){const s=t.split(":")[1];bt(this,j).events.on("keydown",t=>{var n,o;(null==(n=t.key)?void 0:n.toLowerCase())!==s.toLowerCase()&&(null==(o=t.code)?void 0:o.toLowerCase())!==s.toLowerCase()||e(i,t)})}else if(t.startsWith("keyup:")){const s=t.split(":")[1];bt(this,j).events.on("keyup",t=>{var n;(null==(n=t.key)?void 0:n.toLowerCase())===s.toLowerCase()&&e(i,t)})}else bt(this,j).events.on(t,t=>e(i,t));return this}use(t){return t(this),bt(this,et).push(t),this}start(){return bt(this,j).start(),this}stop(){return bt(this,j).stop(),this}restart(){return bt(this,j).restart(),this}get game(){return bt(this,j)}get refs(){return bt(this,Q)}get scenes(){return bt(this,K)}get canvas(){return bt(this,it)}get width(){return bt(this,it).width}get height(){return bt(this,it).height}}j=new WeakMap,K=new WeakMap,J=new WeakMap,Q=new WeakMap,tt=new WeakMap,et=new WeakMap,it=new WeakMap,st=new WeakSet,nt=function(t,e,i){const s=document.createElement("canvas");s.width=t,s.height=e,s.style.display="block";return(i||document.body).appendChild(s),s},ot=function(){return{refs:bt(this,Q),state:bt(this,tt),scenes:Object.fromEntries(bt(this,K)),game:bt(this,j),width:bt(this,it).width,height:bt(this,it).height,showScene:t=>this.showScene(t),hideScene:t=>this.hideScene(t),transition:(t,e,i)=>this.transition(t,e,i)}};class Ds{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 Bs{static init(t,e){Mt(this,rt,t),Mt(this,at,e)}static get ctx(){return bt(this,rt)}static get now(){return bt(this,rt).currentTime}static tone(t,e,i={}){const{type:s="sine",volume:n=.5,attack:o=.01,decay:r=.1,sustain:a=.7,release:h=.2,detune:l=0,startTime:c=bt(this,rt).currentTime}=i,u=bt(this,rt).createOscillator(),d=bt(this,rt).createGain();return u.type=s,u.frequency.setValueAtTime(t,c),u.detune.setValueAtTime(l,c),Ds.applyADSR(d.gain,{attack:o,decay:r,sustain:a,release:h,startTime:c,duration:e,peakVolume:n}),u.connect(d),d.connect(bt(this,at)),u.start(c),u.stop(c+e+h),u}static continuous(t={}){const{type:e="sine",frequency:i=440,volume:s=.5}=t,n=bt(this,rt).createOscillator(),o=bt(this,rt).createGain();n.type=e,n.frequency.value=i,o.gain.value=s,n.connect(o),o.connect(bt(this,at)),n.start();const r=bt(this,rt);return{osc:n,gain:o,setFrequency:(t,e=0)=>{e>0?n.frequency.linearRampToValueAtTime(t,r.currentTime+e):n.frequency.setValueAtTime(t,r.currentTime)},setVolume:(t,e=0)=>{e>0?o.gain.linearRampToValueAtTime(t,r.currentTime+e):o.gain.setValueAtTime(t,r.currentTime)},stop:(t=0)=>{t>0?(o.gain.linearRampToValueAtTime(0,r.currentTime+t),n.stop(r.currentTime+t+.01)):n.stop()}}}static fm(t,e,i,s,n={}){const{volume:o=.5,startTime:r=bt(this,rt).currentTime}=n,a=bt(this,rt).createOscillator(),h=bt(this,rt).createOscillator(),l=bt(this,rt).createGain(),c=bt(this,rt).createGain();return h.frequency.value=e,l.gain.value=i,a.frequency.value=t,c.gain.value=o,h.connect(l),l.connect(a.frequency),a.connect(c),c.connect(bt(this,at)),c.gain.setValueAtTime(o,r),c.gain.linearRampToValueAtTime(0,r+s),h.start(r),a.start(r),h.stop(r+s+.1),a.stop(r+s+.1),{carrier:a,modulator:h,outputGain:c}}static additive(t,e,i,s={}){const{volume:n=.5,startTime:o=bt(this,rt).currentTime}=s,r=[],a=bt(this,rt).createGain();return a.gain.value=n/e.length,a.connect(bt(this,at)),a.gain.setValueAtTime(n/e.length,o),a.gain.linearRampToValueAtTime(0,o+i),e.forEach((e,s)=>{if(e>0){const n=bt(this,rt).createOscillator(),h=bt(this,rt).createGain();n.frequency.value=t*(s+1),h.gain.value=e,n.connect(h),h.connect(a),n.start(o),n.stop(o+i+.1),r.push(n)}}),r}static sweep(t,e,i,s={}){const{type:n="sine",volume:o=.5,exponential:r=!0,startTime:a=bt(this,rt).currentTime}=s,h=bt(this,rt).createOscillator(),l=bt(this,rt).createGain();return h.type=n,h.frequency.setValueAtTime(t,a),r&&e>0?h.frequency.exponentialRampToValueAtTime(e,a+i):h.frequency.linearRampToValueAtTime(e,a+i),l.gain.setValueAtTime(o,a),l.gain.linearRampToValueAtTime(0,a+i),h.connect(l),l.connect(bt(this,at)),h.start(a),h.stop(a+i+.01),h}static pulse(t,e,i=.5,s={}){const{volume:n=.5,startTime:o=bt(this,rt).currentTime}=s,r=bt(this,rt).createOscillator(),a=bt(this,rt).createOscillator(),h=bt(this,rt).createGain(),l=bt(this,rt).createGain(),c=bt(this,rt).createGain();return r.type="sawtooth",a.type="sawtooth",r.frequency.value=t,a.frequency.value=t,h.gain.value=.5,l.gain.value=-.5,c.gain.setValueAtTime(n,o),c.gain.linearRampToValueAtTime(0,o+e),r.connect(h),a.connect(l),h.connect(c),l.connect(c),c.connect(bt(this,at)),r.start(o),a.start(o),r.stop(o+e+.01),a.stop(o+e+.01),{osc1:r,osc2:a,output:c}}}rt=new WeakMap,at=new WeakMap,wt(Bs,rt,null),wt(Bs,at,null);class Is{static init(t,e){Mt(this,ht,t),Mt(this,lt,e)}static get ctx(){return bt(this,ht)}static filter(t="lowpass",e=1e3,i=1){const s=bt(this,ht).createBiquadFilter();return s.type=t,s.frequency.value=e,s.Q.value=i,s}static delay(t=.3,e=.4,i=.5){const s=bt(this,ht).createDelay(5),n=bt(this,ht).createGain(),o=bt(this,ht).createGain(),r=bt(this,ht).createGain(),a=bt(this,ht).createGain(),h=bt(this,ht).createGain();return s.delayTime.value=t,n.gain.value=e,o.gain.value=i,r.gain.value=1-i,a.connect(s),a.connect(r),s.connect(n),n.connect(s),s.connect(o),o.connect(h),r.connect(h),{input:a,output:h,setTime:t=>s.delayTime.setValueAtTime(t,bt(this,ht).currentTime),setFeedback:t=>n.gain.setValueAtTime(t,bt(this,ht).currentTime),setMix:t=>{o.gain.setValueAtTime(t,bt(this,ht).currentTime),r.gain.setValueAtTime(1-t,bt(this,ht).currentTime)}}}static reverb(t=2,e=2){const i=bt(this,ht).createConvolver(),s=bt(this,ht).sampleRate,n=s*t,o=bt(this,ht).createBuffer(2,n,s);for(let 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=bt(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=bt(this,ht).createOscillator(),s=bt(this,ht).createGain(),n=bt(this,ht).createGain();return i.frequency.value=t,s.gain.value=.5*e,n.gain.value=1-.5*e,i.connect(s),s.connect(n.gain),i.start(),{input:n,output:n,lfo:i,setRate:t=>i.frequency.setValueAtTime(t,bt(this,ht).currentTime),setDepth:t=>s.gain.setValueAtTime(.5*t,bt(this,ht).currentTime),stop:()=>i.stop()}}static compressor(t={}){const{threshold:e=-24,knee:i=30,ratio:s=12,attack:n=.003,release:o=.25}=t,r=bt(this,ht).createDynamicsCompressor();return r.threshold.value=e,r.knee.value=i,r.ratio.value=s,r.attack.value=n,r.release.value=o,r}static panner(t=0){const e=bt(this,ht).createStereoPanner();return e.pan.value=t,e}static gain(t=1){const e=bt(this,ht).createGain();return e.gain.value=t,e}}ht=new WeakMap,lt=new WeakMap,wt(Is,ht,null),wt(Is,lt,null);class Es{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 Fs{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)}}_t(Fs,"NOTE_FREQUENCIES",{C:16.35,"C#":17.32,Db:17.32,D:18.35,"D#":19.45,Eb:19.45,E:20.6,F:21.83,"F#":23.12,Gb:23.12,G:24.5,"G#":25.96,Ab:25.96,A:27.5,"A#":29.14,Bb:29.14,B:30.87}),_t(Fs,"SCALES",{major:[0,2,4,5,7,9,11],minor:[0,2,3,5,7,8,10],pentatonic:[0,2,4,7,9],pentatonicMinor:[0,3,5,7,10],blues:[0,3,5,6,7,10],dorian:[0,2,3,5,7,9,10],mixolydian:[0,2,4,5,7,9,10],chromatic:[0,1,2,3,4,5,6,7,8,9,10,11],wholeTone:[0,2,4,6,8,10],diminished:[0,2,3,5,6,8,9,11]}),_t(Fs,"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 Os{static init(t,e){Mt(this,ct,t),Mt(this,ut,t.createAnalyser()),bt(this,ut).fftSize=2048,e.connect(bt(this,ut)),bt(this,ut).connect(t.destination),Mt(this,dt,new Uint8Array(bt(this,ut).frequencyBinCount)),Mt(this,ft,new Uint8Array(bt(this,ut).frequencyBinCount))}static get isInitialized(){return null!==bt(this,ut)}static get node(){return bt(this,ut)}static setFFTSize(t){bt(this,ut)&&(bt(this,ut).fftSize=t,Mt(this,dt,new Uint8Array(bt(this,ut).frequencyBinCount)),Mt(this,ft,new Uint8Array(bt(this,ut).frequencyBinCount)))}static getWaveform(){return bt(this,ut)?(bt(this,ut).getByteTimeDomainData(bt(this,dt)),bt(this,dt)):new Uint8Array(0)}static getFrequency(){return bt(this,ut)?(bt(this,ut).getByteFrequencyData(bt(this,ft)),bt(this,ft)):new Uint8Array(0)}static getBands(t=8){const e=this.getFrequency();if(0===e.length)return new Array(t).fill(0);const i=Math.floor(e.length/t),s=[];for(let n=0;n<t;n++){let t=0;for(let s=0;s<i;s++)t+=e[n*i+s];s.push(t/(255*i))}return s}static getAmplitude(){const t=this.getWaveform();if(0===t.length)return 0;let e=0;for(let i=0;i<t.length;i++){const s=(t[i]-128)/128;e+=s*s}return Math.sqrt(e/t.length)}static getPeakFrequency(){if(!bt(this,ut)||!bt(this,ct))return 0;const t=this.getFrequency();let e=0,i=0;for(let s=0;s<t.length;s++)t[s]>i&&(i=t[s],e=s);return e*(bt(this,ct).sampleRate/2)/bt(this,ut).frequencyBinCount}static dispose(){bt(this,ut)&&(bt(this,ut).disconnect(),Mt(this,ut,null)),Mt(this,dt,null),Mt(this,ft,null)}}ct=new WeakMap,ut=new WeakMap,dt=new WeakMap,ft=new WeakMap,wt(Os,ct,null),wt(Os,ut,null),wt(Os,dt,null),wt(Os,ft,null);class Ls{static init(t={}){if(bt(this,mt))return void console.warn("[Synth] Already initialized");const{masterVolume:e=.5,sampleRate:i=44100,enableAnalyzer:s=!1}=t;try{Mt(this,pt,new(window.AudioContext||window.webkitAudioContext)({sampleRate:i})),Mt(this,gt,bt(this,pt).createGain()),bt(this,gt).gain.value=e,bt(this,gt).connect(bt(this,pt).destination),Bs.init(bt(this,pt),bt(this,gt)),Is.init(bt(this,pt),bt(this,gt)),s&&Os.init(bt(this,pt),bt(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 bt(this,mt)}static get ctx(){return bt(this,pt)}static get master(){return bt(this,gt)}static get osc(){return Bs}static get fx(){return Is}static get env(){return Ds}static get noise(){return Es}static get music(){return Fs}static get analyzer(){return Os}static async resume(){bt(this,pt)&&"suspended"===bt(this,pt).state&&(await bt(this,pt).resume(),console.log("[Synth] Audio context resumed"))}static async suspend(){bt(this,pt)&&"running"===bt(this,pt).state&&await bt(this,pt).suspend()}static get now(){return bt(this,pt)?bt(this,pt).currentTime:0}static get state(){return bt(this,pt)?bt(this,pt).state:"closed"}static set volume(t){bt(this,gt)&&bt(this,gt).gain.setValueAtTime(Math.max(0,Math.min(1,t)),bt(this,pt).currentTime)}static get volume(){return bt(this,gt)?bt(this,gt).gain.value:0}static chain(...t){for(let e=0;e<t.length-1;e++)t[e].connect(t[e+1]);return{first:t[0],last:t[t.length-1],connectTo:e=>t[t.length-1].connect(e)}}static schedule(t,e){const i=Math.max(0,1e3*(e-this.now));return setTimeout(t,i)}static async close(){bt(this,pt)&&(Os.dispose(),await bt(this,pt).close(),Mt(this,pt,null),Mt(this,gt,null),Mt(this,mt,!1),console.log("[Synth] Audio system closed"))}}pt=new WeakMap,gt=new WeakMap,mt=new WeakMap,wt(Ls,pt,null),wt(Ls,gt,null),wt(Ls,mt,!1);class Ys{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 Ys({initial:null==(i=t[0])?void 0:i.name,states:s,context:e.context})}}class Xs{static attract(t,e,i=100,s=1){const n=e.x-t.x,o=e.y-t.y,r=(e.z||0)-(t.z||0),a=n*n+o*o+r*r,h=Math.sqrt(a)||s,l=Math.max(h,s),c=i/(l*l);return{fx:n/h*c,fy:o/h*c,fz:r/h*c,dist:h}}static attractLinear(t,e,i=100){const s=e.x-t.x,n=e.y-t.y,o=(e.z||0)-(t.z||0),r=Math.sqrt(s*s+n*n+o*o)||1;return{fx:s/r*i,fy:n/r*i,fz:o/r*i,dist:r}}static checkCollision(t,e,i=1){const s=e.x-t.x,n=e.y-t.y,o=(e.z||0)-(t.z||0),r=Math.sqrt(s*s+n*n+o*o),a=((t.size||t.radius||1)+(e.size||e.radius||1))*i;return r<a&&r>0?{dist:r,overlap:a-r,dx:s,dy:n,dz:o}:null}static elasticCollision(t,e,i,s=.9){var n,o;const r=t.mass??(null==(n=t.custom)?void 0:n.mass)??1,a=e.mass??(null==(o=e.custom)?void 0:o.mass)??1,h=r+a,l=i.dist||1,c=i.dx/l,u=i.dy/l,d=i.dz/l,f=(t.vx-e.vx)*c+(t.vy-e.vy)*u+((t.vz||0)-(e.vz||0))*d;if(f<0)return null;const p=-(1+s)*f/h;return{v1:{vx:t.vx+p*a*c,vy:t.vy+p*a*u,vz:(t.vz||0)+p*a*d},v2:{vx:e.vx-p*r*c,vy:e.vy-p*r*u,vz:(e.vz||0)-p*r*d}}}static separate(t,e,i,s=.5){var n,o;const r=t.mass??(null==(n=t.custom)?void 0:n.mass)??1,a=e.mass??(null==(o=e.custom)?void 0:o.mass)??1,h=r+a,l=i.dist||1,c=i.dx/l,u=i.dy/l,d=i.dz/l,f=i.overlap*s,p=f*(a/h),g=f*(r/h);t.x-=c*p,t.y-=u*p,void 0!==t.z&&(t.z-=d*p),e.x+=c*g,e.y+=u*g,void 0!==e.z&&(e.z+=d*g)}static boundsCollision(t,e,i=.9){const s=(t.size||t.radius||1)/2;let n=!1;if(void 0!==e.minX){const o=e.minX+s,r=e.maxX-s;t.x<o?(t.x=o,t.vx<0&&(t.vx=-t.vx*i),n=!0):t.x>r&&(t.x=r,t.vx>0&&(t.vx=-t.vx*i),n=!0)}if(void 0!==e.minY){const o=e.minY+s,r=e.maxY-s;t.y<o?(t.y=o,t.vy<0&&(t.vy=-t.vy*i),n=!0):t.y>r&&(t.y=r,t.vy>0&&(t.vy=-t.vy*i),n=!0)}if(void 0!==e.minZ&&void 0!==t.z){const o=e.minZ+s,r=e.maxZ-s;t.z<o?(t.z=o,t.vz<0&&(t.vz=-t.vz*i),n=!0):t.z>r&&(t.z=r,t.vz>0&&(t.vz=-t.vz*i),n=!0)}return n}static sphereBoundsCollision(t,e,i=.9,s=!0){const n=t.x-e.x,o=t.y-e.y,r=(t.z||0)-(e.z||0),a=Math.sqrt(n*n+o*o+r*r),h=(t.size||t.radius||1)/2,l=e.radius-h;if(s&&a>l){const s=n/a,h=o/a,c=r/a;t.x=e.x+s*l,t.y=e.y+h*l,void 0!==t.z&&(t.z=e.z+c*l);const u=t.vx*s+t.vy*h+(t.vz||0)*c;return u>0&&(t.vx-=2*u*s*i,t.vy-=2*u*h*i,void 0!==t.vz&&(t.vz-=2*u*c*i)),!0}return!1}static kineticEnergy(t){var e;const i=t.vx||0,s=t.vy||0,n=t.vz||0;return.5*(t.mass??(null==(e=t.custom)?void 0:e.mass)??1)*(i*i+s*s+n*n)}static speed(t){const e=t.vx||0,i=t.vy||0,s=t.vz||0;return Math.sqrt(e*e+i*i+s*s)}static distance(t,e){const i=e.x-t.x,s=e.y-t.y,n=(e.z||0)-(t.z||0);return Math.sqrt(i*i+s*s+n*n)}static distanceSquared(t,e){const i=e.x-t.x,s=e.y-t.y,n=(e.z||0)-(t.z||0);return i*i+s*s+n*n}static clampVelocity(t,e){const i=Xs.speed(t);if(i>e){const s=e/i;t.vx*=s,t.vy*=s,void 0!==t.vz&&(t.vz*=s)}}static applyForce(t,e,i,s,n){var o;const r=t.mass??(null==(o=t.custom)?void 0:o.mass)??1,a=r>0?1/r:0;t.vx+=e*a*n,t.vy+=i*a*n,void 0!==t.vz&&(t.vz+=(s||0)*a*n)}}const Ws={mutualAttraction:(t=100,e=200,i=5)=>{const s=e*e;return(e,n,o)=>{var r,a;if(!e.alive)return;const h=o.particles,l=e.mass??(null==(r=e.custom)?void 0:r.mass)??1;for(let c=0;c<h.length;c++){const o=h[c];if(o===e||!o.alive)continue;const r=o.x-e.x,u=o.y-e.y,d=(o.z||0)-(e.z||0),f=r*r+u*u+d*d;if(f>s||f<.01)continue;const p=Math.sqrt(f),g=Math.max(p,i),m=o.mass??(null==(a=o.custom)?void 0:a.mass)??1,v=t*l*m/(g*g)*n/p;e.vx+=r*v,e.vy+=u*v,void 0!==e.vz&&(e.vz+=d*v)}}},mutualAttractionLinear:(t=50,e=100)=>{const i=e*e;return(e,s,n)=>{if(e.alive)for(const o of n.particles){if(o===e||!o.alive)continue;const n=o.x-e.x,r=o.y-e.y,a=(o.z||0)-(e.z||0),h=n*n+r*r+a*a;if(h>i||h<.01)continue;const l=Math.sqrt(h),c=t*s/l;e.vx+=n*c,e.vy+=r*c,void 0!==e.vz&&(e.vz+=a*c)}}},particleCollisions:(t=.9,e=1)=>{const i=new Set;return(s,n,o)=>{if(!s.alive)return;0===o.particles.indexOf(s)&&i.clear();const r=o.particles.indexOf(s);for(let a=r+1;a<o.particles.length;a++){const n=o.particles[a];if(!n.alive)continue;const h=`${r}-${a}`;if(i.has(h))continue;const l=Xs.checkCollision(s,n,e);if(l){i.add(h),Xs.separate(s,n,l,.5);const e=Xs.elasticCollision(s,n,l,t);e&&(s.vx=e.v1.vx,s.vy=e.v1.vy,s.vz=e.v1.vz,n.vx=e.v2.vx,n.vy=e.v2.vy,n.vz=e.v2.vz)}}}},bounds3D:(t,e=.9)=>(i,s)=>{i.alive&&Xs.boundsCollision(i,t,e)},sphereBounds:(t,e=.9)=>(i,s)=>{i.alive&&Xs.sphereBoundsCollision(i,t,e,!0)},attractToPoint:(t,e=100,i=10)=>(s,n)=>{if(!s.alive)return;const o="function"==typeof t?t():t,r=Xs.attract(s,o,e,i);s.vx+=r.fx*n,s.vy+=r.fy*n,void 0!==s.vz&&(s.vz+=r.fz*n)},gravity:(t=0,e=200,i=0)=>(s,n)=>{s.alive&&(s.vx+=t*n,s.vy+=e*n,void 0!==s.vz&&(s.vz+=i*n))},maxSpeed:t=>(e,i)=>{e.alive&&Xs.clampVelocity(e,t)},drag:(t=.01)=>(e,i)=>{if(!e.alive)return;const s=Xs.speed(e);if(s>.01){const n=t*s*s,o=Math.max(0,1-n*i/s);e.vx*=o,e.vy*=o,void 0!==e.vz&&(e.vz*=o)}},separation:(t=100,e=1.2)=>(i,s,n)=>{if(i.alive)for(const o of n.particles){if(o===i||!o.alive)continue;const n=Xs.checkCollision(i,o,e);if(n){const e=t*n.overlap,o=-n.dx/n.dist,r=-n.dy/n.dist,a=-n.dz/n.dist;i.vx+=o*e*s,i.vy+=r*e*s,void 0!==i.vz&&(i.vz+=a*e*s)}}},thermal:(t,e=10)=>(i,s)=>{if(!i.alive)return;const n=("function"==typeof t?t():t)*e*s;i.vx+=(Math.random()-.5)*n,i.vy+=(Math.random()-.5)*n,void 0!==i.vz&&(i.vz+=(Math.random()-.5)*n)},orbital:(t,e=100)=>(i,s)=>{if(!i.alive)return;const n=t.x-i.x,o=t.y-i.y,r=(t.z||0)-(i.z||0),a=Math.sqrt(n*n+o*o+r*r)||1,h=e/a;i.vx+=n/a*h*s,i.vy+=o/a*h*s,void 0!==i.vz&&(i.vz+=r/a*h*s)}};const Hs=200,Us="\nprecision highp float;\n\nattribute vec2 aPosition; // random seed in [-1, 1]\n\nuniform float uTime;\nuniform vec4 uParams; // (a, b, c, d)\nuniform int uIterations; // 0..200\nuniform mat3 uTransform; // clip-space transform\nuniform float uZoom;\nuniform float uPointScale;\nuniform float uPointSize;\nuniform int uColorMode;\nuniform vec4 uColor; // non-premultiplied RGBA (0..1)\nuniform vec2 uHueRange; // (minHue, maxHue)\nuniform float uMaxSpeed;\nuniform float uSaturation; // 0..1\nuniform float uLightness; // 0..1\nuniform float uAlpha; // 0..1\nuniform float uHueOffset; // degrees\n\nvarying vec4 vColor;\n\n// HSL to RGB (all 0..1). Based on a compact shader formulation.\nvec3 hsl2rgb(vec3 hsl) {\n vec3 rgb = clamp(abs(mod(hsl.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);\n rgb = rgb * rgb * (3.0 - 2.0 * rgb);\n float c = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\n return (rgb - 0.5) * c + hsl.z;\n}\n\nvoid main() {\n vec2 p = aPosition;\n vec2 lastDelta = vec2(0.0);\n\n // De Jong iterative map\n // x' = sin(a*y) - cos(b*x)\n // y' = sin(c*x) - cos(d*y)\n for (int i = 0; i < 200; i++) {\n if (i >= uIterations) break;\n vec2 prev = p;\n float x = sin(uParams.x * p.y) - cos(uParams.y * p.x);\n float y = sin(uParams.z * p.x) - cos(uParams.w * p.y);\n p = vec2(x, y);\n lastDelta = p - prev;\n }\n\n // Map attractor space into clip space\n vec3 transformed = uTransform * vec3(p * uPointScale * uZoom, 1.0);\n gl_Position = vec4(transformed.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n\n // Color\n vec4 c;\n if (uColorMode == 1) {\n // Lorenz-like mapping: slow → maxHue, fast → minHue\n float speed = length(lastDelta);\n float speedNorm = clamp(speed / max(uMaxSpeed, 0.0001), 0.0, 1.0);\n float baseHue = uHueRange.y - speedNorm * (uHueRange.y - uHueRange.x);\n float hue = mod(baseHue + uHueOffset, 360.0);\n vec3 rgb = hsl2rgb(vec3(hue / 360.0, clamp(uSaturation, 0.0, 1.0), clamp(uLightness, 0.0, 1.0)));\n c = vec4(rgb, clamp(uAlpha, 0.0, 1.0));\n } else {\n c = uColor;\n }\n\n // Premultiply in shader (renderer uses premultipliedAlpha for compositing)\n c.rgb *= c.a;\n vColor = c;\n}\n",Gs={circle:vs,glow:ys,square:_s,softSquare:xs};class Ns{constructor(t=1<<18,e={}){var i,s,n,o;if(this.seedCount=t,this.width=e.width??800,this.height=e.height??600,this.shape=e.shape??"glow",this.blendMode=e.blendMode??"additive",this.pointSize=e.pointSize??1,this.pointScale=e.pointScale??.5,this.iterations=Math.max(0,Math.min(Hs,e.iterations??100)),this.params={a:(null==(i=e.params)?void 0:i.a)??-2,b:(null==(s=e.params)?void 0:s.b)??-2,c:(null==(n=e.params)?void 0:n.c)??-1.2,d:(null==(o=e.params)?void 0:o.d)??2},this.zoom=1,this.transform=Ns.identityMat3(),this.color=e.color??{r:1,g:1,b:1,a:.12},this.colorMode=e.colorMode??0,this.hueRange=e.hueRange??{minHue:30,maxHue:200},this.maxSpeed=e.maxSpeed??1,this.saturation=e.saturation??.85,this.lightness=e.lightness??.55,this.alpha=e.alpha??this.color.a??.12,this.hueShiftSpeed=e.hueShiftSpeed??0,this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!1,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for DeJong renderer"),void(this.available=!1);this.available=!0,this._initGL(),this._createSeedBuffer(t),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}isAvailable(){return Boolean(this.available)}static identityMat3(){return new Float32Array([1,0,0,0,1,0,0,0,1])}static rotationMat3(t){const e=Math.cos(t),i=Math.sin(t);return new Float32Array([e,i,0,-i,e,0,0,0,1])}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_createSeedBuffer(t){const e=this.gl;this._seeds=new Float32Array(2*t);for(let i=0;i<this._seeds.length;i++)this._seeds[i]=2*Math.random()-1;this.seedBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.bufferData(e.ARRAY_BUFFER,this._seeds,e.STATIC_DRAW)}regenerateSeeds(){if(!this.available)return;for(let e=0;e<this._seeds.length;e++)this._seeds[e]=2*Math.random()-1;const t=this.gl;t.bindBuffer(t.ARRAY_BUFFER,this.seedBuffer),t.bufferData(t.ARRAY_BUFFER,this._seeds,t.STATIC_DRAW)}setSeedCount(t){if(!this.available)return;if(t===this.seedCount)return;this.seedCount=t;const e=this.gl;this.seedBuffer&&e.deleteBuffer(this.seedBuffer),this._createSeedBuffer(t)}_compileProgram(){const t=this.gl,e=Gs[this.shape]??Gs.glow,i=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(i,Us),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))return console.error("DeJong vertex shader error:",t.getShaderInfoLog(i)),void(this.available=!1);const s=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(s,e),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,i),t.attachShader(this.program,s),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.uTime=t.getUniformLocation(this.program,"uTime"),this.uParams=t.getUniformLocation(this.program,"uParams"),this.uIterations=t.getUniformLocation(this.program,"uIterations"),this.uTransform=t.getUniformLocation(this.program,"uTransform"),this.uZoom=t.getUniformLocation(this.program,"uZoom"),this.uPointScale=t.getUniformLocation(this.program,"uPointScale"),this.uPointSize=t.getUniformLocation(this.program,"uPointSize"),this.uColorMode=t.getUniformLocation(this.program,"uColorMode"),this.uColor=t.getUniformLocation(this.program,"uColor"),this.uHueRange=t.getUniformLocation(this.program,"uHueRange"),this.uMaxSpeed=t.getUniformLocation(this.program,"uMaxSpeed"),this.uSaturation=t.getUniformLocation(this.program,"uSaturation"),this.uLightness=t.getUniformLocation(this.program,"uLightness"),this.uAlpha=t.getUniformLocation(this.program,"uAlpha"),this.uHueOffset=t.getUniformLocation(this.program,"uHueOffset"),t.deleteShader(i),void t.deleteShader(s)):(console.error("DeJong program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("DeJong fragment shader error:",t.getShaderInfoLog(s)),void(this.available=!1))}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}setShape(t){if(t===this.shape)return;if(this.shape=t,!this.available)return;const e=this.gl;this.program&&e.deleteProgram(this.program),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}_applyStaticUniforms(){if(!this.available)return;const t=this.gl;t.useProgram(this.program),this.uPointScale&&t.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&t.uniform1f(this.uPointSize,this.pointSize)}setColorMode(t){this.colorMode=1===t?1:0}setColorRamp(t={}){void 0!==t.minHue&&(this.hueRange.minHue=t.minHue),void 0!==t.maxHue&&(this.hueRange.maxHue=t.maxHue),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed),void 0!==t.saturation&&(this.saturation=t.saturation),void 0!==t.lightness&&(this.lightness=t.lightness),void 0!==t.alpha&&(this.alpha=t.alpha),void 0!==t.hueShiftSpeed&&(this.hueShiftSpeed=t.hueShiftSpeed)}setParams(t){this.params={...this.params,...t}}setIterations(t){this.iterations=Math.max(0,Math.min(Hs,Math.floor(t)))}setZoom(t){this.zoom=t}setTransform(t){this.transform=t}setPointSize(t){this.pointSize=t,this.available&&this.uPointSize&&(this.gl.useProgram(this.program),this.gl.uniform1f(this.uPointSize,t))}setColor(t){this.color={...this.color,...t}}resize(t,e){this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available&&this.gl.viewport(0,0,t,e)}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t=0){if(!this.available)return;const e=this.gl;e.useProgram(this.program),this.uTime&&e.uniform1f(this.uTime,t),this.uParams&&e.uniform4f(this.uParams,this.params.a,this.params.b,this.params.c,this.params.d),this.uIterations&&e.uniform1i(this.uIterations,this.iterations),this.uTransform&&e.uniformMatrix3fv(this.uTransform,!1,this.transform),this.uZoom&&e.uniform1f(this.uZoom,this.zoom),this.uPointScale&&e.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&e.uniform1f(this.uPointSize,this.pointSize),this.uColor&&e.uniform4f(this.uColor,this.color.r,this.color.g,this.color.b,this.color.a),this.uColorMode&&e.uniform1i(this.uColorMode,this.colorMode),this.uHueRange&&e.uniform2f(this.uHueRange,this.hueRange.minHue,this.hueRange.maxHue),this.uMaxSpeed&&e.uniform1f(this.uMaxSpeed,this.maxSpeed),this.uSaturation&&e.uniform1f(this.uSaturation,this.saturation),this.uLightness&&e.uniform1f(this.uLightness,this.lightness),this.uAlpha&&e.uniform1f(this.uAlpha,this.alpha),this.uHueOffset&&e.uniform1f(this.uHueOffset,t*this.hueShiftSpeed%360),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.drawArrays(e.POINTS,0,this.seedCount)}compositeOnto(t,e=0,i=0,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),this.seedBuffer&&t.deleteBuffer(this.seedBuffer),this._seeds=null}}const qs=200,Zs="\nprecision highp float;\n\nattribute vec2 aPosition; // random seed in [-1, 1]\n\nuniform float uTime;\nuniform vec4 uParams; // (a, b, c, d)\nuniform int uIterations; // 0..200\nuniform mat3 uTransform; // clip-space transform\nuniform float uZoom;\nuniform float uPointScale;\nuniform float uPointSize;\nuniform int uColorMode;\nuniform vec4 uColor; // non-premultiplied RGBA (0..1)\nuniform vec2 uHueRange; // (minHue, maxHue)\nuniform float uMaxSpeed;\nuniform float uSaturation; // 0..1\nuniform float uLightness; // 0..1\nuniform float uAlpha; // 0..1\nuniform float uHueOffset; // degrees\n\nvarying vec4 vColor;\n\n// HSL to RGB (all 0..1). Based on a compact shader formulation.\nvec3 hsl2rgb(vec3 hsl) {\n vec3 rgb = clamp(abs(mod(hsl.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);\n rgb = rgb * rgb * (3.0 - 2.0 * rgb);\n float c = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\n return (rgb - 0.5) * c + hsl.z;\n}\n\nvoid main() {\n vec2 p = aPosition;\n vec2 lastDelta = vec2(0.0);\n\n // Clifford iterative map\n // x' = sin(a*y) + c*cos(a*x)\n // y' = sin(b*x) + d*cos(b*y)\n for (int i = 0; i < 200; i++) {\n if (i >= uIterations) break;\n vec2 prev = p;\n float x = sin(uParams.x * p.y) + uParams.z * cos(uParams.x * p.x);\n float y = sin(uParams.y * p.x) + uParams.w * cos(uParams.y * p.y);\n p = vec2(x, y);\n lastDelta = p - prev;\n }\n\n // Map attractor space into clip space\n vec3 transformed = uTransform * vec3(p * uPointScale * uZoom, 1.0);\n gl_Position = vec4(transformed.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n\n // Color\n vec4 c;\n if (uColorMode == 1) {\n float speed = length(lastDelta);\n float speedNorm = clamp(speed / max(uMaxSpeed, 0.0001), 0.0, 1.0);\n float baseHue = uHueRange.y - speedNorm * (uHueRange.y - uHueRange.x);\n float hue = mod(baseHue + uHueOffset, 360.0);\n vec3 rgb = hsl2rgb(vec3(hue / 360.0, clamp(uSaturation, 0.0, 1.0), clamp(uLightness, 0.0, 1.0)));\n c = vec4(rgb, clamp(uAlpha, 0.0, 1.0));\n } else {\n c = uColor;\n }\n\n // Premultiply in shader (renderer uses premultipliedAlpha for compositing)\n c.rgb *= c.a;\n vColor = c;\n}\n",Vs={circle:vs,glow:ys,square:_s,softSquare:xs};class $s{constructor(t=1<<18,e={}){var i,s,n,o;if(this.seedCount=t,this.width=e.width??800,this.height=e.height??600,this.shape=e.shape??"glow",this.blendMode=e.blendMode??"additive",this.pointSize=e.pointSize??1,this.pointScale=e.pointScale??.5,this.iterations=Math.max(0,Math.min(qs,e.iterations??120)),this.params={a:(null==(i=e.params)?void 0:i.a)??-1.4,b:(null==(s=e.params)?void 0:s.b)??1.6,c:(null==(n=e.params)?void 0:n.c)??1,d:(null==(o=e.params)?void 0:o.d)??.7},this.zoom=1,this.transform=$s.identityMat3(),this.color=e.color??{r:1,g:1,b:1,a:.12},this.colorMode=e.colorMode??0,this.hueRange=e.hueRange??{minHue:180,maxHue:300},this.maxSpeed=e.maxSpeed??1,this.saturation=e.saturation??.85,this.lightness=e.lightness??.55,this.alpha=e.alpha??this.color.a??.12,this.hueShiftSpeed=e.hueShiftSpeed??0,this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!1,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for Clifford renderer"),void(this.available=!1);this.available=!0,this._initGL(),this._createSeedBuffer(t),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}isAvailable(){return Boolean(this.available)}static identityMat3(){return new Float32Array([1,0,0,0,1,0,0,0,1])}static rotationMat3(t){const e=Math.cos(t),i=Math.sin(t);return new Float32Array([e,i,0,-i,e,0,0,0,1])}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_createSeedBuffer(t){const e=this.gl;this._seeds=new Float32Array(2*t);for(let i=0;i<this._seeds.length;i++)this._seeds[i]=2*Math.random()-1;this.seedBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.bufferData(e.ARRAY_BUFFER,this._seeds,e.STATIC_DRAW)}regenerateSeeds(){if(!this.available)return;for(let e=0;e<this._seeds.length;e++)this._seeds[e]=2*Math.random()-1;const t=this.gl;t.bindBuffer(t.ARRAY_BUFFER,this.seedBuffer),t.bufferData(t.ARRAY_BUFFER,this._seeds,t.STATIC_DRAW)}setSeedCount(t){if(!this.available)return;if(t===this.seedCount)return;this.seedCount=t;const e=this.gl;this.seedBuffer&&e.deleteBuffer(this.seedBuffer),this._createSeedBuffer(t)}_compileProgram(){const t=this.gl,e=Vs[this.shape]??Vs.glow,i=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(i,Zs),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS))return console.error("Clifford vertex shader error:",t.getShaderInfoLog(i)),void(this.available=!1);const s=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(s,e),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,i),t.attachShader(this.program,s),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.uTime=t.getUniformLocation(this.program,"uTime"),this.uParams=t.getUniformLocation(this.program,"uParams"),this.uIterations=t.getUniformLocation(this.program,"uIterations"),this.uTransform=t.getUniformLocation(this.program,"uTransform"),this.uZoom=t.getUniformLocation(this.program,"uZoom"),this.uPointScale=t.getUniformLocation(this.program,"uPointScale"),this.uPointSize=t.getUniformLocation(this.program,"uPointSize"),this.uColorMode=t.getUniformLocation(this.program,"uColorMode"),this.uColor=t.getUniformLocation(this.program,"uColor"),this.uHueRange=t.getUniformLocation(this.program,"uHueRange"),this.uMaxSpeed=t.getUniformLocation(this.program,"uMaxSpeed"),this.uSaturation=t.getUniformLocation(this.program,"uSaturation"),this.uLightness=t.getUniformLocation(this.program,"uLightness"),this.uAlpha=t.getUniformLocation(this.program,"uAlpha"),this.uHueOffset=t.getUniformLocation(this.program,"uHueOffset"),t.deleteShader(i),void t.deleteShader(s)):(console.error("Clifford program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("Clifford fragment shader error:",t.getShaderInfoLog(s)),void(this.available=!1))}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}setShape(t){if(t===this.shape)return;if(this.shape=t,!this.available)return;const e=this.gl;this.program&&e.deleteProgram(this.program),this._compileProgram(),this._setupBlending(),this._applyStaticUniforms()}_applyStaticUniforms(){if(!this.available)return;const t=this.gl;t.useProgram(this.program),this.uPointScale&&t.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&t.uniform1f(this.uPointSize,this.pointSize)}setColorMode(t){this.colorMode=1===t?1:0}setColorRamp(t={}){void 0!==t.minHue&&(this.hueRange.minHue=t.minHue),void 0!==t.maxHue&&(this.hueRange.maxHue=t.maxHue),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed),void 0!==t.saturation&&(this.saturation=t.saturation),void 0!==t.lightness&&(this.lightness=t.lightness),void 0!==t.alpha&&(this.alpha=t.alpha),void 0!==t.hueShiftSpeed&&(this.hueShiftSpeed=t.hueShiftSpeed)}setParams(t){this.params={...this.params,...t}}setIterations(t){this.iterations=Math.max(0,Math.min(qs,Math.floor(t)))}setZoom(t){this.zoom=t}setTransform(t){this.transform=t}setPointSize(t){this.pointSize=t,this.available&&this.uPointSize&&(this.gl.useProgram(this.program),this.gl.uniform1f(this.uPointSize,t))}setColor(t){this.color={...this.color,...t}}resize(t,e){this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available&&this.gl.viewport(0,0,t,e)}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t=0){if(!this.available)return;const e=this.gl;e.useProgram(this.program),this.uTime&&e.uniform1f(this.uTime,t),this.uParams&&e.uniform4f(this.uParams,this.params.a,this.params.b,this.params.c,this.params.d),this.uIterations&&e.uniform1i(this.uIterations,this.iterations),this.uTransform&&e.uniformMatrix3fv(this.uTransform,!1,this.transform),this.uZoom&&e.uniform1f(this.uZoom,this.zoom),this.uPointScale&&e.uniform1f(this.uPointScale,this.pointScale),this.uPointSize&&e.uniform1f(this.uPointSize,this.pointSize),this.uColor&&e.uniform4f(this.uColor,this.color.r,this.color.g,this.color.b,this.color.a),this.uColorMode&&e.uniform1i(this.uColorMode,this.colorMode),this.uHueRange&&e.uniform2f(this.uHueRange,this.hueRange.minHue,this.hueRange.maxHue),this.uMaxSpeed&&e.uniform1f(this.uMaxSpeed,this.maxSpeed),this.uSaturation&&e.uniform1f(this.uSaturation,this.saturation),this.uLightness&&e.uniform1f(this.uLightness,this.lightness),this.uAlpha&&e.uniform1f(this.uAlpha,this.alpha),this.uHueOffset&&e.uniform1f(this.uHueOffset,t*this.hueShiftSpeed%360),e.bindBuffer(e.ARRAY_BUFFER,this.seedBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.drawArrays(e.POINTS,0,this.seedCount)}compositeOnto(t,e=0,i=0,s,n){this.available&&t.drawImage(this.canvas,e,i,s??this.canvas.width,n??this.canvas.height)}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),this.seedBuffer&&t.deleteBuffer(this.seedBuffer),this._seeds=null}}t.AdvancedDelay=class{constructor(t,e={}){this.audioContext=t;const{delayTime:i=.15,maxDelay:s=.5,feedback:n=.2,wet:o=.15,dry:r=.85}=e;this.delay=t.createDelay(s),this.delay.delayTime.value=i,this.feedbackGain=t.createGain(),this.feedbackGain.gain.value=n,this.wetGain=t.createGain(),this.wetGain.gain.value=o,this.dryGain=t.createGain(),this.dryGain.gain.value=r,this.output=t.createGain(),this.output.gain.value=1,this.delay.connect(this.feedbackGain),this.feedbackGain.connect(this.delay),this.input=t.createGain()}connect(t){t.connect(this.dryGain),this.dryGain.connect(this.output),t.connect(this.delay),this.delay.connect(this.wetGain),this.wetGain.connect(this.output)}setDelayTime(t){this.delay.delayTime.value=t}setMix(t,e){this.wetGain.gain.value=t,this.dryGain.gain.value=e}setFeedback(t){this.feedbackGain.gain.value=t}getOutput(){return this.output}disconnect(){try{this.delay.disconnect(),this.feedbackGain.disconnect(),this.wetGain.disconnect(),this.dryGain.disconnect(),this.input.disconnect(),this.output.disconnect()}catch(t){}}},t.AdvancedDistortion=class{constructor(t,e={}){this.audioContext=t;const{amount:i=0,oversample:s="4x"}=e;this.shaper=t.createWaveShaper(),this.shaper.oversample=s,this.amount=i,this.updateCurve(i)}updateCurve(t){const e=44100,i=new Float32Array(e),s=Math.PI/180,n=400*t;for(let o=0;o<e;o++){const t=2*o/e-1;i[o]=0===n?t:(3+n)*t*20*s/(Math.PI+n*Math.abs(t))}this.shaper.curve=i,this.amount=t}connect(t){t.connect(this.shaper)}setAmount(t){this.updateCurve(t)}getNode(){return this.shaper}disconnect(){try{this.shaper.disconnect()}catch(t){}}},t.AdvancedTremolo=class{constructor(t,e={}){this.audioContext=t;const{rate:i=4,depth:s=0,lfoType:n="sine"}=e;this.gain=t.createGain(),this.gain.gain.value=1,this.lfo=t.createOscillator(),this.lfo.type=n,this.lfo.frequency.value=i,this.depthGain=t.createGain(),this.depthGain.gain.value=s,this.lfo.connect(this.depthGain),this.depthGain.connect(this.gain.gain),this.lfo.start()}connect(t){t.connect(this.gain)}setRate(t){this.lfo.frequency.value=t}setDepth(t){this.depthGain.gain.value=t}getNode(){return this.gain}disconnect(){try{this.lfo.stop(),this.lfo.disconnect(),this.depthGain.disconnect(),this.gain.disconnect()}catch(t){}}},t.Arc=je,t.Arrow=yi,t.AttractorDimension=ie,t.AttractorType=ee,t.Attractors=se,t.BezierShape=class extends Ve{constructor(t=[],e={}){super(e),this.path=t}draw(){super.draw(),Ye.lines.path(this.path,this.color,this.stroke,this.lineWidth)}getBounds(){return{x:this.x,y:this.y,width:100,height:100}}},t.BooleanAlgebra=te,t.Button=ds,t.CLIFFORD_MAX_ITERATIONS=qs,t.CLIFFORD_POINT_FRAGMENTS=Vs,t.CLIFFORD_POINT_VERTEX=Zs,t.Camera2D=Bt,t.Camera3D=class{constructor(t={}){this.rotationX=t.rotationX??0,this.rotationY=t.rotationY??0,this.rotationZ=t.rotationZ??0,this.x=t.x??0,this.y=t.y??0,this.z=t.z??0,this._initialRotationX=this.rotationX,this._initialRotationY=this.rotationY,this._initialRotationZ=this.rotationZ,this._initialX=this.x,this._initialY=this.y,this._initialZ=this.z,this.perspective=t.perspective??800,this.sensitivity=t.sensitivity??.005,this.minRotationX=t.minRotationX??-1.5,this.maxRotationX=t.maxRotationX??1.5,this.clampX=t.clampX??!0,this.autoRotate=t.autoRotate??!1,this.autoRotateSpeed=t.autoRotateSpeed??.5,this.autoRotateAxis=t.autoRotateAxis??"y",this.inertia=t.inertia??!1,this.friction=t.friction??.92,this.velocityScale=t.velocityScale??1,this._velocityX=0,this._velocityY=0,this._lastDeltaX=0,this._lastDeltaY=0,this._lastMoveTime=0,this._isDragging=!1,this._lastMouseX=0,this._lastMouseY=0,this._canvas=null,this._boundHandlers=null,this._followTarget=null,this._followOffset={x:0,y:0,z:0},this._followLookAt=!0,this._followLerp=.1,this._targetX=null,this._targetY=null,this._targetZ=null,this._targetRotationX=null,this._targetRotationY=null,this._positionLerp=.05}project(t,e,i){if(t-=this.x,e-=this.y,i-=this.z,0!==this.rotationZ){const i=Math.cos(this.rotationZ),s=Math.sin(this.rotationZ),n=t;t=n*i-e*s,e=n*s+e*i}const s=Math.cos(this.rotationY),n=Math.sin(this.rotationY),o=t*s-i*n,r=t*n+i*s,a=Math.cos(this.rotationX),h=Math.sin(this.rotationX),l=e*a-r*h,c=e*h+r*a,u=this.perspective/(this.perspective+c);return{x:o*u,y:l*u,z:c,scale:u}}projectAll(t){return t.map(t=>this.project(t.x,t.y,t.z))}update(t){var e,i,s;if(this._followTarget){const t=this._followTarget,n=(t.x??0)+this._followOffset.x,o=(t.y??0)+this._followOffset.y,r=(t.z??0)+this._followOffset.z;if(this.x+=(n-this.x)*this._followLerp,this.y+=(o-this.y)*this._followLerp,this.z+=(r-this.z)*this._followLerp,this._followLookAt){const t=(null==(e=this._followLookAtTarget)?void 0:e.x)??0,n=(null==(i=this._followLookAtTarget)?void 0:i.y)??0,o=(null==(s=this._followLookAtTarget)?void 0:s.z)??0,r=t-this.x,a=n-this.y,h=o-this.z,l=Math.sqrt(r*r+h*h),c=Math.atan2(r,h),u=Math.atan2(-a,l);this.rotationY+=this._angleDiff(this.rotationY,c)*this._followLerp,this.rotationX+=(u-this.rotationX)*this._followLerp}}else if(null!==this._targetX){const t=this._positionLerp;this.x+=(this._targetX-this.x)*t,this.y+=(this._targetY-this.y)*t,this.z+=(this._targetZ-this.z)*t,null!==this._targetRotationX&&(this.rotationX+=(this._targetRotationX-this.rotationX)*t),null!==this._targetRotationY&&(this.rotationY+=this._angleDiff(this.rotationY,this._targetRotationY)*t);Math.abs(this._targetX-this.x)+Math.abs(this._targetY-this.y)+Math.abs(this._targetZ-this.z)<.1&&(this.x=this._targetX,this.y=this._targetY,this.z=this._targetZ,this._targetX=null,this._targetY=null,this._targetZ=null,this._targetRotationX=null,this._targetRotationY=null)}if(!this.inertia||this._isDragging||this._followTarget||(Math.abs(this._velocityX)>1e-4||Math.abs(this._velocityY)>1e-4)&&(this.rotationY+=this._velocityY,this.rotationX+=this._velocityX,this.clampX&&(this.rotationX=Math.max(this.minRotationX,Math.min(this.maxRotationX,this.rotationX))),this._velocityX*=this.friction,this._velocityY*=this.friction,Math.abs(this._velocityX)<1e-4&&(this._velocityX=0),Math.abs(this._velocityY)<1e-4&&(this._velocityY=0)),this.autoRotate&&!this._isDragging&&!this._followTarget){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=Ke,t.Cloud=Je,t.Collision=Ss,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&&(Ss.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&&Ss.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&&(Ss.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&&(Ss.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 Ve{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;Ye.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=wi,t.Cube=class extends Ve{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)&&Ye.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 Ve{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&&Ye.shapes.fillRect(-t,-t,this.size,this.size,this.faceColors.front))}const t=Ye.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),v=Math.sin(this.camera.rotationY),y=f*m-g*v,_=f*v+g*m,x=Math.cos(this.camera.rotationX),b=Math.sin(this.camera.rotationX),w=p*x-_*b,M=p*b+_*x;if(M>.01)continue;const S=this.camera.project(a,h,l);if(S.z<10-this.camera.perspective)continue;const C=this._calculateLighting(y,w,M),T=this._getFaceVertices(s,n,e);i.push({name:s,config:n,projected:S,vertices:T,depth:S.z,intensity:C,nx:y,ny:w,nz:M})}i.sort((t,e)=>e.depth-t.depth);for(const 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 Fi{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 Ve{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}Ye.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.DEJONG_MAX_ITERATIONS=Hs,t.DEJONG_POINT_FRAGMENTS=Gs,t.DEJONG_POINT_VERTEX=Us,t.DJFilter=class{constructor(t,e={}){this.audioContext=t;const{type:i="lowpass",frequency:s=2e4,Q:n=1}=e;this.filter=t.createBiquadFilter(),this.filter.type=i,this.filter.frequency.value=s,this.filter.Q.value=n}connect(t){t.connect(this.filter)}setFrequency(t){this.filter.frequency.value=t}setQ(t){this.filter.Q.value=t}setType(t){this.filter.type=t}getNode(){return this.filter}disconnect(){try{this.filter.disconnect()}catch(t){}}},t.DebugTab=Ae,t.Diamond=ii,t.EQFilterBank=class{constructor(t,e={}){this.audioContext=t;const{numBands:i=16,minFreq:s=40,maxFreq:n=12e3,Q:o=4}=e;this.filters=[],this.numBands=i;for(let r=0;r<i;r++){const e=t.createBiquadFilter();e.type="peaking";const a=i>1?s*Math.pow(n/s,r/(i-1)):(s+n)/2;e.frequency.value=a,e.Q.value=o,e.gain.value=0,this.filters.push(e)}}connect(t){let e=t;for(const i of this.filters)e.connect(i),e=i}setBandGain(t,e){t>=0&&t<this.filters.length&&(this.filters[t].gain.value=e)}setBandGains(t){for(let e=0;e<Math.min(t.length,this.filters.length);e++)this.filters[e].gain.value=t[e]}getFilter(t){return this.filters[t]}getFilters(){return this.filters}disconnect(){for(const e of this.filters)try{e.disconnect()}catch(t){}}},t.Easing=re,t.Euclidian=We,t.EventEmitter=Ci,t.FPSCounter=class extends Hi{constructor(t,e={}){super(t,"0 FPS",{x:0,y:0,font:us.fonts.small,color:us.colors.neonGreen,align:"center",baseline:"middle",debug:!1,...e}),this.fps=0,this._frames=0,this._accum=0}update(t){const e=this.game.actualFps;e&&(this._frames++,this._accum+=t,this._accum>=.5&&(this.fps=Math.round(e),this.text=`${this.fps} FPS`,this._accum=0,this._frames=0),super.update(t))}getBounds(){if(this.shape&&this.shape.getTextBounds){const t=this.shape.getTextBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}return super.getBounds()}getDebugBounds(){if(this.shape&&this.shape.getDebugBounds){const t=this.shape.getDebugBounds();return{x:t.x,y:t.y,width:t.width,height:t.height}}return super.getDebugBounds()}},t.Flanger=class{constructor(t,e={}){this.audioContext=t;const{baseDelay:i=.005,maxDelay:s=.02,lfoFrequency:n=.5,lfoDepth:o=.002,feedback:r=.5,wet:a=0,dry:h=1}=e;this.delay=t.createDelay(s),this.delay.delayTime.value=i,this.lfo=t.createOscillator(),this.lfo.type="sine",this.lfo.frequency.value=n,this.lfoDepth=t.createGain(),this.lfoDepth.gain.value=o,this.feedback=t.createGain(),this.feedback.gain.value=r,this.wetGain=t.createGain(),this.wetGain.gain.value=a,this.dryGain=t.createGain(),this.dryGain.gain.value=h,this.output=t.createGain(),this.output.gain.value=1,this.lfo.connect(this.lfoDepth),this.lfoDepth.connect(this.delay.delayTime),this.delay.connect(this.feedback),this.feedback.connect(this.delay),this.lfo.start(),this.input=t.createGain()}connect(t){t.connect(this.dryGain),this.dryGain.connect(this.output),t.connect(this.delay),this.delay.connect(this.wetGain),this.wetGain.connect(this.output)}setMix(t,e){this.wetGain.gain.value=t,this.dryGain.gain.value=e}setLFOFrequency(t){this.lfo.frequency.value=t}setFeedback(t){this.feedback.gain.value=t}disconnect(){try{this.lfo.stop(),this.lfo.disconnect(),this.delay.disconnect(),this.feedback.disconnect(),this.wetGain.disconnect(),this.dryGain.disconnect(),this.lfoDepth.disconnect(),this.input.disconnect(),this.output.disconnect()}catch(t){}}},t.FluentGO=ks,t.FluentGame=zs,t.FluentLayer=Ps,t.FluentScene=Rs,t.FluidSystem=Ts,t.Fractals=Ft,t.Game=cs,t.GameObject=Fi,t.GameObjectShapeWrapper=Oi,t.Geometry2d=He,t.Gesture=class{constructor(t,e={}){this.canvas=t,this.onZoom=e.onZoom||null,this.onPan=e.onPan||null,this.onTap=e.onTap||null,this.onDragStart=e.onDragStart||null,this.onDragEnd=e.onDragEnd||null,this.wheelZoomFactor=e.wheelZoomFactor??.1,this.pinchZoomFactor=e.pinchZoomFactor??1,this.panScale=e.panScale??1,this.tapThreshold=e.tapThreshold??10,this.tapTimeout=e.tapTimeout??300,this.preventDefault=e.preventDefault??!0,this._isDragging=!1,this._hasMoved=!1,this._startTime=0,this._startX=0,this._startY=0,this._lastX=0,this._lastY=0,this._touches=new Map,this._lastPinchDist=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0,this._onMouseDown=this._onMouseDown.bind(this),this._onMouseMove=this._onMouseMove.bind(this),this._onMouseUp=this._onMouseUp.bind(this),this._onMouseLeave=this._onMouseLeave.bind(this),this._onWheel=this._onWheel.bind(this),this._onTouchStart=this._onTouchStart.bind(this),this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this._onTouchCancel=this._onTouchCancel.bind(this),this._attachListeners()}get isDragging(){return this._isDragging}_attachListeners(){const t=this.canvas,e=!this.preventDefault;t.addEventListener("mousedown",this._onMouseDown),t.addEventListener("mousemove",this._onMouseMove),t.addEventListener("mouseup",this._onMouseUp),t.addEventListener("mouseleave",this._onMouseLeave),t.addEventListener("wheel",this._onWheel,{passive:e}),t.addEventListener("touchstart",this._onTouchStart,{passive:e}),t.addEventListener("touchmove",this._onTouchMove,{passive:e}),t.addEventListener("touchend",this._onTouchEnd,{passive:e}),t.addEventListener("touchcancel",this._onTouchCancel)}destroy(){const t=this.canvas;t.removeEventListener("mousedown",this._onMouseDown),t.removeEventListener("mousemove",this._onMouseMove),t.removeEventListener("mouseup",this._onMouseUp),t.removeEventListener("mouseleave",this._onMouseLeave),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("touchstart",this._onTouchStart),t.removeEventListener("touchmove",this._onTouchMove),t.removeEventListener("touchend",this._onTouchEnd),t.removeEventListener("touchcancel",this._onTouchCancel),this._touches.clear()}_getMousePos(t){const e=this.canvas.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_getTouchPos(t){const e=this.canvas.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_onMouseDown(t){const e=this._getMousePos(t);this._isDragging=!0,this._hasMoved=!1,this._startTime=Date.now(),this._startX=e.x,this._startY=e.y,this._lastX=e.x,this._lastY=e.y,this.onDragStart&&this.onDragStart(e.x,e.y)}_onMouseMove(t){if(!this._isDragging)return;const e=this._getMousePos(t),i=e.x-this._lastX,s=e.y-this._lastY,n=Math.abs(e.x-this._startX),o=Math.abs(e.y-this._startY);(n>this.tapThreshold||o>this.tapThreshold)&&(this._hasMoved=!0),this.onPan&&this._hasMoved&&this.onPan(i*this.panScale,s*this.panScale),this._lastX=e.x,this._lastY=e.y}_onMouseUp(t){if(!this._isDragging)return;const e=Date.now()-this._startTime;if(!this._hasMoved&&e<this.tapTimeout&&this.onTap){const e=this._getMousePos(t);this.onTap(e.x,e.y)}this._isDragging=!1,this.onDragEnd&&this.onDragEnd()}_onMouseLeave(){this._isDragging&&(this._isDragging=!1,this.onDragEnd&&this.onDragEnd())}_onWheel(t){if(this.preventDefault&&t.preventDefault(),this.onZoom){const e=this._getMousePos(t),i=t.deltaY>0?-this.wheelZoomFactor:this.wheelZoomFactor;this.onZoom(i,e.x,e.y)}}_onTouchStart(t){this.preventDefault&&t.preventDefault(),this._startTime=Date.now(),this._hasMoved=!1;for(const e of t.changedTouches){const t=this._getTouchPos(e);this._touches.set(e.identifier,{x:t.x,y:t.y})}if(2===this._touches.size){const[t,e]=Array.from(this._touches.values());this._lastPinchDist=Math.hypot(e.x-t.x,e.y-t.y),this._lastPinchCenterX=(t.x+e.x)/2,this._lastPinchCenterY=(t.y+e.y)/2,this._isDragging=!1}if(1===this._touches.size){const e=t.touches[0],i=this._getTouchPos(e);this._isDragging=!0,this._startX=i.x,this._startY=i.y,this._lastX=i.x,this._lastY=i.y,this.onDragStart&&this.onDragStart(i.x,i.y)}}_onTouchMove(t){this.preventDefault&&t.preventDefault();for(const e of t.changedTouches)if(this._touches.has(e.identifier)){const t=this._getTouchPos(e);this._touches.set(e.identifier,{x:t.x,y:t.y})}if(2===this._touches.size){const[t,e]=Array.from(this._touches.values()),i=Math.hypot(e.x-t.x,e.y-t.y),s=(t.x+e.x)/2,n=(t.y+e.y)/2;if(this._lastPinchDist>0){if(this.onZoom){const t=(i/this._lastPinchDist-1)*this.pinchZoomFactor;this.onZoom(t,s,n)}if(this.onPan){const t=s-this._lastPinchCenterX,e=n-this._lastPinchCenterY;this.onPan(t*this.panScale,e*this.panScale)}this._hasMoved=!0}this._lastPinchDist=i,this._lastPinchCenterX=s,this._lastPinchCenterY=n}else if(1===this._touches.size&&this._isDragging){const e=t.touches[0],i=this._getTouchPos(e),s=i.x-this._lastX,n=i.y-this._lastY,o=Math.abs(i.x-this._startX),r=Math.abs(i.y-this._startY);(o>this.tapThreshold||r>this.tapThreshold)&&(this._hasMoved=!0),this.onPan&&this._hasMoved&&this.onPan(s*this.panScale,n*this.panScale),this._lastX=i.x,this._lastY=i.y}}_onTouchEnd(t){this.preventDefault&&t.preventDefault();for(const e of t.changedTouches)this._touches.delete(e.identifier);if(this._touches.size<2&&(this._lastPinchDist=0),0===this._touches.size){const t=Date.now()-this._startTime;!this._hasMoved&&t<this.tapTimeout&&this.onTap&&this.onTap(this._startX,this._startY),this._isDragging=!1,this.onDragEnd&&this.onDragEnd()}}_onTouchCancel(){this._touches.clear(),this._lastPinchDist=0,this._isDragging=!1,this.onDragEnd&&this.onDragEnd()}},t.GridLayout=class extends Yi{constructor(t,e={}){super(t,e),this.columns=e.columns??4,this.debug=e.debug??!1}calculateLayout(){return this.children.length?Dt(this.children,{columns:this.columns,spacing:this.spacing,padding:this.padding,centerItems:this.centerItems,width:this.autoSize?void 0:this.width,height:this.autoSize?void 0:this.height}):null}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:-(this._contentHeight??this.height)/2}}},t.Group=$e,t.Heart=bi,t.Hexagon=xi,t.HighShelf=class{constructor(t,e={}){this.audioContext=t;const{frequency:i=4e3,gain:s=3}=e;this.filter=t.createBiquadFilter(),this.filter.type="highshelf",this.filter.frequency.value=i,this.filter.gain.value=s}connect(t){t.connect(this.filter)}setFrequency(t){this.filter.frequency.value=t}setGain(t){this.filter.gain.value=t}getNode(){return this.filter}disconnect(){try{this.filter.disconnect()}catch(t){}}},t.HorizontalLayout=class extends Yi{getScrollAxis(){return{horizontal:!0,vertical:!1}}calculateLayout(){return Rt(this.children,{spacing:this.spacing,padding:this.padding,align:this.align,centerItems:!0})}getLayoutOffset(){return{offsetX:-(this._contentWidth??this.width)/2,offsetY:0}}},t.ImageGo=class extends Oi{constructor(t,e,i={}){super(t,e instanceof Si?e:new Si(e,i),i)}reset(){this.shape.reset()}},t.ImageShape=Si,t.Input=Ti,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 Li{constructor(t,e={}){super(t,e),this.tileWidth=e.tileWidth??64,this.tileHeight=e.tileHeight??this.tileWidth/2,this.depthSort=e.depthSort??!0,this.scaleByDepth=e.scaleByDepth??!1,this.gridSize=e.gridSize??10,this.elevationScale=e.elevationScale??1,this.camera=e.camera??null}setCamera(t){return this.camera=t,this}toIsometric(t,e,i=0){let s=t,n=e;if(this.camera){const i=this.camera.angle,o=Math.cos(i),r=Math.sin(i);s=t*o-e*r,n=t*r+e*o}return{x:(s-n)*(this.tileWidth/2),y:(s+n)*(this.tileHeight/2)-i*this.elevationScale,depth:s+n-.01*i}}fromIsometric(t,e){const i=this.tileWidth/2,s=this.tileHeight/2;let n=(t/i+e/s)/2,o=(e/s-t/i)/2;if(this.camera){const t=-this.camera.angle,e=Math.cos(t),i=Math.sin(t);return{x:n*e-o*i,y:n*i+o*e}}return{x:n,y:o}}update(t){super.update(t),this.camera&&this.camera.update(t)}getTileAt(t,e){const i=this.fromIsometric(t,e);return{x:Math.floor(i.x),y:Math.floor(i.y)}}getRotatedDepth(t,e=0){const i=this.camera?this.camera.angle:0,s=Math.cos(i),n=Math.sin(i);let o=-1/0;for(const r of t){const t=r.x*s-r.y*n+(r.x*n+r.y*s);t>o&&(o=t)}return o+.5*e}getDepthScale(t){return.7+Math.abs(t)/this.gridSize*.6}render(){if(!this.visible)return;Ye.save(),Ye.translateTo(this.x,this.y);const t=[];for(const e of this._collection.getSortedChildren()){if(!e.visible)continue;let i;if(void 0!==e.isoDepth)i=e.isoDepth;else{let t=e.x,s=e.y;if(this.camera){const i=this.camera.angle,n=Math.cos(i),o=Math.sin(i);t=e.x*n-e.y*o,s=e.x*o+e.y*n}i=t+s+.05*(e.z??0)}t.push({child:e,depth:i})}this.depthSort&&t.sort((t,e)=>{const i=t.child.zIndex??0,s=e.child.zIndex??0;return i!==s?i-s:t.depth-e.depth});for(const e of t)Ye.save(),e.child.render(),Ye.restore();Ye.restore()}},t.Kernels=me,t.Keys=Ai,t.LayoutScene=Yi,t.Limiter=class{constructor(t,e={}){this.audioContext=t;const{threshold:i=-3,knee:s=0,ratio:n=20,attack:o=.001,release:r=.1}=e;this.compressor=t.createDynamicsCompressor(),this.compressor.threshold.value=i,this.compressor.knee.value=s,this.compressor.ratio.value=n,this.compressor.attack.value=o,this.compressor.release.value=r}connect(t){t.connect(this.compressor)}setThreshold(t){this.compressor.threshold.value=t}getNode(){return this.compressor}disconnect(){try{this.compressor.disconnect()}catch(t){}}},t.Line=si,t.Loggable=Pe,t.Logger=ke,t.Mask=Ui,t.MasterGain=class{constructor(t,e=1){this.audioContext=t,this.gain=t.createGain(),this.gain.gain.value=e}connect(t){t.connect(this.gain)}setVolume(t){this.gain.gain.value=t}getNode(){return this.gain}disconnect(){try{this.gain.disconnect()}catch(t){}}},t.Motion=rs,t.Mouse=Pi,t.Noise=Lt,t.OutlinedText=class extends Ve{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(!Ye.ctx)return console.warn("Painter context not initialized. Cannot calculate text dimensions."),this.width=0,void(this.height=0);const t=Ye.text.font();this.font&&Ye.text.setFont(this.font);const e=Ye.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,Ye.text.setFont(t)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Ye.ctx)return void console.warn("Painter context not initialized. Cannot draw text.");let t=0;this.font&&Ye.text.setFont(this.font),Ye.text.setTextAlign(this.align),Ye.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)),Ye.outlinedText(this.text,0,t,this.color,this.stroke,this.lineWidth,this.font)}getBounds(){if(!Ye.ctx)return super.getBounds();const t=Ye.text.font();Ye.text.setFont(this.font);const e=Ye.text.measureText(this.text),i=e.width,s=e.actualBoundingBoxAscent+e.actualBoundingBoxDescent||parseInt(this.font)||20;return Ye.text.setFont(t),this.width=i,this.height=s,{x:this.x,y:this.y,width:i,height:s}}},t.POINT_SPRITE_CIRCLE_FRAGMENT=vs,t.POINT_SPRITE_GLOW_FRAGMENT=ys,t.POINT_SPRITE_PRESETS=bs,t.POINT_SPRITE_SOFT_SQUARE_FRAGMENT=xs,t.POINT_SPRITE_SQUARE_FRAGMENT=_s,t.POINT_SPRITE_VERTEX=ms,t.Painter=Ye,t.PainterColors=Xe,t.PainterEffects=De,t.PainterImages=Be,t.PainterLines=Ie,t.PainterOpacity=Ee,t.PainterShapes=Fe,t.PainterText=Oe,t.Parallelogram=class extends Ve{constructor(t={}){super(t),this._pgWidth=t.width??100,this._pgHeight=t.height??50,this._slant=t.slant??this._pgHeight,this._flipX=t.flipX??!1,this._updateDimensions()}get pgWidth(){return this._pgWidth}set pgWidth(t){this._pgWidth=t,this._updateDimensions(),this.invalidateCache()}get pgHeight(){return this._pgHeight}set pgHeight(t){this._pgHeight=t,this._updateDimensions(),this.invalidateCache()}get slant(){return this._slant}set slant(t){this._slant=t,this._updateDimensions(),this.invalidateCache()}get flipX(){return this._flipX}set flipX(t){this._flipX=t,this.invalidateCache()}_updateDimensions(){this._width=this._pgWidth+Math.abs(this._slant),this._height=this._pgHeight}getVertices(){const t=this._pgWidth,e=this._pgHeight;let i=this._slant;this._flipX&&(i=-i);const s=-(t+Math.abs(i))/2+(i<0?-i:0);return[{x:s,y:e/2},{x:s+t,y:e/2},{x:s+t+i,y:-e/2},{x:s+i,y:-e/2}]}draw(){super.draw();const t=this.getVertices();Ye.shapes.polygon(t,this.color,this.stroke,this.lineWidth,this.lineJoin)}calculateBounds(){return{x:this.x,y:this.y,width:this._width,height:this._height}}},t.Particle=fs,t.ParticleEmitter=ps,t.ParticleSystem=Ms,t.PatternRectangle=class extends Ve{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=Ye.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?Ye.img.fillPattern(this.pattern,t,e,this.width,this.height):this.strokeColor&&Ye.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 v=0;v<a.length;v+=4)a[v]=r[0],a[v+1]=r[1],a[v+2]=r[2],a[v+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 v=g;v<=m;v++)for(let e=f;e<=p;e++){const i=c(e,v,h,l,s),n=u>0&&c(e,v,h,l,u);if(i&&!n){const i=4*(v*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,v=c-s/2,y=c+s/2;for(let i=Math.max(0,Math.floor(v));i<Math.min(e,Math.ceil(y));i++)for(let e=Math.max(0,Math.floor(g));e<Math.min(t,Math.ceil(m));e++){const s=4*(i*t+e);h[s]=a[0],h[s+1]=a[1],h[s+2]=a[2],h[s+3]=a[3]}}return h}static mesh(t,e,i={}){const{spacing:s=20,lineWidth:n=2,background:o=[255,255,255,0],foreground:r=[0,0,0,255]}=i,a=new Uint8ClampedArray(t*e*4);for(let 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);Lt.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+=Lt.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);Lt.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+Lt.perlin2(e*a,u*a)*r,o=u+Lt.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&&Lt.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*(Lt.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);Lt.seed(a);const d=[],f=[],p=()=>{let t=1e4*Math.sin(.167*a+.423*d.length);return t-Math.floor(t)},g=Math.sqrt(s),m=t/g,v=e/g,y=t=>{if(l){const[e,i,s,n]=l,o=Math.max(e,i,s)/255,r=Math.min(e,i,s)/255,a=(o+r)/2;let h,u;if(o===r)h=u=0;else{const t=o-r;u=a>.5?t/(2-o-r):t/(o+r),h=o===e/255?(i/255-s/255)/t+(i/255<s/255?6:0):o===i/255?(s/255-e/255)/t+2:(e/255-i/255)/t+4,h/=6}const d=Lt.perlin2(.15*t,0)*c*.3,f=Lt.perlin2(0,.15*t)*c,g=Lt.perlin2(.15*t,.15*t)*c*.5;h=(h+d)%1,u=Math.min(1,Math.max(0,u*(1+f)));const m=Math.min(.9,Math.max(.1,a*(1+g)));let v,y,_;if(0===u)v=y=_=m;else{const t=(t,e,i)=>(i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t),e=m<.5?m*(1+u):m+u-m*u,i=2*m-e;v=t(i,e,h+1/3),y=t(i,e,h),_=t(i,e,h-1/3)}const x=.05,b=()=>(2*p()-1)*x;return[Math.min(255,Math.max(0,Math.floor(255*v*(1+b())))),Math.min(255,Math.max(0,Math.floor(255*y*(1+b())))),Math.min(255,Math.max(0,Math.floor(255*_*(1+b())))),n]}{let e,i,s;const n=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 x=0;x<g;x++)for(let t=0;t<g&&!(d.length>=s);t++){const e=t*m+m/2,i=x*v+v/2,s=(2*p()-1)*h*m,o=(2*p()-1)*h*v;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(y(d.length-1))}const _=(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 x=0;x<e;x++)for(let i=0;i<t;i++){const s=4*(x*t+i);let n=1/0,a=1/0,h=0;for(let t=0;t<d.length;t++){const e=_(i,x,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(x-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.Physics=Xs,t.PhysicsUpdaters=Ws,t.PieSlice=class extends Ve{constructor(t,e,i,s={}){super(s),this.radius=t,this.startAngle=e,this.endAngle=i}draw(){super.draw(),Ye.lines.beginPath(),Ye.lines.moveTo(0,0),Ye.shapes.arc(0,0,this.radius,this.startAngle,this.endAngle),Ye.lines.closePath(),this.color&&Ye.colors.fill(this.color),this.stroke&&Ye.colors.stroke(this.stroke,this.lineWidth)}},t.Pin=_i,t.Pipeline=ls,t.Plane3D=pi,t.PlatformerScene=class extends Li{constructor(t,e={}){super(t,e),this.player=e.player??null,this._layers=[],this.gravity=e.gravity??1200,this.groundY=e.groundY??null,this.moveSpeed=e.moveSpeed??300,this.jumpVelocity=e.jumpVelocity??-500,this.autoInput=e.autoInput??!0,this.autoGravity=e.autoGravity??!0,this._viewportWidth=e.viewportWidth??null,this._viewportHeight=e.viewportHeight??null,this.player&&(void 0===this.player.vx&&(this.player.vx=0),void 0===this.player.vy&&(this.player.vy=0),void 0===this.player._grounded&&(this.player._grounded=!0)),e.camera?this.camera=e.camera:this.player?this.camera=new Bt({target:this.player,viewportWidth:this._viewportWidth??t.width,viewportHeight:this._viewportHeight??t.height,lerp:.1}):this.camera=null}addLayer(t,e={}){const i={gameObject:t,speed:e.speed??1,offsetX:e.offsetX??0,offsetY:e.offsetY??0};return this._layers.push(i),this.add(t),t}removeLayer(t){const e=this._layers.findIndex(e=>e.gameObject===t);return-1!==e&&(this._layers.splice(e,1),this.remove(t),!0)}getLayers(){return[...this._layers]}isLayer(t){return this._layers.some(e=>e.gameObject===t)}applyGravity(t,e){t.vy=(t.vy||0)+this.gravity*e}applyInput(t,e){let i=0;Ai.isDown(Ai.LEFT)||Ai.isDown(Ai.A)?i=-1:(Ai.isDown(Ai.RIGHT)||Ai.isDown(Ai.D))&&(i=1),t.vx=i*this.moveSpeed;(Ai.isDown(Ai.SPACE)||Ai.isDown(Ai.W)||Ai.isDown(Ai.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();Ye.save(),Ye.ctx.beginPath(),Ye.ctx.rect(-this.x,-this.y,t,e),Ye.ctx.clip(),Ye.ctx.beginPath(),Ye.ctx.translate(-this.x,-this.y);for(const s of this._layers){if(!s.gameObject.visible)continue;Ye.save();const t=i.x*s.speed+(s.offsetX||0),e=i.y*s.speed+(s.offsetY||0);Ye.ctx.translate(-t,-e),s.gameObject.render(),Ye.restore()}for(const s of this._collection.getSortedChildren())s.visible&&(this._layers.some(t=>t.gameObject===s)||(Ye.save(),Ye.ctx.translate(-i.x,-i.y),s.render(),Ye.restore()));Ye.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=vi,t.Position=kt,t.Prism=class extends Ve{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)&&Ye.shapes.polygon(e.points,e.color,this.stroke,this.lineWidth)})}getBounds(){const t=1.5*Math.max(this.width,this.height,this.depth);return{x:this.x-t/2,y:this.y-t/2,width:t,height:t}}},t.Random=It,t.Rectangle=Qe,t.Renderable=Ge,t.RightTriangle=class extends Ve{constructor(t=50,e={}){super(e),this._leg=t,this._updateDimensions()}get leg(){return this._leg}set leg(t){this._leg=t,this._updateDimensions(),this.invalidateCache()}get hypotenuse(){return this._leg*Math.SQRT2}_updateDimensions(){this._width=this._leg,this._height=this._leg}getVertices(){const t=this._leg,e=t/3,i=t/3;return[{x:-e,y:-i},{x:t-e,y:-i},{x:-e,y:t-i}]}draw(){super.draw();const t=this.getVertices();Ye.shapes.polygon(t,this.color,this.stroke,this.lineWidth,this.lineJoin)}calculateBounds(){return{x:this.x,y:this.y,width:this._width,height:this._height}}},t.Ring=mi,t.RoundedRectangle=ti,t.SPHERE_SHADERS=hi,t.SVGShape=gi,t.Scene=Li,t.Scene3D=class extends Li{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;Ye.save(),Ye.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)Ye.save(),Ye.translateTo(e.x,e.y),this.scaleByDepth&&Ye.ctx.scale(e.scale,e.scale),Ye.translateTo(-e.child.x,-e.child.y),e.child.render(),Ye.restore();Ye.restore()}},t.Screen=Ii,t.Shape=Ve,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 Oi(t,e,s)}},t.Sound=class{static beep(t=440,e=.1,i={}){if(!Ls.isInitialized)return;const{volume:s=.3,type:n="sine"}=i;Ls.osc.tone(t,e,{type:n,volume:s,attack:.001,decay:.8*e,sustain:0,release:.2*e})}static click(t=.3){Ls.isInitialized&&Ls.osc.tone(1e3,.01,{type:"square",volume:t,attack:.001,decay:.009,sustain:0,release:.001})}static sweep(t,e,i,s={}){if(!Ls.isInitialized)return;const{volume:n=.3,type:o="sine"}=s;Ls.osc.sweep(t,e,i,{type:o,volume:n})}static fromValue(t,e={}){if(!Ls.isInitialized)return;const{root:i="C4",scale:s="pentatonic",octaves:n=2,duration:o=.2,volume:r=.3,type:a="sine"}=e,h=Ls.music.mapToScale(t,i,s,n);Ls.osc.tone(h,o,{volume:r,type:a})}static impact(t=.5){if(!Ls.isInitialized)return;const e=80+200*t,i=.05+.15*t;Ls.osc.tone(e,i,{type:"sine",volume:.4*t,attack:.001,decay:i,sustain:0,release:.02});const s=Ls.noise.white(Ls.ctx,.08),n=Ls.ctx.createGain();n.gain.setValueAtTime(.25*t,Ls.now),n.gain.exponentialRampToValueAtTime(.001,Ls.now+.08),s.connect(n),n.connect(Ls.master),s.start(),s.stop(Ls.now+.1)}static explosion(t=.7){if(!Ls.isInitialized)return;const e=.3+.4*t;Ls.osc.tone(50+30*t,e,{type:"sine",volume:.4*t,attack:.001,decay:.3*e,sustain:.3,release:.7*e});const i=Ls.noise.brown(Ls.ctx,e),s=Ls.ctx.createGain(),n=Ls.fx.filter("lowpass",800+400*t,1);s.gain.setValueAtTime(.5*t,Ls.now),s.gain.exponentialRampToValueAtTime(.001,Ls.now+e),i.connect(n),n.connect(s),s.connect(Ls.master),i.start(),i.stop(Ls.now+e+.1)}static laser(t={}){if(!Ls.isInitialized)return;const{startFreq:e=1200,endFreq:i=200,duration:s=.15,volume:n=.25,type:o="sawtooth"}=t;Ls.osc.sweep(e,i,s,{type:o,volume:n})}static powerUp(t={}){if(!Ls.isInitialized)return;const{startFreq:e=300,endFreq:i=1200,duration:s=.3,volume:n=.3}=t;Ls.osc.sweep(e,i,s,{type:"square",volume:n}),Ls.osc.sweep(1.5*e,1.5*i,s,{type:"sine",volume:.5*n})}static hurt(t=.5){Ls.isInitialized&&(Ls.osc.tone(80+40*t,.1,{type:"sine",volume:.4*t,attack:.001,decay:.08,sustain:0,release:.02}),Ls.osc.tone(200+100*t,.08,{type:"sawtooth",volume:.2*t,attack:.001,decay:.06,sustain:0,release:.02}))}static coin(t={}){if(!Ls.isInitialized)return;const{baseFreq:e=987.77,volume:i=.25}=t;Ls.osc.tone(e,.08,{type:"square",volume:i,attack:.001,decay:.05,sustain:.3,release:.02}),setTimeout(()=>{Ls.isInitialized&&Ls.osc.tone(1.5*e,.12,{type:"square",volume:i,attack:.001,decay:.08,sustain:.2,release:.04})},80)}static jump(t={}){if(!Ls.isInitialized)return;const{startFreq:e=150,endFreq:i=400,duration:s=.15,volume:n=.25}=t;Ls.osc.sweep(e,i,s,{type:"square",volume:n})}static select(t={}){if(!Ls.isInitialized)return;const{frequency:e=660,volume:i=.2}=t;Ls.osc.tone(e,.08,{type:"sine",volume:i,attack:.001,decay:.05,sustain:.3,release:.03})}static error(t={}){if(!Ls.isInitialized)return;const{volume:e=.25}=t;Ls.osc.tone(400,.1,{type:"square",volume:e,attack:.001,decay:.08,sustain:0,release:.02}),setTimeout(()=>{Ls.isInitialized&&Ls.osc.tone(300,.15,{type:"square",volume:e,attack:.001,decay:.12,sustain:0,release:.03})},100)}static drone(t="C2",e={}){if(!Ls.isInitialized)return null;const{volume:i=.2,richness:s=.5}=e,n=Ls.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=Ls.ctx.createOscillator(),n=Ls.ctx.createGain();s.type="sine",s.frequency.value=t,n.gain.value=a[e]*i,s.connect(n),n.connect(Ls.master),s.start(),o.push(s),r.push(n)}),{stop:(t=.5)=>{const e=Ls.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,Ls.now+.1)})}}}static note(t,e=.5,i={}){if(!Ls.isInitialized)return;const{volume:s=.3,type:n="sine",envelope:o={}}=i,r=Ls.music.noteToFreq(t);Ls.osc.tone(r,e,{type:n,volume:s,...Ls.env.presets.pluck,...o})}static chord(t,e="major",i=.5,s={}){if(!Ls.isInitialized)return;const{volume:n=.2,type:o="sine",strum:r=0}=s,a=Ls.music.chord(t,e);a.forEach((t,e)=>{const s=r*e;Ls.osc.tone(t,i,{type:o,volume:n/a.length,attack:.01,decay:.1,sustain:.6,release:.2,startTime:Ls.now+s})})}static sequence(t,e=.2,i=0,s={}){if(!Ls.isInitialized)return;const{volume:n=.3,type:o="sine"}=s,r=e+i;t.forEach((t,i)=>{const s=Ls.now+i*r,a=Ls.music.noteToFreq(t);Ls.osc.tone(a,e,{type:o,volume:n,attack:.01,decay:.05,sustain:.5,release:.1,startTime:s})})}static win(){if(!Ls.isInitialized)return;this.sequence(["C5","E5","G5","C6"],.15,.05,{volume:.25,type:"square"})}static lose(){if(!Ls.isInitialized)return;this.sequence(["E4","D4","C4"],.25,0,{volume:.25,type:"sawtooth"})}},t.Sphere=class extends Ve{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;Ye.lines.line(t[e].x,t[e].y,t[i].x,t[i].y,this.stroke,this.lineWidth)}}for(const o of n)Ye.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=ci,t.Sprite=Xi,t.SpriteSheet=Wi,t.Square=ei,t.Star=oi,t.StateMachine=Ys,t.Stepper=class extends Fi{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=us.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 $e;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 Mi(this.labelText,{font:us.fonts.small,color:us.colors.dimText,align:"center",baseline:"middle"}),this.label.y=o,this.group.add(this.label)),this.decrementBg=new Qe({width:this.buttonSize,height:this.stepperHeight,color:us.button.default.bg,stroke:us.button.default.stroke,lineWidth:1}),this.decrementBg.x=i,this.decrementBg.y=n,this.decrementText=new Mi("−",{font:this.font,color:us.button.default.text,align:"center",baseline:"middle"}),this.decrementText.x=i,this.decrementText.y=n,this.valueBg=new Qe({width:this.valueWidth,height:this.stepperHeight,color:us.colors.darkerBg,stroke:us.colors.subtleBorder,lineWidth:1}),this.valueBg.x=0,this.valueBg.y=n,this.valueText=new Mi(this.formatValue(this._value),{font:this.font,color:us.colors.neonGreen,align:"center",baseline:"middle"}),this.valueText.x=0,this.valueText.y=n,this.incrementBg=new Qe({width:this.buttonSize,height:this.stepperHeight,color:us.button.default.bg,stroke:us.button.default.stroke,lineWidth:1}),this.incrementBg.x=s,this.incrementBg.y=n,this.incrementText=new Mi("+",{font:this.font,color:us.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=us.button.pressed.bg,this.decrementBg.stroke=us.button.pressed.stroke,this.decrementText.color=us.button.pressed.text):this._decrementHover?(this.decrementBg.color=us.button.hover.bg,this.decrementBg.stroke=us.button.hover.stroke,this.decrementText.color=us.button.hover.text):(this.decrementBg.color=us.button.default.bg,this.decrementBg.stroke=us.button.default.stroke,this.decrementText.color=us.button.default.text),this._value<=this.min&&(this.decrementBg.stroke=us.colors.subtleBorder,this.decrementText.color=us.colors.dimText),this._incrementPressed?(this.incrementBg.color=us.button.pressed.bg,this.incrementBg.stroke=us.button.pressed.stroke,this.incrementText.color=us.button.pressed.text):this._incrementHover?(this.incrementBg.color=us.button.hover.bg,this.incrementBg.stroke=us.button.hover.stroke,this.incrementText.color=us.button.hover.text):(this.incrementBg.color=us.button.default.bg,this.incrementBg.stroke=us.button.default.stroke,this.incrementText.color=us.button.default.text),this._value>=this.max&&(this.incrementBg.stroke=us.colors.subtleBorder,this.incrementText.color=us.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 Ve{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(Ye.shapes.fillCircle(0,i,e,this.headColor),Ye.shapes.strokeCircle(0,i,e,this.stroke,this.lineWidth),Ye.lines.line(0,s,0,n,this.stroke,this.lineWidth),Ye.lines.line(-r,o,r,o,this.stroke,this.lineWidth),Ye.lines.line(0,n,-a,h,this.stroke,this.lineWidth),Ye.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])=>Ye.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=Ls,t.SynthAnalyzer=Os,t.SynthEffects=Is,t.SynthEnvelope=Ds,t.SynthMusical=Fs,t.SynthNoise=Es,t.SynthOscillators=Bs,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=Gt,t.Text=Hi,t.TextShape=Mi,t.TileLayout=class extends Yi{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 ds{constructor(t,e={}){const i=e.onClick;super(t,{...e,onClick:()=>{this.toggled=!this.toggled,"function"==typeof e.onToggle&&e.onToggle(this.toggled),"function"==typeof i&&i();const t=this.state;this.refreshToggleVisual(),t&&this.setState(t)}}),this.colorActiveBg=e.colorActiveBg||us.button.active.bg,this.colorActiveStroke=e.colorActiveStroke||us.button.active.stroke,this.colorActiveText=e.colorActiveText||us.button.active.text,this.toggled=!!e.startToggled,this.refreshToggleVisual()}toggle(t){const e=this.state;this.toggled=t,this.refreshToggleVisual(),e&&this.setState(e)}refreshToggleVisual(){this.toggled?(this.bg.color=this.colorActiveBg,this.bg.stroke=this.colorActiveStroke,this.label.color=this.colorActiveText):(this.bg.color=this.colors.default.bg,this.bg.stroke=this.colors.default.stroke,this.label.color=this.colors.default.text)}setState(t){super.setState(t),this.toggled&&(this.bg.color=this.colorActiveBg,this.bg.stroke=this.colorActiveStroke,this.label.color=this.colorActiveText)}},t.Tooltip=class extends Fi{constructor(t,e={}){super(t,{...e,zIndex:9999}),this.font=e.font||us.fonts.small,this.textColor=e.textColor||us.tooltip.text,this.bgColor=e.bgColor||us.tooltip.bg,this.borderColor=e.borderColor||us.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 Qe({width:100,height:30,color:this.bgColor,stroke:this.borderColor,lineWidth:1}),this.lineShapes=[],this.group=new $e,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 Mi(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 r of this._lines){const i=t.measureText(r);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;for(let r=0;r<this.lineShapes.length;r++){const t=this.lineShapes[r],e=(t._width||0)/2,i=(t._height||s)/2;t.x=o+this.padding+e,t.y=-this.bg.height/2+this.padding+r*s+i}}draw(){this._visible&&this.group.render()}},t.Touch=Di,t.Traceable=Ue,t.Transform=qe,t.Transformable=Ze,t.Triangle=ni,t.Tween=Gi,t.Tweenetik=hs,t.UI_THEME=us,t.Updaters=gs,t.VerticalLayout=class extends Yi{calculateLayout(){return At(this.children,{spacing:this.spacing,padding:this.padding,align:this.align,centerItems:!0})}getLayoutOffset(){return{offsetX:0,offsetY:-(this._contentHeight??this.height)/2}}},t.WebGLCliffordRenderer=$s,t.WebGLDeJongRenderer=Ns,t.WebGLLineRenderer=class{constructor(t=1e4,e={}){if(this.maxSegments=t,this.width=e.width||800,this.height=e.height||600,this.blendMode=e.blendMode||"additive",this.canvas=document.createElement("canvas"),this.canvas.width=this.width,this.canvas.height=this.height,this.gl=this.canvas.getContext("webgl",{alpha:!0,premultipliedAlpha:!0,antialias:!0,preserveDrawingBuffer:!0}),!this.gl)return console.warn("WebGL not available for line rendering"),void(this.available=!1);this.available=!0,this._positions=new Float32Array(4*t),this._colors=new Float32Array(8*t),this._initGL(),this._createBuffers(),this._compileShaders(),this._setupBlending()}isAvailable(){return this.available}_initGL(){const t=this.gl;t.viewport(0,0,this.width,this.height),t.enable(t.BLEND)}_setupBlending(){const t=this.gl;"additive"===this.blendMode?t.blendFunc(t.ONE,t.ONE):t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA)}setBlendMode(t){this.blendMode=t,this.available&&this._setupBlending()}_createBuffers(){const t=this.gl;this.positionBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this._positions,t.DYNAMIC_DRAW),this.colorBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.colorBuffer),t.bufferData(t.ARRAY_BUFFER,this._colors,t.DYNAMIC_DRAW)}_compileShaders(){const t=this.gl,e=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(e,"\nprecision highp float;\n\nattribute vec2 aPosition; // Screen position (pixels)\nattribute vec4 aColor; // RGBA color (0-1 range, premultiplied)\n\nvarying vec4 vColor;\n\nuniform vec2 uResolution; // Canvas dimensions\n\nvoid main() {\n // Convert from pixel coords to clip space (-1 to 1)\n vec2 clipPos = (aPosition / uResolution) * 2.0 - 1.0;\n clipPos.y = -clipPos.y; // Flip Y (canvas Y is down, GL Y is up)\n\n gl_Position = vec4(clipPos, 0.0, 1.0);\n vColor = aColor;\n}\n"),t.compileShader(e),!t.getShaderParameter(e,t.COMPILE_STATUS))return console.error("Line vertex shader error:",t.getShaderInfoLog(e)),void(this.available=!1);const i=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(i,"\nprecision mediump float;\n\nvarying vec4 vColor;\n\nvoid main() {\n gl_FragColor = vColor;\n}\n"),t.compileShader(i),t.getShaderParameter(i,t.COMPILE_STATUS)?(this.program=t.createProgram(),t.attachShader(this.program,e),t.attachShader(this.program,i),t.linkProgram(this.program),t.getProgramParameter(this.program,t.LINK_STATUS)?(t.useProgram(this.program),this.aPosition=t.getAttribLocation(this.program,"aPosition"),this.aColor=t.getAttribLocation(this.program,"aColor"),this.uResolution=t.getUniformLocation(this.program,"uResolution"),t.uniform2f(this.uResolution,this.width,this.height),t.deleteShader(e),void t.deleteShader(i)):(console.error("Line program link error:",t.getProgramInfoLog(this.program)),void(this.available=!1))):(console.error("Line fragment shader error:",t.getShaderInfoLog(i)),void(this.available=!1))}resize(t,e){if(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.available){const i=this.gl;i.viewport(0,0,t,e),i.useProgram(this.program),i.uniform2f(this.uResolution,t,e)}}updateLines(t){if(!this.available)return 0;const e=Math.min(t.length,this.maxSegments),i=this.gl;for(let s=0;s<e;s++){const e=t[s],i=4*s,n=8*s;this._positions[i]=e.x1,this._positions[i+1]=e.y1,this._positions[i+2]=e.x2,this._positions[i+3]=e.y2;if(void 0!==e.r1){const t=void 0!==e.a1?e.a1:1,i=void 0!==e.a2?e.a2:1;this._colors[n]=e.r1/255*t,this._colors[n+1]=e.g1/255*t,this._colors[n+2]=e.b1/255*t,this._colors[n+3]=t,this._colors[n+4]=e.r2/255*i,this._colors[n+5]=e.g2/255*i,this._colors[n+6]=e.b2/255*i,this._colors[n+7]=i}else{const t=void 0!==e.a?e.a:1,i=e.r/255*t,s=e.g/255*t,o=e.b/255*t;this._colors[n]=i,this._colors[n+1]=s,this._colors[n+2]=o,this._colors[n+3]=t,this._colors[n+4]=i,this._colors[n+5]=s,this._colors[n+6]=o,this._colors[n+7]=t}}return i.bindBuffer(i.ARRAY_BUFFER,this.positionBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._positions.subarray(0,4*e)),i.bindBuffer(i.ARRAY_BUFFER,this.colorBuffer),i.bufferSubData(i.ARRAY_BUFFER,0,this._colors.subarray(0,8*e)),e}clear(t=0,e=0,i=0,s=0){if(!this.available)return;const n=this.gl;n.clearColor(t,e,i,s),n.clear(n.COLOR_BUFFER_BIT)}render(t){if(!this.available||0===t)return;const e=this.gl;e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorBuffer),e.enableVertexAttribArray(this.aColor),e.vertexAttribPointer(this.aColor,4,e.FLOAT,!1,0,0),e.drawArrays(e.LINES,0,2*t)}compositeOnto(t,e=0,i=0){this.available&&t.drawImage(this.canvas,e,i)}getCanvas(){return this.canvas}destroy(){if(!this.available)return;const t=this.gl;this.program&&t.deleteProgram(this.program),t.deleteBuffer(this.positionBuffer),t.deleteBuffer(this.colorBuffer),this._positions=null,this._colors=null}},t.WebGLParticleRenderer=ws,t.WebGLRenderer=ri,t.WrappedText=class extends Ve{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(!Ye.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=Ye.text.font(),e=Ye.text.textAlign(),i=Ye.text.textBaseline();this.font&&Ye.text.setFont(this.font),Ye.text.setTextAlign("left"),Ye.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]+" ";Ye.text.measureText(o).width>this.maxWidth&&r>0?(this.lines.push(n),this.width=Math.max(this.width,Ye.text.measureText(n).width),n=s[r]+" "):n=o}this.lines.push(n),this.width=Math.max(this.width,Ye.text.measureText(n).width),this.height=this.lines.length*this.lineHeight,Ye.text.setFont(t),Ye.text.setTextAlign(e),Ye.text.setTextBaseline(i)}setText(t){this.text=t,this.calculateDimensions()}draw(){if(super.draw(),!Ye.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&&Ye.text.setFont(this.font),Ye.text.setTextAlign(this.align),Ye.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?Ye.outlinedText(this.lines[s],i,t,this.color,this.outlineColor,this.outlineWidth,this.font):Ye.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=Ei,t.applyDraggable=function(t,e={}){const i=t.game;return t.dragging=!1,t.dragOffset={x:0,y:0},t._dragInputMoveHandler&&i.events.off("inputmove",t._dragInputMoveHandler),t._dragInputUpHandler&&i.events.off("inputup",t._dragInputUpHandler),t.interactive=!0,t._dragInputDownHandler=i=>{t.dragging=!0,t.dragOffset.x=t.x-i.x,t.dragOffset.y=t.y-i.y,e.onDragStart&&e.onDragStart()},t._dragInputMoveHandler=e=>{t.dragging&&(t.x=e.x+t.dragOffset.x,t.y=e.y+t.dragOffset.y)},t._dragInputUpHandler=i=>{t.dragging&&(t.dragging=!1,e.onDragEnd&&e.onDragEnd())},t.on("inputdown",t._dragInputDownHandler),i.events.on("inputmove",t._dragInputMoveHandler),i.events.on("inputup",t._dragInputUpHandler),()=>{t.off("inputdown",t._dragInputDownHandler),i.events.off("inputmove",t._dragInputMoveHandler),i.events.off("inputup",t._dragInputUpHandler),delete t._dragInputDownHandler,delete t._dragInputMoveHandler,delete t._dragInputUpHandler,delete t.dragging,delete t.dragOffset}},t.applyGravitationalLensing=function(t,e,i,s,n,o=5){const r=Math.sqrt(t*t+e*e);if(r<=o||r>=i)return{x:t,y:e,displacement:0};const a=oe(r,i,s,n,o),h=(r+a)/r;return{x:t*h,y:e*h,displacement:a}},t.applyLayout=Pt,t.applyParticleHeatTransfer=function(t,e={}){const{maxDistance:i=50,rate:s=.01,falloff:n=1,temperatureKey:o="temperature",filter:r=null,useSizeAsRadius:a=!0}=e,h=t.length,l=i*i;for(let c=0;c<h;c++){const e=t[c];if(!r||r(e)){void 0===e.custom[o]&&(e.custom[o]=.5);for(let a=c+1;a<h;a++){const h=t[a];if(r&&!r(h))continue;void 0===h.custom[o]&&(h.custom[o]=.5);const c=e.x-h.x,u=e.y-h.y,d=c*c+u*u;if(d>=l||d<1e-4)continue;const f=Math.sqrt(d),p=le(e.custom[o],h.custom[o],f,i,s,n);e.custom[o]+=p,h.custom[o]-=p,e.custom[o]=Math.max(0,Math.min(1,e.custom[o])),h.custom[o]=Math.max(0,Math.min(1,h.custom[o]))}}}},t.bezierV1=as,t.blendForces=be,t.bounceV1=Ni,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=ve,t.computeFluidForces=_e,t.computeGasForces=xe,t.computePressures=ye,t.computeThermalBuoyancy=function(t,e={}){var i;const s=ge(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=ne,t.flammEmbeddingHeight=function(t,e,i,s,n){const o=ne(Math.max(t,e+.01),e,i),r=ne(s,e,i);return(r-o)*n/r},t.floatV1=qi,t.followPath=Zi,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=As,t.generatePenroseTilingPixels=Yt,t.get2DAttractors=function(){return Object.fromEntries(Object.entries(se).filter(([,t])=>t.dimension===ie.TWO_D))},t.get3DAttractors=function(){return Object.fromEntries(Object.entries(se).filter(([,t])=>t.dimension===ie.THREE_D))},t.getAttractor=function(t){return se[t]||null},t.getAttractorNames=function(){return Object.keys(se)},t.getDefaultFluidConfig=function(){return ge()},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=oe,t.gridLayout=Dt,t.groupVelocity=function(t,e,i=.01){return e/t},t.heatTransfer=function(t,e,i,s,n){return i>=s?0:(e-t)*n},t.heatTransferFalloff=le,t.hopV1=ts,t.horizontalLayout=Rt,t.integrateEuler=function(t,e,i,s={}){const n=ge(s),o=new Array(t.length);for(let r=0;r<t.length;r++){const s=t[r],a=e[r],h=we(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=Vi,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=$i,t.parabolicV1=ji,t.patrolV1=Ki,t.pendulumV1=Ji,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=Qi,t.schwarzschildPrecessionRate=function(t,e,i=1){return t<=e?0:i*(e/t)},t.shakeV1=es,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=As({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=is,t.springV1=ss,t.swingV1=ns,t.thermalBuoyancy=function(t,e,i){return(t-e)*i},t.thermalGravity=function(t,e,i){return i*(t/e)},t.tileLayout=zt,t.updateTrail=function(t,e,i=80){return t.unshift(e),t.length>i&&t.pop(),t},t.verticalLayout=At,t.waypointV1=os,t.zoneTemperature=he,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});