@cimplify/sdk 0.108.0 → 0.110.2

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 (608) hide show
  1. package/LICENSE +21 -0
  2. package/dist/advanced.d.mts +4 -3
  3. package/dist/advanced.d.ts +4 -3
  4. package/dist/advanced.js +24 -24
  5. package/dist/advanced.mjs +5 -5
  6. package/dist/animation-4EXBXRVX.js +27 -0
  7. package/dist/animation-6DICNWUP.mjs +6 -0
  8. package/dist/audio-DhvyjqdA.d.mts +249 -0
  9. package/dist/audio-m0w8cnxq.d.ts +249 -0
  10. package/dist/avatars.d.mts +110 -0
  11. package/dist/avatars.d.ts +110 -0
  12. package/dist/avatars.js +82 -0
  13. package/dist/avatars.mjs +5 -0
  14. package/dist/backend-gUCzs5Kg.d.mts +3866 -0
  15. package/dist/backend-gUCzs5Kg.d.ts +3866 -0
  16. package/dist/{catalogue-B4eLL8Mi.d.ts → catalogue-CPTMyBUz.d.mts} +109 -221
  17. package/dist/catalogue-DzrTXP3v.d.mts +541 -0
  18. package/dist/catalogue-DzrTXP3v.d.ts +541 -0
  19. package/dist/{catalogue-OT89_Ifs.d.mts → catalogue-OTuS5zp-.d.ts} +109 -221
  20. package/dist/chunk-22BD3RHN.mjs +1809 -0
  21. package/dist/chunk-25T4JHEA.mjs +21 -0
  22. package/dist/chunk-2AQ237Y4.js +508 -0
  23. package/dist/chunk-2IC4H6OV.mjs +48 -0
  24. package/dist/chunk-2LHLG4OB.mjs +71 -0
  25. package/dist/chunk-2O2CG465.js +1709 -0
  26. package/dist/chunk-2Q4DTHXK.js +316 -0
  27. package/dist/chunk-2QTQ6BUH.mjs +46 -0
  28. package/dist/chunk-2UN4SFLR.mjs +100 -0
  29. package/dist/chunk-2V75I7K3.js +454 -0
  30. package/dist/chunk-2V7IL4HC.js +10 -0
  31. package/dist/chunk-34XBXUMW.js +296 -0
  32. package/dist/chunk-3C4C654I.js +71 -0
  33. package/dist/chunk-3DAD2LDF.mjs +72 -0
  34. package/dist/chunk-3GXH2NFD.mjs +4 -0
  35. package/dist/chunk-3O47ZFW3.js +961 -0
  36. package/dist/chunk-3OY3VYNF.mjs +11 -0
  37. package/dist/chunk-3S6WPBZL.js +2936 -0
  38. package/dist/chunk-3TUOUP5T.js +399 -0
  39. package/dist/chunk-3VEH23I5.mjs +1380 -0
  40. package/dist/chunk-3ZYSAW2T.mjs +263 -0
  41. package/dist/chunk-4ANVF274.js +103 -0
  42. package/dist/chunk-4C7I3ELN.js +388 -0
  43. package/dist/chunk-4DYKAYFO.mjs +8 -0
  44. package/dist/chunk-4ZDR72SG.js +329 -0
  45. package/dist/chunk-52YS45RR.js +1066 -0
  46. package/dist/chunk-5325XSCH.js +107 -0
  47. package/dist/chunk-5AD5X6AV.js +13 -0
  48. package/dist/chunk-5BYDGGWO.mjs +197 -0
  49. package/dist/chunk-5C3C7VDM.mjs +55 -0
  50. package/dist/chunk-5HFMY3D7.js +660 -0
  51. package/dist/chunk-5LH2QN3T.js +1862 -0
  52. package/dist/chunk-5PJEXSOW.js +44 -0
  53. package/dist/chunk-5SXDH3Y7.js +90 -0
  54. package/dist/chunk-5YFBGGCK.mjs +502 -0
  55. package/dist/chunk-5YWN6H5Q.mjs +133 -0
  56. package/dist/chunk-66QP3SMN.js +402 -0
  57. package/dist/chunk-6DAEZKIG.mjs +385 -0
  58. package/dist/chunk-6DATW7TB.mjs +420 -0
  59. package/dist/{chunk-JRGK3NXR.mjs → chunk-6ETDAU62.mjs} +72 -212
  60. package/dist/chunk-6H254EVP.mjs +178 -0
  61. package/dist/chunk-6PFNJPBJ.mjs +820 -0
  62. package/dist/chunk-6PJWXIFX.mjs +357 -0
  63. package/dist/chunk-6SWKWCMS.js +80 -0
  64. package/dist/chunk-6VVXXX7S.js +808 -0
  65. package/dist/chunk-6WUBSMTX.js +1403 -0
  66. package/dist/chunk-73SGZLAQ.mjs +35 -0
  67. package/dist/chunk-76L2V6KD.mjs +4 -0
  68. package/dist/chunk-7AAIAVAA.js +1531 -0
  69. package/dist/chunk-7ARSJPV3.mjs +93 -0
  70. package/dist/chunk-7BHW5GTC.mjs +1234 -0
  71. package/dist/chunk-7DQSDKDU.js +6 -0
  72. package/dist/chunk-7IQQQENP.mjs +401 -0
  73. package/dist/chunk-7KFTYENS.js +11357 -0
  74. package/dist/chunk-7SM6XSPZ.js +3171 -0
  75. package/dist/chunk-7SXOHAIR.mjs +28 -0
  76. package/dist/chunk-A2MAX6S4.js +90 -0
  77. package/dist/chunk-A33OORT7.mjs +1530 -0
  78. package/dist/{chunk-U6ACF76H.mjs → chunk-A36JRXXH.mjs} +1075 -1845
  79. package/dist/chunk-A7BU3BK4.js +52 -0
  80. package/dist/chunk-A7MQSN2V.mjs +77 -0
  81. package/dist/chunk-A7V4L2IT.mjs +416 -0
  82. package/dist/chunk-AABEK6XU.js +226 -0
  83. package/dist/chunk-AGV33FWC.mjs +5005 -0
  84. package/dist/chunk-AHNR3BXI.js +108 -0
  85. package/dist/chunk-AQ5RLBU2.mjs +286 -0
  86. package/dist/chunk-AQOE6WCG.js +1270 -0
  87. package/dist/chunk-ATAWRACV.mjs +62 -0
  88. package/dist/chunk-ATCURNUV.js +14 -0
  89. package/dist/chunk-AWPV33OO.js +6 -0
  90. package/dist/chunk-AYJPHKYV.js +337 -0
  91. package/dist/chunk-AZ5BGWHB.js +162 -0
  92. package/dist/chunk-AZAXD44P.js +1373 -0
  93. package/dist/chunk-BBGKQIJJ.mjs +406 -0
  94. package/dist/chunk-BP4JLSUA.js +1453 -0
  95. package/dist/{chunk-SUCE7FWA.mjs → chunk-BTUSVHIE.mjs} +539 -978
  96. package/dist/chunk-BU6OK542.mjs +818 -0
  97. package/dist/chunk-CVSRWM6W.js +418 -0
  98. package/dist/chunk-CYBMFMJD.mjs +247 -0
  99. package/dist/chunk-DDJLDOUX.mjs +217 -0
  100. package/dist/{chunk-V32BCG7M.js → chunk-DFZWHNRG.js} +75 -215
  101. package/dist/chunk-DJ2C7AVG.js +644 -0
  102. package/dist/chunk-DS2VU4WW.mjs +102 -0
  103. package/dist/chunk-DSAG7T5P.js +7290 -0
  104. package/dist/chunk-E2QPPH7I.js +327 -0
  105. package/dist/chunk-E65WCTIG.mjs +1187 -0
  106. package/dist/{chunk-33VCYWVL.mjs → chunk-E6QQKDNE.mjs} +30 -42
  107. package/dist/chunk-ECDK6QBF.mjs +981 -0
  108. package/dist/chunk-EIB4OWVQ.mjs +620 -0
  109. package/dist/chunk-EQUZYCGO.js +250 -0
  110. package/dist/chunk-F3UJ6ZRM.mjs +313 -0
  111. package/dist/chunk-F63N2ZTQ.js +7023 -0
  112. package/dist/chunk-F6XRYEM3.mjs +26 -0
  113. package/dist/chunk-FE6VCE4K.js +5030 -0
  114. package/dist/chunk-FLWD6GRR.js +1372 -0
  115. package/dist/chunk-FQBFWJBS.mjs +110 -0
  116. package/dist/chunk-FXVJ2HFU.js +26 -0
  117. package/dist/chunk-FZMQMQBW.js +312 -0
  118. package/dist/chunk-G3EEC44R.js +53 -0
  119. package/dist/{chunk-KG3WT4PR.mjs → chunk-GCKWKLZF.mjs} +73 -104
  120. package/dist/chunk-GCX7TY4D.mjs +6826 -0
  121. package/dist/chunk-GDB6TCSD.js +450 -0
  122. package/dist/chunk-GDCV4IWO.mjs +21 -0
  123. package/dist/chunk-GDZT5LZ5.js +170 -0
  124. package/dist/chunk-GHPUYD4I.mjs +213 -0
  125. package/dist/chunk-GHS6MIL6.mjs +1432 -0
  126. package/dist/chunk-GPS2THCL.mjs +11 -0
  127. package/dist/{chunk-EV2EVOYS.js → chunk-GTJWQAGU.js} +31 -42
  128. package/dist/chunk-GVTI6UJQ.mjs +130 -0
  129. package/dist/chunk-GXKI64OT.mjs +1138 -0
  130. package/dist/chunk-GYDYF2WX.js +275 -0
  131. package/dist/chunk-GYLP6UG4.mjs +705 -0
  132. package/dist/chunk-H3OQKK6X.js +1158 -0
  133. package/dist/chunk-H5DFSCJ6.js +40 -0
  134. package/dist/chunk-HAGEIC2L.mjs +186 -0
  135. package/dist/chunk-HAJ4JRFO.js +293 -0
  136. package/dist/chunk-HDR72GB6.js +188 -0
  137. package/dist/chunk-HF5HPS4T.mjs +40 -0
  138. package/dist/chunk-HK6LOFDS.js +218 -0
  139. package/dist/chunk-HMWYTXCY.mjs +143 -0
  140. package/dist/chunk-HPCSRCMA.js +89 -0
  141. package/dist/chunk-HSEO6TPU.js +247 -0
  142. package/dist/chunk-I5FOHCLH.js +132 -0
  143. package/dist/chunk-IDLW4NWA.mjs +85 -0
  144. package/dist/chunk-IIDZ5WUX.js +61 -0
  145. package/dist/chunk-IR74FJHU.js +2332 -0
  146. package/dist/chunk-IRVFYAKP.mjs +100 -0
  147. package/dist/{chunk-XBL3TMPC.mjs → chunk-IZDWAL53.mjs} +1795 -3287
  148. package/dist/chunk-J2KZXIU3.js +51 -0
  149. package/dist/chunk-J2U6PJSO.js +91 -0
  150. package/dist/chunk-J5AJNY2N.js +283 -0
  151. package/dist/chunk-J6KQZ4FO.mjs +821 -0
  152. package/dist/{chunk-OWW5GUSB.js → chunk-JGBCIKJV.js} +7 -6
  153. package/dist/chunk-JKGTBMU7.mjs +25 -0
  154. package/dist/chunk-JR3TNEQC.js +422 -0
  155. package/dist/chunk-JURRXY2J.mjs +29 -0
  156. package/dist/chunk-K3HW5I2A.mjs +317 -0
  157. package/dist/chunk-K46SMZ66.mjs +103 -0
  158. package/dist/chunk-K4UDGE3Z.mjs +6 -0
  159. package/dist/chunk-KDQOR4QQ.mjs +350 -0
  160. package/dist/chunk-KDTVOLHI.mjs +288 -0
  161. package/dist/chunk-KGHJH5KJ.mjs +35 -0
  162. package/dist/chunk-KIZOA5LX.mjs +140 -0
  163. package/dist/chunk-KK6HYVBI.mjs +242 -0
  164. package/dist/chunk-KMKWGXMK.js +856 -0
  165. package/dist/chunk-KPA6K5IB.js +80 -0
  166. package/dist/chunk-KU7O4IXU.mjs +260 -0
  167. package/dist/chunk-KVFNRJOR.mjs +11142 -0
  168. package/dist/chunk-KZJRSXHK.js +2432 -0
  169. package/dist/chunk-LHWPRUJL.js +79 -0
  170. package/dist/chunk-LIV3KXJG.mjs +369 -0
  171. package/dist/chunk-LKV4LACG.js +21 -0
  172. package/dist/chunk-LUY45X3U.mjs +263 -0
  173. package/dist/chunk-LYEZZEEF.mjs +17 -0
  174. package/dist/chunk-M5EXQZYY.mjs +1519 -0
  175. package/dist/chunk-ME6HGG4I.mjs +1338 -0
  176. package/dist/chunk-MEXP6DA6.js +31 -0
  177. package/dist/chunk-MG52AW3H.js +902 -0
  178. package/dist/chunk-MIPO6F72.js +334 -0
  179. package/dist/{chunk-5QW7CQBA.js → chunk-MKIJQL5Q.js} +211 -321
  180. package/dist/chunk-MN3YETVN.mjs +17 -0
  181. package/dist/chunk-MOBSBXVE.mjs +2391 -0
  182. package/dist/chunk-MOMOZEUM.mjs +88 -0
  183. package/dist/chunk-MRFUNRAP.js +62 -0
  184. package/dist/chunk-MTIHEW2M.js +433 -0
  185. package/dist/chunk-N4RGGDEL.mjs +73 -0
  186. package/dist/chunk-NH654HAT.js +10 -0
  187. package/dist/chunk-NHJUGZUR.mjs +253 -0
  188. package/dist/chunk-NMQT4HG3.mjs +757 -0
  189. package/dist/chunk-NPSYB6DC.mjs +906 -0
  190. package/dist/chunk-NW2GPMSO.js +857 -0
  191. package/dist/chunk-NXKQOQ6L.js +76 -0
  192. package/dist/chunk-NXLAZIJZ.js +309 -0
  193. package/dist/chunk-NYWNA5CF.js +148 -0
  194. package/dist/chunk-NZTKLY2W.js +1442 -0
  195. package/dist/chunk-O2ICABUD.js +36 -0
  196. package/dist/chunk-OIVVQQ22.js +862 -0
  197. package/dist/chunk-OKC2B4O3.mjs +312 -0
  198. package/dist/chunk-OLWFPDBK.js +2220 -0
  199. package/dist/chunk-OMTVH334.js +3779 -0
  200. package/dist/chunk-OQRVEM56.mjs +362 -0
  201. package/dist/chunk-OXMIBOD4.js +337 -0
  202. package/dist/chunk-PBL6YL5L.mjs +288 -0
  203. package/dist/chunk-PDOELNNQ.js +97 -0
  204. package/dist/chunk-PDQJY2GZ.js +136 -0
  205. package/dist/chunk-PKOZXD2Q.js +1274 -0
  206. package/dist/chunk-PPF2BYFL.mjs +2191 -0
  207. package/dist/chunk-PQTQKNKD.js +539 -0
  208. package/dist/chunk-PRSR4FAV.mjs +81 -0
  209. package/dist/chunk-PTRNO5UD.js +95 -0
  210. package/dist/chunk-Q2Y3VMKH.js +2000 -0
  211. package/dist/chunk-QCZOE65N.js +96 -0
  212. package/dist/chunk-QDYFLATW.mjs +52 -0
  213. package/dist/chunk-QQABGCMM.js +22 -0
  214. package/dist/chunk-QS6TRHMR.js +345 -0
  215. package/dist/chunk-R56P64LB.mjs +208 -0
  216. package/dist/chunk-RCQ2MPBV.js +428 -0
  217. package/dist/chunk-RFVRPYR2.mjs +856 -0
  218. package/dist/chunk-RKBLPGPV.js +11521 -0
  219. package/dist/chunk-RM2V4IND.mjs +327 -0
  220. package/dist/chunk-RQXN5A34.mjs +613 -0
  221. package/dist/chunk-RUVGVNOF.mjs +2687 -0
  222. package/dist/chunk-SAFJIGYB.mjs +165 -0
  223. package/dist/chunk-SKQFLBDD.js +263 -0
  224. package/dist/chunk-SMK6JU2F.mjs +2092 -0
  225. package/dist/{chunk-UVRPC2P7.js → chunk-SNNEOS5Z.js} +1984 -3476
  226. package/dist/chunk-SPCRQ6NO.mjs +1246 -0
  227. package/dist/chunk-SWX4SALA.mjs +19 -0
  228. package/dist/{chunk-JVODCGFP.mjs → chunk-SYEO2WV4.mjs} +128 -238
  229. package/dist/chunk-T2QQMX2N.js +10 -0
  230. package/dist/chunk-T3AFF3L7.mjs +57 -0
  231. package/dist/chunk-T6Z2EXYL.js +712 -0
  232. package/dist/chunk-T7LOXGYX.js +118 -0
  233. package/dist/chunk-TJCAE7RC.mjs +1315 -0
  234. package/dist/chunk-TJI3K6RP.js +137 -0
  235. package/dist/chunk-TL2SVO4P.mjs +55 -0
  236. package/dist/chunk-TM63CYGN.mjs +399 -0
  237. package/dist/chunk-TU5RYTYU.mjs +13 -0
  238. package/dist/chunk-TVJZ4GPS.js +1553 -0
  239. package/dist/chunk-TWM6DLYF.js +371 -0
  240. package/dist/chunk-U63OC4TQ.js +30 -0
  241. package/dist/{chunk-L5GKVQVJ.js → chunk-U6BVSJZ6.js} +25 -57
  242. package/dist/chunk-U6UVWEAK.mjs +792 -0
  243. package/dist/chunk-UCEPNO6N.mjs +11048 -0
  244. package/dist/{chunk-ANT574FD.js → chunk-UCR5HRYM.js} +74 -105
  245. package/dist/chunk-UG5BTOTF.mjs +334 -0
  246. package/dist/chunk-UGH37BQW.mjs +157 -0
  247. package/dist/chunk-V7ZRH3PY.mjs +271 -0
  248. package/dist/chunk-VBGHBL3E.mjs +1394 -0
  249. package/dist/chunk-VRBDAS5I.js +920 -0
  250. package/dist/chunk-VVE3Y76O.js +230 -0
  251. package/dist/chunk-W65JIRI4.mjs +1182 -0
  252. package/dist/chunk-WHYKAT7G.js +62 -0
  253. package/dist/{chunk-YOIVZ6OA.mjs → chunk-WIZRUIZB.mjs} +25 -57
  254. package/dist/chunk-WKWTDZS7.js +385 -0
  255. package/dist/chunk-WLMINRC4.mjs +78 -0
  256. package/dist/chunk-WOF3AD3J.js +22 -0
  257. package/dist/chunk-WWKMOA76.js +1262 -0
  258. package/dist/chunk-X5A5FOWW.js +615 -0
  259. package/dist/chunk-X6CN6KQF.mjs +192 -0
  260. package/dist/chunk-XD2PMH46.mjs +517 -0
  261. package/dist/chunk-XJA2NGTI.mjs +88 -0
  262. package/dist/chunk-XJIHN3BY.mjs +8 -0
  263. package/dist/chunk-XK6UDWJS.js +203 -0
  264. package/dist/chunk-XPG3N5CF.mjs +415 -0
  265. package/dist/chunk-XVZ2NKSU.mjs +74 -0
  266. package/dist/chunk-XYP45OLE.js +117 -0
  267. package/dist/chunk-XZSDGZX6.mjs +301 -0
  268. package/dist/chunk-Y2EMGN4T.mjs +120 -0
  269. package/dist/chunk-Y3XWP5XW.mjs +298 -0
  270. package/dist/chunk-Y4K22JL6.js +228 -0
  271. package/dist/chunk-Y65LXQGA.mjs +3164 -0
  272. package/dist/chunk-Y66WVMO5.mjs +87 -0
  273. package/dist/chunk-Y7JWLB25.mjs +7280 -0
  274. package/dist/chunk-YCDXAJKU.js +175 -0
  275. package/dist/chunk-YRDQCCIS.js +152 -0
  276. package/dist/chunk-YV52DGSA.js +111 -0
  277. package/dist/chunk-YXGZQPUD.js +94 -0
  278. package/dist/chunk-Z3A3AFVU.mjs +102 -0
  279. package/dist/chunk-ZCY6YKKP.mjs +475 -0
  280. package/dist/chunk-ZEQHXVU5.js +215 -0
  281. package/dist/chunk-ZF7JCXCI.js +284 -0
  282. package/dist/chunk-ZJBRUH6V.js +29 -0
  283. package/dist/chunk-ZMIL4ZOA.js +365 -0
  284. package/dist/chunk-ZR5ULMN2.mjs +337 -0
  285. package/dist/chunk-ZXREOYOW.js +87 -0
  286. package/dist/{client-BSP9U1O1.d.mts → client-CX_WR0-J.d.mts} +2 -2
  287. package/dist/client-Dytx_ZTC.d.ts +230 -0
  288. package/dist/{client-B878xeAP.d.ts → client-dqOhP9Nc.d.ts} +2 -2
  289. package/dist/client-hTKbCuhG.d.mts +230 -0
  290. package/dist/clock-B-UAjkKa.d.mts +5 -0
  291. package/dist/clock-B-UAjkKa.d.ts +5 -0
  292. package/dist/config-BlXQluJR.d.mts +36 -0
  293. package/dist/config-BlXQluJR.d.ts +36 -0
  294. package/dist/courier-Cnn-edJ4.d.ts +95 -0
  295. package/dist/courier-FmGfkvIN.d.mts +95 -0
  296. package/dist/crowd-DdHFbqKK.d.ts +186 -0
  297. package/dist/crowd-hOVSAmA3.d.mts +186 -0
  298. package/dist/danfo-BEBapFlX.d.mts +146 -0
  299. package/dist/danfo-UQ_PTIIx.d.ts +146 -0
  300. package/dist/{elements-Bty6Qs_N.d.mts → elements-DdsRig-2.d.mts} +1548 -257
  301. package/dist/{elements-Bty6Qs_N.d.ts → elements-DdsRig-2.d.ts} +1548 -257
  302. package/dist/engines/godot.d.mts +56 -0
  303. package/dist/engines/godot.d.ts +56 -0
  304. package/dist/engines/godot.js +28 -0
  305. package/dist/engines/godot.mjs +3 -0
  306. package/dist/engines/wasm.d.mts +11 -0
  307. package/dist/engines/wasm.d.ts +11 -0
  308. package/dist/engines/wasm.js +178 -0
  309. package/dist/engines/wasm.mjs +176 -0
  310. package/dist/fallback-CrG_lTFk.d.mts +270 -0
  311. package/dist/fallback-CrG_lTFk.d.ts +270 -0
  312. package/dist/fallback-KDB4Y2CE.mjs +6 -0
  313. package/dist/fallback-Y26TQENE.js +19 -0
  314. package/dist/features-CZB4rmcD.d.mts +118 -0
  315. package/dist/features-CZB4rmcD.d.ts +118 -0
  316. package/dist/fit-BWiE7rgA.d.mts +44 -0
  317. package/dist/fit-DK0oT7zO.d.ts +44 -0
  318. package/dist/five-a-side-Bv1AOUy3.d.mts +115 -0
  319. package/dist/five-a-side-EC51SJY1.d.ts +115 -0
  320. package/dist/fluid-ARr0qUIL.d.ts +939 -0
  321. package/dist/fluid-DLlEj2cs.d.mts +939 -0
  322. package/dist/game/conformance.d.mts +84 -0
  323. package/dist/game/conformance.d.ts +84 -0
  324. package/dist/game/conformance.js +1025 -0
  325. package/dist/game/conformance.mjs +994 -0
  326. package/dist/game/heap.d.mts +40 -0
  327. package/dist/game/heap.d.ts +40 -0
  328. package/dist/game/heap.js +48 -0
  329. package/dist/game/heap.mjs +7 -0
  330. package/dist/game/kit/canvas.d.mts +240 -0
  331. package/dist/game/kit/canvas.d.ts +240 -0
  332. package/dist/game/kit/canvas.js +3566 -0
  333. package/dist/game/kit/canvas.mjs +1039 -0
  334. package/dist/game/kit/courier.d.mts +17 -0
  335. package/dist/game/kit/courier.d.ts +17 -0
  336. package/dist/game/kit/courier.js +66 -0
  337. package/dist/game/kit/courier.mjs +49 -0
  338. package/dist/game/kit/danfo.d.mts +11 -0
  339. package/dist/game/kit/danfo.d.ts +11 -0
  340. package/dist/game/kit/danfo.js +109 -0
  341. package/dist/game/kit/danfo.mjs +44 -0
  342. package/dist/game/kit/engine.d.mts +29 -0
  343. package/dist/game/kit/engine.d.ts +29 -0
  344. package/dist/game/kit/engine.js +183 -0
  345. package/dist/game/kit/engine.mjs +30 -0
  346. package/dist/game/kit/five-a-side.d.mts +11 -0
  347. package/dist/game/kit/five-a-side.d.ts +11 -0
  348. package/dist/game/kit/five-a-side.js +86 -0
  349. package/dist/game/kit/five-a-side.mjs +41 -0
  350. package/dist/game/kit/frontier.d.mts +344 -0
  351. package/dist/game/kit/frontier.d.ts +344 -0
  352. package/dist/game/kit/frontier.js +435 -0
  353. package/dist/game/kit/frontier.mjs +14 -0
  354. package/dist/game/kit/genesis.d.mts +752 -0
  355. package/dist/game/kit/genesis.d.ts +752 -0
  356. package/dist/game/kit/genesis.js +380 -0
  357. package/dist/game/kit/genesis.mjs +15 -0
  358. package/dist/game/kit/ludo.d.mts +15 -0
  359. package/dist/game/kit/ludo.d.ts +15 -0
  360. package/dist/game/kit/ludo.js +87 -0
  361. package/dist/game/kit/ludo.mjs +42 -0
  362. package/dist/game/kit/runner.d.mts +12 -0
  363. package/dist/game/kit/runner.d.ts +12 -0
  364. package/dist/game/kit/runner.js +83 -0
  365. package/dist/game/kit/runner.mjs +46 -0
  366. package/dist/game/kit/shootout.d.mts +13 -0
  367. package/dist/game/kit/shootout.d.ts +13 -0
  368. package/dist/game/kit/shootout.js +122 -0
  369. package/dist/game/kit/shootout.mjs +57 -0
  370. package/dist/game/kit/slots.d.mts +392 -0
  371. package/dist/game/kit/slots.d.ts +392 -0
  372. package/dist/game/kit/slots.js +215 -0
  373. package/dist/game/kit/slots.mjs +6 -0
  374. package/dist/game/kit/tycoon.d.mts +16 -0
  375. package/dist/game/kit/tycoon.d.ts +16 -0
  376. package/dist/game/kit/tycoon.js +145 -0
  377. package/dist/game/kit/tycoon.mjs +44 -0
  378. package/dist/game/kit/word.d.mts +11 -0
  379. package/dist/game/kit/word.d.ts +11 -0
  380. package/dist/game/kit/word.js +78 -0
  381. package/dist/game/kit/word.mjs +41 -0
  382. package/dist/game/kit/worlds.d.mts +18 -0
  383. package/dist/game/kit/worlds.d.ts +18 -0
  384. package/dist/game/kit/worlds.js +74 -0
  385. package/dist/game/kit/worlds.mjs +49 -0
  386. package/dist/game/kit.d.mts +53 -0
  387. package/dist/game/kit.d.ts +53 -0
  388. package/dist/game/kit.js +2610 -0
  389. package/dist/game/kit.mjs +101 -0
  390. package/dist/game/prepared.d.mts +14 -0
  391. package/dist/game/prepared.d.ts +14 -0
  392. package/dist/game/prepared.js +81 -0
  393. package/dist/game/prepared.mjs +32 -0
  394. package/dist/game-Bx8onkhX.d.mts +1451 -0
  395. package/dist/game-fgQy2YIm.d.ts +1451 -0
  396. package/dist/game-theme-CBTw1b_d.d.mts +35 -0
  397. package/dist/game-theme-Dg-ict5A.d.ts +35 -0
  398. package/dist/game.d.mts +3546 -0
  399. package/dist/game.d.ts +3546 -0
  400. package/dist/game.js +4455 -0
  401. package/dist/game.mjs +50 -0
  402. package/dist/graphics-C6YjWYvP.d.ts +5 -0
  403. package/dist/graphics-Dk2yQnYN.d.mts +5 -0
  404. package/dist/guest-DrsA00XD.d.mts +732 -0
  405. package/dist/guest-wIdfoT05.d.ts +732 -0
  406. package/dist/hit-stop-BKkVwTq7.d.mts +43 -0
  407. package/dist/hit-stop-D-8pPYnM.d.ts +43 -0
  408. package/dist/hot-Crn9XpHJ.d.ts +29 -0
  409. package/dist/hot-DH3nOhQD.d.mts +29 -0
  410. package/dist/{index-CQStGb3B.d.mts → index-6gkHMGAq.d.mts} +2 -2
  411. package/dist/index-B8ybCKJI.d.ts +41 -0
  412. package/dist/{index-DJwXmoaP.d.ts → index-B98Xac8e.d.ts} +2 -2
  413. package/dist/{index-B7oA_1XI.d.ts → index-B_ByTtIT.d.ts} +2 -2
  414. package/dist/index-DHjNHb1c.d.mts +41 -0
  415. package/dist/{index-DhUSTAhT.d.mts → index-DbAN_VQE.d.mts} +2 -2
  416. package/dist/index.d.mts +134 -24
  417. package/dist/index.d.ts +134 -24
  418. package/dist/index.js +407 -248
  419. package/dist/index.mjs +184 -58
  420. package/dist/interactives-authoring.d.mts +231 -0
  421. package/dist/interactives-authoring.d.ts +231 -0
  422. package/dist/interactives-authoring.js +1743 -0
  423. package/dist/interactives-authoring.mjs +1704 -0
  424. package/dist/interactives-canvas.global.js +148 -0
  425. package/dist/interactives-guest.d.mts +20 -0
  426. package/dist/interactives-guest.d.ts +20 -0
  427. package/dist/interactives-guest.js +63 -0
  428. package/dist/interactives-guest.json +1 -0
  429. package/dist/interactives-guest.mjs +61 -0
  430. package/dist/interactives-jsc.global.js +9357 -0
  431. package/dist/interactives-meters.d.mts +93 -0
  432. package/dist/interactives-meters.d.ts +93 -0
  433. package/dist/interactives-meters.js +252 -0
  434. package/dist/interactives-meters.mjs +68 -0
  435. package/dist/interactives-production.d.mts +430 -0
  436. package/dist/interactives-production.d.ts +430 -0
  437. package/dist/interactives-production.js +1231 -0
  438. package/dist/interactives-production.mjs +1170 -0
  439. package/dist/interactives-record.d.mts +112 -0
  440. package/dist/interactives-record.d.ts +112 -0
  441. package/dist/interactives-record.js +302 -0
  442. package/dist/interactives-record.mjs +295 -0
  443. package/dist/interactives-runtime.d.mts +61 -0
  444. package/dist/interactives-runtime.d.ts +61 -0
  445. package/dist/interactives-runtime.js +442 -0
  446. package/dist/interactives-runtime.mjs +25 -0
  447. package/dist/interactives-studio-kernel.global.js +1 -0
  448. package/dist/interactives-studio.d.mts +806 -0
  449. package/dist/interactives-studio.d.ts +806 -0
  450. package/dist/interactives-studio.js +5741 -0
  451. package/dist/interactives-studio.mjs +5651 -0
  452. package/dist/interactives-tick.d.mts +90 -0
  453. package/dist/interactives-tick.d.ts +90 -0
  454. package/dist/interactives-tick.js +203 -0
  455. package/dist/interactives-tick.mjs +6 -0
  456. package/dist/interactives-web.d.mts +762 -0
  457. package/dist/interactives-web.d.ts +762 -0
  458. package/dist/interactives-web.js +5000 -0
  459. package/dist/interactives-web.mjs +4628 -0
  460. package/dist/interactives.d.mts +2430 -0
  461. package/dist/interactives.d.ts +2430 -0
  462. package/dist/interactives.js +5723 -0
  463. package/dist/interactives.mjs +4333 -0
  464. package/dist/juice-CoHxlpKA.d.ts +42 -0
  465. package/dist/juice-DQztFS43.d.mts +42 -0
  466. package/dist/launch-T2f4_Di4.d.mts +151 -0
  467. package/dist/launch-d6oreMzR.d.ts +151 -0
  468. package/dist/library-DXYaMFhi.d.mts +69 -0
  469. package/dist/library-DXYaMFhi.d.ts +69 -0
  470. package/dist/link-BUTqGmyi.d.mts +38 -0
  471. package/dist/link-BUTqGmyi.d.ts +38 -0
  472. package/dist/lint.js +104 -204
  473. package/dist/lint.mjs +103 -203
  474. package/dist/local-D8_I6UeL.d.mts +6967 -0
  475. package/dist/local-VZkqsCzR.d.ts +6967 -0
  476. package/dist/lockstep-BLf6dglI.d.mts +321 -0
  477. package/dist/lockstep-D50Ia0JW.d.ts +321 -0
  478. package/dist/ludo-B8ClkDqr.d.ts +205 -0
  479. package/dist/ludo-BOuohQ-M.d.mts +205 -0
  480. package/dist/mock/cli.mjs +200 -56
  481. package/dist/mock/library.js +200 -56
  482. package/dist/mock/library.mjs +200 -56
  483. package/dist/mock/msw.js +200 -56
  484. package/dist/mock/msw.mjs +200 -56
  485. package/dist/native-BodxSh03.d.mts +16 -0
  486. package/dist/native-DUHMT8gA.d.ts +16 -0
  487. package/dist/network-ZXLD7l1b.d.mts +19 -0
  488. package/dist/network-ZXLD7l1b.d.ts +19 -0
  489. package/dist/online-XeymeM9s.d.ts +381 -0
  490. package/dist/online-d7W_Al9a.d.mts +381 -0
  491. package/dist/params-DxFb5G_U.d.mts +155 -0
  492. package/dist/params-DxFb5G_U.d.ts +155 -0
  493. package/dist/play-BRRlfLhX.d.ts +940 -0
  494. package/dist/play-ClrMd_e8.d.mts +940 -0
  495. package/dist/policy-CCw8tXLm.d.mts +3078 -0
  496. package/dist/policy-CMqOSQIu.d.ts +3078 -0
  497. package/dist/ports-B_0v_P3A.d.mts +13 -0
  498. package/dist/ports-CGU_3e_0.d.ts +13 -0
  499. package/dist/prefetch-BHnicOQj.d.ts +117 -0
  500. package/dist/prefetch-CBXgYacv.d.mts +117 -0
  501. package/dist/{price-CSztR02F.d.mts → price-BOzexBww.d.mts} +1 -1
  502. package/dist/{price-C_vasx9A.d.ts → price-C1h9sPxE.d.ts} +1 -1
  503. package/dist/protocol-C8qbpUbT.d.mts +242 -0
  504. package/dist/protocol-C8qbpUbT.d.ts +242 -0
  505. package/dist/rapier-AZHT4YI7.js +7886 -0
  506. package/dist/rapier-ODEPCQA6.mjs +7792 -0
  507. package/dist/react.d.mts +157 -15
  508. package/dist/react.d.ts +157 -15
  509. package/dist/react.js +5564 -5904
  510. package/dist/react.mjs +5451 -5808
  511. package/dist/runner-CQcLL7By.d.ts +189 -0
  512. package/dist/runner-D46Yj-wE.d.mts +189 -0
  513. package/dist/runtime-BRWfkf_q.d.mts +51 -0
  514. package/dist/runtime-DyuBMkKM.d.ts +51 -0
  515. package/dist/scheduling-D2ajXpMC.d.ts +224 -0
  516. package/dist/scheduling-DSRbbaZb.d.mts +224 -0
  517. package/dist/schema-BrWxzKp6.d.mts +63 -0
  518. package/dist/schema-BrWxzKp6.d.ts +63 -0
  519. package/dist/server/evict.js +34 -37
  520. package/dist/server/evict.mjs +34 -37
  521. package/dist/server/tanstack.d.mts +49 -3
  522. package/dist/server/tanstack.d.ts +49 -3
  523. package/dist/server/tanstack.js +169 -117
  524. package/dist/server/tanstack.mjs +166 -118
  525. package/dist/{server-Dckg4Vdr.d.ts → server-D29IIuDV.d.ts} +136 -130
  526. package/dist/{server-B6dW7-Lj.d.mts → server-DQMWPnc8.d.mts} +136 -130
  527. package/dist/server.d.mts +45 -5
  528. package/dist/server.d.ts +45 -5
  529. package/dist/server.js +171 -227
  530. package/dist/server.mjs +165 -225
  531. package/dist/session-grant-CJ27DwrT.d.mts +19 -0
  532. package/dist/session-grant-CJ27DwrT.d.ts +19 -0
  533. package/dist/shootout-BJZeX6FG.d.ts +140 -0
  534. package/dist/shootout-tcZd1Rxt.d.mts +140 -0
  535. package/dist/state-replica-stMtdkVD.d.mts +42 -0
  536. package/dist/state-replica-stMtdkVD.d.ts +42 -0
  537. package/dist/studio-CowqWqez.d.mts +14 -0
  538. package/dist/studio-CowqWqez.d.ts +14 -0
  539. package/dist/styles.css +1 -1
  540. package/dist/template-AhCdB1kW.d.mts +190 -0
  541. package/dist/template-BkEGVTQj.d.ts +190 -0
  542. package/dist/terrain-BMxEc6Oc.d.ts +429 -0
  543. package/dist/terrain-C-XC1Oui.d.mts +429 -0
  544. package/dist/testing/msw.d.mts +28 -4
  545. package/dist/testing/msw.d.ts +28 -4
  546. package/dist/testing/msw.js +15 -21
  547. package/dist/testing/msw.mjs +15 -21
  548. package/dist/testing/suite.d.mts +6 -5
  549. package/dist/testing/suite.d.ts +6 -5
  550. package/dist/testing/suite.js +89 -124
  551. package/dist/testing/suite.mjs +81 -116
  552. package/dist/testing.d.mts +27 -1227
  553. package/dist/testing.d.ts +27 -1227
  554. package/dist/testing.js +127 -131
  555. package/dist/testing.mjs +19 -23
  556. package/dist/tick-transport-C8QEh8Uw.d.mts +50 -0
  557. package/dist/tick-transport-UjHY3xK1.d.ts +50 -0
  558. package/dist/timeline-protocol-hp6e8zFB.d.mts +47 -0
  559. package/dist/timeline-protocol-hp6e8zFB.d.ts +47 -0
  560. package/dist/tokens-DhanQRQS.d.mts +21 -0
  561. package/dist/tokens-K8yxwd6G.d.ts +21 -0
  562. package/dist/tree-C-Io2Hbx.d.mts +35 -0
  563. package/dist/tree-CP_qSW4H.d.ts +35 -0
  564. package/dist/tycoon-B5KHk2Xx.d.mts +255 -0
  565. package/dist/tycoon-hmHo-3HX.d.ts +255 -0
  566. package/dist/types-BQkxPwZP.d.mts +219 -0
  567. package/dist/types-D_f6UUxM.d.ts +219 -0
  568. package/dist/ui-DwHicuFv.d.mts +563 -0
  569. package/dist/ui-hi7S2YcH.d.ts +563 -0
  570. package/dist/{sign-in-DQlIdqsi.d.mts → url-52ndUruG.d.mts} +15 -1
  571. package/dist/{sign-in-DQlIdqsi.d.ts → url-52ndUruG.d.ts} +15 -1
  572. package/dist/utils.d.mts +3 -3
  573. package/dist/utils.d.ts +3 -3
  574. package/dist/utils.js +37 -37
  575. package/dist/utils.mjs +4 -4
  576. package/dist/vars-Dc_PrhBK.d.mts +511 -0
  577. package/dist/vars-Dc_PrhBK.d.ts +511 -0
  578. package/dist/vm-IUARFFAI.mjs +63 -0
  579. package/dist/vm-N7L6MGGH.js +65 -0
  580. package/dist/weave-delivery-CW-Kstut.d.mts +360 -0
  581. package/dist/weave-delivery-CW-Kstut.d.ts +360 -0
  582. package/dist/web-Dss74a7v.d.ts +883 -0
  583. package/dist/web-f9ZQPoyw.d.mts +883 -0
  584. package/dist/web-transport-C7MkBL0a.d.ts +19 -0
  585. package/dist/web-transport-aYEqXMd9.d.mts +19 -0
  586. package/dist/weight-CPGjsgjV.d.ts +92 -0
  587. package/dist/weight-tF1ODR1p.d.mts +92 -0
  588. package/dist/word-BcX9Jcmv.d.mts +70 -0
  589. package/dist/word-C7sVPLHm.d.ts +70 -0
  590. package/dist/world-PvILHDR1.d.ts +2285 -0
  591. package/dist/world-qekkXjJv.d.mts +2285 -0
  592. package/dist/worlds-Br2Pb0Cs.d.ts +109 -0
  593. package/dist/worlds-D5ydYr7d.d.mts +109 -0
  594. package/engines/c/cimplify.h +108 -0
  595. package/engines/c/cimplify.lib.js +11 -0
  596. package/engines/godot/addons/cimplify/cimplify.gd +97 -0
  597. package/engines/rust/interactives-ctx/Cargo.toml +9 -0
  598. package/engines/rust/interactives-ctx/src/lib.rs +189 -0
  599. package/package.json +189 -3
  600. package/vendor/rapier3d-compat/LICENSE +201 -0
  601. package/vendor/rapier3d-compat/PATCHES.md +61 -0
  602. package/dist/chunk-2P4KXFB6.js +0 -274
  603. package/dist/chunk-3G6RQLXK.mjs +0 -21
  604. package/dist/chunk-3V4DVXV3.mjs +0 -254
  605. package/dist/chunk-EDK3LNM6.js +0 -2436
  606. package/dist/chunk-F7J3HK27.js +0 -4549
  607. package/dist/chunk-U4MW6PYU.mjs +0 -23
  608. package/dist/chunk-XREIZ56K.js +0 -26
@@ -0,0 +1,4333 @@
1
+ export { UI_CLOCK_SECONDS, currencyCounter, dialogueBox, iconButton, itemCard, panel, progressBar, tabs, toast, uiClock, worldLabel } from './chunk-3ZYSAW2T.mjs';
2
+ import { yawRotation, withinWorld, snappedToGrid, snapHeightToGrid, overlapsFootprint, movedAbout, identityTransform, encodeTransformSelection, encodeSettings, encodeSetTransform, encodeSelect, encodePlace, encodeModerate, encodeJoinCopy, encodeDuplicate, encodeClock, encodeBare, copyTransform, connectWorld, canonical, bounds, WorldRoleCode, WorldMirror, WorldBuilder, Visibility, TRANSFORM_WORDS, Status, Sky, SelectMode, Sanction, SNAP_SURFACE, SNAP_GRID, SCALE, ROTATION, POSITION, Notice, NOT_SENT, MessageKind, LocalWorld, Likeness, Lighting, Ground, CommandWriter, COMMAND_OP_ID_BYTES, BOUNDS_WORDS, BOUNDS_MIN, BOUNDS_MAX, Action } from './chunk-NPSYB6DC.mjs';
3
+ export { LOCKSTEP_AXIS_LIMIT, LOCKSTEP_AXIS_X, LOCKSTEP_AXIS_Z, LOCKSTEP_BATCH_BYTES, LOCKSTEP_BUTTONS, LOCKSTEP_CONFIG_HEADER_BYTES, LOCKSTEP_CONFIG_MAX_WORDS, LOCKSTEP_CONFIG_TAG, LOCKSTEP_INPUT_ACTION, LOCKSTEP_INPUT_STRIDE, LOCKSTEP_MAX_SEATS, LOCKSTEP_PRESENT, LOCKSTEP_REFEREE_BYTES, LOCKSTEP_WINDOW, LockstepLoopback, LockstepPhase, LockstepRecord, LockstepSession, createTickRoomSimulation, decodeLockstepRecord, defineLockstep, defineLockstepRoom, encodeLockstepConfig, lockstepChecksum, lockstepConfigHash, lockstepRefereeState, lockstepRefereeTick, quantiseLockstepAxis, seededWords as tickSeededWords, unwrapTick16 } from './chunk-RQXN5A34.mjs';
4
+ import { woven, weaveParts, weaveNodeValid, weaveNodeLevel, weaveNodeCount, weaveHeadMessage, walkWeave, verifyRoot, verifyChild, validWeaveRoot, unweaveIndex, storeWeaveSource, planWeave, openWeaveSession, openWeaveHead, nodeMatches, leafZone, leafLength, leafFlags, leafDigestAt, leafDigest, leafAt, deliverSchedule, chunkWeaveSource, childDigestAt, buildWeave, WeaveVerifyError, WeaveRefusal, WEAVE_VERSION, WEAVE_NODE_ZONE, WEAVE_NODE_MAGIC, WEAVE_NODE_HEADER_BYTES, WEAVE_MIN_NODE_ENTRIES, WEAVE_MAX_NODE_ENTRIES, WEAVE_MAX_NODE_BYTES, WEAVE_MAX_HEIGHT, WEAVE_LEAF_TWINNED, WEAVE_LEAF_ENTRY_BYTES, WEAVE_LEAF_DECORATED, WEAVE_HEAD_DOMAIN, WEAVE_CHILD_ENTRY_BYTES, WEAVE_BOUNDARY_MASK } from './chunk-ZR5ULMN2.mjs';
5
+ export { AUDIO_RELAY_EXPORT, AUDIO_WORKLET_FILE, AUDIO_WORKLET_GROUP, AUDIO_WORKLET_PATH, ENGINE_AUDIO_UNIT } from './chunk-ZR5ULMN2.mjs';
6
+ export { SurfacePointer } from './chunk-3GXH2NFD.mjs';
7
+ export { DEFAULT_DISK_RESERVE_BYTES, DEFAULT_KEPT_BUDGET_BYTES, DEFAULT_PART_STORE_BUDGET_BYTES, DEFAULT_PART_ZONE, ENGINE_ARENA_BASELINE_BYTES, ENGINE_ARENA_CHUNK_BYTES, ENGINE_ARENA_FEATURE, ENGINE_ARENA_MAX_CEILING_BYTES, ENGINE_COMPATIBILITY_EXPORT_NAMES, ENGINE_CORE_SCRIPTS_UNIT, ENGINE_FEATURES, ENGINE_FEATURE_NAMES, ENGINE_LUAU_UNIT, ENGINE_OPTIONAL_EXPORTS, KEEP_REASONS, LUAU_SCRIPTS_GROUP, LUAU_VM_EXCEPTIONS, LUAU_VM_FILE, LUAU_VM_PATH, LuauVmModules, MemoryPartBackend, PartSession, PartVerifyError, SCRIPTS_CORE_GROUP, SCRIPTS_CORE_PATH, SharedPartStore, engineExportsUsed, engineFeatureExports, engineFeatureMember, exceptionSupport, luauVmModules, luauVmRunsHere, openLuauScripts, unmetEngineExport, unmetEngineFeature } from './chunk-BU6OK542.mjs';
8
+ import './chunk-PRSR4FAV.mjs';
9
+ import './chunk-TM63CYGN.mjs';
10
+ import './chunk-X6CN6KQF.mjs';
11
+ export { LuauScriptError } from './chunk-MN3YETVN.mjs';
12
+ export { UI_CHECKS, UI_EXEMPT_REASONS, UI_INSPECT_HOOK, exemptUi, inspectScene, inspectSceneEntered, inspectSceneSwitch, uiSite } from './chunk-73SGZLAQ.mjs';
13
+ export { Connecting, Connector, GAME_CHANNEL_RELIABLE_BASE, GAME_CHANNEL_SLOTS, InMemoryNetworkMemory, JoinStatus, Locomotion, LocomotionMotion, MAX_STATE_FRAGMENTS, ROOM_STATE_SLOT, RoomClient, RoomPhase, STATE_CHUNK_BYTES, STATE_FRAME_VERSION, STATE_HEADER_BYTES, StorageNetworkMemory, TickStateReplica, Transport, WebSocketDialer, WebTransportDialer, blankReply, currentNetwork, decodeJoinReply, isqrt, locomotionMotion, perAxisUnit, previousSend, resumeRequest, sendsOn, spawn, steer, ticketRequest } from './chunk-M5EXQZYY.mjs';
14
+ export { Lane, Pace } from './chunk-TU5RYTYU.mjs';
15
+ import './chunk-3OY3VYNF.mjs';
16
+ import './chunk-EIB4OWVQ.mjs';
17
+ export { LOCKSTEP_STORAGE_U64_HI, LOCKSTEP_STORAGE_U64_LO, LOCKSTEP_TABLE_ALIGN, LockstepKernel, LockstepTable, COMMAND_AREA_BYTES as TICK_COMMAND_AREA_BYTES, TICK_DEADLINE_MS, GUEST_HEAP_BYTES as TICK_GUEST_HEAP_BYTES, MAX_COMMAND_PAYLOAD_BYTES as TICK_MAX_COMMAND_PAYLOAD_BYTES, MAX_STATE_BYTES as TICK_MAX_STATE_BYTES, TickRoomError, defineTickRoom, defineTickState, lockstepKernel, lockstepKernelHost, lockstepTable, setLockstepKernelHost, tickLayout } from './chunk-PBL6YL5L.mjs';
18
+ import './chunk-GXKI64OT.mjs';
19
+ import './chunk-NHJUGZUR.mjs';
20
+ import './chunk-E65WCTIG.mjs';
21
+ import './chunk-5YFBGGCK.mjs';
22
+ import './chunk-K4UDGE3Z.mjs';
23
+ import './chunk-MOBSBXVE.mjs';
24
+ import './chunk-SMK6JU2F.mjs';
25
+ import { soleSpan, segmentOutput, partKindName, manifestBytes, isManifest, encodePart, encodeManifest, encodeDelta, decodePart, decodeManifest, assembleInto, assemble, applyDelta, SegmentOp, SEGMENT_BYTES, PartKind, PartFormatError, PART_VERSION, PART_MAGIC, PART_HEADER_BYTES, MAX_MANIFEST_PARTS, MAX_ASSET_BYTES, MANIFEST_VERSION, MANIFEST_PART_BYTES, MANIFEST_MAGIC, MANIFEST_HEADER_BYTES, DeltaOp, ProgressiveKind, containerBounds, writePatch, readLayout, progressiveKindName, liftForward, isProgressive, isCoarseKey, headBytes, encodeContainer, decodeProgressive, coarseKeys, checkLayout, UNLIFT_PARAM_BYTES, UNIT_BYTES, TableWriter, SEGMENT_STAGED, SEGMENT_BYTES2, SAMPLE_BYTES, ProgressiveLayout, ProgressiveFormatError, ProgressiveFeed, ProgressiveDecoder, ProgressiveCancelled, PatchOp, PROGRESSIVE_VERSION, PROGRESSIVE_MAGIC, PPM, PATCH_BYTES, MERGE_PARAM_BYTES, MAX_PROGRESSIVE_DECODE_BYTES, MAX_PROGRESSIVE_BYTES, LEVEL_BYTES, Header, HEADER_BYTES, FILL_BYTE_MAX } from './chunk-U6UVWEAK.mjs';
26
+ export { ENGINE_ABI_DIGEST, ENGINE_ABI_VERSION, ENGINE_EXPORT_PROTOTYPES } from './chunk-A33OORT7.mjs';
27
+ import { validateValue, t, select, runContent, rule, dialogueSchema, createGenerate, contentRequest, applyRules, acceptContent, MIN_TIMEOUT_MS, MAX_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, DEFAULT_RETRIES } from './chunk-OKC2B4O3.mjs';
28
+ import { styles, compileStyle, Condition } from './chunk-PPF2BYFL.mjs';
29
+ export { BREAKPOINT_LG, BREAKPOINT_SM, CompiledStyle, Condition, GameUi, GameUiError, SLOT_REFERENCE, STYLE_BLOCK_MAGIC, STYLE_BLOCK_VERSION, KEY_NAMES as STYLE_KEYS, STYLE_PROPERTY_NAMES, STYLE_RECORD_REFERENCED, STYLE_RECORD_SAFE_EDGES, TextMeasurer, UiElement, UiProps, UiStyleCompileError, VariantKind, collectingSink, compileClasses, compileStyle, conditionPriority, encodeStyleRecords, props, readBlock, styles, tailwindStyle, tailwindVocabulary } from './chunk-PPF2BYFL.mjs';
30
+ import { defineVars, tokens, createTheme, mergeThemes, UiSlot } from './chunk-WLMINRC4.mjs';
31
+ export { TOKEN_NAMESPACE, UiSlot, UiTheme, UiVar, createTheme, defineVars, themeTokens, tokens, varId } from './chunk-WLMINRC4.mjs';
32
+ import { DEFAULT_THEME, theme, UiAction } from './chunk-RFVRPYR2.mjs';
33
+ export { DEFAULT_THEME, NO_NODE, PatchWriter, StyleCache, UI_EVENT_BYTES, UI_EVENT_DX_OFFSET, UI_EVENT_DY_OFFSET, UI_EVENT_KIND_OFFSET, UI_EVENT_NODE_OFFSET, UI_EVENT_PHASE_OFFSET, UI_EVENT_POINTER_OFFSET, UI_EVENT_TIME_OFFSET, UI_EVENT_VALUE_OFFSET, UI_EVENT_X_OFFSET, UI_EVENT_Y_OFFSET, UI_EXCLUSION_HEADER_WORDS, UI_HEADER_BYTES, UI_MAGIC, UI_MAX_EXCLUSIONS, UI_RECORD_HEADER_WORDS, UI_SLOT_REFERENCE, UI_STYLE_REFERENCED, UI_STYLE_SAFE_EDGES, UI_TOKENS_REPLACE, UI_VERSION, UiAction, UiAnchor, UiEasing, UiEventKind, UiExclusionShape, UiFlag, UiFocusFlag, UiKind, UiNumberFormat, UiOp, UiProp, UiRole, UiStyleError, UiTextOption, UiTrait, UiTransition, UiUnit, UiVectorData, UiVectorPlay, codePointOffset, eventStride, parseColor, readEvent, textComposition, textEventCapacity, textEventPadding, theme, writeStyle, writeTextEvent } from './chunk-RFVRPYR2.mjs';
34
+ export { BASE_ENGINE_VARIANT, CONTENT_ENGINE_VARIANT, ENGINE_CORE_GL_UNIT, ENGINE_FEATURE_CARGO, ENGINE_VARIANTS, FULL_ENGINE_VARIANT, GATED_ENGINE_FEATURES, GL_CORE_GROUP, GL_CORE_PATH, GL_ENGINE_VARIANTS, PHYSICS_ENGINE_VARIANT, SCRIPTS_ENGINE_VARIANT, SCRIPTS_ENGINE_VARIANTS, SCRIPTS_SHADERS_ENGINE_VARIANT, SCRIPTS_SHADERS_ENGINE_VARIANTS, TEXT_DICTIONARIES_ASSET, TEXT_DICTIONARIES_FILE, THREADED_ENGINE_VARIANT, THREADED_ENGINE_VARIANTS, engineVariantFor, glVariantOf, isGlVariant, isScriptsVariant, isShadersVariant, isThreadedVariant, scriptsShadersVariantOf, scriptsVariantOf, threadedVariantOf, webGpuVariantOf } from './chunk-DS2VU4WW.mjs';
35
+ import './chunk-5YWN6H5Q.mjs';
36
+ export { suggest } from './chunk-F6XRYEM3.mjs';
37
+ export { FrameBufferPool, FrameCode, FrameFault, acknowledges, compareStamps, decodeAck, decodeChannelFrame, decodeCounterAdd, decodeCounterValue, decodeFastRead, decodeFastValue, decodeMoveInput, decodePresenceDelta, decodePresenceTick, decodeRoomInputFrame, dequantiseAxis, dequantiseCellOffset, dequantiseHeight, dequantiseYaw, encodeAck, encodeCounterAdd, encodeCounterValue, encodeMoveInput, finishPresenceTick, frameLength, frameTag, peekFrameCode, quantiseAxis, quantiseCellOffset, quantiseHeight, quantiseYaw, readPresenceDeltaEntry, readPresenceEntry, stampChannelSender, writeChannelHeader, writeFastReadHeader, writeFastValueHeader, writePresenceEntry, writeRoomInputHeader } from './chunk-OQRVEM56.mjs';
38
+ import { FRAME_LIMITS, CTX_LIMITS } from './chunk-SPCRQ6NO.mjs';
39
+ export { CTX_CAPABILITIES, CTX_COMPATIBLE_FINGERPRINTS, CTX_CONTRACT_FINGERPRINT, CTX_CONTRACT_VERSION, CTX_LIMITS, CTX_MIN_SUPPORTED_CONTRACT_VERSION, FRAME_CODES, FRAME_FLAGS, FRAME_LAYOUT, FRAME_LIMITS, FRAME_VERSION, MAX_DATAGRAM_BYTES, QUANTISATION } from './chunk-SPCRQ6NO.mjs';
40
+ import './chunk-V7ZRH3PY.mjs';
41
+ export { BreakDictionaries, breakDictionaries, registerBreakDictionaries } from './chunk-GYLP6UG4.mjs';
42
+ export { FontTable, fontTable, registerFontTable } from './chunk-XJA2NGTI.mjs';
43
+ import './chunk-2IC4H6OV.mjs';
44
+ import './chunk-MOMOZEUM.mjs';
45
+ import './chunk-N4RGGDEL.mjs';
46
+ import './chunk-XJIHN3BY.mjs';
47
+ import { __export } from './chunk-25T4JHEA.mjs';
48
+
49
+ // src/interactives/simulator.ts
50
+ var SimulatorUnsupportedError = class extends Error {
51
+ constructor(member) {
52
+ super(`ctx.${member} is not available in the local simulator yet`), this.name = "SimulatorUnsupportedError", this.member = member;
53
+ }
54
+ }, SIMULATOR_FIXED_STEP_MS = 1e3 / 60, MAX_FRAME_MS = 250, PREPARED_ENGINE = { kind: "prepared" }, UINT32 = 4294967296, DEFAULT_SEED = 2654435769, STATUS_TEXT_FIELD = "text", DEFAULT_PERSONA = {
55
+ age_range: "adult",
56
+ avatar: null,
57
+ display_name: "Local Player",
58
+ handle: "local",
59
+ participant_id: "participant_local"
60
+ }, DEFAULT_LOCALE = {
61
+ currency: "GHS",
62
+ decimal_separator: ".",
63
+ direction: "ltr",
64
+ first_day_of_week: "monday",
65
+ grouping_separator: ",",
66
+ hour_cycle: "h23",
67
+ language: "en-GH",
68
+ measurement: "metric",
69
+ region: "GH",
70
+ time_zone: "Africa/Accra"
71
+ }, Xoshiro128 = class {
72
+ constructor(words) {
73
+ this.a = words[0] >>> 0, this.b = words[1] >>> 0, this.c = words[2] >>> 0, this.d = words[3] >>> 0 || 1;
74
+ }
75
+ next_u32() {
76
+ let result = Math.imul(rotl(Math.imul(this.b, 5), 7), 9) >>> 0, t2 = this.b << 9;
77
+ return this.c ^= this.a, this.d ^= this.b, this.b ^= this.c, this.a ^= this.d, this.c ^= t2, this.d = rotl(this.d, 11), result;
78
+ }
79
+ next_float() {
80
+ return this.next_u32() / (4294967296);
81
+ }
82
+ };
83
+ function rotl(x, k) {
84
+ return (x << k | x >>> 32 - k) >>> 0;
85
+ }
86
+ function splitmix(state) {
87
+ let z = state + 2654435769 | 0;
88
+ return z = Math.imul(z ^ z >>> 16, 2246822507), z = Math.imul(z ^ z >>> 13, 3266489909), (z ^ z >>> 16) >>> 0;
89
+ }
90
+ function copyEntries(entries) {
91
+ let out = /* @__PURE__ */ new Map();
92
+ for (let [k, v] of entries) out.set(k, { value: structuredClone(v.value), revision: v.revision });
93
+ return out;
94
+ }
95
+ function createSimulatorCtx(options) {
96
+ let host = options.host, now = options.now ?? (() => Date.now()), persona = options.persona ?? DEFAULT_PERSONA, locale = options.locale ?? DEFAULT_LOCALE, unsupported = /* @__PURE__ */ new Set(), disposers = [], lifecycle = /* @__PURE__ */ new Map(), stores = /* @__PURE__ */ new Map(), uiListeners = /* @__PURE__ */ new Set(), cosmeticState = (options.seed ?? (2654435769)) >>> 0, checkpointCounter = 0, lifecycleState = "visible", status = { text: null, your_turn: false }, completions = [], info = {
97
+ capabilities: [],
98
+ contract_version: 1,
99
+ data_lineage: null,
100
+ features: [],
101
+ instance: "simulator",
102
+ interactive_id: options.interactiveId ?? "itv_simulator",
103
+ kit_version: null,
104
+ launch: { source: "direct", reference: null, selected: null },
105
+ location: "client",
106
+ profile: options.profile,
107
+ revision: "rev_local"
108
+ }, program = {
109
+ ready() {
110
+ },
111
+ ...info,
112
+ async set_status(request) {
113
+ if ([...request.text].length > CTX_LIMITS.max_status_line_chars)
114
+ throw { code: "invalid_arguments", field: STATUS_TEXT_FIELD, problem: "too_long" };
115
+ return status = { text: request.text.length === 0 ? null : request.text, your_turn: request.your_turn }, status;
116
+ }
117
+ }, storeById = (id) => {
118
+ let store = stores.get(id);
119
+ if (!store) throw new Error(`unknown store ${id}`);
120
+ return store;
121
+ }, emitStore = (store, event) => {
122
+ for (let l of store.listeners) l(event);
123
+ }, openStore = async (request) => {
124
+ let key = `${request.scope}:${request.name}`, store = stores.get(key);
125
+ store || (store = {
126
+ handle: {
127
+ access: "read_write",
128
+ classification: request.classification,
129
+ migrate_from: null,
130
+ revision: 0,
131
+ schema: request.schema,
132
+ scope: request.scope,
133
+ store_id: key
134
+ },
135
+ entries: /* @__PURE__ */ new Map(),
136
+ checkpoints: /* @__PURE__ */ new Map(),
137
+ listeners: /* @__PURE__ */ new Set()
138
+ }, stores.set(key, store));
139
+ let s9 = store, id = s9.handle.store_id;
140
+ return {
141
+ get handle() {
142
+ return s9.handle;
143
+ },
144
+ async get(req) {
145
+ let hit = storeById(id).entries.get(req.key);
146
+ return { key: req.key, revision: hit ? hit.revision : 0, value: hit ? structuredClone(hit.value) : null };
147
+ },
148
+ async list(req) {
149
+ let prefix = req.prefix ?? "", entries = [];
150
+ for (let [k, v] of s9.entries) k.startsWith(prefix) && entries.push({ key: k, revision: v.revision, value: structuredClone(v.value) });
151
+ entries.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
152
+ let limit = req.page.limit ?? entries.length;
153
+ return { entries: entries.slice(0, limit), next: null, revision: s9.handle.revision };
154
+ },
155
+ async commit(req) {
156
+ if (req.expected !== void 0 && req.expected !== null && req.expected !== s9.handle.revision)
157
+ throw new Error(`store ${id} is at revision ${s9.handle.revision}, expected ${req.expected}`);
158
+ let revision = s9.handle.revision + 1, keys = [];
159
+ for (let w of req.writes)
160
+ keys.push(w.key), w.op === "put" ? s9.entries.set(w.key, { value: structuredClone(w.value), revision }) : s9.entries.delete(w.key);
161
+ return s9.handle = { ...s9.handle, revision }, emitStore(s9, { kind: "changed", keys, revision, store_id: id }), { revision, store_id: id };
162
+ },
163
+ async checkpoint() {
164
+ checkpointCounter++;
165
+ let checkpoint_id = `checkpoint_${checkpointCounter}`;
166
+ return s9.checkpoints.set(checkpoint_id, { revision: s9.handle.revision, entries: copyEntries(s9.entries) }), { checkpoint_id, created_at: now(), revision: s9.handle.revision, store_id: id };
167
+ },
168
+ async restore(req) {
169
+ let cp = s9.checkpoints.get(req.checkpoint_id);
170
+ if (!cp) throw new Error(`unknown checkpoint ${req.checkpoint_id}`);
171
+ s9.entries = copyEntries(cp.entries);
172
+ let revision = s9.handle.revision + 1;
173
+ return s9.handle = { ...s9.handle, revision }, emitStore(s9, { kind: "restored", checkpoint_id: req.checkpoint_id, revision, store_id: id }), s9.handle;
174
+ },
175
+ async migrate(req) {
176
+ let revision = s9.handle.revision + 1;
177
+ return s9.handle = { ...s9.handle, revision, schema: req.to, migrate_from: s9.handle.schema.version }, emitStore(s9, { kind: "migrated", revision, schema: req.to, store_id: id }), s9.handle;
178
+ },
179
+ on_event(listener) {
180
+ return s9.listeners.add(listener), () => s9.listeners.delete(listener);
181
+ }
182
+ };
183
+ }, loop = createLoop(host, () => record("game.loop")), record = (member) => {
184
+ throw unsupported.add(member), new SimulatorUnsupportedError(member);
185
+ }, fire = (event) => {
186
+ let listeners = lifecycle.get(event);
187
+ if (listeners) for (let l of listeners) l();
188
+ }, base = {
189
+ program,
190
+ session: {
191
+ async complete(request) {
192
+ return completions.push(request), { recorded: false };
193
+ }
194
+ },
195
+ clock: {
196
+ now,
197
+ async sync() {
198
+ return { display_offset_ms: 0, now: now(), room_tick: null, source: "app_clock" };
199
+ }
200
+ },
201
+ random: {
202
+ cosmetic() {
203
+ return cosmeticState = splitmix(cosmeticState), cosmeticState / (4294967296);
204
+ },
205
+ async seed(request) {
206
+ let s9 = cosmeticState, words = [0, 0, 0, 0];
207
+ for (let i = 0; i < 4; i++)
208
+ s9 = splitmix(s9 + i), words[i] = s9;
209
+ return { label: request.label, recorded: false, scope: request.scope, words };
210
+ },
211
+ stream(grant) {
212
+ return new Xoshiro128(grant.words);
213
+ }
214
+ },
215
+ locale: {
216
+ ...locale,
217
+ format_number(value, fraction_digits) {
218
+ return new Intl.NumberFormat(locale.language, {
219
+ minimumFractionDigits: fraction_digits,
220
+ maximumFractionDigits: fraction_digits
221
+ }).format(value);
222
+ },
223
+ format_money(amount, currency) {
224
+ return new Intl.NumberFormat(locale.language, { style: "currency", currency: currency ?? locale.currency }).format(Number(amount));
225
+ },
226
+ format_time(unix_ms) {
227
+ return new Intl.DateTimeFormat(locale.language, { timeStyle: "short", timeZone: locale.time_zone }).format(unix_ms);
228
+ }
229
+ },
230
+ identity: {
231
+ async current() {
232
+ return persona;
233
+ },
234
+ async personas(request) {
235
+ return { personas: request.participants.indexOf(persona.participant_id) >= 0 ? [persona] : [] };
236
+ },
237
+ async profile() {
238
+ return {
239
+ participant_id: persona.participant_id,
240
+ display_name: persona.display_name,
241
+ handle: persona.handle ?? null,
242
+ avatar: persona.avatar ?? null
243
+ };
244
+ }
245
+ },
246
+ open_store: openStore,
247
+ async share() {
248
+ return host.toast("Share sheet opened"), { decision: "confirmed", link: null };
249
+ },
250
+ ui: {
251
+ render(tree) {
252
+ host.render(tree);
253
+ },
254
+ async present() {
255
+ },
256
+ open_sheet(request) {
257
+ return host.openSheet ? host.openSheet(request) : record("ui.open_sheet");
258
+ },
259
+ async open_handoff() {
260
+ return { status: "cancelled" };
261
+ },
262
+ toast(text) {
263
+ host.toast(text);
264
+ },
265
+ haptic() {
266
+ },
267
+ announce(text) {
268
+ host.toast(text);
269
+ },
270
+ on_event(listener) {
271
+ return uiListeners.add(listener), () => uiListeners.delete(listener);
272
+ }
273
+ },
274
+ graphics: {
275
+ features: { apis: ["canvas2d"], max_texture_size: 4096, device_tier: "mid" },
276
+ engine() {
277
+ return host.engine ? host.engine() : Promise.resolve(PREPARED_ENGINE);
278
+ },
279
+ acquire_surface(surfaceOptions) {
280
+ return host.acquireSurface ? host.acquireSurface(surfaceOptions) : record("graphics.acquire_surface");
281
+ },
282
+ attach_engine() {
283
+ return record("graphics.attach_engine");
284
+ },
285
+ on_context_lost() {
286
+ return () => {
287
+ };
288
+ },
289
+ on_context_restored() {
290
+ return () => {
291
+ };
292
+ }
293
+ },
294
+ game: guard("game", { kit_version: "simulator", loop }, unsupported),
295
+ lifecycle: {
296
+ get state() {
297
+ return lifecycleState;
298
+ },
299
+ on(event, listener) {
300
+ let set = lifecycle.get(event);
301
+ return set || (set = /* @__PURE__ */ new Set(), lifecycle.set(event, set)), set.add(listener), () => set.delete(listener);
302
+ }
303
+ },
304
+ on_dispose(callback) {
305
+ disposers.push(callback);
306
+ }
307
+ };
308
+ return {
309
+ ctx: guard("", base, unsupported),
310
+ unsupported,
311
+ get status() {
312
+ return status;
313
+ },
314
+ completions,
315
+ emit(event) {
316
+ event === "hidden" ? lifecycleState = "hidden" : event === "visible" || event === "resume" ? lifecycleState = "visible" : event === "suspend" && (lifecycleState = "suspended"), fire(event);
317
+ },
318
+ dispatch(event) {
319
+ if (lifecycleState !== "disposed")
320
+ for (let listener of uiListeners) listener(event);
321
+ },
322
+ dispose() {
323
+ if (lifecycleState !== "disposed") {
324
+ loop.stop(), lifecycleState = "disposed", fire("dispose");
325
+ for (let i = disposers.length - 1; i >= 0; i--) disposers[i]();
326
+ disposers.length = 0, uiListeners.clear();
327
+ }
328
+ }
329
+ };
330
+ }
331
+ function guard(prefix, target, unsupported) {
332
+ return new Proxy(target, {
333
+ get(obj, prop, receiver) {
334
+ if (typeof prop == "symbol" || prop in obj) return Reflect.get(obj, prop, receiver);
335
+ if (prop === "then") return;
336
+ let member = prefix === "" ? prop : `${prefix}.${prop}`;
337
+ throw unsupported.add(member), new SimulatorUnsupportedError(member);
338
+ }
339
+ });
340
+ }
341
+ function createLoop(host, missing) {
342
+ let callbacks = null, handle = -1, last = -1, accumulator = 0, tick = 0, paused = false, step = SIMULATOR_FIXED_STEP_MS, frame = (time) => {
343
+ if (callbacks === null || !host.requestFrame) return;
344
+ if (handle = host.requestFrame(frame), paused) {
345
+ last = time;
346
+ return;
347
+ }
348
+ let elapsed = last < 0 ? step : time - last;
349
+ for (last = time, accumulator += elapsed > (250) ? (250) : elapsed; accumulator >= step; )
350
+ callbacks.update(step, tick), tick++, accumulator -= step;
351
+ callbacks.render(accumulator / step);
352
+ };
353
+ return {
354
+ fixed_step_ms: step,
355
+ get tick() {
356
+ return tick;
357
+ },
358
+ start(next) {
359
+ host.requestFrame || missing(), callbacks = next, paused = false, last = -1, handle = host.requestFrame(frame);
360
+ },
361
+ pause() {
362
+ paused = true;
363
+ },
364
+ resume() {
365
+ paused = false;
366
+ },
367
+ stop() {
368
+ callbacks = null, handle >= 0 && host.cancelFrame && host.cancelFrame(handle), handle = -1;
369
+ }
370
+ };
371
+ }
372
+
373
+ // src/interactives/game-ui/widgets/theme.ts
374
+ var KIT_NAMESPACE = "kit", UI_FONT_SET = ["sans", "rounded", "condensed", "serif", "mono", "pixel"], UI_DEFAULT_FONT = 0, UI_FONT_ROLES = ["body", "display", "mono"], ROLE_FAMILIES = { body: "kit.body", display: "kit.display", mono: "kit.mono" }, ROLE_INDEX = { body: 0, display: 1, mono: 2 }, KIT_WEIGHTS = [400, 600, 700, 800], DEFAULT_WEIGHT = 400, DEFAULT_METRICS = {
375
+ radius: DEFAULT_THEME.radius,
376
+ radiusSmall: 8,
377
+ padding: DEFAULT_THEME.padding,
378
+ gap: DEFAULT_THEME.gap,
379
+ gapSmall: 4,
380
+ small: DEFAULT_THEME.small,
381
+ body: DEFAULT_THEME.body,
382
+ title: DEFAULT_THEME.title,
383
+ display: 30,
384
+ borderWidth: 1,
385
+ focusWidth: 2,
386
+ pressScale: DEFAULT_THEME.press_scale
387
+ }, DEFAULT_EXTRAS = {
388
+ focus: "#ffffffff",
389
+ scrim: "#05070cb3",
390
+ highlight: "#ffffff1f",
391
+ shadow: "#0000008c",
392
+ onDanger: "#ffffffff",
393
+ silver: "#c7ccd6ff",
394
+ bronze: "#cd7f32ff"
395
+ }, kitVars = defineVars(KIT_NAMESPACE, { ...DEFAULT_METRICS, ...DEFAULT_EXTRAS }), AI_MARK_NAMESPACE = "ai_mark", DEFAULT_AI_MARK = { fill: "#ffffff1f", text: "#a1a1aaff", fontSize: 10, radius: 4, paddingInline: 4 }, aiMarkVars = defineVars(AI_MARK_NAMESPACE, { ...DEFAULT_AI_MARK });
396
+ function aiMarkTheme(overrides) {
397
+ return createTheme(aiMarkVars, overrides);
398
+ }
399
+ function themePack(definition) {
400
+ let metrics = { ...DEFAULT_METRICS, ...definition.metrics }, c = definition.colors, game = theme({
401
+ surface: c.surface,
402
+ raised: c.raised,
403
+ border: c.border,
404
+ accent: c.accent,
405
+ on_accent: c.onAccent,
406
+ text: c.text,
407
+ muted: c.muted,
408
+ track: c.track,
409
+ danger: c.danger,
410
+ success: c.success,
411
+ gold: c.gold,
412
+ radius: metrics.radius,
413
+ padding: metrics.padding,
414
+ gap: metrics.gap,
415
+ small: metrics.small,
416
+ body: metrics.body,
417
+ title: metrics.title,
418
+ press_scale: metrics.pressScale,
419
+ motion: definition.motion ?? DEFAULT_THEME.motion
420
+ }), palette = createTheme(tokens, {
421
+ surface: c.surface,
422
+ raised: c.raised,
423
+ border: c.border,
424
+ accent: c.accent,
425
+ onAccent: c.onAccent,
426
+ text: c.text,
427
+ muted: c.muted,
428
+ track: c.track,
429
+ danger: c.danger,
430
+ success: c.success,
431
+ gold: c.gold
432
+ }), kit = createTheme(kitVars, {
433
+ ...metrics,
434
+ focus: c.focus,
435
+ scrim: c.scrim,
436
+ highlight: c.highlight,
437
+ shadow: c.shadow,
438
+ onDanger: c.onDanger,
439
+ silver: c.silver,
440
+ bronze: c.bronze
441
+ }), mark = aiMarkTheme({ fill: c.track, text: c.muted, ...definition.aiMark });
442
+ return { name: definition.name, colors: c, metrics, fonts: definition.fonts, game, theme: mergeThemes([palette, kit, mark]) };
443
+ }
444
+ var NEON_ARCADE = themePack({
445
+ name: "Neon arcade",
446
+ colors: {
447
+ surface: "#0b0420eb",
448
+ raised: "#1d0b3dff",
449
+ border: "#ff2bd666",
450
+ accent: "#ff2bd6ff",
451
+ onAccent: "#12021fff",
452
+ text: "#f4f0ffff",
453
+ muted: "#a493d6ff",
454
+ track: "#ffffff1f",
455
+ danger: "#ff3860ff",
456
+ success: "#22f5a0ff",
457
+ gold: "#fff03aff",
458
+ focus: "#2bf3ffff",
459
+ scrim: "#05010fcc",
460
+ highlight: "#2bf3ff26",
461
+ shadow: "#ff2bd659",
462
+ onDanger: "#ffffffff",
463
+ silver: "#b8c4ffff",
464
+ bronze: "#ff9d5cff"
465
+ },
466
+ metrics: { radius: 4, radiusSmall: 2, borderWidth: 2, focusWidth: 3, pressScale: 0.92, display: 34 },
467
+ fonts: { body: "sans", display: "pixel", mono: "mono" },
468
+ motion: 0.1
469
+ }), COZY_PASTEL = themePack({
470
+ name: "Cozy pastel",
471
+ colors: {
472
+ surface: "#fff7efef",
473
+ raised: "#ffe9dcff",
474
+ border: "#e8cbb866",
475
+ accent: "#f49cb8ff",
476
+ onAccent: "#3b1d2aff",
477
+ text: "#4a3a40ff",
478
+ muted: "#9a8590ff",
479
+ track: "#e9d8d2ff",
480
+ danger: "#ef7f7fff",
481
+ success: "#7fcfa6ff",
482
+ gold: "#f6c560ff",
483
+ focus: "#8fb8ffff",
484
+ scrim: "#5a4a5266",
485
+ highlight: "#8fb8ff2e",
486
+ shadow: "#9a6f8040",
487
+ onDanger: "#ffffffff",
488
+ silver: "#b9bfd0ff",
489
+ bronze: "#d9a07aff"
490
+ },
491
+ metrics: { radius: 20, radiusSmall: 14, padding: 16, gap: 10, pressScale: 0.96 },
492
+ fonts: { body: "rounded", display: "rounded", mono: "mono" },
493
+ motion: 0.22
494
+ }), SPORTS_BROADCAST = themePack({
495
+ name: "Sports broadcast",
496
+ colors: {
497
+ surface: "#0d1b2af2",
498
+ raised: "#16324fff",
499
+ border: "#ffffff33",
500
+ accent: "#e4002bff",
501
+ onAccent: "#ffffffff",
502
+ text: "#ffffffff",
503
+ muted: "#9fb3c8ff",
504
+ track: "#ffffff26",
505
+ danger: "#ff5a36ff",
506
+ success: "#00c389ff",
507
+ gold: "#ffcd00ff",
508
+ focus: "#ffcd00ff",
509
+ scrim: "#020a12cc",
510
+ highlight: "#ffffff1a",
511
+ shadow: "#00000080",
512
+ onDanger: "#ffffffff",
513
+ silver: "#c0c8d2ff",
514
+ bronze: "#c9844aff"
515
+ },
516
+ metrics: { radius: 2, radiusSmall: 2, padding: 10, gap: 6, gapSmall: 3, body: 15, title: 20, display: 32, pressScale: 0.97 },
517
+ fonts: { body: "sans", display: "condensed", mono: "condensed" },
518
+ motion: 0.12
519
+ }), FANTASY_PARCHMENT = themePack({
520
+ name: "Fantasy parchment",
521
+ colors: {
522
+ surface: "#f1e2c2f2",
523
+ raised: "#e5cf9fff",
524
+ border: "#7a5a2e99",
525
+ accent: "#8b2a1fff",
526
+ onAccent: "#fbf1dcff",
527
+ text: "#3a2614ff",
528
+ muted: "#7a6448ff",
529
+ track: "#c9b083ff",
530
+ danger: "#a3241bff",
531
+ success: "#4f7a2aff",
532
+ gold: "#b8860bff",
533
+ focus: "#2f5d8aff",
534
+ scrim: "#1a0f0599",
535
+ highlight: "#2f5d8a26",
536
+ shadow: "#3a261459",
537
+ onDanger: "#fbf1dcff",
538
+ silver: "#8d8f94ff",
539
+ bronze: "#8c5a2bff"
540
+ },
541
+ metrics: { radius: 6, radiusSmall: 4, padding: 14, borderWidth: 2, focusWidth: 2, title: 21, display: 32 },
542
+ fonts: { body: "serif", display: "serif", mono: "mono" },
543
+ motion: 0.2
544
+ }), THEME_PACKS = [NEON_ARCADE, COZY_PASTEL, SPORTS_BROADCAST, FANTASY_PARCHMENT], books = /* @__PURE__ */ new WeakMap();
545
+ function book(ui) {
546
+ let found = books.get(ui);
547
+ return found === void 0 && (found = { fonts: /* @__PURE__ */ new Map(), pack: null, roles: [] }, books.set(ui, found)), found;
548
+ }
549
+ function kitFamily(ui, role) {
550
+ return ui.family(ROLE_FAMILIES[role]);
551
+ }
552
+ function fontStyle(ui, role) {
553
+ let roles = book(ui).roles, index = ROLE_INDEX[role], style = roles[index];
554
+ if (style === void 0) {
555
+ let fonts = book(ui);
556
+ (fonts.pack === null || !fonts.fonts.has(fonts.pack.fonts[role])) && ui.registerFont(ROLE_FAMILIES[role], (0), (400)), style = styles({ font: { fontFamily: kitFamily(ui, role) } }).font, roles[index] = style;
557
+ }
558
+ return style;
559
+ }
560
+ function nearest(entry, weight) {
561
+ let best = -1, distance = 1 / 0;
562
+ for (let i = 0; i < entry.weights.length; i++) {
563
+ let gap = Math.abs(entry.weights[i] - weight);
564
+ gap < distance && (distance = gap, best = entry.fonts[i]);
565
+ }
566
+ return best;
567
+ }
568
+ function bind(ui, fonts, pack) {
569
+ for (let r = 0; r < UI_FONT_ROLES.length; r++) {
570
+ let role = UI_FONT_ROLES[r], entry = fonts.fonts.get(pack.fonts[role]);
571
+ if (entry !== void 0)
572
+ for (let w = 0; w < KIT_WEIGHTS.length; w++) ui.registerFont(ROLE_FAMILIES[role], nearest(entry, KIT_WEIGHTS[w]), KIT_WEIGHTS[w]);
573
+ }
574
+ }
575
+ function registerUiFont(ui, name, font, weight = (400)) {
576
+ let fonts = book(ui), entry = fonts.fonts.get(name);
577
+ entry === void 0 && (entry = { weights: [], fonts: [] }, fonts.fonts.set(name, entry));
578
+ let at = entry.weights.indexOf(weight);
579
+ at >= 0 ? entry.fonts[at] = font : (entry.weights.push(weight), entry.fonts.push(font)), ui.registerFont(name, font, weight), fonts.pack !== null && bind(ui, fonts, fonts.pack);
580
+ }
581
+ function applyThemePack(ui, pack) {
582
+ let fonts = book(ui);
583
+ ui.theme(pack.theme), fonts.pack !== pack && (fonts.pack = pack, bind(ui, fonts, pack));
584
+ }
585
+ function currentThemePack(ui) {
586
+ return books.get(ui)?.pack ?? null;
587
+ }
588
+
589
+ // src/interactives/game-ui/widgets/sheet.ts
590
+ var TRANSPARENT = "#00000000", TAP_TARGET = 44, PRESS_SECONDS = 0.12, FADE_SECONDS = 0.18, HALF = 0.5, PERCENT = 100, BOLD = 700, HEAVY = 800, sheet = styles({
591
+ text: { fontSize: kitVars.body, textColor: tokens.text, pointerEvents: "none" },
592
+ small: { fontSize: kitVars.small, textColor: tokens.muted, pointerEvents: "none" },
593
+ title: { fontSize: kitVars.title, fontWeight: (700), textColor: tokens.text, pointerEvents: "none" },
594
+ display: { fontSize: kitVars.display, fontWeight: (800), textColor: tokens.text, pointerEvents: "none" },
595
+ strong: { fontWeight: (700) },
596
+ muted: { textColor: tokens.muted },
597
+ center: { textAlign: "center" },
598
+ wrap: { textWrap: true, alignSelf: "stretch" },
599
+ hidden: { hidden: true },
600
+ shown: { hidden: false },
601
+ layer: { width: "100%", height: "100%", pointerEvents: "none" },
602
+ panel: {
603
+ padding: kitVars.padding,
604
+ gap: kitVars.gap,
605
+ fill: tokens.surface,
606
+ radius: kitVars.radius,
607
+ borderWidth: kitVars.borderWidth,
608
+ borderColor: tokens.border
609
+ },
610
+ focusRing: {
611
+ borderWidth: kitVars.focusWidth,
612
+ borderColor: { default: TRANSPARENT, ":focus": kitVars.focus }
613
+ },
614
+ pressable: {
615
+ scale: { default: 1, ":pressed": kitVars.pressScale },
616
+ opacity: { default: 1, ":disabled": 0.5 }
617
+ }
618
+ }), PERCENT_TEXT = Array.from({ length: (100) + 1 }, (_, i) => `${i}%`), INTEGER = { format: "integer", separator: "," }, PLAIN = { format: "integer", separator: "" }, TIMER = { format: "timer" };
619
+ function label(ui, value, role, a, b, c) {
620
+ return ui.text(value, ui.props(fontStyle(ui, role), a, b, c));
621
+ }
622
+ function clamp(value, low, high) {
623
+ return value < low ? low : value > high ? high : value;
624
+ }
625
+ var SLOTS = new Float64Array(4);
626
+ function slotWords(template) {
627
+ return compileStyle(template);
628
+ }
629
+ function slot(index, percent = false) {
630
+ return new UiSlot(index, percent);
631
+ }
632
+ var A11y = class {
633
+ constructor(options) {
634
+ this.first = true;
635
+ this.actions = options.actions, this.options = { ...options, actions: void 0 };
636
+ }
637
+ apply(element) {
638
+ if (this.first) {
639
+ this.first = false, this.options.actions = this.actions, element.accessibility(this.options), this.options.actions = void 0;
640
+ return;
641
+ }
642
+ element.accessibility(this.options);
643
+ }
644
+ }, StableList = class {
645
+ constructor() {
646
+ this.items = [];
647
+ this.count = 0;
648
+ }
649
+ get size() {
650
+ return this.count;
651
+ }
652
+ at(index) {
653
+ return this.items[index];
654
+ }
655
+ push(item) {
656
+ this.count < this.items.length ? this.items[this.count] = item : this.items.push(item), this.count++;
657
+ }
658
+ indexOf(item) {
659
+ for (let i = 0; i < this.count; i++) if (this.items[i] === item) return i;
660
+ return -1;
661
+ }
662
+ removeAt(index) {
663
+ for (let i = index; i + 1 < this.count; i++) this.items[i] = this.items[i + 1];
664
+ this.count--;
665
+ }
666
+ };
667
+ function removeAt(list2, index) {
668
+ for (let i = index; i + 1 < list2.length; i++) list2[i] = list2[i + 1];
669
+ list2.length = list2.length - 1;
670
+ }
671
+ var Rng = class {
672
+ constructor(seed) {
673
+ this.state = new Int32Array(1);
674
+ this.state[0] = (seed | 0) === 0 ? 2654435769 : seed | 0;
675
+ }
676
+ next() {
677
+ let x = this.state[0];
678
+ return x ^= x << 13, x ^= x >>> 17, x ^= x << 5, this.state[0] = x, (x >>> 0) / 4294967296;
679
+ }
680
+ range(low, high) {
681
+ return low + (high - low) * this.next();
682
+ }
683
+ };
684
+
685
+ // src/interactives/game-ui/widgets/ai-mark.ts
686
+ var AI_MARK_SOURCES = ["generated", "cached", "replicated"], AI_MARK_TEXT = "AI", AI_MARK_LABEL = "AI generated";
687
+ function isAiGenerated(source) {
688
+ return source === "generated" || source === "cached" || source === "replicated";
689
+ }
690
+ var s = styles({
691
+ mark: { fill: aiMarkVars.fill, radius: aiMarkVars.radius, paddingInline: aiMarkVars.paddingInline, alignSelf: "center", shrink: 0, pointerEvents: "none" },
692
+ markText: { fontSize: aiMarkVars.fontSize, fontWeight: (800), textColor: aiMarkVars.text, pointerEvents: "none" },
693
+ row: { direction: "row", alignItems: "center", gap: kitVars.gapSmall },
694
+ text: { fontSize: kitVars.body, textColor: tokens.text, shrink: 1, pointerEvents: "none" }
695
+ }), AiMark = class {
696
+ constructor(ui, options = {}) {
697
+ this.ui = ui;
698
+ this.on = false;
699
+ this.states = [ui.props(s.mark, options.style, sheet.hidden), ui.props(s.mark, options.style)], this.root = ui.box(this.states[0]), this.text = label(ui, options.text ?? AI_MARK_TEXT, "body", s.markText, options.textStyle), this.root.append(this.text), this.root.accessibility({ hidden: true });
700
+ }
701
+ get shown() {
702
+ return this.on;
703
+ }
704
+ show(source) {
705
+ let on = isAiGenerated(source);
706
+ return on === this.on || (this.on = on, this.root.style(this.states[on ? 1 : 0])), on;
707
+ }
708
+ };
709
+ function aiMark(ui, options = {}) {
710
+ return new AiMark(ui, options);
711
+ }
712
+ function aiLabel(text, marked) {
713
+ return marked ? `${text}, ${AI_MARK_LABEL}` : text;
714
+ }
715
+ var GeneratedText = class {
716
+ constructor(ui, options = {}) {
717
+ this.ui = ui;
718
+ this.current = "";
719
+ this.source = null;
720
+ this.shown = false;
721
+ this.a11y = new A11y({ role: "text", label: "" });
722
+ this.root = ui.box(ui.props(s.row, options.style)), this.text = label(ui, "", options.role ?? "body", s.text, options.wrap === true && sheet.wrap, options.textStyle), this.mark = new AiMark(ui, options.mark), this.root.append(this.text).append(this.mark.root), this.set(options.text ?? "", options.source ?? null);
723
+ }
724
+ get value() {
725
+ return this.current;
726
+ }
727
+ get marked() {
728
+ return this.mark.shown;
729
+ }
730
+ set(text, source = null) {
731
+ this.shown && text === this.current && isAiGenerated(source) === isAiGenerated(this.source) || (this.shown = true, this.current = text, this.source = source, this.text.text(text), this.a11y.options.label = aiLabel(text, this.mark.show(source)), this.a11y.apply(this.root));
732
+ }
733
+ show(result) {
734
+ this.set(result.value, result.source);
735
+ }
736
+ };
737
+ function generatedText(ui, options = {}) {
738
+ return new GeneratedText(ui, options);
739
+ }
740
+
741
+ // src/interactives/game-ui/widgets/collections.ts
742
+ var CELL = 64, CELL_GAP = 8, GRID_PADDING = 8, ICON_RATIO = 0.7, GHOST_SCALE = 1.08, GHOST_Z = 20, EMPTY = -1, ROW_HEIGHT = 44, LIST_HEIGHT = 320, POOL_SLACK = 2, RANK_WIDTH = 44, SCORE_WIDTH = 96, NO_INDEX = -1, TRAVEL_SHIFT = 4, TRAVEL_SCALE = 1 << (4), MEDALS = 3, s2 = styles({
743
+ grid: { padding: (8), gap: (8), fill: tokens.surface, radius: kitVars.radius, position: "relative", borderWidth: kitVars.focusWidth, borderColor: { default: tokens.border, ":focus": kitVars.focus } },
744
+ gridRow: { direction: "row", gap: (8) },
745
+ cell: {
746
+ alignItems: "center",
747
+ justify: "center",
748
+ radius: kitVars.radiusSmall,
749
+ fill: tokens.raised,
750
+ borderWidth: 2,
751
+ borderColor: TRANSPARENT,
752
+ position: "relative",
753
+ scale: { default: 1, ":pressed": kitVars.pressScale }
754
+ },
755
+ cellCursor: { borderColor: kitVars.focus },
756
+ cellHover: { borderColor: tokens.accent, fill: kitVars.highlight },
757
+ cellSource: { opacity: 0.35 },
758
+ icon: { pointerEvents: "none" },
759
+ iconEmpty: { hidden: true },
760
+ count: { position: "absolute", right: 4, bottom: 2, fontSize: kitVars.small, fontWeight: 800, textColor: tokens.text, pointerEvents: "none" },
761
+ ghost: { position: "absolute", alignItems: "center", justify: "center", pointerEvents: "none", zIndex: (20), scale: (1.08), opacity: 0.92, radius: kitVars.radiusSmall, fill: kitVars.highlight, hidden: true },
762
+ ghostShown: { hidden: false },
763
+ ghostAt: { left: 0, top: 0 },
764
+ list: { scrollAxes: "y", clip: true, radius: kitVars.radius, fill: tokens.surface, borderWidth: kitVars.focusWidth, borderColor: { default: tokens.border, ":focus": kitVars.focus } },
765
+ extent: { height: 0 },
766
+ content: { position: "relative", width: "100%" },
767
+ slot: { position: "absolute", left: 0, right: 0, direction: "row", alignItems: "center" },
768
+ slotHidden: { hidden: true },
769
+ slotCursor: { fill: kitVars.highlight },
770
+ slotAt: { top: 0, height: 0 },
771
+ rowMe: { fill: tokens.accent },
772
+ leader: { direction: "row", alignItems: "center", gap: kitVars.gap, padding: [0, kitVars.padding, 0, kitVars.padding], width: "100%", height: "100%" },
773
+ rank: { width: (44), fontSize: kitVars.body, fontWeight: 800, textColor: tokens.muted, textAlign: "center", pointerEvents: "none" },
774
+ name: { grow: 1, shrink: 1, fontSize: kitVars.body, textColor: tokens.text, pointerEvents: "none" },
775
+ score: { width: (96), fontSize: kitVars.body, fontWeight: 700, textColor: tokens.gold, textAlign: "right", pointerEvents: "none" },
776
+ gold: { textColor: tokens.gold },
777
+ silver: { textColor: kitVars.silver },
778
+ bronze: { textColor: kitVars.bronze },
779
+ onAccent: { textColor: tokens.onAccent }
780
+ }, {
781
+ ghostAt: slotWords({ left: slot(0), top: slot(1) }),
782
+ extent: slotWords({ height: slot(0) }),
783
+ slotAt: slotWords({ top: slot(0), height: slot(1) })
784
+ }), InventoryGrid = class {
785
+ constructor(ui, options) {
786
+ this.ui = ui;
787
+ this.cellStates = [];
788
+ this.cellA11y = [];
789
+ this.cursorAt = 0;
790
+ this.focused = false;
791
+ this.source = (-1);
792
+ this.hover = (-1);
793
+ this.travel = new Int32Array(2);
794
+ this.held = false;
795
+ this.columns = options.columns, this.rows = options.rows, this.size = options.cell ?? (64);
796
+ let gap = options.gap ?? (8);
797
+ this.pitch = this.size + gap, this.natural = options.natural ?? [this.size, this.size], this.onMove = options.onMove ?? null, this.onSelect = options.onSelect ?? null;
798
+ let count2 = this.columns * this.rows;
799
+ this.assets = new Int32Array(count2).fill((-1)), this.amounts = new Int32Array(count2), this.cellColumn = new Int32Array(count2), this.cellRow = new Int32Array(count2);
800
+ for (let i = 0; i < count2; i++)
801
+ this.cellColumn[i] = i % this.columns, this.cellRow[i] = Math.floor(i / this.columns);
802
+ this.names = new Array(count2).fill("Empty");
803
+ let sized = { width: this.size, height: this.size }, iconSize = { width: this.size * (0.7), height: this.size * (0.7) };
804
+ for (let state = 0; state < 8; state++) this.cellStates.push(ui.props(s2.cell, sized, (state & 1) !== 0 && s2.cellCursor, (state & 2) !== 0 && s2.cellHover, (state & 4) !== 0 && s2.cellSource));
805
+ this.iconStates = [ui.props(s2.icon, iconSize), ui.props(s2.icon, iconSize, s2.iconEmpty)], this.ghostStates = [ui.props(s2.ghost, sized), ui.props(s2.ghost, sized, s2.ghostShown)];
806
+ let mono = fontStyle(ui, "mono");
807
+ this.countStates = [ui.props(mono, s2.count), ui.props(mono, s2.count, sheet.hidden)], this.root = ui.box(ui.props(s2.grid, { gap }, options.style));
808
+ let cells = [], icons = [], counts = [];
809
+ for (let r = 0; r < this.rows; r++) {
810
+ let row = ui.box(ui.props(s2.gridRow, { gap }));
811
+ for (let c = 0; c < this.columns; c++) {
812
+ let index = r * this.columns + c, cell = ui.box(this.cellStates[0]);
813
+ cell.transition(["scale_x", "scale_y", "opacity"], { duration: (0.12), easing: "back_out" });
814
+ let icon = ui.image(0, this.natural, this.iconStates[1]), amount = ui.text("", this.countStates[1]);
815
+ cell.append(icon).append(amount), cell.on("tap", () => this.select(index)), cell.on("drag_start", () => this.begin(index)), cell.on("drag_move", (event) => this.drag(event)), cell.on("drag_end", () => this.drop());
816
+ let a11y = new A11y({ role: "button", label: "Empty", actions: ["activate"] });
817
+ a11y.apply(cell), this.cellA11y.push(a11y), row.append(cell), cells.push(cell), icons.push(icon), counts.push(amount);
818
+ }
819
+ this.root.append(row);
820
+ }
821
+ this.cells = cells, this.icons = icons, this.counts = counts, this.ghost = ui.box(this.ghostStates[0]), this.ghostIcon = ui.image(0, this.natural, ui.props(s2.icon, iconSize)), this.ghost.append(this.ghostIcon), this.root.append(this.ghost), this.root.accessibility({ role: "group", label: options.label ?? "Inventory" }), options.scope?.add(this);
822
+ }
823
+ get cursor() {
824
+ return this.cursorAt;
825
+ }
826
+ get dragging() {
827
+ return this.source;
828
+ }
829
+ setSlot(index, asset, count2, name) {
830
+ this.assets[index] = asset, this.amounts[index] = asset === (-1) ? 0 : count2, this.names[index] = asset === (-1) ? "Empty" : name, this.render(index);
831
+ }
832
+ clearSlot(index) {
833
+ this.setSlot(index, (-1), 0, "Empty");
834
+ }
835
+ swap(a, b) {
836
+ if (a === b) return;
837
+ let asset = this.assets[a], amount = this.amounts[a], name = this.names[a];
838
+ this.assets[a] = this.assets[b], this.amounts[a] = this.amounts[b], this.names[a] = this.names[b], this.assets[b] = asset, this.amounts[b] = amount, this.names[b] = name, this.render(a), this.render(b);
839
+ }
840
+ select(index) {
841
+ let previous = this.cursorAt;
842
+ this.cursorAt = index, this.paint(previous), this.paint(index), this.onSelect?.(index);
843
+ }
844
+ focusChanged(focused) {
845
+ this.focused = focused, this.paint(this.cursorAt);
846
+ }
847
+ move(move) {
848
+ let c = this.cellColumn[this.cursorAt], r = this.cellRow[this.cursorAt], next = (-1);
849
+ if (move === "left" && c > 0 ? next = this.cursorAt - 1 : move === "right" && c + 1 < this.columns ? next = this.cursorAt + 1 : move === "up" && r > 0 ? next = this.cursorAt - this.columns : move === "down" && r + 1 < this.rows && (next = this.cursorAt + this.columns), next === (-1)) return false;
850
+ let previous = this.cursorAt;
851
+ return this.cursorAt = next, this.held && (this.hover = next, this.placeGhost(next)), this.paint(previous), this.paint(next), true;
852
+ }
853
+ activate() {
854
+ if (!this.held) {
855
+ if (this.assets[this.cursorAt] === (-1)) {
856
+ this.onSelect?.(this.cursorAt);
857
+ return;
858
+ }
859
+ this.begin(this.cursorAt), this.held = true, this.hover = this.cursorAt, this.placeGhost(this.cursorAt);
860
+ return;
861
+ }
862
+ this.held = false, this.drop();
863
+ }
864
+ cancel() {
865
+ return this.source === (-1) ? false : (this.held = false, this.hover = (-1), this.drop(), true);
866
+ }
867
+ begin(index) {
868
+ this.assets[index] !== (-1) && (this.source = index, this.hover = index, this.travel[0] = 0, this.travel[1] = 0, this.ghostIcon.image(this.assets[index], this.natural[0], this.natural[1]), this.placeGhost(index), this.paint(index));
869
+ }
870
+ drag(event) {
871
+ let source = this.source;
872
+ if (source === (-1) || this.held) return;
873
+ let travel = this.travel;
874
+ travel[0] += event.dx * TRAVEL_SCALE | 0, travel[1] += event.dy * TRAVEL_SCALE | 0, this.placeGhost(source);
875
+ let c = this.cellColumn[source] + this.pitchesIn(travel[0]), r = this.cellRow[source] + this.pitchesIn(travel[1]), next = c < 0 || r < 0 || c >= this.columns || r >= this.rows ? (-1) : r * this.columns + c;
876
+ if (next === this.hover) return;
877
+ let previous = this.hover;
878
+ this.hover = next, previous !== (-1) && this.paint(previous), next !== (-1) && this.paint(next);
879
+ }
880
+ drop() {
881
+ let source = this.source;
882
+ if (source === (-1)) return;
883
+ let target = this.hover;
884
+ this.source = (-1), this.hover = (-1), this.ghost.style(this.ghostStates[0]), this.paint(source), target !== (-1) && this.paint(target), !(target === (-1) || target === source) && (this.swap(source, target), this.onMove?.(source, target));
885
+ }
886
+ pitchesIn(travel) {
887
+ let pitch = this.pitch * TRAVEL_SCALE, half = pitch >> 1, rest = travel, count2 = 0;
888
+ for (; rest >= half; )
889
+ rest -= pitch, count2++;
890
+ for (; rest < -half; )
891
+ rest += pitch, count2--;
892
+ return count2;
893
+ }
894
+ placeGhost(index) {
895
+ SLOTS[0] = (8) + this.cellColumn[index] * this.pitch + (this.travel[0] >> (4)), SLOTS[1] = (8) + this.cellRow[index] * this.pitch + (this.travel[1] >> (4)), this.ghost.style(this.ui.props(this.source === (-1) ? this.ghostStates[0] : this.ghostStates[1], s2.ghostAt.setSlotsFrom(SLOTS)));
896
+ }
897
+ render(index) {
898
+ let asset = this.assets[index], icon = this.icons[index];
899
+ asset === (-1) ? icon.style(this.iconStates[1]) : (icon.image(asset, this.natural[0], this.natural[1]), icon.style(this.iconStates[0]));
900
+ let amount = this.amounts[index], text = this.counts[index];
901
+ amount > 1 ? (text.number(amount, PLAIN), text.style(this.countStates[0])) : text.style(this.countStates[1]);
902
+ let a11y = this.cellA11y[index];
903
+ a11y.options.label = this.names[index], a11y.apply(this.cells[index]);
904
+ }
905
+ paint(index) {
906
+ if (index < 0) return;
907
+ let cursor = this.focused && index === this.cursorAt ? 1 : 0, hover = index === this.hover && index !== this.source ? 2 : 0, source = index === this.source ? 4 : 0;
908
+ this.cells[index].style(this.cellStates[cursor | hover | source]);
909
+ }
910
+ };
911
+ function inventoryGrid(ui, options) {
912
+ return new InventoryGrid(ui, options);
913
+ }
914
+ var VirtualList = class {
915
+ constructor(ui, options) {
916
+ this.ui = ui;
917
+ this.options = options;
918
+ this.offsetY = 0;
919
+ this.cursorAt = 0;
920
+ this.focused = false;
921
+ this.total = Math.max(0, options.count), this.rowHeight = options.rowHeight ?? (44), this.height = options.height ?? (320), this.onSelect = options.onSelect ?? null, this.heightOf = options.heightOf ?? null, this.offsets = new Float64Array(this.heightOf === null ? 1 : this.total + 1), this.measureRows(0);
922
+ let pool = Math.ceil(this.height / this.rowHeight) + (2);
923
+ this.bound = new Int32Array(pool).fill((-1)), this.flags = new Uint8Array(pool).fill(255), this.states = [ui.props(s2.slot), ui.props(s2.slot, s2.slotCursor), ui.props(s2.slot, s2.slotHidden)], this.root = ui.scroll(ui.props(s2.list, { height: this.height, width: options.width ?? "100%" }, options.style)), this.content = ui.box();
924
+ let slots = [], rows = [];
925
+ for (let p = 0; p < pool; p++) {
926
+ let element = ui.box(this.states[2]), row = options.create(ui);
927
+ element.append(row.root), element.on("tap", () => {
928
+ let index = this.bound[p];
929
+ index !== (-1) && this.choose(index);
930
+ }), this.content.append(element), slots.push(element), rows.push(row);
931
+ }
932
+ this.slots = slots, this.rows = rows, this.root.append(this.content), this.root.on("scroll", (event) => this.scrolled(event.dy)), this.root.accessibility({ role: "scroll_view", label: options.label ?? "List", actions: ["scroll"] }), this.extend(), this.refresh(true), options.scope?.add(this);
933
+ }
934
+ get count() {
935
+ return this.total;
936
+ }
937
+ get offset() {
938
+ return this.offsetY;
939
+ }
940
+ get cursor() {
941
+ return this.cursorAt;
942
+ }
943
+ get pool() {
944
+ return this.slots.length;
945
+ }
946
+ get variable() {
947
+ return this.heightOf !== null;
948
+ }
949
+ rowTop(index) {
950
+ return this.heightOf === null ? index * this.rowHeight : this.offsets[index];
951
+ }
952
+ rowSize(index) {
953
+ return this.heightOf === null ? this.rowHeight : this.offsets[index + 1] - this.offsets[index];
954
+ }
955
+ get contentHeight() {
956
+ return this.heightOf === null ? this.total * this.rowHeight : this.offsets[this.total];
957
+ }
958
+ invalidateHeights(from = 0) {
959
+ this.heightOf !== null && (this.measureRows(clamp(from, 0, this.total)), this.extend(), this.offsetY = clamp(this.offsetY, 0, this.maxOffset()) | 0, this.refresh(true));
960
+ }
961
+ measureRows(from) {
962
+ let heightOf = this.heightOf;
963
+ if (heightOf === null) return;
964
+ if (this.offsets.length < this.total + 1) {
965
+ let grown = new Float64Array(Math.max(this.total + 1, this.offsets.length * 2));
966
+ grown.set(this.offsets.subarray(0, from + 1)), this.offsets = grown;
967
+ }
968
+ let offsets = this.offsets;
969
+ offsets[0] = 0;
970
+ for (let i = from; i < this.total; i++) offsets[i + 1] = offsets[i] + Math.max(0, heightOf(i));
971
+ }
972
+ firstVisible(offset) {
973
+ if (this.heightOf === null) return (offset - offset % this.rowHeight) / this.rowHeight;
974
+ let offsets = this.offsets, low = 0, high = this.total;
975
+ for (; low < high; ) {
976
+ let middle = low + high >>> 1;
977
+ offsets[middle + 1] <= offset ? low = middle + 1 : high = middle;
978
+ }
979
+ return low;
980
+ }
981
+ setCount(count2) {
982
+ let previous = this.total;
983
+ this.total = Math.max(0, count2), this.measureRows(Math.min(previous, this.total)), this.cursorAt = clamp(this.cursorAt, 0, Math.max(0, this.total - 1)), this.extend(), this.offsetY = clamp(this.offsetY, 0, this.maxOffset()) | 0, this.refresh(true);
984
+ }
985
+ rebind() {
986
+ this.refresh(true);
987
+ }
988
+ scrollTo(offset) {
989
+ let next = clamp(offset, 0, this.maxOffset());
990
+ this.root.scrollTo(0, next), this.scrolled(next);
991
+ }
992
+ scrollToIndex(index) {
993
+ let top = this.rowTop(index), size = this.rowSize(index);
994
+ top < this.offsetY ? this.scrollTo(top) : top + size > this.offsetY + this.height && this.scrollTo(top + size - this.height);
995
+ }
996
+ focusChanged(focused) {
997
+ this.focused = focused, this.refresh(false);
998
+ }
999
+ move(move) {
1000
+ if (this.total === 0) return false;
1001
+ let next = this.cursorAt;
1002
+ if (move === "up") next--;
1003
+ else if (move === "down") next++;
1004
+ else return false;
1005
+ return next < 0 || next >= this.total ? false : (this.cursorAt = next, this.scrollToIndex(next), this.refresh(false), true);
1006
+ }
1007
+ activate() {
1008
+ this.total > 0 && this.choose(this.cursorAt);
1009
+ }
1010
+ choose(index) {
1011
+ this.cursorAt = index, this.refresh(false), this.onSelect?.(index);
1012
+ }
1013
+ scrolled(offset) {
1014
+ this.offsetY = offset | 0, this.refresh(false);
1015
+ }
1016
+ maxOffset() {
1017
+ return Math.max(0, this.contentHeight - this.height);
1018
+ }
1019
+ extend() {
1020
+ SLOTS[0] = this.contentHeight, this.content.style(this.ui.props(s2.content, s2.extent.setSlotsFrom(SLOTS)));
1021
+ }
1022
+ refresh(force) {
1023
+ let pool = this.slots.length, offset = this.offsetY < 0 ? 0 : this.offsetY, first = this.firstVisible(offset);
1024
+ for (let k = 0; k < pool; k++) {
1025
+ let index = first + k, p = index % pool, slotElement = this.slots[p], visible = index < this.total, flag = visible ? this.focused && index === this.cursorAt ? 1 : 0 : 2, moved = this.bound[p] !== index;
1026
+ if (visible && (moved || force) && this.options.bind(this.rows[p], index), !moved && this.flags[p] === flag && !force) continue;
1027
+ this.bound[p] = visible ? index : (-1), this.flags[p] = flag;
1028
+ let fixed = this.heightOf === null;
1029
+ SLOTS[0] = fixed || visible ? this.rowTop(index) : this.contentHeight, SLOTS[1] = fixed || !visible ? this.rowHeight : this.rowSize(index), slotElement.style(this.ui.props(this.states[flag], s2.slotAt.setSlotsFrom(SLOTS)));
1030
+ }
1031
+ }
1032
+ };
1033
+ function virtualList(ui, options) {
1034
+ return new VirtualList(ui, options);
1035
+ }
1036
+ var Leaderboard = class {
1037
+ constructor(ui, options = {}) {
1038
+ this.ui = ui;
1039
+ this.names = [];
1040
+ this.scores = [];
1041
+ this.me = (-1);
1042
+ this.rowStates = [ui.props(s2.leader), ui.props(s2.leader, s2.rowMe)];
1043
+ let mono = fontStyle(ui, "mono"), body = fontStyle(ui, "body");
1044
+ this.rankStates = [ui.props(mono, s2.rank), ui.props(mono, s2.rank, s2.gold), ui.props(mono, s2.rank, s2.silver), ui.props(mono, s2.rank, s2.bronze), ui.props(mono, s2.rank, s2.onAccent)], this.nameStates = [ui.props(body, s2.name), ui.props(body, s2.name, s2.onAccent)], this.scoreStyle = ui.props(mono, s2.score), this.list = new VirtualList(ui, {
1045
+ count: 0,
1046
+ rowHeight: options.rowHeight,
1047
+ height: options.height,
1048
+ width: options.width,
1049
+ label: options.label ?? "Leaderboard",
1050
+ style: options.style,
1051
+ scope: options.scope,
1052
+ onSelect: options.onSelect,
1053
+ create: (owner) => {
1054
+ let root = owner.box(this.rowStates[0]), rank = owner.text("", this.rankStates[0]), name = owner.text("", this.nameStates[0]), score = owner.text("", this.scoreStyle);
1055
+ return root.append(rank).append(name).append(score), { root, rank, name, score };
1056
+ },
1057
+ bind: (row, index) => this.bind(row, index)
1058
+ });
1059
+ }
1060
+ get root() {
1061
+ return this.list.root;
1062
+ }
1063
+ setEntries(names, scores, me = (-1)) {
1064
+ this.names = names, this.scores = scores, this.me = me, this.list.setCount(Math.min(names.length, scores.length));
1065
+ }
1066
+ showMe() {
1067
+ this.me !== (-1) && this.list.scrollToIndex(this.me);
1068
+ }
1069
+ bind(row, index) {
1070
+ let mine = index === this.me;
1071
+ row.root.style(this.rowStates[mine ? 1 : 0]), row.rank.style(this.rankStates[mine ? 4 : index < (3) ? index + 1 : 0]), row.rank.number(index + 1, PLAIN), row.name.text(this.names[index]), row.name.style(this.nameStates[mine ? 1 : 0]), row.score.number(this.scores[index], INTEGER);
1072
+ }
1073
+ };
1074
+ function leaderboard(ui, options = {}) {
1075
+ return new Leaderboard(ui, options);
1076
+ }
1077
+ var CHAT_LOG_WIDTH = 300, CHAT_LOG_HEIGHT = 240, CHAT_LOG_FONT = 14, CHAT_LOG_PADDING = 6, CHAT_LOG_CAPACITY = 2e3, CHAT_LOG_MIN_ROW = 18, SCROLL_END = Number.MAX_SAFE_INTEGER, chatLogStyles = styles({
1078
+ row: { width: "100%", height: "100%", padding: [0, (6), 0, (6)], justify: "center" },
1079
+ line: { textWrap: true, textColor: tokens.text, pointerEvents: "none" }
1080
+ }), ChatLog = class {
1081
+ constructor(ui, options = {}) {
1082
+ this.ui = ui;
1083
+ this.lines = [];
1084
+ this.head = 0;
1085
+ this.measured = { lines: 0, width: 0, height: 0 };
1086
+ let width = options.width ?? (300), fontSize = options.fontSize ?? (14);
1087
+ this.capacity = options.capacity ?? (2e3), this.lineWidth = width - (6) * 2, this.measureStyle = { fontFamily: kitFamily(ui, "body"), fontSize };
1088
+ let lineStyle = ui.props(fontStyle(ui, "body"), chatLogStyles.line, { fontSize }), rowStyle = ui.props(chatLogStyles.row);
1089
+ this.list = new VirtualList(ui, {
1090
+ count: 0,
1091
+ rowHeight: Math.min((18), fontSize),
1092
+ height: options.height ?? (240),
1093
+ width,
1094
+ label: options.label ?? "Chat",
1095
+ style: options.style,
1096
+ scope: options.scope,
1097
+ heightOf: (index) => this.heightOf(index),
1098
+ create: (owner) => {
1099
+ let root = owner.box(rowStyle), line = owner.text("", lineStyle);
1100
+ return root.append(line), { root, line };
1101
+ },
1102
+ bind: (row, index) => {
1103
+ row.line.text(this.line(index));
1104
+ }
1105
+ });
1106
+ }
1107
+ get root() {
1108
+ return this.list.root;
1109
+ }
1110
+ get count() {
1111
+ return this.lines.length;
1112
+ }
1113
+ line(index) {
1114
+ return this.lines[(this.head + index) % this.lines.length];
1115
+ }
1116
+ push(sender, message) {
1117
+ let text = sender.length > 0 ? `${sender}: ${message}` : message;
1118
+ this.lines.length < this.capacity ? (this.lines.push(text), this.list.setCount(this.lines.length)) : (this.lines[this.head] = text, this.head = (this.head + 1) % this.capacity, this.list.invalidateHeights(0)), this.list.scrollTo(SCROLL_END);
1119
+ }
1120
+ heightOf(index) {
1121
+ return this.ui.measureText(this.line(index), this.measureStyle, this.lineWidth, this.measured).height;
1122
+ }
1123
+ };
1124
+ function chatLog(ui, options = {}) {
1125
+ return new ChatLog(ui, options);
1126
+ }
1127
+
1128
+ // src/interactives/game-ui/widgets/focus.ts
1129
+ var UiFocusScope = class {
1130
+ constructor(columns = 1, onBack = null) {
1131
+ this.columns = columns;
1132
+ this.onBack = onBack;
1133
+ this.targets = [];
1134
+ this.current = -1;
1135
+ }
1136
+ add(target) {
1137
+ return this.targets.indexOf(target) < 0 && this.targets.push(target), this;
1138
+ }
1139
+ remove(target) {
1140
+ let at = this.targets.indexOf(target);
1141
+ return at < 0 ? this : (removeAt(this.targets, at), this.current === at ? this.current = -1 : this.current > at && this.current--, this);
1142
+ }
1143
+ clear() {
1144
+ this.targets.length = 0, this.current = -1;
1145
+ }
1146
+ };
1147
+ function focusNodeOf(target) {
1148
+ return target.focusNode ?? target.root;
1149
+ }
1150
+ function usable(target) {
1151
+ let root = focusNodeOf(target);
1152
+ return !root.destroyed && (root.active() & Condition.disabled) === 0;
1153
+ }
1154
+ function stepOf(move, columns) {
1155
+ switch (move) {
1156
+ case "next":
1157
+ case "right":
1158
+ return 1;
1159
+ case "previous":
1160
+ case "left":
1161
+ return -1;
1162
+ case "down":
1163
+ return columns;
1164
+ default:
1165
+ return -columns;
1166
+ }
1167
+ }
1168
+ var UiNavigator = class {
1169
+ constructor(base = new UiFocusScope()) {
1170
+ this.scopes = new StableList();
1171
+ this.listeners = [];
1172
+ this.shown = null;
1173
+ this.base = base, this.scopes.push(base);
1174
+ }
1175
+ get scope() {
1176
+ return this.scopes.at(this.scopes.size - 1);
1177
+ }
1178
+ get depth() {
1179
+ return this.scopes.size;
1180
+ }
1181
+ get focused() {
1182
+ return this.shown;
1183
+ }
1184
+ onChange(listener) {
1185
+ return this.listeners.push(listener), () => {
1186
+ let at = this.listeners.indexOf(listener);
1187
+ at >= 0 && removeAt(this.listeners, at);
1188
+ };
1189
+ }
1190
+ has(scope) {
1191
+ return this.scopes.indexOf(scope) >= 0;
1192
+ }
1193
+ push(scope) {
1194
+ this.has(scope) || (this.scopes.push(scope), this.restore(scope));
1195
+ }
1196
+ pop(scope = null) {
1197
+ let target = scope ?? this.scope;
1198
+ if (target === this.base) return;
1199
+ let at = this.scopes.indexOf(target);
1200
+ if (at < 0) return;
1201
+ let wasTop = at === this.scopes.size - 1;
1202
+ this.scopes.removeAt(at), wasTop && this.restore(this.scope);
1203
+ }
1204
+ focus(target) {
1205
+ let scope = this.scope, at = scope.targets.indexOf(target);
1206
+ return at < 0 || !usable(target) ? false : (this.show(scope, at), true);
1207
+ }
1208
+ move(move) {
1209
+ let scope = this.scope, count2 = scope.targets.length;
1210
+ if (count2 === 0) return false;
1211
+ let at = scope.current;
1212
+ if (at >= 0 && at < count2 && this.shown === scope.targets[at]) {
1213
+ let current = scope.targets[at];
1214
+ if (current.move !== void 0 && current.move(move)) return true;
1215
+ } else
1216
+ return this.first(scope);
1217
+ let step = stepOf(move, scope.columns);
1218
+ for (let i = 1; i <= count2; i++) {
1219
+ let next = ((at + step * i) % count2 + count2) % count2;
1220
+ if (next === at) break;
1221
+ if (usable(scope.targets[next]))
1222
+ return this.show(scope, next), true;
1223
+ }
1224
+ return false;
1225
+ }
1226
+ activate() {
1227
+ let target = this.shown;
1228
+ return target === null || target.activate === void 0 || !usable(target) ? false : (target.activate(), true);
1229
+ }
1230
+ back() {
1231
+ let onBack = this.scope.onBack;
1232
+ return onBack !== null && onBack();
1233
+ }
1234
+ blur() {
1235
+ this.set(null);
1236
+ }
1237
+ first(scope) {
1238
+ for (let i = 0; i < scope.targets.length; i++)
1239
+ if (usable(scope.targets[i]))
1240
+ return this.show(scope, i), true;
1241
+ return this.set(null), false;
1242
+ }
1243
+ restore(scope) {
1244
+ let at = scope.current;
1245
+ at >= 0 && at < scope.targets.length && usable(scope.targets[at]) ? this.show(scope, at) : scope.targets.length > 0 ? this.first(scope) : this.set(null);
1246
+ }
1247
+ show(scope, at) {
1248
+ scope.current = at, this.set(scope.targets[at]);
1249
+ }
1250
+ set(target) {
1251
+ let previous = this.shown;
1252
+ if (previous !== target) {
1253
+ if (this.shown = target, previous !== null && !focusNodeOf(previous).destroyed) {
1254
+ let node = focusNodeOf(previous);
1255
+ node.setState("focus", false), previous.focusChanged?.(false), target === null && node.blur();
1256
+ }
1257
+ if (target !== null) {
1258
+ let node = focusNodeOf(target);
1259
+ node.setState("focus", true), node.focus(), target.focusChanged?.(true);
1260
+ }
1261
+ for (let i = 0; i < this.listeners.length; i++) this.listeners[i](target);
1262
+ }
1263
+ }
1264
+ };
1265
+
1266
+ // src/interactives/game-ui/widgets/controls.ts
1267
+ var TRACK_WIDTH = 52, TRACK_HEIGHT = 30, KNOB = 24, KNOB_INSET = 3, RAIL = 6, THUMB = 24, SLIDER_HEIGHT = 32, SLIDER_WIDTH = 220, DROPDOWN_WIDTH = 200, OPTION_HEIGHT = 40, CHEVRON = 8, CHEVRON_TURN = Math.PI / 4, POPUP_Z = 50, MAX_LABELLED_STEPS = 1001, s3 = styles({
1268
+ button: {
1269
+ direction: "row",
1270
+ alignItems: "center",
1271
+ justify: "center",
1272
+ gap: kitVars.gapSmall,
1273
+ minHeight: (44),
1274
+ padding: [kitVars.gap, kitVars.padding, kitVars.gap, kitVars.padding],
1275
+ radius: kitVars.radius,
1276
+ fill: { default: tokens.raised, ":disabled": tokens.track },
1277
+ borderWidth: kitVars.focusWidth,
1278
+ borderColor: { default: TRANSPARENT, ":focus": kitVars.focus },
1279
+ scale: { default: 1, ":pressed": kitVars.pressScale },
1280
+ opacity: { default: 1, ":disabled": 0.55 }
1281
+ },
1282
+ primary: { fill: { default: tokens.accent, ":disabled": tokens.track } },
1283
+ danger: { fill: { default: tokens.danger, ":disabled": tokens.track } },
1284
+ ghost: { fill: { default: TRANSPARENT, ":focus": kitVars.highlight, ":pressed": kitVars.highlight, ":disabled": TRANSPARENT } },
1285
+ label: { fontSize: kitVars.body, fontWeight: 700, textColor: { default: tokens.text, ":disabled": tokens.muted }, pointerEvents: "none" },
1286
+ onPrimary: { textColor: { default: tokens.onAccent, ":disabled": tokens.muted } },
1287
+ onDanger: { textColor: { default: kitVars.onDanger, ":disabled": tokens.muted } },
1288
+ icon: { width: 20, height: 20, pointerEvents: "none" },
1289
+ row: {
1290
+ direction: "row",
1291
+ alignItems: "center",
1292
+ justify: "space-between",
1293
+ gap: kitVars.gap,
1294
+ minHeight: (44),
1295
+ padding: [kitVars.gapSmall, kitVars.gap, kitVars.gapSmall, kitVars.gap],
1296
+ radius: kitVars.radius,
1297
+ borderWidth: kitVars.focusWidth,
1298
+ borderColor: { default: TRANSPARENT, ":focus": kitVars.focus },
1299
+ fill: { default: TRANSPARENT, ":pressed": kitVars.highlight },
1300
+ opacity: { default: 1, ":disabled": 0.5 }
1301
+ },
1302
+ track: { width: (52), height: (30), radius: (30) / 2, fill: tokens.track, padding: (3), justify: "center", pointerEvents: "none" },
1303
+ trackOn: { fill: tokens.accent },
1304
+ knob: {
1305
+ width: (24),
1306
+ height: (24),
1307
+ radius: (24) / 2,
1308
+ fill: tokens.text,
1309
+ translateX: 0,
1310
+ scale: { default: 1, ":pressed": 0.88 },
1311
+ shadow: { color: kitVars.shadow, y: 1, blur: 3 }
1312
+ },
1313
+ knobOn: { translateX: (52) - (24) - (3) * 2, fill: tokens.onAccent },
1314
+ slider: { gap: kitVars.gapSmall, padding: [kitVars.gapSmall, kitVars.gap, kitVars.gapSmall, kitVars.gap], radius: kitVars.radius, borderWidth: kitVars.focusWidth, borderColor: { default: TRANSPARENT, ":focus": kitVars.focus }, opacity: { default: 1, ":disabled": 0.5 } },
1315
+ header: { direction: "row", justify: "space-between", alignItems: "center", pointerEvents: "none" },
1316
+ rail: { height: (32), position: "relative" },
1317
+ railLine: { position: "absolute", left: 0, right: 0, top: ((32) - (6)) / 2, height: (6), radius: (6) / 2, fill: tokens.track, pointerEvents: "none" },
1318
+ railFill: { position: "absolute", left: 0, top: ((32) - (6)) / 2, height: (6), radius: (6) / 2, fill: tokens.accent, pointerEvents: "none" },
1319
+ thumb: {
1320
+ position: "absolute",
1321
+ top: ((32) - (24)) / 2,
1322
+ width: (24),
1323
+ height: (24),
1324
+ marginLeft: -(24) / 2,
1325
+ radius: (24) / 2,
1326
+ fill: tokens.text,
1327
+ borderWidth: kitVars.focusWidth,
1328
+ borderColor: { default: TRANSPARENT, ":focus": kitVars.focus },
1329
+ scale: { default: 1, ":pressed": 1.15 },
1330
+ shadow: { color: kitVars.shadow, y: 1, blur: 4 },
1331
+ pointerEvents: "none"
1332
+ },
1333
+ fillTo: { width: "0%" },
1334
+ thumbAt: { left: "0%" },
1335
+ dropdown: { position: "relative", gap: kitVars.gapSmall },
1336
+ field: { justify: "space-between" },
1337
+ chevron: { width: (8), height: (8), borderColor: tokens.muted, borderWidth: [0, 2, 2, 0], rotate: CHEVRON_TURN, marginTop: -(8) / 2, pointerEvents: "none" },
1338
+ chevronOpen: { rotate: -CHEVRON_TURN * 3, marginTop: (8) / 2 },
1339
+ popup: {
1340
+ position: "absolute",
1341
+ top: "100%",
1342
+ left: 0,
1343
+ right: 0,
1344
+ marginTop: kitVars.gapSmall,
1345
+ padding: kitVars.gapSmall,
1346
+ gap: 2,
1347
+ fill: tokens.surface,
1348
+ radius: kitVars.radius,
1349
+ borderWidth: kitVars.borderWidth,
1350
+ borderColor: tokens.border,
1351
+ shadow: { color: kitVars.shadow, y: 8, blur: 24 },
1352
+ zIndex: (50),
1353
+ hidden: true
1354
+ },
1355
+ option: {
1356
+ minHeight: (40),
1357
+ justify: "center",
1358
+ padding: [kitVars.gapSmall, kitVars.gap, kitVars.gapSmall, kitVars.gap],
1359
+ radius: kitVars.radiusSmall,
1360
+ fill: { default: TRANSPARENT, ":focus": kitVars.highlight, ":pressed": kitVars.highlight },
1361
+ borderWidth: kitVars.focusWidth,
1362
+ borderColor: { default: TRANSPARENT, ":focus": kitVars.focus }
1363
+ },
1364
+ optionOn: { fill: { default: tokens.accent, ":focus": tokens.accent } }
1365
+ }, {
1366
+ fillTo: slotWords({ width: slot(0, true) }),
1367
+ thumbAt: slotWords({ left: slot(0, true) })
1368
+ }), TextButton = class {
1369
+ constructor(ui, options) {
1370
+ this.ui = ui;
1371
+ let variant = options.variant ?? "secondary";
1372
+ this.onPress = options.onPress ?? null, this.root = ui.box(ui.props(s3.button, variant === "primary" && s3.primary, variant === "danger" && s3.danger, variant === "ghost" && s3.ghost, options.style)), this.root.transition(["scale_x", "scale_y", "fill"], { duration: (0.12), easing: "back_out" }), options.icon !== void 0 && this.root.append(ui.image(options.icon, options.natural ?? [32, 32], s3.icon)), this.text = label(ui, options.label, "body", s3.label, variant === "primary" ? s3.onPrimary : variant === "danger" ? s3.onDanger : null, options.labelStyle), this.root.append(this.text), this.root.on("tap", () => this.activate()), this.a11y = new A11y({ role: "button", label: options.label, disabled: options.disabled === true, actions: ["activate"] }), this.a11y.apply(this.root), options.scope?.add(this);
1373
+ }
1374
+ get disabled() {
1375
+ return this.a11y.options.disabled === true;
1376
+ }
1377
+ setLabel(value) {
1378
+ this.text.text(value), this.a11y.options.label = value, this.a11y.apply(this.root);
1379
+ }
1380
+ setDisabled(disabled) {
1381
+ disabled !== this.disabled && (this.a11y.options.disabled = disabled, this.a11y.apply(this.root));
1382
+ }
1383
+ activate() {
1384
+ this.disabled || this.onPress?.();
1385
+ }
1386
+ };
1387
+ function textButton(ui, options) {
1388
+ return new TextButton(ui, options);
1389
+ }
1390
+ var Toggle = class {
1391
+ constructor(ui, options) {
1392
+ this.on = options.value ?? false, this.onChange = options.onChange ?? null, this.root = ui.box(ui.props(s3.row, options.style)), this.root.append(label(ui, options.label, "body", sheet.text)), this.tracks = [ui.props(s3.track), ui.props(s3.track, s3.trackOn)], this.knobs = [ui.props(s3.knob), ui.props(s3.knob, s3.knobOn)], this.track = ui.box(this.tracks[this.on ? 1 : 0]), this.knob = ui.box(this.knobs[this.on ? 1 : 0]), this.track.transition(["fill"], { duration: (0.18) }), this.knob.transition(["translate_x", "scale_x", "scale_y"], { duration: (0.18), easing: "back_out" }), this.track.append(this.knob), this.root.append(this.track), this.root.on("tap", () => this.activate()), this.a11y = new A11y({ role: "button", label: options.label, value: this.on ? "On" : "Off", selected: this.on, disabled: options.disabled === true, actions: ["activate"] }), this.a11y.apply(this.root), options.scope?.add(this);
1393
+ }
1394
+ get value() {
1395
+ return this.on;
1396
+ }
1397
+ set(value, notify = false) {
1398
+ if (value === this.on) return;
1399
+ this.on = value;
1400
+ let index = value ? 1 : 0;
1401
+ this.track.style(this.tracks[index]), this.knob.style(this.knobs[index]), this.a11y.options.value = value ? "On" : "Off", this.a11y.options.selected = value, this.a11y.apply(this.root), notify && this.onChange?.(value);
1402
+ }
1403
+ setDisabled(disabled) {
1404
+ this.a11y.options.disabled !== disabled && (this.a11y.options.disabled = disabled, this.a11y.apply(this.root));
1405
+ }
1406
+ activate() {
1407
+ this.a11y.options.disabled !== true && this.set(!this.on, true);
1408
+ }
1409
+ };
1410
+ function toggle(ui, options) {
1411
+ return new Toggle(ui, options);
1412
+ }
1413
+ var Slider = class {
1414
+ constructor(ui, options) {
1415
+ this.ui = ui;
1416
+ this.index = -1;
1417
+ this.dragFrom = 0;
1418
+ this.travel = new Float64Array(1);
1419
+ this.min = options.min ?? 0, this.max = options.max ?? 1, this.step = options.step ?? (this.max - this.min) / (100), this.width = options.width ?? (220), this.onChange = options.onChange ?? null, this.steps = Math.max(1, Math.round((this.max - this.min) / this.step));
1420
+ let format = options.format ?? ((value) => percentLabel(value, this.min, this.max));
1421
+ this.texts = this.steps < (1001) ? Array.from({ length: this.steps + 1 }, (_, i) => format(this.min + i * this.step)) : null, this.root = ui.box(ui.props(s3.slider, { width: this.width }, options.style));
1422
+ let header = ui.box(s3.header);
1423
+ header.append(label(ui, options.label, "body", sheet.text)), this.readout = label(ui, "", "mono", sheet.small, sheet.strong), header.append(this.readout), this.rail = ui.box(s3.rail), this.rail.append(ui.box(s3.railLine)), this.fill = ui.box(), this.thumb = ui.box(), this.rail.append(this.fill).append(this.thumb), this.root.append(header).append(this.rail), this.rail.on("drag_start", () => {
1424
+ this.dragFrom = this.index, this.travel[0] = 0;
1425
+ }), this.rail.on("drag_move", (event) => {
1426
+ let travel = this.travel;
1427
+ travel[0] += event.dx, this.select(this.dragFrom + Math.round(travel[0] / this.width * this.steps), true);
1428
+ }), this.root.on("action", (event) => {
1429
+ event.value === UiAction.increment ? this.nudge(1) : event.value === UiAction.decrement && this.nudge(-1);
1430
+ }), this.a11y = new A11y({ role: "adjustable", label: options.label, disabled: options.disabled === true, actions: ["increment", "decrement"] }), this.set(options.value ?? this.min), options.scope?.add(this);
1431
+ }
1432
+ get value() {
1433
+ return clamp(this.min + this.index * this.step, this.min, this.max);
1434
+ }
1435
+ set(value, notify = false) {
1436
+ this.select(Math.round((clamp(value, this.min, this.max) - this.min) / this.step), notify);
1437
+ }
1438
+ select(step, notify = false) {
1439
+ let next = step < 0 ? 0 : step > this.steps ? this.steps : step;
1440
+ if (next === this.index) return;
1441
+ this.index = next;
1442
+ let ui = this.ui;
1443
+ SLOTS[0] = next * (100) / this.steps, this.fill.style(ui.props(s3.railFill, s3.fillTo.setSlotsFrom(SLOTS))), this.thumb.style(ui.props(s3.thumb, s3.thumbAt.setSlotsFrom(SLOTS)));
1444
+ let text = this.texts === null ? PERCENT_TEXT[Math.round(next * (100) / this.steps)] : this.texts[next];
1445
+ this.readout.text(text), this.a11y.options.value = text, this.a11y.apply(this.root), notify && this.onChange?.(this.value);
1446
+ }
1447
+ nudge(direction) {
1448
+ this.a11y.options.disabled !== true && this.select(this.index + direction, true);
1449
+ }
1450
+ setDisabled(disabled) {
1451
+ this.a11y.options.disabled !== disabled && (this.a11y.options.disabled = disabled, this.a11y.apply(this.root));
1452
+ }
1453
+ move(move) {
1454
+ if (move === "left") this.nudge(-1);
1455
+ else if (move === "right") this.nudge(1);
1456
+ else return false;
1457
+ return true;
1458
+ }
1459
+ };
1460
+ function percentLabel(value, min, max) {
1461
+ let percent = max > min ? Math.round((value - min) / (max - min) * (100)) : 0;
1462
+ return PERCENT_TEXT[clamp(percent, 0, (100))];
1463
+ }
1464
+ function slider(ui, options) {
1465
+ return new Slider(ui, options);
1466
+ }
1467
+ var DropdownOption = class {
1468
+ constructor(ui, owner, index, value) {
1469
+ this.owner = owner;
1470
+ this.index = index;
1471
+ this.root = ui.box(owner.optionProps[0]), this.text = label(ui, value, "body", sheet.text), this.root.append(this.text), this.root.on("tap", () => this.activate()), this.a11y = new A11y({ role: "button", label: value, selected: false, actions: ["activate"] }), this.a11y.apply(this.root);
1472
+ }
1473
+ mark(selected) {
1474
+ this.root.style(this.owner.optionProps[selected ? 1 : 0]), this.text.style(this.owner.optionText[selected ? 1 : 0]), this.a11y.options.selected = selected, this.a11y.apply(this.root);
1475
+ }
1476
+ activate() {
1477
+ this.owner.choose(this.index, true);
1478
+ }
1479
+ }, Dropdown = class {
1480
+ constructor(ui, options) {
1481
+ this.options = options;
1482
+ this.chosen = -1;
1483
+ this.shown = false;
1484
+ this.onChange = options.onChange ?? null, this.navigator = options.navigator ?? null, this.optionProps = [ui.props(s3.option), ui.props(s3.option, s3.optionOn)];
1485
+ let body = fontStyle(ui, "body");
1486
+ this.optionText = [ui.props(body, sheet.text), ui.props(body, sheet.text, s3.onPrimary)], this.popups = [ui.props(s3.popup), ui.props(s3.popup, sheet.shown)], this.chevrons = [ui.props(s3.chevron), ui.props(s3.chevron, s3.chevronOpen)], this.root = ui.box(ui.props(s3.dropdown, { width: options.width ?? (200) }, options.style)), this.root.append(label(ui, options.label, "body", sheet.small)), this.field = ui.box(ui.props(s3.button, s3.field)), this.field.transition(["scale_x", "scale_y"], { duration: (0.12), easing: "back_out" }), this.current = label(ui, "", "body", s3.label), this.chevron = ui.box(this.chevrons[0]), this.chevron.transition(["rotate"], { duration: (0.18) }), this.field.append(this.current).append(this.chevron), this.popup = ui.box(this.popups[0]), this.scope = new UiFocusScope(1, () => (this.close(), true));
1487
+ let items = [];
1488
+ for (let i = 0; i < options.options.length; i++) {
1489
+ let item = new DropdownOption(ui, this, i, options.options[i]);
1490
+ this.popup.append(item.root), this.scope.add(item), items.push(item);
1491
+ }
1492
+ this.items = items, this.root.append(this.field).append(this.popup), this.field.on("tap", () => this.activate()), this.a11y = new A11y({ role: "button", label: options.label, value: "", disabled: options.disabled === true, actions: ["activate"] }), this.choose(options.selected ?? 0, false), this.popupA11y = new A11y({ role: "group", label: options.label, hidden: true, modal: false }), this.popupA11y.apply(this.popup), options.scope?.add(this);
1493
+ }
1494
+ get focusNode() {
1495
+ return this.field;
1496
+ }
1497
+ get selected() {
1498
+ return this.chosen;
1499
+ }
1500
+ get open() {
1501
+ return this.shown;
1502
+ }
1503
+ choose(index, notify) {
1504
+ let next = clamp(index, 0, this.items.length - 1);
1505
+ if (next !== this.chosen) {
1506
+ this.chosen >= 0 && this.items[this.chosen].mark(false), this.chosen = next, this.items[next].mark(true);
1507
+ let value = this.options.options[next];
1508
+ this.current.text(value), this.a11y.options.value = value, this.a11y.apply(this.field), notify && this.onChange?.(next);
1509
+ }
1510
+ notify && this.close();
1511
+ }
1512
+ activate() {
1513
+ this.a11y.options.disabled !== true && (this.shown ? this.close() : this.show());
1514
+ }
1515
+ show() {
1516
+ this.shown || (this.shown = true, this.popup.style(this.popups[1]), this.chevron.style(this.chevrons[1]), this.popupA11y.options.hidden = false, this.popupA11y.options.modal = true, this.popupA11y.apply(this.popup), this.scope.current = this.chosen, this.navigator?.push(this.scope));
1517
+ }
1518
+ close() {
1519
+ this.shown && (this.shown = false, this.popup.style(this.popups[0]), this.chevron.style(this.chevrons[0]), this.popupA11y.options.hidden = true, this.popupA11y.options.modal = false, this.popupA11y.apply(this.popup), this.navigator?.pop(this.scope));
1520
+ }
1521
+ setDisabled(disabled) {
1522
+ this.a11y.options.disabled !== disabled && (disabled && this.close(), this.a11y.options.disabled = disabled, this.a11y.apply(this.field));
1523
+ }
1524
+ move(move) {
1525
+ return this.shown || move !== "left" && move !== "right" ? false : (this.choose(this.chosen + (move === "left" ? -1 : 1), true), true);
1526
+ }
1527
+ };
1528
+ function dropdown(ui, options) {
1529
+ return new Dropdown(ui, options);
1530
+ }
1531
+
1532
+ // src/interactives/game-ui/widgets/hud.ts
1533
+ var PULSE_SECONDS = 0.16, REMAIN = 0, PULSE = 1, TAU = Math.PI * 2, MINIMAP = 160, MARKER = 8, MARKER_KINDS = 4, NEEDLE_WIDTH = 4, NEEDLE_HEIGHT = 14, PLAYER = 10, RADIAL_RADIUS = 96, RADIAL_ITEM = 56, RADIAL_CENTER = 76, RADIAL_DEAD_ZONE = 18, RADIAL_ICON = 28, DIRECTION_SCALE = 1024, TRAVEL_SHIFT2 = 4, TRAVEL_SCALE2 = 1 << (4), DAMAGE_WIDTH = 120, HALF_DAMAGE_WIDTH = (120) / 2, DAMAGE_SECONDS = 0.9, DAMAGE_RISE = 56, DAMAGE_POP = 1.35, DAMAGE_Z = 700, DAMAGE_KINDS = 4, POP_SPEED = 4, CONFIG_SECONDS = 0, CONFIG_RISE = 1, BADGE = 20, BADGE_DOT = 10, BADGE_MAX = 99, BADGE_OFFSET = -6, s4 = styles({
1534
+ timer: {
1535
+ direction: "row",
1536
+ alignItems: "center",
1537
+ gap: kitVars.gapSmall,
1538
+ padding: [kitVars.gapSmall, kitVars.gap, kitVars.gapSmall, kitVars.gap],
1539
+ radius: kitVars.radius,
1540
+ fill: tokens.surface,
1541
+ borderWidth: kitVars.borderWidth,
1542
+ borderColor: tokens.border,
1543
+ scale: 1
1544
+ },
1545
+ timerWarn: { fill: tokens.danger, borderColor: tokens.danger },
1546
+ timerPulse: { scale: 1.12 },
1547
+ timerText: { fontSize: kitVars.title, fontWeight: 800, textColor: tokens.text, pointerEvents: "none" },
1548
+ timerTextWarn: { textColor: kitVars.onDanger },
1549
+ map: { position: "relative", clip: true, fill: tokens.surface, borderWidth: 3, borderColor: tokens.border, shadow: { color: kitVars.shadow, y: 4, blur: 12 } },
1550
+ mapImage: { position: "absolute", left: 0, top: 0, pointerEvents: "none" },
1551
+ pan: { translate: [0, 0] },
1552
+ marker: { position: "absolute", left: "50%", top: "50%", width: (8), height: (8), marginLeft: -(8) / 2, marginTop: -(8) / 2, radius: (8) / 2, borderWidth: 1, borderColor: tokens.surface, pointerEvents: "none", hidden: true },
1553
+ markerShown: { hidden: false },
1554
+ markerAt: { translate: [0, 0] },
1555
+ markerAccent: { fill: tokens.accent },
1556
+ markerDanger: { fill: tokens.danger },
1557
+ markerSuccess: { fill: tokens.success },
1558
+ markerGold: { fill: tokens.gold },
1559
+ player: { position: "absolute", left: "50%", top: "50%", width: (10), height: (10), marginLeft: -(10) / 2, marginTop: -(10) / 2, radius: (10) / 2, fill: tokens.text, borderWidth: 2, borderColor: tokens.accent, pointerEvents: "none" },
1560
+ needle: { position: "absolute", left: "50%", top: "50%", width: (4), height: (14), marginLeft: -(4) / 2, marginTop: -(14), radius: (4) / 2, fill: tokens.accent, origin: [0.5, 1], pointerEvents: "none" },
1561
+ heading: { rotate: 0 },
1562
+ compass: { position: "absolute", top: 4, left: 0, right: 0, textAlign: "center", fontSize: kitVars.small, fontWeight: 800, textColor: tokens.text, pointerEvents: "none" },
1563
+ radial: { position: "relative", alignItems: "center", justify: "center", scale: 0.6, opacity: 0, hidden: true },
1564
+ radialOpen: { scale: 1, opacity: 1, hidden: false },
1565
+ radialItem: {
1566
+ position: "absolute",
1567
+ left: "50%",
1568
+ top: "50%",
1569
+ width: (56),
1570
+ height: (56),
1571
+ marginLeft: -(56) / 2,
1572
+ marginTop: -(56) / 2,
1573
+ radius: (56) / 2,
1574
+ alignItems: "center",
1575
+ justify: "center",
1576
+ fill: tokens.raised,
1577
+ borderWidth: kitVars.focusWidth,
1578
+ borderColor: tokens.border,
1579
+ scale: 1
1580
+ },
1581
+ radialItemOn: { fill: tokens.accent, borderColor: kitVars.focus, scale: 1.15 },
1582
+ radialIcon: { width: (28), height: (28), pointerEvents: "none" },
1583
+ radialCenter: { width: (76), height: (76), radius: (76) / 2, alignItems: "center", justify: "center", padding: kitVars.gapSmall, fill: tokens.surface, borderWidth: kitVars.borderWidth, borderColor: tokens.border, pointerEvents: "none" },
1584
+ damage: { position: "absolute", left: 0, top: 0, width: (120), textAlign: "center", fontSize: kitVars.title, fontWeight: 800, textColor: tokens.text, pointerEvents: "none", hidden: true },
1585
+ damageShown: { hidden: false },
1586
+ damageCrit: { textColor: tokens.gold, fontSize: kitVars.display },
1587
+ damageHeal: { textColor: tokens.success },
1588
+ damageMiss: { textColor: tokens.muted },
1589
+ float: { translate: [0, 0], opacity: 1, scale: 1 },
1590
+ badge: {
1591
+ position: "absolute",
1592
+ top: (-6),
1593
+ right: (-6),
1594
+ minWidth: (20),
1595
+ height: (20),
1596
+ padding: [0, 5, 0, 5],
1597
+ radius: (20) / 2,
1598
+ alignItems: "center",
1599
+ justify: "center",
1600
+ fill: tokens.danger,
1601
+ borderWidth: 2,
1602
+ borderColor: tokens.surface,
1603
+ pointerEvents: "none",
1604
+ scale: 1
1605
+ },
1606
+ badgeDot: { minWidth: (10), width: (10), height: (10), padding: 0, top: -2, right: -2 },
1607
+ badgeBump: { scale: 1.3 },
1608
+ badgeText: { fontSize: 11, fontWeight: 800, textColor: kitVars.onDanger, pointerEvents: "none" }
1609
+ }, {
1610
+ pan: slotWords({ translate: [slot(0), slot(1)] }),
1611
+ markerAt: slotWords({ translate: [slot(0), slot(1)] }),
1612
+ heading: slotWords({ rotate: slot(0) }),
1613
+ float: slotWords({ translate: [slot(0), slot(1)], opacity: slot(2), scale: slot(3) })
1614
+ }), Countdown = class {
1615
+ constructor(ui, options) {
1616
+ this.ui = ui;
1617
+ this.clock = new Float64Array(2);
1618
+ this.shown = -1;
1619
+ this.warned = false;
1620
+ this.mode = options.mode ?? "down", this.warnAt = options.warnAt ?? 0, this.onExpire = options.onExpire ?? null, this.clock[(0)] = this.mode === "down" ? options.seconds : 0, this.active = options.autostart ?? true, this.roots = [ui.props(s4.timer, options.style), ui.props(s4.timer, options.style, s4.timerWarn), ui.props(s4.timer, options.style, s4.timerWarn, s4.timerPulse)];
1621
+ let mono = fontStyle(ui, "mono");
1622
+ this.texts = [ui.props(mono, s4.timerText), ui.props(mono, s4.timerText, s4.timerTextWarn)], this.root = ui.box(this.roots[0]), this.root.transition(["scale_x", "scale_y", "fill"], { duration: (0.16), easing: "back_out" }), this.text = ui.text("", this.texts[0]), this.root.append(this.text), this.root.accessibility({ role: "text", label: options.label ?? "Timer" }), this.render();
1623
+ }
1624
+ get remaining() {
1625
+ return this.clock[(0)];
1626
+ }
1627
+ get running() {
1628
+ return this.active;
1629
+ }
1630
+ get warning() {
1631
+ return this.warned;
1632
+ }
1633
+ start(seconds) {
1634
+ this.clock[(0)] = this.mode === "down" ? seconds : 0, this.active = true, this.render();
1635
+ }
1636
+ pause() {
1637
+ this.active = false;
1638
+ }
1639
+ resume() {
1640
+ this.active = true;
1641
+ }
1642
+ add(seconds) {
1643
+ let c = this.clock;
1644
+ c[(0)] = Math.max(0, c[(0)] + seconds), this.render();
1645
+ }
1646
+ update(frame) {
1647
+ let dt = frame[1], c = this.clock;
1648
+ if (c[(1)] > 0 && (c[(1)] -= dt, c[(1)] <= 0 && this.root.style(this.roots[this.warned ? 1 : 0])), !!this.active) {
1649
+ if (this.mode === "up") c[(0)] += dt;
1650
+ else if (c[(0)] -= dt, c[(0)] <= 0) {
1651
+ c[(0)] = 0, this.active = false, this.render(), this.onExpire?.();
1652
+ return;
1653
+ }
1654
+ this.render();
1655
+ }
1656
+ }
1657
+ render() {
1658
+ let c = this.clock, truncated = c[(0)] | 0, whole = this.mode === "down" && truncated < c[(0)] ? truncated + 1 : truncated;
1659
+ if (whole === this.shown) return;
1660
+ this.shown = whole, this.text.number(whole, TIMER);
1661
+ let warn = this.mode === "down" && this.warnAt > 0 && c[(0)] <= this.warnAt && c[(0)] > 0;
1662
+ warn !== this.warned && (this.warned = warn, this.text.style(this.texts[warn ? 1 : 0])), warn ? (this.root.style(this.roots[2]), c[(1)] = (0.16)) : this.root.style(this.roots[0]);
1663
+ }
1664
+ };
1665
+ function countdown(ui, options) {
1666
+ return new Countdown(ui, options);
1667
+ }
1668
+ var MAP_PAN_X = 0, MAP_PAN_Y = 1, MAP_HEADING = 2, MARKER_INDEX = { accent: 0, danger: 1, success: 2, gold: 3 }, Minimap = class {
1669
+ constructor(ui, options) {
1670
+ this.ui = ui;
1671
+ this.view = new Float64Array(3);
1672
+ this.size = options.size ?? (160);
1673
+ let map = options.mapSize ?? [this.size, this.size], radius = (options.shape ?? "circle") === "circle" ? this.size / 2 : 12;
1674
+ this.root = ui.box(ui.props(s4.map, { width: this.size, height: this.size, radius }, options.style)), this.imageBase = ui.props(s4.mapImage, { width: map[0], height: map[1] }), SLOTS[0] = 0, SLOTS[1] = 0, this.image = ui.image(options.asset, options.natural, ui.props(this.imageBase, s4.pan.setSlotsFrom(SLOTS))), this.root.append(this.image);
1675
+ let kindStates = [s4.markerAccent, s4.markerDanger, s4.markerSuccess, s4.markerGold], states = [];
1676
+ for (let i = 0; i < (4); i++) states.push(ui.props(s4.marker, kindStates[i], s4.markerShown));
1677
+ this.markerStates = states, this.hiddenMarker = ui.props(s4.marker);
1678
+ let count2 = options.markers ?? 8;
1679
+ this.kinds = new Int8Array(count2).fill(-1), this.shown = new Uint8Array(count2), this.points = new Float64Array(count2 * 2);
1680
+ let markers = [];
1681
+ for (let i = 0; i < count2; i++) {
1682
+ let marker = ui.box(this.hiddenMarker);
1683
+ this.root.append(marker), markers.push(marker);
1684
+ }
1685
+ this.markers = markers, this.needle = ui.box(ui.props(s4.needle, s4.heading.setSlotsFrom(SLOTS))), this.root.append(this.needle).append(ui.box(s4.player)), (options.compass ?? true) && this.root.append(label(ui, "N", "display", s4.compass)), this.root.accessibility({ role: "image", label: options.label ?? "Minimap" });
1686
+ }
1687
+ setImage(asset, width, height) {
1688
+ this.image.image(asset, width, height);
1689
+ }
1690
+ pan(x, y) {
1691
+ this.view[(0)] = x, this.view[(1)] = y, this.writePan();
1692
+ }
1693
+ heading(radians) {
1694
+ this.view[(2)] = radians, this.writeHeading();
1695
+ }
1696
+ marker(index, x, y, kind = "accent") {
1697
+ this.points[index * 2] = x, this.points[index * 2 + 1] = y, this.kinds[index] = MARKER_INDEX[kind], this.place(index);
1698
+ }
1699
+ setMarkerKind(index, kind) {
1700
+ this.kinds[index] = MARKER_INDEX[kind];
1701
+ }
1702
+ hideMarker(index) {
1703
+ this.kinds[index] = -1, this.place(index);
1704
+ }
1705
+ apply() {
1706
+ this.writePan(), this.writeHeading();
1707
+ for (let i = 0; i < this.markers.length; i++) this.place(i);
1708
+ }
1709
+ writePan() {
1710
+ SLOTS[0] = this.view[(0)], SLOTS[1] = this.view[(1)], this.image.style(this.ui.props(this.imageBase, s4.pan.setSlotsFrom(SLOTS)));
1711
+ }
1712
+ writeHeading() {
1713
+ SLOTS[0] = this.view[(2)], this.needle.style(this.ui.props(s4.needle, s4.heading.setSlotsFrom(SLOTS)));
1714
+ }
1715
+ place(index) {
1716
+ let half = this.size * (0.5), x = this.points[index * 2], y = this.points[index * 2 + 1], k = this.kinds[index];
1717
+ if (k < 0 || x < -half || x > half || y < -half || y > half) {
1718
+ if (this.shown[index] === 0) return;
1719
+ this.shown[index] = 0, this.markers[index].style(this.hiddenMarker);
1720
+ return;
1721
+ }
1722
+ this.shown[index] = 1, SLOTS[0] = x, SLOTS[1] = y, this.markers[index].style(this.ui.props(this.markerStates[k], s4.markerAt.setSlotsFrom(SLOTS)));
1723
+ }
1724
+ };
1725
+ function minimap(ui, options) {
1726
+ return new Minimap(ui, options);
1727
+ }
1728
+ var RadialMenu = class {
1729
+ constructor(ui, options) {
1730
+ this.ui = ui;
1731
+ this.chosen = -1;
1732
+ this.shown = false;
1733
+ this.travel = new Int32Array(2);
1734
+ this.onSelect = options.onSelect ?? null, this.deadZone = options.deadZone ?? (18), this.directions = new Int32Array(options.items.length * 2);
1735
+ let radius = options.radius ?? (96), span = radius * 2 + (56), sized = { width: span, height: span };
1736
+ this.states = [ui.props(s4.radial, sized), ui.props(s4.radial, sized, s4.radialOpen)], this.root = ui.box(this.states[0]), this.root.transition(["scale_x", "scale_y", "opacity"], { duration: (0.18), easing: "back_out" });
1737
+ let count2 = options.items.length, items = [], itemStates = [], labels = [];
1738
+ for (let i = 0; i < count2; i++) {
1739
+ let angle = -Math.PI / 2 + i / count2 * TAU;
1740
+ this.directions[i * 2] = Math.round(Math.cos(angle) * (1024)), this.directions[i * 2 + 1] = Math.round(Math.sin(angle) * (1024));
1741
+ let at = { translate: [Math.cos(angle) * radius, Math.sin(angle) * radius] }, pair = [ui.props(s4.radialItem, at), ui.props(s4.radialItem, at, s4.radialItemOn)], item = ui.box(pair[0]);
1742
+ item.transition(["scale_x", "scale_y", "fill"], { duration: (0.12), easing: "back_out" });
1743
+ let entry = options.items[i];
1744
+ entry.icon !== void 0 ? item.append(ui.image(entry.icon, entry.natural ?? [(28), (28)], s4.radialIcon)) : item.append(label(ui, entry.label.slice(0, 2), "display", sheet.text, sheet.strong)), item.on("tap", () => {
1745
+ this.select(i), this.confirm();
1746
+ }), item.accessibility({ role: "button", label: entry.label, actions: ["activate"] }), this.root.append(item), items.push(item), itemStates.push(pair), labels.push(entry.label);
1747
+ }
1748
+ this.items = items, this.itemStates = itemStates, this.labels = labels;
1749
+ let hub = ui.box(s4.radialCenter);
1750
+ this.center = label(ui, "", "body", sheet.small, sheet.center, sheet.wrap), hub.append(this.center), this.root.append(hub), this.root.on("drag_start", () => {
1751
+ this.travel[0] = 0, this.travel[1] = 0;
1752
+ }), this.root.on("drag_move", (event) => {
1753
+ this.travel[0] += event.dx * TRAVEL_SCALE2 | 0, this.travel[1] += event.dy * TRAVEL_SCALE2 | 0, this.aim();
1754
+ }), this.root.on("drag_end", () => this.confirm()), this.a11y = new A11y({ role: "group", label: options.label ?? "Radial menu", hidden: true }), this.a11y.apply(this.root), options.scope?.add(this);
1755
+ }
1756
+ get open() {
1757
+ return this.shown;
1758
+ }
1759
+ get selected() {
1760
+ return this.chosen;
1761
+ }
1762
+ show() {
1763
+ this.shown || (this.shown = true, this.root.style(this.states[1]), this.a11y.options.hidden = false, this.a11y.apply(this.root));
1764
+ }
1765
+ hide() {
1766
+ this.shown && (this.shown = false, this.select(-1), this.root.style(this.states[0]), this.a11y.options.hidden = true, this.a11y.apply(this.root));
1767
+ }
1768
+ point(dx, dy) {
1769
+ this.travel[0] = dx * TRAVEL_SCALE2 | 0, this.travel[1] = dy * TRAVEL_SCALE2 | 0, this.aim();
1770
+ }
1771
+ aim() {
1772
+ let x = this.travel[0] >> (4), y = this.travel[1] >> (4);
1773
+ if (x * x + y * y < this.deadZone * this.deadZone) {
1774
+ this.select(-1);
1775
+ return;
1776
+ }
1777
+ let directions = this.directions, best = 0, score = x * directions[0] + y * directions[1];
1778
+ for (let i = 1; i < this.items.length; i++) {
1779
+ let next = x * directions[i * 2] + y * directions[i * 2 + 1];
1780
+ next > score && (score = next, best = i);
1781
+ }
1782
+ this.select(best);
1783
+ }
1784
+ select(index) {
1785
+ index !== this.chosen && (this.chosen >= 0 && this.items[this.chosen].style(this.itemStates[this.chosen][0]), this.chosen = index, index >= 0 ? (this.items[index].style(this.itemStates[index][1]), this.center.text(this.labels[index])) : this.center.text(""));
1786
+ }
1787
+ confirm() {
1788
+ let index = this.chosen;
1789
+ return this.hide(), index >= 0 && this.onSelect?.(index), index;
1790
+ }
1791
+ activate() {
1792
+ this.shown ? this.confirm() : this.show();
1793
+ }
1794
+ move(move) {
1795
+ if (!this.shown) return false;
1796
+ let count2 = this.items.length;
1797
+ if (move === "left" || move === "previous") this.select(((this.chosen < 0 ? 0 : this.chosen) - 1 + count2) % count2);
1798
+ else if (move === "right" || move === "next") this.select(((this.chosen < 0 ? -1 : this.chosen) + 1) % count2);
1799
+ else return false;
1800
+ return true;
1801
+ }
1802
+ };
1803
+ function radialMenu(ui, options) {
1804
+ return new RadialMenu(ui, options);
1805
+ }
1806
+ var DAMAGE_INDEX = { hit: 0, crit: 1, heal: 2, miss: 3 }, DamageNumbers = class {
1807
+ constructor(ui, options = {}) {
1808
+ this.ui = ui;
1809
+ this.config = new Float64Array(2);
1810
+ this.cursor = 0;
1811
+ this.live = 0;
1812
+ let capacity = options.capacity ?? 24;
1813
+ this.config[(0)] = options.seconds ?? (0.9), this.config[(1)] = options.rise ?? (56), this.x = new Float32Array(capacity), this.y = new Float32Array(capacity), this.age = new Float32Array(capacity), this.kind = new Int8Array(capacity).fill(-1);
1814
+ let display = fontStyle(ui, "display"), kinds = [null, s4.damageCrit, s4.damageHeal, s4.damageMiss], states = [];
1815
+ for (let i = 0; i < (4); i++) states.push(ui.props(display, s4.damage, kinds[i], s4.damageShown));
1816
+ this.states = states, this.hidden = ui.props(display, s4.damage), this.root = ui.box(sheet.layer);
1817
+ let entries = [];
1818
+ for (let i = 0; i < capacity; i++) {
1819
+ let entry = ui.text("", this.hidden);
1820
+ this.root.append(entry), entries.push(entry);
1821
+ }
1822
+ this.entries = entries;
1823
+ let rooting = { anchor: "fill", safe_area: false, z: options.z ?? (700) };
1824
+ ui.root(this.root, rooting), this.root.accessibility({ role: "none", hidden: true });
1825
+ }
1826
+ get active() {
1827
+ return this.live;
1828
+ }
1829
+ spawn(value, x, y, kind = "hit") {
1830
+ let i = this.cursor;
1831
+ this.cursor = (i + 1) % this.entries.length, this.kind[i] < 0 && this.live++;
1832
+ let k = DAMAGE_INDEX[kind];
1833
+ this.kind[i] = k, this.x[i] = x - HALF_DAMAGE_WIDTH, this.y[i] = y, this.age[i] = 0;
1834
+ let entry = this.entries[i];
1835
+ entry.number(value, PLAIN), SLOTS[0] = x - HALF_DAMAGE_WIDTH, SLOTS[1] = y, SLOTS[2] = 1, SLOTS[3] = k === 1 ? (1.35) : 1, entry.style(this.ui.props(this.states[k], s4.float.setSlotsFrom(SLOTS)));
1836
+ }
1837
+ update(frame) {
1838
+ if (this.live === 0) return;
1839
+ let dt = frame[1], ui = this.ui, config = this.config;
1840
+ for (let i = 0; i < this.entries.length; i++) {
1841
+ let k = this.kind[i];
1842
+ if (k < 0) continue;
1843
+ let age = this.age[i] + dt;
1844
+ if (age >= config[(0)]) {
1845
+ this.kind[i] = -1, this.live--, this.entries[i].style(this.hidden);
1846
+ continue;
1847
+ }
1848
+ this.age[i] = age;
1849
+ let p = age / config[(0)], rest = 1 - p, pop = 1 - p * (4);
1850
+ SLOTS[0] = this.x[i], SLOTS[1] = this.y[i] - config[(1)] * (1 - rest * rest), SLOTS[2] = 1 - p * p * p, SLOTS[3] = k === 1 && pop > 0 ? 1 + ((1.35) - 1) * pop : 1, this.entries[i].style(ui.props(this.states[k], s4.float.setSlotsFrom(SLOTS)));
1851
+ }
1852
+ }
1853
+ clear() {
1854
+ for (let i = 0; i < this.entries.length; i++)
1855
+ this.kind[i] < 0 || (this.kind[i] = -1, this.entries[i].style(this.hidden));
1856
+ this.live = 0;
1857
+ }
1858
+ };
1859
+ function damageNumbers(ui, options = {}) {
1860
+ return new DamageNumbers(ui, options);
1861
+ }
1862
+ var Badge = class {
1863
+ constructor(ui, options) {
1864
+ this.ui = ui;
1865
+ this.current = -1;
1866
+ this.clock = new Float64Array(1);
1867
+ this.a11y = new A11y({ role: "text", label: "", hidden: true });
1868
+ this.max = options.max ?? (99), this.dot = options.dot ?? false, this.overflow = `${this.max}+`;
1869
+ let noun = options.label ?? "new";
1870
+ this.labels = Array.from({ length: this.max + 2 }, (_, i) => i > this.max ? `${this.max}+ ${noun}` : `${i} ${noun}`);
1871
+ let shape = this.dot ? s4.badgeDot : null;
1872
+ this.states = [ui.props(s4.badge, shape, sheet.hidden), ui.props(s4.badge, shape), ui.props(s4.badge, shape, s4.badgeBump)], this.root = ui.box(this.states[0]), this.root.transition(["scale_x", "scale_y"], { duration: (0.16), easing: "back_out" }), this.text = label(ui, "", "mono", s4.badgeText, this.dot ? sheet.hidden : null), this.root.append(this.text), options.host.append(this.root), this.set(options.count ?? 0);
1873
+ }
1874
+ get count() {
1875
+ return this.current;
1876
+ }
1877
+ set(count2) {
1878
+ let next = Math.max(0, Math.floor(count2));
1879
+ if (next === this.current) return;
1880
+ let grew = next > this.current && this.current >= 0;
1881
+ this.current = next, this.dot || (next > this.max ? this.text.text(this.overflow) : this.text.number(next, PLAIN)), this.a11y.options.label = this.labels[Math.min(next, this.max + 1)], this.a11y.options.hidden = next === 0, this.a11y.apply(this.root), next === 0 ? (this.clock[0] = 0, this.root.style(this.states[0])) : grew ? (this.clock[0] = (0.16), this.root.style(this.states[2])) : this.root.style(this.states[1]);
1882
+ }
1883
+ update(frame) {
1884
+ let clock = this.clock;
1885
+ clock[0] <= 0 || (clock[0] -= frame[1], clock[0] <= 0 && this.current > 0 && this.root.style(this.states[1]));
1886
+ }
1887
+ };
1888
+ function badge(ui, options) {
1889
+ return new Badge(ui, options);
1890
+ }
1891
+
1892
+ // src/interactives/game-ui/widgets/overlay.ts
1893
+ var MODAL_Z = 800, MODAL_WIDTH = 340, ENTER_SCALE = 0.94, TOOLTIP_SECONDS = 2.5, TOOLTIP_Z = 60, ARROW = 10, TOOLTIP_MAX = 240, s5 = styles({
1894
+ layer: { width: "100%", height: "100%", alignItems: "center", justify: "center", fill: kitVars.scrim, opacity: 0, hidden: true },
1895
+ layerShown: { opacity: 1, hidden: false },
1896
+ card: {
1897
+ width: (340),
1898
+ maxWidth: "92%",
1899
+ padding: kitVars.padding,
1900
+ gap: kitVars.gap,
1901
+ fill: tokens.surface,
1902
+ radius: kitVars.radius,
1903
+ borderWidth: kitVars.borderWidth,
1904
+ borderColor: tokens.border,
1905
+ shadow: { color: kitVars.shadow, y: 12, blur: 32 },
1906
+ scale: (0.94)
1907
+ },
1908
+ cardShown: { scale: 1 },
1909
+ content: { gap: kitVars.gap, alignItems: "stretch" },
1910
+ tipAnchor: { position: "absolute", left: 0, right: 0, alignItems: "center", pointerEvents: "none", zIndex: (60), opacity: 0, hidden: true },
1911
+ above: { bottom: "100%", marginBottom: kitVars.gapSmall },
1912
+ below: { top: "100%", marginTop: kitVars.gapSmall },
1913
+ tipShown: { opacity: 1, hidden: false },
1914
+ bubble: { maxWidth: (240), padding: [kitVars.gapSmall, kitVars.gap, kitVars.gapSmall, kitVars.gap], fill: tokens.raised, radius: kitVars.radiusSmall, borderWidth: kitVars.borderWidth, borderColor: tokens.border, shadow: { color: kitVars.shadow, y: 4, blur: 12 } },
1915
+ arrow: { width: (10), height: (10), fill: tokens.raised, rotate: Math.PI / 4, marginTop: -(10) / 2, marginBottom: -(10) / 2 }
1916
+ }), Modal = class {
1917
+ constructor(ui, options = {}) {
1918
+ this.ui = ui;
1919
+ this.onClose = null;
1920
+ this.stack = null;
1921
+ this.dismissible = options.dismissible ?? true, this.layers = [ui.props(s5.layer), ui.props(s5.layer, s5.layerShown)], this.cards = [ui.props(s5.card, options.style), ui.props(s5.card, options.style, s5.cardShown)], this.layer = ui.box(this.layers[0]), this.layer.transition(["opacity"], { duration: (0.18), easing: "ease_out" }), this.root = ui.box(this.cards[0]), this.root.transition(["scale_x", "scale_y"], { duration: (0.18), easing: "back_out" }), this.title = options.title === void 0 ? null : label(ui, options.title, "display", sheet.title, sheet.center), this.title !== null && this.root.append(this.title), this.content = ui.box(s5.content), this.root.append(this.content), this.layer.append(this.root), this.scope = new UiFocusScope(options.columns ?? 1, () => this.stack?.back() ?? false), this.a11y = new A11y({ role: "group", label: options.title ?? "", hidden: true, modal: false }), this.a11y.apply(this.root);
1922
+ }
1923
+ add(target) {
1924
+ return this.scope.add(target), this;
1925
+ }
1926
+ append(element) {
1927
+ return this.content.append(element), this;
1928
+ }
1929
+ get open() {
1930
+ return this.stack !== null;
1931
+ }
1932
+ shown(on, top) {
1933
+ this.layer.style(this.layers[on ? 1 : 0]), this.root.style(this.cards[on ? 1 : 0]), this.a11y.options.hidden = !on || !top, this.a11y.options.modal = on && top, this.a11y.options.disabled = on && !top, this.a11y.apply(this.root);
1934
+ }
1935
+ };
1936
+ function modal(ui, options = {}) {
1937
+ return new Modal(ui, options);
1938
+ }
1939
+ var ModalStack = class {
1940
+ constructor(ui, options = {}) {
1941
+ this.ui = ui;
1942
+ this.modals = new StableList();
1943
+ this.rooting = { anchor: "fill", safe_area: false, z: 0 };
1944
+ this.navigator = options.navigator ?? null, this.inert = options.inert ?? [], this.z = options.z ?? (800);
1945
+ }
1946
+ get depth() {
1947
+ return this.modals.size;
1948
+ }
1949
+ get top() {
1950
+ return this.modals.size === 0 ? null : this.modals.at(this.modals.size - 1);
1951
+ }
1952
+ contains(modal2) {
1953
+ return this.modals.indexOf(modal2) >= 0;
1954
+ }
1955
+ push(modal2) {
1956
+ if (modal2.stack !== null) return;
1957
+ let below = this.top;
1958
+ if (below !== null) below.shown(true, false);
1959
+ else for (let i = 0; i < this.inert.length; i++) this.inert[i].setState("disabled", true);
1960
+ this.modals.push(modal2), modal2.stack = this, this.rooting.z = this.z + this.modals.size, this.ui.root(modal2.layer, this.rooting), modal2.shown(true, true), modal2.scope.current = -1, this.navigator?.push(modal2.scope);
1961
+ }
1962
+ pop() {
1963
+ let top = this.top;
1964
+ return top === null ? null : (this.remove(top), top);
1965
+ }
1966
+ remove(modal2) {
1967
+ let at = this.modals.indexOf(modal2);
1968
+ if (at < 0) return;
1969
+ this.modals.removeAt(at), modal2.stack = null, modal2.shown(false, false), this.ui.unroot(modal2.layer);
1970
+ let top = this.top;
1971
+ if (top !== null) top.shown(true, true);
1972
+ else for (let i = 0; i < this.inert.length; i++) this.inert[i].setState("disabled", false);
1973
+ this.navigator?.pop(modal2.scope), modal2.onClose?.();
1974
+ }
1975
+ clear() {
1976
+ for (; this.modals.size > 0; ) this.pop();
1977
+ }
1978
+ back() {
1979
+ let top = this.top;
1980
+ return top === null || !top.dismissible ? false : (this.remove(top), true);
1981
+ }
1982
+ };
1983
+ function modalStack(ui, options = {}) {
1984
+ return new ModalStack(ui, options);
1985
+ }
1986
+ var Tooltip = class {
1987
+ constructor(ui, options) {
1988
+ this.ui = ui;
1989
+ this.options = options;
1990
+ this.remaining = new Float64Array(2);
1991
+ this.pinned = false;
1992
+ this.visible = false;
1993
+ let above = (options.placement ?? "above") === "above", side = above ? s5.above : s5.below;
1994
+ this.states = [ui.props(s5.tipAnchor, side), ui.props(s5.tipAnchor, side, s5.tipShown)], this.remaining[1] = options.seconds ?? (2.5), this.root = ui.box(this.states[0]), this.root.transition(["opacity"], { duration: (0.18) }), this.bubble = ui.box(s5.bubble), this.text = label(ui, options.text, "body", sheet.small, sheet.wrap), this.bubble.append(this.text);
1995
+ let arrow = ui.box(s5.arrow);
1996
+ above ? this.root.append(this.bubble).append(arrow) : this.root.append(arrow).append(this.bubble), options.target.append(this.root), this.root.accessibility({ role: "text", label: options.text, hidden: true }), options.target.on("long_press", () => this.show()), options.navigator?.onChange((focused) => {
1997
+ focused !== null && focusNodeOf(focused) === options.target ? this.pin() : this.visible && this.pinned && this.hide();
1998
+ });
1999
+ }
2000
+ get shown() {
2001
+ return this.visible;
2002
+ }
2003
+ setText(value) {
2004
+ this.text.text(value);
2005
+ }
2006
+ show() {
2007
+ this.reveal(false);
2008
+ }
2009
+ pin() {
2010
+ this.reveal(true);
2011
+ }
2012
+ hide() {
2013
+ this.pinned = false, this.remaining[0] = 0, this.visible && (this.visible = false, this.root.style(this.states[0]));
2014
+ }
2015
+ update(frame) {
2016
+ if (!this.visible || this.pinned) return;
2017
+ let remaining = this.remaining;
2018
+ remaining[0] -= frame[1], remaining[0] <= 0 && this.hide();
2019
+ }
2020
+ reveal(pinned) {
2021
+ this.pinned = pinned, this.remaining.copyWithin(0, 1, 2), !this.visible && (this.visible = true, this.root.style(this.states[1]));
2022
+ }
2023
+ };
2024
+ function tooltip(ui, options) {
2025
+ return new Tooltip(ui, options);
2026
+ }
2027
+
2028
+ // src/interactives/game-ui/widgets/particles.ts
2029
+ var CAPACITY = 64, PARTICLE_Z = 950, CONFETTI_W = 7, CONFETTI_H = 11, SPARKLE = 10, GRAVITY = 900, DRAG = 1.6, CONFETTI_SPEED = 520, SPARKLE_SPEED = 180, CONFETTI_LIFE = 1.6, SPARKLE_LIFE = 0.8, SPIN = 12, TWINKLE = 18, PALETTE = 6, KINDS = 2, CONFETTI = 0, SPARKLE_KIND = 1, DEAD = -1, SPREAD = Math.PI * 0.7, UP = -Math.PI / 2, TAU2 = Math.PI * 2, FADE_FROM = 0.7, SEED = 20973, TABLE_ROWS = 97, F_VX = 0, F_VY = 1, F_ANGLE = 2, F_SPIN = 3, F_LIFE = 4, F_X = 5, F_Y = 6, F_AGE = 7, STRIDE = 8, s6 = styles({
2030
+ confetti: { position: "absolute", left: 0, top: 0, width: (7), height: (11), marginLeft: -(7) / 2, marginTop: -(11) / 2, radius: 1, pointerEvents: "none", hidden: false },
2031
+ sparkle: { position: "absolute", left: 0, top: 0, width: (10), height: (10), marginLeft: -(10) / 2, marginTop: -(10) / 2, radius: (10) / 2, pointerEvents: "none", hidden: false, shadow: { color: tokens.gold, blur: 6 } },
2032
+ dead: { position: "absolute", hidden: true, pointerEvents: "none" },
2033
+ c0: { fill: tokens.accent },
2034
+ c1: { fill: tokens.gold },
2035
+ c2: { fill: tokens.success },
2036
+ c3: { fill: tokens.danger },
2037
+ c4: { fill: kitVars.focus },
2038
+ c5: { fill: tokens.text },
2039
+ piece: { translate: [0, 0], rotate: 0, opacity: 1 },
2040
+ glint: { translate: [0, 0], scale: 1, opacity: 1 }
2041
+ }, {
2042
+ piece: slotWords({ translate: [slot(0), slot(1)], rotate: slot(2), opacity: slot(3) }),
2043
+ glint: slotWords({ translate: [slot(0), slot(1)], scale: slot(2), opacity: slot(3) })
2044
+ });
2045
+ function fillLaunchTable(rng, data, colors) {
2046
+ for (let kind = 0; kind < (2); kind++) {
2047
+ let confetti = kind === (0);
2048
+ for (let r = 0; r < (97); r++) {
2049
+ let row = kind * (97) + r, o = row * (8), heading = confetti ? UP + rng.range(-SPREAD, SPREAD) : rng.range(0, TAU2), speed = (confetti ? (520) : (180)) * rng.range(0.45, 1);
2050
+ data[o + (0)] = Math.cos(heading) * speed, data[o + (1)] = Math.sin(heading) * speed, data[o + (2)] = rng.range(0, TAU2), data[o + (3)] = rng.range(-(12), (12)), data[o + (4)] = (confetti ? (1.6) : (0.8)) * rng.range(0.7, 1), colors[row] = rng.next() * (6) | 0;
2051
+ }
2052
+ }
2053
+ }
2054
+ var UiParticles = class {
2055
+ constructor(ui, options = {}) {
2056
+ this.ui = ui;
2057
+ this.launchColors = new Uint8Array((97) * (2));
2058
+ this.cursor = 0;
2059
+ this.row = 0;
2060
+ this.live = 0;
2061
+ let capacity = options.capacity ?? (64);
2062
+ this.data = new Float32Array(((97) * (2) + capacity) * (8)), this.kind = new Int8Array(capacity).fill((-1)), this.color = new Uint8Array(capacity), fillLaunchTable(new Rng(options.seed ?? (20973)), this.data, this.launchColors);
2063
+ let palette = [s6.c0, s6.c1, s6.c2, s6.c3, s6.c4, s6.c5], states = [];
2064
+ for (let kind = 0; kind < (2); kind++) for (let c = 0; c < (6); c++) states.push(ui.props(kind === (0) ? s6.confetti : s6.sparkle, palette[kind === (0) ? c : 1 + (c & 1) * 4]));
2065
+ this.states = states, this.dead = ui.props(s6.dead), this.root = ui.box(sheet.layer);
2066
+ let pieces = [];
2067
+ for (let i = 0; i < capacity; i++) {
2068
+ let piece = ui.box(this.dead);
2069
+ this.root.append(piece), pieces.push(piece);
2070
+ }
2071
+ this.pieces = pieces;
2072
+ let rooting = { anchor: "fill", safe_area: false, z: options.z ?? (950) };
2073
+ ui.root(this.root, rooting), this.root.accessibility({ role: "none", hidden: true });
2074
+ }
2075
+ get active() {
2076
+ return this.live;
2077
+ }
2078
+ burst(kind, x, y, count2) {
2079
+ let confetti = kind === "confetti", data = this.data, base = confetti ? 0 : (97);
2080
+ for (let n = 0; n < count2; n++) {
2081
+ let i = this.cursor;
2082
+ this.cursor = (i + 1) % this.pieces.length, this.kind[i] === (-1) && this.live++, this.kind[i] = confetti ? (0) : (1);
2083
+ let row = base + this.row;
2084
+ this.row = (this.row + 1) % (97);
2085
+ let o = ((97) * (2) + i) * (8);
2086
+ data.copyWithin(o, row * (8), row * (8) + (8)), data[o + (5)] = x, data[o + (6)] = y, data[o + (7)] = 0, this.color[i] = this.launchColors[row], this.draw(i);
2087
+ }
2088
+ }
2089
+ update(frame) {
2090
+ if (this.live === 0) return;
2091
+ let dt = frame[1], damping = (1.6) * dt < 1 ? 1 - (1.6) * dt : 0, data = this.data;
2092
+ for (let i = 0; i < this.pieces.length; i++) {
2093
+ let kind = this.kind[i];
2094
+ if (kind === (-1)) continue;
2095
+ let o = ((97) * (2) + i) * (8), age = data[o + (7)] + dt;
2096
+ if (age >= data[o + (4)]) {
2097
+ this.kind[i] = (-1), this.live--, this.pieces[i].style(this.dead);
2098
+ continue;
2099
+ }
2100
+ data[o + (7)] = age, kind === (0) && (data[o + (1)] += (900) * dt), data[o + (0)] *= damping, data[o + (1)] *= damping, data[o + (5)] += data[o + (0)] * dt, data[o + (6)] += data[o + (1)] * dt, data[o + (2)] += data[o + (3)] * dt, this.draw(i);
2101
+ }
2102
+ }
2103
+ clear() {
2104
+ for (let i = 0; i < this.pieces.length; i++)
2105
+ this.kind[i] !== (-1) && (this.kind[i] = (-1), this.pieces[i].style(this.dead));
2106
+ this.live = 0;
2107
+ }
2108
+ draw(i) {
2109
+ let kind = this.kind[i], data = this.data, o = ((97) * (2) + i) * (8), p = data[o + (7)] / data[o + (4)], state = this.states[kind * (6) + this.color[i]];
2110
+ if (SLOTS[0] = data[o + (5)], SLOTS[1] = data[o + (6)], SLOTS[3] = p < (0.7) ? 1 : 1 - (p - (0.7)) / (1 - (0.7)), kind === (0))
2111
+ SLOTS[2] = data[o + (2)], this.pieces[i].style(this.ui.props(state, s6.piece.setSlotsFrom(SLOTS)));
2112
+ else {
2113
+ let phase = data[o + (7)] * (18) + i, wave = phase - (phase | 0);
2114
+ SLOTS[2] = (0.6 + 0.8 * (wave < 0.5 ? wave : 1 - wave)) * (1 - p * 0.5), this.pieces[i].style(this.ui.props(state, s6.glint.setSlotsFrom(SLOTS)));
2115
+ }
2116
+ }
2117
+ };
2118
+ function uiParticles(ui, options = {}) {
2119
+ return new UiParticles(ui, options);
2120
+ }
2121
+
2122
+ // src/interactives/game-ui/widgets/screens.ts
2123
+ var STAR = 30, STARS = 3, STAR_SECONDS = 0.35, SCORE_SECONDS = 1.1, REWARD_ICON = 28, REWARDS = 3, SPINNER = 44, SPINNER_SPEED = Math.PI * 2, LOADING_BAR = 260, BAR_HEIGHT = 8, TIP_SECONDS = 4, LOADING_Z = 1200, HINT_Z = 900, HINT_WIDTH = 260, HINT_DOTS = 8, DOT = 7, ARROW2 = 16, BOB = 6, BOB_SPEED = 1, SPARKLES = 10, TURN = Math.PI * 2, SPIN2 = 0, TIP = 1, TIP_SECONDS_AT = 2, HINT_X = 0, HINT_Y = 1, HINT_CLOCK = 2, CONFETTI2 = 36, s7 = styles({
2124
+ actions: { direction: "row", gap: kitVars.gap, justify: "center" },
2125
+ grow: { grow: 1, basis: 0 },
2126
+ section: { fontSize: kitVars.small, fontWeight: 800, textColor: tokens.muted, letterSpacing: 1, pointerEvents: "none" },
2127
+ score: { textAlign: "center", fontSize: kitVars.display, fontWeight: 800, textColor: tokens.gold, pointerEvents: "none" },
2128
+ stars: { direction: "row", gap: kitVars.gap, justify: "center", padding: kitVars.gapSmall },
2129
+ star: { width: (30), height: (30), radius: 4, rotate: Math.PI / 4, fill: tokens.track, scale: 0.8 },
2130
+ starOn: { fill: tokens.gold, scale: 1, shadow: { color: tokens.gold, blur: 10 } },
2131
+ rewards: { direction: "row", gap: kitVars.gap, justify: "center", wrap: true },
2132
+ reward: { direction: "row", alignItems: "center", gap: kitVars.gapSmall, padding: [kitVars.gapSmall, kitVars.gap, kitVars.gapSmall, kitVars.gapSmall], radius: kitVars.radius, fill: tokens.raised, hidden: true },
2133
+ rewardShown: { hidden: false },
2134
+ rewardIcon: { width: (28), height: (28), pointerEvents: "none" },
2135
+ loading: { width: "100%", height: "100%", alignItems: "center", justify: "center", gap: kitVars.padding, padding: kitVars.padding, fill: tokens.surface, hidden: true, opacity: 0 },
2136
+ loadingShown: { hidden: false, opacity: 1 },
2137
+ spinner: { width: (44), height: (44), radius: (44) / 2, borderWidth: 4, borderColor: [tokens.accent, tokens.track, tokens.track, tokens.track] },
2138
+ spin: { rotate: 0 },
2139
+ bar: { width: (260), height: (8), radius: (8) / 2, fill: tokens.track, clip: true },
2140
+ barFill: { height: "100%", radius: (8) / 2, fill: tokens.accent },
2141
+ barTo: { width: "0%" },
2142
+ tip: { maxWidth: (260) + 80, textAlign: "center" },
2143
+ hint: { width: "100%", height: "100%", hidden: true },
2144
+ hintShown: { hidden: false },
2145
+ bubble: { position: "absolute", width: (260), gap: kitVars.gap, padding: kitVars.padding, fill: tokens.raised, radius: kitVars.radius, borderWidth: kitVars.borderWidth, borderColor: tokens.accent, shadow: { color: kitVars.shadow, y: 6, blur: 18 } },
2146
+ bubbleAt: { left: 0, top: 0 },
2147
+ dots: { direction: "row", gap: 4, alignItems: "center" },
2148
+ dot: { width: (7), height: (7), radius: (7) / 2, fill: tokens.track },
2149
+ dotOn: { fill: tokens.accent },
2150
+ dotHidden: { hidden: true },
2151
+ footer: { direction: "row", justify: "space-between", alignItems: "center" },
2152
+ arrow: { position: "absolute", width: (16), height: (16), rotate: Math.PI / 4, fill: tokens.accent, pointerEvents: "none" },
2153
+ arrowAt: { left: 0, top: 0 }
2154
+ }, {
2155
+ spin: slotWords({ rotate: slot(0) }),
2156
+ barTo: slotWords({ width: slot(0, true) }),
2157
+ bubbleAt: slotWords({ left: slot(0), top: slot(1) }),
2158
+ arrowAt: slotWords({ left: slot(0), top: slot(1) })
2159
+ }), PauseScreen = class {
2160
+ constructor(ui, options) {
2161
+ this.options = options;
2162
+ this.modal = new Modal(ui, { title: options.title ?? "Paused" }), this.resume = new TextButton(ui, { label: "Resume", variant: "primary", scope: this.modal.scope, onPress: () => this.close() }), this.settings = new TextButton(ui, { label: "Settings", scope: this.modal.scope, onPress: () => options.onSettings?.() }), this.quit = new TextButton(ui, { label: "Quit", variant: "ghost", scope: this.modal.scope, onPress: () => options.onQuit?.() }), this.modal.append(this.resume.root).append(this.settings.root).append(this.quit.root), this.modal.onClose = () => options.onResume?.();
2163
+ }
2164
+ get open() {
2165
+ return this.modal.open;
2166
+ }
2167
+ show() {
2168
+ this.options.stack.push(this.modal);
2169
+ }
2170
+ close() {
2171
+ this.options.stack.remove(this.modal);
2172
+ }
2173
+ };
2174
+ function pauseScreen(ui, options) {
2175
+ return new PauseScreen(ui, options);
2176
+ }
2177
+ var DEFAULT_QUALITIES = ["Low", "Medium", "High"], DEFAULT_LANGUAGES = ["English", "Fran\xE7ais", "Espa\xF1ol", "Kiswahili", "Yor\xF9b\xE1", "Portugu\xEAs"], SettingsScreen = class {
2178
+ constructor(ui, options) {
2179
+ this.options = options;
2180
+ this.values = { music: 0.8, effects: 1, haptics: true, quality: 1, language: 0, ...options.values };
2181
+ let values = this.values, changed = (key) => options.onChange?.(values, key);
2182
+ this.modal = new Modal(ui, { title: "Settings" });
2183
+ let scope = this.modal.scope, nav = options.navigator;
2184
+ this.music = new Slider(ui, { label: "Music", value: values.music, step: 0.05, scope, onChange: (v) => {
2185
+ values.music = v, changed("music");
2186
+ } }), this.effects = new Slider(ui, { label: "Effects", value: values.effects, step: 0.05, scope, onChange: (v) => {
2187
+ values.effects = v, changed("effects");
2188
+ } }), this.haptics = new Toggle(ui, { label: "Haptics", value: values.haptics, scope, onChange: (v) => {
2189
+ values.haptics = v, changed("haptics");
2190
+ } }), this.quality = new Dropdown(ui, { label: "Quality", options: options.qualities ?? DEFAULT_QUALITIES, selected: values.quality, width: 280, navigator: nav, scope, onChange: (i) => {
2191
+ values.quality = i, changed("quality");
2192
+ } }), this.language = new Dropdown(ui, { label: "Language", options: options.languages ?? DEFAULT_LANGUAGES, selected: values.language, width: 280, navigator: nav, scope, onChange: (i) => {
2193
+ values.language = i, changed("language");
2194
+ } }), this.done = new TextButton(ui, { label: "Done", variant: "primary", scope, onPress: () => this.close() }), this.modal.append(label(ui, "AUDIO", "body", s7.section)).append(this.music.root).append(this.effects.root), this.modal.append(label(ui, "GAME", "body", s7.section)).append(this.haptics.root).append(this.quality.root).append(this.language.root), this.modal.append(this.done.root), this.modal.onClose = () => {
2195
+ this.quality.close(), this.language.close(), options.onDone?.(values);
2196
+ };
2197
+ }
2198
+ get open() {
2199
+ return this.modal.open;
2200
+ }
2201
+ show() {
2202
+ this.options.stack.push(this.modal);
2203
+ }
2204
+ close() {
2205
+ this.options.stack.remove(this.modal);
2206
+ }
2207
+ };
2208
+ function settingsScreen(ui, options) {
2209
+ return new SettingsScreen(ui, options);
2210
+ }
2211
+ var ResultsScreen = class {
2212
+ constructor(ui, options) {
2213
+ this.ui = ui;
2214
+ this.options = options;
2215
+ this.target = 0;
2216
+ this.shownScore = -1;
2217
+ this.earned = 0;
2218
+ this.revealed = 0;
2219
+ this.clock = new Float64Array(2);
2220
+ this.natural = options.natural ?? [(28), (28)], this.modal = new Modal(ui, { columns: 2, dismissible: false }), this.title = label(ui, "", "display", sheet.display, sheet.center), this.score = label(ui, "", "mono", s7.score), this.starStates = [ui.props(s7.star), ui.props(s7.star, s7.starOn)], this.rewardStates = [ui.props(s7.reward), ui.props(s7.reward, s7.rewardShown)];
2221
+ let stars = ui.box(s7.stars), starList = [];
2222
+ for (let i = 0; i < (3); i++) {
2223
+ let star = ui.box(this.starStates[0]);
2224
+ star.transition(["scale_x", "scale_y", "fill"], { duration: (0.18), easing: "back_out" }), stars.append(star), starList.push(star);
2225
+ }
2226
+ this.stars = starList;
2227
+ let rewards = ui.box(s7.rewards), rewardList = [], icons = [], amounts = [];
2228
+ for (let i = 0; i < (options.rewards ?? (3)); i++) {
2229
+ let chip = ui.box(this.rewardStates[0]), icon = ui.image(0, this.natural, s7.rewardIcon), amount = label(ui, "", "mono", sheet.text, sheet.strong);
2230
+ chip.append(icon).append(amount), rewards.append(chip), rewardList.push(chip), icons.push(icon), amounts.push(amount);
2231
+ }
2232
+ this.rewards = rewardList, this.rewardIcons = icons, this.rewardAmounts = amounts;
2233
+ let actions = ui.box(s7.actions);
2234
+ this.retry = new TextButton(ui, { label: "Retry", variant: "primary", style: s7.grow, scope: this.modal.scope, onPress: () => options.onRetry?.() }), this.share = new TextButton(ui, { label: "Share", style: s7.grow, scope: this.modal.scope, onPress: () => options.onShare?.() }), actions.append(this.retry.root).append(this.share.root), this.modal.append(this.title).append(stars).append(this.score).append(rewards).append(actions), this.a11y = new A11y({ role: "text", label: "", live: true });
2235
+ }
2236
+ get open() {
2237
+ return this.modal.open;
2238
+ }
2239
+ get starsShown() {
2240
+ return this.revealed;
2241
+ }
2242
+ get scoreShown() {
2243
+ return this.shownScore;
2244
+ }
2245
+ show(result) {
2246
+ this.title.text(result.victory ? "Victory!" : "Defeat"), this.a11y.options.label = result.victory ? "Victory" : "Defeat", this.a11y.apply(this.title), this.target = result.score, this.earned = clamp(Math.round(result.stars), 0, (3)), this.revealed = 0, this.clock[0] = 0, this.shownScore = -1, this.score.number(0, INTEGER);
2247
+ for (let i = 0; i < (3); i++) this.stars[i].style(this.starStates[0]);
2248
+ this.modal.open || this.options.stack.push(this.modal), result.victory && this.options.particles?.burst("confetti", this.at(0), this.at(1), (36));
2249
+ }
2250
+ setReward(index, icon, amount) {
2251
+ this.rewardIcons[index].image(icon, this.natural[0], this.natural[1]), this.rewardAmounts[index].number(amount, PLAIN), this.rewards[index].style(this.rewardStates[1]);
2252
+ }
2253
+ hideReward(index) {
2254
+ this.rewards[index].style(this.rewardStates[0]);
2255
+ }
2256
+ close() {
2257
+ this.options.stack.remove(this.modal);
2258
+ }
2259
+ update(frame) {
2260
+ if (!this.modal.open) return;
2261
+ let clock = this.clock;
2262
+ clock[0] += frame[1], clock[1] = clock[0] < (1.1) ? 1 - clock[0] / (1.1) : 0;
2263
+ let value = this.target * (1 - clock[1] * clock[1] * clock[1]) + 0.5 | 0;
2264
+ value !== this.shownScore && (this.shownScore = value, this.score.number(value, INTEGER));
2265
+ let stars = clock[0] / (0.35) | 0, due = stars < this.earned ? stars : this.earned;
2266
+ for (; this.revealed < due; )
2267
+ this.stars[this.revealed].style(this.starStates[1]), this.revealed++, this.options.particles?.burst("sparkle", this.at(0), this.at(1), (10));
2268
+ }
2269
+ at(axis) {
2270
+ return this.options.celebrateAt?.[axis] ?? 0;
2271
+ }
2272
+ };
2273
+ function resultsScreen(ui, options) {
2274
+ return new ResultsScreen(ui, options);
2275
+ }
2276
+ var LoadingScreen = class {
2277
+ constructor(ui, options = {}) {
2278
+ this.ui = ui;
2279
+ this.clock = new Float64Array(3);
2280
+ this.tipIndex = 0;
2281
+ this.shownPercent = -1;
2282
+ this.visible = false;
2283
+ this.tips = options.tips ?? [], this.clock[(2)] = options.tipSeconds ?? (4), this.states = [ui.props(s7.loading), ui.props(s7.loading, s7.loadingShown)], this.root = ui.box(this.states[0]), this.root.transition(["opacity"], { duration: (0.18) }), SLOTS[0] = 0, this.spinner = ui.box(ui.props(s7.spinner, s7.spin.setSlotsFrom(SLOTS)));
2284
+ let bar = ui.box(s7.bar);
2285
+ this.fill = ui.box(ui.props(s7.barFill, s7.barTo.setSlotsFrom(SLOTS))), bar.append(this.fill), this.percent = label(ui, "", "mono", sheet.small, sheet.strong), this.tip = label(ui, this.tips.length > 0 ? this.tips[0] : "", "body", sheet.text, sheet.muted, s7.tip), this.root.append(label(ui, options.title ?? "Loading", "display", sheet.title)), this.root.append(this.spinner).append(bar).append(this.percent).append(this.tip);
2286
+ let rooting = { anchor: "fill", safe_area: false, z: options.z ?? (1200) };
2287
+ ui.root(this.root, rooting), this.a11y = new A11y({ role: "progress", label: options.title ?? "Loading", value: "0%", hidden: true }), this.a11y.apply(this.root), this.setProgress(0);
2288
+ }
2289
+ get shown() {
2290
+ return this.visible;
2291
+ }
2292
+ show() {
2293
+ this.visible || (this.visible = true, this.root.style(this.states[1]), this.a11y.options.hidden = false, this.a11y.apply(this.root));
2294
+ }
2295
+ hide() {
2296
+ this.visible && (this.visible = false, this.root.style(this.states[0]), this.a11y.options.hidden = true, this.a11y.apply(this.root));
2297
+ }
2298
+ setProgress(ratio) {
2299
+ this.setPercent(Math.round(clamp(ratio, 0, 1) * (100)));
2300
+ }
2301
+ setPercent(value) {
2302
+ let percent = value < 0 ? 0 : value > (100) ? (100) : value | 0;
2303
+ percent !== this.shownPercent && (this.shownPercent = percent, SLOTS[0] = percent, this.fill.style(this.ui.props(s7.barFill, s7.barTo.setSlotsFrom(SLOTS))), this.percent.text(PERCENT_TEXT[percent]), this.a11y.options.value = PERCENT_TEXT[percent], this.a11y.apply(this.root));
2304
+ }
2305
+ update(frame) {
2306
+ if (!this.visible) return;
2307
+ let dt = frame[1], clock = this.clock;
2308
+ clock[(0)] += SPINNER_SPEED * dt, clock[(0)] >= TURN && (clock[(0)] -= TURN), SLOTS[0] = clock[(0)], this.spinner.style(this.ui.props(s7.spinner, s7.spin.setSlotsFrom(SLOTS))), !(this.tips.length < 2) && (clock[(1)] += dt, !(clock[(1)] < clock[(2)]) && (clock[(1)] = 0, this.tipIndex = (this.tipIndex + 1) % this.tips.length, this.tip.text(this.tips[this.tipIndex])));
2309
+ }
2310
+ };
2311
+ function loadingScreen(ui, options = {}) {
2312
+ return new LoadingScreen(ui, options);
2313
+ }
2314
+ var TutorialHint = class {
2315
+ constructor(ui, options = {}) {
2316
+ this.ui = ui;
2317
+ this.steps = [];
2318
+ this.step = 0;
2319
+ this.at = new Float64Array(3);
2320
+ this.visible = false;
2321
+ this.navigator = options.navigator ?? null, this.onDone = options.onDone ?? null, this.states = [ui.props(s7.hint), ui.props(s7.hint, s7.hintShown)], this.dotStates = [ui.props(s7.dot), ui.props(s7.dot, s7.dotOn), ui.props(s7.dot, s7.dotHidden)], this.root = ui.box(this.states[0]), SLOTS[0] = 0, SLOTS[1] = 0, this.bubble = ui.box(ui.props(s7.bubble, s7.bubbleAt.setSlotsFrom(SLOTS))), this.text = label(ui, "", "body", sheet.text, sheet.wrap);
2322
+ let footer = ui.box(s7.footer), dots = ui.box(s7.dots), dotList = [];
2323
+ for (let i = 0; i < (8); i++) {
2324
+ let dot = ui.box(this.dotStates[2]);
2325
+ dots.append(dot), dotList.push(dot);
2326
+ }
2327
+ this.dots = dotList, this.scope = new UiFocusScope(1, () => (this.hide(), true)), this.next = new TextButton(ui, { label: "Next", variant: "primary", scope: this.scope, onPress: () => this.advance() }), this.skip = new TextButton(ui, { label: "Skip", variant: "ghost", scope: this.scope, onPress: () => this.finish() });
2328
+ let buttons = ui.box(s7.actions);
2329
+ buttons.append(this.skip.root).append(this.next.root), footer.append(dots).append(buttons), this.bubble.append(this.text).append(footer), this.arrow = ui.box(ui.props(s7.arrow, s7.arrowAt.setSlotsFrom(SLOTS))), this.root.append(this.arrow).append(this.bubble);
2330
+ let rooting = { anchor: "fill", safe_area: true, z: options.z ?? (900) };
2331
+ ui.root(this.root, rooting), this.a11y = new A11y({ role: "alert", label: "", live: true, hidden: true }), this.a11y.apply(this.bubble);
2332
+ }
2333
+ get shown() {
2334
+ return this.visible;
2335
+ }
2336
+ get index() {
2337
+ return this.step;
2338
+ }
2339
+ show(steps, x, y) {
2340
+ this.steps = steps, this.at[(0)] = x, this.at[(1)] = y, this.visible = true, this.root.style(this.states[1]), SLOTS[0] = x, SLOTS[1] = y + (16), this.bubble.style(this.ui.props(s7.bubble, s7.bubbleAt.setSlotsFrom(SLOTS))), this.go(0), this.scope.current = -1, this.navigator?.push(this.scope);
2341
+ }
2342
+ advance() {
2343
+ this.step + 1 >= this.steps.length ? this.finish() : this.go(this.step + 1);
2344
+ }
2345
+ hide() {
2346
+ this.visible && (this.visible = false, this.root.style(this.states[0]), this.a11y.options.hidden = true, this.a11y.apply(this.bubble), this.navigator?.pop(this.scope));
2347
+ }
2348
+ update(frame) {
2349
+ if (!this.visible) return;
2350
+ let at = this.at;
2351
+ at[(2)] += frame[1], SLOTS[0] = at[(0)] + (16);
2352
+ let phase = at[(2)] * (1), wave = phase - (phase | 0);
2353
+ SLOTS[1] = at[(1)] + (wave < 0.5 ? wave * 4 - 1 : 3 - wave * 4) * (6), this.arrow.style(this.ui.props(s7.arrow, s7.arrowAt.setSlotsFrom(SLOTS)));
2354
+ }
2355
+ finish() {
2356
+ this.hide(), this.onDone?.();
2357
+ }
2358
+ go(step) {
2359
+ this.step = step, this.text.text(this.steps[step]);
2360
+ let last = step + 1 >= this.steps.length;
2361
+ this.next.setLabel(last ? "Got it" : "Next");
2362
+ for (let i = 0; i < (8); i++) this.dots[i].style(this.dotStates[i >= this.steps.length || this.steps.length < 2 ? 2 : i === step ? 1 : 0]);
2363
+ this.a11y.options.label = this.steps[step], this.a11y.options.hidden = false, this.a11y.apply(this.bubble);
2364
+ }
2365
+ };
2366
+ function tutorialHint(ui, options = {}) {
2367
+ return new TutorialHint(ui, options);
2368
+ }
2369
+
2370
+ // src/interactives/game-ui/widgets/text.ts
2371
+ var CHAT_WIDTH = 300, CHAT_LINES = 6, SENDER_COLORS = 6, FADED_LINES = 2, RICH_SPANS = 24, ICON_SIZE = 18, PARSE_CACHE = 64, s8 = styles({
2372
+ chat: { gap: 2, padding: [kitVars.gapSmall, kitVars.gap, kitVars.gapSmall, kitVars.gap], fill: tokens.surface, radius: kitVars.radius, pointerEvents: "none" },
2373
+ line: { direction: "row", wrap: true, gap: kitVars.gapSmall, alignItems: "start", hidden: false, opacity: 1 },
2374
+ lineFaded: { opacity: 0.55 },
2375
+ lineHidden: { hidden: true },
2376
+ name: { fontSize: kitVars.small, fontWeight: 800, pointerEvents: "none" },
2377
+ body: { fontSize: kitVars.small, textColor: tokens.text, textWrap: true, shrink: 1, grow: 1, basis: 0, pointerEvents: "none" },
2378
+ system: { textColor: tokens.muted },
2379
+ sender0: { textColor: tokens.accent },
2380
+ sender1: { textColor: tokens.success },
2381
+ sender2: { textColor: tokens.gold },
2382
+ sender3: { textColor: tokens.danger },
2383
+ sender4: { textColor: kitVars.silver },
2384
+ sender5: { textColor: kitVars.bronze },
2385
+ rich: { direction: "row", wrap: true, alignItems: "center" },
2386
+ span: { fontSize: kitVars.body, textColor: tokens.text, pointerEvents: "none" },
2387
+ spanBold: { fontWeight: 800 },
2388
+ spanIcon: { width: (18), height: (18), marginInline: 2, pointerEvents: "none" },
2389
+ cText: { textColor: tokens.text },
2390
+ cMuted: { textColor: tokens.muted },
2391
+ cAccent: { textColor: tokens.accent },
2392
+ cGold: { textColor: tokens.gold },
2393
+ cDanger: { textColor: tokens.danger },
2394
+ cSuccess: { textColor: tokens.success }
2395
+ }), ChatPanel = class {
2396
+ constructor(ui, options = {}) {
2397
+ this.ui = ui;
2398
+ this.head = 0;
2399
+ this.size = 0;
2400
+ let lines = options.lines ?? (6);
2401
+ this.senders = new Array(lines).fill(""), this.messages = new Array(lines).fill(""), this.colors = new Int8Array(lines);
2402
+ let body = fontStyle(ui, "body"), colors = [s8.sender0, s8.sender1, s8.sender2, s8.sender3, s8.sender4, s8.sender5];
2403
+ this.lineStates = [ui.props(s8.line), ui.props(s8.line, s8.lineFaded), ui.props(s8.line, s8.lineHidden)];
2404
+ let nameStates = [];
2405
+ for (let i = 0; i < (6); i++) nameStates.push(ui.props(body, s8.name, colors[i]));
2406
+ nameStates.push(ui.props(body, s8.name, sheet.hidden)), this.nameStates = nameStates, this.bodyStates = [ui.props(body, s8.body), ui.props(body, s8.body, s8.system)], this.root = ui.box(ui.props(s8.chat, { width: options.width ?? (300) }, options.style));
2407
+ let rows = [], names = [], bodies = [];
2408
+ for (let i = 0; i < lines; i++) {
2409
+ let row = ui.box(this.lineStates[2]), name = ui.text("", this.nameStates[0]), text = ui.text("", this.bodyStates[0]);
2410
+ row.append(name).append(text), this.root.append(row), rows.push(row), names.push(name), bodies.push(text);
2411
+ }
2412
+ this.rows = rows, this.names = names, this.bodies = bodies, this.root.accessibility({ role: "group", label: options.label ?? "Chat", live: true });
2413
+ }
2414
+ get count() {
2415
+ return this.size;
2416
+ }
2417
+ push(sender, message, color = 0) {
2418
+ let capacity = this.rows.length;
2419
+ this.senders[this.head] = sender, this.messages[this.head] = message, this.colors[this.head] = color, this.head = (this.head + 1) % capacity, this.size < capacity && this.size++, this.render();
2420
+ }
2421
+ system(message) {
2422
+ this.push("", message, -1);
2423
+ }
2424
+ clear() {
2425
+ this.size = 0, this.render();
2426
+ }
2427
+ render() {
2428
+ let capacity = this.rows.length, empty = capacity - this.size;
2429
+ for (let line = 0; line < capacity; line++) {
2430
+ let row = this.rows[line];
2431
+ if (line < empty) {
2432
+ row.style(this.lineStates[2]);
2433
+ continue;
2434
+ }
2435
+ let at = (this.head - (capacity - line) + capacity * 2) % capacity, color = this.colors[at];
2436
+ row.style(this.lineStates[line - empty < (2) && this.size > (2) ? 1 : 0]), this.names[line].style(this.nameStates[color < 0 ? (6) : color % (6)]), color >= 0 && this.names[line].text(this.senders[at]), this.bodies[line].style(this.bodyStates[color < 0 ? 1 : 0]), this.bodies[line].text(this.messages[at]);
2437
+ }
2438
+ }
2439
+ };
2440
+ function chatPanel(ui, options = {}) {
2441
+ return new ChatPanel(ui, options);
2442
+ }
2443
+ var RICH_COLORS = ["text", "muted", "accent", "gold", "danger", "success"], SPAN_TEXT = 0, SPAN_ICON = 1, BOLD_BIT = 8, RichTextError = class extends Error {
2444
+ constructor(message) {
2445
+ super(message), this.name = "RichTextError";
2446
+ }
2447
+ };
2448
+ function parseRich(markup, icons, limit) {
2449
+ let texts = [], kinds = [], styles2 = [], assets = [], bold = false, colors = [0], word = "", flush = () => {
2450
+ if (word.length === 0) return;
2451
+ let last = texts.length - 1;
2452
+ if (word.trim().length === 0 && last >= 0 && kinds[last] === (0)) {
2453
+ texts[last] += word, word = "";
2454
+ return;
2455
+ }
2456
+ texts.push(word), kinds.push((0)), styles2.push(colors[colors.length - 1] | (bold ? (8) : 0)), assets.push(-1), word = "";
2457
+ };
2458
+ for (let i = 0; i < markup.length; i++) {
2459
+ let c = markup[i];
2460
+ if (c === "*" && markup[i + 1] === "*") {
2461
+ flush(), bold = !bold, i++;
2462
+ continue;
2463
+ }
2464
+ if (c === "[") {
2465
+ let end = markup.indexOf("]", i);
2466
+ if (end < 0) throw new RichTextError(`rich text: unclosed "[" at ${i}`);
2467
+ let name = markup.slice(i + 1, end);
2468
+ if (flush(), name === "/")
2469
+ colors.length > 1 && colors.pop();
2470
+ else {
2471
+ let color = RICH_COLORS.indexOf(name);
2472
+ if (color < 0) throw new RichTextError(`rich text: unknown colour "${name}"; use one of ${RICH_COLORS.join(", ")}`);
2473
+ colors.push(color);
2474
+ }
2475
+ i = end;
2476
+ continue;
2477
+ }
2478
+ if (c === "{") {
2479
+ let end = markup.indexOf("}", i);
2480
+ if (end < 0) throw new RichTextError(`rich text: unclosed "{" at ${i}`);
2481
+ let name = markup.slice(i + 1, end), asset = icons[name];
2482
+ if (asset === void 0) throw new RichTextError(`rich text: unknown icon "${name}"`);
2483
+ flush(), texts.push(""), kinds.push((1)), styles2.push(0), assets.push(asset), i = end;
2484
+ continue;
2485
+ }
2486
+ word += c, c === " " && word.trim().length > 0 && flush();
2487
+ }
2488
+ if (flush(), texts.length > limit) throw new RichTextError(`rich text: ${texts.length} spans exceed the widget's ${limit}; raise spans`);
2489
+ return { texts, kinds: Uint8Array.from(kinds), styles: Uint8Array.from(styles2), icons: Int32Array.from(assets), count: texts.length, plain: texts.join("").replace(/\s+/g, " ").trim() };
2490
+ }
2491
+ var RichText = class {
2492
+ constructor(ui, options = {}) {
2493
+ this.ui = ui;
2494
+ this.source = null;
2495
+ this.cache = /* @__PURE__ */ new Map();
2496
+ this.shown = null;
2497
+ this.current = "";
2498
+ this.a11y = new A11y({ role: "text", label: "" });
2499
+ let spans = options.spans ?? (24);
2500
+ this.icons = options.icons ?? {}, this.natural = options.natural ?? [(18), (18)];
2501
+ let body = fontStyle(ui, "body"), colorStyles = [s8.cText, s8.cMuted, s8.cAccent, s8.cGold, s8.cDanger, s8.cSuccess], textStates = [];
2502
+ for (let bold = 0; bold < 2; bold++) for (let c = 0; c < (8); c++) textStates.push(ui.props(body, s8.span, colorStyles[c % colorStyles.length], bold === 1 && s8.spanBold));
2503
+ this.textStates = textStates, this.hiddenText = ui.props(body, s8.span, sheet.hidden), this.iconStates = [ui.props(s8.spanIcon), ui.props(s8.spanIcon, sheet.hidden)], this.root = ui.box(ui.props(s8.rich, options.style));
2504
+ let texts = [], images = [];
2505
+ for (let i = 0; i < spans; i++) {
2506
+ let text = ui.text("", this.hiddenText), image = ui.image(0, this.natural, this.iconStates[1]);
2507
+ this.root.append(text).append(image), texts.push(text), images.push(image);
2508
+ }
2509
+ this.texts = texts, this.images = images, this.mark = new AiMark(ui, options.mark), this.root.append(this.mark.root), options.flowAround !== void 0 && this.root.flowAround(options.flowAround), options.markup !== void 0 && this.set(options.markup, options.source ?? null);
2510
+ }
2511
+ flowAround(exclusions) {
2512
+ return this.root.flowAround(exclusions), this;
2513
+ }
2514
+ get marked() {
2515
+ return this.mark.shown;
2516
+ }
2517
+ get markup() {
2518
+ return this.current;
2519
+ }
2520
+ get spans() {
2521
+ return this.shown?.count ?? 0;
2522
+ }
2523
+ show(result) {
2524
+ this.set(result.value, result.source);
2525
+ }
2526
+ set(markup, source = null) {
2527
+ if (markup === this.current && this.shown !== null && isAiGenerated(source) === isAiGenerated(this.source)) return;
2528
+ this.source = source;
2529
+ let parsed = this.cache.get(markup);
2530
+ parsed === void 0 && (parsed = parseRich(markup, this.icons, this.texts.length), this.cache.size >= (64) && this.cache.clear(), this.cache.set(markup, parsed));
2531
+ let previous = this.shown?.count ?? 0;
2532
+ this.current = markup, this.shown = parsed;
2533
+ for (let i = 0; i < parsed.count; i++) {
2534
+ if (parsed.kinds[i] === (1)) {
2535
+ this.texts[i].style(this.hiddenText), this.images[i].image(parsed.icons[i], this.natural[0], this.natural[1]), this.images[i].style(this.iconStates[0]);
2536
+ continue;
2537
+ }
2538
+ this.images[i].style(this.iconStates[1]), this.texts[i].text(parsed.texts[i]), this.texts[i].style(this.textStates[parsed.styles[i]]);
2539
+ }
2540
+ for (let i = parsed.count; i < previous; i++)
2541
+ this.texts[i].style(this.hiddenText), this.images[i].style(this.iconStates[1]);
2542
+ this.a11y.options.label = aiLabel(parsed.plain, this.mark.show(source)), this.a11y.apply(this.root);
2543
+ }
2544
+ };
2545
+ function richText(ui, options = {}) {
2546
+ return new RichText(ui, options);
2547
+ }
2548
+
2549
+ // src/interactives/worlds/index.ts
2550
+ var worlds_exports = {};
2551
+ __export(worlds_exports, {
2552
+ ACTION_BASE: () => ACTION_BASE,
2553
+ Action: () => Action,
2554
+ BOUNDS_MAX: () => BOUNDS_MAX,
2555
+ BOUNDS_MIN: () => BOUNDS_MIN,
2556
+ BOUNDS_WORDS: () => BOUNDS_WORDS,
2557
+ CENTIDEGREES_PER_TURN: () => CENTIDEGREES_PER_TURN,
2558
+ COMMAND_BYTES: () => COMMAND_BYTES,
2559
+ COMMAND_OP_ID_BYTES: () => COMMAND_OP_ID_BYTES,
2560
+ CommandWriter: () => CommandWriter,
2561
+ DEFAULT_ANGLE_STEP_CENTIDEGREES: () => DEFAULT_ANGLE_STEP_CENTIDEGREES,
2562
+ DEFAULT_GRID_MM: () => DEFAULT_GRID_MM,
2563
+ Ground: () => Ground,
2564
+ Lighting: () => Lighting,
2565
+ Likeness: () => Likeness,
2566
+ LocalWorld: () => LocalWorld,
2567
+ MAX_SELECT_IDS: () => MAX_SELECT_IDS,
2568
+ MILLIMETRES_PER_METRE: () => MILLIMETRES_PER_METRE,
2569
+ MessageKind: () => MessageKind,
2570
+ NOT_SENT: () => NOT_SENT,
2571
+ NO_BUILDER: () => NO_BUILDER,
2572
+ Notice: () => Notice,
2573
+ OBJECT_RECORD_BYTES: () => OBJECT_RECORD_BYTES,
2574
+ POSITION: () => POSITION,
2575
+ QUATERNION_SCALE: () => QUATERNION_SCALE,
2576
+ ROTATION: () => ROTATION,
2577
+ SCALE: () => SCALE,
2578
+ SCALE_UNIT_PERMILLE: () => SCALE_UNIT_PERMILLE,
2579
+ SNAP_GRID: () => SNAP_GRID,
2580
+ SNAP_SURFACE: () => SNAP_SURFACE,
2581
+ Sanction: () => Sanction,
2582
+ SelectMode: () => SelectMode,
2583
+ Sky: () => Sky,
2584
+ Status: () => Status,
2585
+ TRANSFORM_BYTES: () => TRANSFORM_BYTES,
2586
+ TRANSFORM_WORDS: () => TRANSFORM_WORDS,
2587
+ Visibility: () => Visibility,
2588
+ WORLD_CHANNEL_SLOT: () => WORLD_CHANNEL_SLOT,
2589
+ WORLD_DEPTH_MM: () => WORLD_DEPTH_MM,
2590
+ WORLD_EXTENT_MM: () => WORLD_EXTENT_MM,
2591
+ WorldBuilder: () => WorldBuilder,
2592
+ WorldMirror: () => WorldMirror,
2593
+ WorldRoleCode: () => WorldRoleCode,
2594
+ bounds: () => bounds,
2595
+ canonical: () => canonical,
2596
+ connectWorld: () => connectWorld,
2597
+ copyTransform: () => copyTransform,
2598
+ encodeBare: () => encodeBare,
2599
+ encodeClock: () => encodeClock,
2600
+ encodeDuplicate: () => encodeDuplicate,
2601
+ encodeJoinCopy: () => encodeJoinCopy,
2602
+ encodeModerate: () => encodeModerate,
2603
+ encodePlace: () => encodePlace,
2604
+ encodeSelect: () => encodeSelect,
2605
+ encodeSetTransform: () => encodeSetTransform,
2606
+ encodeSettings: () => encodeSettings,
2607
+ encodeTransformSelection: () => encodeTransformSelection,
2608
+ identityTransform: () => identityTransform,
2609
+ movedAbout: () => movedAbout,
2610
+ overlapsFootprint: () => overlapsFootprint,
2611
+ snapHeightToGrid: () => snapHeightToGrid,
2612
+ snappedToGrid: () => snappedToGrid,
2613
+ withinWorld: () => withinWorld,
2614
+ yawRotation: () => yawRotation
2615
+ });
2616
+
2617
+ // src/interactives/generate/index.ts
2618
+ var generate_exports = {};
2619
+ __export(generate_exports, {
2620
+ CONTENT_CHANNEL_SLOT: () => CONTENT_CHANNEL_SLOT,
2621
+ DEFAULT_RETRIES: () => DEFAULT_RETRIES,
2622
+ DEFAULT_TIMEOUT_MS: () => DEFAULT_TIMEOUT_MS,
2623
+ MAX_TIMEOUT_MS: () => MAX_TIMEOUT_MS,
2624
+ MIN_TIMEOUT_MS: () => MIN_TIMEOUT_MS,
2625
+ REPLICATION_GRACE_MS: () => (2e3),
2626
+ RoomGenerateError: () => RoomGenerateError,
2627
+ acceptContent: () => acceptContent,
2628
+ applyRules: () => applyRules,
2629
+ contentRequest: () => contentRequest,
2630
+ createGenerate: () => createGenerate,
2631
+ createRoomGenerate: () => createRoomGenerate,
2632
+ createTickContentLink: () => createTickContentLink,
2633
+ dialogueSchema: () => dialogueSchema,
2634
+ recipeToScene: () => recipeToScene,
2635
+ requestTickContent: () => requestTickContent,
2636
+ roomRecipeSchema: () => roomRecipeSchema,
2637
+ rule: () => rule,
2638
+ runContent: () => runContent,
2639
+ select: () => select,
2640
+ solveRoom: () => solveRoom,
2641
+ t: () => t,
2642
+ tickContentAsk: () => tickContentAsk,
2643
+ validateValue: () => validateValue
2644
+ });
2645
+
2646
+ // src/interactives/generate/room.ts
2647
+ var REPLICATION_VERSION = 1, REPLICATION_GRACE_MS = 2e3, MAX_REMEMBERED = 256, RoomGenerateError = class extends Error {
2648
+ constructor(message) {
2649
+ super(message), this.name = "RoomGenerateError";
2650
+ }
2651
+ }, encoder = new TextEncoder(), decoder = new TextDecoder();
2652
+ function decode(bytes) {
2653
+ try {
2654
+ let message = JSON.parse(decoder.decode(bytes));
2655
+ return message.v === (1) && typeof message.key == "string" ? message : null;
2656
+ } catch {
2657
+ return null;
2658
+ }
2659
+ }
2660
+ function fallbackValue(request) {
2661
+ return typeof request.fallback == "function" ? request.fallback() : request.fallback;
2662
+ }
2663
+ function fromMessage(request, message) {
2664
+ return message.source === "fallback" || message.value === void 0 ? {
2665
+ value: fallbackValue(request),
2666
+ source: "fallback",
2667
+ reason: message.reason ?? "unavailable",
2668
+ seed: message.seed,
2669
+ runId: null,
2670
+ digest: null
2671
+ } : {
2672
+ value: message.value,
2673
+ source: message.source === "generated" || message.source === "cached" ? "replicated" : message.source,
2674
+ reason: null,
2675
+ seed: message.seed,
2676
+ runId: message.runId,
2677
+ digest: message.digest
2678
+ };
2679
+ }
2680
+ function createRoomGenerate(ai, link) {
2681
+ if (link.authority && ai === null)
2682
+ throw new RoomGenerateError("the room authority needs ctx.ai to generate");
2683
+ let seen = /* @__PURE__ */ new Map(), waiting = /* @__PURE__ */ new Map(), remember = (message) => {
2684
+ if (seen.set(message.key, message), seen.size > (256)) {
2685
+ let oldest = seen.keys().next().value;
2686
+ oldest !== void 0 && seen.delete(oldest);
2687
+ }
2688
+ let waiters = waiting.get(message.key);
2689
+ if (waiters !== void 0) {
2690
+ waiting.delete(message.key);
2691
+ for (let waiter of waiters) waiter(message);
2692
+ }
2693
+ }, unsubscribe = link.subscribe((bytes) => {
2694
+ let message = decode(bytes);
2695
+ message !== null && remember(message);
2696
+ }), follow = (key, request) => {
2697
+ let known = seen.get(key);
2698
+ if (known !== void 0) return Promise.resolve(fromMessage(request, known));
2699
+ let patience = (request.timeoutMs ?? 0) + (2e3);
2700
+ return new Promise((resolve) => {
2701
+ let timer = setTimeout(() => {
2702
+ let list3 = waiting.get(key);
2703
+ if (list3 !== void 0) {
2704
+ let index = list3.indexOf(waiter);
2705
+ index >= 0 && list3.splice(index, 1);
2706
+ }
2707
+ resolve({
2708
+ value: fallbackValue(request),
2709
+ source: "fallback",
2710
+ reason: "offline",
2711
+ seed: request.seed ?? 0,
2712
+ runId: null,
2713
+ digest: null
2714
+ });
2715
+ }, patience), waiter = (message) => {
2716
+ clearTimeout(timer), resolve(fromMessage(request, message));
2717
+ }, list2 = waiting.get(key) ?? [];
2718
+ list2.push(waiter), waiting.set(key, list2);
2719
+ });
2720
+ }, lead = async (kind, key, request) => {
2721
+ let known = seen.get(key);
2722
+ if (known !== void 0) return fromMessage(request, known);
2723
+ let result = await runContent(
2724
+ ai,
2725
+ kind,
2726
+ request,
2727
+ { room_id: link.roomId, key },
2728
+ key
2729
+ ), message = {
2730
+ v: (1),
2731
+ key,
2732
+ source: result.source,
2733
+ reason: result.reason,
2734
+ seed: result.seed,
2735
+ runId: result.runId,
2736
+ digest: result.digest,
2737
+ ...result.source === "fallback" ? {} : { value: result.value }
2738
+ };
2739
+ return seen.set(key, message), link.publish(encoder.encode(JSON.stringify(message))), result;
2740
+ }, generate = (kind, key, request) => link.authority ? lead(kind, key, request) : follow(key, request);
2741
+ return {
2742
+ generate,
2743
+ dialogue: (key, request) => generate("dialogue", key, request),
2744
+ text: (key, request) => generate("text", key, request),
2745
+ item: (key, request) => generate("item", key, request),
2746
+ quest: (key, request) => generate("quest", key, request),
2747
+ room: (key, request) => generate("room", key, request),
2748
+ dispose: () => {
2749
+ unsubscribe(), waiting.clear(), seen.clear();
2750
+ }
2751
+ };
2752
+ }
2753
+
2754
+ // src/interactives/generate/scene.ts
2755
+ var MAX_ROOM_SIZE_M = 200, MIN_ROOM_SIZE_M = 2, MAX_ROOM_GROUPS = 16, MAX_GROUP_COUNT = 64, MAX_WITHIN_M = 50;
2756
+ function roomRecipeSchema(kinds, grounds = ["grass"]) {
2757
+ let name = t.string({ min: 1, max: 32, note: "a short snake_case name for the group" });
2758
+ return t.object({
2759
+ name: t.string({ min: 1, max: 60 }),
2760
+ size: t.array(t.number({ min: (2), max: (200) }), {
2761
+ min: 2,
2762
+ max: 2,
2763
+ note: "width and depth in metres"
2764
+ }),
2765
+ ground: t.enum(grounds),
2766
+ style: t.optional(t.string({ max: 40 })),
2767
+ points: t.optional(
2768
+ t.array(
2769
+ t.object({
2770
+ name,
2771
+ at: t.array(t.number({ min: 0, max: (200) }), { min: 2, max: 2 })
2772
+ }),
2773
+ { max: 8 }
2774
+ )
2775
+ ),
2776
+ objects: t.array(
2777
+ t.object({
2778
+ name,
2779
+ kind: t.enum(kinds),
2780
+ count: t.integer({ min: 1, max: (64) }),
2781
+ near: t.optional(t.string({ max: 32 })),
2782
+ within: t.optional(t.number({ min: 0, max: (50) })),
2783
+ facing: t.optional(t.string({ max: 32 })),
2784
+ along: t.optional(t.string({ max: 40 })),
2785
+ on: t.optional(t.string({ max: 32 })),
2786
+ clear: t.optional(t.number({ min: 0, max: 10 })),
2787
+ reachable_from: t.optional(t.string({ max: 32 }))
2788
+ }),
2789
+ { min: 1, max: (16) }
2790
+ )
2791
+ });
2792
+ }
2793
+ function recipeToScene(recipe, seed) {
2794
+ let points = {};
2795
+ for (let point of recipe.points ?? [])
2796
+ points[point.name] = [point.at[0] ?? 0, point.at[1] ?? 0];
2797
+ let objects = {};
2798
+ for (let group of recipe.objects) {
2799
+ let spec = { kind: group.kind, count: group.count };
2800
+ for (let field of [
2801
+ "near",
2802
+ "within",
2803
+ "facing",
2804
+ "along",
2805
+ "on",
2806
+ "clear",
2807
+ "reachable_from"
2808
+ ])
2809
+ group[field] !== void 0 && (spec[field] = group[field]);
2810
+ objects[group.name] = spec;
2811
+ }
2812
+ return {
2813
+ area: {
2814
+ size: [recipe.size[0] ?? (2), recipe.size[1] ?? (2)],
2815
+ ground: recipe.ground,
2816
+ points
2817
+ },
2818
+ objects,
2819
+ ...recipe.style === void 0 ? {} : { style: recipe.style },
2820
+ seed
2821
+ };
2822
+ }
2823
+ function solveRoom(recipe, seed, compile, solver) {
2824
+ let compiled = compile(recipe.name, recipeToScene(recipe, seed));
2825
+ return compiled.wire === null ? { status: "rejected", diagnostics: compiled.diagnostics } : { status: "solved", result: solver.solve(compiled.wire, seed), seed };
2826
+ }
2827
+
2828
+ // src/interactives/generate/tick.ts
2829
+ var CONTENT_CHANNEL_SLOT = FRAME_LIMITS.game_channel_slots - 4, CONTENT_FRAGMENT_HEADER_BYTES = 8, MAX_PENDING_RECORDS = 32;
2830
+ function utf8(text) {
2831
+ let out = [];
2832
+ for (let char of text) {
2833
+ let code = char.codePointAt(0) ?? 0;
2834
+ code < 128 ? out.push(code) : code < 2048 ? out.push(192 | code >> 6, 128 | code & 63) : code < 65536 ? out.push(224 | code >> 12, 128 | code >> 6 & 63, 128 | code & 63) : out.push(
2835
+ 240 | code >> 18,
2836
+ 128 | code >> 12 & 63,
2837
+ 128 | code >> 6 & 63,
2838
+ 128 | code & 63
2839
+ );
2840
+ }
2841
+ return Uint8Array.from(out);
2842
+ }
2843
+ function tickContentAsk(key, kind, request) {
2844
+ let timeout = Math.min(
2845
+ Math.max(Math.round(request.timeoutMs ?? DEFAULT_TIMEOUT_MS), MIN_TIMEOUT_MS),
2846
+ MAX_TIMEOUT_MS
2847
+ );
2848
+ return utf8(
2849
+ JSON.stringify({
2850
+ key,
2851
+ kind,
2852
+ prompt: request.prompt,
2853
+ schema: kind === "dialogue" && request.schema === void 0 ? null : request.schema?.json ?? null,
2854
+ rules: request.rules ?? [],
2855
+ slots: request.slots ?? [],
2856
+ context: request.context ?? null,
2857
+ language: request.language ?? null,
2858
+ variant: request.variant ?? 0,
2859
+ seed: request.seed ?? null,
2860
+ retries: request.retries ?? DEFAULT_RETRIES,
2861
+ timeout_ms: timeout
2862
+ })
2863
+ );
2864
+ }
2865
+ function requestTickContent(ctx, key, kind, request) {
2866
+ return ctx.outbox(1, tickContentAsk(key, kind, request));
2867
+ }
2868
+ function createTickContentLink(roomId, subscribe) {
2869
+ let listeners = /* @__PURE__ */ new Set(), pending = /* @__PURE__ */ new Map(), unsubscribe = subscribe((payload) => {
2870
+ if (payload.length < (8)) return;
2871
+ let view2 = new DataView(payload.buffer, payload.byteOffset, payload.byteLength), record = view2.getUint32(0, true), index = view2.getUint16(4, true), count2 = view2.getUint16(6, true);
2872
+ if (count2 === 0 || index >= count2) return;
2873
+ let parts = pending.get(record);
2874
+ if ((parts === void 0 || parts.length !== count2) && (parts = new Array(count2).fill(null), pending.set(record, parts), pending.size > (32))) {
2875
+ let oldest = pending.keys().next().value;
2876
+ oldest !== void 0 && oldest !== record && pending.delete(oldest);
2877
+ }
2878
+ if (parts[index] = payload.slice((8)), parts.some((part) => part === null)) return;
2879
+ pending.delete(record);
2880
+ let total = parts.reduce((sum, part) => sum + (part?.length ?? 0), 0), joined = new Uint8Array(total), offset = 0;
2881
+ for (let part of parts)
2882
+ part !== null && (joined.set(part, offset), offset += part.length);
2883
+ for (let listener of listeners) listener(joined);
2884
+ });
2885
+ return {
2886
+ roomId,
2887
+ authority: false,
2888
+ publish: () => {
2889
+ },
2890
+ subscribe: (listener) => (listeners.add(listener), () => {
2891
+ listeners.delete(listener), listeners.size === 0 && unsubscribe();
2892
+ })
2893
+ };
2894
+ }
2895
+
2896
+ // src/interactives/parts/index.ts
2897
+ var parts_exports = {};
2898
+ __export(parts_exports, {
2899
+ CDC_MAX_BYTES: () => CDC_MAX_BYTES,
2900
+ CDC_MIN_BYTES: () => CDC_MIN_BYTES,
2901
+ DELTA_LIMIT: () => (0.5),
2902
+ DeltaOp: () => DeltaOp,
2903
+ MANIFEST_HEADER_BYTES: () => MANIFEST_HEADER_BYTES,
2904
+ MANIFEST_MAGIC: () => MANIFEST_MAGIC,
2905
+ MANIFEST_PART_BYTES: () => MANIFEST_PART_BYTES,
2906
+ MANIFEST_VERSION: () => MANIFEST_VERSION,
2907
+ MAX_ASSET_BYTES: () => MAX_ASSET_BYTES,
2908
+ MAX_MANIFEST_PARTS: () => MAX_MANIFEST_PARTS,
2909
+ MIN_PART_BYTES: () => (2048),
2910
+ PART_HEADER_BYTES: () => PART_HEADER_BYTES,
2911
+ PART_MAGIC: () => PART_MAGIC,
2912
+ PART_VERSION: () => PART_VERSION,
2913
+ PartFormatError: () => PartFormatError,
2914
+ PartIndex: () => PartIndex,
2915
+ PartKind: () => PartKind,
2916
+ SEGMENT_BYTES: () => SEGMENT_BYTES,
2917
+ SegmentOp: () => SegmentOp,
2918
+ WEAVE_BOUNDARY_MASK: () => WEAVE_BOUNDARY_MASK,
2919
+ WEAVE_CHILD_ENTRY_BYTES: () => WEAVE_CHILD_ENTRY_BYTES,
2920
+ WEAVE_HEAD_DOMAIN: () => WEAVE_HEAD_DOMAIN,
2921
+ WEAVE_LEAF_DECORATED: () => WEAVE_LEAF_DECORATED,
2922
+ WEAVE_LEAF_ENTRY_BYTES: () => WEAVE_LEAF_ENTRY_BYTES,
2923
+ WEAVE_LEAF_TWINNED: () => WEAVE_LEAF_TWINNED,
2924
+ WEAVE_MAX_HEIGHT: () => WEAVE_MAX_HEIGHT,
2925
+ WEAVE_MAX_NODE_BYTES: () => WEAVE_MAX_NODE_BYTES,
2926
+ WEAVE_MAX_NODE_ENTRIES: () => WEAVE_MAX_NODE_ENTRIES,
2927
+ WEAVE_MIN_NODE_ENTRIES: () => WEAVE_MIN_NODE_ENTRIES,
2928
+ WEAVE_NODE_HEADER_BYTES: () => WEAVE_NODE_HEADER_BYTES,
2929
+ WEAVE_NODE_MAGIC: () => WEAVE_NODE_MAGIC,
2930
+ WEAVE_NODE_ZONE: () => WEAVE_NODE_ZONE,
2931
+ WEAVE_VERSION: () => WEAVE_VERSION,
2932
+ WeaveRefusal: () => WeaveRefusal,
2933
+ WeaveVerifyError: () => WeaveVerifyError,
2934
+ applyDelta: () => applyDelta,
2935
+ assemble: () => assemble,
2936
+ assembleInto: () => assembleInto,
2937
+ buildAsset: () => buildAsset,
2938
+ buildWeave: () => buildWeave,
2939
+ childDigestAt: () => childDigestAt,
2940
+ chunkWeaveSource: () => chunkWeaveSource,
2941
+ coalesce: () => coalesce,
2942
+ combinedBases: () => combinedBases,
2943
+ contentSpans: () => contentSpans,
2944
+ decodeManifest: () => decodeManifest,
2945
+ decodePart: () => decodePart,
2946
+ deliverSchedule: () => deliverSchedule,
2947
+ encodeDelta: () => encodeDelta,
2948
+ encodeManifest: () => encodeManifest,
2949
+ encodePart: () => encodePart,
2950
+ isManifest: () => isManifest,
2951
+ leafAt: () => leafAt,
2952
+ leafDigest: () => leafDigest,
2953
+ leafDigestAt: () => leafDigestAt,
2954
+ leafFlags: () => leafFlags,
2955
+ leafLength: () => leafLength,
2956
+ leafZone: () => leafZone,
2957
+ manifestBytes: () => manifestBytes,
2958
+ nodeMatches: () => nodeMatches,
2959
+ openWeaveHead: () => openWeaveHead,
2960
+ openWeaveSession: () => openWeaveSession,
2961
+ partKindName: () => partKindName,
2962
+ planWeave: () => planWeave,
2963
+ progressiveSpans: () => progressiveSpans,
2964
+ sealPart: () => sealPart,
2965
+ segmentOutput: () => segmentOutput,
2966
+ soleSpan: () => soleSpan,
2967
+ splitAsset: () => splitAsset,
2968
+ storeWeaveSource: () => storeWeaveSource,
2969
+ structuralSpans: () => structuralSpans,
2970
+ unweaveIndex: () => unweaveIndex,
2971
+ validWeaveRoot: () => validWeaveRoot,
2972
+ verifyChild: () => verifyChild,
2973
+ verifyRoot: () => verifyRoot,
2974
+ walkWeave: () => walkWeave,
2975
+ weaveHeadMessage: () => weaveHeadMessage,
2976
+ weaveNodeCount: () => weaveNodeCount,
2977
+ weaveNodeLevel: () => weaveNodeLevel,
2978
+ weaveNodeValid: () => weaveNodeValid,
2979
+ weaveParts: () => weaveParts,
2980
+ woven: () => woven
2981
+ });
2982
+
2983
+ // src/interactives/parts/split.ts
2984
+ var MIN_PART_BYTES = 2048, CDC_MIN_BYTES = 8 * 1024, CDC_MAX_BYTES = 128 * 1024, CDC_MASK = 32767, GEAR_SEED = 2654435769, GLB_MAGIC = 1179937895, GLB_VERSION = 2, GLB_HEADER_BYTES = 12, GLB_CHUNK_HEADER_BYTES = 8, GLB_JSON = 1313821514, GLB_BIN = 5130562, KTX2_IDENTIFIER = [171, 75, 84, 88, 32, 50, 48, 187, 13, 10, 26, 10], KTX2_LEVEL_COUNT = 40, KTX2_LEVEL_INDEX = 80, KTX2_LEVEL_BYTES = 24, CELLS_MAGIC = 1263556419, CELLS_HEADER_BYTES = 16, CELLS_ENTRY_BYTES = 16, WORLD_MAGIC = 1145853763;
2985
+ function view(bytes) {
2986
+ return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
2987
+ }
2988
+ function gearTable() {
2989
+ let table = new Uint32Array(256), x = (2654435769);
2990
+ for (let i = 0; i < 256; i++)
2991
+ x ^= x << 13, x ^= x >>> 17, x ^= x << 5, table[i] = x >>> 0;
2992
+ return table;
2993
+ }
2994
+ var GEAR = gearTable();
2995
+ function contentSpans(bytes, start, end, kind) {
2996
+ let out = [], at = start;
2997
+ for (; at < end; ) {
2998
+ let limit = Math.min(end, at + CDC_MAX_BYTES), cut = limit;
2999
+ if (limit - at > CDC_MIN_BYTES) {
3000
+ let h = 0;
3001
+ for (let i = at + CDC_MIN_BYTES; i < limit; i++)
3002
+ if (h = (h << 1) + GEAR[bytes[i]] >>> 0, (h & (32767)) === 0) {
3003
+ cut = i + 1;
3004
+ break;
3005
+ }
3006
+ }
3007
+ out.push({ start: at, end: cut, kind }), at = cut;
3008
+ }
3009
+ return out;
3010
+ }
3011
+ function covering(length, ranges) {
3012
+ ranges.sort((a, b) => a.start - b.start || b.end - a.end);
3013
+ let out = [], cursor = 0;
3014
+ for (let r of ranges)
3015
+ r.start < cursor || r.end > length || r.end <= r.start || (r.start > cursor && out.push({ start: cursor, end: r.start, kind: null }), out.push(r), cursor = r.end);
3016
+ return cursor < length && out.push({ start: cursor, end: length, kind: null }), out;
3017
+ }
3018
+ function list(value) {
3019
+ return Array.isArray(value) ? value : [];
3020
+ }
3021
+ function num(value) {
3022
+ return typeof value == "number" && Number.isInteger(value) && value >= 0 ? value : null;
3023
+ }
3024
+ function glbViewKinds(gltf) {
3025
+ let kinds = /* @__PURE__ */ new Map(), accessors = list(gltf.accessors), mark = (accessor, kind) => {
3026
+ let a = num(accessor), view2 = a === null ? null : num(accessors[a]?.bufferView);
3027
+ view2 !== null && !kinds.has(view2) && kinds.set(view2, kind);
3028
+ };
3029
+ for (let mesh of list(gltf.meshes))
3030
+ for (let primitive of list(mesh.primitives)) {
3031
+ mark(primitive.indices, PartKind.mesh_index);
3032
+ let attributes = primitive.attributes ?? {};
3033
+ for (let key of Object.keys(attributes).sort()) mark(attributes[key], PartKind.mesh_vertex);
3034
+ for (let target of list(primitive.targets)) for (let key of Object.keys(target).sort()) mark(target[key], PartKind.mesh_vertex);
3035
+ }
3036
+ for (let skin of list(gltf.skins)) mark(skin.inverseBindMatrices, PartKind.skeleton);
3037
+ for (let animation of list(gltf.animations))
3038
+ for (let sampler of list(animation.samplers))
3039
+ mark(sampler.input, PartKind.clip), mark(sampler.output, PartKind.clip);
3040
+ for (let image of list(gltf.images)) {
3041
+ let view2 = num(image.bufferView);
3042
+ view2 !== null && !kinds.has(view2) && kinds.set(view2, PartKind.image);
3043
+ }
3044
+ return kinds;
3045
+ }
3046
+ function splitGlb(bytes) {
3047
+ if (bytes.length < (12) + (8)) return null;
3048
+ let v = view(bytes);
3049
+ if (v.getUint32(0, true) !== (1179937895) || v.getUint32(4, true) !== (2) || v.getUint32(8, true) !== bytes.length) return null;
3050
+ let jsonLength = v.getUint32((12), true);
3051
+ if (v.getUint32((12) + 4, true) !== (1313821514)) return null;
3052
+ let jsonStart = (12) + (8), jsonEnd = jsonStart + jsonLength;
3053
+ if (jsonEnd > bytes.length) return null;
3054
+ let gltf;
3055
+ try {
3056
+ gltf = JSON.parse(new TextDecoder().decode(bytes.subarray(jsonStart, jsonEnd)));
3057
+ } catch {
3058
+ return null;
3059
+ }
3060
+ let ranges = [{ start: jsonStart, end: jsonEnd, kind: PartKind.scene }], binHeader = jsonEnd;
3061
+ if (binHeader + (8) <= bytes.length && v.getUint32(binHeader + 4, true) === (5130562)) {
3062
+ let binStart = binHeader + (8), binEnd = Math.min(bytes.length, binStart + v.getUint32(binHeader, true)), kinds = glbViewKinds(gltf), views = list(gltf.bufferViews);
3063
+ for (let i = 0; i < views.length; i++) {
3064
+ let bufferView = views[i], kind = kinds.get(i) ?? PartKind.data, source = bufferView.extensions?.EXT_meshopt_compression ?? bufferView;
3065
+ if ((num(source.buffer) ?? 0) !== 0) continue;
3066
+ let offset = num(source.byteOffset) ?? 0, length = num(source.byteLength);
3067
+ if (length === null) continue;
3068
+ let start = binStart + offset, end = start + length;
3069
+ end <= binEnd && ranges.push({ start, end, kind });
3070
+ }
3071
+ }
3072
+ return covering(bytes.length, ranges);
3073
+ }
3074
+ function isKtx2(bytes) {
3075
+ if (bytes.length < (80)) return false;
3076
+ for (let i = 0; i < KTX2_IDENTIFIER.length; i++) if (bytes[i] !== KTX2_IDENTIFIER[i]) return false;
3077
+ return true;
3078
+ }
3079
+ function splitKtx2(bytes) {
3080
+ if (!isKtx2(bytes)) return null;
3081
+ let v = view(bytes), levels = Math.max(1, v.getUint32((40), true));
3082
+ if ((80) + levels * (24) > bytes.length) return null;
3083
+ let ranges = [];
3084
+ for (let l = 0; l < levels; l++) {
3085
+ let at = (80) + l * (24), offset = Number(v.getBigUint64(at, true)), length = Number(v.getBigUint64(at + 8, true));
3086
+ offset + length <= bytes.length && ranges.push({ start: offset, end: offset + length, kind: PartKind.texture });
3087
+ }
3088
+ return covering(bytes.length, ranges);
3089
+ }
3090
+ function splitCells(bytes) {
3091
+ if (bytes.length < (16)) return null;
3092
+ let v = view(bytes);
3093
+ if (v.getUint32(0, true) !== (1263556419)) return null;
3094
+ let count2 = v.getUint32(8, true);
3095
+ if ((16) + count2 * (16) > bytes.length) return null;
3096
+ let ranges = [];
3097
+ for (let e = 0; e < count2; e++) {
3098
+ let at = (16) + e * (16), offset = v.getUint32(at + 4, true), length = v.getUint32(at + 8, true);
3099
+ ranges.push({ start: offset, end: offset + length, kind: PartKind.cell });
3100
+ }
3101
+ return covering(bytes.length, ranges);
3102
+ }
3103
+ function expandLarge(bytes, spans) {
3104
+ let out = [];
3105
+ for (let s9 of spans)
3106
+ if (s9.kind !== null && s9.end - s9.start > CDC_MAX_BYTES) for (let c of contentSpans(bytes, s9.start, s9.end, s9.kind)) out.push(c);
3107
+ else out.push(s9);
3108
+ return out;
3109
+ }
3110
+ function joinSmall(spans, minPart) {
3111
+ let out = [];
3112
+ for (let i = 0; i < spans.length; i++) {
3113
+ let s9 = spans[i];
3114
+ if (s9.kind === null) {
3115
+ out.push(s9);
3116
+ continue;
3117
+ }
3118
+ let end = s9.end, j = i + 1;
3119
+ for (; end - s9.start < minPart; ) {
3120
+ let k = j;
3121
+ for (; k < spans.length && spans[k].kind === null && spans[k].end - spans[k].start <= (16) && spans[k].end - end <= (16); ) k++;
3122
+ let next = spans[k];
3123
+ if (next === void 0 || next.kind !== s9.kind || next.start - end > (16) || next.end - s9.start > CDC_MAX_BYTES) break;
3124
+ end = next.end, j = k + 1;
3125
+ }
3126
+ out.push({ start: s9.start, end, kind: s9.kind }), i = j - 1;
3127
+ }
3128
+ return out;
3129
+ }
3130
+ var MAX_JOIN_GAP = 16;
3131
+ function coalesce(input, minPart = (2048)) {
3132
+ let spans = joinSmall(input, minPart), out = [];
3133
+ for (let s9 of spans) {
3134
+ let kind = s9.kind !== null && s9.end - s9.start >= minPart ? s9.kind : null, last = out[out.length - 1];
3135
+ kind === null && last !== void 0 && last.kind === null && last.end === s9.start ? out[out.length - 1] = { start: last.start, end: s9.end, kind: null } : out.push({ start: s9.start, end: s9.end, kind });
3136
+ }
3137
+ return out;
3138
+ }
3139
+ function structuralSpans(bytes) {
3140
+ let structured = splitGlb(bytes) ?? splitKtx2(bytes) ?? splitCells(bytes);
3141
+ return structured !== null ? expandLarge(bytes, structured) : bytes.length >= 4 && view(bytes).getUint32(0, true) === (1145853763) ? contentSpans(bytes, 0, bytes.length, PartKind.data) : null;
3142
+ }
3143
+ var PROGRESSIVE_PART_KIND = {
3144
+ [ProgressiveKind.opaque]: PartKind.data,
3145
+ [ProgressiveKind.texture]: PartKind.texture,
3146
+ [ProgressiveKind.mesh]: PartKind.mesh_vertex,
3147
+ [ProgressiveKind.splat]: PartKind.data,
3148
+ [ProgressiveKind.audio]: PartKind.audio,
3149
+ [ProgressiveKind.cells]: PartKind.cell
3150
+ };
3151
+ function progressiveSpans(bytes) {
3152
+ let bounds2 = containerBounds(bytes);
3153
+ if (bounds2 === null) return null;
3154
+ let kind = PROGRESSIVE_PART_KIND[bounds2.kind] ?? PartKind.data, refine = [], at = bounds2.first;
3155
+ for (let end of bounds2.unitEnds)
3156
+ end <= at || (refine.push({ start: at, end, kind }), at = end);
3157
+ return { base: [{ start: 0, end: bounds2.first, kind }], refine };
3158
+ }
3159
+ function splitAsset(bytes, minPart = (2048)) {
3160
+ let progressive = progressiveSpans(bytes);
3161
+ if (progressive !== null) {
3162
+ let merged2 = [...coalesce(expandLarge(bytes, progressive.base), minPart), ...coalesce(expandLarge(bytes, progressive.refine), minPart)];
3163
+ return merged2.some((s9) => s9.kind !== null) ? merged2 : null;
3164
+ }
3165
+ let spans = structuralSpans(bytes);
3166
+ if (spans === null) return null;
3167
+ let merged = coalesce(spans, minPart);
3168
+ return merged.some((s9) => s9.kind !== null) ? merged : null;
3169
+ }
3170
+
3171
+ // src/interactives/parts/build.ts
3172
+ var DELTA_LIMIT = 0.5, ANCHOR_WINDOW = 64, ANCHOR_MASK = 511, MIN_SHARED_ANCHORS = 0.25, SAME_LENGTH_CANDIDATES = 4, HASH_BASE = 16777619;
3173
+ function anchors(body) {
3174
+ let out = /* @__PURE__ */ new Set(), h = 0;
3175
+ for (let i = 0; i < body.length; i++) {
3176
+ if (h = Math.imul(h, 31) + body[i] | 0, (h & (511)) !== 0 || i + (64) > body.length) continue;
3177
+ let w = 0;
3178
+ for (let j = i; j < i + (64); j++) w = Math.imul(w, (16777619)) + body[j] | 0;
3179
+ out.add(w);
3180
+ }
3181
+ return out;
3182
+ }
3183
+ function combinedBases(...sources) {
3184
+ return {
3185
+ has: (digest) => sources.some((s9) => s9.has(digest)),
3186
+ candidates: (kind, body) => {
3187
+ let out = [];
3188
+ for (let s9 of sources) for (let c of s9.candidates(kind, body)) out.some((o) => o.digest === c.digest) || out.push(c);
3189
+ return out;
3190
+ }
3191
+ };
3192
+ }
3193
+ var PartIndex = class {
3194
+ constructor() {
3195
+ this.parts = [];
3196
+ this.digests = /* @__PURE__ */ new Set();
3197
+ this.byAnchor = /* @__PURE__ */ new Map();
3198
+ this.byLength = /* @__PURE__ */ new Map();
3199
+ }
3200
+ get size() {
3201
+ return this.parts.length;
3202
+ }
3203
+ has(digest) {
3204
+ return this.digests.has(digest);
3205
+ }
3206
+ add(part) {
3207
+ if (this.digests.has(part.digest)) return;
3208
+ this.digests.add(part.digest);
3209
+ let at = this.parts.length;
3210
+ this.parts.push(part);
3211
+ for (let a of anchors(part.body)) {
3212
+ let list2 = this.byAnchor.get(a);
3213
+ list2 === void 0 ? this.byAnchor.set(a, [at]) : list2.push(at);
3214
+ }
3215
+ let key = `${part.kind}:${part.body.length}`, same = this.byLength.get(key);
3216
+ same === void 0 ? this.byLength.set(key, [at]) : same.push(at);
3217
+ }
3218
+ candidates(kind, body) {
3219
+ let out = [], mine = anchors(body);
3220
+ if (mine.size > 0) {
3221
+ let counts = /* @__PURE__ */ new Map();
3222
+ for (let a of mine) for (let at of this.byAnchor.get(a) ?? []) counts.set(at, (counts.get(at) ?? 0) + 1);
3223
+ let best = -1, bestCount = 0;
3224
+ for (let [at, count2] of counts)
3225
+ this.parts[at].kind === kind && (count2 > bestCount || count2 === bestCount && at < best) && (best = at, bestCount = count2);
3226
+ best >= 0 && bestCount >= mine.size * (0.25) && out.push(best);
3227
+ }
3228
+ for (let at of (this.byLength.get(`${kind}:${body.length}`) ?? []).slice(0, (4))) out.indexOf(at) < 0 && out.push(at);
3229
+ return out.map((at) => this.parts[at]);
3230
+ }
3231
+ }, Literal = class {
3232
+ constructor() {
3233
+ this.chunks = [];
3234
+ this.length = 0;
3235
+ }
3236
+ push(bytes) {
3237
+ let at = this.length;
3238
+ return this.chunks.push(bytes), this.length += bytes.length, at;
3239
+ }
3240
+ bytes() {
3241
+ let out = new Uint8Array(this.length), at = 0;
3242
+ for (let c of this.chunks)
3243
+ out.set(c, at), at += c.length;
3244
+ return out;
3245
+ }
3246
+ };
3247
+ function sealPart(kind, body, seal) {
3248
+ let payload = encodePart(kind, body);
3249
+ return { digest: seal(payload), kind, body: payload.subarray(payload.length - body.length), payload };
3250
+ }
3251
+ function buildAsset(bytes, assetKind, seal, options = {}) {
3252
+ let spans = splitAsset(bytes, options.minPart ?? (2048));
3253
+ if (spans === null) return null;
3254
+ let literal = new Literal(), refs = [], sealed = [], slot2 = /* @__PURE__ */ new Map(), segments = [], deltas = [], partSlot = (part) => {
3255
+ let known = slot2.get(part.digest);
3256
+ if (known !== void 0) return known;
3257
+ let at = refs.length;
3258
+ return slot2.set(part.digest, at), refs.push({ digest: part.digest, kind: part.kind, length: part.body.length }), sealed.push(part), at;
3259
+ };
3260
+ for (let span of spans) {
3261
+ let body = bytes.subarray(span.start, span.end);
3262
+ if (span.kind === null) {
3263
+ segments.push({ op: SegmentOp.literal, offset: literal.push(body), length: body.length });
3264
+ continue;
3265
+ }
3266
+ let part = sealPart(span.kind, body, seal), bases = options.bases ?? null, derived = false;
3267
+ if (bases !== null && !bases.has(part.digest))
3268
+ for (let base of bases.candidates(span.kind, body)) {
3269
+ let delta = encodeDelta(base.body, body, Math.floor(body.length * (0.5)));
3270
+ if (delta !== null) {
3271
+ segments.push({ op: SegmentOp.delta, part: partSlot(base), offset: literal.push(delta), length: delta.length, output: body.length }), deltas.push({ base: base.digest, variantBytes: body.length, deltaBytes: delta.length }), derived = true;
3272
+ break;
3273
+ }
3274
+ }
3275
+ derived || segments.push({ op: SegmentOp.part, part: partSlot(part), offset: 0, length: body.length });
3276
+ }
3277
+ let manifest = { kind: assetKind, length: bytes.length, parts: refs, segments, literal: literal.bytes() };
3278
+ return { manifest: encodeManifest(manifest), parts: sealed, deltas, literalBytes: manifest.literal.length };
3279
+ }
3280
+
3281
+ // src/interactives/progressive/index.ts
3282
+ var progressive_exports = {};
3283
+ __export(progressive_exports, {
3284
+ DEFAULT_PROGRESSIVE_KINDS: () => DEFAULT_PROGRESSIVE_KINDS,
3285
+ FILL_BYTE_MAX: () => FILL_BYTE_MAX,
3286
+ HEADER_BYTES: () => HEADER_BYTES,
3287
+ Header: () => Header,
3288
+ LEVEL_BYTES: () => LEVEL_BYTES,
3289
+ MAX_PROGRESSIVE_BYTES: () => MAX_PROGRESSIVE_BYTES,
3290
+ MAX_PROGRESSIVE_DECODE_BYTES: () => MAX_PROGRESSIVE_DECODE_BYTES,
3291
+ MERGE_PARAM_BYTES: () => MERGE_PARAM_BYTES,
3292
+ MIN_PROGRESSIVE_BYTES: () => MIN_PROGRESSIVE_BYTES,
3293
+ PATCH_BYTES: () => PATCH_BYTES,
3294
+ PPM: () => PPM,
3295
+ PROGRESSIVE_MAGIC: () => PROGRESSIVE_MAGIC,
3296
+ PROGRESSIVE_VERSION: () => PROGRESSIVE_VERSION,
3297
+ PatchOp: () => PatchOp,
3298
+ ProgressiveCancelled: () => ProgressiveCancelled,
3299
+ ProgressiveDecoder: () => ProgressiveDecoder,
3300
+ ProgressiveFeed: () => ProgressiveFeed,
3301
+ ProgressiveFormatError: () => ProgressiveFormatError,
3302
+ ProgressiveKind: () => ProgressiveKind,
3303
+ ProgressiveLayout: () => ProgressiveLayout,
3304
+ SAMPLE_BYTES: () => SAMPLE_BYTES,
3305
+ SEGMENT_BYTES: () => SEGMENT_BYTES2,
3306
+ SEGMENT_STAGED: () => SEGMENT_STAGED,
3307
+ TableWriter: () => TableWriter,
3308
+ UNIT_BYTES: () => UNIT_BYTES,
3309
+ UNLIFT_PARAM_BYTES: () => UNLIFT_PARAM_BYTES,
3310
+ buildProgressive: () => buildProgressive,
3311
+ checkLayout: () => checkLayout,
3312
+ coarseKeys: () => coarseKeys,
3313
+ containerBounds: () => containerBounds,
3314
+ decodeProgressive: () => decodeProgressive,
3315
+ encodeContainer: () => encodeContainer,
3316
+ headBytes: () => headBytes,
3317
+ isCoarseKey: () => isCoarseKey,
3318
+ isProgressive: () => isProgressive,
3319
+ liftForward: () => liftForward,
3320
+ planAudio: () => planAudio,
3321
+ planCells: () => planCells,
3322
+ planMesh: () => planMesh,
3323
+ planSplat: () => planSplat,
3324
+ planTexture: () => planTexture,
3325
+ progressiveKindName: () => progressiveKindName,
3326
+ readKtx2: () => readKtx2,
3327
+ readLayout: () => readLayout,
3328
+ writePatch: () => writePatch
3329
+ });
3330
+
3331
+ // src/interactives/progressive/audio.ts
3332
+ var RIFF = 1179011410, WAVE = 1163280727, FMT = 544501094, DATA = 1635017060, RIFF_HEADER_BYTES = 12, CHUNK_HEADER_BYTES = 8, PCM = 1, BITS = 16, FMT_CHANNELS = 2, FMT_RATE = 4, FMT_BYTE_RATE = 8, FMT_BITS = 14, FMT_MIN_BYTES = 16, RIFF_SIZE = 4, MIN_BASE_RATE = 8e3, MAX_BANDS = 3;
3333
+ function u32(value) {
3334
+ let out = new Uint8Array(4);
3335
+ return new DataView(out.buffer).setUint32(0, value, true), out;
3336
+ }
3337
+ function isWave(bytes) {
3338
+ if (bytes.length < (12)) return false;
3339
+ let v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
3340
+ return v.getUint32(0, true) === (1179011410) && v.getUint32(8, true) === (1163280727);
3341
+ }
3342
+ function planAudio(bytes) {
3343
+ if (!isWave(bytes)) return null;
3344
+ let v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength), at = (12), fmt = -1, dataStart = -1, dataBytes = 0;
3345
+ for (; at + (8) <= bytes.length; ) {
3346
+ let id = v.getUint32(at, true), size = v.getUint32(at + 4, true), body = at + (8);
3347
+ if (id === (544501094) && size >= (16) && (fmt = body), id === (1635017060)) {
3348
+ dataStart = body, dataBytes = size;
3349
+ break;
3350
+ }
3351
+ at = body + size + (size & 1);
3352
+ }
3353
+ if (fmt < 0 || dataStart < 0 || dataStart + dataBytes !== bytes.length || v.getUint16(fmt, true) !== (1) || v.getUint16(fmt + (14), true) !== (16)) return null;
3354
+ let channels = v.getUint16(fmt + (2), true), rate = v.getUint32(fmt + (4), true), block = channels * SAMPLE_BYTES;
3355
+ if (channels === 0 || dataBytes % block !== 0) return null;
3356
+ let frames = dataBytes / block, bands = 0;
3357
+ for (; bands < (3) && rate % 2 ** (bands + 1) === 0 && rate / 2 ** (bands + 1) >= (8e3) && frames >> bands + 1 > 0; ) bands++;
3358
+ if (bands === 0) return null;
3359
+ let samples = new Int16Array(frames * channels);
3360
+ for (let i = 0; i < samples.length; i++) samples[i] = v.getInt16(dataStart + i * SAMPLE_BYTES, true);
3361
+ let lows = [samples], details = [new Int16Array(0)], counts = [frames];
3362
+ for (let k = 1; k <= bands; k++) {
3363
+ let lifted = liftForward(lows[k - 1], counts[k - 1], channels);
3364
+ lows.push(lifted.low), details.push(lifted.detail), counts.push(Math.ceil(counts[k - 1] / 2));
3365
+ }
3366
+ let table = new TableWriter(), state = (k) => {
3367
+ let r = rate / 2 ** k, size = counts[k] * block;
3368
+ return [
3369
+ { op: PatchOp.write, a: (4), b: table.bytes(u32(dataStart + size - (8))), c: 4 },
3370
+ { op: PatchOp.write, a: fmt + (4), b: table.bytes(u32(r)), c: 4 },
3371
+ { op: PatchOp.write, a: fmt + (8), b: table.bytes(u32(r * block)), c: 4 },
3372
+ { op: PatchOp.write, a: dataStart - 4, b: table.bytes(u32(size)), c: 4 }
3373
+ ];
3374
+ }, pcm = (s9) => {
3375
+ let out = new Uint8Array(s9.length * SAMPLE_BYTES), ov = new DataView(out.buffer);
3376
+ for (let i = 0; i < s9.length; i++) ov.setInt16(i * SAMPLE_BYTES, s9[i], true);
3377
+ return out;
3378
+ }, levels = [
3379
+ [
3380
+ {
3381
+ segments: [
3382
+ { dest: 0, bytes: bytes.subarray(0, dataStart) },
3383
+ { dest: dataStart, bytes: pcm(lows[bands]) }
3384
+ ],
3385
+ patches: state(bands),
3386
+ quality: Math.floor(PPM / 2 ** bands)
3387
+ }
3388
+ ]
3389
+ ];
3390
+ for (let k = bands; k >= 1; k--) {
3391
+ let params = table.words(counts[k], counts[k - 1], channels);
3392
+ levels.push([
3393
+ {
3394
+ segments: [{ dest: 0, bytes: pcm(details[k]), staged: true }],
3395
+ patches: [{ op: PatchOp.unlift, a: dataStart, b: 0, c: params }, ...state(k - 1)],
3396
+ quality: k === 1 ? PPM : Math.floor(PPM / 2 ** (k - 1))
3397
+ }
3398
+ ]);
3399
+ }
3400
+ return { kind: ProgressiveKind.audio, output: bytes.length, levels, table: table.finish() };
3401
+ }
3402
+
3403
+ // src/interactives/progressive/cells.ts
3404
+ var PACK_MAGIC = 1263556419, PACK_VERSION = 3, PACK_HEADER_BYTES = 16, PACK_ENTRY_BYTES = 16, PACK_COUNT = 8, ENTRY_OFFSET = 4, ENTRY_LENGTH = 8, ENTRY_LEVEL = 12, LEVEL_PROXY = 2;
3405
+ function isCellPack(bytes) {
3406
+ return bytes.length >= (16) && new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0, true) === (1263556419);
3407
+ }
3408
+ function count(value) {
3409
+ let out = new Uint8Array(4);
3410
+ return new DataView(out.buffer).setUint32(0, value, true), out;
3411
+ }
3412
+ function planCells(bytes) {
3413
+ if (!isCellPack(bytes)) return null;
3414
+ let v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
3415
+ if (v.getUint32(4, true) !== (3)) return null;
3416
+ let cells = v.getUint32((8), true), tableEnd = (16) + cells * (16);
3417
+ if (cells < 2 || tableEnd > bytes.length) return null;
3418
+ let offsets = [], level = (e) => v.getUint32((16) + e * (16) + (12), true), tiers = level(0) === (2);
3419
+ for (let e = 0; e < cells; e++) {
3420
+ let at = (16) + e * (16), offset = v.getUint32(at + (4), true), length = v.getUint32(at + (8), true);
3421
+ if ((tiers ? level(e) !== (2) : level(e) >= (2)) || offset < tableEnd || offset + length > bytes.length || e > 0 && offset <= offsets[e - 1] || e > 0 && offsets[e - 1] + v.getUint32(at - (16) + (8), true) > offset) return null;
3422
+ offsets.push(offset);
3423
+ }
3424
+ let end = (e) => e + 1 < cells ? offsets[e + 1] : bytes.length, bodies = bytes.length - offsets[0], table = new TableWriter(), quality = (e) => e === cells - 1 ? PPM : Math.floor((end(e) - offsets[0]) * PPM / bodies), levels = [[{ segments: [{ dest: 0, bytes: bytes.subarray(0, end(0)) }], patches: [writePatch(table, (8), count(1))], quality: quality(0) }]];
3425
+ for (let e = 1; e < cells; e++) {
3426
+ let unit = { segments: [{ dest: offsets[e], bytes: bytes.subarray(offsets[e], end(e)) }], patches: [writePatch(table, (8), count(e + 1))], quality: quality(e) };
3427
+ (e & e - 1) === 0 && levels.push([]), levels[levels.length - 1].push(unit);
3428
+ }
3429
+ return { kind: ProgressiveKind.cells, output: bytes.length, levels, table: table.finish() };
3430
+ }
3431
+
3432
+ // src/interactives/progressive/simplify.ts
3433
+ function stampKey(from, to) {
3434
+ return from * 1048576 + to % 1048576;
3435
+ }
3436
+ var LOD_RATIO = 4, MIN_LOD_TRIANGLES = 64, MIN_PROGRESSIVE_TRIANGLES = 256, Heap = class {
3437
+ constructor() {
3438
+ this.cost = [];
3439
+ this.from = [];
3440
+ this.to = [];
3441
+ this.stamp = [];
3442
+ }
3443
+ get size() {
3444
+ return this.cost.length;
3445
+ }
3446
+ push(cost, from, to, stamp) {
3447
+ let i = this.cost.length;
3448
+ for (this.cost.push(cost), this.from.push(from), this.to.push(to), this.stamp.push(stamp); i > 0; ) {
3449
+ let parent = i - 1 >> 1;
3450
+ if (!this.less(i, parent)) break;
3451
+ this.swap(i, parent), i = parent;
3452
+ }
3453
+ }
3454
+ less(a, b) {
3455
+ let d = this.cost[a] - this.cost[b];
3456
+ return d !== 0 ? d < 0 : this.from[a] - this.from[b] < 0 || this.from[a] === this.from[b] && this.to[a] < this.to[b];
3457
+ }
3458
+ swap(a, b) {
3459
+ let c = this.cost[a];
3460
+ this.cost[a] = this.cost[b], this.cost[b] = c;
3461
+ let f = this.from[a];
3462
+ this.from[a] = this.from[b], this.from[b] = f;
3463
+ let t2 = this.to[a];
3464
+ this.to[a] = this.to[b], this.to[b] = t2;
3465
+ let s9 = this.stamp[a];
3466
+ this.stamp[a] = this.stamp[b], this.stamp[b] = s9;
3467
+ }
3468
+ pop(out) {
3469
+ if (this.cost.length === 0) return false;
3470
+ out[0] = this.from[0], out[1] = this.to[0], out[2] = this.stamp[0];
3471
+ let last = this.cost.length - 1;
3472
+ this.swap(0, last), this.cost.pop(), this.from.pop(), this.to.pop(), this.stamp.pop();
3473
+ let i = 0, n = this.cost.length;
3474
+ for (; ; ) {
3475
+ let l = 2 * i + 1, r = l + 1, m = i;
3476
+ if (l < n && this.less(l, m) && (m = l), r < n && this.less(r, m) && (m = r), m === i) break;
3477
+ this.swap(i, m), i = m;
3478
+ }
3479
+ return true;
3480
+ }
3481
+ };
3482
+ function addPlane(q, at, nx, ny, nz, d, w) {
3483
+ q[at] += w * nx * nx, q[at + 1] += w * nx * ny, q[at + 2] += w * nx * nz, q[at + 3] += w * nx * d, q[at + 4] += w * ny * ny, q[at + 5] += w * ny * nz, q[at + 6] += w * ny * d, q[at + 7] += w * nz * nz, q[at + 8] += w * nz * d, q[at + 9] += w * d * d;
3484
+ }
3485
+ function evaluate(q, a, b, x, y, z) {
3486
+ let s9 = (k) => q[a + k] + q[b + k];
3487
+ return s9(0) * x * x + 2 * s9(1) * x * y + 2 * s9(2) * x * z + 2 * s9(3) * x + s9(4) * y * y + 2 * s9(5) * y * z + 2 * s9(6) * y + s9(7) * z * z + 2 * s9(8) * z + s9(9);
3488
+ }
3489
+ function weld(positions, vertices) {
3490
+ let bits = new Uint32Array(positions.buffer, positions.byteOffset, vertices * 3), seen = /* @__PURE__ */ new Map(), of = new Int32Array(vertices);
3491
+ for (let w = 0; w < vertices; w++) {
3492
+ let key = `${bits[w * 3]},${bits[w * 3 + 1]},${bits[w * 3 + 2]}`, known = seen.get(key);
3493
+ known === void 0 ? (of[w] = seen.size, seen.set(key, seen.size)) : of[w] = known;
3494
+ }
3495
+ return { of, count: seen.size };
3496
+ }
3497
+ function simplifyLods(input, targets) {
3498
+ let { positions, indices, vertices, signatures, signatureWidth } = input, faces = indices.length / 3, { of, count: count2 } = weld(positions, vertices), px = new Float64Array(count2), py = new Float64Array(count2), pz = new Float64Array(count2);
3499
+ for (let w = 0; w < vertices; w++)
3500
+ px[of[w]] = positions[w * 3], py[of[w]] = positions[w * 3 + 1], pz[of[w]] = positions[w * 3 + 2];
3501
+ let corners = Int32Array.from(indices), alive = new Uint8Array(faces).fill(1), ring = Array.from({ length: count2 }, () => []);
3502
+ for (let f = 0; f < faces; f++) for (let k = 0; k < 3; k++) ring[of[corners[f * 3 + k]]].push(f);
3503
+ let q = new Float64Array(count2 * 10), normal = (f, out) => {
3504
+ let a = of[corners[f * 3]], b = of[corners[f * 3 + 1]], c = of[corners[f * 3 + 2]], ux = px[b] - px[a], uy = py[b] - py[a], uz = pz[b] - pz[a], vx = px[c] - px[a], vy = py[c] - py[a], vz = pz[c] - pz[a], nx = uy * vz - uz * vy, ny = uz * vx - ux * vz, nz = ux * vy - uy * vx, len = Math.hypot(nx, ny, nz);
3505
+ return out[0] = len > 0 ? nx / len : 0, out[1] = len > 0 ? ny / len : 0, out[2] = len > 0 ? nz / len : 0, len * 0.5;
3506
+ }, n = [0, 0, 0], edgeFaces = /* @__PURE__ */ new Map(), edgeKey = (a, b) => a < b ? a * count2 + b : b * count2 + a;
3507
+ for (let f = 0; f < faces; f++) {
3508
+ let area = normal(f, n), a = of[corners[f * 3]];
3509
+ if (area > 1e-12) {
3510
+ let d = -(n[0] * px[a] + n[1] * py[a] + n[2] * pz[a]);
3511
+ for (let k = 0; k < 3; k++) addPlane(q, of[corners[f * 3 + k]] * 10, n[0], n[1], n[2], d, area);
3512
+ }
3513
+ for (let k = 0; k < 3; k++) {
3514
+ let key = edgeKey(of[corners[f * 3 + k]], of[corners[f * 3 + (k + 1) % 3]]), list2 = edgeFaces.get(key);
3515
+ list2 === void 0 ? edgeFaces.set(key, [f]) : list2.push(f);
3516
+ }
3517
+ }
3518
+ let wedgeAt = (f, p) => {
3519
+ for (let k = 0; k < 3; k++) if (of[corners[f * 3 + k]] === p) return corners[f * 3 + k];
3520
+ return -1;
3521
+ };
3522
+ for (let [key, list2] of edgeFaces) {
3523
+ let a = Math.floor(key / count2), b = key % count2, seam = list2.length === 2 && (wedgeAt(list2[0], a) !== wedgeAt(list2[1], a) || wedgeAt(list2[0], b) !== wedgeAt(list2[1], b));
3524
+ if (list2.length !== 1 && !seam) continue;
3525
+ let weight = list2.length === 1 ? 16 : 2;
3526
+ for (let f of list2) {
3527
+ normal(f, n);
3528
+ let ex = px[b] - px[a], ey = py[b] - py[a], ez = pz[b] - pz[a], cx = ey * n[2] - ez * n[1], cy = ez * n[0] - ex * n[2], cz = ex * n[1] - ey * n[0], len = Math.hypot(cx, cy, cz);
3529
+ if (len <= 0) continue;
3530
+ cx /= len, cy /= len, cz /= len;
3531
+ let d = -(cx * px[a] + cy * py[a] + cz * pz[a]), w = weight * (ex * ex + ey * ey + ez * ez);
3532
+ addPlane(q, a * 10, cx, cy, cz, d, w), addPlane(q, b * 10, cx, cy, cz, d, w);
3533
+ }
3534
+ }
3535
+ let stamp = new Int32Array(count2), removed = new Uint8Array(count2), heap = new Heap(), cost = (u, v) => evaluate(q, u * 10, v * 10, px[v], py[v], pz[v]), pushAround = (u) => {
3536
+ let seen = /* @__PURE__ */ new Set();
3537
+ for (let f of ring[u])
3538
+ if (alive[f] !== 0)
3539
+ for (let k = 0; k < 3; k++) {
3540
+ let v = of[corners[f * 3 + k]];
3541
+ v === u || seen.has(v) || (seen.add(v), heap.push(cost(u, v), u, v, stampKey(stamp[u], stamp[v])), heap.push(cost(v, u), v, u, stampKey(stamp[v], stamp[u])));
3542
+ }
3543
+ };
3544
+ for (let p = 0; p < count2; p++) pushAround(p);
3545
+ let live = faces, lods = [], snapshot = () => {
3546
+ let out = new Uint32Array(live * 3), at = 0;
3547
+ for (let f = 0; f < faces; f++)
3548
+ alive[f] !== 0 && (out[at++] = corners[f * 3], out[at++] = corners[f * 3 + 1], out[at++] = corners[f * 3 + 2]);
3549
+ lods.push(out);
3550
+ }, before = [0, 0, 0], after = [0, 0, 0], nearest2 = (w, candidates) => {
3551
+ if (signatures === null || candidates.length === 1) return candidates[0];
3552
+ let best = candidates[0], bestDistance = 1 / 0;
3553
+ for (let c of candidates) {
3554
+ let d = 0;
3555
+ for (let k = 0; k < signatureWidth; k++) {
3556
+ let e = signatures[w * signatureWidth + k] - signatures[c * signatureWidth + k];
3557
+ d += e * e;
3558
+ }
3559
+ (d < bestDistance || d === bestDistance && c < best) && (best = c, bestDistance = d);
3560
+ }
3561
+ return best;
3562
+ }, valid = (u, v) => {
3563
+ let shared = false;
3564
+ for (let f of ring[u]) {
3565
+ if (alive[f] === 0) continue;
3566
+ let hasV = false;
3567
+ for (let k = 0; k < 3; k++) of[corners[f * 3 + k]] === v && (hasV = true);
3568
+ if (hasV) {
3569
+ shared = true;
3570
+ continue;
3571
+ }
3572
+ normal(f, before);
3573
+ let saved = [px[u], py[u], pz[u]];
3574
+ px[u] = px[v], py[u] = py[v], pz[u] = pz[v];
3575
+ let area = normal(f, after);
3576
+ if (px[u] = saved[0], py[u] = saved[1], pz[u] = saved[2], area <= 1e-12 || before[0] * after[0] + before[1] * after[1] + before[2] * after[2] < 0.25) return false;
3577
+ }
3578
+ return shared;
3579
+ }, collapse = (u, v) => {
3580
+ let mapped = /* @__PURE__ */ new Map(), targets2 = [];
3581
+ for (let f of ring[v])
3582
+ if (alive[f] !== 0)
3583
+ for (let k = 0; k < 3; k++) {
3584
+ let w = corners[f * 3 + k];
3585
+ of[w] === v && targets2.indexOf(w) < 0 && targets2.push(w);
3586
+ }
3587
+ for (let f of ring[u]) {
3588
+ if (alive[f] === 0) continue;
3589
+ let wu = wedgeAt(f, u), wv = wedgeAt(f, v);
3590
+ wv >= 0 && !mapped.has(wu) && mapped.set(wu, wv);
3591
+ }
3592
+ for (let f of ring[u])
3593
+ if (alive[f] !== 0) {
3594
+ if (wedgeAt(f, v) >= 0) {
3595
+ alive[f] = 0, live--;
3596
+ continue;
3597
+ }
3598
+ for (let k = 0; k < 3; k++) {
3599
+ let w = corners[f * 3 + k];
3600
+ if (of[w] !== u) continue;
3601
+ let to = mapped.get(w);
3602
+ to === void 0 && (to = nearest2(w, targets2), mapped.set(w, to)), corners[f * 3 + k] = to;
3603
+ }
3604
+ ring[v].push(f);
3605
+ }
3606
+ ring[u] = [], removed[u] = 1;
3607
+ for (let k = 0; k < 10; k++) q[v * 10 + k] += q[u * 10 + k];
3608
+ stamp[v]++;
3609
+ let neighbours = /* @__PURE__ */ new Set();
3610
+ for (let f of ring[v]) if (alive[f] === 1) for (let k = 0; k < 3; k++) neighbours.add(of[corners[f * 3 + k]]);
3611
+ for (let p of neighbours) p !== v && stamp[p]++;
3612
+ pushAround(v);
3613
+ for (let p of neighbours) p !== v && pushAround(p);
3614
+ }, popped = [0, 0, 0];
3615
+ for (let t2 = 0; t2 < targets.length; t2++) {
3616
+ let target = targets[t2];
3617
+ for (; live > target && heap.pop(popped); ) {
3618
+ let u = popped[0], v = popped[1];
3619
+ removed[u] === 1 || removed[v] === 1 || popped[2] === stampKey(stamp[u], stamp[v]) && valid(u, v) && collapse(u, v);
3620
+ }
3621
+ let previous = lods.length === 0 ? faces : lods[lods.length - 1].length / 3;
3622
+ if (live > target && live > previous * 0.8 || (snapshot(), live > target)) break;
3623
+ }
3624
+ return lods;
3625
+ }
3626
+ function lodTargets(triangles) {
3627
+ let out = [], t2 = Math.floor(triangles / (4));
3628
+ for (; t2 >= (64); )
3629
+ out.push(t2), t2 = Math.floor(t2 / (4));
3630
+ return out;
3631
+ }
3632
+
3633
+ // src/interactives/progressive/texture.ts
3634
+ var KTX2_IDENTIFIER2 = [171, 75, 84, 88, 32, 50, 48, 187, 13, 10, 26, 10], KTX2_WIDTH = 20, KTX2_HEIGHT = 24, KTX2_DEPTH = 28, KTX2_LEVEL_COUNT2 = 40, KTX2_SCHEME = 44, KTX2_LEVEL_INDEX2 = 80, KTX2_LEVEL_BYTES2 = 24, KTX2_LEVEL_LENGTH = 8, KTX2_MAX_LEVELS = 32, SCHEME_BASIS_LZ = 1, BASE_TEXTURE_EDGE = 64;
3635
+ function isKtx2At(bytes, start, end) {
3636
+ if (end - start < (80) + (24)) return false;
3637
+ for (let i = 0; i < KTX2_IDENTIFIER2.length; i++) if (bytes[start + i] !== KTX2_IDENTIFIER2[i]) return false;
3638
+ return true;
3639
+ }
3640
+ function readKtx2(bytes, start = 0, end = bytes.length) {
3641
+ if (!isKtx2At(bytes, start, end)) return null;
3642
+ let v = new DataView(bytes.buffer, bytes.byteOffset + start, end - start);
3643
+ if (v.getUint32((44), true) === (1)) return null;
3644
+ let levels = Math.max(1, v.getUint32((40), true));
3645
+ if (levels > (32) || (80) + levels * (24) > end - start) return null;
3646
+ let offsets = [];
3647
+ for (let l = 0; l < levels; l++) {
3648
+ let at = (80) + l * (24), offset = Number(v.getBigUint64(at, true)), length = Number(v.getBigUint64(at + (8), true));
3649
+ if (offset + length > end - start) return null;
3650
+ offsets.push(offset);
3651
+ }
3652
+ if (offsets[levels - 1] < (80) + levels * (24)) return null;
3653
+ for (let l = 0; l < levels; l++) {
3654
+ let length = Number(v.getBigUint64((80) + l * (24) + (8), true));
3655
+ if (offsets[l] + length > (l === 0 ? end - start : offsets[l - 1]) || l + 1 < levels && offsets[l + 1] >= offsets[l]) return null;
3656
+ }
3657
+ return { start, end, width: v.getUint32((20), true), height: v.getUint32((24), true), depth: v.getUint32((28), true), levels, offsets };
3658
+ }
3659
+ function levelEnd(k, level) {
3660
+ return k.start + (level === 0 ? k.end - k.start : k.offsets[level - 1]);
3661
+ }
3662
+ function levelStart(k, level) {
3663
+ return k.start + k.offsets[level];
3664
+ }
3665
+ function shrink(size, level) {
3666
+ return size === 0 ? 0 : Math.max(1, size >>> level);
3667
+ }
3668
+ function texels(k, level) {
3669
+ return shrink(k.width, level) * Math.max(1, shrink(k.height, level)) * Math.max(1, shrink(k.depth, level));
3670
+ }
3671
+ function baseLevel(k, edge = (64)) {
3672
+ let level = k.levels - 1;
3673
+ for (; level > 0 && Math.max(shrink(k.width, level - 1), shrink(k.height, level - 1)) <= edge; ) level--;
3674
+ return level;
3675
+ }
3676
+ var KtxStates = class {
3677
+ constructor(bytes, k, table) {
3678
+ this.bytes = bytes;
3679
+ this.k = k;
3680
+ this.table = table;
3681
+ this.indexAt = -1;
3682
+ }
3683
+ state(finest) {
3684
+ let k = this.k, index = k.start + (80);
3685
+ this.indexAt < 0 && (this.indexAt = this.table.bytes(Uint8Array.from(this.bytes.subarray(index, index + k.levels * (24)))));
3686
+ let fields = Uint8Array.from(this.bytes.subarray(k.start + (20), k.start + (40) + 4)), d = new DataView(fields.buffer);
3687
+ return d.setUint32((20) - (20), shrink(k.width, finest), true), d.setUint32((24) - (20), shrink(k.height, finest), true), d.setUint32((28) - (20), shrink(k.depth, finest), true), d.setUint32((40) - (20), k.levels - finest, true), [
3688
+ writePatch(this.table, k.start + (20), fields),
3689
+ { op: PatchOp.write, a: index, b: this.indexAt + finest * (24), c: (k.levels - finest) * (24) }
3690
+ ];
3691
+ }
3692
+ };
3693
+ function planTexture(bytes) {
3694
+ let k = readKtx2(bytes);
3695
+ if (k === null) return null;
3696
+ let table = new TableWriter(), states = new KtxStates(bytes, k, table), full = texels(k, 0), base = baseLevel(k), quality = (level) => Math.floor(texels(k, level) * PPM / full), levels = [
3697
+ [{ segments: [{ dest: 0, bytes: bytes.subarray(0, levelEnd(k, base)) }], patches: base === 0 ? [] : states.state(base), quality: base === 0 ? PPM : quality(base) }]
3698
+ ];
3699
+ for (let level = base - 1; level >= 0; level--) {
3700
+ let start = levelStart(k, level);
3701
+ levels.push([{ segments: [{ dest: start, bytes: bytes.subarray(start, levelEnd(k, level)) }], patches: states.state(level), quality: level === 0 ? PPM : quality(level) }]);
3702
+ }
3703
+ return { kind: ProgressiveKind.texture, output: bytes.length, levels, table: table.finish() };
3704
+ }
3705
+
3706
+ // src/interactives/progressive/mesh.ts
3707
+ var GLB_MAGIC2 = 1179937895, GLB_VERSION2 = 2, GLB_HEADER_BYTES2 = 12, GLB_CHUNK_HEADER_BYTES2 = 8, GLB_JSON2 = 1313821514, GLB_BIN2 = 5130562, GLB_ALIGN = 4, JSON_PAD = 32, COUNT_WIDTH = 10, SENTINEL_BASE = 91e8, TRIANGLES = 4, FLOAT = 5126, UNSIGNED_BYTE = 5121, UNSIGNED_SHORT = 5123, UNSIGNED_INT = 5125, MESHOPT = "EXT_meshopt_compression", KTX2_MIME = "image/ktx2", INSTANCING = "EXT_mesh_gpu_instancing", STEP = "STEP", LINEAR = "LINEAR", MIN_DECIMATE_KEYS = 16, DECIMATE_STEP = 4, COMPONENT_BYTES = { 5120: 1, 5121: 1, 5122: 2, 5123: 2, 5125: 4, 5126: 4 }, TYPE_COMPONENTS = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4, MAT2: 4, MAT3: 9, MAT4: 16 };
3708
+ function elementBytes(a) {
3709
+ return (COMPONENT_BYTES[a.componentType] ?? 0) * (TYPE_COMPONENTS[a.type] ?? 0);
3710
+ }
3711
+ function readGlb(bytes) {
3712
+ if (bytes.length < (12) + (8)) return null;
3713
+ let v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
3714
+ if (v.getUint32(0, true) !== (1179937895) || v.getUint32(4, true) !== (2) || v.getUint32(8, true) !== bytes.length) return null;
3715
+ let jsonLength = v.getUint32((12), true);
3716
+ if (v.getUint32((12) + 4, true) !== (1313821514)) return null;
3717
+ let jsonStart = (12) + (8), jsonEnd = jsonStart + jsonLength;
3718
+ if (jsonEnd + (8) > bytes.length) return null;
3719
+ let binLength = v.getUint32(jsonEnd, true);
3720
+ if (v.getUint32(jsonEnd + 4, true) !== (5130562) || jsonEnd + (8) + binLength !== bytes.length) return null;
3721
+ let jsonText = new TextDecoder().decode(bytes.subarray(jsonStart, jsonEnd));
3722
+ try {
3723
+ return { gltf: JSON.parse(jsonText), jsonText, bin: bytes.subarray(jsonEnd + (8)) };
3724
+ } catch {
3725
+ return null;
3726
+ }
3727
+ }
3728
+ function countUsers(gltf) {
3729
+ let accessors = Array.from({ length: gltf.accessors?.length ?? 0 }, () => 0), views = Array.from({ length: gltf.bufferViews?.length ?? 0 }, () => 0), use = (a) => {
3730
+ a !== void 0 && a >= 0 && a < accessors.length && accessors[a]++;
3731
+ };
3732
+ for (let mesh of gltf.meshes ?? [])
3733
+ for (let p of mesh.primitives) {
3734
+ use(p.indices);
3735
+ for (let key of Object.keys(p.attributes)) use(p.attributes[key]);
3736
+ for (let t2 of p.targets ?? []) for (let key of Object.keys(t2)) use(t2[key]);
3737
+ }
3738
+ for (let s9 of gltf.skins ?? []) use(s9.inverseBindMatrices);
3739
+ for (let a of gltf.animations ?? [])
3740
+ for (let s9 of a.samplers)
3741
+ use(s9.input), use(s9.output);
3742
+ for (let n of gltf.nodes ?? []) {
3743
+ let attributes = n.extensions?.[INSTANCING]?.attributes;
3744
+ if (attributes !== void 0) for (let key of Object.keys(attributes)) use(attributes[key]);
3745
+ }
3746
+ let view2 = (index) => {
3747
+ index !== void 0 && index >= 0 && index < views.length && views[index]++;
3748
+ };
3749
+ for (let a of gltf.accessors ?? []) {
3750
+ view2(a.bufferView);
3751
+ let sparse = a.sparse;
3752
+ view2(sparse?.indices?.bufferView), view2(sparse?.values?.bufferView);
3753
+ }
3754
+ for (let image of gltf.images ?? []) view2(image.bufferView);
3755
+ return { accessors, views };
3756
+ }
3757
+ function plainView(gltf, index) {
3758
+ if (index === void 0) return null;
3759
+ let view2 = gltf.bufferViews?.[index];
3760
+ return view2 === void 0 || view2.buffer !== 0 || view2.extensions?.[MESHOPT] !== void 0 ? null : view2;
3761
+ }
3762
+ function plainAccessor(gltf, index) {
3763
+ let a = gltf.accessors?.[index];
3764
+ return a === void 0 || a.sparse !== void 0 || a.bufferView === void 0 || elementBytes(a) === 0 ? null : a;
3765
+ }
3766
+ function readFloats(bin, start, stride, count2, width) {
3767
+ let out = new Float32Array(count2 * width), v = new DataView(bin.buffer, bin.byteOffset, bin.byteLength);
3768
+ for (let i = 0; i < count2; i++) for (let k = 0; k < width; k++) out[i * width + k] = v.getFloat32(start + i * stride + k * 4, true);
3769
+ return out;
3770
+ }
3771
+ function readIndices(bin, start, count2, componentType) {
3772
+ let out = new Uint32Array(count2), v = new DataView(bin.buffer, bin.byteOffset, bin.byteLength);
3773
+ for (let i = 0; i < count2; i++)
3774
+ out[i] = componentType === (5125) ? v.getUint32(start + i * 4, true) : componentType === (5123) ? v.getUint16(start + i * 2, true) : v.getUint8(start + i);
3775
+ return out;
3776
+ }
3777
+ function encodeIndices(indices, rank, componentType) {
3778
+ let size = COMPONENT_BYTES[componentType], out = new Uint8Array(indices.length * size), v = new DataView(out.buffer);
3779
+ for (let i = 0; i < indices.length; i++) {
3780
+ let value = rank[indices[i]];
3781
+ componentType === (5125) ? v.setUint32(i * 4, value, true) : componentType === (5123) ? v.setUint16(i * 2, value, true) : v.setUint8(i, value);
3782
+ }
3783
+ return out;
3784
+ }
3785
+ function primitiveRows(gltf, users, p, vertices) {
3786
+ let accessors = [...Object.values(p.attributes), ...(p.targets ?? []).flatMap((t2) => Object.values(t2))], byView = /* @__PURE__ */ new Map();
3787
+ for (let index of accessors) {
3788
+ let a = plainAccessor(gltf, index);
3789
+ if (a === null || a.count !== vertices || users.accessors[index] !== 1 || plainView(gltf, a.bufferView) === null) return null;
3790
+ let list2 = byView.get(a.bufferView) ?? [];
3791
+ list2.push(index), byView.set(a.bufferView, list2);
3792
+ }
3793
+ let rows = [];
3794
+ for (let [viewIndex, list2] of byView) {
3795
+ let view2 = gltf.bufferViews[viewIndex];
3796
+ if (users.views[viewIndex] !== list2.length) return null;
3797
+ if (list2.length === 1) {
3798
+ let a = gltf.accessors[list2[0]], stride2 = view2.byteStride ?? elementBytes(a);
3799
+ if ((a.byteOffset ?? 0) + vertices * stride2 > view2.byteLength) return null;
3800
+ rows.push({ start: (view2.byteOffset ?? 0) + (a.byteOffset ?? 0), stride: stride2 });
3801
+ continue;
3802
+ }
3803
+ let stride = view2.byteStride;
3804
+ if (stride === void 0 || vertices * stride > view2.byteLength) return null;
3805
+ for (let index of list2) {
3806
+ let a = gltf.accessors[index];
3807
+ if ((a.byteOffset ?? 0) + elementBytes(a) > stride) return null;
3808
+ }
3809
+ rows.push({ start: view2.byteOffset ?? 0, stride });
3810
+ }
3811
+ return rows;
3812
+ }
3813
+ function planPrimitive(gltf, users, bin, p, index) {
3814
+ if ((p.mode ?? (4)) !== (4) || p.indices === void 0 || p.extensions !== void 0) return null;
3815
+ let position = p.attributes.POSITION;
3816
+ if (position === void 0) return null;
3817
+ let pa = plainAccessor(gltf, position);
3818
+ if (pa === null || pa.componentType !== (5126) || pa.type !== "VEC3") return null;
3819
+ let vertices = pa.count, ia = plainAccessor(gltf, p.indices);
3820
+ if (ia === null || ia.type !== "SCALAR" || users.accessors[p.indices] !== 1 || ia.componentType !== (5121) && ia.componentType !== (5123) && ia.componentType !== (5125) || ia.count % 3 !== 0 || ia.count / 3 < (256)) return null;
3821
+ let iv = plainView(gltf, ia.bufferView);
3822
+ if (iv === null || iv.byteStride !== void 0 || users.views[ia.bufferView] !== 1) return null;
3823
+ let indexStart = (iv.byteOffset ?? 0) + (ia.byteOffset ?? 0), indexBytes = ia.count * elementBytes(ia);
3824
+ if ((ia.byteOffset ?? 0) + indexBytes > iv.byteLength) return null;
3825
+ let rows = primitiveRows(gltf, users, p, vertices);
3826
+ if (rows === null) return null;
3827
+ let pv = gltf.bufferViews[pa.bufferView], positions = readFloats(bin, (pv.byteOffset ?? 0) + (pa.byteOffset ?? 0), pv.byteStride ?? elementBytes(pa), vertices, 3), indices = readIndices(bin, indexStart, ia.count, ia.componentType);
3828
+ for (let i = 0; i < indices.length; i++) if (indices[i] >= vertices) return null;
3829
+ let signatureParts = [], signatureWidth = 0;
3830
+ for (let [name, width] of [
3831
+ ["TEXCOORD_0", 2],
3832
+ ["NORMAL", 3]
3833
+ ]) {
3834
+ let at2 = p.attributes[name], a = at2 === void 0 ? null : plainAccessor(gltf, at2);
3835
+ if (a === null || a.componentType !== (5126)) continue;
3836
+ let view2 = gltf.bufferViews[a.bufferView];
3837
+ signatureParts.push(readFloats(bin, (view2.byteOffset ?? 0) + (a.byteOffset ?? 0), view2.byteStride ?? elementBytes(a), vertices, width)), signatureWidth += width;
3838
+ }
3839
+ let signatures = null;
3840
+ if (signatureWidth > 0) {
3841
+ signatures = new Float32Array(vertices * signatureWidth);
3842
+ let offset = 0;
3843
+ for (let part of signatureParts) {
3844
+ let width = part.length / vertices;
3845
+ for (let w = 0; w < vertices; w++) for (let k = 0; k < width; k++) signatures[w * signatureWidth + offset + k] = part[w * width + k];
3846
+ offset += width;
3847
+ }
3848
+ }
3849
+ let coarse = simplifyLods({ positions, indices, vertices, signatures, signatureWidth }, lodTargets(ia.count / 3));
3850
+ if (coarse.length === 0) return null;
3851
+ let lods = [...coarse.reverse(), indices], group = new Uint32Array(vertices).fill(lods.length - 1);
3852
+ for (let k = lods.length - 1; k >= 0; k--) for (let w of lods[k]) group[w] = k;
3853
+ let order = Uint32Array.from({ length: vertices }, (_, i) => i).sort((a, b) => group[a] - group[b] || a - b), rank = new Uint32Array(vertices);
3854
+ for (let i = 0; i < vertices; i++) rank[order[i]] = i;
3855
+ let prefix = [], at = 0;
3856
+ for (let k = 0; k < lods.length; k++) {
3857
+ for (; at < vertices && group[order[at]] <= k; ) at++;
3858
+ prefix.push(at);
3859
+ }
3860
+ return prefix[lods.length - 1] = vertices, { index, rows, indexStart, indexBytes, componentType: ia.componentType, lods, prefix, order, rank };
3861
+ }
3862
+ function planClips(gltf, users) {
3863
+ let byInput = /* @__PURE__ */ new Map(), blocked = /* @__PURE__ */ new Set();
3864
+ for (let a of gltf.animations ?? [])
3865
+ for (let s9 of a.samplers) {
3866
+ let interpolation = s9.interpolation ?? LINEAR;
3867
+ interpolation !== LINEAR && interpolation !== STEP && blocked.add(s9.input);
3868
+ let list2 = byInput.get(s9.input) ?? [];
3869
+ list2.push(s9), byInput.set(s9.input, list2);
3870
+ }
3871
+ let out = [], claimed = /* @__PURE__ */ new Set();
3872
+ for (let [input, samplers] of byInput) {
3873
+ if (blocked.has(input)) continue;
3874
+ let ia = plainAccessor(gltf, input);
3875
+ if (ia === null || ia.componentType !== (5126) || ia.type !== "SCALAR" || ia.count < (16) || users.accessors[input] !== samplers.length) continue;
3876
+ let accessors = [input], ok = true;
3877
+ for (let s9 of samplers) {
3878
+ (s9.output === input || accessors.includes(s9.output) || users.accessors[s9.output] !== 1) && (ok = false);
3879
+ let oa = plainAccessor(gltf, s9.output);
3880
+ (oa === null || oa.count % ia.count !== 0) && (ok = false), accessors.push(s9.output);
3881
+ }
3882
+ if (!ok || accessors.some((a) => claimed.has(a))) continue;
3883
+ let plans = [];
3884
+ for (let index of accessors) {
3885
+ let a = gltf.accessors[index], view2 = plainView(gltf, a.bufferView);
3886
+ if (view2 === null || view2.byteStride !== void 0) {
3887
+ ok = false;
3888
+ break;
3889
+ }
3890
+ let rowBytes = a.count / ia.count * elementBytes(a);
3891
+ if ((a.byteOffset ?? 0) + ia.count * rowBytes > view2.byteLength) {
3892
+ ok = false;
3893
+ break;
3894
+ }
3895
+ plans.push({ accessor: index, start: (view2.byteOffset ?? 0) + (a.byteOffset ?? 0), rowBytes });
3896
+ }
3897
+ if (ok) {
3898
+ for (let a of accessors) claimed.add(a);
3899
+ out.push({ keys: ia.count, accessors: plans });
3900
+ }
3901
+ }
3902
+ return out;
3903
+ }
3904
+ function planImages(gltf, users, bin) {
3905
+ let out = [];
3906
+ for (let image of gltf.images ?? []) {
3907
+ if (image.mimeType !== KTX2_MIME || image.bufferView === void 0 || users.views[image.bufferView] !== 1) continue;
3908
+ let view2 = plainView(gltf, image.bufferView);
3909
+ if (view2 === null) continue;
3910
+ let start = view2.byteOffset ?? 0, k = readKtx2(bin, start, start + view2.byteLength);
3911
+ k === null || baseLevel(k) === 0 || out.push({ start, end: start + view2.byteLength });
3912
+ }
3913
+ return out;
3914
+ }
3915
+ function overlapping(ranges) {
3916
+ let sorted = [...ranges].sort((a, b) => a.start - b.start || a.end - b.end), bad = /* @__PURE__ */ new Set();
3917
+ for (let i = 1; i < sorted.length; i++)
3918
+ sorted[i].start < sorted[i - 1].end && (bad.add(sorted[i].owner), bad.add(sorted[i - 1].owner));
3919
+ return bad;
3920
+ }
3921
+ function digits(value) {
3922
+ return new TextEncoder().encode(String(value).padStart((10), " "));
3923
+ }
3924
+ function sentinelOffsets(json, sentinels) {
3925
+ let text = new TextDecoder("latin1").decode(json), out = [];
3926
+ for (let s9 of sentinels) {
3927
+ let needle = String(s9), at = text.indexOf(needle);
3928
+ if (at < 0 || text.indexOf(needle, at + 1) >= 0) return null;
3929
+ out.push(at);
3930
+ }
3931
+ return out;
3932
+ }
3933
+ function firstLevelBytes(plan) {
3934
+ let n = 0;
3935
+ for (let unit of plan.levels[0] ?? []) for (let segment of unit.segments) n += segment.bytes.length;
3936
+ return n;
3937
+ }
3938
+ function planMesh(bytes) {
3939
+ let boot = planBootTier(bytes), layered = planMeshLevels(bytes);
3940
+ return boot === null ? layered : layered === null ? boot : firstLevelBytes(layered.plan) < firstLevelBytes(boot.plan) ? layered : boot;
3941
+ }
3942
+ function planMeshLevels(bytes) {
3943
+ let glb = readGlb(bytes);
3944
+ if (glb === null) return null;
3945
+ let { gltf } = glb;
3946
+ for (let b = 1; b < (gltf.buffers ?? []).length; b++) {
3947
+ let buffer = (gltf.buffers ?? [])[b];
3948
+ if (buffer.uri !== void 0 || buffer.extensions?.[MESHOPT] === void 0) return null;
3949
+ }
3950
+ if (gltf.buffers?.[0]?.uri !== void 0) return null;
3951
+ let users = countUsers(gltf), bin = Uint8Array.from(glb.bin), primitives = [], primitiveIndex = 0;
3952
+ for (let mesh of gltf.meshes ?? [])
3953
+ for (let p of mesh.primitives) {
3954
+ let planned = planPrimitive(gltf, users, bin, p, primitiveIndex);
3955
+ planned !== null && primitives.push(planned), primitiveIndex++;
3956
+ }
3957
+ let images = planImages(gltf, users, bin), clips = planClips(gltf, users), ranges = [];
3958
+ for (let p of primitives) {
3959
+ for (let r of p.rows) ranges.push({ start: r.start, end: r.start + p.order.length * r.stride, owner: `p${p.index}` });
3960
+ ranges.push({ start: p.indexStart, end: p.indexStart + p.indexBytes, owner: `p${p.index}` });
3961
+ }
3962
+ images.forEach((im, i) => ranges.push({ start: im.start, end: im.end, owner: `i${i}` })), clips.forEach((c, i) => {
3963
+ for (let a of c.accessors) ranges.push({ start: a.start, end: a.start + c.keys * a.rowBytes, owner: `c${i}` });
3964
+ });
3965
+ let bad = overlapping(ranges), keptPrimitives = primitives.filter((p) => !bad.has(`p${p.index}`));
3966
+ if (images = images.filter((_, i) => !bad.has(`i${i}`)), clips = clips.filter((_, i) => !bad.has(`c${i}`)), keptPrimitives.length === 0 && images.length === 0 && clips.length === 0) return null;
3967
+ for (let p of keptPrimitives) {
3968
+ for (let r of p.rows) {
3969
+ let length = p.order.length * r.stride, old = bin.slice(r.start, r.start + length);
3970
+ for (let i = 0; i < p.order.length; i++) bin.set(old.subarray(p.order[i] * r.stride, (p.order[i] + 1) * r.stride), r.start + i * r.stride);
3971
+ }
3972
+ bin.set(encodeIndices(p.lods[p.lods.length - 1], p.rank, p.componentType), p.indexStart);
3973
+ }
3974
+ let edited = structuredClone(gltf), sentinels = [], counted = [], sentinel = (accessor) => {
3975
+ let a = edited.accessors[accessor], value = (91e8) + counted.length;
3976
+ counted.push({ accessor, full: a.count }), sentinels.push(value), a.count = value;
3977
+ };
3978
+ for (let p of keptPrimitives) {
3979
+ let prim = (edited.meshes ?? []).flatMap((m) => m.primitives)[p.index], a = edited.accessors[prim.indices];
3980
+ delete a.min, delete a.max, sentinel(prim.indices);
3981
+ }
3982
+ for (let c of clips) for (let a of c.accessors) sentinel(a.accessor);
3983
+ let encoded = new TextEncoder().encode(JSON.stringify(edited)), jsonLength = Math.ceil(encoded.length / (4)) * (4), json = new Uint8Array(jsonLength).fill((32));
3984
+ json.set(encoded);
3985
+ let found = sentinelOffsets(json, sentinels);
3986
+ if (found === null) return null;
3987
+ let jsonAt = (12) + (8), countAt = /* @__PURE__ */ new Map();
3988
+ counted.forEach((c, i) => {
3989
+ json.set(digits(c.full), found[i]), countAt.set(c.accessor, jsonAt + found[i]);
3990
+ });
3991
+ let binAt = jsonAt + jsonLength + (8), source = new Uint8Array(binAt + bin.length), sv = new DataView(source.buffer);
3992
+ return sv.setUint32(0, (1179937895), true), sv.setUint32(4, (2), true), sv.setUint32(8, source.length, true), sv.setUint32((12), jsonLength, true), sv.setUint32((12) + 4, (1313821514), true), source.set(json, jsonAt), sv.setUint32(jsonAt + jsonLength, bin.length, true), sv.setUint32(jsonAt + jsonLength + 4, (5130562), true), source.set(bin, binAt), { plan: schedule(source, binAt, keptPrimitives, images, clips, countAt, gltf), source };
3993
+ }
3994
+ function schedule(source, binAt, primitives, images, clips, countAt, gltf) {
3995
+ let table = new TableWriter(), slice = (start, end) => ({ dest: start, bytes: source.subarray(start, end) }), countPatch = (accessor, value) => writePatch(table, countAt.get(accessor), digits(value)), dynamic = [], base = [], basePatches = [], refinements = [], components = [], primitiveList = (gltf.meshes ?? []).flatMap((m) => m.primitives), order = 0;
3996
+ for (let p of primitives) {
3997
+ let indexAccessor = primitiveList[p.index].indices, indexStart = binAt + p.indexStart, rows = p.rows.map((r) => ({ start: binAt + r.start, stride: r.stride })), weight = p.indexBytes;
3998
+ for (let r of rows)
3999
+ dynamic.push({ start: r.start, end: r.start + p.order.length * r.stride, owner: "" }), weight += p.order.length * r.stride;
4000
+ dynamic.push({ start: indexStart, end: indexStart + p.indexBytes, owner: "" });
4001
+ let full = p.lods[p.lods.length - 1].length, component = { weight, quality: p.lods[0].length / full };
4002
+ components.push(component);
4003
+ for (let r of rows) base.push(slice(r.start, r.start + p.prefix[0] * r.stride));
4004
+ base.push({ dest: indexStart, bytes: encodeIndices(p.lods[0], p.rank, p.componentType) }), basePatches.push(countPatch(indexAccessor, p.lods[0].length));
4005
+ for (let k = 1; k < p.lods.length; k++) {
4006
+ let segments = rows.map((r) => slice(r.start + p.prefix[k - 1] * r.stride, r.start + p.prefix[k] * r.stride)), indices = k === p.lods.length - 1 ? source.subarray(indexStart, indexStart + p.indexBytes) : encodeIndices(p.lods[k], p.rank, p.componentType);
4007
+ segments.push({ dest: 0, bytes: indices, staged: true });
4008
+ let patches = [{ op: PatchOp.staged, a: indexStart, b: 0, c: indices.length }, countPatch(indexAccessor, p.lods[k].length)];
4009
+ refinements.push({ step: k, order: order++, unit: { segments, patches }, component, quality: p.lods[k].length / full });
4010
+ }
4011
+ }
4012
+ for (let image of images) {
4013
+ let start = binAt + image.start, k = readKtx2(source, start, binAt + image.end);
4014
+ dynamic.push({ start, end: binAt + image.end, owner: "" });
4015
+ let b = baseLevel(k), full = texels(k, 0), component = { weight: image.end - image.start, quality: texels(k, b) / full };
4016
+ components.push(component);
4017
+ let states = new KtxStates(source, k, table);
4018
+ base.push(slice(start, levelEnd(k, b))), basePatches.push(...states.state(b));
4019
+ for (let level = b - 1; level >= 0; level--) {
4020
+ let unit = { segments: [slice(levelStart(k, level), levelEnd(k, level))], patches: states.state(level) };
4021
+ refinements.push({ step: b - level, order: order++, unit, component, quality: texels(k, level) / full });
4022
+ }
4023
+ }
4024
+ for (let clip of clips) {
4025
+ let coarse = coarseKeys(clip.keys, (4)), weight = 0, staged = [], patches = [], stagingAt = 0;
4026
+ for (let a of clip.accessors) {
4027
+ let start = binAt + a.start, length = clip.keys * a.rowBytes;
4028
+ weight += length, dynamic.push({ start, end: start + length, owner: "" });
4029
+ let front = new Uint8Array(coarse * a.rowBytes), rest = new Uint8Array((clip.keys - coarse) * a.rowBytes), f = 0, r = 0;
4030
+ for (let i = 0; i < clip.keys; i++) {
4031
+ let row = source.subarray(start + i * a.rowBytes, start + (i + 1) * a.rowBytes);
4032
+ isCoarseKey(i, clip.keys, (4)) ? front.set(row, f++ * a.rowBytes) : rest.set(row, r++ * a.rowBytes);
4033
+ }
4034
+ base.push({ dest: start, bytes: front });
4035
+ let ratio = a.rowBytes / elementBytes(gltf.accessors[a.accessor]);
4036
+ basePatches.push(countPatch(a.accessor, coarse * ratio)), staged.push({ dest: stagingAt, bytes: rest, staged: true }), patches.push({ op: PatchOp.merge, a: start, b: stagingAt, c: table.words(clip.keys, a.rowBytes, (4)) }), patches.push(countPatch(a.accessor, clip.keys * ratio)), stagingAt += rest.length;
4037
+ }
4038
+ let component = { weight, quality: coarse / clip.keys };
4039
+ components.push(component), refinements.push({ step: 1, order: order++, unit: { segments: staged, patches }, component, quality: 1 });
4040
+ }
4041
+ dynamic.sort((a, b) => a.start - b.start);
4042
+ let statics = [slice(0, binAt)], cursor = binAt;
4043
+ for (let r of dynamic)
4044
+ r.start > cursor && statics.push(slice(cursor, r.start)), cursor = Math.max(cursor, r.end);
4045
+ cursor < source.length && statics.push(slice(cursor, source.length));
4046
+ let staticWeight = 0;
4047
+ for (let s9 of statics) staticWeight += s9.bytes.length;
4048
+ let total = staticWeight;
4049
+ for (let c of components) total += c.weight;
4050
+ let quality = () => {
4051
+ let value = staticWeight;
4052
+ for (let c of components) value += c.weight * c.quality;
4053
+ return Math.min(PPM, Math.floor(value * PPM / total));
4054
+ }, levels = [[{ segments: [...statics, ...base], patches: basePatches, quality: quality() }]];
4055
+ refinements.sort((a, b) => a.step - b.step || unitBytes(a.unit) - unitBytes(b.unit) || a.order - b.order);
4056
+ let step = 0;
4057
+ for (let i = 0; i < refinements.length; i++) {
4058
+ let r = refinements[i];
4059
+ r.component.quality = r.quality;
4060
+ let last = i === refinements.length - 1, unit = { ...r.unit, quality: last ? PPM : quality() };
4061
+ r.step !== step && (levels.push([]), step = r.step), levels[levels.length - 1].push(unit);
4062
+ }
4063
+ return { kind: ProgressiveKind.mesh, output: source.length, levels, table: table.finish() };
4064
+ }
4065
+ function unitBytes(unit) {
4066
+ let n = 0;
4067
+ for (let s9 of unit.segments) n += s9.bytes.length;
4068
+ return n;
4069
+ }
4070
+ var BOOT_HINT = "cimplify_boot", BOOT_HINT_VERSION = 1;
4071
+ function accessorRefs(value, out) {
4072
+ if (typeof value == "number" && Number.isInteger(value)) out.add(value);
4073
+ else if (Array.isArray(value)) for (let v of value) accessorRefs(v, out);
4074
+ else if (value !== null && typeof value == "object") for (let v of Object.values(value)) accessorRefs(v, out);
4075
+ }
4076
+ function usedAccessors(gltf) {
4077
+ let used = /* @__PURE__ */ new Set();
4078
+ for (let mesh of gltf.meshes ?? [])
4079
+ for (let p of mesh.primitives) {
4080
+ p.indices !== void 0 && used.add(p.indices);
4081
+ for (let a of Object.values(p.attributes)) used.add(a);
4082
+ for (let t2 of p.targets ?? []) for (let a of Object.values(t2)) used.add(a);
4083
+ accessorRefs(p.extensions, used);
4084
+ }
4085
+ for (let s9 of gltf.skins ?? []) s9.inverseBindMatrices !== void 0 && used.add(s9.inverseBindMatrices);
4086
+ for (let a of gltf.animations ?? [])
4087
+ for (let s9 of a.samplers)
4088
+ used.add(s9.input), used.add(s9.output);
4089
+ for (let n of gltf.nodes ?? []) accessorRefs(n.extensions?.[INSTANCING]?.attributes, used);
4090
+ return used;
4091
+ }
4092
+ function usedViews(gltf, accessors) {
4093
+ let views = /* @__PURE__ */ new Set();
4094
+ for (let index of accessors) {
4095
+ let a = gltf.accessors?.[index];
4096
+ a?.bufferView !== void 0 && views.add(a.bufferView);
4097
+ let sparse = a?.sparse;
4098
+ sparse?.indices?.bufferView !== void 0 && views.add(sparse.indices.bufferView), sparse?.values?.bufferView !== void 0 && views.add(sparse.values.bufferView);
4099
+ }
4100
+ for (let image of gltf.images ?? []) image.bufferView !== void 0 && views.add(image.bufferView);
4101
+ return views;
4102
+ }
4103
+ function viewRange(view2) {
4104
+ let compressed = view2.extensions?.[MESHOPT];
4105
+ return compressed !== void 0 ? compressed.buffer === 0 ? [compressed.byteOffset ?? 0, (compressed.byteOffset ?? 0) + compressed.byteLength] : null : view2.buffer === 0 ? [view2.byteOffset ?? 0, (view2.byteOffset ?? 0) + view2.byteLength] : null;
4106
+ }
4107
+ function paddedJson(json, length) {
4108
+ let out = new Uint8Array(length).fill((32));
4109
+ return out.set(json), out;
4110
+ }
4111
+ function planBootTier(bytes) {
4112
+ let glb = readGlb(bytes);
4113
+ if (glb === null) return null;
4114
+ let root = glb.gltf, hint = root.extras?.[BOOT_HINT];
4115
+ if (hint === void 0 || hint.version !== (1)) return null;
4116
+ let whole = structuredClone(root);
4117
+ delete whole.extras[BOOT_HINT], Object.keys(whole.extras ?? {}).length === 0 && delete whole.extras;
4118
+ let base = structuredClone(whole);
4119
+ for (let p of hint.primitives ?? []) {
4120
+ let primitive = base.meshes?.[p.mesh]?.primitives[p.primitive];
4121
+ if (primitive === void 0) return null;
4122
+ primitive.attributes = { ...p.attributes }, primitive.indices = p.indices, delete primitive.extensions;
4123
+ }
4124
+ for (let s9 of hint.samplers ?? []) {
4125
+ let sampler = base.animations?.[s9.animation]?.samplers[s9.sampler];
4126
+ if (sampler === void 0) return null;
4127
+ sampler.input = s9.input, sampler.output = s9.output;
4128
+ }
4129
+ (base.animations ?? []).forEach((animation, index) => {
4130
+ index !== (hint.clip ?? 0) && (animation.samplers = [], animation.channels = []);
4131
+ });
4132
+ let live = usedAccessors(base), baseViews = usedViews(base, live);
4133
+ base.accessors = (base.accessors ?? []).map(
4134
+ (accessor, index) => live.has(index) || accessor.bufferView === void 0 || baseViews.has(accessor.bufferView) ? accessor : { bufferView: accessor.bufferView, componentType: (5121), count: 1, type: "SCALAR" }
4135
+ );
4136
+ let late = [];
4137
+ (base.bufferViews ?? []).forEach((view2, index) => {
4138
+ if (baseViews.has(index)) return;
4139
+ let range = viewRange(view2);
4140
+ range !== null && late.push(range), view2.extensions?.[MESHOPT] !== void 0 && (delete view2.extensions[MESHOPT], Object.keys(view2.extensions).length === 0 && delete view2.extensions);
4141
+ });
4142
+ let kept = (whole.bufferViews ?? []).map((view2, index) => baseViews.has(index) ? viewRange(view2) : null).filter((r) => r !== null), reserved = late.filter(([start, end]) => !kept.some(([a, b]) => a < end && start < b));
4143
+ if (reserved.length === 0) return null;
4144
+ let encoder2 = new TextEncoder(), baseJson = encoder2.encode(JSON.stringify(base)), wholeJson = encoder2.encode(JSON.stringify(whole)), length = Math.ceil(Math.max(baseJson.length, wholeJson.length) / (4)) * (4), jsonAt = (12) + (8), binAt = jsonAt + length + (8), source = new Uint8Array(binAt + glb.bin.length), sv = new DataView(source.buffer);
4145
+ sv.setUint32(0, (1179937895), true), sv.setUint32(4, (2), true), sv.setUint32(8, source.length, true), sv.setUint32((12), length, true), sv.setUint32((12) + 4, (1313821514), true), source.set(paddedJson(wholeJson, length), jsonAt), sv.setUint32(binAt - (8), glb.bin.length, true), sv.setUint32(binAt - (8) + 4, (5130562), true), source.set(glb.bin, binAt), reserved.sort((a, b) => a[0] - b[0]);
4146
+ let slice = (start, end) => ({ dest: start, bytes: source.subarray(start, end) }), head = [slice(0, jsonAt), { dest: jsonAt, bytes: baseJson }, slice(binAt - (8), binAt)], pad = { op: PatchOp.fill, a: jsonAt + baseJson.length, b: (32), c: length - baseJson.length }, refinement = [slice(jsonAt, jsonAt + length)], cursor = 0, deferred = 0;
4147
+ for (let [start, end] of reserved) {
4148
+ start > cursor && head.push(slice(binAt + cursor, binAt + start));
4149
+ let from = Math.max(start, cursor);
4150
+ end > from && (refinement.push(slice(binAt + from, binAt + end)), deferred += end - from), cursor = Math.max(cursor, end);
4151
+ }
4152
+ cursor < glb.bin.length && head.push(slice(binAt + cursor, binAt + glb.bin.length));
4153
+ let quality = Math.floor((source.length - deferred) * PPM / source.length), table = new TableWriter();
4154
+ return {
4155
+ plan: {
4156
+ kind: ProgressiveKind.mesh,
4157
+ output: source.length,
4158
+ levels: [[{ segments: head, patches: pad.c > 0 ? [pad] : [], quality }], [{ segments: refinement, patches: [], quality: PPM }]],
4159
+ table: table.finish()
4160
+ },
4161
+ source
4162
+ };
4163
+ }
4164
+
4165
+ // src/interactives/progressive/mips.ts
4166
+ var VK_R8G8B8A8_UNORM = 37, VK_R8G8B8A8_SRGB = 43, VK_R16G16B16A16_SFLOAT = 97, SCHEME_NONE = 0, SCHEME_ZSTD = 2, HEADER_VK_FORMAT = 12, HEADER_TYPE_SIZE = 16, HEADER_WIDTH = 20, HEADER_HEIGHT = 24, HEADER_DEPTH = 28, HEADER_LAYERS = 32, HEADER_FACES = 36, HEADER_LEVELS = 40, HEADER_SCHEME = 44, HEADER_DFD_OFFSET = 48, HEADER_DFD_LENGTH = 52, HEADER_KVD_OFFSET = 56, HEADER_KVD_LENGTH = 60, HEADER_SGD_OFFSET = 64, HEADER_SGD_LENGTH = 72, LEVEL_INDEX = 80, LEVEL_ENTRY = 24, LEVEL_LENGTH = 8, LEVEL_UNCOMPRESSED = 16, CHANNELS = 4, HALF_BYTES = 2, ALIGN = 4, SRGB_CUTOFF = 0.04045, SRGB_LINEAR_CUTOFF = 31308e-7, SRGB_SCALE = 12.92, SRGB_A = 0.055, SRGB_GAMMA = 2.4, BYTE_MAX = 255, HALF_EXPONENT_BIAS = 15, FLOAT_EXPONENT_BIAS = 127, HALF_MANTISSA_BITS = 10, FLOAT_MANTISSA_BITS = 23, HALF_EXPONENT_MAX = 31, SAMPLES_PER_TEXEL = 4;
4167
+ function formatOf(vk) {
4168
+ return vk === (37) ? "unorm" : vk === (43) ? "srgb" : vk === (97) ? "half" : null;
4169
+ }
4170
+ var scratch = new DataView(new ArrayBuffer(4));
4171
+ function halfToFloat(bits) {
4172
+ let sign = bits & 32768 ? -1 : 1, exponent = bits >> (10) & (31), mantissa = bits & 1023;
4173
+ return exponent === 0 ? sign * mantissa * 2 ** (1 - (15) - (10)) : exponent === (31) ? mantissa === 0 ? sign * (1 / 0) : Number.NaN : sign * (1 + mantissa / (1 << (10))) * 2 ** (exponent - (15));
4174
+ }
4175
+ function floatToHalf(value) {
4176
+ scratch.setFloat32(0, value);
4177
+ let bits = scratch.getUint32(0), sign = bits >>> 16 & 32768, exponent = (bits >>> (23) & 255) - (127) + (15), mantissa = bits & 8388607;
4178
+ return exponent <= 0 ? sign : exponent >= (31) ? sign | 31744 : sign | exponent << (10) | mantissa >>> (23) - (10);
4179
+ }
4180
+ function toLinear(byte) {
4181
+ let c = byte / (255);
4182
+ return c <= (0.04045) ? c / (12.92) : ((c + (0.055)) / (1 + (0.055))) ** (2.4);
4183
+ }
4184
+ function toSrgb(linear) {
4185
+ let c = linear <= (31308e-7) ? linear * (12.92) : (1 + (0.055)) * linear ** (1 / (2.4)) - (0.055);
4186
+ return Math.round(Math.min(1, Math.max(0, c)) * (255));
4187
+ }
4188
+ function read(level, format) {
4189
+ let texels2 = format === "half" ? level.length / (2) : level.length, out = new Float32Array(texels2);
4190
+ if (format === "half") {
4191
+ let view2 = new DataView(level.buffer, level.byteOffset, level.byteLength);
4192
+ for (let i = 0; i < texels2; i++) out[i] = halfToFloat(view2.getUint16(i * (2), true));
4193
+ } else
4194
+ for (let i = 0; i < texels2; i++) out[i] = format === "srgb" && i % (4) !== (4) - 1 ? toLinear(level[i]) : level[i] / (255);
4195
+ return out;
4196
+ }
4197
+ function write(values, format) {
4198
+ if (format === "half") {
4199
+ let out2 = new Uint8Array(values.length * (2)), view2 = new DataView(out2.buffer);
4200
+ for (let i = 0; i < values.length; i++) view2.setUint16(i * (2), floatToHalf(values[i]), true);
4201
+ return out2;
4202
+ }
4203
+ let out = new Uint8Array(values.length);
4204
+ for (let i = 0; i < values.length; i++)
4205
+ out[i] = format === "srgb" && i % (4) !== (4) - 1 ? toSrgb(values[i]) : Math.round(Math.min(1, Math.max(0, values[i])) * (255));
4206
+ return out;
4207
+ }
4208
+ function halve(source, width, height) {
4209
+ let w = Math.max(1, width >>> 1), h = Math.max(1, height >>> 1), out = new Float32Array(w * h * (4));
4210
+ for (let y = 0; y < h; y++)
4211
+ for (let x = 0; x < w; x++)
4212
+ for (let c = 0; c < (4); c++) {
4213
+ let sum = 0;
4214
+ for (let dy = 0; dy < 2; dy++)
4215
+ for (let dx = 0; dx < 2; dx++) {
4216
+ let sx = Math.min(width - 1, x * 2 + dx), sy = Math.min(height - 1, y * 2 + dy);
4217
+ sum += source[(sy * width + sx) * (4) + c];
4218
+ }
4219
+ out[(y * w + x) * (4) + c] = sum / (4);
4220
+ }
4221
+ return { values: out, width: w, height: h };
4222
+ }
4223
+ function align(value) {
4224
+ return Math.ceil(value / (4)) * (4);
4225
+ }
4226
+ function withMipChain(bytes, inflate, compress) {
4227
+ if (!isKtx2At(bytes, 0, bytes.length)) return null;
4228
+ let v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength), format = formatOf(v.getUint32((12), true)), scheme = v.getUint32((44), true), width = v.getUint32((20), true), height = v.getUint32((24), true);
4229
+ if (format === null || Math.max(1, v.getUint32((40), true)) !== 1 || v.getUint32((28), true) !== 0 || v.getUint32((32), true) > 1 || v.getUint32((36), true) !== 1 || width < 2 || height < 2 || scheme !== (0) && (scheme !== (2) || inflate === null || compress === null) || Number(v.getBigUint64((72), true)) !== 0) return null;
4230
+ let offset = Number(v.getBigUint64((80), true)), length = Number(v.getBigUint64((80) + (8), true)), stored = bytes.subarray(offset, offset + length), level0 = scheme === (2) ? inflate?.(stored) ?? null : stored, texelBytes = format === "half" ? (4) * (2) : (4);
4231
+ if (level0 === null || level0.length !== width * height * texelBytes) return null;
4232
+ let levels = [level0], current = { values: read(level0, format), width, height };
4233
+ for (; current.width > 1 || current.height > 1; )
4234
+ current = halve(current.values, current.width, current.height), levels.push(write(current.values, format));
4235
+ let encoded = levels.map((level) => scheme === (2) && compress !== null ? compress(level) : level), dfdOffset = v.getUint32((48), true), dfdLength = v.getUint32((52), true), kvdOffset = v.getUint32((56), true), kvdLength = v.getUint32((60), true), indexEnd = (80) + levels.length * (24), newDfd = align(indexEnd), newKvd = kvdLength === 0 ? 0 : align(newDfd + dfdLength), at = align(kvdLength === 0 ? newDfd + dfdLength : newKvd + kvdLength), placed = new Array(levels.length).fill(0);
4236
+ for (let l = levels.length - 1; l >= 0; l--)
4237
+ placed[l] = at, at = align(at + encoded[l].length);
4238
+ let total = placed[0] + encoded[0].length, out = new Uint8Array(total), w = new DataView(out.buffer);
4239
+ return out.set(bytes.subarray(0, (80))), w.setUint32((40), levels.length, true), w.setUint32((48), newDfd, true), w.setUint32((56), newKvd, true), w.setBigUint64((64), 0n, true), w.setBigUint64((72), 0n, true), w.setUint32((16), v.getUint32((16), true), true), levels.forEach((level, l) => {
4240
+ let entry = (80) + l * (24);
4241
+ w.setBigUint64(entry, BigInt(placed[l]), true), w.setBigUint64(entry + (8), BigInt(encoded[l].length), true), w.setBigUint64(entry + (16), BigInt(level.length), true);
4242
+ }), out.set(bytes.subarray(dfdOffset, dfdOffset + dfdLength), newDfd), kvdLength > 0 && out.set(bytes.subarray(kvdOffset, kvdOffset + kvdLength), newKvd), encoded.forEach((level, l) => out.set(level, placed[l])), out;
4243
+ }
4244
+
4245
+ // src/interactives/progressive/splat.ts
4246
+ var CSPL_MAGIC = 1280332611, CSPL_VERSION = 3, CSPL_VERSION_STATIC = 2, CSPL_HEADER_BYTES = 120, CSPL_HEADER_BYTES_STATIC = 96, CSPL_REGIONS = 96, CSPL_SKIN = 100, REGION_PLANES = 1, SKIN_PLANES = 8, CSPL_COUNT = 8, CSPL_FLAGS = 12, CSPL_LEVEL1 = 56, CSPL_LEVEL2 = 60, CSPL_PALETTE = 64, CSPL_PAYLOAD = 92, SH_DEGREE_MASK = 255, CODEC_SHIFT = 8, CODEC_MASK = 255, CODEC_RAW = 0, CODEC_ZSTD = 1, BASE_PLANES = 16, LABEL_PLANES = 2, CHANNELS2 = 3, REST_BY_DEGREE = [0, 3, 8, 15];
4247
+ function isSplatChunk(bytes) {
4248
+ return bytes.length >= (96) && new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0, true) === (1280332611);
4249
+ }
4250
+ function planSplat(bytes, inflate, compress) {
4251
+ if (!isSplatChunk(bytes) || compress === null) return null;
4252
+ let v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength), version = v.getUint32(4, true);
4253
+ if (version !== (3) && version !== (2)) return null;
4254
+ let headerBytes = version === (3) ? (120) : (96);
4255
+ if (bytes.length < headerBytes) return null;
4256
+ let skinned = version === (3) && v.getUint32((100), true) !== 0, labelled = version === (3) && v.getUint32((96), true) !== 0, count2 = v.getUint32((8), true), flags = v.getUint32((12), true), codec = flags >>> (8) & (255), degree = flags & (255);
4257
+ if (degree >= REST_BY_DEGREE.length) return null;
4258
+ let planes = (16) + (degree > 0 ? (2) : 0) + (labelled ? (1) : 0) + (skinned ? (8) : 0), paletteBytes = v.getUint32((64), true) * REST_BY_DEGREE[degree] * (3), payloadBytes = v.getUint32((92), true);
4259
+ if (headerBytes + payloadBytes !== bytes.length || count2 === 0) return null;
4260
+ let payload = bytes.subarray(headerBytes), raw = codec === (0) ? payload : codec === (1) && inflate !== null ? inflate(payload) : null;
4261
+ if (raw === null || raw.length !== count2 * planes + paletteBytes) return null;
4262
+ let level1 = Math.min(count2, v.getUint32((56), true)), level2 = Math.min(level1, v.getUint32((60), true)), bounds2 = [0, level2, level1, count2].filter((b, i, all) => i === 0 || b > all[i - 1]), bands = bounds2.length - 1;
4263
+ if (bands < 2) return null;
4264
+ let frames = [];
4265
+ for (let p = 0; p < planes; p++) {
4266
+ let row = [];
4267
+ for (let k = 0; k < bands; k++) row.push(compress(raw.subarray(p * count2 + bounds2[k], p * count2 + bounds2[k + 1])));
4268
+ frames.push(row);
4269
+ }
4270
+ let palette = paletteBytes > 0 ? compress(raw.subarray(count2 * planes)) : new Uint8Array(0), payloadFor = (last) => {
4271
+ let n = palette.length;
4272
+ for (let p = 0; p < planes; p++) for (let k = 0; k <= last; k++) n += frames[p][k].length;
4273
+ return n;
4274
+ }, full = payloadFor(bands - 1), source = new Uint8Array(headerBytes + full);
4275
+ source.set(bytes.subarray(0, headerBytes));
4276
+ let sv = new DataView(source.buffer);
4277
+ sv.setUint32((12), flags & -65281 | (1) << (8), true), sv.setUint32((92), full, true);
4278
+ let at = headerBytes;
4279
+ for (let p = 0; p < planes; p++)
4280
+ for (let k = 0; k < bands; k++)
4281
+ source.set(frames[p][k], at), at += frames[p][k].length;
4282
+ source.set(palette, at);
4283
+ let table = new TableWriter(), scratch2 = frames.map(() => []), staging = 0, paletteAt = 0, levels = [];
4284
+ for (let k = 0; k < bands; k++) {
4285
+ let segments = [];
4286
+ for (let p = 0; p < planes; p++)
4287
+ scratch2[p].push(staging), segments.push({ dest: staging, bytes: frames[p][k], staged: true }), staging += frames[p][k].length;
4288
+ k === 0 && palette.length > 0 && (paletteAt = staging, segments.push({ dest: staging, bytes: palette, staged: true }), staging += palette.length);
4289
+ let records = bounds2[k + 1], last = k === bands - 1, header = source.slice(0, headerBytes), hv = new DataView(header.buffer);
4290
+ hv.setUint32((8), records, true), hv.setUint32((56), Math.min(level1, records), true), hv.setUint32((60), Math.min(level2, records), true), hv.setUint32((92), payloadFor(k), true);
4291
+ let patches = [writePatch(table, 0, header)], out = headerBytes;
4292
+ for (let p = 0; p < planes; p++)
4293
+ for (let b = 0; b <= k; b++)
4294
+ patches.push({ op: PatchOp.staged, a: out, b: scratch2[p][b], c: frames[p][b].length }), out += frames[p][b].length;
4295
+ palette.length > 0 && (patches.push({ op: PatchOp.staged, a: out, b: paletteAt, c: palette.length }), out += palette.length), patches.push({ op: PatchOp.length, a: out, b: 0, c: 0 }), levels.push([{ segments, patches, quality: last ? PPM : Math.floor(records * PPM / count2) }]);
4296
+ }
4297
+ return { plan: { kind: ProgressiveKind.splat, output: source.length, levels, table: table.finish() }, source };
4298
+ }
4299
+
4300
+ // src/interactives/progressive/build.ts
4301
+ var MIN_PROGRESSIVE_BYTES = 16 * 1024, DEFAULT_PROGRESSIVE_KINDS = /* @__PURE__ */ new Set(["texture", "mesh", "audio", "cells", "splat"]);
4302
+ function planFor(bytes, options) {
4303
+ let allowed = (kind) => options.kinds === void 0 || options.kinds.has(kind), mesh = allowed("mesh") ? planMesh(bytes) : null;
4304
+ if (mesh !== null) return mesh;
4305
+ if (allowed("texture")) {
4306
+ let mipped = withMipChain(bytes, options.inflate ?? null, options.compress ?? null) ?? bytes, texture = planTexture(mipped);
4307
+ if (texture !== null) return { plan: texture, source: mipped };
4308
+ }
4309
+ let splat = allowed("splat") ? planSplat(bytes, options.inflate ?? null, options.compress ?? null) : null;
4310
+ if (splat !== null) return splat;
4311
+ let audio = allowed("audio") ? planAudio(bytes) : null;
4312
+ if (audio !== null) return { plan: audio, source: bytes };
4313
+ let cells = allowed("cells") ? planCells(bytes) : null;
4314
+ return cells !== null ? { plan: cells, source: bytes } : null;
4315
+ }
4316
+ function buildProgressive(input, options = {}) {
4317
+ if (input.length < (options.minBytes ?? MIN_PROGRESSIVE_BYTES)) return null;
4318
+ let bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength), planned = planFor(bytes, options);
4319
+ if (planned === null || planned.plan.levels.length < 2) return null;
4320
+ let encoded = encodeContainer(planned.plan);
4321
+ return {
4322
+ kind: planned.plan.kind,
4323
+ source: planned.source,
4324
+ container: encoded.bytes,
4325
+ head: encoded.head,
4326
+ first: encoded.first,
4327
+ levelEnds: encoded.levelEnds,
4328
+ unitEnds: encoded.unitEnds,
4329
+ levelQuality: planned.plan.levels.map((l) => l[l.length - 1].quality)
4330
+ };
4331
+ }
4332
+
4333
+ export { AI_MARK_LABEL, AI_MARK_NAMESPACE, AI_MARK_SOURCES, AI_MARK_TEXT, AiMark, Badge, COZY_PASTEL, ChatLog, ChatPanel, Countdown, DEFAULT_AI_MARK, DEFAULT_LANGUAGES, DEFAULT_QUALITIES, DamageNumbers, Dropdown, FANTASY_PARCHMENT, GeneratedText, InventoryGrid, KIT_NAMESPACE, Leaderboard, LoadingScreen, MAP_HEADING, MAP_PAN_X, MAP_PAN_Y, Minimap, Modal, ModalStack, NEON_ARCADE, PauseScreen, RICH_COLORS, RadialMenu, ResultsScreen, RichText, RichTextError, SIMULATOR_FIXED_STEP_MS, SPORTS_BROADCAST, SettingsScreen, SimulatorUnsupportedError, Slider, THEME_PACKS, TextButton, Toggle, Tooltip, TutorialHint, UI_DEFAULT_FONT, UI_FONT_ROLES, UI_FONT_SET, UiFocusScope, UiNavigator, UiParticles, VirtualList, aiLabel, aiMark, aiMarkTheme, aiMarkVars, applyThemePack, badge, chatLog, chatPanel, countdown, createSimulatorCtx, currentThemePack, damageNumbers, dropdown, focusNodeOf, fontStyle, generatedText, generate_exports as generation, inventoryGrid, isAiGenerated, kitFamily, kitVars, leaderboard, loadingScreen, minimap, modal, modalStack, parts_exports as parts, pauseScreen, progressive_exports as progressive, radialMenu, registerUiFont, resultsScreen, richText, settingsScreen, slider, textButton, themePack, toggle, tooltip, tutorialHint, uiParticles, virtualList, worlds_exports as worlds };