@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,108 @@
1
+ // A printable Easter activity sheet for children, for a church's Sunday school, a library story hour or the brunch
2
+ // table: three eggs drawn in outline with their bands pencilled in to decorate, a maze to take the rabbit to its
3
+ // basket, and a word builder ("how many words can you make from SPRINGTIME?") with lines to write on. A garden border
4
+ // of tulips and grass runs round the foot into the bleed, and a pastel header carries the title. US Letter, and A4.
5
+
6
+ import { Kit, preset } from '../kit'
7
+ import { defineTemplate } from '../build'
8
+ import { SERIF } from '../shared/type'
9
+ import type { VectorPath } from '@/lib/document/types'
10
+ import { draw, egg, eggBands, grass, maze, polyP, printVariant, rabbit, sparkle, tulip, type Drawn } from '../themes/holidays-shared'
11
+
12
+ const NAME = 'Easter activity sheet for kids'
13
+ const PAD = { top: 30, right: 48, bottom: 96, left: 48 }
14
+
15
+ function frame(w: number, h: number): Drawn[] {
16
+ const s = w / 816, B = 12
17
+ const wave: VectorPath = polyP([{ x: -B, y: -B }, { x: w + B, y: -B }, ...Array.from({ length: 25 }, (_, i) => ({ x: w + B - ((w + 2 * B) * i) / 24, y: 128 + Math.sin(i * 0.9) * 8 }))])
18
+ const tl = [0.03, 0.09, 0.91, 0.97].map((x, i) => tulip(w * x, h + 4, (70 + (i % 2) * 22) * s, (i % 2 ? -0.06 : 0.06)))
19
+ return [
20
+ { name: 'Header', paths: [wave], color: 'band' },
21
+ { name: 'Header sparkles', paths: [sparkle(w * 0.06, 52, 14 * s), sparkle(w * 0.12, 96, 8 * s)], color: 'onBand' },
22
+ { name: 'Header sparkles', paths: [sparkle(w * 0.93, 46, 16 * s), sparkle(w * 0.87, 92, 9 * s)], color: 'onBand' },
23
+ { name: 'Grass', paths: grass(-B, w + B, h + B, 52 * s, 9, 80), color: 'grass' },
24
+ { name: 'Tulip stems', paths: tl.flatMap(t => t.stem), color: 'grassDeep', o: { strokeWidth: 3.4 * s } },
25
+ { name: 'Tulip leaves', paths: tl.flatMap(t => t.leaves), color: 'grassDeep' },
26
+ { name: 'Tulips', paths: tl.slice(0, 2).flatMap(t => t.cup), color: 'tulip' },
27
+ { name: 'Tulips', paths: tl.slice(2).flatMap(t => t.cup), color: 'tulipYellow' },
28
+ ]
29
+ }
30
+
31
+ export default defineTemplate({
32
+ id: 'print-holidays-easter-activity-sheet',
33
+ meta: {
34
+ name: NAME,
35
+ description: 'A printable Easter activity sheet for children: three eggs in outline to decorate, a maze to take the rabbit to its basket, and a word builder for SPRINGTIME with lines to write on, under a pastel header and above a border of tulips and grass. US Letter with bleed, and an A4 copy',
36
+ category: 'document', tags: ['easter', 'spring', 'kids', 'children', 'activity sheet', 'coloring page', 'colouring', 'maze', 'eggs', 'bunny', 'sunday school', 'printable', 'print'],
37
+ platforms: ['print'], formats: ['document'], useCases: ['education', 'event'],
38
+ created: '2026-10-10', updated: '2026-10-10',
39
+ },
40
+ stableNumbers: true,
41
+ build() {
42
+ const k = new Kit(NAME, preset('us-letter'))
43
+ k.quantizeGeometry = true
44
+ k.brand(
45
+ { paper: '#FFFDF7', text: '#3D3360', onPaper: '#6A5F8E', primary: '#D9577A', onPrimary: '#FFFFFF', line: '#CFC6E4', card: '#F4F0FB', onCard: '#3D3360' },
46
+ { name: 'St Mark’s Sunday School' },
47
+ )
48
+ k.palette({ ink: '#3D3360', band: '#C9E7D9', onBand: '#FFFFFF', grass: '#9ED39B', grassDeep: '#5DA466', tulip: '#F28CA6', tulipYellow: '#F7C85C', outline: '#3D3360', soft: '#F4F0FB', basket: '#C99561', rabbit: '#BFA58C' })
49
+ k.textStyle('Title 48', { ...SERIF, size: 48, fontWeight: 700, letterSpacing: -1, lineHeight: 52 })
50
+ k.textStyle('Band sub 15', { size: 15, fontWeight: 600, letterSpacing: 2.6, lineHeight: 20 })
51
+ k.textStyle('Head 20', { ...SERIF, size: 21, fontWeight: 700, lineHeight: 25 })
52
+ k.textStyle('Hint 12.5', { size: 12.5, fontWeight: 400, lineHeight: 18 })
53
+ k.textStyle('Big word 40', { size: 34, fontWeight: 900, letterSpacing: 5, lineHeight: 42 })
54
+ k.textStyle('Name 12', { size: 12, fontWeight: 600, lineHeight: 18 })
55
+ k.textStyle('Foot 10', { size: 10, fontWeight: 500, lineHeight: 14 })
56
+
57
+ k.component('Panel head', { gap: 2, width: 320, props: { Title: 'Puzzle', Hint: 'What to do' } }, id => {
58
+ k.propText(id, 'Title', { style: 'Head 20', color: 'onCard', width: 'FILL', name: 'Panel title' })
59
+ k.propText(id, 'Hint', { style: 'Hint 12.5', color: 'onCard', width: 'FILL', name: 'Panel hint' })
60
+ })
61
+ const panel = (parent: string, title: string, hint: string, name: string, width: number | 'FILL' = 'FILL') => {
62
+ const p = k.stack(parent, { width, gap: 10, padding: 18, fill: 'card', radius: 22, name })
63
+ k.instance(p, 'Panel head', { Title: title, Hint: hint }, { name: 'Panel head', width: 'FILL' })
64
+ return p
65
+ }
66
+
67
+ const sheet = k.sheet
68
+ const { width: W } = k.node(sheet)
69
+ k.flowSheet(sheet, 14, PAD, 'paper', 'MIN', 'MIN')
70
+ draw(k, sheet, frame(W, k.node(sheet).height))
71
+ const head = k.stack(sheet, { width: 'FILL', height: 92, gap: 2, justify: 'CENTER', align: 'CENTER', name: 'Header' })
72
+ k.text(head, 'Spring Garden Puzzles', { style: 'Title 48', color: 'ink', autoWidth: true, name: 'Title' })
73
+ k.text(head, 'HAPPY EASTER!', { style: 'Band sub 15', color: 'ink', autoWidth: true, name: 'Subtitle' })
74
+ k.stack(sheet, { height: 6, name: 'Gap' })
75
+ const top = k.stack(sheet, { direction: 'HORIZONTAL', width: 'FILL', justify: 'SPACE_BETWEEN', name: 'Name row' })
76
+ k.text(top, 'Name: ________________________', { style: 'Name 12', color: 'text', autoWidth: true, name: 'Name' })
77
+ k.text(top, 'Age: ______', { style: 'Name 12', color: 'text', autoWidth: true, name: 'Age' })
78
+
79
+ // Three eggs to decorate: the outline and its bands, nothing filled.
80
+ const eggs = panel(sheet, 'Decorate the eggs', 'Colour them in, follow the lines or invent your own patterns: stripes, spots, zigzags, flowers.', 'Egg panel')
81
+ const ea = k.stack(eggs, { width: 'FILL', height: 230, name: 'Egg art' })
82
+ const shapes = [[120, 120, 150, 200, -0.12, 'zigzag'], [340, 116, 160, 212, 0.05, 'waves'], [560, 120, 150, 200, 0.14, 'dots']] as const
83
+ draw(k, ea, [
84
+ { name: 'Egg outlines', paths: shapes.map(([x, y, w, h, t]) => egg(x, y, w, h, t)), color: 'outline', o: { strokeWidth: 3 } },
85
+ { name: 'Egg guides', paths: shapes.flatMap(([x, y, w, h, t, kind]) => eggBands(x, y, w, h, t, kind).lines), color: 'outline', o: { strokeWidth: 1.6, opacity: 0.6 } },
86
+ { name: 'Egg guide dots', paths: shapes.flatMap(([x, y, w, h, t, kind]) => eggBands(x, y, w, h, t, kind).dots), color: 'outline', o: { strokeWidth: 1.6, opacity: 0.6 } },
87
+ ])
88
+
89
+ const row = k.stack(sheet, { direction: 'HORIZONTAL', gap: 16, width: 'FILL', name: 'Puzzles' })
90
+ const mz = panel(row, 'Hop to the basket', 'Help the rabbit find the way to its basket of eggs.', 'Maze panel')
91
+ const mart = k.stack(mz, { width: 300, height: 284, name: 'Maze art' })
92
+ const cell = 25
93
+ const rb = rabbit(16, 36, 46, 1)
94
+ draw(k, mart, [
95
+ { name: 'Maze walls', paths: maze(0, 40, 12, 9, cell, 327), color: 'outline', o: { strokeWidth: 3 } },
96
+ { name: 'Rabbit', paths: rb.body, color: 'rabbit' },
97
+ { name: 'Basket', paths: [polyP([{ x: 268, y: 266 }, { x: 300, y: 266 }, { x: 296, y: 284 }, { x: 272, y: 284 }]), { closed: false, points: [{ x: 270, y: 266 }, { x: 298, y: 266, handleIn: { x: 284, y: 248 } }] }], color: 'basket', o: { strokeWidth: 2.4 } },
98
+ { name: 'Basket eggs', paths: [egg(278, 262, 10, 13), egg(290, 262, 10, 13, 0.3)], color: 'tulip' },
99
+ ])
100
+ const wb = panel(row, 'Word builder', 'How many words can you make from the letters of this word? Rest, ring, time…', 'Word panel')
101
+ k.text(wb, 'SPRINGTIME', { style: 'Big word 40', color: 'onCard', align: 'CENTER', width: 'FILL', name: 'Big word' })
102
+ k.text(wb, '_________________ _________________\n_________________ _________________\n_________________ _________________\n_________________ _________________\n_________________ _________________', { style: 'Name 12', color: 'onCard', align: 'CENTER', width: 'FILL', name: 'Lines' })
103
+ k.text(sheet, 'Happy Easter from {{brand.name}}. Bring your sheet on Sunday for a sticker!', { style: 'Foot 10', color: 'onPaper', align: 'CENTER', width: 'FILL', name: 'Foot' })
104
+
105
+ k.variants(sheet, [printVariant('a4', { art: frame, pad: PAD, masterWidth: W })])
106
+ return k.finish()
107
+ },
108
+ })
@@ -0,0 +1,118 @@
1
+ // A flyer for a neighbourhood Easter egg hunt in the park, in spring pastels cut like paper: a sun and clouds across
2
+ // the top, "The Great Egg Hunt" in chunky type, the three age groups and their start times as cards, what to bring
3
+ // and what else is on, and along the foot layered hills with painted eggs hidden in the grass, tulips, and a rabbit
4
+ // watching from the hedge. US Letter for the noticeboard and the school bag, with the sky and hills running into the
5
+ // bleed, and an A4 copy with the drawing worked out again.
6
+
7
+ import { Kit, preset } from '../kit'
8
+ import { defineTemplate } from '../build'
9
+ import { SERIF } from '../shared/type'
10
+ import type { VectorPath } from '@/lib/document/types'
11
+ import { along, disc, draw, egg, eggBands, grass, polyP, quad, printVariant, rabbit, rectPath, tulip, type Drawn } from '../themes/holidays-shared'
12
+
13
+ const NAME = 'Easter egg hunt flyer'
14
+ const PAD = { top: 236, right: 56, bottom: 316, left: 56 }
15
+
16
+ function hill(w: number, y: number, amp: number, phase: number, bottom: number, B: number): VectorPath {
17
+ return polyP([{ x: -B, y: bottom + B }, ...Array.from({ length: 17 }, (_, i) => ({ x: -B + ((w + 2 * B) * i) / 16, y: y + Math.sin(i * 0.5 + phase) * amp })), { x: w + B, y: bottom + B }])
18
+ }
19
+
20
+ function art(w: number, h: number): Drawn[] {
21
+ const s = w / 816, B = 12
22
+ const sun = { x: w - 120 * s, y: 70 * s }
23
+ const rays: VectorPath[] = Array.from({ length: 14 }, (_, i) => { const a = (i * Math.PI) / 7; return polyP([{ x: sun.x + Math.cos(a - 0.09) * 70 * s, y: sun.y + Math.sin(a - 0.09) * 70 * s }, { x: sun.x + Math.cos(a) * 112 * s, y: sun.y + Math.sin(a) * 112 * s }, { x: sun.x + Math.cos(a + 0.09) * 70 * s, y: sun.y + Math.sin(a + 0.09) * 70 * s }]) })
24
+ const cloud = (x: number, y: number, k: number) => [disc(x, y, 46 * k * s, 26 * k * s), disc(x + 40 * k * s, y - 14 * k * s, 36 * k * s, 30 * k * s), disc(x + 82 * k * s, y + 2 * k * s, 40 * k * s, 22 * k * s), rectPath(x - 30 * k * s, y + 4 * k * s, 140 * k * s, 22 * k * s)]
25
+ const g = h - 330 * s
26
+ const eggs = [[0.12, 0.83, 54, -0.3, 'zigzag', 'eggPink'], [0.3, 0.9, 46, 0.25, 'dots', 'eggYellow'], [0.52, 0.86, 58, -0.1, 'waves', 'eggBlue'], [0.7, 0.93, 44, 0.35, 'zigzag', 'eggLilac'], [0.9, 0.85, 50, -0.2, 'dots', 'eggPink'], [0.42, 0.96, 40, -0.4, 'zigzag', 'eggYellow']] as const
27
+ // Bunting across the top: a string that dips twice, and pennants in the eggs' colours.
28
+ const flags = { eggPink: [] as VectorPath[], eggYellow: [] as VectorPath[], eggBlue: [] as VectorPath[], eggLilac: [] as VectorPath[] }
29
+ const string: VectorPath[] = []
30
+ const cols = ['eggPink', 'eggYellow', 'eggBlue', 'eggLilac'] as const
31
+ for (let span = 0; span < 2; span++) {
32
+ const a = { x: -B + span * (w + 2 * B) / 2, y: 150 * s }, c = { x: -B + (span + 1) * (w + 2 * B) / 2, y: 150 * s }, m = { x: (a.x + c.x) / 2, y: 210 * s }
33
+ string.push(quad(a, m, c, 16))
34
+ for (let i = 1; i < 9; i++) {
35
+ const t = i / 9, p = along(a, m, c, t), q = along(a, m, c, t + 0.07)
36
+ const dx = q.p.x - p.p.x, dy = q.p.y - p.p.y
37
+ flags[cols[(i + span) % 4]].push(polyP([p.p, q.p, { x: (p.p.x + q.p.x) / 2 - dy * 0.9, y: (p.p.y + q.p.y) / 2 + Math.abs(dx) * 1.3 }]))
38
+ }
39
+ }
40
+ const out: Drawn[] = [
41
+ { name: 'Sun rays', paths: rays, color: 'sun', o: { opacity: 0.7 } },
42
+ { name: 'Sun', paths: [disc(sun.x, sun.y, 60 * s)], color: 'sun' },
43
+ { name: 'Clouds', paths: cloud(60 * s, 82 * s, 1), color: 'cloud' },
44
+ { name: 'Clouds', paths: cloud(380 * s, 46 * s, 0.7), color: 'cloud' },
45
+ { name: 'Bunting string', paths: string, color: 'eggInk', o: { strokeWidth: 1.6 * s } },
46
+ ...cols.map(cname => ({ name: 'Bunting', paths: flags[cname], color: cname })),
47
+ { name: 'Far hill', paths: [hill(w, g + 70 * s, 18 * s, 0.3, h, B)], color: 'hillFar' },
48
+ { name: 'Hedge', paths: Array.from({ length: 9 }, (_, i) => disc(w * (0.58 + i * 0.055), g + 96 * s - (i % 2) * 8 * s, 34 * s, 28 * s)), color: 'hedge' },
49
+ { name: 'Mid hill', paths: [hill(w, g + 150 * s, 14 * s, 2.0, h, B)], color: 'hillMid' },
50
+ { name: 'Near hill', paths: [hill(w, g + 220 * s, 10 * s, 4.2, h, B)], color: 'hillNear' },
51
+ ]
52
+ const r = rabbit(w * 0.84, g + 120 * s, 120 * s, -1)
53
+ out.push({ name: 'Rabbit', paths: r.body, color: 'rabbit' }, { name: 'Rabbit tail', paths: r.tail, color: 'cloud' })
54
+ const tl = [tulip(w * 0.04, h - 70 * s, 120 * s, 0.05), tulip(w * 0.08, h - 60 * s, 96 * s, -0.08), tulip(w * 0.96, h - 64 * s, 110 * s, -0.05), tulip(w * 0.62, h - 30 * s, 84 * s, 0.06)]
55
+ out.push({ name: 'Tulip stems', paths: tl.flatMap(t => t.stem), color: 'stem', o: { strokeWidth: 4 * s } }, { name: 'Tulip leaves', paths: tl.flatMap(t => t.leaves), color: 'stem' }, { name: 'Tulips', paths: tl.flatMap(t => t.cup), color: 'tulip' })
56
+ for (const [x, y, sz, t, kind, col] of eggs) {
57
+ const cx = w * x, cy = h * y
58
+ const b = eggBands(cx, cy, sz * 0.78 * s, sz * s, t, kind)
59
+ out.push({ name: 'Egg', paths: [egg(cx, cy, sz * 0.78 * s, sz * s, t)], color: col }, { name: 'Egg bands', paths: b.lines, color: 'eggInk', o: { strokeWidth: 2.6 * s } }, { name: 'Egg dots', paths: b.dots, color: 'cloud' })
60
+ }
61
+ out.push({ name: 'Grass', paths: grass(-B, w + B, h + B, 44 * s, 31, 70), color: 'hillNear' })
62
+ return out
63
+ }
64
+
65
+ export default defineTemplate({
66
+ id: 'print-holidays-easter-egg-hunt-flyer',
67
+ meta: {
68
+ name: NAME,
69
+ description: 'A flyer for a neighbourhood Easter egg hunt in spring pastels cut like paper: sun and clouds, “The Great Egg Hunt” in chunky type, the age groups and start times as cards, what to bring and what else is on, and layered hills with painted eggs hidden in the grass, tulips and a rabbit. US Letter with bleed, and an A4 copy',
70
+ category: 'flyer', tags: ['easter', 'egg hunt', 'spring', 'kids', 'family', 'community', 'church', 'park', 'eggs', 'bunny', 'tulips', 'pastel', 'flyer', 'poster', 'print', 'event'],
71
+ platforms: ['print'], formats: ['flyer', 'poster'], useCases: ['event', 'announcement'],
72
+ created: '2026-10-10', updated: '2026-10-10',
73
+ },
74
+ stableNumbers: true,
75
+ build() {
76
+ const k = new Kit(NAME, preset('us-letter'))
77
+ k.quantizeGeometry = true
78
+ k.brand(
79
+ { paper: '#EAF4FB', text: '#3B2A5C', onPaper: '#6A3FA8', primary: '#7B4FB8', onPrimary: '#FFFFFF', card: '#FFFFFF', onCard: '#3B2A5C' },
80
+ { name: 'Linden Park Neighbours' },
81
+ )
82
+ k.palette({ sun: '#FFD36B', cloud: '#FFFFFF', hillFar: '#B9DFA6', hillMid: '#8CCB83', hillNear: '#5FAE6A', hedge: '#4E9A5C', rabbit: '#C9B39C', stem: '#4E8F55', tulip: '#F27A8E', eggPink: '#F7A6C1', eggYellow: '#FFE07A', eggBlue: '#9ED4F2', eggLilac: '#C8B2EE', eggInk: '#7B4FB8' })
83
+ k.textStyle('Kicker 15', { size: 15, fontWeight: 700, letterSpacing: 3.5, lineHeight: 20 })
84
+ k.textStyle('Title 84', { size: 96, fontWeight: 900, letterSpacing: -3.6, lineHeight: 90 })
85
+ k.textStyle('When 22', { ...SERIF, size: 22, fontWeight: 600, lineHeight: 28 })
86
+ k.textStyle('Age 13', { size: 13, fontWeight: 800, letterSpacing: 1.6, lineHeight: 17 })
87
+ k.textStyle('Time 26', { size: 26, fontWeight: 900, lineHeight: 30, fontFeatures: { tnum: 1 } })
88
+ k.textStyle('Where 13', { ...SERIF, size: 13, fontWeight: 400, fontStyle: 'italic', lineHeight: 17 })
89
+ k.textStyle('Body 15', { ...SERIF, size: 15, fontWeight: 400, lineHeight: 21 })
90
+
91
+ k.component('Age group', { gap: 2, width: 212, padding: { top: 14, right: 16, bottom: 14, left: 16 }, fill: 'card', radius: 18, align: 'CENTER', props: { Ages: 'AGES 0–3', Time: '10:00', Where: 'The toddler meadow' } }, id => {
92
+ k.propText(id, 'Ages', { style: 'Age 13', color: 'onCard', align: 'CENTER', width: 'FILL', name: 'Ages' })
93
+ k.propText(id, 'Time', { style: 'Time 26', color: 'onCard', align: 'CENTER', width: 'FILL', name: 'Time' })
94
+ k.propText(id, 'Where', { style: 'Where 13', color: 'onCard', align: 'CENTER', width: 'FILL', name: 'Where' })
95
+ })
96
+
97
+ const sheet = k.sheet
98
+ const { width: W, height: H } = k.node(sheet)
99
+ k.flowSheet(sheet, 0, PAD, 'paper', 'MIN', 'CENTER')
100
+ draw(k, sheet, art(W, H))
101
+ const c = { align: 'CENTER' as const, width: 'FILL' as const }
102
+ k.text(sheet, 'BRING A BASKET TO', { style: 'Kicker 15', color: 'onPaper', ...c, name: 'Kicker' })
103
+ k.stack(sheet, { height: 8, name: 'Gap' })
104
+ k.text(sheet, 'The Great Egg Hunt', { style: 'Title 84', color: 'text', ...c, name: 'Title' })
105
+ k.stack(sheet, { height: 14, name: 'Gap' })
106
+ k.text(sheet, 'Saturday 27 March · from 10 am · Linden Park bandstand', { style: 'When 22', color: 'text', ...c, name: 'When' })
107
+ k.stack(sheet, { height: 22, name: 'Gap' })
108
+ const ages = k.stack(sheet, { direction: 'HORIZONTAL', gap: 16, width: 'HUG', name: 'Age groups' })
109
+ for (const [a, t, wh] of [['AGES 0–3', '10:00', 'The toddler meadow'], ['AGES 4–7', '10:20', 'Round the bandstand'], ['AGES 8–11', '10:40', 'The whole park. Good luck']]) k.instance(ages, 'Age group', { Ages: a, Time: t, Where: wh }, { name: 'Age group' })
110
+ k.stack(sheet, { height: 22, name: 'Gap' })
111
+ k.text(sheet, 'Free for every child. Over 1,500 eggs hidden, one golden egg per hunt with a prize, face painting, and hot cross buns from the bake stall. Rain or shine: if it pours, we move to the scout hut.', { style: 'Body 15', color: 'text', ...c, name: 'Body' })
112
+ k.stack(sheet, { height: 12, name: 'Gap' })
113
+ k.text(sheet, 'Hosted by {{brand.name}} · lindenparkneighbours.org', { style: 'Age 13', color: 'onPaper', ...c, name: 'Host' })
114
+
115
+ k.variants(sheet, [printVariant('a4', { art, pad: PAD, masterWidth: W })])
116
+ return k.finish()
117
+ },
118
+ })
@@ -0,0 +1,104 @@
1
+ // A printed invitation to an Eid al-Fitr dinner at home: a pointed arch drawn in fine gold double lines frames the
2
+ // card, eight-pointed stars tile the margins outside it on deep midnight teal, a crescent moon and star sit in the
3
+ // arch's crown, and three lanterns (fanous) hang inside it at different heights over "Eid Mubarak" in a gold serif
4
+ // and the evening's details, with the date given as the moon allows. 5 × 7 inches with the tiles running into the
5
+ // bleed, and an A6 copy with the drawing worked out again.
6
+
7
+ import { Kit, preset } from '../kit'
8
+ import { defineTemplate } from '../build'
9
+ import { SERIF } from '../shared/type'
10
+ import { blurred } from '../shared/texture'
11
+ import { archPath, crescent, draw, eightStar, fanous, flourishComponent, printVariant, starPath, tilePattern, type Drawn } from '../themes/holidays-shared'
12
+
13
+ const NAME = 'Eid dinner invitation'
14
+ const PAD = { top: 318, right: 74, bottom: 66, left: 74 }
15
+
16
+ function art(w: number, h: number): Drawn[] {
17
+ const s = w / 480, B = 14 * s, cx = w / 2
18
+ const aw = w - 92 * s, base = h - 34 * s, spring = 196 * s, tip = 44 * s
19
+ const outer = archPath(cx, aw, base, spring, tip), inner = archPath(cx, aw - 14 * s, base - 7 * s, spring + 4 * s, tip + 10 * s)
20
+ // The tiles only in the margins outside the arch: a band down each side, and the two corners above its shoulders.
21
+ const tiles = (x0: number, y0: number, x1: number, y1: number) => { const t = tilePattern(x1 - x0, y1 - y0, 34 * s); const mv = (p: Drawn['paths'][number]) => ({ ...p, points: p.points.map(q => ({ ...q, x: q.x + x0, y: q.y + y0 })) }); return { stars: t.stars.map(mv), joins: t.joins.map(mv) } }
22
+ const parts = [tiles(-B, -B, 40 * s, h + B), tiles(w - 40 * s, -B, w + B, h + B), tiles(40 * s, -B, w * 0.3, 92 * s), tiles(w * 0.7, -B, w - 40 * s, 92 * s)]
23
+ const lanterns = [fanous(cx - 100 * s, 0, 104 * s), fanous(cx, 0, 136 * s), fanous(cx + 100 * s, 0, 94 * s)].map((l, i) => ({ l, drop: [92, 140, 70][i] * s }))
24
+ const lifted = lanterns.map(({ l, drop }) => {
25
+ const mv = (p: Drawn['paths'][number]) => ({ ...p, points: p.points.map(q => ({ ...q, y: q.y + drop, ...(q.handleIn ? { handleIn: { ...q.handleIn, y: q.handleIn.y + drop } } : {}), ...(q.handleOut ? { handleOut: { ...q.handleOut, y: q.handleOut.y + drop } } : {}) })) })
26
+ return { metal: l.metal.map(mv), glass: l.glass.map(mv), frame: l.frame.map(mv), glow: l.glow.map(mv) }
27
+ })
28
+ const chains = lanterns.map(({ drop }, i) => { const x = [cx - 100 * s, cx, cx + 100 * s][i]; return { closed: false, points: [{ x, y: tip + 34 * s }, { x, y: drop + 3 * s }] } })
29
+ return [
30
+ ...parts.map(p => ({ name: 'Tiles', paths: p.stars, color: 'tile' })),
31
+ ...parts.map(p => ({ name: 'Tile joins', paths: p.joins, color: 'tileDeep' })),
32
+ { name: 'Arch', paths: [outer], color: 'gold', o: { strokeWidth: 2 * s } },
33
+ { name: 'Arch inner', paths: [inner], color: 'gold', o: { strokeWidth: 0.8 * s, opacity: 0.8 } },
34
+ { name: 'Crescent', paths: [crescent(cx - 4 * s, tip + 36 * s, 16 * s, 0.5, 1, -0.5)], color: 'gold' },
35
+ { name: 'Star', paths: [starPath(cx + 12 * s, tip + 28 * s, 5 * s, 2 * s)], color: 'gold' },
36
+ { name: 'Chains', paths: chains, color: 'gold', o: { strokeWidth: 0.8 * s } },
37
+ { name: 'Lantern glow', paths: lifted.flatMap(l => l.glass), color: 'amber', o: { opacity: 0.5, effects: [blurred(12 * s)] } },
38
+ { name: 'Lantern glass', paths: lifted.flatMap(l => l.glass), color: 'amber' },
39
+ { name: 'Lantern flames', paths: lifted.flatMap(l => l.glow), color: 'cream' },
40
+ { name: 'Lantern frames', paths: lifted.flatMap(l => l.frame), color: 'goldDeep', o: { strokeWidth: 1.2 * s } },
41
+ { name: 'Lanterns', paths: lifted.flatMap(l => l.metal), color: 'gold' },
42
+ { name: 'Foot star', paths: [eightStar(cx, h - 52 * s, 8 * s)], color: 'gold' },
43
+ ]
44
+ }
45
+
46
+ export default defineTemplate({
47
+ id: 'print-holidays-eid-dinner-invitation',
48
+ meta: {
49
+ name: NAME,
50
+ description: 'A printed invitation to an Eid al-Fitr dinner at home: a pointed arch in fine gold lines frames the card, eight-pointed stars tile the margins on deep midnight teal, a crescent and star sit in the arch’s crown and three lanterns hang inside it over “Eid Mubarak” in a gold serif and the details, the date given as the moon allows. 5 × 7 inches with bleed, and an A6 copy',
51
+ category: 'invitation', tags: ['eid', 'eid al-fitr', 'eid mubarak', 'ramadan', 'iftar', 'dinner', 'family', 'lantern', 'fanous', 'crescent', 'islamic geometric', 'muslim', 'invitation', 'print', 'card'],
52
+ platforms: ['print'], formats: ['card'], useCases: ['invitation', 'event'],
53
+ created: '2026-10-10', updated: '2026-10-10',
54
+ },
55
+ stableNumbers: true,
56
+ build() {
57
+ const k = new Kit(NAME, preset('invitation-5x7'))
58
+ k.quantizeGeometry = true
59
+ k.brand(
60
+ { paper: '#0B3B44', text: '#FFF6E2', onPaper: '#E7C77A', primary: '#E7C77A', onPrimary: '#0B3B44' },
61
+ { name: 'the Rahman family' },
62
+ )
63
+ k.palette({ gold: '#E2BE6A', goldDeep: '#A88334', amber: '#F2A93B', cream: '#FFF6E2', tile: '#1C5A63', tileDeep: '#13474F' })
64
+ k.textStyle('Kicker 10.5', { size: 10.5, fontWeight: 700, letterSpacing: 3.2, lineHeight: 15 })
65
+ k.textStyle('Title 50', { ...SERIF, size: 50, fontWeight: 600, letterSpacing: -0.8, lineHeight: 52 })
66
+ k.textStyle('Sub 16', { ...SERIF, size: 16, fontWeight: 400, fontStyle: 'italic', lineHeight: 22 })
67
+ k.textStyle('When 14', { size: 14, fontWeight: 700, lineHeight: 20 })
68
+ k.textStyle('Body 11.5', { ...SERIF, size: 11.5, fontWeight: 400, lineHeight: 16.5 })
69
+ k.textStyle('Rsvp 9.5', { size: 9.5, fontWeight: 700, letterSpacing: 1.4, lineHeight: 14 })
70
+
71
+ const sheet = k.sheet
72
+ const { width: W, height: H } = k.node(sheet)
73
+ k.flowSheet(sheet, 0, PAD, 'paper', 'MIN', 'CENTER')
74
+ draw(k, sheet, art(W, H))
75
+ const c = { align: 'CENTER' as const, width: 'FILL' as const }
76
+ k.text(sheet, 'WITH JOY, WE INVITE YOU', { style: 'Kicker 10.5', color: 'onPaper', ...c, name: 'Kicker' })
77
+ k.stack(sheet, { height: 6, name: 'Gap' })
78
+ k.text(sheet, 'Eid Mubarak', { style: 'Title 50', color: 'onPaper', ...c, name: 'Title' })
79
+ k.text(sheet, 'to Eid al-Fitr dinner with {{brand.name}}', { style: 'Sub 16', color: 'text', ...c, name: 'Sub' })
80
+ k.stack(sheet, { height: 12, name: 'Gap' })
81
+ flourishComponent(k, 'Star rule', 'primary', eightStar(0, 0, 10), { rule: 26, size: 9 })
82
+ k.instance(sheet, 'Star rule', {}, { name: 'Divider' })
83
+ k.stack(sheet, { height: 12, name: 'Gap' })
84
+ k.text(sheet, 'Tuesday 9 March, after Maghrib', { style: 'When 14', color: 'text', ...c, name: 'When' })
85
+ k.text(sheet, 'or the evening Eid falls, as the moon decides', { style: 'Body 11.5', color: 'onPaper', ...c, name: 'Moon' })
86
+ k.text(sheet, '12 Cedar Hollow Drive, Dearborn', { style: 'Body 11.5', color: 'text', ...c, name: 'Where' })
87
+ k.stack(sheet, { height: 10, name: 'Gap' })
88
+ k.text(sheet, 'Biryani, sheer khurma and far too many sweets. Eidi bags for the children at the door.', { style: 'Body 11.5', color: 'text', ...c, name: 'Body' })
89
+ k.stack(sheet, { height: 10, name: 'Gap' })
90
+ k.text(sheet, 'RSVP TO AMINA · (313) 555-0147', { style: 'Rsvp 9.5', color: 'onPaper', ...c, name: 'Rsvp' })
91
+
92
+ k.textStyle('Title 42', { ...SERIF, size: 42, fontWeight: 600, letterSpacing: -0.6, lineHeight: 44 })
93
+ k.textStyle('Sub 13.5', { ...SERIF, size: 13.5, fontWeight: 400, fontStyle: 'italic', lineHeight: 18 })
94
+ k.textStyle('When 12', { size: 12, fontWeight: 700, lineHeight: 17 })
95
+ k.textStyle('Body 10', { ...SERIF, size: 10, fontWeight: 400, lineHeight: 14 })
96
+ k.textStyle('Rsvp 8.5', { size: 8.5, fontWeight: 700, letterSpacing: 1.1, lineHeight: 13 })
97
+ k.textStyle('Kicker 9', { size: 9, fontWeight: 700, letterSpacing: 2.6, lineHeight: 13 })
98
+ k.variants(sheet, [printVariant('a6', {
99
+ art, pad: PAD, masterWidth: W,
100
+ styles: [['Title', 'Title 42'], ['Sub', 'Sub 13.5'], ['When', 'When 12'], ['Where', 'Body 10'], ['Moon', 'Body 10'], ['Body', 'Body 10'], ['Rsvp', 'Rsvp 8.5'], ['Kicker', 'Kicker 9']],
101
+ })])
102
+ return k.finish()
103
+ },
104
+ })
@@ -0,0 +1,94 @@
1
+ // A sheet of twelve Eid gift tags for Eidi envelopes and presents: tall tags with clipped corners and a punched hole
2
+ // for the ribbon, in mint, lilac, sand and deep teal, each with a picture (a hanging lantern, a crescent and star, an
3
+ // eight-pointed star, an arched window), a greeting ("Eid Mubarak", "Eid Saeed") and "To" and "From" lines. One
4
+ // component set, so a colour change reaches every tag. US Letter on a soft ground with a border of eight-pointed stars
5
+ // running into the bleed, and an A4 copy.
6
+
7
+ import { Kit, preset } from '../kit'
8
+ import { defineTemplate } from '../build'
9
+ import { SERIF } from '../shared/type'
10
+ import type { VectorPath } from '@/lib/document/types'
11
+ import { archPath, crescent, disc, draw, eightStar, fanous, polyP, printVariant, starPath, tilePattern, type Drawn } from '../themes/holidays-shared'
12
+
13
+ const NAME = 'Eid gift tags sheet'
14
+ const TW = 158, TH = 256
15
+ const PAD = { top: 60, right: 48, bottom: 44, left: 48 }
16
+
17
+ type Design = 'Lantern' | 'Crescent' | 'Star' | 'Arch'
18
+ const DESIGNS: readonly Design[] = ['Lantern', 'Crescent', 'Star', 'Arch']
19
+ const LOOK: Record<Design, { tag: string; ink: string; art: string; art2: string }> = {
20
+ Lantern: { tag: 'mint', ink: 'tealInk', art: 'gold', art2: 'tealInk' },
21
+ Crescent: { tag: 'teal', ink: 'sand', art: 'gold', art2: 'sand' },
22
+ Star: { tag: 'lilac', ink: 'plumInk', art: 'gold', art2: 'plumInk' },
23
+ Arch: { tag: 'sand', ink: 'tealInk', art: 'teal', art2: 'gold' },
24
+ }
25
+
26
+ /** The tag: a tall card with its top corners clipped. */
27
+ const tagShape = (): VectorPath => polyP([{ x: 28, y: 0 }, { x: TW - 28, y: 0 }, { x: TW, y: 28 }, { x: TW, y: TH }, { x: 0, y: TH }, { x: 0, y: 28 }])
28
+
29
+ function picture(d: Design, cx: number, cy: number): Drawn[] {
30
+ const L = LOOK[d]
31
+ if (d === 'Lantern') { const f = fanous(cx, cy - 46, 92); return [{ name: 'Lantern glass', paths: f.glass, color: 'amber' }, { name: 'Lantern frame', paths: f.frame, color: L.art2, o: { strokeWidth: 1.2 } }, { name: 'Lantern', paths: f.metal, color: L.art }] }
32
+ if (d === 'Crescent') return [{ name: 'Crescent', paths: [crescent(cx - 4, cy, 34, 0.5, 1, -0.5)], color: L.art }, { name: 'Star', paths: [starPath(cx + 22, cy - 16, 9, 3.6)], color: L.art }, { name: 'Little stars', paths: [starPath(cx - 30, cy + 30, 4, 1.6), starPath(cx + 30, cy + 26, 3, 1.2)], color: L.art2 }]
33
+ if (d === 'Star') return [{ name: 'Big star', paths: [eightStar(cx, cy, 36)], color: L.art }, { name: 'Star heart', paths: [eightStar(cx, cy, 20)], color: L.tag }, { name: 'Star dot', paths: [disc(cx, cy, 8)], color: L.art2 }]
34
+ return [{ name: 'Window', paths: [archPath(cx, 64, cy + 40, cy - 6, cy - 50)], color: L.art }, { name: 'Window light', paths: [archPath(cx, 44, cy + 32, cy, cy - 34)], color: 'amber' }, { name: 'Sill', paths: [polyP([{ x: cx - 40, y: cy + 40 }, { x: cx + 40, y: cy + 40 }, { x: cx + 34, y: cy + 48 }, { x: cx - 34, y: cy + 48 }])], color: L.art2 }]
35
+ }
36
+
37
+ function border(w: number, h: number): Drawn[] {
38
+ const B = 12, band = 30
39
+ const place = (x0: number, y0: number, x1: number, y1: number) => { const t = tilePattern(x1 - x0, y1 - y0, 30); return t.stars.map(p => ({ ...p, points: p.points.map(q => ({ ...q, x: q.x + x0, y: q.y + y0 })) })) }
40
+ return [
41
+ { name: 'Border', paths: place(-B, -B, w + B, band), color: 'border' },
42
+ { name: 'Border', paths: place(-B, h - band, w + B, h + B), color: 'border' },
43
+ ]
44
+ }
45
+
46
+ export default defineTemplate({
47
+ id: 'print-holidays-eid-gift-tags',
48
+ meta: {
49
+ name: NAME,
50
+ description: 'Twelve Eid gift tags for Eidi envelopes and presents on one sheet: tall tags with clipped corners and a ribbon hole in mint, lilac, sand and deep teal, each with a lantern, a crescent and star, an eight-pointed star or an arched window, a greeting and “To” and “From” lines. One component set, so a colour change reaches every tag. US Letter with bleed, and an A4 copy',
51
+ category: 'sticker', tags: ['eid', 'eid al-fitr', 'eid al-adha', 'eid mubarak', 'eidi', 'gift tags', 'labels', 'presents', 'lantern', 'crescent', 'islamic geometric', 'printable', 'diy', 'print'],
52
+ platforms: ['print'], formats: ['card'], useCases: ['greeting'],
53
+ created: '2026-10-10', updated: '2026-10-10',
54
+ },
55
+ stableNumbers: true,
56
+ build() {
57
+ const k = new Kit(NAME, preset('us-letter'))
58
+ k.quantizeGeometry = true
59
+ k.brand(
60
+ { paper: '#FBF7EF', text: '#123F45', onPaper: '#5A6E6F', primary: '#1C5A63', onPrimary: '#FFFFFF' },
61
+ { name: 'The Siddiqui family' },
62
+ )
63
+ k.palette({ mint: '#CFEAD9', teal: '#1C5A63', lilac: '#DCCDEE', sand: '#F1E2C4', gold: '#D9A93E', amber: '#F2B54A', tealInk: '#123F45', plumInk: '#40285E', border: '#E3D4AE' })
64
+ k.textStyle('Head 30', { ...SERIF, size: 30, fontWeight: 600, letterSpacing: -0.4, lineHeight: 34 })
65
+ k.textStyle('Note 11', { size: 11, fontWeight: 500, lineHeight: 16 })
66
+ k.textStyle('Greeting 17', { ...SERIF, size: 17, fontWeight: 700, lineHeight: 21 })
67
+ k.textStyle('Tag word 8.5', { size: 8.5, fontWeight: 700, letterSpacing: 1.8, lineHeight: 15 })
68
+
69
+ k.variantSet('Eid tag', 'Design', DESIGNS, { width: TW, height: TH, padding: { top: 150, right: 14, bottom: 16, left: 14 }, gap: 4, align: 'CENTER', props: { Greeting: 'Eid Mubarak', To: 'TO: ____________', From: 'FROM: __________' } }, (d, id) => {
70
+ const L = LOOK[d as Design]
71
+ k.vector(id, TW, TH, [tagShape()], L.tag, { name: 'Tag', absolute: { x: 0, y: 0 } })
72
+ k.vector(id, 14, 14, [disc(7, 7, 7)], 'paper', { name: 'Ribbon hole', absolute: { x: TW / 2 - 7, y: 14 } })
73
+ k.vector(id, 20, 20, [disc(10, 10, 10)], [], { name: 'Hole ring', absolute: { x: TW / 2 - 10, y: 11 }, stroke: { color: L.art, width: 1.4 } })
74
+ draw(k, id, picture(d as Design, TW / 2, 92))
75
+ k.propText(id, 'Greeting', { style: 'Greeting 17', color: L.ink, align: 'CENTER', width: 'FILL', name: 'Greeting' })
76
+ k.propText(id, 'To', { style: 'Tag word 8.5', color: L.ink, align: 'CENTER', width: 'FILL', name: 'To' })
77
+ k.propText(id, 'From', { style: 'Tag word 8.5', color: L.ink, align: 'CENTER', width: 'FILL', name: 'From' })
78
+ })
79
+
80
+ const sheet = k.sheet
81
+ const { width: W, height: H } = k.node(sheet)
82
+ k.flowSheet(sheet, 18, PAD, 'paper', 'MIN', 'CENTER')
83
+ draw(k, sheet, border(W, H))
84
+ k.text(sheet, 'Eid gift tags', { style: 'Head 30', color: 'text', align: 'CENTER', width: 'FILL', name: 'Title' })
85
+ const grid = k.stack(sheet, { direction: 'HORIZONTAL', wrap: true, gap: 18, width: 'FILL', justify: 'CENTER', name: 'Tags' })
86
+ k.patch(grid, { counterAxisSpacing: 18 })
87
+ const greet = ['Eid Mubarak', 'Eid Saeed', 'Your Eidi!', 'With love', 'Eid Mubarak', 'For you', 'Happy Eid', 'Eid Mubarak', 'Eid Saeed', 'With love', 'Your Eidi!', 'Happy Eid']
88
+ greet.forEach((g, i) => k.instance(grid, `Eid tag/${DESIGNS[(i + Math.floor(i / 4)) % 4]}`, { Greeting: g }, { name: 'Eid tag' }))
89
+ k.text(sheet, 'Print on card, cut round each tag, punch the hole and thread a ribbon. From {{brand.name}}', { style: 'Note 11', color: 'text', align: 'CENTER', width: 'FILL', name: 'Note' })
90
+
91
+ k.variants(sheet, [printVariant('a4', { art: border, pad: PAD, masterWidth: W })])
92
+ return k.finish()
93
+ },
94
+ })
@@ -0,0 +1,101 @@
1
+ // A printed invitation to a grown-ups' Halloween costume party: a full harvest moon fills the top of a night-black card
2
+ // with "Monster Mash" set heavy in black across its face, bats wheel round its edge and a web hangs in the corner,
3
+ // the details follow in bone and pumpkin orange, and three jack-o'-lanterns glow along the foot in the grass. 5 × 7
4
+ // inches with the night running into the bleed, and an A6 copy with the drawing worked out again.
5
+
6
+ import { Kit, preset } from '../kit'
7
+ import { defineTemplate } from '../build'
8
+ import { SERIF } from '../shared/type'
9
+ import { blurred } from '../shared/texture'
10
+ import { bat, branch, disc, draw, polyP, rectPath, flourishComponent, grass, jackFace, printVariant, pumpkin, specksIn, web, type Drawn } from '../themes/holidays-shared'
11
+
12
+ const NAME = 'Halloween costume party invitation'
13
+ const PAD = { top: 92, right: 44, bottom: 120, left: 44 }
14
+
15
+ function art(w: number, h: number): Drawn[] {
16
+ const s = w / 480, B = 14 * s, cx = w / 2
17
+ const moon = { x: cx, y: 160 * s, r: 132 * s }
18
+ const craters = [[-50, -60, 18], [40, -30, 12], [-20, 50, 22], [60, 60, 14], [-80, 20, 9]].map(([x, y, r]) => disc(moon.x + x * s, moon.y + y * s, r * s))
19
+ const bats = [[0.12, 0.08, 46, 0.4], [0.86, 0.06, 38, -0.2], [0.92, 0.33, 30, 0.2], [0.08, 0.34, 26, -0.4], [0.76, 0.42, 22, 0.1]].map(([x, y, sz, f]) => bat(w * x, h * y, sz * s, f))
20
+ const fence = Array.from({ length: 11 }, (_, i) => { const x = w * 0.52 + i * 20 * s; return polyP([{ x, y: h - 92 * s }, { x: x + 5 * s, y: h - 104 * s }, { x: x + 10 * s, y: h - 92 * s }, { x: x + 10 * s, y: h - 40 * s }, { x, y: h - 40 * s }]) })
21
+ fence.push(rectPath(w * 0.52, h - 82 * s, 220 * s, 5 * s), rectPath(w * 0.52, h - 58 * s, 220 * s, 5 * s))
22
+ const tree = branch([{ x: 40 * s, y: h }, { x: 46 * s, y: h - 120 * s }, { x: 64 * s, y: h - 190 * s }, { x: 104 * s, y: h - 236 * s }], 8, 6, 46 * s)
23
+ const pk = [[0.2, 74, 60], [0.5, 104, 80], [0.8, 78, 62]].map(([x, pw, ph]) => ({ x: w * x, p: pumpkin(w * x, h - 22 * s, pw * s * 1.2, ph * s), face: jackFace(w * x, h - 22 * s - ph * s * 0.48, pw * s * 1.0) }))
24
+ return [
25
+ { name: 'Stars', paths: specksIn({ x: -B, y: -B, w: 90 * s, h: 330 * s }, 300 * s * s, 4, 2 * s), color: 'bone', o: { opacity: 0.5 } },
26
+ { name: 'Stars', paths: specksIn({ x: w - 76 * s, y: -B, w: 90 * s, h: 330 * s }, 300 * s * s, 5, 2 * s), color: 'bone', o: { opacity: 0.5 } },
27
+ { name: 'Moon glow', paths: [disc(moon.x, moon.y, moon.r * 1.12)], color: 'bone', o: { opacity: 0.22, effects: [blurred(18 * s)] } },
28
+ { name: 'Moon', paths: [disc(moon.x, moon.y, moon.r)], color: 'bone' },
29
+ { name: 'Craters', paths: craters, color: 'boneDeep', o: { opacity: 0.55 } },
30
+ { name: 'Web', paths: web(-4 * s, -4 * s, 120 * s, 0, Math.PI / 2, 7, 6), color: 'bone', o: { strokeWidth: 1 * s, opacity: 0.6 } },
31
+ ...bats.map(b => ({ name: 'Bat', paths: [b], color: 'batPurple' })),
32
+ { name: 'Hill', paths: [polyP([{ x: -B, y: h + B }, ...Array.from({ length: 13 }, (_, i) => ({ x: -B + ((w + 2 * B) * i) / 12, y: h - 96 * s + Math.sin(i * 0.7) * 10 * s })), { x: w + B, y: h + B }])], color: 'hill' },
33
+ { name: 'Fence', paths: fence, color: 'hill' },
34
+ { name: 'Tree', paths: tree.limb, color: 'hill', o: { strokeWidth: 7 * s } },
35
+ { name: 'Twigs', paths: tree.twigs, color: 'hill', o: { strokeWidth: 3 * s } },
36
+ { name: 'Pumpkin glow', paths: pk.map(p => disc(p.x, h - 48 * s, 64 * s, 44 * s)), color: 'pumpkin', o: { opacity: 0.35, effects: [blurred(22 * s)] } },
37
+ { name: 'Pumpkins', paths: pk.flatMap(p => p.p.lobes), color: 'pumpkin' },
38
+ { name: 'Pumpkin creases', paths: pk.flatMap(p => p.p.creases), color: 'pumpkinDeep', o: { strokeWidth: 1.6 * s } },
39
+ { name: 'Pumpkin stems', paths: pk.flatMap(p => p.p.stem), color: 'stem' },
40
+ { name: 'Faces', paths: pk.flatMap(p => p.face), color: 'candle' },
41
+ { name: 'Grass', paths: grass(-B, w + B, h + B, 30 * s, 13, 60), color: 'ink' },
42
+ ]
43
+ }
44
+
45
+ export default defineTemplate({
46
+ id: 'print-holidays-halloween-party-invitation',
47
+ meta: {
48
+ name: NAME,
49
+ description: 'A printed invitation to a grown-ups’ Halloween costume party: a full harvest moon fills the top of a night-black card with “Monster Mash” set heavy across its face, bats round its edge and a web in the corner, the details in bone and pumpkin orange, and three glowing jack-o’-lanterns in the grass. 5 × 7 inches with bleed, and an A6 copy',
50
+ category: 'invitation', tags: ['halloween', 'costume party', 'party', 'monster mash', 'pumpkins', 'jack-o’-lantern', 'bats', 'moon', 'spooky', 'invitation', 'print', 'card', 'october'],
51
+ platforms: ['print'], formats: ['card'], useCases: ['invitation', 'event'],
52
+ created: '2026-10-10', updated: '2026-10-10',
53
+ },
54
+ stableNumbers: true,
55
+ build() {
56
+ const k = new Kit(NAME, preset('invitation-5x7'))
57
+ k.quantizeGeometry = true
58
+ k.brand(
59
+ { paper: '#15121B', text: '#F1E6CF', onPaper: '#F08A2C', primary: '#F08A2C', onPrimary: '#15121B' },
60
+ { name: 'the Hendersons' },
61
+ )
62
+ k.palette({ batPurple: '#5A3F86', hill: '#26202F', bone: '#F1E6CF', boneDeep: '#D8C7A3', ink: '#15121B', pumpkin: '#F08A2C', pumpkinDeep: '#B85A12', stem: '#5B6B3A', candle: '#FFD35C' })
63
+ k.textStyle('Kicker 12', { size: 12, fontWeight: 800, letterSpacing: 4, lineHeight: 16 })
64
+ k.textStyle('Title 64', { size: 56, fontWeight: 900, letterSpacing: -2.2, lineHeight: 50 })
65
+ k.textStyle('When 16', { ...SERIF, size: 16, fontWeight: 700, lineHeight: 22 })
66
+ k.textStyle('Body 12', { ...SERIF, size: 12, fontWeight: 400, lineHeight: 17 })
67
+ k.textStyle('Rsvp 10', { size: 10, fontWeight: 700, letterSpacing: 1.6, lineHeight: 15 })
68
+
69
+ const sheet = k.sheet
70
+ const { width: W, height: H } = k.node(sheet)
71
+ k.flowSheet(sheet, 0, PAD, 'paper', 'MIN', 'CENTER')
72
+ draw(k, sheet, art(W, H))
73
+ const c = { align: 'CENTER' as const, width: 'FILL' as const }
74
+ k.text(sheet, 'THE ANNUAL', { style: 'Kicker 12', color: 'ink', ...c, name: 'Kicker' })
75
+ k.stack(sheet, { height: 6, name: 'Gap' })
76
+ k.text(sheet, 'MONSTER\nMASH', { style: 'Title 64', color: 'ink', ...c, name: 'Title' })
77
+ k.stack(sheet, { height: 6, name: 'Gap' })
78
+ k.text(sheet, 'A COSTUME PARTY', { style: 'Kicker 12', color: 'ink', ...c, name: 'Sub' })
79
+ k.stack(sheet, { height: 92, name: 'Gap' })
80
+ k.text(sheet, 'Saturday 31 October · 8 pm till late', { style: 'When 16', color: 'onPaper', ...c, name: 'When' })
81
+ k.text(sheet, 'at {{brand.name}}’, 77 Ravenwood Lane', { style: 'Body 12', color: 'text', ...c, name: 'Where' })
82
+ k.stack(sheet, { height: 10, name: 'Gap' })
83
+ flourishComponent(k, 'Bat rule', 'primary', bat(0, 0, 30), { rule: 30, size: 18 })
84
+ k.instance(sheet, 'Bat rule', {}, { name: 'Divider' })
85
+ k.stack(sheet, { height: 10, name: 'Gap' })
86
+ k.text(sheet, 'Costumes compulsory. Prizes for the scariest, the funniest and the most homemade. Witches’ brew, a candy table and a DJ who takes requests.', { style: 'Body 12', color: 'text', ...c, name: 'Body' })
87
+ k.stack(sheet, { height: 10, name: 'Gap' })
88
+ k.text(sheet, 'RSVP TO MEG · (614) 555-0131', { style: 'Rsvp 10', color: 'onPaper', ...c, name: 'Rsvp' })
89
+
90
+ k.textStyle('Title 54', { size: 47, fontWeight: 900, letterSpacing: -1.8, lineHeight: 42 })
91
+ k.textStyle('When 13.5', { ...SERIF, size: 13.5, fontWeight: 700, lineHeight: 19 })
92
+ k.textStyle('Body 10.5', { ...SERIF, size: 10.5, fontWeight: 400, lineHeight: 15 })
93
+ k.textStyle('Rsvp 8.5', { size: 8.5, fontWeight: 700, letterSpacing: 1.2, lineHeight: 13 })
94
+ k.textStyle('Kicker 10', { size: 10, fontWeight: 800, letterSpacing: 3.4, lineHeight: 14 })
95
+ k.variants(sheet, [printVariant('a6', {
96
+ art, pad: PAD, masterWidth: W,
97
+ styles: [['Title', 'Title 54'], ['When', 'When 13.5'], ['Where', 'Body 10.5'], ['Body', 'Body 10.5'], ['Rsvp', 'Rsvp 8.5'], ['Kicker', 'Kicker 10'], ['Sub', 'Kicker 10']],
98
+ })])
99
+ return k.finish()
100
+ },
101
+ })