@popcraft/kit 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/chunks/{agent-45ZGYKTC.js → agent-NTEAEZBN.js} +1 -1
  2. package/dist/chunks/{build-K6QBTLT7.js → build-W5O2ZVN7.js} +2 -2
  3. package/dist/chunks/{builtin-ZS3HJHZL.js → builtin-KX2SGDND.js} +3 -3
  4. package/dist/chunks/{check-template-RZ7IO333.js → check-template-B2KKE6BW.js} +2 -2
  5. package/dist/chunks/{chunk-ZKHYC3QO.js → chunk-37WES5PM.js} +2 -2
  6. package/dist/chunks/chunk-45JABNLR.js +161 -0
  7. package/dist/chunks/chunk-4OGILN7Y.js +141 -0
  8. package/dist/chunks/{chunk-63X37RCC.js → chunk-5NWVUAWR.js} +4 -4
  9. package/dist/chunks/{chunk-QREG6HEK.js → chunk-67SLLJJB.js} +40 -40
  10. package/dist/chunks/chunk-6DV5JZ5M.js +121 -0
  11. package/dist/chunks/chunk-7Q67MXXL.js +140 -0
  12. package/dist/chunks/{chunk-R5CW4CNP.js → chunk-A6GPFR5O.js} +11 -11
  13. package/dist/chunks/chunk-AISWLDDO.js +895 -0
  14. package/dist/chunks/{chunk-ADZXK6SM.js → chunk-AQGECTRJ.js} +1 -1
  15. package/dist/chunks/chunk-ASWWZNTY.js +130 -0
  16. package/dist/chunks/chunk-BNEFANT2.js +134 -0
  17. package/dist/chunks/{chunk-REJO7GXO.js → chunk-CFEKYNGQ.js} +2 -2
  18. package/dist/chunks/{chunk-5HG4LWF5.js → chunk-D4HEDPVN.js} +161 -0
  19. package/dist/chunks/chunk-DRESZDOP.js +130 -0
  20. package/dist/chunks/{chunk-3W2MSVJA.js → chunk-EBLHS2EG.js} +5 -5
  21. package/dist/chunks/chunk-EHTLT6XJ.js +131 -0
  22. package/dist/chunks/{chunk-2AQK4IIV.js → chunk-EVFG2K4L.js} +1 -1
  23. package/dist/chunks/{chunk-6TJIEERG.js → chunk-F4NTIOTT.js} +26 -26
  24. package/dist/chunks/chunk-FC7B22QS.js +150 -0
  25. package/dist/chunks/{chunk-V6COW3DB.js → chunk-G6MIC23V.js} +1 -1
  26. package/dist/chunks/{chunk-4QBQ4RAA.js → chunk-GODXMHO3.js} +4 -4
  27. package/dist/chunks/chunk-GT22XGDH.js +152 -0
  28. package/dist/chunks/chunk-HL4M53ZR.js +143 -0
  29. package/dist/chunks/{chunk-MPI6SCA7.js → chunk-IDL5KKIC.js} +5 -5
  30. package/dist/chunks/{chunk-HR7HCFPX.js → chunk-IM6HORNC.js} +5 -5
  31. package/dist/chunks/{chunk-UVMU6CXR.js → chunk-IWCZDFXL.js} +17 -17
  32. package/dist/chunks/{chunk-OCSLBM6W.js → chunk-JXAJ6OST.js} +1 -1
  33. package/dist/chunks/{chunk-5WGMPGKY.js → chunk-KS7DVWDB.js} +1 -1
  34. package/dist/chunks/chunk-NHDBQ4G7.js +137 -0
  35. package/dist/chunks/chunk-NKPU5TF2.js +103 -0
  36. package/dist/chunks/chunk-NO734F3F.js +146 -0
  37. package/dist/chunks/{chunk-ASWAIYNC.js → chunk-NR2SFSJU.js} +3 -3
  38. package/dist/chunks/{chunk-CJY4TNOS.js → chunk-O3BEBIDN.js} +3 -1
  39. package/dist/chunks/{chunk-UDO3ZU5T.js → chunk-OR6HMJRM.js} +1 -1
  40. package/dist/chunks/chunk-OTICJQ4T.js +267 -0
  41. package/dist/chunks/chunk-PWZZRGWI.js +141 -0
  42. package/dist/chunks/{chunk-AE6S2M2B.js → chunk-QX4U3VTU.js} +25 -25
  43. package/dist/chunks/{chunk-TRUFIU5W.js → chunk-R3YD6VL6.js} +3 -3
  44. package/dist/chunks/{chunk-YSYZW4VZ.js → chunk-SFPM3UJA.js} +7 -7
  45. package/dist/chunks/chunk-SNXQM4UO.js +115 -0
  46. package/dist/chunks/chunk-T3LV66CQ.js +139 -0
  47. package/dist/chunks/chunk-TDGIO2S7.js +145 -0
  48. package/dist/chunks/chunk-TFNV2UP4.js +87 -0
  49. package/dist/chunks/chunk-UJZXKOTP.js +136 -0
  50. package/dist/chunks/{chunk-QAVWMRRM.js → chunk-V5HI55XO.js} +2 -2
  51. package/dist/chunks/chunk-VVNPBBPL.js +174 -0
  52. package/dist/chunks/{chunk-22RNC42G.js → chunk-YHA45NK5.js} +1 -1
  53. package/dist/chunks/{chunk-27EVM272.js → chunk-YPMT4Y4N.js} +2 -2
  54. package/dist/chunks/chunk-YRSDFRCX.js +122 -0
  55. package/dist/chunks/chunk-ZNARVSMD.js +140 -0
  56. package/dist/chunks/{chunk-3DWOQ4LW.js → chunk-ZTBKAGBN.js} +2 -2
  57. package/dist/chunks/{client-6DUSRTZG.js → client-25NJXQWL.js} +1 -1
  58. package/dist/chunks/{client-XYPBNSQ7.js → client-7AQTKZHV.js} +2 -2
  59. package/dist/chunks/{client-TRFNJJHQ.js → client-LWBTUXQK.js} +2 -2
  60. package/dist/chunks/{client-actions-SSUZUEG7.js → client-actions-3HIRRSOL.js} +4 -4
  61. package/dist/chunks/{dangerous-UX4DHJ7U.js → dangerous-XJOHEWL6.js} +3 -3
  62. package/dist/chunks/{editor-seams-V7ZP7XH3.js → editor-seams-4DREZRTT.js} +9 -9
  63. package/dist/chunks/{editor-store-OIHZT244.js → editor-store-C4VWC23J.js} +1 -1
  64. package/dist/chunks/{export-watermark-4NAP5RVM.js → export-watermark-OKGRZNOU.js} +5 -5
  65. package/dist/chunks/{eyedropper-QXEY7LVL.js → eyedropper-WZYSTUTM.js} +1 -1
  66. package/dist/chunks/{generate-media-JAEHWNF6.js → generate-media-DFSHOPOI.js} +2 -2
  67. package/dist/chunks/{host-IKFYVZS7.js → host-4ZE7SIWR.js} +6 -6
  68. package/dist/chunks/{integrations-U5X2BHVK.js → integrations-LPC35FKX.js} +1 -1
  69. package/dist/chunks/{kit-modules-BAUMECYQ.js → kit-modules-BAKTDLOZ.js} +1 -1
  70. package/dist/chunks/{libraries-Q5TCHWGI.js → libraries-ACERXG2O.js} +5 -5
  71. package/dist/chunks/{live-4XQEGNLA.js → live-ZIVBFX3G.js} +3 -3
  72. package/dist/chunks/{media-tool-OSQR45HY.js → media-tool-2ZPIQKJD.js} +1 -1
  73. package/dist/chunks/{new-file-VVLWHEJ4.js → new-file-XS3KCMGM.js} +3 -3
  74. package/dist/chunks/{plugin-44ZW5UEP.js → plugin-6RNMUP5I.js} +2 -2
  75. package/dist/chunks/{plugin-import-3ISLDX7T.js → plugin-import-UC5BHZFE.js} +13 -13
  76. package/dist/chunks/{presence-WVU4OIUA.js → presence-TLDOMBPD.js} +2 -2
  77. package/dist/chunks/{project-EG7XFEJU.js → project-NMPK4R5M.js} +1 -1
  78. package/dist/chunks/{publish-site-WFIX42D3.js → publish-site-R46ZILSS.js} +6 -6
  79. package/dist/chunks/{publish-store-6BS7OIP4.js → publish-store-MIPHEDLV.js} +4 -4
  80. package/dist/chunks/{raster-actions-37XUQSVZ.js → raster-actions-7EI5THLB.js} +1 -1
  81. package/dist/chunks/{runner-HZ7MU6ER.js → runner-I66TTKKZ.js} +16 -16
  82. package/dist/chunks/{store-PHWBXKNY.js → store-7WMR3JKP.js} +5 -5
  83. package/dist/chunks/{sync-IJNKHQRF.js → sync-OFINS45Q.js} +5 -5
  84. package/dist/chunks/{tabs-G6OTEGA5.js → tabs-PEH6VX3X.js} +8 -8
  85. package/dist/chunks/{team-M2EN4JT5.js → team-GGW3O32G.js} +1 -1
  86. package/dist/chunks/{tools-WDFCY4BH.js → tools-TKCA46ZS.js} +2 -2
  87. package/dist/chunks/{ui-commands-QHFGR33P.js → ui-commands-6K4PYKU5.js} +11 -11
  88. package/dist/chunks/{versions-S7COCZSQ.js → versions-KHRNQFGF.js} +5 -5
  89. package/dist/index.js +4 -4
  90. package/dist/seed/files.json +1 -1
  91. package/dist/templates/count.js +1 -1
  92. package/dist/templates/index.js +125 -101
  93. package/dist/templates/index.json +756 -0
  94. package/dist/templates/motion/landing-hero/index.js +4 -4
  95. package/dist/templates/motion/launch-trailer/document.js +125 -101
  96. package/dist/templates/motion/launch-trailer/index.js +4 -4
  97. package/dist/templates/motion/launch-trailer/scenes.js +3 -3
  98. package/dist/templates/motion/template-wall.js +2 -2
  99. package/dist/templates/print/holidays-christmas-church-newsletter.js +94 -0
  100. package/dist/templates/print/holidays-christmas-eve-invitation.js +94 -0
  101. package/dist/templates/print/holidays-christmas-gift-tags.js +94 -0
  102. package/dist/templates/print/holidays-diwali-party-invitation.js +95 -0
  103. package/dist/templates/print/holidays-easter-activity-sheet.js +94 -0
  104. package/dist/templates/print/holidays-easter-egg-hunt-flyer.js +94 -0
  105. package/dist/templates/print/holidays-eid-dinner-invitation.js +95 -0
  106. package/dist/templates/print/holidays-eid-gift-tags.js +94 -0
  107. package/dist/templates/print/holidays-halloween-party-invitation.js +95 -0
  108. package/dist/templates/print/holidays-halloween-treat-labels.js +94 -0
  109. package/dist/templates/print/holidays-halloween-trunk-or-treat-poster.js +94 -0
  110. package/dist/templates/print/holidays-hanukkah-activity-sheet.js +94 -0
  111. package/dist/templates/print/holidays-hanukkah-party-invitation.js +94 -0
  112. package/dist/templates/print/holidays-lunar-new-year-banquet-menu.js +95 -0
  113. package/dist/templates/print/holidays-new-years-eve-poster.js +94 -0
  114. package/dist/templates/print/holidays-thanksgiving-dinner-menu.js +94 -0
  115. package/dist/templates/print/holidays-thanksgiving-place-cards.js +94 -0
  116. package/dist/templates/print/holidays-valentines-dinner-menu.js +94 -0
  117. package/dist/templates/saas/email-decks.js +2 -2
  118. package/dist/templates/saas/index.js +37 -37
  119. package/dist/templates/saas/launch-kit.js +2 -2
  120. package/dist/templates/saas/launch-video.js +2 -2
  121. package/dist/templates/saas/stores.js +2 -2
  122. package/dist/templates/saas/style-bento.js +2 -2
  123. package/dist/templates/saas/style-dark.js +2 -2
  124. package/dist/templates/saas/style-editorial.js +2 -2
  125. package/dist/templates/saas/style-gradient.js +2 -2
  126. package/dist/templates/saas/style-pastel.js +2 -2
  127. package/dist/templates/saas/style-swiss.js +2 -2
  128. package/dist/templates/slideshow/index.js +3 -3
  129. package/dist/templates/social/holidays-diwali-sweet-shop-post.js +96 -0
  130. package/dist/templates/social/holidays-lunar-new-year-bakery-post.js +96 -0
  131. package/dist/templates/social/holidays-new-years-eve-shop-hours.js +96 -0
  132. package/dist/templates/social/holidays-thanksgiving-pie-orders-post.js +96 -0
  133. package/dist/templates/social/holidays-valentines-florist-post.js +96 -0
  134. package/dist/templates/themes/black-friday-coupons.js +2 -2
  135. package/dist/templates/themes/black-friday-neon.js +2 -2
  136. package/dist/templates/themes/blueprint.js +2 -2
  137. package/dist/templates/themes/broadsheet.js +2 -2
  138. package/dist/templates/themes/cyberpunk.js +2 -2
  139. package/dist/templates/themes/departure-board.js +2 -2
  140. package/dist/templates/themes/festival-presale-family-a.js +2 -2
  141. package/dist/templates/themes/festival-presale-family-b.js +2 -2
  142. package/dist/templates/themes/holidays-shared.js +172 -0
  143. package/dist/templates/themes/holidays.js +107 -1
  144. package/dist/templates/themes/index.js +72 -48
  145. package/dist/templates/themes/lunar-new-year.js +2 -2
  146. package/dist/templates/themes/noir.js +2 -2
  147. package/dist/templates/themes/psychedelic.js +2 -2
  148. package/dist/templates/themes/space-opera.js +2 -2
  149. package/dist/templates/themes/studio.js +3 -3
  150. package/dist/templates/themes/tour-tickets.js +2 -2
  151. package/dist/templates/themes/vaporwave.js +2 -2
  152. package/package.json +1 -1
  153. package/src/templates/print/holidays-christmas-church-newsletter.ts +246 -0
  154. package/src/templates/print/holidays-christmas-eve-invitation.ts +121 -0
  155. package/src/templates/print/holidays-christmas-gift-tags.ts +117 -0
  156. package/src/templates/print/holidays-diwali-party-invitation.ts +98 -0
  157. package/src/templates/print/holidays-easter-activity-sheet.ts +108 -0
  158. package/src/templates/print/holidays-easter-egg-hunt-flyer.ts +118 -0
  159. package/src/templates/print/holidays-eid-dinner-invitation.ts +104 -0
  160. package/src/templates/print/holidays-eid-gift-tags.ts +94 -0
  161. package/src/templates/print/holidays-halloween-party-invitation.ts +101 -0
  162. package/src/templates/print/holidays-halloween-treat-labels.ts +86 -0
  163. package/src/templates/print/holidays-halloween-trunk-or-treat-poster.ts +148 -0
  164. package/src/templates/print/holidays-hanukkah-activity-sheet.ts +112 -0
  165. package/src/templates/print/holidays-hanukkah-party-invitation.ts +112 -0
  166. package/src/templates/print/holidays-lunar-new-year-banquet-menu.ts +110 -0
  167. package/src/templates/print/holidays-new-years-eve-poster.ts +117 -0
  168. package/src/templates/print/holidays-thanksgiving-dinner-menu.ts +110 -0
  169. package/src/templates/print/holidays-thanksgiving-place-cards.ts +80 -0
  170. package/src/templates/print/holidays-valentines-dinner-menu.ts +95 -0
  171. package/src/templates/social/holidays-diwali-sweet-shop-post.ts +121 -0
  172. package/src/templates/social/holidays-lunar-new-year-bakery-post.ts +110 -0
  173. package/src/templates/social/holidays-new-years-eve-shop-hours.ts +118 -0
  174. package/src/templates/social/holidays-thanksgiving-pie-orders-post.ts +115 -0
  175. package/src/templates/social/holidays-valentines-florist-post.ts +102 -0
  176. package/src/templates/themes/holidays-shared.ts +903 -0
  177. package/src/templates/themes/holidays.ts +24 -1
  178. package/types/templates/src/print/holidays-christmas-church-newsletter.d.ts +2 -0
  179. package/types/templates/src/print/holidays-christmas-eve-invitation.d.ts +2 -0
  180. package/types/templates/src/print/holidays-christmas-gift-tags.d.ts +2 -0
  181. package/types/templates/src/print/holidays-diwali-party-invitation.d.ts +2 -0
  182. package/types/templates/src/print/holidays-easter-activity-sheet.d.ts +2 -0
  183. package/types/templates/src/print/holidays-easter-egg-hunt-flyer.d.ts +2 -0
  184. package/types/templates/src/print/holidays-eid-dinner-invitation.d.ts +2 -0
  185. package/types/templates/src/print/holidays-eid-gift-tags.d.ts +2 -0
  186. package/types/templates/src/print/holidays-halloween-party-invitation.d.ts +2 -0
  187. package/types/templates/src/print/holidays-halloween-treat-labels.d.ts +2 -0
  188. package/types/templates/src/print/holidays-halloween-trunk-or-treat-poster.d.ts +2 -0
  189. package/types/templates/src/print/holidays-hanukkah-activity-sheet.d.ts +2 -0
  190. package/types/templates/src/print/holidays-hanukkah-party-invitation.d.ts +2 -0
  191. package/types/templates/src/print/holidays-lunar-new-year-banquet-menu.d.ts +2 -0
  192. package/types/templates/src/print/holidays-new-years-eve-poster.d.ts +2 -0
  193. package/types/templates/src/print/holidays-thanksgiving-dinner-menu.d.ts +2 -0
  194. package/types/templates/src/print/holidays-thanksgiving-place-cards.d.ts +2 -0
  195. package/types/templates/src/print/holidays-valentines-dinner-menu.d.ts +2 -0
  196. package/types/templates/src/social/holidays-diwali-sweet-shop-post.d.ts +2 -0
  197. package/types/templates/src/social/holidays-lunar-new-year-bakery-post.d.ts +2 -0
  198. package/types/templates/src/social/holidays-new-years-eve-shop-hours.d.ts +2 -0
  199. package/types/templates/src/social/holidays-thanksgiving-pie-orders-post.d.ts +2 -0
  200. package/types/templates/src/social/holidays-valentines-florist-post.d.ts +2 -0
  201. package/types/templates/src/themes/holidays-shared.d.ts +374 -0
  202. package/dist/chunks/chunk-OWZLREWX.js +0 -18
  203. package/dist/chunks/{chunk-IFJTWD4O.js → chunk-2R3MZKA2.js} +3 -3
  204. package/dist/chunks/{chunk-P67L32AF.js → chunk-3DBNMCGN.js} +3 -3
  205. package/dist/chunks/{chunk-DZDTVMUO.js → chunk-3VHOXVMF.js} +3 -3
  206. package/dist/chunks/{chunk-2PQI2R5L.js → chunk-64RMGOTG.js} +0 -0
  207. package/dist/chunks/{chunk-7BDCMMSD.js → chunk-6Y46SDFE.js} +3 -3
  208. package/dist/chunks/{chunk-6VCQ4ZEG.js → chunk-AFARXTNQ.js} +3 -3
  209. package/dist/chunks/{chunk-ITSYENCT.js → chunk-BI3M4RUH.js} +3 -3
  210. package/dist/chunks/{chunk-25FM5JIR.js → chunk-BP7CHO7K.js} +3 -3
  211. package/dist/chunks/{chunk-D22534DX.js → chunk-DPTFZDOS.js} +3 -3
  212. package/dist/chunks/{chunk-JWLR6K62.js → chunk-FNUM5W3W.js} +3 -3
  213. package/dist/chunks/{chunk-JPH6HOYU.js → chunk-HJQU5POV.js} +3 -3
  214. package/dist/chunks/{chunk-HQYZ4URA.js → chunk-IJ65QZLL.js} +3 -3
  215. package/dist/chunks/{chunk-47VVF5TM.js → chunk-INT2OPPY.js} +8 -8
  216. package/dist/chunks/{chunk-AYVAHMWQ.js → chunk-JPMLUHZX.js} +3 -3
  217. package/dist/chunks/{chunk-LFYNAAAQ.js → chunk-LMRTRVPC.js} +3 -3
  218. package/dist/chunks/{chunk-HJIMF4NA.js → chunk-NGMCQZA6.js} +3 -3
  219. package/dist/chunks/{chunk-B3ASV6KS.js → chunk-PQBYL7AI.js} +3 -3
  220. package/dist/chunks/{chunk-NHXNUDC5.js → chunk-QD4QORNR.js} +3 -3
  221. package/dist/chunks/{chunk-P6TPDLAF.js → chunk-S3C6L5KF.js} +3 -3
  222. package/dist/chunks/{chunk-TIRPXUK2.js → chunk-S7L2D7NH.js} +3 -3
  223. package/dist/chunks/{chunk-QFGFR5FQ.js → chunk-TYOOL27R.js} +3 -3
  224. package/dist/chunks/{chunk-32V4D45K.js → chunk-TYW7EXV6.js} +3 -3
  225. package/dist/chunks/{chunk-3QIDCP4M.js → chunk-VOEAQIQT.js} +3 -3
  226. package/dist/chunks/{chunk-ASVDOX62.js → chunk-VVUQG4ME.js} +3 -3
  227. package/dist/chunks/{chunk-ZXZ22FKF.js → chunk-XTWKSMJC.js} +3 -3
  228. package/dist/chunks/{chunk-6NG5K7WN.js → chunk-YHEMML5Q.js} +3 -3
  229. package/dist/chunks/{chunk-MVFPEBMY.js → chunk-ZKRSVNY4.js} +3 -3
@@ -0,0 +1,895 @@
1
+ import { createRequire as __popcraftRequire } from 'node:module';
2
+ import { fileURLToPath as __popcraftPath } from 'node:url';
3
+ import { dirname as __popcraftDirname } from 'node:path';
4
+ const require = __popcraftRequire(import.meta.url);
5
+ const __filename = __popcraftPath(import.meta.url);
6
+ const __dirname = __popcraftDirname(__filename);
7
+ import {
8
+ pt3,
9
+ rng
10
+ } from "./chunk-BNVLVZUT.js";
11
+ import {
12
+ init_define_POPCRAFT_COMPONENT_IDS
13
+ } from "./chunk-6VMOKHMF.js";
14
+
15
+ // templates/src/themes/holidays-shared.ts
16
+ init_define_POPCRAFT_COMPONENT_IDS();
17
+ function boxTight(paths) {
18
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
19
+ for (const p of paths) for (const q of p.points) {
20
+ for (const c of [q, q.handleIn, q.handleOut]) if (c) {
21
+ x0 = Math.min(x0, c.x);
22
+ y0 = Math.min(y0, c.y);
23
+ x1 = Math.max(x1, c.x);
24
+ y1 = Math.max(y1, c.y);
25
+ }
26
+ }
27
+ x0 = Math.floor(x0);
28
+ y0 = Math.floor(y0);
29
+ const mv = (q) => pt3(q.x - x0, q.y - y0);
30
+ const moved = paths.map((p) => ({ ...p, points: p.points.map((q) => ({ ...q, ...mv(q), ...q.handleIn ? { handleIn: mv(q.handleIn) } : {}, ...q.handleOut ? { handleOut: mv(q.handleOut) } : {} })) }));
31
+ return { x: x0, y: y0, width: Math.max(1, Math.ceil(x1 - x0)), height: Math.max(1, Math.ceil(y1 - y0)), paths: moved };
32
+ }
33
+ function draw(k, parent, parts) {
34
+ return parts.filter((p) => p.paths.length).map((p) => {
35
+ const b = boxTight(p.paths);
36
+ return k.vector(parent, b.width, b.height, b.paths, p.color, { name: p.name, ...p.o, absolute: { x: b.x, y: b.y } });
37
+ });
38
+ }
39
+ function redraw(k, root, parts) {
40
+ const seen = /* @__PURE__ */ new Map();
41
+ for (const p of parts.filter((q) => q.paths.length)) {
42
+ const i = seen.get(p.name) ?? 0;
43
+ seen.set(p.name, i + 1);
44
+ const id = k.named(root, p.name)[i];
45
+ if (!id) continue;
46
+ const b = boxTight(p.paths);
47
+ const w = p.o?.strokeWidth;
48
+ const strokes = k.node(id).strokes ?? [];
49
+ k.patch(id, { x: b.x, y: b.y, width: b.width, height: b.height, paths: b.paths, ...w !== void 0 ? { strokes: strokes.map((st) => ({ ...st, width: w })) } : {} });
50
+ }
51
+ }
52
+ function restyleAll(k, root, pairs) {
53
+ for (const [layer, style] of pairs) for (const n of k.named(root, layer)) k.restyle(n, style);
54
+ }
55
+ function scaleGaps(k, root, s) {
56
+ for (const n of k.named(root, "Gap")) k.patch(n, { height: Math.max(2, Math.round(k.node(n).height * s)) });
57
+ }
58
+ function printVariant(preset, o) {
59
+ return {
60
+ preset,
61
+ adjust: (k, id) => {
62
+ const { width: w, height: h } = k.node(id);
63
+ const s = w / o.masterWidth;
64
+ redraw(k, id, o.art(w, h));
65
+ k.patch(id, { padding: { top: Math.round(o.pad.top * s), right: Math.round(o.pad.right * s), bottom: Math.round(o.pad.bottom * s), left: Math.round(o.pad.left * s) } });
66
+ restyleAll(k, id, o.styles ?? []);
67
+ scaleGaps(k, id, s);
68
+ o.more?.(k, id, s);
69
+ }
70
+ };
71
+ }
72
+ var C = 0.5523;
73
+ function disc(cx, cy, r, ry = r) {
74
+ return { closed: true, points: [
75
+ { ...pt3(cx, cy - ry), handleIn: pt3(cx - r * C, cy - ry), handleOut: pt3(cx + r * C, cy - ry) },
76
+ { ...pt3(cx + r, cy), handleIn: pt3(cx + r, cy - ry * C), handleOut: pt3(cx + r, cy + ry * C) },
77
+ { ...pt3(cx, cy + ry), handleIn: pt3(cx + r * C, cy + ry), handleOut: pt3(cx - r * C, cy + ry) },
78
+ { ...pt3(cx - r, cy), handleIn: pt3(cx - r, cy + ry * C), handleOut: pt3(cx - r, cy - ry * C) }
79
+ ] };
80
+ }
81
+ function roundRect(x, y, w, h, r) {
82
+ r = Math.min(r, w / 2, h / 2);
83
+ const k = r * (1 - C);
84
+ return { closed: true, points: [
85
+ { ...pt3(x + r, y), handleIn: pt3(x + k, y) },
86
+ { ...pt3(x + w - r, y), handleOut: pt3(x + w - k, y) },
87
+ { ...pt3(x + w, y + r), handleIn: pt3(x + w, y + k) },
88
+ { ...pt3(x + w, y + h - r), handleOut: pt3(x + w, y + h - k) },
89
+ { ...pt3(x + w - r, y + h), handleIn: pt3(x + w - k, y + h) },
90
+ { ...pt3(x + r, y + h), handleOut: pt3(x + k, y + h) },
91
+ { ...pt3(x, y + h - r), handleIn: pt3(x, y + h - k) },
92
+ { ...pt3(x, y + r), handleOut: pt3(x, y + k) }
93
+ ] };
94
+ }
95
+ var rectPath = (x, y, w, h) => ({ closed: true, points: [pt3(x, y), pt3(x + w, y), pt3(x + w, y + h), pt3(x, y + h)] });
96
+ var seg = (a, b) => ({ closed: false, points: [pt3(a.x, a.y), pt3(b.x, b.y)] });
97
+ var polyP = (pts, closed = true) => ({ closed, points: pts.map((p) => pt3(p.x, p.y)) });
98
+ var at = (cx, cy, r, a) => ({ x: cx + Math.cos(a) * r, y: cy + Math.sin(a) * r });
99
+ function arc(cx, cy, r, a0, a1, n = 16, ry = r) {
100
+ return { closed: false, points: Array.from({ length: n + 1 }, (_, i) => {
101
+ const a = a0 + (a1 - a0) * i / n;
102
+ return pt3(cx + Math.cos(a) * r, cy + Math.sin(a) * ry);
103
+ }) };
104
+ }
105
+ function starPath(cx, cy, R, r = R * 0.42, n = 5, turn = 0) {
106
+ return polyP(Array.from({ length: n * 2 }, (_, i) => at(cx, cy, i % 2 ? r : R, -Math.PI / 2 + turn + i * Math.PI / n)));
107
+ }
108
+ function sparkle(cx, cy, s, pinch = 0.18) {
109
+ const q = s * pinch;
110
+ const pts = [];
111
+ for (let i = 0; i < 4; i++) {
112
+ const a = -Math.PI / 2 + i * Math.PI / 2;
113
+ const tip = at(cx, cy, s, a);
114
+ pts.push({ ...pt3(tip.x, tip.y) });
115
+ const mid = at(cx, cy, q, a + Math.PI / 4);
116
+ pts.push({ ...pt3(mid.x, mid.y) });
117
+ }
118
+ return { closed: true, points: pts };
119
+ }
120
+ function heart(cx, cy, s, turn = 0) {
121
+ const u = s / 2;
122
+ const raw = [
123
+ [0, -0.45, [-0.08, -0.85], [0.08, -0.85]],
124
+ [0.62, -0.78, [0.32, -1], [0.95, -0.55]],
125
+ [0.98, -0.18, [1.02, -0.45], [0.92, 0.18]],
126
+ [0, 0.95, [0.45, 0.55], [-0.45, 0.55]],
127
+ [-0.98, -0.18, [-0.92, 0.18], [-1.02, -0.45]],
128
+ [-0.62, -0.78, [-0.95, -0.55], [-0.32, -1]]
129
+ ];
130
+ const c = Math.cos(turn), sn = Math.sin(turn);
131
+ const tr = (x, y) => pt3(cx + (x * c - y * sn) * u, cy + (x * sn + y * c) * u + u * 0.08);
132
+ return { closed: true, points: raw.map(([x, y, hi, ho]) => ({ ...tr(x, y), ...hi ? { handleIn: tr(hi[0], hi[1]) } : {}, ...ho ? { handleOut: tr(ho[0], ho[1]) } : {} })) };
133
+ }
134
+ function leaf(base, len, w, angle) {
135
+ const c = Math.cos(angle), s = Math.sin(angle);
136
+ const p = (u, v) => pt3(base.x + u * c - v * s, base.y + u * s + v * c);
137
+ return { closed: true, points: [
138
+ { ...p(0, 0), handleIn: p(len * 0.3, w * 0.62), handleOut: p(len * 0.3, -w * 0.62) },
139
+ { ...p(len, 0), handleIn: p(len * 0.72, -w * 0.5), handleOut: p(len * 0.72, w * 0.5) }
140
+ ] };
141
+ }
142
+ function petal(base, len, w, angle) {
143
+ const c = Math.cos(angle), s = Math.sin(angle);
144
+ const p = (u, v) => pt3(base.x + u * c - v * s, base.y + u * s + v * c);
145
+ return { closed: true, points: [
146
+ { ...p(0, 0), handleIn: p(len * 0.15, w * 0.5), handleOut: p(len * 0.15, -w * 0.5) },
147
+ { ...p(len, 0), handleIn: p(len * 1.02, -w * 0.62), handleOut: p(len * 1.02, w * 0.62) }
148
+ ] };
149
+ }
150
+ function flame(cx, cy, w, h) {
151
+ return { closed: true, points: [
152
+ { ...pt3(cx, cy - h), handleIn: pt3(cx - w * 0.1, cy - h * 0.7), handleOut: pt3(cx + w * 0.1, cy - h * 0.7) },
153
+ { ...pt3(cx + w / 2, cy - h * 0.28), handleIn: pt3(cx + w * 0.5, cy - h * 0.5), handleOut: pt3(cx + w * 0.5, cy - h * 0.05) },
154
+ { ...pt3(cx, cy), handleIn: pt3(cx + w * 0.3, cy), handleOut: pt3(cx - w * 0.3, cy) },
155
+ { ...pt3(cx - w / 2, cy - h * 0.28), handleIn: pt3(cx - w * 0.5, cy - h * 0.05), handleOut: pt3(cx - w * 0.5, cy - h * 0.5) }
156
+ ] };
157
+ }
158
+ function crescent(cx, cy, r, bite = 0.62, side = 1, turn = 0) {
159
+ const d = r * bite, R2 = r * 0.92;
160
+ const pts = [];
161
+ const x = (r * r - R2 * R2 + d * d) / (2 * d), y = Math.sqrt(Math.max(0, r * r - x * x));
162
+ const a0 = Math.atan2(y, x), a1 = Math.atan2(-y, x);
163
+ for (let i = 0; i <= 28; i++) {
164
+ const a = a0 + (a1 + 2 * Math.PI - a0) * i / 28;
165
+ pts.push({ x: Math.cos(a) * r, y: Math.sin(a) * r });
166
+ }
167
+ const b0 = Math.atan2(-y, x - d), b1 = Math.atan2(y, x - d);
168
+ const span = (b1 > b0 ? b1 - 2 * Math.PI : b1) - b0;
169
+ for (let i = 1; i < 20; i++) {
170
+ const a = b0 + span * i / 20;
171
+ pts.push({ x: d + Math.cos(a) * R2, y: Math.sin(a) * R2 });
172
+ }
173
+ const c = Math.cos(turn), s = Math.sin(turn);
174
+ return polyP(pts.map((p) => ({ x: cx + side * (p.x * c - p.y * s), y: cy + p.x * s + p.y * c })));
175
+ }
176
+ function confetti(w, h, n, seed, size = 10, keepOut = []) {
177
+ const r = rng(seed), bars = [], dots = [];
178
+ for (let i = 0, made = 0; made < n && i < n * 8; i++) {
179
+ const x = r() * w, y = r() * h;
180
+ if (keepOut.some((b) => x > b.x && x < b.x + b.w && y > b.y && y < b.y + b.h)) continue;
181
+ made++;
182
+ if (r() < 0.6) {
183
+ const a = r() * Math.PI, l = size * (0.7 + r() * 0.8), t = size * 0.32;
184
+ const c = Math.cos(a), s = Math.sin(a);
185
+ const p = (u, v) => ({ x: x + u * c - v * s, y: y + u * s + v * c });
186
+ bars.push(polyP([p(-l / 2, -t / 2), p(l / 2, -t / 2), p(l / 2, t / 2), p(-l / 2, t / 2)]));
187
+ } else dots.push(disc(x, y, size * (0.22 + r() * 0.2)));
188
+ }
189
+ return { bars, dots };
190
+ }
191
+ function specks(w, h, n, seed, size = 2) {
192
+ const r = rng(seed);
193
+ return Array.from({ length: n }, () => {
194
+ const x = r() * w, y = r() * h, s = size * (0.5 + r());
195
+ return polyP([{ x, y }, { x: x + s, y: y + r() * s * 0.4 }, { x: x + s * 0.5, y: y + s }]);
196
+ });
197
+ }
198
+ function bandsAround(w, h, keep, bleed = 0) {
199
+ return [
200
+ { x: -bleed, y: -bleed, w: w + 2 * bleed, h: keep.y + bleed },
201
+ { x: -bleed, y: keep.y + keep.h, w: w + 2 * bleed, h: h - keep.y - keep.h + bleed },
202
+ { x: -bleed, y: keep.y, w: keep.x + bleed, h: keep.h },
203
+ { x: keep.x + keep.w, y: keep.y, w: w - keep.x - keep.w + bleed, h: keep.h }
204
+ ].filter((b) => b.w > 2 && b.h > 2);
205
+ }
206
+ function perBand(name, color, bands, paths, o) {
207
+ return bands.map((b, i) => ({ name, color, paths: paths(b, i), ...o ? { o } : {} }));
208
+ }
209
+ var specksIn = (b, density, seed, size = 2) => specks(b.w, b.h, Math.max(1, Math.round(b.w * b.h / density)), seed, size).map((p) => ({ ...p, points: p.points.map((q) => pt3(q.x + b.x, q.y + b.y)) }));
210
+ function flourishComponent(k, name, role, mark, o = {}) {
211
+ if (k.hasComponent(name)) return;
212
+ const size = o.size ?? 9;
213
+ k.component(name, { direction: "HORIZONTAL", width: "HUG", gap: o.gap ?? 6, align: "CENTER" }, (id) => {
214
+ k.rect(id, o.rule ?? 28, 1, role, { name: "Rule" });
215
+ const b = boxTight([mark]);
216
+ k.vector(id, size, size * (b.height / Math.max(1, b.width)), b.paths.map((p) => ({ ...p, points: p.points.map((q) => scalePt(q, size / Math.max(1, b.width))) })), role, { name: "Mark" });
217
+ k.rect(id, o.rule ?? 28, 1, role, { name: "Rule" });
218
+ });
219
+ }
220
+ var scalePt = (q, f) => ({ ...q, ...pt3(q.x * f, q.y * f), ...q.handleIn ? { handleIn: pt3(q.handleIn.x * f, q.handleIn.y * f) } : {}, ...q.handleOut ? { handleOut: pt3(q.handleOut.x * f, q.handleOut.y * f) } : {} });
221
+ function bauble(cx, top, r, o = {}) {
222
+ const s = o.string ?? 0;
223
+ const cy = top + s + r * 0.28 + r;
224
+ return {
225
+ string: s > 0 ? [seg({ x: cx, y: top }, { x: cx, y: top + s })] : [],
226
+ cap: [rectPath(cx - r * 0.2, top + s, r * 0.4, r * 0.3), disc(cx, top + s - r * 0.04, r * 0.09)],
227
+ body: [disc(cx, cy, r)],
228
+ band: [arc(cx, cy, r * 0.98, Math.PI * 0.05, Math.PI * 0.95, 14, r * 0.3), arc(cx, cy + r * 0.1, r * 0.99, Math.PI * 0.08, Math.PI * 0.92, 14, r * 0.42)].map((p) => ({ ...p })),
229
+ shine: [leaf({ x: cx - r * 0.62, y: cy - r * 0.05 }, r * 0.55, r * 0.16, -1.25), disc(cx - r * 0.42, cy - r * 0.62, r * 0.07)],
230
+ shade: [crescent(cx, cy, r, 0.36, -1, -0.75)]
231
+ };
232
+ }
233
+ function pine(a, b, c, o) {
234
+ const r = rng(o.seed);
235
+ const n = Math.round(26 * (o.density ?? 1));
236
+ const pts = Array.from({ length: 13 }, (_, i) => along(a, b, c, i / 12).p);
237
+ const dark = [], light = [];
238
+ for (let i = 0; i < n; i++) {
239
+ const t = 0.04 + 0.94 * i / n;
240
+ const { p, angle } = along(a, b, c, t);
241
+ const len = o.needle * (1 - t * 0.45) * (0.85 + r() * 0.3);
242
+ for (const side of [-1, 1]) {
243
+ const tilt = angle + side * (0.55 + r() * 0.2);
244
+ const end = at(p.x, p.y, len, tilt);
245
+ ((i + (side > 0 ? 1 : 0)) % 2 ? dark : light).push(seg(p, end));
246
+ }
247
+ }
248
+ return { stem: polyP(pts, false), dark, light };
249
+ }
250
+ function holly(base, len, angle) {
251
+ const c = Math.cos(angle), s = Math.sin(angle);
252
+ const p = (u, v) => ({ x: base.x + u * c - v * s, y: base.y + u * s + v * c });
253
+ const w = len * 0.24, pts = [p(0, 0)];
254
+ for (let i = 1; i <= 4; i++) {
255
+ const u = len * i / 5;
256
+ const bulge = Math.sin(Math.PI * i / 5) * w;
257
+ pts.push(p(u - len * 0.08, bulge * 0.55), p(u, bulge * 1.05));
258
+ }
259
+ pts.push(p(len, 0));
260
+ for (let i = 4; i >= 1; i--) {
261
+ const u = len * i / 5;
262
+ const bulge = Math.sin(Math.PI * i / 5) * w;
263
+ pts.push(p(u, -bulge * 1.05), p(u - len * 0.08, -bulge * 0.55));
264
+ }
265
+ return polyP(pts);
266
+ }
267
+ function snowflake(cx, cy, r, turn = 0) {
268
+ const out = [];
269
+ for (let i = 0; i < 6; i++) {
270
+ const a = turn + i * Math.PI / 3;
271
+ out.push(seg({ x: cx, y: cy }, at(cx, cy, r, a)));
272
+ for (const f of [0.45, 0.72]) {
273
+ const p = at(cx, cy, r * f, a), l = r * (f < 0.6 ? 0.3 : 0.2);
274
+ out.push(seg(p, at(p.x, p.y, l, a + 0.75)), seg(p, at(p.x, p.y, l, a - 0.75)));
275
+ }
276
+ }
277
+ return out;
278
+ }
279
+ function along(a, b, c, t) {
280
+ const u = 1 - t;
281
+ const p = { x: u * u * a.x + 2 * u * t * b.x + t * t * c.x, y: u * u * a.y + 2 * u * t * b.y + t * t * c.y };
282
+ const d = { x: 2 * u * (b.x - a.x) + 2 * t * (c.x - b.x), y: 2 * u * (b.y - a.y) + 2 * t * (c.y - b.y) };
283
+ return { p, angle: Math.atan2(d.y, d.x) };
284
+ }
285
+ var quad = (a, b, c, n = 20) => polyP(Array.from({ length: n + 1 }, (_, i) => along(a, b, c, i / n).p), false);
286
+ function sprig(a, b, c, o) {
287
+ const r = rng(o.seed);
288
+ const dark = [], light = [], berries = [];
289
+ for (let i = 0; i < o.leaves; i++) {
290
+ const t = 0.08 + 0.9 * i / o.leaves;
291
+ const { p, angle } = along(a, b, c, t);
292
+ const len = o.size * (1 - t * 0.5) * (0.85 + r() * 0.3), w = len * (o.narrow ?? 0.42);
293
+ for (const side of [-1, 1]) (side < 0 === (i % 2 === 0) ? dark : light).push(leaf(p, len, w, angle + side * (0.75 + r() * 0.25)));
294
+ }
295
+ const tip = along(a, b, c, 1);
296
+ dark.push(leaf(tip.p, o.size * 0.55, o.size * 0.22, tip.angle));
297
+ for (let i = 0; i < (o.berries ?? 0); i++) {
298
+ const { p, angle } = along(a, b, c, 0.2 + r() * 0.65);
299
+ const off = (r() > 0.5 ? 1 : -1) * o.size * 0.42;
300
+ berries.push(disc(p.x - Math.sin(angle) * off, p.y + Math.cos(angle) * off, o.size * 0.1));
301
+ }
302
+ return { stem: quad(a, b, c), dark, light, berries };
303
+ }
304
+ function menorah(cx, base, w, h, nights = 8) {
305
+ const stand = [], candles = [], flames = [], cups = [];
306
+ const cupY = base - h, armBase = base - h * 0.32;
307
+ const step = w / 8;
308
+ stand.push(seg({ x: cx, y: base - h * 0.06 }, { x: cx, y: cupY - h * 0.1 }));
309
+ for (let i = 1; i <= 4; i++) stand.push(arc(cx, cupY, step * i, 0, Math.PI, 18, armBase - cupY));
310
+ const foot = [polyP([{ x: cx - w * 0.2, y: base }, { x: cx + w * 0.2, y: base }, { x: cx + w * 0.05, y: base - h * 0.08 }, { x: cx - w * 0.05, y: base - h * 0.08 }])];
311
+ const cw = step * 0.34, ch = h * 0.3;
312
+ for (let i = -4; i <= 4; i++) {
313
+ const x = cx + i * step, top = i === 0 ? cupY - h * 0.1 : cupY;
314
+ cups.push(rectPath(x - cw * 0.85, top - h * 0.03, cw * 1.7, h * 0.04));
315
+ const rank = i > 0 ? 4 - i : 3 - i;
316
+ if (i !== 0 && rank >= nights) continue;
317
+ candles.push(rectPath(x - cw / 2, top - h * 0.03 - ch, cw, ch));
318
+ flames.push(flame(x, top - h * 0.03 - ch - h * 0.015, cw * 1.25, ch * 0.62));
319
+ }
320
+ return { stand, candles, flames, foot, cups };
321
+ }
322
+ function dreidel(cx, cy, s, turn = 0) {
323
+ const c = Math.cos(turn), sn = Math.sin(turn);
324
+ const p = (x, y) => ({ x: cx + (x * c - y * sn) * s, y: cy + (x * sn + y * c) * s });
325
+ return {
326
+ handle: [polyP([p(-0.06, -0.62), p(0.06, -0.62), p(0.06, -0.3), p(-0.06, -0.3)])],
327
+ body: [polyP([p(-0.3, -0.3), p(0.22, -0.3), p(0.22, 0.18), p(0, 0.5), p(-0.3, 0.18)])],
328
+ side: [polyP([p(0.22, -0.3), p(0.36, -0.36), p(0.36, 0.1), p(0, 0.5), p(0.22, 0.18)])]
329
+ };
330
+ }
331
+ function starOfDavid(cx, cy, r) {
332
+ const tri = (off) => polyP([0, 1, 2].map((i) => at(cx, cy, r, -Math.PI / 2 + off + i * 2 * Math.PI / 3)));
333
+ return [tri(0), tri(Math.PI / 3)];
334
+ }
335
+ var gelt = (cx, cy, r) => ({ coin: [disc(cx, cy, r)], rim: [disc(cx, cy, r * 0.78)] });
336
+ function burst(cx, cy, r1, n = 18, seed = 1, r0 = r1 * 0.25) {
337
+ const r = rng(seed), rays = [], sparks = [];
338
+ for (let i = 0; i < n; i++) {
339
+ const a = i * 2 * Math.PI / n + (r() - 0.5) * 0.12;
340
+ const len = r1 * (0.82 + r() * 0.18);
341
+ const p0 = at(cx, cy, r0, a), p1 = at(cx, cy, len, a);
342
+ rays.push({ closed: false, points: [pt3(p0.x, p0.y), { ...pt3(p1.x, p1.y + len * 0.04), handleIn: pt3((p0.x + p1.x) / 2, (p0.y + p1.y) / 2 - len * 0.03) }] });
343
+ const e = at(cx, cy, len * 1.08, a);
344
+ sparks.push(disc(e.x, e.y + len * 0.05, r1 * 0.022));
345
+ if (i % 2 === 0) {
346
+ const m = at(cx, cy, len * 0.62, a + Math.PI / n);
347
+ sparks.push(disc(m.x, m.y, r1 * 0.014));
348
+ }
349
+ }
350
+ return { rays, sparks };
351
+ }
352
+ function coupe(cx, base, s, tilt = 0) {
353
+ const c = Math.cos(tilt), sn = Math.sin(tilt);
354
+ const p = (x, y) => pt3(cx + (x * c - y * sn) * s, base + (x * sn + y * c) * s);
355
+ const bowl = { closed: true, points: [
356
+ { ...p(-0.42, -0.92) },
357
+ { ...p(0.42, -0.92), handleOut: p(0.4, -0.66) },
358
+ { ...p(0.04, -0.6), handleIn: p(0.22, -0.6) },
359
+ { ...p(-0.04, -0.6), handleOut: p(-0.22, -0.6) },
360
+ { ...p(-0.42, -0.92), handleIn: p(-0.4, -0.66) }
361
+ ] };
362
+ return {
363
+ glass: [bowl, polyP([p(-0.025, -0.6), p(0.025, -0.6), p(0.025, -0.06), p(-0.025, -0.06)].map((q) => ({ x: q.x, y: q.y }))), disc(p(0, -0.03).x, p(0, -0.03).y, 0.26 * s, 0.045 * s)],
364
+ wine: [{ closed: true, points: [{ ...p(-0.36, -0.86) }, { ...p(0.36, -0.86), handleOut: p(0.34, -0.66) }, { ...p(0, -0.63), handleIn: p(0.2, -0.63), handleOut: p(-0.2, -0.63) }, { ...p(-0.36, -0.86), handleIn: p(-0.34, -0.66) }] }]
365
+ };
366
+ }
367
+ function streamer(a, len, angle, amp, waves) {
368
+ const c = Math.cos(angle), s = Math.sin(angle);
369
+ const n = Math.round(waves * 10);
370
+ return polyP(Array.from({ length: n + 1 }, (_, i) => {
371
+ const u = len * i / n, v = Math.sin(i / n * waves * 2 * Math.PI) * amp;
372
+ return { x: a.x + u * c - v * s, y: a.y + u * s + v * c };
373
+ }), false);
374
+ }
375
+ function clock(cx, cy, r) {
376
+ const ticks = Array.from({ length: 12 }, (_, i) => {
377
+ const a = i * Math.PI / 6;
378
+ return seg(at(cx, cy, r * (i % 3 ? 0.84 : 0.76), a), at(cx, cy, r * 0.92, a));
379
+ });
380
+ return { ring: [disc(cx, cy, r)], ticks, hands: [seg({ x: cx, y: cy }, at(cx, cy, r * 0.5, -Math.PI / 2 - 0.08)), seg({ x: cx, y: cy }, at(cx, cy, r * 0.74, -Math.PI / 2 - Math.PI / 6 * 0.5))] };
381
+ }
382
+ function rose(cx, cy, r, seed = 1) {
383
+ const rr = rng(seed);
384
+ const ring = (n, R, off) => Array.from({ length: n }, (_, i) => {
385
+ const a = off + i * 2 * Math.PI / n + (rr() - 0.5) * 0.25;
386
+ const p = at(cx, cy, R * 0.5, a);
387
+ return disc(p.x, p.y, R * 0.56, R * 0.5);
388
+ });
389
+ const outer = ring(7, r, rr() * 6);
390
+ const mid = ring(5, r * 0.66, rr() * 6);
391
+ const core = [disc(cx, cy, r * 0.34)];
392
+ const swirl = Array.from({ length: 3 }, (_, i) => arc(cx, cy, r * (0.12 + i * 0.09), i * 2.1, i * 2.1 + 3.6, 12));
393
+ return { outer, inner: [...mid, ...core], mid, core, swirl };
394
+ }
395
+ function egg(cx, cy, w, h, turn = 0) {
396
+ const c = Math.cos(turn), s = Math.sin(turn);
397
+ const p = (x, y) => pt3(cx + (x * c - y * s), cy + (x * s + y * c));
398
+ const a = w / 2, top = -h * 0.55, bot = h * 0.45;
399
+ return { closed: true, points: [
400
+ { ...p(0, top), handleIn: p(-a * 0.58, top), handleOut: p(a * 0.58, top) },
401
+ { ...p(a, h * 0.08), handleIn: p(a, top * 0.55), handleOut: p(a, bot * 0.62) },
402
+ { ...p(0, bot), handleIn: p(a * 0.56, bot), handleOut: p(-a * 0.56, bot) },
403
+ { ...p(-a, h * 0.08), handleIn: p(-a, bot * 0.62), handleOut: p(-a, top * 0.55) }
404
+ ] };
405
+ }
406
+ function eggBands(cx, cy, w, h, turn = 0, kind = "zigzag") {
407
+ const c = Math.cos(turn), s = Math.sin(turn);
408
+ const p = (x, y) => ({ x: cx + (x * c - y * s), y: cy + (x * s + y * c) });
409
+ const half = (y) => {
410
+ const t = (y + h * 0.05) / (h * 0.52);
411
+ return w / 2 * Math.sqrt(Math.max(0, 1 - t * t)) * 0.96;
412
+ };
413
+ const lines = [], dots = [];
414
+ const band = (y) => {
415
+ const hw = half(y);
416
+ lines.push(polyP(Array.from({ length: 9 }, (_, i) => p(-hw + 2 * hw * i / 8, y + Math.sin(i / 8 * Math.PI) * h * 0.035)), false));
417
+ };
418
+ band(-h * 0.12);
419
+ band(h * 0.14);
420
+ if (kind === "zigzag") {
421
+ const hw = half(0);
422
+ lines.push(polyP(Array.from({ length: 11 }, (_, i) => p(-hw * 0.92 + 1.84 * hw * i / 10, (i % 2 ? -1 : 1) * h * 0.06 + h * 0.01)), false));
423
+ }
424
+ if (kind === "waves") {
425
+ const hw = half(0);
426
+ lines.push(polyP(Array.from({ length: 25 }, (_, i) => p(-hw * 0.94 + 1.88 * hw * i / 24, Math.sin(i * 0.8) * h * 0.045 + h * 0.01)), false));
427
+ }
428
+ if (kind === "dots") {
429
+ const hw = half(0);
430
+ for (let i = 0; i < 5; i++) {
431
+ const q = p(-hw * 0.7 + 1.4 * hw * i / 4, h * 0.01);
432
+ dots.push(disc(q.x, q.y, w * 0.055));
433
+ }
434
+ }
435
+ for (const y of [-h * 0.33, h * 0.32]) {
436
+ const hw = half(y) * 0.6;
437
+ for (let i = 0; i < 3; i++) {
438
+ const q = p(-hw + hw * i, y);
439
+ dots.push(disc(q.x, q.y, w * 0.035));
440
+ }
441
+ }
442
+ return { lines, dots };
443
+ }
444
+ function tulip(x, ground, h, lean = 0) {
445
+ const topX = x + lean * h, topY = ground - h;
446
+ const w = h * 0.2;
447
+ const cup = { closed: true, points: [
448
+ { ...pt3(topX - w / 2, topY - w * 0.9) },
449
+ { ...pt3(topX - w * 0.18, topY - w * 0.45) },
450
+ { ...pt3(topX, topY - w * 1) },
451
+ { ...pt3(topX + w * 0.18, topY - w * 0.45) },
452
+ { ...pt3(topX + w / 2, topY - w * 0.9), handleOut: pt3(topX + w * 0.62, topY - w * 0.1) },
453
+ { ...pt3(topX, topY + w * 0.12), handleIn: pt3(topX + w * 0.42, topY + w * 0.12), handleOut: pt3(topX - w * 0.42, topY + w * 0.12) },
454
+ { ...pt3(topX - w / 2, topY - w * 0.9), handleIn: pt3(topX - w * 0.62, topY - w * 0.1) }
455
+ ] };
456
+ return {
457
+ cup: [cup],
458
+ stem: [{ closed: false, points: [pt3(x, ground), { ...pt3(topX, topY), handleIn: pt3(x + lean * h * 0.2, ground - h * 0.6) }] }],
459
+ leaves: [leaf({ x, y: ground }, h * 0.55, h * 0.14, -Math.PI / 2 - 0.35), leaf({ x, y: ground }, h * 0.42, h * 0.12, -Math.PI / 2 + 0.42)]
460
+ };
461
+ }
462
+ function grass(x0, x1, ground, h, seed, n = 30) {
463
+ const r = rng(seed);
464
+ return Array.from({ length: n }, (_, i) => {
465
+ const x = x0 + (x1 - x0) * (i + r() * 0.8) / n, hh = h * (0.5 + r() * 0.6), lean = (r() - 0.5) * hh * 0.5, w = h * 0.06;
466
+ return { closed: true, points: [pt3(x - w, ground), { ...pt3(x + lean, ground - hh), handleIn: pt3(x - w * 0.5, ground - hh * 0.5) }, { ...pt3(x + w, ground), handleIn: pt3(x + w * 0.4, ground - hh * 0.5) }] };
467
+ });
468
+ }
469
+ function rabbit(cx, ground, s, facing = 1) {
470
+ const f = facing;
471
+ return {
472
+ body: [
473
+ disc(cx, ground - s * 0.27, s * 0.3, s * 0.27),
474
+ disc(cx + f * s * 0.2, ground - s * 0.56, s * 0.15, s * 0.14),
475
+ leaf({ x: cx + f * s * 0.17, y: ground - s * 0.64 }, s * 0.38, s * 0.12, -Math.PI / 2 - f * 0.25),
476
+ leaf({ x: cx + f * s * 0.25, y: ground - s * 0.64 }, s * 0.36, s * 0.11, -Math.PI / 2 + f * 0.05),
477
+ disc(cx + f * s * 0.2, ground - s * 0.04, s * 0.12, s * 0.05)
478
+ ],
479
+ tail: [disc(cx - f * s * 0.29, ground - s * 0.16, s * 0.07)]
480
+ };
481
+ }
482
+ function pumpkin(cx, ground, w, h) {
483
+ const cy = ground - h / 2;
484
+ const lobes = [disc(cx - w * 0.27, cy, w * 0.25, h / 2), disc(cx + w * 0.27, cy, w * 0.25, h / 2), disc(cx - w * 0.12, cy, w * 0.24, h / 2 * 1.01), disc(cx + w * 0.12, cy, w * 0.24, h / 2 * 1.01), disc(cx, cy, w * 0.2, h / 2 * 1.02)];
485
+ const creases = [-0.2, -0.07, 0.07, 0.2].map((f) => ({ closed: false, points: [pt3(cx + w * f * 0.7, cy - h * 0.42), { ...pt3(cx + w * f * 0.7, cy + h * 0.42), handleIn: pt3(cx + w * f * 1.35, cy) }] }));
486
+ const stem = { closed: true, points: [pt3(cx - w * 0.05, cy - h * 0.44), { ...pt3(cx - w * 0.03, cy - h * 0.66), handleIn: pt3(cx - w * 0.06, cy - h * 0.56) }, pt3(cx + w * 0.07, cy - h * 0.7), { ...pt3(cx + w * 0.05, cy - h * 0.44), handleIn: pt3(cx + w * 0.02, cy - h * 0.58) }] };
487
+ return { lobes, creases, stem: [stem] };
488
+ }
489
+ function jackFace(cx, cy, w) {
490
+ const u = w / 100;
491
+ const tri = (x, y, s, up = true) => polyP(up ? [{ x: cx + (x - s) * u, y: cy + (y + s * 0.7) * u }, { x: cx + (x + s) * u, y: cy + (y + s * 0.7) * u }, { x: cx + x * u, y: cy + (y - s) * u }] : [{ x: cx + (x - s) * u, y: cy + (y - s * 0.6) * u }, { x: cx + (x + s) * u, y: cy + (y - s * 0.6) * u }, { x: cx + x * u, y: cy + (y + s * 0.6) * u }]);
492
+ const mouth = polyP([[-32, 8], [-20, 14], [-14, 9], [-6, 16], [6, 16], [14, 9], [20, 14], [32, 8], [24, 24], [10, 28], [6, 22], [-6, 22], [-10, 28], [-24, 24]].map(([x, y]) => ({ x: cx + x * u, y: cy + y * u })));
493
+ return [tri(-17, -12, 10), tri(17, -12, 10), tri(0, 0, 5, true), mouth];
494
+ }
495
+ function bat(cx, cy, s, flap = 0) {
496
+ const u = s / 100, f = flap * 10;
497
+ const pts = [[0, -8], [4, -14], [6, -6], [14, -10 - f], [30, -18 - f], [50, -12 - f], [44, -2], [36, 2], [30, 8], [20, 4], [12, 12], [4, 6], [0, 12]];
498
+ const full = [...pts, ...pts.slice(1, -1).reverse().map(([x, y]) => [-x, y])];
499
+ return polyP(full.map(([x, y]) => ({ x: cx + x * u, y: cy + y * u })));
500
+ }
501
+ function web(cx, cy, r, a0, a1, spokes = 7, rings = 6) {
502
+ const out = [];
503
+ const angles = Array.from({ length: spokes }, (_, i) => a0 + (a1 - a0) * i / (spokes - 1));
504
+ for (const a of angles) out.push(seg({ x: cx, y: cy }, at(cx, cy, r, a)));
505
+ for (let j = 1; j <= rings; j++) {
506
+ const rr = r * j / (rings + 0.4);
507
+ for (let i = 0; i < spokes - 1; i++) {
508
+ const p0 = at(cx, cy, rr, angles[i]), p1 = at(cx, cy, rr, angles[i + 1]), m = at(cx, cy, rr * 0.86, (angles[i] + angles[i + 1]) / 2);
509
+ out.push({ closed: false, points: [pt3(p0.x, p0.y), { ...pt3(p1.x, p1.y), handleIn: pt3(m.x, m.y) }] });
510
+ }
511
+ }
512
+ return out;
513
+ }
514
+ function ghost(cx, top, s) {
515
+ const w = s * 0.62, bot = top + s;
516
+ const pts = [{ ...pt3(cx - w / 2, bot - s * 0.05), handleOut: pt3(cx - w / 2, top + s * 0.2) }, { ...pt3(cx, top), handleIn: pt3(cx - w / 2, top), handleOut: pt3(cx + w / 2, top) }, { ...pt3(cx + w / 2, bot - s * 0.05), handleIn: pt3(cx + w / 2, top + s * 0.2) }];
517
+ for (let i = 1; i <= 4; i++) {
518
+ const x = cx + w / 2 - w * i / 4;
519
+ pts.push({ ...pt3(x, bot - (i % 2 ? 0 : s * 0.08)), handleIn: pt3(x + w / 8, bot + (i % 2 ? s * 0.04 : -s * 0.12)) });
520
+ }
521
+ return { sheet: [{ closed: true, points: pts }], face: [disc(cx - w * 0.16, top + s * 0.32, s * 0.05, s * 0.07), disc(cx + w * 0.16, top + s * 0.32, s * 0.05, s * 0.07), disc(cx, top + s * 0.5, s * 0.06, s * 0.08)] };
522
+ }
523
+ function candyCorn(cx, cy, s, turn = 0) {
524
+ const c = Math.cos(turn), sn = Math.sin(turn);
525
+ const p = (x, y) => ({ x: cx + (x * c - y * sn) * s, y: cy + (x * sn + y * c) * s });
526
+ const band = (y0, y1) => {
527
+ const w0 = 0.36 * (y0 + 0.5), w1 = 0.36 * (y1 + 0.5);
528
+ return polyP([p(-w0, y0), p(w0, y0), p(w1, y1), p(-w1, y1)]);
529
+ };
530
+ return { tip: [polyP([p(0, -0.5), p(0.12, -0.17), p(-0.12, -0.17)])], mid: [band(-0.17, 0.15)], base: [{ ...band(0.15, 0.48) }] };
531
+ }
532
+ function maple(cx, cy, s, turn = 0) {
533
+ const u = s / 100, c = Math.cos(turn), sn = Math.sin(turn);
534
+ const raw = [[0, -50], [8, -30], [18, -36], [16, -14], [38, -26], [34, -14], [48, -10], [30, 4], [36, 14], [14, 12], [10, 22], [4, 18], [2, 40], [-2, 40], [-4, 18], [-10, 22], [-14, 12], [-36, 14], [-30, 4], [-48, -10], [-34, -14], [-38, -26], [-16, -14], [-18, -36], [-8, -30]];
535
+ const p = ([x, y]) => ({ x: cx + (x * c - y * sn) * u, y: cy + (x * sn + y * c) * u });
536
+ return [polyP(raw.map(p))];
537
+ }
538
+ function mapleVeins(cx, cy, s, turn = 0) {
539
+ const u = s / 100, c = Math.cos(turn), sn = Math.sin(turn);
540
+ const p = (x, y) => ({ x: cx + (x * c - y * sn) * u, y: cy + (x * sn + y * c) * u });
541
+ return [seg(p(0, 36), p(0, -42)), seg(p(0, 14), p(36, -20)), seg(p(0, 14), p(-36, -20)), seg(p(0, 20), p(28, 10)), seg(p(0, 20), p(-28, 10))];
542
+ }
543
+ function oak(base, len, angle) {
544
+ const c = Math.cos(angle), s = Math.sin(angle);
545
+ const p = (u, v) => ({ x: base.x + u * c - v * s, y: base.y + u * s + v * c });
546
+ const pts = [p(0, 0)];
547
+ const lobes = 4;
548
+ for (let i = 0; i < lobes; i++) {
549
+ const u0 = len * (0.12 + i * 0.8 / lobes), u1 = u0 + len * 0.8 / lobes / 2, w = len * 0.26 * (1 - i * 0.12);
550
+ pts.push(p(u0, w * 0.45), p(u1, w), p(u0 + len * 0.8 / lobes, w * 0.42));
551
+ }
552
+ pts.push(p(len, 0));
553
+ for (let i = lobes - 1; i >= 0; i--) {
554
+ const u0 = len * (0.12 + i * 0.8 / lobes), u1 = u0 + len * 0.8 / lobes / 2, w = len * 0.26 * (1 - i * 0.12);
555
+ pts.push(p(u0 + len * 0.8 / lobes, -w * 0.42), p(u1, -w), p(u0, -w * 0.45));
556
+ }
557
+ return smoothP(pts, 0.18);
558
+ }
559
+ function smoothP(pts, tension = 0.2) {
560
+ const n = pts.length;
561
+ return { closed: true, points: pts.map((p, i) => {
562
+ const a = pts[(i - 1 + n) % n], b = pts[(i + 1) % n], tx = (b.x - a.x) * tension, ty = (b.y - a.y) * tension;
563
+ return { ...pt3(p.x, p.y), handleIn: pt3(p.x - tx, p.y - ty), handleOut: pt3(p.x + tx, p.y + ty) };
564
+ }) };
565
+ }
566
+ function wheat(x, ground, h, lean = 0) {
567
+ const top = { x: x + lean * h, y: ground - h };
568
+ const grains = [];
569
+ const angle = Math.atan2(top.y - ground, top.x - x);
570
+ for (let i = 0; i < 7; i++) {
571
+ const t = 0.66 + i * 0.05;
572
+ const p = { x: x + (top.x - x) * t, y: ground + (top.y - ground) * t };
573
+ const len = h * 0.1 * (1 - i * 0.06);
574
+ grains.push(petal(p, len, len * 0.5, angle - 0.5), petal(p, len, len * 0.5, angle + 0.5));
575
+ }
576
+ grains.push(petal(top, h * 0.08, h * 0.04, angle));
577
+ return { stalk: [{ closed: false, points: [pt3(x, ground), { ...pt3(top.x, top.y), handleIn: pt3(x + lean * h * 0.3, ground - h * 0.5) }] }], grains };
578
+ }
579
+ function acorn(cx, cy, s, turn = 0) {
580
+ const c = Math.cos(turn), sn = Math.sin(turn);
581
+ const tr = (x, y) => ({ x: cx + (x * c - y * sn) * s, y: cy + (x * sn + y * c) * s });
582
+ const nut = egg(cx, cy + s * 0.12, s * 0.5, s * 0.66, turn + Math.PI);
583
+ const cap = smoothP([tr(-0.3, -0.1), tr(-0.28, -0.26), tr(0, -0.34), tr(0.28, -0.26), tr(0.3, -0.1), tr(0, -0.06)], 0.2);
584
+ return { nut: [nut], cap: [cap, polyP([tr(-0.03, -0.32), tr(0.03, -0.32), tr(0.06, -0.46), tr(0.01, -0.46)])] };
585
+ }
586
+ function diya(cx, ground, w) {
587
+ const h = w * 0.36, top = ground - h;
588
+ const bowl = { closed: true, points: [
589
+ { ...pt3(cx - w / 2, top) },
590
+ { ...pt3(cx + w * 0.38, top) },
591
+ { ...pt3(cx + w * 0.58, top - h * 0.28) },
592
+ { ...pt3(cx + w * 0.42, top + h * 0.3), handleOut: pt3(cx + w * 0.3, ground + h * 0.05) },
593
+ { ...pt3(cx - w * 0.1, ground), handleIn: pt3(cx + w * 0.15, ground + h * 0.02), handleOut: pt3(cx - w * 0.38, ground) },
594
+ { ...pt3(cx - w / 2, top), handleIn: pt3(cx - w * 0.52, top + h * 0.6) }
595
+ ] };
596
+ const rim = [polyP([{ x: cx - w * 0.47, y: top + h * 0.12 }, { x: cx + w * 0.4, y: top + h * 0.12 }, { x: cx + w * 0.37, y: top + h * 0.26 }, { x: cx - w * 0.45, y: top + h * 0.26 }])];
597
+ const fx = cx + w * 0.5, fy = top - h * 0.22;
598
+ return { bowl: [bowl], rim, flame: [flame(fx, fy, w * 0.2, w * 0.5)], core: [flame(fx, fy - w * 0.02, w * 0.09, w * 0.24)] };
599
+ }
600
+ function marigold(cx, cy, r, seed = 1) {
601
+ const rr = rng(seed);
602
+ const ring = (R, n, off) => Array.from({ length: n }, (_, i) => {
603
+ const a = off + i * 2 * Math.PI / n;
604
+ const p = at(cx, cy, R * (0.92 + rr() * 0.12), a);
605
+ return disc(p.x, p.y, r * 0.3);
606
+ });
607
+ return { outer: ring(r * 0.7, 12, 0), inner: [...ring(r * 0.36, 7, 0.3), disc(cx, cy, r * 0.36)] };
608
+ }
609
+ function rangoli(cx, cy, R, petals = 8) {
610
+ const outer = [], middle = [], inner = [], dots = [];
611
+ for (let i = 0; i < petals * 2; i++) {
612
+ const a = i * Math.PI / petals;
613
+ outer.push(petal(at(cx, cy, R * 0.42, a), R * 0.56, R * 0.3, a));
614
+ }
615
+ for (let i = 0; i < petals; i++) {
616
+ const a = i * 2 * Math.PI / petals + Math.PI / petals;
617
+ middle.push(petal(at(cx, cy, R * 0.18, a), R * 0.5, R * 0.36, a));
618
+ }
619
+ for (let i = 0; i < petals; i++) {
620
+ const a = i * 2 * Math.PI / petals;
621
+ inner.push(petal({ x: cx, y: cy }, R * 0.36, R * 0.2, a));
622
+ }
623
+ for (let i = 0; i < petals * 4; i++) {
624
+ const a = i * Math.PI / (petals * 2);
625
+ const p = at(cx, cy, R * 1.04, a);
626
+ dots.push(disc(p.x, p.y, R * 0.022));
627
+ }
628
+ for (let i = 0; i < petals * 2; i++) {
629
+ const a = i * Math.PI / petals + Math.PI / (petals * 2);
630
+ const p = at(cx, cy, R * 0.78, a);
631
+ dots.push(disc(p.x, p.y, R * 0.03));
632
+ }
633
+ return { outer, middle, inner, dots, heart: [disc(cx, cy, R * 0.12)] };
634
+ }
635
+ function toran(x0, x1, y, sag, n, r, seed = 3) {
636
+ const string = [], outer = [], inner = [], leaves = [];
637
+ const span = (x1 - x0) / n;
638
+ for (let i = 0; i < n; i++) {
639
+ const a = { x: x0 + span * i, y }, b = { x: x0 + span * (i + 1), y }, m = { x: (a.x + b.x) / 2, y: y + sag * 2 };
640
+ string.push(quad(a, m, b, 12));
641
+ const lowest = along(a, m, b, 0.5).p;
642
+ const g = marigold(lowest.x, lowest.y + r * 0.6, r, seed + i);
643
+ outer.push(...g.outer);
644
+ inner.push(...g.inner);
645
+ for (const t of [0.25, 0.75]) {
646
+ const p = along(a, m, b, t).p;
647
+ leaves.push(leaf(p, r * 2.3, r * 0.75, Math.PI / 2 + (t < 0.5 ? 0.15 : -0.15)));
648
+ }
649
+ }
650
+ return { string, blooms: { outer, inner }, leaves };
651
+ }
652
+ function eightStar(cx, cy, r) {
653
+ return starPath(cx, cy, r, r * 0.76, 8, Math.PI / 8);
654
+ }
655
+ function fanous(cx, top, s) {
656
+ const u = s / 100;
657
+ const y = (v) => top + v * u, x = (v) => cx + v * u;
658
+ const metal = [
659
+ disc(cx, y(3), 3 * u),
660
+ polyP([{ x: x(-3), y: y(6) }, { x: x(3), y: y(6) }, { x: x(2), y: y(14) }, { x: x(-2), y: y(14) }]),
661
+ { closed: true, points: [pt3(x(-16), y(26)), { ...pt3(x(0), y(13)), handleIn: pt3(x(-14), y(15)), handleOut: pt3(x(14), y(15)) }, pt3(x(16), y(26))] },
662
+ polyP([{ x: x(-20), y: y(26) }, { x: x(20), y: y(26) }, { x: x(18), y: y(30) }, { x: x(-18), y: y(30) }]),
663
+ polyP([{ x: x(-18), y: y(74) }, { x: x(18), y: y(74) }, { x: x(10), y: y(84) }, { x: x(-10), y: y(84) }]),
664
+ polyP([{ x: x(-4), y: y(84) }, { x: x(4), y: y(84) }, { x: x(0), y: y(97) }])
665
+ ];
666
+ const glass = [polyP([{ x: x(-17), y: y(30) }, { x: x(17), y: y(30) }, { x: x(22), y: y(52) }, { x: x(17), y: y(74) }, { x: x(-17), y: y(74) }, { x: x(-22), y: y(52) }])];
667
+ const frame = [
668
+ seg({ x: x(-6), y: y(30) }, { x: x(-6), y: y(74) }),
669
+ seg({ x: x(6), y: y(30) }, { x: x(6), y: y(74) }),
670
+ seg({ x: x(-22), y: y(52) }, { x: x(22), y: y(52) }),
671
+ { closed: false, points: [pt3(x(-6), y(44)), { ...pt3(x(6), y(44)), handleIn: pt3(x(0), y(36)) }] },
672
+ { closed: false, points: [pt3(x(-6), y(66)), { ...pt3(x(6), y(66)), handleIn: pt3(x(0), y(58)) }] }
673
+ ];
674
+ return { metal, glass, frame, glow: [flame(cx, y(70), 12 * u, 26 * u)] };
675
+ }
676
+ function archPath(cx, w, base, spring, tip) {
677
+ const l = cx - w / 2, r = cx + w / 2;
678
+ return { closed: true, points: [
679
+ pt3(l, base),
680
+ { ...pt3(l, spring), handleOut: pt3(l, spring - (spring - tip) * 0.55) },
681
+ { ...pt3(cx, tip), handleIn: pt3(cx - w * 0.12, tip + (spring - tip) * 0.35), handleOut: pt3(cx + w * 0.12, tip + (spring - tip) * 0.35) },
682
+ { ...pt3(r, spring), handleIn: pt3(r, spring - (spring - tip) * 0.55) },
683
+ pt3(r, base)
684
+ ] };
685
+ }
686
+ function tilePattern(w, h, step, x0 = 0, y0 = 0) {
687
+ const stars = [], joins = [];
688
+ for (let y = y0; y < h + step; y += step) for (let x = x0; x < w + step; x += step) {
689
+ stars.push(eightStar(x, y, step * 0.3));
690
+ const m = { x: x + step / 2, y: y + step / 2 };
691
+ joins.push(polyP([{ x: m.x, y: m.y - step * 0.12 }, { x: m.x + step * 0.12, y: m.y }, { x: m.x, y: m.y + step * 0.12 }, { x: m.x - step * 0.12, y: m.y }]));
692
+ }
693
+ return { stars, joins };
694
+ }
695
+ function redLantern(cx, top, w, cord = 0) {
696
+ const h = w * 0.82, y0 = top + cord + w * 0.08, cy = y0 + h / 2;
697
+ const ribs = [];
698
+ for (const f of [-0.62, -0.3, 0, 0.3, 0.62]) ribs.push({ closed: false, points: [pt3(cx + f * w * 0.32, y0 + h * 0.03), { ...pt3(cx + f * w * 0.32, y0 + h * 0.97), handleIn: pt3(cx + f * w * 0.62, cy) }] });
699
+ const tTop = y0 + h + w * 0.07;
700
+ return {
701
+ cord: cord > 0 ? [seg({ x: cx, y: top }, { x: cx, y: top + cord })] : [],
702
+ caps: [rectPath(cx - w * 0.22, y0 - w * 0.07, w * 0.44, w * 0.1), rectPath(cx - w * 0.22, y0 + h - w * 0.03, w * 0.44, w * 0.1)],
703
+ body: [disc(cx, cy, w / 2, h / 2)],
704
+ ribs,
705
+ tassel: [rectPath(cx - w * 0.04, tTop, w * 0.08, w * 0.06), polyP([{ x: cx - w * 0.06, y: tTop + w * 0.06 }, { x: cx + w * 0.06, y: tTop + w * 0.06 }, { x: cx + w * 0.1, y: tTop + w * 0.42 }, { x: cx - w * 0.1, y: tTop + w * 0.42 }])]
706
+ };
707
+ }
708
+ function plum(cx, cy, r, turn = 0) {
709
+ const petals = Array.from({ length: 5 }, (_, i) => {
710
+ const a = turn + i * 2 * Math.PI / 5;
711
+ const p = at(cx, cy, r * 0.55, a);
712
+ return disc(p.x, p.y, r * 0.48);
713
+ });
714
+ return { petals, heart: [disc(cx, cy, r * 0.22)] };
715
+ }
716
+ function branch(pts, seed, twigs = 5, len = 60) {
717
+ const r = rng(seed);
718
+ const limb = [polyP(pts, false)];
719
+ const tw = [], ends = [pts[pts.length - 1]];
720
+ for (let i = 0; i < twigs; i++) {
721
+ const j = 1 + Math.floor(r() * (pts.length - 2));
722
+ const a = pts[j - 1], b = pts[j], t = r();
723
+ const p = { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
724
+ const dir = Math.atan2(b.y - a.y, b.x - a.x) + (r() > 0.5 ? 1 : -1) * (0.5 + r() * 0.5);
725
+ const l = len * (0.5 + r() * 0.6);
726
+ const e = at(p.x, p.y, l, dir), m = at(p.x, p.y, l * 0.5, dir + 0.2);
727
+ tw.push(polyP([p, m, e], false));
728
+ ends.push(e, m);
729
+ }
730
+ return { limb, twigs: tw, ends };
731
+ }
732
+ function cloudCurl(x, y, s, flip = 1) {
733
+ const u = s / 100;
734
+ const curl = (cx, cy, r, dir) => polyP(Array.from({ length: 22 }, (_, i) => {
735
+ const t = i / 21;
736
+ const a = dir * (Math.PI * 0.2 + t * Math.PI * 1.9);
737
+ const rr = r * (1 - t * 0.6);
738
+ return { x: x + flip * (cx + Math.cos(a + Math.PI) * rr) * u, y: y + (cy + Math.sin(a + Math.PI) * rr) * u };
739
+ }), false);
740
+ return [curl(30, 0, 22, 1), curl(62, -4, 18, -1), curl(48, -20, 14, 1), polyP([{ x: x + flip * 8 * u, y: y + 22 * u }, { x: x + flip * 96 * u, y: y + 22 * u }], false)];
741
+ }
742
+ function coin(cx, cy, r) {
743
+ return { coin: [disc(cx, cy, r)], rim: [disc(cx, cy, r * 0.82)], hole: [rectPath(cx - r * 0.24, cy - r * 0.24, r * 0.48, r * 0.48)] };
744
+ }
745
+ function firecrackers(cx, top, n, s) {
746
+ const crackers = [], tips = [];
747
+ for (let i = 0; i < n; i++) {
748
+ const y = top + s * 0.5 + i * s * 0.55, side = i % 2 ? 1 : -1;
749
+ const c = Math.cos(side * 0.5), sn = Math.sin(side * 0.5);
750
+ const p = (u, v) => ({ x: cx + u * c - v * sn, y: y + u * sn + v * c });
751
+ crackers.push(polyP([p(0, -s * 0.1), p(side * s * 0.6, -s * 0.1), p(side * s * 0.6, s * 0.1), p(0, s * 0.1)]));
752
+ tips.push(polyP([p(side * s * 0.6, -s * 0.1), p(side * s * 0.68, -s * 0.1), p(side * s * 0.68, s * 0.1), p(side * s * 0.6, s * 0.1)]));
753
+ }
754
+ return { cord: [seg({ x: cx, y: top }, { x: cx, y: top + s * 0.5 + n * s * 0.55 })], crackers, tips };
755
+ }
756
+ function dashedFrame(w, h, m, r = 0) {
757
+ return [r > 0 ? roundRect(m, m, w - 2 * m, h - 2 * m, r) : rectPath(m, m, w - 2 * m, h - 2 * m)];
758
+ }
759
+ function doubleRule(w, h, m, gap, r = 0) {
760
+ return [r ? roundRect(m, m, w - 2 * m, h - 2 * m, r) : rectPath(m, m, w - 2 * m, h - 2 * m), r ? roundRect(m + gap, m + gap, w - 2 * (m + gap), h - 2 * (m + gap), Math.max(0, r - gap)) : rectPath(m + gap, m + gap, w - 2 * (m + gap), h - 2 * (m + gap))];
761
+ }
762
+ function maze(x, y, cols, rows, cell, seed) {
763
+ const r = rng(seed);
764
+ const right = Array.from({ length: cols }, () => Array(rows).fill(true));
765
+ const bottom = Array.from({ length: cols }, () => Array(rows).fill(true));
766
+ const seen = Array.from({ length: cols }, () => Array(rows).fill(false));
767
+ const stack = [[0, 0]];
768
+ seen[0][0] = true;
769
+ while (stack.length) {
770
+ const [c, w] = stack[stack.length - 1];
771
+ const next = [[1, 0], [-1, 0], [0, 1], [0, -1]].map(([dc, dr]) => [c + dc, w + dr]).filter(([a2, b2]) => a2 >= 0 && b2 >= 0 && a2 < cols && b2 < rows && !seen[a2][b2]);
772
+ if (!next.length) {
773
+ stack.pop();
774
+ continue;
775
+ }
776
+ const [a, b] = next[Math.floor(r() * next.length)];
777
+ if (a > c) right[c][w] = false;
778
+ else if (a < c) right[a][b] = false;
779
+ else if (b > w) bottom[c][w] = false;
780
+ else bottom[a][b] = false;
781
+ seen[a][b] = true;
782
+ stack.push([a, b]);
783
+ }
784
+ const out = [];
785
+ out.push(seg({ x: x + cell, y }, { x: x + cols * cell, y }), seg({ x, y }, { x, y: y + rows * cell }));
786
+ out.push(seg({ x, y: y + rows * cell }, { x: x + (cols - 1) * cell, y: y + rows * cell }), seg({ x: x + cols * cell, y }, { x: x + cols * cell, y: y + rows * cell }));
787
+ for (let c = 0; c < cols; c++) for (let w = 0; w < rows; w++) {
788
+ if (right[c][w] && c < cols - 1) out.push(seg({ x: x + (c + 1) * cell, y: y + w * cell }, { x: x + (c + 1) * cell, y: y + (w + 1) * cell }));
789
+ if (bottom[c][w] && w < rows - 1) out.push(seg({ x: x + c * cell, y: y + (w + 1) * cell }, { x: x + (c + 1) * cell, y: y + (w + 1) * cell }));
790
+ }
791
+ return out;
792
+ }
793
+ function wordSearch(words, n, seed) {
794
+ const r = rng(seed);
795
+ const g = Array.from({ length: n }, () => Array(n).fill(""));
796
+ const dirs = [[1, 0], [0, 1], [1, 1], [1, -1]];
797
+ for (const word of words) {
798
+ const w = word.toUpperCase().replace(/[^A-Z]/g, "");
799
+ for (let tries = 0; tries < 400; tries++) {
800
+ const [dx, dy] = dirs[Math.floor(r() * dirs.length)];
801
+ const x = Math.floor(r() * n), y = Math.floor(r() * n);
802
+ const ex = x + dx * (w.length - 1), ey = y + dy * (w.length - 1);
803
+ if (ex < 0 || ex >= n || ey < 0 || ey >= n) continue;
804
+ if ([...w].some((ch, i) => {
805
+ const c = g[y + dy * i][x + dx * i];
806
+ return c && c !== ch;
807
+ })) continue;
808
+ [...w].forEach((ch, i) => {
809
+ g[y + dy * i][x + dx * i] = ch;
810
+ });
811
+ break;
812
+ }
813
+ }
814
+ const A = "ABCDEFGHIJKLMNOPRSTUWY";
815
+ return g.map((row) => row.map((c) => c || A[Math.floor(r() * A.length)]).join(" "));
816
+ }
817
+
818
+ export {
819
+ boxTight,
820
+ draw,
821
+ redraw,
822
+ restyleAll,
823
+ scaleGaps,
824
+ printVariant,
825
+ disc,
826
+ roundRect,
827
+ rectPath,
828
+ seg,
829
+ polyP,
830
+ arc,
831
+ starPath,
832
+ sparkle,
833
+ heart,
834
+ leaf,
835
+ petal,
836
+ flame,
837
+ crescent,
838
+ confetti,
839
+ specks,
840
+ bandsAround,
841
+ perBand,
842
+ specksIn,
843
+ flourishComponent,
844
+ bauble,
845
+ pine,
846
+ holly,
847
+ snowflake,
848
+ along,
849
+ quad,
850
+ sprig,
851
+ menorah,
852
+ dreidel,
853
+ starOfDavid,
854
+ gelt,
855
+ burst,
856
+ coupe,
857
+ streamer,
858
+ clock,
859
+ rose,
860
+ egg,
861
+ eggBands,
862
+ tulip,
863
+ grass,
864
+ rabbit,
865
+ pumpkin,
866
+ jackFace,
867
+ bat,
868
+ web,
869
+ ghost,
870
+ candyCorn,
871
+ maple,
872
+ mapleVeins,
873
+ oak,
874
+ smoothP,
875
+ wheat,
876
+ acorn,
877
+ diya,
878
+ marigold,
879
+ rangoli,
880
+ toran,
881
+ eightStar,
882
+ fanous,
883
+ archPath,
884
+ tilePattern,
885
+ redLantern,
886
+ plum,
887
+ branch,
888
+ cloudCurl,
889
+ coin,
890
+ firecrackers,
891
+ dashedFrame,
892
+ doubleRule,
893
+ maze,
894
+ wordSearch
895
+ };