kasaframe 0.1.3 → 0.1.5

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 (1016) hide show
  1. package/NOTICE +298 -0
  2. package/README.md +16 -3
  3. package/docs/AGENTS.md +1 -1
  4. package/package.json +1 -1
  5. package/packages/adapters/src/project.ts +4 -0
  6. package/packages/adapters/src/texture.ts +94 -0
  7. package/packages/cli/src/cells.ts +227 -0
  8. package/packages/cli/src/commands/doctor.ts +15 -2
  9. package/packages/cli/src/commands/fonts.ts +118 -0
  10. package/packages/cli/src/commands/make.ts +77 -9
  11. package/packages/cli/src/commands/new.ts +2 -2
  12. package/packages/cli/src/commands/theme.ts +141 -10
  13. package/packages/cli/src/commands/update.ts +66 -0
  14. package/packages/cli/src/fonts.ts +405 -0
  15. package/packages/cli/src/kf.ts +5 -0
  16. package/packages/cli/src/lock.ts +8 -6
  17. package/packages/cli/src/pick.ts +110 -0
  18. package/packages/cli/src/update.ts +250 -0
  19. package/packages/cli/src/vary.ts +124 -0
  20. package/packages/core/src/index.ts +1 -1
  21. package/packages/core/src/project.ts +15 -0
  22. package/packages/director/src/assemble.ts +6 -3
  23. package/packages/motion/src/moves/menu.ts +2 -1
  24. package/packages/patterns/src/kit.ts +3 -2
  25. package/packages/plan/src/asks.ts +25 -16
  26. package/packages/plan/src/index.ts +2 -2
  27. package/packages/plan/src/plan.ts +4 -2
  28. package/packages/plan/src/themes.ts +71 -9
  29. package/packages/plan/src/types.ts +3 -0
  30. package/packages/themes/kit/THEME-MAKE.md +2 -1
  31. package/packages/themes/kit/fonts/display.json +3517 -0
  32. package/packages/themes/kit/fonts/sans.json +5155 -0
  33. package/packages/themes/kit/fonts/serif.json +5229 -0
  34. package/packages/themes/kit/fonts.json +907 -0
  35. package/packages/themes/package.json +8 -1
  36. package/packages/themes/src/color.ts +152 -0
  37. package/packages/themes/src/fontfile.ts +183 -0
  38. package/packages/themes/src/fonts.ts +296 -0
  39. package/packages/themes/src/fx.ts +4 -2
  40. package/packages/themes/src/index.ts +75 -3
  41. package/packages/themes/src/look.ts +249 -0
  42. package/packages/themes/src/name.ts +9 -0
  43. package/packages/themes/src/palette.ts +194 -0
  44. package/packages/themes/src/slotkit.ts +14 -1
  45. package/packages/themes/src/slots.ts +17 -2
  46. package/packages/themes/src/types.ts +89 -0
  47. package/packages/themes/src/vary.ts +291 -0
  48. package/presets/kawaii-pastel.json +2 -2
  49. package/skills/kasaframe/SKILL.md +1 -0
  50. package/themes/blueprint/THEME.md +64 -0
  51. package/themes/blueprint/effects.ts +570 -0
  52. package/themes/blueprint/sample/beats.json +1005 -0
  53. package/themes/blueprint/sample/index.html +11 -0
  54. package/themes/blueprint/sample/kf.json +59 -0
  55. package/themes/blueprint/sample/lib/facts.ts +29 -0
  56. package/themes/blueprint/sample/lib/sheet.ts +55 -0
  57. package/themes/blueprint/sample/main.ts +9 -0
  58. package/themes/blueprint/sample/scenes/end.ts +91 -0
  59. package/themes/blueprint/sample/scenes/gather.ts +75 -0
  60. package/themes/blueprint/sample/scenes/models.ts +117 -0
  61. package/themes/blueprint/sample/scenes/price.ts +94 -0
  62. package/themes/blueprint/sample/style.json +114 -0
  63. package/themes/blueprint/slots.ts +88 -0
  64. package/themes/blueprint/still.png +0 -0
  65. package/themes/blueprint/style.json +114 -0
  66. package/themes/blueprint/theme.json +139 -0
  67. package/themes/blueprint/variants/deep-rose-2.json +90 -0
  68. package/themes/blueprint/variants/deep-rose-suit.json +117 -0
  69. package/themes/blueprint/variants/deep-rose.json +117 -0
  70. package/themes/blueprint/variants/navy-coral-2.json +118 -0
  71. package/themes/blueprint/variants/navy-coral-suit.json +118 -0
  72. package/themes/blueprint/variants/navy-coral.json +128 -0
  73. package/themes/blueprint/variants/navy-orange-2.json +118 -0
  74. package/themes/blueprint/variants/navy-orange-3.json +91 -0
  75. package/themes/blueprint/variants/navy-orange-4.json +128 -0
  76. package/themes/blueprint/variants/navy-orange-mono.json +128 -0
  77. package/themes/blueprint/variants/navy-orange-plex.json +128 -0
  78. package/themes/blueprint/variants/navy-orange-suit.json +118 -0
  79. package/themes/blueprint/variants/navy-orange.json +118 -0
  80. package/themes/blueprint/variants/navy-rose-plex.json +127 -0
  81. package/themes/blueprint/variants/navy-rose.json +127 -0
  82. package/themes/cartography/THEME.md +61 -0
  83. package/themes/cartography/effects.ts +845 -0
  84. package/themes/cartography/sample/assets/og/logo.svg +12 -0
  85. package/themes/cartography/sample/beats.json +1005 -0
  86. package/themes/cartography/sample/index.html +11 -0
  87. package/themes/cartography/sample/kf.json +59 -0
  88. package/themes/cartography/sample/lib/facts.ts +29 -0
  89. package/themes/cartography/sample/lib/map.ts +39 -0
  90. package/themes/cartography/sample/main.ts +9 -0
  91. package/themes/cartography/sample/scenes/end.ts +56 -0
  92. package/themes/cartography/sample/scenes/gather.ts +46 -0
  93. package/themes/cartography/sample/scenes/models.ts +43 -0
  94. package/themes/cartography/sample/scenes/price.ts +73 -0
  95. package/themes/cartography/sample/style.json +103 -0
  96. package/themes/cartography/slots.ts +87 -0
  97. package/themes/cartography/still.png +0 -0
  98. package/themes/cartography/style.json +103 -0
  99. package/themes/cartography/theme.json +162 -0
  100. package/themes/cartography/variants/blush-amber.json +128 -0
  101. package/themes/cartography/variants/blush-indigo.json +128 -0
  102. package/themes/cartography/variants/blush-pink.json +136 -0
  103. package/themes/cartography/variants/chalk-plum.json +137 -0
  104. package/themes/cartography/variants/chalk-sky.json +100 -0
  105. package/themes/cartography/variants/cocoa-amber.json +128 -0
  106. package/themes/cartography/variants/deep-plum.json +125 -0
  107. package/themes/cartography/variants/dusk-coral.json +128 -0
  108. package/themes/cartography/variants/forest-lime.json +131 -0
  109. package/themes/cartography/variants/frost-teal.json +128 -0
  110. package/themes/cartography/variants/navy-green.json +131 -0
  111. package/themes/cartography/variants/navy-indigo.json +138 -0
  112. package/themes/cartography/variants/navy-sky.json +100 -0
  113. package/themes/cartography/variants/sage-green.json +127 -0
  114. package/themes/cartography/variants/wine-teal.json +128 -0
  115. package/themes/circuit-board/THEME.md +61 -0
  116. package/themes/circuit-board/effects.ts +576 -0
  117. package/themes/circuit-board/pcb.ts +103 -0
  118. package/themes/circuit-board/sample/assets/og/logo.svg +12 -0
  119. package/themes/circuit-board/sample/beats.json +1005 -0
  120. package/themes/circuit-board/sample/index.html +11 -0
  121. package/themes/circuit-board/sample/kf.json +59 -0
  122. package/themes/circuit-board/sample/lib/facts.ts +29 -0
  123. package/themes/circuit-board/sample/lib/kit.ts +45 -0
  124. package/themes/circuit-board/sample/main.ts +9 -0
  125. package/themes/circuit-board/sample/scenes/end.ts +102 -0
  126. package/themes/circuit-board/sample/scenes/gather.ts +76 -0
  127. package/themes/circuit-board/sample/scenes/models.ts +101 -0
  128. package/themes/circuit-board/sample/scenes/price.ts +109 -0
  129. package/themes/circuit-board/sample/style.json +104 -0
  130. package/themes/circuit-board/slots.ts +108 -0
  131. package/themes/circuit-board/still.png +0 -0
  132. package/themes/circuit-board/style.json +104 -0
  133. package/themes/circuit-board/theme.json +151 -0
  134. package/themes/circuit-board/variants/deep-gold-plex.json +133 -0
  135. package/themes/circuit-board/variants/deep-gold.json +123 -0
  136. package/themes/circuit-board/variants/dusk-gold-grain.json +138 -0
  137. package/themes/circuit-board/variants/dusk-gold-pretendard.json +118 -0
  138. package/themes/circuit-board/variants/dusk-gold.json +97 -0
  139. package/themes/circuit-board/variants/forest-gold-2.json +96 -0
  140. package/themes/circuit-board/variants/forest-gold-grain.json +129 -0
  141. package/themes/circuit-board/variants/forest-gold-mono.json +124 -0
  142. package/themes/circuit-board/variants/forest-gold.json +128 -0
  143. package/themes/circuit-board/variants/navy-gold-grain.json +124 -0
  144. package/themes/circuit-board/variants/navy-gold.json +101 -0
  145. package/themes/circuit-board/variants/wine-gold-grain.json +128 -0
  146. package/themes/circuit-board/variants/wine-gold-plex.json +133 -0
  147. package/themes/circuit-board/variants/wine-gold-pretendard.json +118 -0
  148. package/themes/circuit-board/variants/wine-gold.json +128 -0
  149. package/themes/clay-toy/THEME.md +73 -0
  150. package/themes/clay-toy/effects.ts +643 -0
  151. package/themes/clay-toy/glyphs.ts +32 -0
  152. package/themes/clay-toy/sample/assets/og/logo.svg +12 -0
  153. package/themes/clay-toy/sample/beats.json +1005 -0
  154. package/themes/clay-toy/sample/index.html +11 -0
  155. package/themes/clay-toy/sample/kf.json +59 -0
  156. package/themes/clay-toy/sample/lib/clay.ts +20 -0
  157. package/themes/clay-toy/sample/lib/facts.ts +29 -0
  158. package/themes/clay-toy/sample/main.ts +9 -0
  159. package/themes/clay-toy/sample/scenes/end.ts +81 -0
  160. package/themes/clay-toy/sample/scenes/gather.ts +53 -0
  161. package/themes/clay-toy/sample/scenes/models.ts +77 -0
  162. package/themes/clay-toy/sample/scenes/price.ts +91 -0
  163. package/themes/clay-toy/sample/style.json +101 -0
  164. package/themes/clay-toy/slots.ts +132 -0
  165. package/themes/clay-toy/still.png +0 -0
  166. package/themes/clay-toy/style.json +101 -0
  167. package/themes/clay-toy/theme.json +148 -0
  168. package/themes/clay-toy/variants/blush-coral-grain.json +126 -0
  169. package/themes/clay-toy/variants/blush-coral.json +123 -0
  170. package/themes/clay-toy/variants/chalk-indigo.json +97 -0
  171. package/themes/clay-toy/variants/chalk-jade.json +125 -0
  172. package/themes/clay-toy/variants/chalk-teal.json +120 -0
  173. package/themes/clay-toy/variants/frost-orange.json +125 -0
  174. package/themes/clay-toy/variants/frost-sky-grain.json +126 -0
  175. package/themes/clay-toy/variants/frost-sky.json +121 -0
  176. package/themes/clay-toy/variants/frost-teal.json +120 -0
  177. package/themes/clay-toy/variants/lilac-green.json +120 -0
  178. package/themes/clay-toy/variants/lilac-plum-round.json +120 -0
  179. package/themes/clay-toy/variants/lilac-plum.json +124 -0
  180. package/themes/clay-toy/variants/sage-indigo.json +125 -0
  181. package/themes/clay-toy/variants/sage-magenta.json +119 -0
  182. package/themes/clay-toy/variants/sand-amber.json +125 -0
  183. package/themes/conveyor-factory/THEME.md +71 -0
  184. package/themes/conveyor-factory/effects.ts +744 -0
  185. package/themes/conveyor-factory/sample/assets/og/logo.svg +12 -0
  186. package/themes/conveyor-factory/sample/beats.json +1005 -0
  187. package/themes/conveyor-factory/sample/index.html +11 -0
  188. package/themes/conveyor-factory/sample/kf.json +59 -0
  189. package/themes/conveyor-factory/sample/lib/factory.ts +48 -0
  190. package/themes/conveyor-factory/sample/lib/facts.ts +29 -0
  191. package/themes/conveyor-factory/sample/main.ts +9 -0
  192. package/themes/conveyor-factory/sample/scenes/end.ts +44 -0
  193. package/themes/conveyor-factory/sample/scenes/gather.ts +47 -0
  194. package/themes/conveyor-factory/sample/scenes/models.ts +91 -0
  195. package/themes/conveyor-factory/sample/scenes/price.ts +77 -0
  196. package/themes/conveyor-factory/sample/style.json +107 -0
  197. package/themes/conveyor-factory/slots.ts +121 -0
  198. package/themes/conveyor-factory/still.png +0 -0
  199. package/themes/conveyor-factory/style.json +107 -0
  200. package/themes/conveyor-factory/theme.json +144 -0
  201. package/themes/conveyor-factory/variants/cocoa-gold.json +125 -0
  202. package/themes/conveyor-factory/variants/dusk-gold.json +135 -0
  203. package/themes/conveyor-factory/variants/forest-gold.json +135 -0
  204. package/themes/conveyor-factory/variants/navy-amber.json +93 -0
  205. package/themes/conveyor-factory/variants/navy-gold.json +120 -0
  206. package/themes/conveyor-factory/variants/slate-amber-2.json +120 -0
  207. package/themes/conveyor-factory/variants/slate-amber-grain.json +125 -0
  208. package/themes/conveyor-factory/variants/slate-amber-suit.json +120 -0
  209. package/themes/conveyor-factory/variants/slate-amber.json +125 -0
  210. package/themes/conveyor-factory/variants/slate-gold-bold.json +120 -0
  211. package/themes/conveyor-factory/variants/slate-gold.json +120 -0
  212. package/themes/data-journal/THEME.md +74 -0
  213. package/themes/data-journal/effects.ts +570 -0
  214. package/themes/data-journal/sample/assets/og/logo.svg +12 -0
  215. package/themes/data-journal/sample/beats.json +1005 -0
  216. package/themes/data-journal/sample/index.html +11 -0
  217. package/themes/data-journal/sample/kf.json +59 -0
  218. package/themes/data-journal/sample/lib/facts.ts +29 -0
  219. package/themes/data-journal/sample/lib/page.ts +25 -0
  220. package/themes/data-journal/sample/main.ts +9 -0
  221. package/themes/data-journal/sample/scenes/end.ts +69 -0
  222. package/themes/data-journal/sample/scenes/gather.ts +58 -0
  223. package/themes/data-journal/sample/scenes/models.ts +51 -0
  224. package/themes/data-journal/sample/scenes/price.ts +73 -0
  225. package/themes/data-journal/sample/style.json +114 -0
  226. package/themes/data-journal/slots.ts +119 -0
  227. package/themes/data-journal/still.png +0 -0
  228. package/themes/data-journal/style.json +114 -0
  229. package/themes/data-journal/theme.json +142 -0
  230. package/themes/data-journal/variants/blush-green.json +129 -0
  231. package/themes/data-journal/variants/chalk-magenta.json +138 -0
  232. package/themes/data-journal/variants/cocoa-amber.json +140 -0
  233. package/themes/data-journal/variants/cocoa-sky.json +130 -0
  234. package/themes/data-journal/variants/deep-coral.json +135 -0
  235. package/themes/data-journal/variants/dusk-plum.json +132 -0
  236. package/themes/data-journal/variants/forest-green.json +138 -0
  237. package/themes/data-journal/variants/frost-indigo.json +141 -0
  238. package/themes/data-journal/variants/lilac-amber.json +141 -0
  239. package/themes/data-journal/variants/navy-indigo.json +131 -0
  240. package/themes/data-journal/variants/navy-lime.json +128 -0
  241. package/themes/data-journal/variants/snow-sky.json +125 -0
  242. package/themes/data-journal/variants/wine-indigo.json +129 -0
  243. package/themes/data-journal/variants/wine-magenta.json +138 -0
  244. package/themes/data-journal/variants/wine-teal.json +97 -0
  245. package/themes/debug-hud/sample/style.json +1 -1
  246. package/themes/debug-hud/style.json +1 -1
  247. package/themes/debug-hud/theme.json +57 -0
  248. package/themes/debug-hud/variants/cocoa-gold.json +113 -0
  249. package/themes/debug-hud/variants/cocoa-teal.json +119 -0
  250. package/themes/debug-hud/variants/deep-cyan.json +85 -0
  251. package/themes/debug-hud/variants/deep-teal-scan.json +118 -0
  252. package/themes/debug-hud/variants/deep-teal.json +112 -0
  253. package/themes/debug-hud/variants/dusk-plum.json +116 -0
  254. package/themes/debug-hud/variants/dusk-violet.json +112 -0
  255. package/themes/debug-hud/variants/forest-amber.json +86 -0
  256. package/themes/debug-hud/variants/forest-lime.json +117 -0
  257. package/themes/debug-hud/variants/forest-magenta.json +111 -0
  258. package/themes/debug-hud/variants/navy-jade.json +79 -0
  259. package/themes/debug-hud/variants/slate-green.json +112 -0
  260. package/themes/debug-hud/variants/wine-gold.json +119 -0
  261. package/themes/debug-hud/variants/wine-jade.json +83 -0
  262. package/themes/debug-hud/variants/wine-sky.json +112 -0
  263. package/themes/depth-flight/THEME.md +54 -0
  264. package/themes/depth-flight/effects.ts +396 -0
  265. package/themes/depth-flight/sample/assets/og/logo.svg +12 -0
  266. package/themes/depth-flight/sample/beats.json +1005 -0
  267. package/themes/depth-flight/sample/index.html +11 -0
  268. package/themes/depth-flight/sample/kf.json +59 -0
  269. package/themes/depth-flight/sample/lib/facts.ts +29 -0
  270. package/themes/depth-flight/sample/lib/fly.ts +15 -0
  271. package/themes/depth-flight/sample/main.ts +9 -0
  272. package/themes/depth-flight/sample/scenes/end.ts +51 -0
  273. package/themes/depth-flight/sample/scenes/gather.ts +40 -0
  274. package/themes/depth-flight/sample/scenes/models.ts +75 -0
  275. package/themes/depth-flight/sample/scenes/price.ts +50 -0
  276. package/themes/depth-flight/sample/style.json +94 -0
  277. package/themes/depth-flight/slots.ts +196 -0
  278. package/themes/depth-flight/still.png +0 -0
  279. package/themes/depth-flight/style.json +94 -0
  280. package/themes/depth-flight/theme.json +121 -0
  281. package/themes/depth-flight/variants/cocoa-cyan.json +121 -0
  282. package/themes/depth-flight/variants/cocoa-indigo.json +121 -0
  283. package/themes/depth-flight/variants/cocoa-violet.json +122 -0
  284. package/themes/depth-flight/variants/deep-sky.json +126 -0
  285. package/themes/depth-flight/variants/dusk-violet-bold.json +117 -0
  286. package/themes/depth-flight/variants/dusk-violet.json +132 -0
  287. package/themes/depth-flight/variants/forest-blue.json +116 -0
  288. package/themes/depth-flight/variants/forest-cyan.json +122 -0
  289. package/themes/depth-flight/variants/navy-sky-grain.json +122 -0
  290. package/themes/depth-flight/variants/navy-sky.json +116 -0
  291. package/themes/depth-flight/variants/night-teal.json +116 -0
  292. package/themes/depth-flight/variants/slate-cyan.json +127 -0
  293. package/themes/depth-flight/variants/slate-indigo.json +116 -0
  294. package/themes/depth-flight/variants/slate-sky.json +94 -0
  295. package/themes/depth-flight/variants/slate-violet.json +121 -0
  296. package/themes/film-reel/THEME.md +60 -0
  297. package/themes/film-reel/effects.ts +477 -0
  298. package/themes/film-reel/sample/assets/og/logo.svg +12 -0
  299. package/themes/film-reel/sample/beats.json +1005 -0
  300. package/themes/film-reel/sample/index.html +11 -0
  301. package/themes/film-reel/sample/kf.json +59 -0
  302. package/themes/film-reel/sample/lib/facts.ts +29 -0
  303. package/themes/film-reel/sample/lib/reel.ts +9 -0
  304. package/themes/film-reel/sample/main.ts +9 -0
  305. package/themes/film-reel/sample/scenes/end.ts +31 -0
  306. package/themes/film-reel/sample/scenes/gather.ts +40 -0
  307. package/themes/film-reel/sample/scenes/models.ts +37 -0
  308. package/themes/film-reel/sample/scenes/price.ts +63 -0
  309. package/themes/film-reel/sample/style.json +103 -0
  310. package/themes/film-reel/slots.ts +75 -0
  311. package/themes/film-reel/still.png +0 -0
  312. package/themes/film-reel/style.json +103 -0
  313. package/themes/film-reel/theme.json +144 -0
  314. package/themes/film-reel/variants/chalk-amber.json +124 -0
  315. package/themes/film-reel/variants/chalk-pink.json +123 -0
  316. package/themes/film-reel/variants/cream-violet.json +121 -0
  317. package/themes/film-reel/variants/frost-blue.json +126 -0
  318. package/themes/film-reel/variants/frost-green.json +123 -0
  319. package/themes/film-reel/variants/frost-indigo.json +121 -0
  320. package/themes/film-reel/variants/frost-jade.json +120 -0
  321. package/themes/film-reel/variants/frost-plum.json +120 -0
  322. package/themes/film-reel/variants/frost-teal.json +93 -0
  323. package/themes/film-reel/variants/lilac-gold.json +120 -0
  324. package/themes/film-reel/variants/lilac-jade.json +123 -0
  325. package/themes/film-reel/variants/lilac-magenta.json +125 -0
  326. package/themes/film-reel/variants/lilac-violet.json +122 -0
  327. package/themes/film-reel/variants/sand-cyan.json +124 -0
  328. package/themes/film-reel/variants/sand-lime.json +96 -0
  329. package/themes/glass-light/THEME.md +55 -0
  330. package/themes/glass-light/effects.ts +433 -0
  331. package/themes/glass-light/sample/assets/og/logo.svg +12 -0
  332. package/themes/glass-light/sample/beats.json +1005 -0
  333. package/themes/glass-light/sample/index.html +11 -0
  334. package/themes/glass-light/sample/kf.json +59 -0
  335. package/themes/glass-light/sample/lib/facts.ts +29 -0
  336. package/themes/glass-light/sample/lib/glass.ts +81 -0
  337. package/themes/glass-light/sample/main.ts +9 -0
  338. package/themes/glass-light/sample/scenes/end.ts +43 -0
  339. package/themes/glass-light/sample/scenes/gather.ts +38 -0
  340. package/themes/glass-light/sample/scenes/models.ts +46 -0
  341. package/themes/glass-light/sample/scenes/price.ts +46 -0
  342. package/themes/glass-light/sample/style.json +94 -0
  343. package/themes/glass-light/slots.ts +198 -0
  344. package/themes/glass-light/still.png +0 -0
  345. package/themes/glass-light/style.json +94 -0
  346. package/themes/glass-light/theme.json +121 -0
  347. package/themes/glass-light/variants/blush-coral.json +116 -0
  348. package/themes/glass-light/variants/blush-orange.json +115 -0
  349. package/themes/glass-light/variants/blush-pink.json +119 -0
  350. package/themes/glass-light/variants/blush-plum.json +115 -0
  351. package/themes/glass-light/variants/blush-teal.json +115 -0
  352. package/themes/glass-light/variants/cream-blue.json +125 -0
  353. package/themes/glass-light/variants/cream-pink.json +87 -0
  354. package/themes/glass-light/variants/cream-violet.json +119 -0
  355. package/themes/glass-light/variants/frost-green.json +115 -0
  356. package/themes/glass-light/variants/frost-sky-suit.json +115 -0
  357. package/themes/glass-light/variants/frost-sky.json +121 -0
  358. package/themes/glass-light/variants/lilac-gold.json +126 -0
  359. package/themes/glass-light/variants/lilac-plum.json +114 -0
  360. package/themes/glass-light/variants/sage-green.json +119 -0
  361. package/themes/glass-light/variants/sage-rose.json +114 -0
  362. package/themes/ink-wash/THEME.md +59 -0
  363. package/themes/ink-wash/effects.ts +574 -0
  364. package/themes/ink-wash/sample/assets/og/logo.svg +12 -0
  365. package/themes/ink-wash/sample/beats.json +1005 -0
  366. package/themes/ink-wash/sample/index.html +11 -0
  367. package/themes/ink-wash/sample/kf.json +59 -0
  368. package/themes/ink-wash/sample/lib/facts.ts +29 -0
  369. package/themes/ink-wash/sample/lib/ink.ts +35 -0
  370. package/themes/ink-wash/sample/main.ts +9 -0
  371. package/themes/ink-wash/sample/scenes/end.ts +72 -0
  372. package/themes/ink-wash/sample/scenes/gather.ts +53 -0
  373. package/themes/ink-wash/sample/scenes/models.ts +58 -0
  374. package/themes/ink-wash/sample/scenes/price.ts +85 -0
  375. package/themes/ink-wash/sample/style.json +108 -0
  376. package/themes/ink-wash/slots.ts +150 -0
  377. package/themes/ink-wash/still.png +0 -0
  378. package/themes/ink-wash/style.json +108 -0
  379. package/themes/ink-wash/theme.json +133 -0
  380. package/themes/ink-wash/variants/blush-orange.json +125 -0
  381. package/themes/ink-wash/variants/blush-rose.json +124 -0
  382. package/themes/ink-wash/variants/chalk-coral-grain.json +125 -0
  383. package/themes/ink-wash/variants/chalk-coral-serif.json +118 -0
  384. package/themes/ink-wash/variants/chalk-coral.json +120 -0
  385. package/themes/ink-wash/variants/chalk-orange-grain.json +97 -0
  386. package/themes/ink-wash/variants/chalk-orange-serif.json +120 -0
  387. package/themes/ink-wash/variants/chalk-orange.json +120 -0
  388. package/themes/ink-wash/variants/frost-coral.json +119 -0
  389. package/themes/ink-wash/variants/frost-rose.json +91 -0
  390. package/themes/ink-wash/variants/lilac-coral.json +96 -0
  391. package/themes/ink-wash/variants/sage-coral.json +119 -0
  392. package/themes/ink-wash/variants/sage-rose.json +119 -0
  393. package/themes/ink-wash/variants/sand-coral.json +125 -0
  394. package/themes/ink-wash/variants/sand-orange.json +120 -0
  395. package/themes/iso-diorama/THEME.md +54 -0
  396. package/themes/iso-diorama/effects.ts +374 -0
  397. package/themes/iso-diorama/sample/assets/og/logo.svg +12 -0
  398. package/themes/iso-diorama/sample/beats.json +1005 -0
  399. package/themes/iso-diorama/sample/index.html +11 -0
  400. package/themes/iso-diorama/sample/kf.json +59 -0
  401. package/themes/iso-diorama/sample/lib/facts.ts +29 -0
  402. package/themes/iso-diorama/sample/lib/iso.ts +22 -0
  403. package/themes/iso-diorama/sample/main.ts +9 -0
  404. package/themes/iso-diorama/sample/scenes/end.ts +41 -0
  405. package/themes/iso-diorama/sample/scenes/gather.ts +39 -0
  406. package/themes/iso-diorama/sample/scenes/models.ts +55 -0
  407. package/themes/iso-diorama/sample/scenes/price.ts +49 -0
  408. package/themes/iso-diorama/sample/style.json +98 -0
  409. package/themes/iso-diorama/slots.ts +222 -0
  410. package/themes/iso-diorama/still.png +0 -0
  411. package/themes/iso-diorama/style.json +98 -0
  412. package/themes/iso-diorama/theme.json +133 -0
  413. package/themes/iso-diorama/variants/chalk-plum.json +121 -0
  414. package/themes/iso-diorama/variants/cocoa-gold.json +93 -0
  415. package/themes/iso-diorama/variants/cocoa-indigo.json +122 -0
  416. package/themes/iso-diorama/variants/cocoa-rose.json +125 -0
  417. package/themes/iso-diorama/variants/deep-green.json +125 -0
  418. package/themes/iso-diorama/variants/deep-plum.json +120 -0
  419. package/themes/iso-diorama/variants/dusk-blue.json +126 -0
  420. package/themes/iso-diorama/variants/dusk-coral.json +122 -0
  421. package/themes/iso-diorama/variants/dusk-jade.json +121 -0
  422. package/themes/iso-diorama/variants/forest-cyan.json +127 -0
  423. package/themes/iso-diorama/variants/frost-blue.json +126 -0
  424. package/themes/iso-diorama/variants/frost-green.json +126 -0
  425. package/themes/iso-diorama/variants/frost-orange.json +125 -0
  426. package/themes/iso-diorama/variants/frost-teal.json +123 -0
  427. package/themes/iso-diorama/variants/navy-amber.json +125 -0
  428. package/themes/isotype/THEME.md +58 -0
  429. package/themes/isotype/effects.ts +297 -0
  430. package/themes/isotype/kit.ts +102 -0
  431. package/themes/isotype/sample/assets/og/logo.svg +12 -0
  432. package/themes/isotype/sample/beats.json +1005 -0
  433. package/themes/isotype/sample/index.html +11 -0
  434. package/themes/isotype/sample/kf.json +59 -0
  435. package/themes/isotype/sample/lib/chart.ts +47 -0
  436. package/themes/isotype/sample/lib/facts.ts +29 -0
  437. package/themes/isotype/sample/main.ts +9 -0
  438. package/themes/isotype/sample/scenes/end.ts +80 -0
  439. package/themes/isotype/sample/scenes/gather.ts +65 -0
  440. package/themes/isotype/sample/scenes/models.ts +75 -0
  441. package/themes/isotype/sample/scenes/price.ts +90 -0
  442. package/themes/isotype/sample/style.json +101 -0
  443. package/themes/isotype/slots.ts +74 -0
  444. package/themes/isotype/still.png +0 -0
  445. package/themes/isotype/style.json +101 -0
  446. package/themes/isotype/theme.json +141 -0
  447. package/themes/isotype/variants/blush-rose.json +127 -0
  448. package/themes/isotype/variants/chalk-amber.json +123 -0
  449. package/themes/isotype/variants/chalk-coral-bold.json +118 -0
  450. package/themes/isotype/variants/chalk-coral.json +117 -0
  451. package/themes/isotype/variants/chalk-orange.json +128 -0
  452. package/themes/isotype/variants/frost-amber-plex.json +128 -0
  453. package/themes/isotype/variants/frost-amber.json +123 -0
  454. package/themes/isotype/variants/frost-coral-grain.json +95 -0
  455. package/themes/isotype/variants/frost-coral.json +123 -0
  456. package/themes/isotype/variants/frost-orange.json +123 -0
  457. package/themes/isotype/variants/lilac-rose.json +127 -0
  458. package/themes/isotype/variants/sage-coral.json +90 -0
  459. package/themes/isotype/variants/sand-amber.json +118 -0
  460. package/themes/isotype/variants/sand-orange.json +128 -0
  461. package/themes/kawaii-sticker/THEME.md +44 -0
  462. package/themes/kawaii-sticker/effects.ts +412 -0
  463. package/themes/kawaii-sticker/sample/assets/stickers/bolt.png +0 -0
  464. package/themes/kawaii-sticker/sample/assets/stickers/bubble.png +0 -0
  465. package/themes/kawaii-sticker/sample/assets/stickers/clock.png +0 -0
  466. package/themes/kawaii-sticker/sample/assets/stickers/coin.png +0 -0
  467. package/themes/kawaii-sticker/sample/assets/stickers/moon.png +0 -0
  468. package/themes/kawaii-sticker/sample/assets/stickers/og-logo.svg +12 -0
  469. package/themes/kawaii-sticker/sample/assets/stickers/server.png +0 -0
  470. package/themes/kawaii-sticker/sample/beats.json +1 -0
  471. package/themes/kawaii-sticker/sample/index.html +11 -0
  472. package/themes/kawaii-sticker/sample/kf.json +66 -0
  473. package/themes/kawaii-sticker/sample/lib/og.ts +54 -0
  474. package/themes/kawaii-sticker/sample/main.ts +9 -0
  475. package/themes/kawaii-sticker/sample/scenes/end.ts +37 -0
  476. package/themes/kawaii-sticker/sample/scenes/gather.ts +50 -0
  477. package/themes/kawaii-sticker/sample/scenes/models.ts +43 -0
  478. package/themes/kawaii-sticker/sample/scenes/one.ts +45 -0
  479. package/themes/kawaii-sticker/sample/scenes/price.ts +47 -0
  480. package/themes/kawaii-sticker/sample/style.json +99 -0
  481. package/themes/kawaii-sticker/slots.ts +95 -0
  482. package/themes/kawaii-sticker/still.png +0 -0
  483. package/themes/kawaii-sticker/style.json +99 -0
  484. package/themes/kawaii-sticker/theme.json +147 -0
  485. package/themes/kawaii-sticker/variants/blush-coral.json +134 -0
  486. package/themes/kawaii-sticker/variants/blush-teal.json +129 -0
  487. package/themes/kawaii-sticker/variants/blush-violet.json +134 -0
  488. package/themes/kawaii-sticker/variants/cream-gold.json +135 -0
  489. package/themes/kawaii-sticker/variants/deep-jade.json +134 -0
  490. package/themes/kawaii-sticker/variants/dusk-green.json +134 -0
  491. package/themes/kawaii-sticker/variants/dusk-indigo.json +130 -0
  492. package/themes/kawaii-sticker/variants/dusk-sky.json +135 -0
  493. package/themes/kawaii-sticker/variants/dusk-teal.json +134 -0
  494. package/themes/kawaii-sticker/variants/frost-blue.json +135 -0
  495. package/themes/kawaii-sticker/variants/frost-plum.json +133 -0
  496. package/themes/kawaii-sticker/variants/lilac-violet.json +133 -0
  497. package/themes/kawaii-sticker/variants/navy-gold.json +134 -0
  498. package/themes/kawaii-sticker/variants/navy-plum.json +134 -0
  499. package/themes/kawaii-sticker/variants/sage-sky.json +107 -0
  500. package/themes/lab-notebook/THEME.md +56 -0
  501. package/themes/lab-notebook/effects.ts +423 -0
  502. package/themes/lab-notebook/kit.ts +84 -0
  503. package/themes/lab-notebook/sample/assets/og/logo.svg +12 -0
  504. package/themes/lab-notebook/sample/beats.json +1005 -0
  505. package/themes/lab-notebook/sample/index.html +11 -0
  506. package/themes/lab-notebook/sample/kf.json +59 -0
  507. package/themes/lab-notebook/sample/lib/facts.ts +29 -0
  508. package/themes/lab-notebook/sample/lib/note.ts +53 -0
  509. package/themes/lab-notebook/sample/main.ts +9 -0
  510. package/themes/lab-notebook/sample/scenes/end.ts +127 -0
  511. package/themes/lab-notebook/sample/scenes/gather.ts +83 -0
  512. package/themes/lab-notebook/sample/scenes/models.ts +73 -0
  513. package/themes/lab-notebook/sample/scenes/price.ts +89 -0
  514. package/themes/lab-notebook/sample/style.json +109 -0
  515. package/themes/lab-notebook/slots.ts +75 -0
  516. package/themes/lab-notebook/still.png +0 -0
  517. package/themes/lab-notebook/style.json +109 -0
  518. package/themes/lab-notebook/theme.json +142 -0
  519. package/themes/lab-notebook/variants/blush-orange.json +125 -0
  520. package/themes/lab-notebook/variants/chalk-coral.json +126 -0
  521. package/themes/lab-notebook/variants/chalk-orange.json +129 -0
  522. package/themes/lab-notebook/variants/chalk-rose-2.json +96 -0
  523. package/themes/lab-notebook/variants/chalk-rose.json +125 -0
  524. package/themes/lab-notebook/variants/frost-orange.json +101 -0
  525. package/themes/lab-notebook/variants/frost-rose-grain.json +101 -0
  526. package/themes/lab-notebook/variants/frost-rose.json +96 -0
  527. package/themes/lab-notebook/variants/lilac-rose-2.json +96 -0
  528. package/themes/lab-notebook/variants/lilac-rose.json +128 -0
  529. package/themes/lab-notebook/variants/sage-rose.json +124 -0
  530. package/themes/lab-notebook/variants/sand-orange-grain.json +101 -0
  531. package/themes/lab-notebook/variants/sand-orange.json +129 -0
  532. package/themes/lab-notebook/variants/snow-orange.json +129 -0
  533. package/themes/lab-notebook/variants/snow-rose.json +124 -0
  534. package/themes/manga-panel/THEME.md +60 -0
  535. package/themes/manga-panel/effects.ts +791 -0
  536. package/themes/manga-panel/sample/assets/og/logo.svg +12 -0
  537. package/themes/manga-panel/sample/beats.json +1005 -0
  538. package/themes/manga-panel/sample/index.html +11 -0
  539. package/themes/manga-panel/sample/kf.json +59 -0
  540. package/themes/manga-panel/sample/lib/facts.ts +29 -0
  541. package/themes/manga-panel/sample/lib/manga.ts +58 -0
  542. package/themes/manga-panel/sample/main.ts +9 -0
  543. package/themes/manga-panel/sample/scenes/end.ts +96 -0
  544. package/themes/manga-panel/sample/scenes/gather.ts +100 -0
  545. package/themes/manga-panel/sample/scenes/models.ts +96 -0
  546. package/themes/manga-panel/sample/scenes/price.ts +154 -0
  547. package/themes/manga-panel/sample/style.json +105 -0
  548. package/themes/manga-panel/slots.ts +127 -0
  549. package/themes/manga-panel/still.png +0 -0
  550. package/themes/manga-panel/style.json +105 -0
  551. package/themes/manga-panel/theme.json +150 -0
  552. package/themes/manga-panel/variants/chalk-cyan-dots.json +122 -0
  553. package/themes/manga-panel/variants/chalk-cyan.json +122 -0
  554. package/themes/manga-panel/variants/chalk-magenta.json +121 -0
  555. package/themes/manga-panel/variants/chalk-orange-bold.json +117 -0
  556. package/themes/manga-panel/variants/chalk-orange.json +122 -0
  557. package/themes/manga-panel/variants/chalk-rose-dots.json +121 -0
  558. package/themes/manga-panel/variants/chalk-rose.json +116 -0
  559. package/themes/manga-panel/variants/chalk-sky-bold.json +117 -0
  560. package/themes/manga-panel/variants/chalk-sky.json +117 -0
  561. package/themes/manga-panel/variants/snow-cyan.json +117 -0
  562. package/themes/manga-panel/variants/snow-magenta-dots.json +121 -0
  563. package/themes/manga-panel/variants/snow-magenta.json +116 -0
  564. package/themes/manga-panel/variants/snow-rose-dots.json +121 -0
  565. package/themes/manga-panel/variants/snow-rose.json +116 -0
  566. package/themes/manga-panel/variants/snow-sky.json +95 -0
  567. package/themes/marble-run/THEME.md +73 -0
  568. package/themes/marble-run/effects.ts +678 -0
  569. package/themes/marble-run/sample/assets/og/logo.svg +12 -0
  570. package/themes/marble-run/sample/beats.json +1005 -0
  571. package/themes/marble-run/sample/index.html +11 -0
  572. package/themes/marble-run/sample/kf.json +59 -0
  573. package/themes/marble-run/sample/lib/facts.ts +29 -0
  574. package/themes/marble-run/sample/lib/run.ts +30 -0
  575. package/themes/marble-run/sample/main.ts +9 -0
  576. package/themes/marble-run/sample/scenes/end.ts +58 -0
  577. package/themes/marble-run/sample/scenes/gather.ts +51 -0
  578. package/themes/marble-run/sample/scenes/models.ts +73 -0
  579. package/themes/marble-run/sample/scenes/price.ts +51 -0
  580. package/themes/marble-run/sample/style.json +109 -0
  581. package/themes/marble-run/slots.ts +116 -0
  582. package/themes/marble-run/still.png +0 -0
  583. package/themes/marble-run/style.json +109 -0
  584. package/themes/marble-run/theme.json +147 -0
  585. package/themes/marble-run/variants/cocoa-amber.json +128 -0
  586. package/themes/marble-run/variants/cocoa-orange.json +142 -0
  587. package/themes/marble-run/variants/dusk-orange.json +133 -0
  588. package/themes/marble-run/variants/forest-gold.json +128 -0
  589. package/themes/marble-run/variants/navy-gold.json +137 -0
  590. package/themes/marble-run/variants/night-gold-grain.json +105 -0
  591. package/themes/marble-run/variants/night-gold.json +137 -0
  592. package/themes/marble-run/variants/slate-gold-grain.json +133 -0
  593. package/themes/marble-run/variants/slate-gold.json +133 -0
  594. package/themes/marble-run/variants/slate-orange-grain.json +105 -0
  595. package/themes/marble-run/variants/slate-orange-mono.json +128 -0
  596. package/themes/marble-run/variants/slate-orange-serif.json +128 -0
  597. package/themes/marble-run/variants/slate-orange.json +131 -0
  598. package/themes/neon-sign/THEME.md +59 -0
  599. package/themes/neon-sign/effects.ts +424 -0
  600. package/themes/neon-sign/sample/assets/og/logo.svg +12 -0
  601. package/themes/neon-sign/sample/beats.json +1005 -0
  602. package/themes/neon-sign/sample/index.html +11 -0
  603. package/themes/neon-sign/sample/kf.json +59 -0
  604. package/themes/neon-sign/sample/lib/facts.ts +29 -0
  605. package/themes/neon-sign/sample/lib/neon.ts +50 -0
  606. package/themes/neon-sign/sample/main.ts +9 -0
  607. package/themes/neon-sign/sample/scenes/end.ts +62 -0
  608. package/themes/neon-sign/sample/scenes/gather.ts +59 -0
  609. package/themes/neon-sign/sample/scenes/models.ts +63 -0
  610. package/themes/neon-sign/sample/scenes/price.ts +74 -0
  611. package/themes/neon-sign/sample/style.json +104 -0
  612. package/themes/neon-sign/slots.ts +110 -0
  613. package/themes/neon-sign/still.png +0 -0
  614. package/themes/neon-sign/style.json +104 -0
  615. package/themes/neon-sign/theme.json +137 -0
  616. package/themes/neon-sign/variants/deep-plum.json +121 -0
  617. package/themes/neon-sign/variants/deep-violet.json +121 -0
  618. package/themes/neon-sign/variants/dusk-plum.json +121 -0
  619. package/themes/neon-sign/variants/forest-magenta.json +126 -0
  620. package/themes/neon-sign/variants/forest-plum.json +98 -0
  621. package/themes/neon-sign/variants/night-coral.json +122 -0
  622. package/themes/neon-sign/variants/night-magenta-round.json +121 -0
  623. package/themes/neon-sign/variants/night-magenta.json +126 -0
  624. package/themes/neon-sign/variants/night-pink.json +125 -0
  625. package/themes/neon-sign/variants/night-violet.json +126 -0
  626. package/themes/neon-sign/variants/slate-plum.json +120 -0
  627. package/themes/neon-sign/variants/slate-violet.json +127 -0
  628. package/themes/neon-sign/variants/wine-coral.json +127 -0
  629. package/themes/neon-sign/variants/wine-pink.json +125 -0
  630. package/themes/neon-sign/variants/wine-plum.json +126 -0
  631. package/themes/newspaper/THEME.md +67 -0
  632. package/themes/newspaper/effects.ts +347 -0
  633. package/themes/newspaper/sample/assets/og/logo.svg +12 -0
  634. package/themes/newspaper/sample/beats.json +1005 -0
  635. package/themes/newspaper/sample/index.html +11 -0
  636. package/themes/newspaper/sample/kf.json +59 -0
  637. package/themes/newspaper/sample/lib/facts.ts +29 -0
  638. package/themes/newspaper/sample/lib/page.ts +27 -0
  639. package/themes/newspaper/sample/main.ts +9 -0
  640. package/themes/newspaper/sample/scenes/end.ts +62 -0
  641. package/themes/newspaper/sample/scenes/gather.ts +66 -0
  642. package/themes/newspaper/sample/scenes/models.ts +61 -0
  643. package/themes/newspaper/sample/scenes/price.ts +103 -0
  644. package/themes/newspaper/sample/style.json +100 -0
  645. package/themes/newspaper/slots.ts +73 -0
  646. package/themes/newspaper/still.png +0 -0
  647. package/themes/newspaper/style.json +100 -0
  648. package/themes/newspaper/theme.json +141 -0
  649. package/themes/newspaper/variants/blush-amber.json +123 -0
  650. package/themes/newspaper/variants/blush-orange.json +125 -0
  651. package/themes/newspaper/variants/chalk-cyan.json +119 -0
  652. package/themes/newspaper/variants/chalk-indigo.json +124 -0
  653. package/themes/newspaper/variants/chalk-jade.json +95 -0
  654. package/themes/newspaper/variants/chalk-magenta.json +127 -0
  655. package/themes/newspaper/variants/frost-plum.json +123 -0
  656. package/themes/newspaper/variants/frost-sky.json +129 -0
  657. package/themes/newspaper/variants/frost-violet.json +96 -0
  658. package/themes/newspaper/variants/lilac-coral.json +124 -0
  659. package/themes/newspaper/variants/lilac-green.json +127 -0
  660. package/themes/newspaper/variants/sage-blue.json +124 -0
  661. package/themes/newspaper/variants/sage-lime.json +117 -0
  662. package/themes/newspaper/variants/sand-gold.json +124 -0
  663. package/themes/newspaper/variants/sand-jade.json +123 -0
  664. package/themes/og-measure/THEME.md +32 -6
  665. package/themes/og-measure/effects.ts +219 -115
  666. package/themes/og-measure/sample/assets/brand/og-logo.svg +11 -11
  667. package/themes/og-measure/sample/lib/data.ts +6 -0
  668. package/themes/og-measure/sample/scenes/end.ts +14 -10
  669. package/themes/og-measure/sample/scenes/gather.ts +12 -1
  670. package/themes/og-measure/sample/scenes/models.ts +13 -2
  671. package/themes/og-measure/sample/scenes/one.ts +8 -6
  672. package/themes/og-measure/sample/scenes/price.ts +20 -3
  673. package/themes/og-measure/sample/style.json +30 -35
  674. package/themes/og-measure/slots.ts +25 -30
  675. package/themes/og-measure/still.png +0 -0
  676. package/themes/og-measure/style.json +30 -35
  677. package/themes/og-measure/theme.json +91 -14
  678. package/themes/og-measure/variants/snow-blue.json +90 -0
  679. package/themes/orbit-system/THEME.md +77 -0
  680. package/themes/orbit-system/effects.ts +665 -0
  681. package/themes/orbit-system/sample/assets/og/logo.svg +12 -0
  682. package/themes/orbit-system/sample/beats.json +1005 -0
  683. package/themes/orbit-system/sample/index.html +11 -0
  684. package/themes/orbit-system/sample/kf.json +59 -0
  685. package/themes/orbit-system/sample/lib/facts.ts +29 -0
  686. package/themes/orbit-system/sample/lib/orbit.ts +84 -0
  687. package/themes/orbit-system/sample/main.ts +9 -0
  688. package/themes/orbit-system/sample/scenes/end.ts +50 -0
  689. package/themes/orbit-system/sample/scenes/gather.ts +35 -0
  690. package/themes/orbit-system/sample/scenes/models.ts +49 -0
  691. package/themes/orbit-system/sample/scenes/price.ts +57 -0
  692. package/themes/orbit-system/sample/style.json +108 -0
  693. package/themes/orbit-system/slots.ts +174 -0
  694. package/themes/orbit-system/still.png +0 -0
  695. package/themes/orbit-system/style.json +108 -0
  696. package/themes/orbit-system/theme.json +144 -0
  697. package/themes/orbit-system/variants/cocoa-amber.json +122 -0
  698. package/themes/orbit-system/variants/cocoa-coral.json +127 -0
  699. package/themes/orbit-system/variants/cocoa-cyan.json +127 -0
  700. package/themes/orbit-system/variants/deep-cyan.json +132 -0
  701. package/themes/orbit-system/variants/deep-sky.json +122 -0
  702. package/themes/orbit-system/variants/dusk-magenta.json +121 -0
  703. package/themes/orbit-system/variants/dusk-plum-pretendard.json +121 -0
  704. package/themes/orbit-system/variants/dusk-plum.json +127 -0
  705. package/themes/orbit-system/variants/dusk-violet.json +122 -0
  706. package/themes/orbit-system/variants/forest-coral.json +126 -0
  707. package/themes/orbit-system/variants/forest-plum.json +94 -0
  708. package/themes/orbit-system/variants/navy-amber.json +127 -0
  709. package/themes/orbit-system/variants/wine-amber.json +127 -0
  710. package/themes/orbit-system/variants/wine-coral.json +123 -0
  711. package/themes/orbit-system/variants/wine-magenta.json +126 -0
  712. package/themes/origami-fold/THEME.md +74 -0
  713. package/themes/origami-fold/effects.ts +535 -0
  714. package/themes/origami-fold/sample/assets/og/logo.svg +12 -0
  715. package/themes/origami-fold/sample/beats.json +1005 -0
  716. package/themes/origami-fold/sample/index.html +11 -0
  717. package/themes/origami-fold/sample/kf.json +59 -0
  718. package/themes/origami-fold/sample/lib/facts.ts +29 -0
  719. package/themes/origami-fold/sample/lib/fold.ts +53 -0
  720. package/themes/origami-fold/sample/main.ts +9 -0
  721. package/themes/origami-fold/sample/scenes/end.ts +51 -0
  722. package/themes/origami-fold/sample/scenes/gather.ts +37 -0
  723. package/themes/origami-fold/sample/scenes/models.ts +46 -0
  724. package/themes/origami-fold/sample/scenes/price.ts +54 -0
  725. package/themes/origami-fold/sample/style.json +108 -0
  726. package/themes/origami-fold/slots.ts +176 -0
  727. package/themes/origami-fold/still.png +0 -0
  728. package/themes/origami-fold/style.json +108 -0
  729. package/themes/origami-fold/theme.json +125 -0
  730. package/themes/origami-fold/variants/deep-amber-sunflower.json +122 -0
  731. package/themes/origami-fold/variants/deep-amber.json +122 -0
  732. package/themes/origami-fold/variants/deep-orange.json +128 -0
  733. package/themes/origami-fold/variants/forest-coral.json +127 -0
  734. package/themes/origami-fold/variants/forest-pink.json +123 -0
  735. package/themes/origami-fold/variants/forest-rose.json +100 -0
  736. package/themes/origami-fold/variants/frost-amber-grain.json +127 -0
  737. package/themes/origami-fold/variants/frost-amber-paper.json +128 -0
  738. package/themes/origami-fold/variants/frost-amber.json +95 -0
  739. package/themes/origami-fold/variants/sage-coral-grain.json +100 -0
  740. package/themes/origami-fold/variants/sage-coral-sunflower.json +122 -0
  741. package/themes/origami-fold/variants/sage-coral.json +128 -0
  742. package/themes/origami-fold/variants/sage-pink-grain.json +127 -0
  743. package/themes/origami-fold/variants/sage-pink-round.json +124 -0
  744. package/themes/origami-fold/variants/sage-pink.json +127 -0
  745. package/themes/paper-cutout/THEME.md +63 -0
  746. package/themes/paper-cutout/effects.ts +609 -0
  747. package/themes/paper-cutout/sample/assets/og/logo.svg +12 -0
  748. package/themes/paper-cutout/sample/beats.json +1005 -0
  749. package/themes/paper-cutout/sample/index.html +11 -0
  750. package/themes/paper-cutout/sample/kf.json +59 -0
  751. package/themes/paper-cutout/sample/lib/facts.ts +29 -0
  752. package/themes/paper-cutout/sample/lib/paper.ts +91 -0
  753. package/themes/paper-cutout/sample/main.ts +9 -0
  754. package/themes/paper-cutout/sample/scenes/end.ts +54 -0
  755. package/themes/paper-cutout/sample/scenes/gather.ts +63 -0
  756. package/themes/paper-cutout/sample/scenes/models.ts +93 -0
  757. package/themes/paper-cutout/sample/scenes/price.ts +100 -0
  758. package/themes/paper-cutout/sample/style.json +104 -0
  759. package/themes/paper-cutout/slots.ts +87 -0
  760. package/themes/paper-cutout/still.png +0 -0
  761. package/themes/paper-cutout/style.json +104 -0
  762. package/themes/paper-cutout/theme.json +146 -0
  763. package/themes/paper-cutout/variants/blush-coral.json +122 -0
  764. package/themes/paper-cutout/variants/blush-violet.json +122 -0
  765. package/themes/paper-cutout/variants/chalk-teal.json +122 -0
  766. package/themes/paper-cutout/variants/cream-gold.json +122 -0
  767. package/themes/paper-cutout/variants/frost-blue.json +123 -0
  768. package/themes/paper-cutout/variants/frost-lime.json +121 -0
  769. package/themes/paper-cutout/variants/frost-plum.json +122 -0
  770. package/themes/paper-cutout/variants/lilac-blue.json +123 -0
  771. package/themes/paper-cutout/variants/lilac-gold.json +122 -0
  772. package/themes/paper-cutout/variants/sage-cyan.json +122 -0
  773. package/themes/paper-cutout/variants/sage-green.json +122 -0
  774. package/themes/paper-cutout/variants/sage-pink.json +122 -0
  775. package/themes/paper-cutout/variants/sand-blue.json +123 -0
  776. package/themes/paper-cutout/variants/sand-green.json +121 -0
  777. package/themes/paper-cutout/variants/sand-plum.json +120 -0
  778. package/themes/pixel-quest/THEME.md +57 -0
  779. package/themes/pixel-quest/effects.ts +491 -0
  780. package/themes/pixel-quest/kit.ts +232 -0
  781. package/themes/pixel-quest/sample/assets/og/logo.svg +12 -0
  782. package/themes/pixel-quest/sample/beats.json +1005 -0
  783. package/themes/pixel-quest/sample/index.html +11 -0
  784. package/themes/pixel-quest/sample/kf.json +59 -0
  785. package/themes/pixel-quest/sample/lib/facts.ts +29 -0
  786. package/themes/pixel-quest/sample/lib/game.ts +71 -0
  787. package/themes/pixel-quest/sample/lib/logo.ts +51 -0
  788. package/themes/pixel-quest/sample/main.ts +9 -0
  789. package/themes/pixel-quest/sample/scenes/end.ts +75 -0
  790. package/themes/pixel-quest/sample/scenes/gather.ts +65 -0
  791. package/themes/pixel-quest/sample/scenes/models.ts +104 -0
  792. package/themes/pixel-quest/sample/scenes/price.ts +118 -0
  793. package/themes/pixel-quest/sample/style.json +115 -0
  794. package/themes/pixel-quest/slots.ts +94 -0
  795. package/themes/pixel-quest/still.png +0 -0
  796. package/themes/pixel-quest/style.json +115 -0
  797. package/themes/pixel-quest/theme.json +144 -0
  798. package/themes/pixel-quest/variants/navy-gold-2.json +98 -0
  799. package/themes/pixel-quest/variants/navy-gold-3.json +127 -0
  800. package/themes/pixel-quest/variants/navy-gold-4.json +95 -0
  801. package/themes/pixel-quest/variants/navy-gold-pixel.json +132 -0
  802. package/themes/pixel-quest/variants/navy-gold-scan.json +99 -0
  803. package/themes/pixel-quest/variants/navy-gold.json +131 -0
  804. package/themes/pixel-quest/variants/navy-lime-2.json +93 -0
  805. package/themes/pixel-quest/variants/navy-lime-3.json +124 -0
  806. package/themes/pixel-quest/variants/navy-lime-pixel.json +126 -0
  807. package/themes/pixel-quest/variants/navy-lime-scan.json +97 -0
  808. package/themes/pixel-quest/variants/navy-lime.json +130 -0
  809. package/themes/receipt/THEME.md +72 -0
  810. package/themes/receipt/effects.ts +257 -0
  811. package/themes/receipt/sample/assets/og/logo.svg +12 -0
  812. package/themes/receipt/sample/beats.json +1005 -0
  813. package/themes/receipt/sample/index.html +11 -0
  814. package/themes/receipt/sample/kf.json +59 -0
  815. package/themes/receipt/sample/lib/facts.ts +29 -0
  816. package/themes/receipt/sample/lib/sheet.ts +52 -0
  817. package/themes/receipt/sample/main.ts +9 -0
  818. package/themes/receipt/sample/scenes/end.ts +44 -0
  819. package/themes/receipt/sample/scenes/gather.ts +57 -0
  820. package/themes/receipt/sample/scenes/models.ts +48 -0
  821. package/themes/receipt/sample/scenes/price.ts +64 -0
  822. package/themes/receipt/sample/style.json +104 -0
  823. package/themes/receipt/slots.ts +89 -0
  824. package/themes/receipt/still.png +0 -0
  825. package/themes/receipt/style.json +104 -0
  826. package/themes/receipt/theme.json +133 -0
  827. package/themes/receipt/variants/blush-coral.json +89 -0
  828. package/themes/receipt/variants/sand-coral-2.json +89 -0
  829. package/themes/receipt/variants/sand-coral-3.json +89 -0
  830. package/themes/receipt/variants/sand-coral-4.json +90 -0
  831. package/themes/receipt/variants/sand-coral-5.json +89 -0
  832. package/themes/receipt/variants/sand-coral-6.json +88 -0
  833. package/themes/receipt/variants/sand-coral-7.json +88 -0
  834. package/themes/receipt/variants/sand-coral-8.json +89 -0
  835. package/themes/receipt/variants/sand-coral-9.json +89 -0
  836. package/themes/receipt/variants/sand-coral.json +88 -0
  837. package/themes/receipt/variants/sand-orange-2.json +89 -0
  838. package/themes/receipt/variants/sand-orange-3.json +90 -0
  839. package/themes/receipt/variants/sand-orange-4.json +89 -0
  840. package/themes/receipt/variants/sand-orange-5.json +89 -0
  841. package/themes/receipt/variants/sand-orange.json +89 -0
  842. package/themes/riso-zine/sample/style.json +2 -2
  843. package/themes/riso-zine/style.json +2 -2
  844. package/themes/riso-zine/theme.json +68 -0
  845. package/themes/riso-zine/variants/blush-coral.json +120 -0
  846. package/themes/riso-zine/variants/blush-gold.json +120 -0
  847. package/themes/riso-zine/variants/blush-pink.json +115 -0
  848. package/themes/riso-zine/variants/chalk-cyan.json +120 -0
  849. package/themes/riso-zine/variants/chalk-lime.json +119 -0
  850. package/themes/riso-zine/variants/cream-amber.json +89 -0
  851. package/themes/riso-zine/variants/frost-blue.json +119 -0
  852. package/themes/riso-zine/variants/frost-coral.json +118 -0
  853. package/themes/riso-zine/variants/frost-cyan.json +120 -0
  854. package/themes/riso-zine/variants/frost-green.json +120 -0
  855. package/themes/riso-zine/variants/lilac-plum.json +118 -0
  856. package/themes/riso-zine/variants/lilac-violet.json +123 -0
  857. package/themes/riso-zine/variants/sage-green.json +119 -0
  858. package/themes/riso-zine/variants/sand-jade.json +120 -0
  859. package/themes/riso-zine/variants/sand-plum.json +113 -0
  860. package/themes/server-hall/THEME.md +58 -0
  861. package/themes/server-hall/effects.ts +455 -0
  862. package/themes/server-hall/kit.ts +138 -0
  863. package/themes/server-hall/sample/assets/og/logo.svg +12 -0
  864. package/themes/server-hall/sample/beats.json +1005 -0
  865. package/themes/server-hall/sample/index.html +11 -0
  866. package/themes/server-hall/sample/kf.json +59 -0
  867. package/themes/server-hall/sample/lib/facts.ts +29 -0
  868. package/themes/server-hall/sample/lib/hall.ts +81 -0
  869. package/themes/server-hall/sample/main.ts +9 -0
  870. package/themes/server-hall/sample/scenes/end.ts +57 -0
  871. package/themes/server-hall/sample/scenes/gather.ts +38 -0
  872. package/themes/server-hall/sample/scenes/models.ts +49 -0
  873. package/themes/server-hall/sample/scenes/price.ts +65 -0
  874. package/themes/server-hall/sample/style.json +107 -0
  875. package/themes/server-hall/slots.ts +106 -0
  876. package/themes/server-hall/still.png +0 -0
  877. package/themes/server-hall/style.json +107 -0
  878. package/themes/server-hall/theme.json +145 -0
  879. package/themes/server-hall/variants/navy-indigo.json +140 -0
  880. package/themes/server-hall/variants/night-indigo.json +120 -0
  881. package/themes/server-hall/variants/wine-plum.json +130 -0
  882. package/themes/server-hall/variants/wine-violet.json +103 -0
  883. package/themes/subway-map/THEME.md +64 -0
  884. package/themes/subway-map/effects.ts +662 -0
  885. package/themes/subway-map/sample/assets/og/logo.svg +12 -0
  886. package/themes/subway-map/sample/beats.json +1005 -0
  887. package/themes/subway-map/sample/index.html +11 -0
  888. package/themes/subway-map/sample/kf.json +59 -0
  889. package/themes/subway-map/sample/lib/facts.ts +29 -0
  890. package/themes/subway-map/sample/lib/map.ts +58 -0
  891. package/themes/subway-map/sample/main.ts +9 -0
  892. package/themes/subway-map/sample/scenes/end.ts +94 -0
  893. package/themes/subway-map/sample/scenes/gather.ts +64 -0
  894. package/themes/subway-map/sample/scenes/models.ts +117 -0
  895. package/themes/subway-map/sample/scenes/price.ts +119 -0
  896. package/themes/subway-map/sample/style.json +108 -0
  897. package/themes/subway-map/slots.ts +66 -0
  898. package/themes/subway-map/still.png +0 -0
  899. package/themes/subway-map/style.json +108 -0
  900. package/themes/subway-map/theme.json +163 -0
  901. package/themes/subway-map/variants/blush-jade.json +131 -0
  902. package/themes/subway-map/variants/chalk-jade.json +141 -0
  903. package/themes/subway-map/variants/deep-green.json +131 -0
  904. package/themes/subway-map/variants/deep-teal.json +132 -0
  905. package/themes/subway-map/variants/dusk-teal-bold.json +132 -0
  906. package/themes/subway-map/variants/dusk-teal.json +105 -0
  907. package/themes/subway-map/variants/forest-green.json +141 -0
  908. package/themes/subway-map/variants/forest-jade.json +131 -0
  909. package/themes/subway-map/variants/frost-jade.json +131 -0
  910. package/themes/subway-map/variants/frost-teal.json +137 -0
  911. package/themes/subway-map/variants/sage-teal.json +132 -0
  912. package/themes/subway-map/variants/slate-green.json +136 -0
  913. package/themes/subway-map/variants/slate-jade.json +131 -0
  914. package/themes/subway-map/variants/snow-jade.json +136 -0
  915. package/themes/subway-map/variants/wine-green.json +104 -0
  916. package/themes/swiss-poster/THEME.md +59 -0
  917. package/themes/swiss-poster/effects.ts +339 -0
  918. package/themes/swiss-poster/grid.ts +35 -0
  919. package/themes/swiss-poster/sample/assets/og/logo.svg +12 -0
  920. package/themes/swiss-poster/sample/beats.json +1005 -0
  921. package/themes/swiss-poster/sample/index.html +11 -0
  922. package/themes/swiss-poster/sample/kf.json +59 -0
  923. package/themes/swiss-poster/sample/lib/facts.ts +29 -0
  924. package/themes/swiss-poster/sample/lib/poster.ts +36 -0
  925. package/themes/swiss-poster/sample/main.ts +9 -0
  926. package/themes/swiss-poster/sample/scenes/end.ts +70 -0
  927. package/themes/swiss-poster/sample/scenes/gather.ts +68 -0
  928. package/themes/swiss-poster/sample/scenes/models.ts +63 -0
  929. package/themes/swiss-poster/sample/scenes/price.ts +74 -0
  930. package/themes/swiss-poster/sample/style.json +100 -0
  931. package/themes/swiss-poster/slots.ts +69 -0
  932. package/themes/swiss-poster/still.png +0 -0
  933. package/themes/swiss-poster/style.json +100 -0
  934. package/themes/swiss-poster/theme.json +133 -0
  935. package/themes/swiss-poster/variants/blush-green.json +116 -0
  936. package/themes/swiss-poster/variants/chalk-plum.json +121 -0
  937. package/themes/swiss-poster/variants/chalk-sky.json +90 -0
  938. package/themes/swiss-poster/variants/cocoa-cyan.json +117 -0
  939. package/themes/swiss-poster/variants/dusk-coral.json +89 -0
  940. package/themes/swiss-poster/variants/dusk-magenta.json +117 -0
  941. package/themes/swiss-poster/variants/forest-amber.json +127 -0
  942. package/themes/swiss-poster/variants/forest-blue.json +118 -0
  943. package/themes/swiss-poster/variants/forest-jade.json +89 -0
  944. package/themes/swiss-poster/variants/frost-gold.json +128 -0
  945. package/themes/swiss-poster/variants/frost-indigo.json +117 -0
  946. package/themes/swiss-poster/variants/sand-magenta.json +126 -0
  947. package/themes/swiss-poster/variants/slate-orange.json +122 -0
  948. package/themes/swiss-poster/variants/slate-pink.json +126 -0
  949. package/themes/swiss-poster/variants/slate-violet.json +89 -0
  950. package/themes/water-works/THEME.md +61 -0
  951. package/themes/water-works/effects.ts +609 -0
  952. package/themes/water-works/sample/assets/og/logo.svg +12 -0
  953. package/themes/water-works/sample/beats.json +1005 -0
  954. package/themes/water-works/sample/index.html +11 -0
  955. package/themes/water-works/sample/kf.json +59 -0
  956. package/themes/water-works/sample/lib/facts.ts +29 -0
  957. package/themes/water-works/sample/lib/hall.ts +22 -0
  958. package/themes/water-works/sample/main.ts +9 -0
  959. package/themes/water-works/sample/scenes/end.ts +55 -0
  960. package/themes/water-works/sample/scenes/gather.ts +42 -0
  961. package/themes/water-works/sample/scenes/models.ts +51 -0
  962. package/themes/water-works/sample/scenes/price.ts +66 -0
  963. package/themes/water-works/sample/style.json +105 -0
  964. package/themes/water-works/slots.ts +140 -0
  965. package/themes/water-works/still.png +0 -0
  966. package/themes/water-works/style.json +105 -0
  967. package/themes/water-works/theme.json +140 -0
  968. package/themes/water-works/variants/blush-rose.json +123 -0
  969. package/themes/water-works/variants/chalk-blue.json +124 -0
  970. package/themes/water-works/variants/chalk-cyan-2.json +96 -0
  971. package/themes/water-works/variants/chalk-cyan.json +123 -0
  972. package/themes/water-works/variants/chalk-gold-mono.json +122 -0
  973. package/themes/water-works/variants/chalk-gold.json +123 -0
  974. package/themes/water-works/variants/chalk-green.json +123 -0
  975. package/themes/water-works/variants/frost-indigo.json +123 -0
  976. package/themes/water-works/variants/frost-rose.json +132 -0
  977. package/themes/water-works/variants/lilac-violet-mono.json +124 -0
  978. package/themes/water-works/variants/lilac-violet.json +133 -0
  979. package/themes/water-works/variants/sage-amber.json +133 -0
  980. package/themes/water-works/variants/sage-green.json +133 -0
  981. package/themes/water-works/variants/sand-amber.json +123 -0
  982. package/themes/water-works/variants/sand-plum.json +121 -0
  983. package/themes/whiteboard/THEME.md +78 -0
  984. package/themes/whiteboard/effects.ts +561 -0
  985. package/themes/whiteboard/sample/assets/og/logo.svg +12 -0
  986. package/themes/whiteboard/sample/beats.json +1005 -0
  987. package/themes/whiteboard/sample/index.html +11 -0
  988. package/themes/whiteboard/sample/kf.json +59 -0
  989. package/themes/whiteboard/sample/lib/board.ts +93 -0
  990. package/themes/whiteboard/sample/lib/facts.ts +29 -0
  991. package/themes/whiteboard/sample/main.ts +9 -0
  992. package/themes/whiteboard/sample/scenes/end.ts +59 -0
  993. package/themes/whiteboard/sample/scenes/gather.ts +50 -0
  994. package/themes/whiteboard/sample/scenes/models.ts +56 -0
  995. package/themes/whiteboard/sample/scenes/price.ts +79 -0
  996. package/themes/whiteboard/sample/style.json +106 -0
  997. package/themes/whiteboard/slots.ts +152 -0
  998. package/themes/whiteboard/still.png +0 -0
  999. package/themes/whiteboard/style.json +106 -0
  1000. package/themes/whiteboard/theme.json +145 -0
  1001. package/themes/whiteboard/variants/chalk-coral-do.json +126 -0
  1002. package/themes/whiteboard/variants/chalk-coral.json +132 -0
  1003. package/themes/whiteboard/variants/cream-lime.json +131 -0
  1004. package/themes/whiteboard/variants/cream-plum.json +103 -0
  1005. package/themes/whiteboard/variants/frost-teal-do.json +127 -0
  1006. package/themes/whiteboard/variants/frost-teal.json +127 -0
  1007. package/themes/whiteboard/variants/lilac-indigo.json +132 -0
  1008. package/themes/whiteboard/variants/lilac-jade.json +103 -0
  1009. package/themes/whiteboard/variants/sage-green.json +130 -0
  1010. package/themes/whiteboard/variants/sage-plum.json +126 -0
  1011. package/themes/whiteboard/variants/snow-amber.json +99 -0
  1012. package/themes/whiteboard/variants/snow-cyan.json +132 -0
  1013. package/themes/whiteboard/variants/snow-green.json +126 -0
  1014. package/themes/whiteboard/variants/snow-magenta.json +126 -0
  1015. package/themes/whiteboard/variants/snow-plum.json +130 -0
  1016. /package/themes/{og-measure/sample/assets/brand/og-logo-full.svg → blueprint/sample/assets/og/logo.svg} +0 -0
@@ -0,0 +1,227 @@
1
+ // 테마 견본 칸 — 같은 문장 한 장면(쇼츠 첫 장면 hook-number)을 테마·변주마다 찍은 한 장. kf theme sheet·vary 와 kf make 테마 질문이 같이 쓴다.
2
+ // 변주는 세계 기본 판 표준 장면을 한 번 지어 두고 style.json 만 갈아 찍는다 — 감독이 고른 장면 문법이 같아야 겉모습만 견줄 수 있다.
3
+ import { spawnSync } from "node:child_process";
4
+ import { createHash } from "node:crypto";
5
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
6
+ import { dirname, join } from "node:path";
7
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
+ import type { KfStyle } from "@kasaframe/core";
9
+ import { cellPath, loadTheme, themeDims, themesDir, type Theme } from "@kasaframe/themes";
10
+ import { launch } from "./browser.ts";
11
+
12
+ const kfBin = new URL("./kf.ts", import.meta.url).pathname;
13
+ const kf = (...a: string[]) => spawnSync(process.execPath, [kfBin, ...a], { encoding: "utf8" });
14
+ const tail = (r: { stdout?: string; stderr?: string }, n = 3) => `${r.stderr ?? ""}${r.stdout ?? ""}`.trim().split("\n").slice(-n).join(" / ");
15
+
16
+ export const SAMPLE = {
17
+ title: "kasaframe",
18
+ request: "테마 견본 — 같은 문장을 테마마다",
19
+ scenes: [{ id: "hook", type: "hook-number", value: 57, unit: "×", label: "KV 캐시가 이만큼 작아진다", source: "DeepSeek-V2 기술 보고서", dur: 4 }],
20
+ };
21
+
22
+ export interface Frame {
23
+ width: number;
24
+ height: number;
25
+ safe: { top: number; bottom: number; left: number; right: number };
26
+ /** 장면 끝 프레임 — 움직임이 다 앉은 자리 */
27
+ at: number;
28
+ dur: number;
29
+ pattern?: string;
30
+ }
31
+
32
+ const readJson = (p: string) => JSON.parse(readFileSync(p, "utf8"));
33
+
34
+ function frameOf(dir: string): Frame {
35
+ const p = readJson(join(dir, "kf.json"));
36
+ const scene = p.scenes.find((x: { id: string }) => x.id === SAMPLE.scenes[0].id);
37
+ const d = existsSync(join(dir, "director.json")) ? readJson(join(dir, "director.json")) : null;
38
+ return { width: p.width, height: p.height, safe: p.safeArea, at: +(scene.from + scene.dur - 1 / p.fps).toFixed(4), dur: scene.dur, pattern: d?.scenes?.find((s: { id: string }) => s.id === scene.id)?.pattern };
39
+ }
40
+
41
+ /** 표준 장면 프로젝트 — 감독이 짓고, check 면 검사 고리까지(떨어진 패턴은 감독이 다음 후보로). 1 = 다시 지어도 검사 오류가 남음 */
42
+ export function standardProject(theme: string, dir: string, o: { check: boolean }): { status: number; why: string; frame: Frame | null } {
43
+ rmSync(dir, { recursive: true, force: true });
44
+ let r = kf("new", dir, "--template", "shorts", "--theme", theme, "--title", SAMPLE.title, "--series", "none");
45
+ if (r.status === 0) {
46
+ writeFileSync(join(dir, "content.json"), `${JSON.stringify(SAMPLE, null, 2)}\n`);
47
+ r = kf("direct", dir, "--no-narrate", "--no-lock", ...(o.check ? [] : ["--no-check"]));
48
+ }
49
+ const built = r.status === 0 || r.status === 1;
50
+ return { status: r.status ?? 1, why: r.status === 0 ? "" : tail(r), frame: built && existsSync(join(dir, "director.json")) ? frameOf(dir) : null };
51
+ }
52
+
53
+ /** 지어 둔 표준 장면에 테마(변주) style 만 갈아 끼운 복사본 — 장면 파일·패턴은 그대로 */
54
+ export function restyle(from: string, dir: string, id: string, style: KfStyle = loadTheme(id).style): void {
55
+ rmSync(dir, { recursive: true, force: true });
56
+ cpSync(from, dir, { recursive: true, filter: (src) => !src.startsWith(join(from, "out")) });
57
+ const was = readJson(join(from, "style.json"));
58
+ style = structuredClone(style);
59
+ // 틀의 움직임 규칙은 kf new 가 덮은 그대로 — 변주가 바꾸는 건 빠르기(durations)뿐
60
+ style.motion = { ...was.motion, ...(style.motion.durations ? { durations: style.motion.durations } : {}) };
61
+ writeFileSync(join(dir, "style.json"), `${JSON.stringify(style, null, 2)}\n`);
62
+ const p = readJson(join(dir, "kf.json"));
63
+ writeFileSync(join(dir, "kf.json"), `${JSON.stringify({ ...p, theme: id }, null, 2)}\n`);
64
+ }
65
+
66
+ export interface Verdict {
67
+ ok: boolean;
68
+ /** 오류 규칙·한 줄 */
69
+ errors: string[];
70
+ ran: boolean;
71
+ }
72
+
73
+ /** kf check — 잠금은 부르는 쪽이 쥔다. from·to 를 주면 그 구간만(입체 세계는 무거워 끝 구간만) */
74
+ export function checkProject(dir: string, win?: { from: number; to: number }): Verdict {
75
+ const file = join(dir, "out", "check.json");
76
+ rmSync(file, { force: true });
77
+ const r = kf("check", dir, "--no-lock", "--tabs", "2", ...(win ? ["--from", String(win.from), "--to", String(win.to)] : []));
78
+ if (!existsSync(file)) return { ok: false, ran: false, errors: [`kf check 를 못 돌렸다(종료 ${r.status}) — ${tail(r)}`] };
79
+ const rep = readJson(file);
80
+ const errors = (rep.findings ?? []).filter((f: { severity: string }) => f.severity === "error").map((f: { rule: string; message: string }) => `${f.rule}: ${f.message}`);
81
+ return { ok: r.status === 0 && !errors.length, ran: true, errors };
82
+ }
83
+
84
+ export function still(dir: string, at: number, out: string): string | null {
85
+ mkdirSync(dirname(out), { recursive: true });
86
+ const r = kf("still", dir, "--t", String(at), "--out", out);
87
+ return r.status === 0 ? null : tail(r);
88
+ }
89
+
90
+ /** 칸 그림을 36×64 로 줄인 RGB — 판끼리 얼마나 다른지 잰다 */
91
+ export function thumb(png: string): Uint8Array {
92
+ const r = spawnSync("ffmpeg", ["-v", "error", "-i", png, "-vf", "scale=36:64:flags=area", "-f", "rawvideo", "-pix_fmt", "rgb24", "-"], { maxBuffer: 1 << 20 });
93
+ return new Uint8Array(r.stdout ?? []);
94
+ }
95
+
96
+ /** 0..1 — 평균 화소 차. 0.04 아래면 사람 눈에 같은 판 */
97
+ export function imageDiff(a: Uint8Array, b: Uint8Array): number {
98
+ if (!a.length || a.length !== b.length) return 1;
99
+ let s = 0;
100
+ for (let i = 0; i < a.length; i++) s += Math.abs(a[i] - b[i]);
101
+ return s / a.length / 255;
102
+ }
103
+
104
+ // 칸 캐시 열쇠 — 겉모습(style)·견본 내용·세계 코드·견본 장면 문법(hook-number 패턴과 그 도구)이 같으면 같은 칸
105
+ const patternsDir = fileURLToPath(new URL("../../patterns/src/", import.meta.url));
106
+ const SAMPLE_CODE = [join(patternsDir, "kit.ts"), ...readdirSync(join(patternsDir, "hook-number")).sort().map((f) => join(patternsDir, "hook-number", f))];
107
+
108
+ export function cellKey(t: Theme): string {
109
+ const h = createHash("sha256");
110
+ h.update(JSON.stringify(t.style));
111
+ h.update(JSON.stringify(SAMPLE));
112
+ for (const f of ["effects.ts", "slots.ts"]) if (existsSync(join(themesDir, t.world, f))) h.update(readFileSync(join(themesDir, t.world, f)));
113
+ for (const f of SAMPLE_CODE) if (existsSync(f)) h.update(readFileSync(f));
114
+ return h.digest("hex").slice(0, 16);
115
+ }
116
+
117
+ const metaOf = (id: string) => cellPath(id).replace(/\.png$/, ".json");
118
+
119
+ export function cellFresh(t: Theme): boolean {
120
+ const m = metaOf(t.id);
121
+ return existsSync(cellPath(t.id)) && existsSync(m) && readJson(m).key === cellKey(t);
122
+ }
123
+
124
+ export function markCell(t: Theme, frame: Frame): void {
125
+ writeFileSync(metaOf(t.id), `${JSON.stringify({ key: cellKey(t), at: frame.at, width: frame.width, height: frame.height, safe: frame.safe, pattern: frame.pattern ?? null }, null, 2)}\n`);
126
+ }
127
+
128
+ export const cellFrame = (id: string): Frame | null => (existsSync(metaOf(id)) ? readJson(metaOf(id)) : null);
129
+
130
+ /**
131
+ * 칸이 없거나 낡은 테마만 찍는다(검사 없이 — 변주는 뽑을 때 검사를 넘었다). 세계마다 표준 장면을 한 번 짓고 변주는 style 만 갈아 찍는다.
132
+ * 돌려주는 것: id → 칸 경로(못 찍은 것은 빠진다)
133
+ */
134
+ export function ensureCells(ids: string[], tmp: string, log: (l: string) => void = () => {}): Map<string, string> {
135
+ const out = new Map<string, string>();
136
+ const byWorld = new Map<string, Theme[]>();
137
+ for (const id of ids) {
138
+ const t = loadTheme(id);
139
+ if (cellFresh(t)) out.set(id, cellPath(id));
140
+ else byWorld.set(t.world, [...(byWorld.get(t.world) ?? []), t]);
141
+ }
142
+ for (const [world, list] of byWorld) {
143
+ const base = join(tmp, `${world}-base`);
144
+ const b = standardProject(world, base, { check: false });
145
+ if (!b.frame) {
146
+ log(`견본 칸 ${world}: 표준 장면을 못 지었다 — ${b.why}`);
147
+ continue;
148
+ }
149
+ for (const t of list) {
150
+ const dir = t.variant ? join(tmp, t.id.replace("/", "--")) : base;
151
+ if (t.variant) restyle(base, dir, t.id);
152
+ const bad = still(dir, b.frame.at, cellPath(t.id));
153
+ if (bad) {
154
+ log(`견본 칸 ${t.id}: 못 찍음 — ${bad}`);
155
+ continue;
156
+ }
157
+ markCell(t, b.frame);
158
+ out.set(t.id, cellPath(t.id));
159
+ log(`견본 칸 ${t.id}: ${cellPath(t.id)}`);
160
+ }
161
+ }
162
+ return out;
163
+ }
164
+
165
+ export interface GridCell {
166
+ png: string;
167
+ title: string;
168
+ sub?: string;
169
+ note?: string;
170
+ swatches?: string[];
171
+ badge?: string;
172
+ bad?: boolean;
173
+ }
174
+
175
+ const esc = (s: string) => s.replace(/[&<>"]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[c]!);
176
+
177
+ /** 칸 격자 한 장 — 안전 영역 점선, 이름·설명·색 견본 */
178
+ export async function gridSheet(cells: GridCell[], out: string, o: { heading: string; cols: number; w: number; frame: Pick<Frame, "width" | "height" | "safe"> }): Promise<string> {
179
+ const { w, cols, frame } = o;
180
+ const h = Math.round((w * frame.height) / frame.width);
181
+ const k = w / frame.width;
182
+ const html = `<!doctype html><meta charset="utf-8"><style>
183
+ body { margin: 0; padding: 24px; background: #111; font: 15px/1.35 -apple-system, "Apple SD Gothic Neo", sans-serif; color: #ddd; width: ${cols * w + (cols - 1) * 16}px; }
184
+ h1 { margin: 0 0 16px; font-size: 18px; font-weight: 600; color: #fff; }
185
+ main { display: grid; grid-template-columns: repeat(${cols}, ${w}px); gap: 22px 16px; }
186
+ figure { margin: 0; position: relative; }
187
+ .safe { position: absolute; left: 0; width: ${w}px; border-top: 2px dashed #ff4d4d; opacity: .8; }
188
+ img { display: block; width: ${w}px; height: ${h}px; outline: 1px solid #333; object-fit: cover; }
189
+ figcaption { padding: 8px 2px 0; }
190
+ b { color: #fff; }
191
+ .d { display: inline-block; margin-left: 6px; padding: 0 6px; border: 1px solid #666; border-radius: 4px; font-size: 12px; }
192
+ small { display: block; color: #999; font-size: 12.5px; word-break: keep-all; }
193
+ .sw { display: flex; gap: 3px; margin-top: 5px; }
194
+ .sw i { width: 18px; height: 12px; border-radius: 2px; outline: 1px solid #444; }
195
+ .bad { color: #ff6b6b; }
196
+ </style><h1>${esc(o.heading)}</h1><main>${cells
197
+ .map(
198
+ (c) =>
199
+ `<figure><img src="${pathToFileURL(c.png).href}"><div class="safe" style="top:${Math.round(frame.safe.top * k)}px"></div><div class="safe" style="top:${Math.round((frame.height - frame.safe.bottom) * k)}px"></div><figcaption><b>${esc(c.title)}</b>${c.badge ? `<span class="d">${esc(c.badge)}</span>` : ""}${c.sub ? `<small>${esc(c.sub)}</small>` : ""}${c.note ? `<small class="${c.bad ? "bad" : ""}">${esc(c.note)}</small>` : ""}${c.swatches ? `<div class="sw">${c.swatches.map((s) => `<i style="background:${s}"></i>`).join("")}</div>` : ""}</figcaption></figure>`,
200
+ )
201
+ .join("")}</main>`;
202
+ mkdirSync(dirname(out), { recursive: true });
203
+ const page = out.replace(/\.png$/, ".html");
204
+ writeFileSync(page, html);
205
+ const browser = await launch();
206
+ try {
207
+ const p = await browser.newPage({ viewport: { width: 48 + cols * w + (cols - 1) * 16, height: 400 } });
208
+ await p.goto(pathToFileURL(page).href, { waitUntil: "load" });
209
+ writeFileSync(out, await p.screenshot({ fullPage: true, type: "png" }));
210
+ } finally {
211
+ await browser.close();
212
+ rmSync(page, { force: true });
213
+ }
214
+ return out;
215
+ }
216
+
217
+ /** 격자 칸 글 — 이름·2D/3D·설명·색 견본 */
218
+ export function cellOf(t: Theme, png: string): GridCell {
219
+ const c = t.style.colors;
220
+ return {
221
+ png,
222
+ title: t.variant ? t.variant.name : `${t.name} · 기본`,
223
+ badge: themeDims(t),
224
+ sub: t.variant ? `${t.id} — ${t.variant.desc}` : `${t.id} — 세계 그대로`,
225
+ swatches: [c.bg, c.surface, c.ink, c.accent, c.success, c.danger],
226
+ };
227
+ }
@@ -5,14 +5,27 @@ import { join } from "node:path";
5
5
  import type { Command } from "../command.ts";
6
6
  import { checks, pad, report } from "../deps.ts";
7
7
  import { repoRoot } from "../serve.ts";
8
+ import { commandFor, isNewer, refresh } from "../update.ts";
9
+
10
+ async function versionLine(now: string): Promise<string> {
11
+ try {
12
+ const latest = await refresh(5000);
13
+ if (!isNewer(latest, now)) return `판: 지금 ${now} · 최신 ${latest} — 최신이다`;
14
+ const command = commandFor(latest);
15
+ return `판: 지금 ${now} · 최신 ${latest} · ${command ? `올리기 kf update (${command.join(" ")})` : "레포 체크아웃 — git pull"}`;
16
+ } catch (e) {
17
+ return `판: 지금 ${now} · 최신을 확인하지 못했다(${(e as Error).message}) — kf update --check`;
18
+ }
19
+ }
8
20
 
9
21
  const cmd: Command = {
10
- summary: "바깥 도구 점검 — ffmpeg·크롬(Playwright)·python3+librosa·OG 키, 없으면 까는 명령",
22
+ summary: "바깥 도구 점검 — 판(지금·최신)·ffmpeg·크롬(Playwright)·python3+librosa·OG 키, 없으면 까는 명령",
11
23
  usage: `kf doctor
12
24
  없음 은 렌더가 안 되는 것, 선택 은 그 기능만 빠지는 것. 크롬·librosa 는 kf setup 이 깐다. 종료 코드: 없음 이 있으면 1`,
13
25
  async run() {
14
26
  const version = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8")).version ?? "?";
15
- console.log(`kasaframe ${version} · Node ${process.version} · ${platform()} ${arch()}\n`);
27
+ console.log(`kasaframe ${version} · Node ${process.version} · ${platform()} ${arch()}`);
28
+ console.log(`${await versionLine(version)}\n`);
16
29
  const list = await checks();
17
30
  report(list);
18
31
  const missing = list.filter((c) => c.required && !c.ok);
@@ -0,0 +1,118 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { basename, join, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { type FontPair, fontGroups, fontPairs } from "@kasaframe/themes/fonts";
7
+ import { type Command, parseFlags } from "../command.ts";
8
+ import { checkFonts, fontCacheDir, fontSheet, noticeSection, type PairReport, replaceNotice } from "../fonts.ts";
9
+
10
+ const cmd: Command = {
11
+ summary: "글꼴 짝 검사·견본 격자 — 주소·판·라이선스 글·한글 덮음·굵기, 크롬으로 찍어 투명·두부·떨어짐",
12
+ usage: `kf fonts list [--group <무리>]
13
+ kf fonts check [--group <무리>[,…]] [--id <짝>[,…]] [--json] [--no-render] [--offline]
14
+ kf fonts sheet [--group <무리>[,…]] [--id <짝>[,…]] [--out 파일.png] [--share]
15
+ kf fonts notice [--write]
16
+
17
+ 짝 목록은 packages/themes/kit/fonts.json(무리 core)과 kit/fonts/<무리>.json 을 합친 것.
18
+ check 는 짝마다
19
+ - 칸: hangul(full|ks2350)·face 마다 license·source, 스택 첫 글꼴의 face, 모든 스택이 Pretendard Variable 로 끝남
20
+ - 주소: 파일·라이선스 글이 200, 판 박힘(jsdelivr gh@커밋|태그·npm@x.y.z — @main·@latest·@5 는 안 된다)
21
+ - 라이선스 글: OFL-1.1·Apache-2.0 은 글에 그 문구가 있는지. 목록 밖 이름은 사람이 읽을 것으로 남긴다
22
+ - 파일: 한글 음절 수(11,172 = full, KS X 1001 2,350 다 = ks2350, 그 아래는 탈락)와 적은 hangul 이 맞는지,
23
+ 적은 굵기 범위가 파일(wght 축·usWeightClass)과 맞는지, 제목 굵기 단이 있는지(없으면 가짜 굵기)
24
+ - 크롬: 스택마다 한글·라틴·숫자 견본 한 줄을 찍어 투명·두부·시스템 글꼴로 떨어짐·예상과 다른 face 를 잡는다
25
+ 받은 파일은 ${fontCacheDir()}/files 에 두고 다음부터는 주소가 살았는지만 묻는다. 문제가 있는 짝이 있으면 종료 1.
26
+ --json { pairs: [{ id, group, ok, hangul, syllables, boldest, licenses, problems, notes }], summary }
27
+ --no-render 크롬 없이(파일·주소만)
28
+ --offline 주소를 묻지 않고 캐시만(라이선스 글 대조도 건너뛴다)
29
+ sheet 는 짝마다 제목·본문·고정폭 견본 칸을 격자 한 장으로 — 기본 ${fontCacheDir()}/sheet[-<무리>].png.
30
+ --share 면 kasaterm 공유 폴더 kasaframe-글꼴 로 옮긴다.
31
+ notice 는 모든 무리를 합친 목록으로 NOTICE 의 글꼴 절(글꼴 이름 · 라이선스 · 라이선스 글)을 찍는다. --write 면 레포 NOTICE 에
32
+ 그 절을 갈아 끼운다 — 무리 파일을 고친 뒤 한 번.`,
33
+ async run(argv) {
34
+ const [sub, ...rest] = argv;
35
+ const { opts } = parseFlags(rest);
36
+ const list = pick(opts);
37
+ if (!list) return 2;
38
+ if (sub === "list" || !sub) {
39
+ for (const { group, pair } of list) console.log(`${group.padEnd(10)} ${pair.id.padEnd(26)} ${String(pair.hangul ?? "?").padEnd(7)} ${pair.tags.join(",").padEnd(30)} ${pair.name}`);
40
+ console.log(`짝 ${list.length}`);
41
+ return 0;
42
+ }
43
+ if (sub === "check") {
44
+ const reports = await checkFonts(list, { offline: !!opts.offline, render: !opts["no-render"], log: (l) => console.error(l) });
45
+ const summary = summarize(reports);
46
+ if (opts.json) console.log(JSON.stringify({ pairs: reports, summary }, null, 1));
47
+ else print(reports, summary);
48
+ return reports.every((r) => r.ok) ? 0 : 1;
49
+ }
50
+ if (sub === "notice") {
51
+ const section = noticeSection(fontPairs());
52
+ if (!opts.write) {
53
+ process.stdout.write(section);
54
+ return 0;
55
+ }
56
+ const file = fileURLToPath(new URL("../../../../NOTICE", import.meta.url));
57
+ writeFileSync(file, replaceNotice(readFileSync(file, "utf8"), section));
58
+ console.log(file);
59
+ return 0;
60
+ }
61
+ if (sub === "sheet") {
62
+ const groups = typeof opts.group === "string" ? opts.group.replace(/,/g, "+") : "";
63
+ const out = resolve(typeof opts.out === "string" ? opts.out : join(fontCacheDir(), `sheet${groups ? `-${groups}` : ""}.png`));
64
+ await fontSheet(list, out, { log: (l) => console.error(l) });
65
+ console.log(out);
66
+ if (opts.share) {
67
+ const r = spawnSync("kasaterm-cli", ["share", "new", "kasaframe-글꼴"], { encoding: "utf8" });
68
+ let dir = r.status === 0 ? (r.stdout.trim().split("\n").pop() ?? "") : "";
69
+ if (!dir || !existsSync(dir)) {
70
+ dir = join(homedir(), "Desktop", "kasaframe-글꼴");
71
+ mkdirSync(dir, { recursive: true });
72
+ }
73
+ copyFileSync(out, join(dir, basename(out)));
74
+ console.log(`공유 폴더 ${dir}`);
75
+ }
76
+ return 0;
77
+ }
78
+ console.error(`kf fonts: 모르는 하위 명령 ${sub} — list·check·sheet·notice`);
79
+ return 2;
80
+ },
81
+ };
82
+
83
+ function pick(opts: Record<string, string | boolean | undefined>): { group: string; pair: FontPair }[] | null {
84
+ const groups = fontGroups();
85
+ const want = typeof opts.group === "string" ? opts.group.split(",") : null;
86
+ const unknown = want?.filter((g) => !groups.some((x) => x.group === g));
87
+ if (unknown?.length) {
88
+ console.error(`kf fonts: 무리 ${unknown.join(",")} 가 없다 — 있는 무리: ${groups.map((g) => g.group).join(" ")}`);
89
+ return null;
90
+ }
91
+ const ids = typeof opts.id === "string" ? new Set(opts.id.split(",")) : null;
92
+ const list = groups.filter((g) => !want || want.includes(g.group)).flatMap((g) => g.pairs.map((pair) => ({ group: g.group, pair }))).filter(({ pair }) => !ids || ids.has(pair.id));
93
+ if (ids && list.length < ids.size) console.error(`kf fonts: 없는 짝 — ${[...ids].filter((i) => !list.some((x) => x.pair.id === i)).join(",")}`);
94
+ return list;
95
+ }
96
+
97
+ const tally = (xs: string[]) => Object.fromEntries([...new Set(xs)].sort().map((x) => [x, xs.filter((y) => y === x).length]));
98
+
99
+ function summarize(reports: PairReport[]) {
100
+ return {
101
+ pairs: reports.length,
102
+ ok: reports.filter((r) => r.ok).length,
103
+ hangul: tally(reports.map((r) => r.hangul ?? "?")),
104
+ licenses: tally(reports.flatMap((r) => r.licenses)),
105
+ };
106
+ }
107
+
108
+ function print(reports: PairReport[], s: ReturnType<typeof summarize>): void {
109
+ for (const r of reports) {
110
+ console.log(`${r.ok ? "ok " : "문제"} ${r.group.padEnd(10)} ${r.id.padEnd(26)} 한글 ${r.hangul ?? "?"}(${r.syllables ?? "?"}) · 굵은 단 ${r.boldest ?? "?"} · ${r.licenses.join(",")}`);
111
+ for (const p of r.problems) console.log(` ! ${p}`);
112
+ for (const n of r.notes) console.log(` · ${n}`);
113
+ }
114
+ const fmt = (o: Record<string, number>) => Object.entries(o).map(([k, v]) => `${k} ${v}`).join(" · ");
115
+ console.log(`\n짝 ${s.pairs} — 통과 ${s.ok} · 문제 ${s.pairs - s.ok} | 한글 ${fmt(s.hangul)} | 라이선스(짝 기준) ${fmt(s.licenses)}`);
116
+ }
117
+
118
+ export default cmd;
@@ -4,14 +4,15 @@ import { basename, dirname, extname, join, resolve } from "node:path";
4
4
  import { createInterface } from "node:readline/promises";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { askTerminal, blenderLibDir, capabilities, genImage, genVideo, hasKey, NeedsApproval, parseAllow, type Question, questionsText, seam, seamFrames, settle, still, whereToPut } from "@kasaframe/gen";
7
- import { applyAnswers, attachStudio, loadSeries, type Series, seriesFromRequest, chat, codeBlock, detect, formatLook, jsonBlock, listTemplates, loadTemplate, look, lookSheet, makePlan, type Message, type Plan, planQuestions, premiumBlock, projectBrief, PURPOSES, type Purpose, readProject, spend, spentLine, WAIT, writeCaptions, writeStats } from "@kasaframe/plan";
7
+ import { applyAnswers, attachStudio, type LookInput, loadSeries, suggestThemes, usableTheme, type Series, seriesFromRequest, chat, codeBlock, detect, formatLook, jsonBlock, listTemplates, loadTemplate, look, lookSheet, makePlan, type Message, type Plan, planQuestions, premiumBlock, projectBrief, PURPOSES, type Purpose, readProject, spend, spentLine, WAIT, writeCaptions, writeStats } from "@kasaframe/plan";
8
8
  import { checkContent, contentPrompt, directBrief } from "@kasaframe/director";
9
9
  import { transform } from "esbuild";
10
10
  import { bundleFor, dressSeed, pickDress } from "@kasaframe/motion/menu";
11
- import { themeStyle } from "@kasaframe/themes";
11
+ import { themeStyle, worldOf } from "@kasaframe/themes";
12
12
  import { captionMode } from "@kasaframe/motion/captions";
13
13
  import { jizuraCheck } from "@kasaframe/jizura/install";
14
14
  import { openPage } from "../browser.ts";
15
+ import { askThemeTerminal, candidateSheet, refLook } from "../pick.ts";
15
16
  import { librosa } from "../deps.ts";
16
17
  import { lyricsCheck } from "./lyrics.ts";
17
18
  import { type Command, num, parseFlags } from "../command.ts";
@@ -92,8 +93,11 @@ kf make --answer <폴더> --image <값> --video <값> … Claude Code 모드
92
93
  끝날 때(성공·실패·중단) <작업 폴더>/make-stats.json 에 단계별 모델·ms·토큰·usd 와 합계를 남기고 「OG 호출 N번 · 토큰 · $」 한 줄을 찍는다
93
94
  --series 시리즈 묶음(series/<id>.json) · none. 안 주면 요청이 짚은 시리즈(「OG 쇼츠」처럼) — 용도·테마·목소리·곡·자막·길이·끝 카드·생성 답을 묻지 않고 그 묶음대로
94
95
  --purpose 용도를 못 박는다: ${PURPOSES.join(" · ")}
95
- --theme 테마 id · auto(요청이 「리소 느낌」처럼 짚은 테마, 아니면 내용에 맞는 approved 후보 셋 중 첫째. 첫 장면을 셋 다 찍어 out/theme-<id>.png) · none(프리셋만)
96
- 안 주면(시리즈가 정하지도 않았으면) 묻는다 — 보기는 approved 테마 전부(생김새 한 줄·2D/3D·견본)와 「알아서」(= auto). kf theme sheet
96
+ --theme 테마 id·변주 「<세계>/<변주>」 · auto(요청이 「리소 느낌」처럼 짚은 테마, 아니면 요청·분위기에 맞는 approved 후보 중 첫째) · none(프리셋만)
97
+ 안 주면(시리즈가 정하지도 않았으면) 묻는다 — 보기는 「알아서」(= auto)와 요청·용도·분위기 낱말에 맞는 approved 세계·변주 넷,
98
+ 넷만 담은 견본 시트를 그 자리에서 만든다(칸은 캐시). 테마 이름이 아닌 말을 주면 분위기 한 마디로 읽는다
99
+ --theme-mood 분위기 한 마디(「따뜻한 종이 느낌」·「어두운 네온」) — 그걸로 후보 넷을 다시 고른다. --answer 와 함께 주면 다시 묻는다
100
+ --theme-ref 레퍼런스 그림 경로·그림 주소·웹 페이지 주소 — 바탕·강조색을 읽어 후보 넷을 다시 고른다
97
101
  --yes 묻지 않고 권장 답으로 — 돈이 드는 그림·영상도 승인한다(지역 제한이 걸린 H3 는 --video h3-pod 로 짚어야만)
98
102
  --max-usd 영상 하나 상한(기본 1)
99
103
  --video-provider 영상 공급자를 못 박는다(예: h3-pod — KF_H3_URL·KF_H3_STEPS 필요). 기본은 KF_VIDEO_PROVIDER, 없으면 생성 담당 기본
@@ -228,6 +232,13 @@ async function make(argv: string[], at: Track): Promise<number> {
228
232
  return 2;
229
233
  }
230
234
  const assetFiles = str("assets") ? listFiles(resolve(str("assets")!)) : [];
235
+ let themeLook: LookInput;
236
+ try {
237
+ themeLook = await lookFlags(opts);
238
+ } catch (e) {
239
+ console.error(`kf make: ${(e as Error).message}`);
240
+ return 2;
241
+ }
231
242
  // 시리즈가 먼저 — 같은 시리즈면 매번 같은 묶음. 사람이 따로 준 플래그는 그대로 이긴다
232
243
  const series: Series | null = str("series") === "none" ? null : str("series") ? loadSeries(str("series")!) : seriesFromRequest(request);
233
244
  if (series) console.error(`시리즈 ${series.id}(${series.label}) — 용도·테마·목소리·곡·자막·길이·끝 카드를 묶음대로`);
@@ -256,8 +267,10 @@ async function make(argv: string[], at: Track): Promise<number> {
256
267
 
257
268
  // 만들기 전에 묻는다 — 뼈대를 만들고 나서 멈추면 반쯤 만든 폴더가 남는다
258
269
  const caps = await capabilities({ probe: true });
259
- const draft = makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none" });
270
+ const draft = makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none", look: themeLook });
260
271
  const { questions, auto } = planQuestions(draft, caps);
272
+ // 테마를 물을 거면 후보 넷 견본 시트를 그 자리에서 — 질문 글에 시트 경로가 붙는다
273
+ const themeQ = questions.find((q) => q.id === "theme");
261
274
  const flags = { ...seriesAnswers(series), ...opts };
262
275
  const settled = settle(questions, { given: flags, yes: !!opts.yes, noGen: !!opts["no-gen"], allow: parseAllow(opts.allow) });
263
276
  // 묻지 않고 정한 답(있는 공짜 능력)도 사람이 준 플래그·시리즈 답이 이긴다. --no-gen 이면 공짜라도 생성 모델(그림·영상)은 뺀다
@@ -282,6 +295,20 @@ async function make(argv: string[], at: Track): Promise<number> {
282
295
  answers = { ...answers, ...asked };
283
296
  }
284
297
  if (answers.beats === "none" && answers.music && !/^(gen:|none$)/.test(answers.music)) answers.music = "none";
298
+ if (themeQ && open.includes(themeQ)) await candidateSheet(themeQ, (l) => console.error(l));
299
+ // 터미널이면 테마는 따로 — 분위기 한 마디·그림 경로·주소를 치면 그걸로 후보를 다시 골라 다시 묻는다
300
+ if (themeQ && open.includes(themeQ) && model !== "claude-code") {
301
+ const picked = await askThemeTerminal(themeQ, async (r) => {
302
+ themeLook = { ...themeLook, ...r, ...(r.mood ? { mood: [themeLook.mood, r.mood].filter(Boolean).join(" ") } : {}) };
303
+ const q = planQuestions(makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none", look: themeLook }), caps).questions.find((x) => x.id === "theme")!;
304
+ await candidateSheet(q, (l) => console.error(l));
305
+ return q;
306
+ });
307
+ if (picked) {
308
+ answers.theme = picked;
309
+ open = open.filter((q) => q !== themeQ);
310
+ }
311
+ }
285
312
  if (open.length && model !== "claude-code") {
286
313
  const asked = await askTerminal(open);
287
314
  if (!asked) {
@@ -307,7 +334,10 @@ async function make(argv: string[], at: Track): Promise<number> {
307
334
  if (song) newArgs.push("--music", song);
308
335
  if (str("title")) newArgs.push("--title", str("title")!);
309
336
  // 테마 질문의 답(플래그·터미널) → 아직 묻는 중이거나 묻지 않은 테마(시리즈·요청이 짚은 것)는 auto. 테마 없이 프리셋만 쓰려면 --theme none
310
- newArgs.push("--theme", answers.theme && answers.theme !== WAIT ? answers.theme : (str("theme") ?? "auto"));
337
+ // 「알아서」·묻는 중이면 후보 첫째 — 분위기·레퍼런스로 고른 넷이라 kf new 의 auto(요청 낱말만)와 다를 수 있다
338
+ const firstPick = themeQ?.choices.find((c) => c.value !== "auto")?.value;
339
+ const themeArg = answers.theme && answers.theme !== WAIT && answers.theme !== "auto" ? answers.theme : (str("theme") ?? (firstPick && (answers.theme === "auto" || open.includes(themeQ!)) ? firstPick : "auto"));
340
+ newArgs.push("--theme", themeArg);
311
341
  if (opts.force) newArgs.push("--force");
312
342
  const made = spawnSync(process.execPath, newArgs, { stdio: ["ignore", "inherit", "inherit"] });
313
343
  if (made.status !== 0) return made.status ?? 1;
@@ -315,7 +345,7 @@ async function make(argv: string[], at: Track): Promise<number> {
315
345
  const studio = await attachStudio({ dir, request, model, purpose });
316
346
  const unmirror = studio?.mirror();
317
347
  if (studio) console.log(`작업실: ${studio.url}`);
318
- const plan: Plan = { ...applyAnswers(JSON.parse(readFileSync(join(dir, "plan.json"), "utf8")), answers).plan, asks: open };
348
+ const plan: Plan = { ...applyAnswers(JSON.parse(readFileSync(join(dir, "plan.json"), "utf8")), answers).plan, asks: open, ...(themeLook.mood || themeLook.ref ? { themeLook } : {}) };
319
349
  // 새 프로젝트는 이 영상의 기본으로 적는다 — 계획 다듬기가 내레이션을 쓸지도 이걸 본다
320
350
  if (captions) {
321
351
  const kfPath = join(dir, "kf.json");
@@ -582,6 +612,19 @@ async function probeScene(dir: string, id: string): Promise<string[]> {
582
612
  return [...new Set(problems)];
583
613
  }
584
614
 
615
+ // 테마 고르기 플래그 — --theme-mood·--theme-ref, 그리고 테마 이름이 아닌 --theme 값(분위기 한 마디로 읽는다)
616
+ async function lookFlags(opts: Record<string, string | boolean | undefined>): Promise<LookInput> {
617
+ const look: LookInput = {};
618
+ const theme = typeof opts.theme === "string" ? opts.theme : undefined;
619
+ if (theme && theme !== "auto" && theme !== "none" && !usableTheme(theme)) {
620
+ look.mood = theme;
621
+ delete opts.theme;
622
+ }
623
+ if (typeof opts["theme-mood"] === "string") look.mood = [look.mood, opts["theme-mood"]].filter(Boolean).join(" ");
624
+ if (typeof opts["theme-ref"] === "string") look.ref = await refLook(opts["theme-ref"]);
625
+ return look;
626
+ }
627
+
585
628
  // 테마 후보마다 첫 장면을 그 테마로 한 장 — 사람이 셋을 나란히 보고 고른다. style.json 만 잠깐 바꿔 찍고 되돌린다
586
629
  function themeStills(dir: string, ids: string[]): void {
587
630
  const stylePath = join(dir, "style.json");
@@ -734,6 +777,30 @@ async function answerProject(dir: string, opts: Record<string, string | boolean
734
777
  return 2;
735
778
  }
736
779
  const plan: Plan = JSON.parse(readFileSync(file, "utf8"));
780
+ // 테마에 분위기 한 마디·레퍼런스를 줬으면 후보 넷을 다시 고르고 견본 시트를 새로 만들어 다시 묻는다 — 답은 그다음
781
+ let look: LookInput;
782
+ try {
783
+ look = await lookFlags(opts);
784
+ } catch (e) {
785
+ console.error(`kf make --answer: ${(e as Error).message}`);
786
+ return 2;
787
+ }
788
+ if (look.mood || look.ref) {
789
+ plan.themeLook = { ...plan.themeLook, ...look, ...(look.mood ? { mood: [plan.themeLook?.mood, look.mood].filter(Boolean).join(" ") } : {}) };
790
+ const q = planQuestions(plan, await capabilities({ probe: false })).questions.find((x) => x.id === "theme");
791
+ if (!q) {
792
+ console.error("kf make --answer: 이 프로젝트는 테마를 묻지 않는다(시리즈나 요청이 테마를 정했다) — --theme <id> 로 바꾼다");
793
+ return 2;
794
+ }
795
+ const sheet = await candidateSheet(q, (l) => console.error(l));
796
+ plan.asks = [...(plan.asks ?? []).filter((x) => x.id !== "theme"), q];
797
+ writeJson(file, plan);
798
+ writeFileSync(join(dir, "MAKE.md"), isDirect(dir) ? directBrief(dir) : projectBrief(dir));
799
+ console.log(`테마 후보를 다시 골랐다${sheet ? ` — 견본 시트 ${sheet}` : ""}:`);
800
+ for (const c of q.choices) console.log(` --theme ${c.value.padEnd(30)} ${c.label}${c.note ? ` — ${c.note}` : ""}`);
801
+ console.error("사람에게 다시 묻고 kf make --answer <폴더> --theme <값> 으로 답을 넣는다");
802
+ return 3;
803
+ }
737
804
  const waiting = new Set((plan.asks ?? []).map((q) => q.id));
738
805
  const fresh = planQuestions(plan, await capabilities({ probe: true })).questions.filter((q) => waiting.has(q.id));
739
806
  const settled = settle(fresh, { given: opts, yes: !!opts.yes, noGen: !!opts["no-gen"], allow: parseAllow(opts.allow) });
@@ -765,7 +832,8 @@ function retheme(dir: string, answer: string): string | null {
765
832
  const plan = readPlan(dir) as Plan;
766
833
  const kfPath = join(dir, "kf.json");
767
834
  const kf = JSON.parse(readFileSync(kfPath, "utf8"));
768
- const id: string | null = answer === "auto" ? (plan.themeCandidates?.[0]?.id ?? kf.theme ?? null) : answer === "none" ? null : answer;
835
+ const id: string | null =
836
+ answer === "auto" ? (suggestThemes(plan.request, plan.purpose, plan.aspect, 1, plan.themeLook ?? {})[0]?.id ?? plan.themeCandidates?.[0]?.id ?? kf.theme ?? null) : answer === "none" ? null : answer;
769
837
  if ((kf.theme ?? null) === id) return id;
770
838
  const tpl = loadTemplate(plan.purpose);
771
839
  // 프리셋으로 돌아가면 kf new 가 테마 없이 골랐을 프리셋 — 시리즈·요청 낱말·틀 차례
@@ -774,7 +842,7 @@ function retheme(dir: string, answer: string): string | null {
774
842
  style.motion = { ...style.motion, ...tpl.motion };
775
843
  writeJson(join(dir, "style.json"), style);
776
844
  if (tpl.moves) {
777
- const dress = pickDress(dressSeed(plan.request || plan.title, plan.purpose, id ?? preset!), plan.scenes, bundleFor(tpl.moves, id ?? undefined));
845
+ const dress = pickDress(dressSeed(plan.request || plan.title, plan.purpose, worldOf(id) ?? preset!), plan.scenes, bundleFor(tpl.moves, id ?? undefined));
778
846
  const byId = new Map(plan.scenes.map((s, i) => [s.id, dress[i]]));
779
847
  for (const s of kf.scenes as { id: string; file: string; dress?: Record<string, string> }[]) {
780
848
  const next = byId.get(s.id);
@@ -3,7 +3,7 @@ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFi
3
3
  import { basename, join, relative, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { bundleFor, dressSeed, NO_DRESS, pickDress } from "@kasaframe/motion/menu";
6
- import { themeStyle } from "@kasaframe/themes";
6
+ import { themeStyle, worldOf } from "@kasaframe/themes";
7
7
  import { type Aspect, type BeatsLike, type Plan, type Purpose, listTemplates, loadTemplate, makePlan, parseTitle, PURPOSES, sceneSkeleton, templatesDir } from "@kasaframe/plan";
8
8
  import { type Command, num, parseFlags } from "../command.ts";
9
9
 
@@ -116,7 +116,7 @@ kf new <폴더> --plan plan.json kf make 가 세운 계
116
116
 
117
117
  // 장면마다 연출 수(바탕·글·경계 덮기) — 용도 틀·테마 묶음에서 요청 글을 씨앗으로 고른다. 같은 요청이면 같은 수가 걸린다
118
118
  // 틀에 묶음이 없으면(뮤비 — 가사 층이 화면을 맡는다) 무대 기본 그대로
119
- const dress = tpl.moves ? pickDress(dressSeed(plan.request || plan.title, plan.purpose, plan.theme ?? plan.style), plan.scenes, bundleFor(tpl.moves, plan.theme ?? undefined)) : plan.scenes.map(() => ({ ...NO_DRESS }));
119
+ const dress = tpl.moves ? pickDress(dressSeed(plan.request || plan.title, plan.purpose, worldOf(plan.theme) ?? plan.style), plan.scenes, bundleFor(tpl.moves, plan.theme ?? undefined)) : plan.scenes.map(() => ({ ...NO_DRESS }));
120
120
 
121
121
  const frame = { width: plan.width, height: plan.height };
122
122
  const safeArea = plan.aspect === tpl.aspect ? tpl.safeArea : (tpl.variants?.[plan.aspect]?.safeArea ?? tpl.safeArea);