kasaframe 0.1.4 → 0.1.6

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 (374) hide show
  1. package/NOTICE +311 -0
  2. package/README.md +18 -5
  3. package/docs/AGENTS.md +2 -1
  4. package/package.json +1 -1
  5. package/packages/adapters/src/project.ts +2 -0
  6. package/packages/check/package.json +1 -0
  7. package/packages/check/src/check.ts +8 -2
  8. package/packages/check/src/rules/frames.ts +4 -5
  9. package/packages/cli/src/commands/doctor.ts +15 -2
  10. package/packages/cli/src/commands/fonts.ts +118 -0
  11. package/packages/cli/src/commands/make.ts +15 -5
  12. package/packages/cli/src/commands/render.ts +34 -7
  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/mix.ts +66 -4
  17. package/packages/cli/src/segments.ts +1 -1
  18. package/packages/cli/src/sfx.ts +429 -0
  19. package/packages/cli/src/update.ts +250 -0
  20. package/packages/core/src/frame.ts +7 -4
  21. package/packages/core/src/index.ts +3 -1
  22. package/packages/core/src/project.ts +19 -0
  23. package/packages/core/src/sfx.ts +70 -0
  24. package/packages/director/src/assemble.ts +7 -4
  25. package/packages/director/src/index.ts +1 -1
  26. package/packages/director/src/pattern.ts +2 -0
  27. package/packages/director/src/scene.ts +14 -5
  28. package/packages/director/src/transitions.ts +21 -8
  29. package/packages/motion/src/enter.ts +7 -1
  30. package/packages/motion/src/impact.ts +5 -2
  31. package/packages/motion/src/moves/dress.ts +15 -2
  32. package/packages/motion/src/moves/menu.ts +11 -5
  33. package/packages/motion/src/transition.ts +3 -1
  34. package/packages/motion/src/transition3d/index.ts +3 -1
  35. package/packages/motion/src/transition3d/live.ts +5 -3
  36. package/packages/patterns/src/bars/rank.ts +6 -7
  37. package/packages/patterns/src/before-after/shrink.ts +3 -4
  38. package/packages/patterns/src/before-after/strike.ts +4 -5
  39. package/packages/patterns/src/code/terminal.ts +25 -16
  40. package/packages/patterns/src/end/lockup.ts +13 -10
  41. package/packages/patterns/src/end/slam.ts +7 -5
  42. package/packages/patterns/src/hook-number/counter.ts +15 -9
  43. package/packages/patterns/src/hook-number/slam.ts +6 -8
  44. package/packages/patterns/src/kit.ts +281 -58
  45. package/packages/patterns/src/limit/gauge.ts +16 -11
  46. package/packages/patterns/src/quote/karaoke.ts +17 -12
  47. package/packages/patterns/src/sfx.ts +80 -0
  48. package/packages/patterns/src/term-reveal/chips.ts +24 -10
  49. package/packages/patterns/src/term-reveal/expand.ts +17 -13
  50. package/packages/patterns/src/title/mask.ts +9 -8
  51. package/packages/patterns/src/title/slam.ts +1 -1
  52. package/packages/patterns/src/types.ts +1 -0
  53. package/packages/plan/src/asks.ts +1 -1
  54. package/packages/plan/src/brief.ts +5 -2
  55. package/packages/plan/src/themes.ts +8 -2
  56. package/packages/themes/kit/THEME-MAKE.md +2 -2
  57. package/packages/themes/kit/fonts/display.json +3517 -0
  58. package/packages/themes/kit/fonts/sans.json +5155 -0
  59. package/packages/themes/kit/fonts/serif.json +5229 -0
  60. package/packages/themes/kit/fonts.json +243 -79
  61. package/packages/themes/package.json +3 -1
  62. package/packages/themes/src/fontfile.ts +183 -0
  63. package/packages/themes/src/fonts.ts +296 -0
  64. package/packages/themes/src/index.ts +32 -2
  65. package/packages/themes/src/look.ts +34 -8
  66. package/packages/themes/src/slots.ts +32 -2
  67. package/packages/themes/src/types.ts +33 -0
  68. package/packages/themes/src/vary.ts +35 -34
  69. package/presets/kawaii-pastel.json +2 -2
  70. package/sfx/README.md +82 -0
  71. package/sfx/click/appear.wav +0 -0
  72. package/sfx/click/burst.wav +0 -0
  73. package/sfx/click/drop.wav +0 -0
  74. package/sfx/click/end.wav +0 -0
  75. package/sfx/click/hop.wav +0 -0
  76. package/sfx/click/land.wav +0 -0
  77. package/sfx/click/select.wav +0 -0
  78. package/sfx/click/stick.wav +0 -0
  79. package/sfx/click/tick.wav +0 -0
  80. package/sfx/click/type.wav +0 -0
  81. package/sfx/click/whoosh.wav +0 -0
  82. package/sfx/pop/appear.wav +0 -0
  83. package/sfx/pop/burst.wav +0 -0
  84. package/sfx/pop/drop.wav +0 -0
  85. package/sfx/pop/end.wav +0 -0
  86. package/sfx/pop/hop.wav +0 -0
  87. package/sfx/pop/land.wav +0 -0
  88. package/sfx/pop/select.wav +0 -0
  89. package/sfx/pop/stick.wav +0 -0
  90. package/sfx/pop/tick.wav +0 -0
  91. package/sfx/pop/type.wav +0 -0
  92. package/sfx/pop/whoosh.wav +0 -0
  93. package/sfx/tags.json +545 -0
  94. package/sfx/ui/appear.wav +0 -0
  95. package/sfx/ui/burst.wav +0 -0
  96. package/sfx/ui/drop.wav +0 -0
  97. package/sfx/ui/end.wav +0 -0
  98. package/sfx/ui/hop.wav +0 -0
  99. package/sfx/ui/land.wav +0 -0
  100. package/sfx/ui/select.wav +0 -0
  101. package/sfx/ui/stick.wav +0 -0
  102. package/sfx/ui/tick.wav +0 -0
  103. package/sfx/ui/type.wav +0 -0
  104. package/sfx/ui/whoosh.wav +0 -0
  105. package/skills/kasaframe/SKILL.md +1 -0
  106. package/themes/blueprint/sample/style.json +5 -5
  107. package/themes/blueprint/style.json +5 -5
  108. package/themes/blueprint/theme.json +3 -1
  109. package/themes/blueprint/variants/deep-rose-suit.json +1 -1
  110. package/themes/blueprint/variants/navy-coral-2.json +1 -1
  111. package/themes/blueprint/variants/navy-coral-suit.json +1 -1
  112. package/themes/blueprint/variants/navy-orange-2.json +1 -1
  113. package/themes/blueprint/variants/navy-orange-suit.json +1 -1
  114. package/themes/cartography/sample/style.json +2 -2
  115. package/themes/cartography/style.json +2 -2
  116. package/themes/cartography/theme.json +3 -1
  117. package/themes/cartography/variants/deep-plum.json +1 -1
  118. package/themes/cartography/variants/frost-teal.json +1 -1
  119. package/themes/cartography/variants/navy-green.json +1 -1
  120. package/themes/circuit-board/sample/style.json +2 -2
  121. package/themes/circuit-board/style.json +2 -2
  122. package/themes/circuit-board/theme.json +3 -1
  123. package/themes/circuit-board/variants/dusk-gold-pretendard.json +1 -1
  124. package/themes/circuit-board/variants/navy-gold-grain.json +1 -1
  125. package/themes/circuit-board/variants/wine-gold-pretendard.json +1 -1
  126. package/themes/clay-toy/sample/style.json +2 -2
  127. package/themes/clay-toy/style.json +2 -2
  128. package/themes/clay-toy/theme.json +3 -1
  129. package/themes/clay-toy/variants/blush-coral-grain.json +1 -1
  130. package/themes/clay-toy/variants/chalk-teal.json +1 -1
  131. package/themes/clay-toy/variants/frost-sky.json +1 -1
  132. package/themes/clay-toy/variants/frost-teal.json +1 -1
  133. package/themes/clay-toy/variants/lilac-plum-round.json +1 -1
  134. package/themes/clay-toy/variants/lilac-plum.json +1 -1
  135. package/themes/clay-toy/variants/sage-indigo.json +1 -1
  136. package/themes/conveyor-factory/sample/style.json +3 -3
  137. package/themes/conveyor-factory/style.json +3 -3
  138. package/themes/conveyor-factory/theme.json +3 -1
  139. package/themes/conveyor-factory/variants/cocoa-gold.json +1 -1
  140. package/themes/conveyor-factory/variants/navy-gold.json +1 -1
  141. package/themes/conveyor-factory/variants/slate-amber-2.json +1 -1
  142. package/themes/conveyor-factory/variants/slate-amber-suit.json +1 -1
  143. package/themes/conveyor-factory/variants/slate-gold-bold.json +1 -1
  144. package/themes/data-journal/theme.json +3 -1
  145. package/themes/data-journal/variants/deep-coral.json +1 -1
  146. package/themes/data-journal/variants/navy-lime.json +1 -1
  147. package/themes/data-journal/variants/wine-indigo.json +1 -1
  148. package/themes/debug-hud/sample/style.json +1 -1
  149. package/themes/debug-hud/style.json +1 -1
  150. package/themes/debug-hud/theme.json +2 -1
  151. package/themes/debug-hud/variants/cocoa-teal.json +2 -2
  152. package/themes/debug-hud/variants/deep-teal-scan.json +2 -2
  153. package/themes/debug-hud/variants/dusk-plum.json +2 -2
  154. package/themes/debug-hud/variants/forest-lime.json +2 -2
  155. package/themes/debug-hud/variants/slate-green.json +2 -2
  156. package/themes/debug-hud/variants/wine-gold.json +2 -2
  157. package/themes/depth-flight/sample/style.json +1 -1
  158. package/themes/depth-flight/style.json +1 -1
  159. package/themes/depth-flight/theme.json +3 -1
  160. package/themes/depth-flight/variants/cocoa-cyan.json +1 -1
  161. package/themes/depth-flight/variants/cocoa-violet.json +1 -1
  162. package/themes/depth-flight/variants/deep-sky.json +1 -1
  163. package/themes/depth-flight/variants/forest-blue.json +1 -1
  164. package/themes/depth-flight/variants/navy-sky-grain.json +1 -1
  165. package/themes/depth-flight/variants/navy-sky.json +1 -1
  166. package/themes/depth-flight/variants/night-teal.json +1 -1
  167. package/themes/depth-flight/variants/slate-indigo.json +1 -1
  168. package/themes/depth-flight/variants/slate-violet.json +1 -1
  169. package/themes/film-reel/sample/style.json +2 -2
  170. package/themes/film-reel/style.json +2 -2
  171. package/themes/film-reel/theme.json +3 -1
  172. package/themes/film-reel/variants/chalk-pink.json +1 -1
  173. package/themes/film-reel/variants/lilac-gold.json +1 -1
  174. package/themes/film-reel/variants/lilac-violet.json +1 -1
  175. package/themes/glass-light/sample/style.json +1 -1
  176. package/themes/glass-light/style.json +1 -1
  177. package/themes/glass-light/theme.json +3 -1
  178. package/themes/glass-light/variants/blush-pink.json +1 -1
  179. package/themes/glass-light/variants/blush-plum.json +1 -1
  180. package/themes/glass-light/variants/cream-violet.json +1 -1
  181. package/themes/glass-light/variants/frost-sky-suit.json +1 -1
  182. package/themes/glass-light/variants/frost-sky.json +1 -1
  183. package/themes/glass-light/variants/sage-green.json +1 -1
  184. package/themes/ink-wash/sample/style.json +3 -3
  185. package/themes/ink-wash/style.json +3 -3
  186. package/themes/ink-wash/theme.json +3 -1
  187. package/themes/iso-diorama/sample/style.json +1 -1
  188. package/themes/iso-diorama/style.json +1 -1
  189. package/themes/iso-diorama/theme.json +3 -1
  190. package/themes/iso-diorama/variants/chalk-plum.json +1 -1
  191. package/themes/iso-diorama/variants/cocoa-indigo.json +1 -1
  192. package/themes/iso-diorama/variants/dusk-blue.json +1 -1
  193. package/themes/iso-diorama/variants/dusk-coral.json +1 -1
  194. package/themes/iso-diorama/variants/dusk-jade.json +1 -1
  195. package/themes/iso-diorama/variants/forest-cyan.json +1 -1
  196. package/themes/iso-diorama/variants/frost-green.json +1 -1
  197. package/themes/iso-diorama/variants/frost-teal.json +1 -1
  198. package/themes/iso-diorama/variants/navy-amber.json +1 -1
  199. package/themes/isotype/sample/style.json +2 -2
  200. package/themes/isotype/style.json +2 -2
  201. package/themes/isotype/theme.json +2 -1
  202. package/themes/isotype/variants/blush-rose.json +1 -1
  203. package/themes/isotype/variants/chalk-coral.json +1 -1
  204. package/themes/isotype/variants/chalk-orange.json +1 -1
  205. package/themes/isotype/variants/frost-amber.json +1 -1
  206. package/themes/isotype/variants/frost-coral.json +1 -1
  207. package/themes/isotype/variants/frost-orange.json +1 -1
  208. package/themes/isotype/variants/sand-amber.json +1 -1
  209. package/themes/kawaii-sticker/effects.ts +15 -3
  210. package/themes/kawaii-sticker/sample/style.json +2 -2
  211. package/themes/kawaii-sticker/style.json +2 -2
  212. package/themes/kawaii-sticker/theme.json +4 -1
  213. package/themes/kawaii-sticker/variants/cream-gold.json +1 -1
  214. package/themes/kawaii-sticker/variants/dusk-green.json +1 -1
  215. package/themes/kawaii-sticker/variants/dusk-indigo.json +1 -1
  216. package/themes/kawaii-sticker/variants/dusk-sky.json +1 -1
  217. package/themes/kawaii-sticker/variants/dusk-teal.json +1 -1
  218. package/themes/kawaii-sticker/variants/frost-blue.json +1 -1
  219. package/themes/kawaii-sticker/variants/frost-plum.json +1 -1
  220. package/themes/kawaii-sticker/variants/lilac-violet.json +1 -1
  221. package/themes/kawaii-sticker/variants/navy-gold.json +1 -1
  222. package/themes/kawaii-sticker/variants/navy-plum.json +1 -1
  223. package/themes/lab-notebook/sample/style.json +3 -3
  224. package/themes/lab-notebook/style.json +3 -3
  225. package/themes/lab-notebook/theme.json +2 -1
  226. package/themes/lab-notebook/variants/blush-orange.json +1 -1
  227. package/themes/lab-notebook/variants/chalk-coral.json +1 -1
  228. package/themes/lab-notebook/variants/chalk-orange.json +1 -1
  229. package/themes/lab-notebook/variants/chalk-rose.json +1 -1
  230. package/themes/lab-notebook/variants/lilac-rose.json +1 -1
  231. package/themes/lab-notebook/variants/sage-rose.json +1 -1
  232. package/themes/lab-notebook/variants/sand-orange.json +1 -1
  233. package/themes/lab-notebook/variants/snow-orange.json +1 -1
  234. package/themes/lab-notebook/variants/snow-rose.json +1 -1
  235. package/themes/manga-panel/sample/style.json +3 -3
  236. package/themes/manga-panel/style.json +3 -3
  237. package/themes/manga-panel/theme.json +3 -1
  238. package/themes/manga-panel/variants/chalk-cyan-dots.json +1 -1
  239. package/themes/manga-panel/variants/chalk-rose.json +1 -1
  240. package/themes/manga-panel/variants/snow-cyan.json +1 -1
  241. package/themes/manga-panel/variants/snow-magenta-dots.json +1 -1
  242. package/themes/marble-run/sample/style.json +2 -2
  243. package/themes/marble-run/style.json +2 -2
  244. package/themes/marble-run/theme.json +3 -1
  245. package/themes/marble-run/variants/slate-orange.json +1 -1
  246. package/themes/neon-sign/sample/style.json +2 -2
  247. package/themes/neon-sign/style.json +2 -2
  248. package/themes/neon-sign/theme.json +2 -1
  249. package/themes/neon-sign/variants/dusk-plum.json +1 -1
  250. package/themes/neon-sign/variants/forest-magenta.json +1 -1
  251. package/themes/neon-sign/variants/night-pink.json +1 -1
  252. package/themes/neon-sign/variants/night-violet.json +1 -1
  253. package/themes/neon-sign/variants/slate-violet.json +1 -1
  254. package/themes/newspaper/sample/style.json +2 -2
  255. package/themes/newspaper/style.json +2 -2
  256. package/themes/newspaper/theme.json +2 -1
  257. package/themes/newspaper/variants/blush-amber.json +1 -1
  258. package/themes/newspaper/variants/chalk-magenta.json +1 -1
  259. package/themes/newspaper/variants/frost-sky.json +1 -1
  260. package/themes/newspaper/variants/lilac-green.json +1 -1
  261. package/themes/newspaper/variants/sage-lime.json +1 -1
  262. package/themes/og-measure/THEME.md +41 -6
  263. package/themes/og-measure/effects.ts +236 -115
  264. package/themes/og-measure/sample/assets/brand/og-logo.svg +11 -11
  265. package/themes/og-measure/sample/lib/data.ts +6 -0
  266. package/themes/og-measure/sample/scenes/end.ts +14 -10
  267. package/themes/og-measure/sample/scenes/gather.ts +4 -1
  268. package/themes/og-measure/sample/scenes/models.ts +5 -2
  269. package/themes/og-measure/sample/scenes/one.ts +9 -6
  270. package/themes/og-measure/sample/scenes/price.ts +8 -3
  271. package/themes/og-measure/sample/style.json +30 -35
  272. package/themes/og-measure/slots.ts +54 -30
  273. package/themes/og-measure/still.png +0 -0
  274. package/themes/og-measure/style.json +30 -35
  275. package/themes/og-measure/theme.json +72 -49
  276. package/themes/og-measure/variants/snow-blue.json +90 -0
  277. package/themes/orbit-system/sample/style.json +3 -3
  278. package/themes/orbit-system/style.json +3 -3
  279. package/themes/orbit-system/theme.json +3 -1
  280. package/themes/orbit-system/variants/cocoa-amber.json +1 -1
  281. package/themes/orbit-system/variants/cocoa-cyan.json +1 -1
  282. package/themes/orbit-system/variants/dusk-magenta.json +1 -1
  283. package/themes/orbit-system/variants/dusk-violet.json +1 -1
  284. package/themes/orbit-system/variants/forest-coral.json +1 -1
  285. package/themes/orbit-system/variants/wine-amber.json +1 -1
  286. package/themes/orbit-system/variants/wine-magenta.json +1 -1
  287. package/themes/origami-fold/sample/style.json +1 -1
  288. package/themes/origami-fold/style.json +1 -1
  289. package/themes/origami-fold/theme.json +3 -1
  290. package/themes/origami-fold/variants/deep-amber-sunflower.json +1 -1
  291. package/themes/origami-fold/variants/deep-orange.json +1 -1
  292. package/themes/origami-fold/variants/forest-coral.json +1 -1
  293. package/themes/origami-fold/variants/forest-pink.json +1 -1
  294. package/themes/origami-fold/variants/frost-amber-paper.json +1 -1
  295. package/themes/origami-fold/variants/sage-coral-sunflower.json +1 -1
  296. package/themes/origami-fold/variants/sage-coral.json +1 -1
  297. package/themes/origami-fold/variants/sage-pink-round.json +1 -1
  298. package/themes/origami-fold/variants/sage-pink.json +1 -1
  299. package/themes/paper-cutout/sample/style.json +2 -2
  300. package/themes/paper-cutout/style.json +2 -2
  301. package/themes/paper-cutout/theme.json +3 -1
  302. package/themes/paper-cutout/variants/blush-violet.json +1 -1
  303. package/themes/paper-cutout/variants/frost-lime.json +1 -1
  304. package/themes/paper-cutout/variants/lilac-gold.json +1 -1
  305. package/themes/paper-cutout/variants/sage-cyan.json +1 -1
  306. package/themes/paper-cutout/variants/sage-green.json +1 -1
  307. package/themes/paper-cutout/variants/sage-pink.json +1 -1
  308. package/themes/paper-cutout/variants/sand-blue.json +1 -1
  309. package/themes/pixel-quest/theme.json +2 -1
  310. package/themes/receipt/sample/style.json +2 -2
  311. package/themes/receipt/style.json +2 -2
  312. package/themes/riso-zine/sample/style.json +2 -2
  313. package/themes/riso-zine/style.json +2 -2
  314. package/themes/riso-zine/theme.json +3 -1
  315. package/themes/riso-zine/variants/chalk-lime.json +1 -1
  316. package/themes/riso-zine/variants/frost-green.json +1 -1
  317. package/themes/riso-zine/variants/lilac-plum.json +1 -1
  318. package/themes/riso-zine/variants/lilac-violet.json +1 -1
  319. package/themes/server-hall/sample/style.json +2 -2
  320. package/themes/server-hall/style.json +2 -2
  321. package/themes/server-hall/theme.json +3 -1
  322. package/themes/server-hall/variants/night-indigo.json +1 -1
  323. package/themes/server-hall/variants/wine-plum.json +1 -1
  324. package/themes/subway-map/sample/style.json +2 -2
  325. package/themes/subway-map/style.json +2 -2
  326. package/themes/subway-map/theme.json +3 -1
  327. package/themes/subway-map/variants/deep-green.json +1 -1
  328. package/themes/subway-map/variants/deep-teal.json +1 -1
  329. package/themes/subway-map/variants/frost-jade.json +1 -1
  330. package/themes/subway-map/variants/frost-teal.json +1 -1
  331. package/themes/subway-map/variants/slate-green.json +1 -1
  332. package/themes/subway-map/variants/snow-jade.json +1 -1
  333. package/themes/swiss-poster/sample/style.json +2 -2
  334. package/themes/swiss-poster/style.json +2 -2
  335. package/themes/swiss-poster/theme.json +3 -1
  336. package/themes/swiss-poster/variants/chalk-plum.json +1 -1
  337. package/themes/swiss-poster/variants/cocoa-cyan.json +1 -1
  338. package/themes/swiss-poster/variants/dusk-magenta.json +1 -1
  339. package/themes/swiss-poster/variants/frost-indigo.json +1 -1
  340. package/themes/swiss-poster/variants/slate-orange.json +1 -1
  341. package/themes/water-works/sample/style.json +1 -1
  342. package/themes/water-works/style.json +1 -1
  343. package/themes/water-works/theme.json +3 -1
  344. package/themes/water-works/variants/chalk-cyan.json +1 -1
  345. package/themes/water-works/variants/frost-indigo.json +1 -1
  346. package/themes/water-works/variants/sand-amber.json +1 -1
  347. package/themes/water-works/variants/sand-plum.json +1 -1
  348. package/themes/whiteboard/sample/style.json +2 -2
  349. package/themes/whiteboard/style.json +2 -2
  350. package/themes/whiteboard/theme.json +3 -1
  351. package/themes/whiteboard/variants/chalk-coral.json +1 -1
  352. package/themes/whiteboard/variants/cream-lime.json +1 -1
  353. package/themes/whiteboard/variants/frost-teal.json +1 -1
  354. package/themes/whiteboard/variants/lilac-indigo.json +1 -1
  355. package/themes/whiteboard/variants/sage-plum.json +1 -1
  356. package/themes/whiteboard/variants/snow-cyan.json +1 -1
  357. package/themes/whiteboard/variants/snow-green.json +1 -1
  358. package/themes/whiteboard/variants/snow-magenta.json +1 -1
  359. package/themes/og-measure/sample/assets/brand/og-logo-full.svg +0 -12
  360. package/themes/og-measure/variants/chalk-orange.json +0 -102
  361. package/themes/og-measure/variants/cocoa-amber.json +0 -138
  362. package/themes/og-measure/variants/cocoa-cyan.json +0 -138
  363. package/themes/og-measure/variants/cocoa-gold.json +0 -129
  364. package/themes/og-measure/variants/cream-lime.json +0 -137
  365. package/themes/og-measure/variants/deep-jade.json +0 -100
  366. package/themes/og-measure/variants/dusk-violet.json +0 -133
  367. package/themes/og-measure/variants/forest-cyan.json +0 -123
  368. package/themes/og-measure/variants/frost-amber.json +0 -129
  369. package/themes/og-measure/variants/frost-cyan.json +0 -133
  370. package/themes/og-measure/variants/lilac-plum.json +0 -127
  371. package/themes/og-measure/variants/lilac-violet.json +0 -139
  372. package/themes/og-measure/variants/sage-green.json +0 -137
  373. package/themes/og-measure/variants/wine-jade.json +0 -127
  374. package/themes/og-measure/variants/wine-plum.json +0 -127
@@ -1,5 +1,5 @@
1
1
  /// <reference types="vite/client" />
2
- // 페이지(Vite) 쪽. 장면 문법 패턴은 테마 이름을 모른다 — 일반 자리 여섯을 부르고, 테마가 themes/<id>/slots.ts 에서 자기 효과로 채운다.
2
+ // 페이지(Vite) 쪽. 장면 문법 패턴은 테마 이름을 모른다 — 일반 자리 일곱을 부르고, 테마가 themes/<id>/slots.ts 에서 자기 효과로 채운다.
3
3
  // effects.ts 와 따로 두는 까닭: effects.ts 내보내기는 theme.json 효과 목록과 같아야 한다(테마 시험).
4
4
  import type { SceneCtx, Style } from "@kasaframe/core";
5
5
  import type { DropBurstState } from "@kasaframe/motion";
@@ -7,6 +7,31 @@ import { worldOf } from "./name.ts";
7
7
 
8
8
  export type Paint = (t: number) => void;
9
9
 
10
+ /** 짚는 칸 자리 — 칸을 깔 상자(왼쪽 위·크기, 패턴이 정한 좌표 px) */
11
+ export interface MarkBox {
12
+ x: number;
13
+ y: number;
14
+ w: number;
15
+ h: number;
16
+ }
17
+
18
+ export interface MarkPaint {
19
+ /** 칸이 덮은 글의 색 — 비우면 글색을 그대로 둔다(칸이 옅게 글 뒤에 깔리는 테마) */
20
+ ink?: string;
21
+ /**
22
+ * 짚기 방식 — true 면 장면의 요점(주인공·그 순간 목소리가 말하는 값)에 내려앉아 머물고 다음 요점에서만 옮긴다. 비우면 박 정지점마다
23
+ * 주인공과 나머지를 번갈아 훑는다(내용이 다 선 뒤 쉬지 않는 몫을 짚개가 진다). 머무는 테마는 쉬는 구간을 멈춤 기준(theme.json
24
+ * motion.maxFreezeSec)과 내용 움직임으로 감당해야 한다
25
+ */
26
+ dwell?: boolean;
27
+ /**
28
+ * u(0..1)만큼 간 칸 자리 — from 칸(앞 요점)에서 to 칸(새 요점)으로 옮겨 가는 중. from 이 null 이면 to 자리에 처음 나타나는 중.
29
+ * u 는 옮김 동안 고르게 흐르고 u=1 이면 to 그대로 — 머무는 짚개(dwell)는 0.3초 안팎에 옮겨 다음 요점까지 서고, 훑는 짚개는 박 정지점 사이를 내내 옮긴다.
30
+ * 감속·모양 바꿈(높이·칠 짙기)은 테마 몫이고 el 칠을 그 크기에 맞춰 바꿔도 된다
31
+ */
32
+ at(from: MarkBox | null, to: MarkBox, u: number): MarkBox;
33
+ }
34
+
10
35
  /**
11
36
  * 모든 슬롯은 같은 t 면 같은 화면이고, 난수는 seed 로만. 비운 슬롯은 패턴이 제 기본으로 그린다.
12
37
  * 화면 전체를 덮는 3D(three)는 surface 에서만 — 크롬이 WebGL 문맥을 몇 개만 살려 두므로 나머지 슬롯은 DOM·캔버스 2D 로.
@@ -33,9 +58,14 @@ export interface ThemeSlots {
33
58
  trace?(el: HTMLElement, o: { ctx: SceneCtx; points: readonly (readonly [number, number])[]; at: number; dur: number; seed: string; tone?: "base" | "accent" }): Paint;
34
59
  /** 드롭 터짐 — 그 테마의 드롭 연출. 돌려준 shake 는 패턴이 화면 틀에, punch 는 주인공에 준다. 드롭 번호로만 */
35
60
  drop?(el: HTMLElement, o: { ctx: SceneCtx; drop: number }): (t: number) => DropBurstState;
61
+ /**
62
+ * 짚음 — 패턴이 「지금 볼 것」(장면의 요점·목소리가 말하는 값)을 짚는 칸(짚개·반전 짚음)의 모양. el = 패턴이 지은 빈 칸(position:absolute, 글 뒤에 깔린다).
63
+ * 칸 칠(바탕·테두리·모서리)은 여기서 하고, 자리·크기는 패턴이 프레임마다 돌려받은 at 으로 준다. 비우면 강조색 꽉 찬 칸 + onAccent 글
64
+ */
65
+ mark?(el: HTMLElement, o: { ctx: SceneCtx; seed: string }): MarkPaint;
36
66
  }
37
67
 
38
- export const SLOT_NAMES = ["surface", "panel", "land", "write", "trace", "drop"] as const satisfies readonly (keyof ThemeSlots)[];
68
+ export const SLOT_NAMES = ["surface", "panel", "land", "write", "trace", "drop", "mark"] as const satisfies readonly (keyof ThemeSlots)[];
39
69
 
40
70
  const mods = import.meta.glob("../../../themes/*/slots.ts", { eager: true }) as Record<string, { slots?: ThemeSlots }>;
41
71
 
@@ -29,6 +29,13 @@ export interface ThemeManifest {
29
29
  purposes: string[];
30
30
  /** 견본이 서는 화면비. 앞이 견본의 화면비 */
31
31
  aspect: string[];
32
+ /** 장면 사이 전환 허용 목록 — 덮기(none·fade·brushWipe·irisBlades·flood)와 이음매(dive·portal·… · gl:<이름>) 이름. 없으면 다 허용, 모르는 이름은 허용 안 한 것과 같다 */
33
+ transitions?: string[];
34
+ /**
35
+ * 검사 기준 — maxFreezeSec 은 멈춤 오류 기준(초). 실제 오류 기준은 틀·style.json 값과 이것 중 큰 쪽이라 테마는 늘리기만 하고,
36
+ * 경고는 틀·style.json 값 그대로 남는다(core freezeLimits). 화면을 살려 두려고 칸을 돌리지 않고 쉬는 구간을 두는 세계가 쓴다
37
+ */
38
+ motion?: { maxFreezeSec?: number };
32
39
  effects: ThemeEffectInfo[];
33
40
  /** 테마 폴더 기준 파일 이름. 기본 still.png · sample.mp4 */
34
41
  still?: string;
@@ -37,6 +44,27 @@ export interface ThemeManifest {
37
44
  vary?: ThemeVary;
38
45
  /** 고르기 태그 — 분위기·밝기·용도·2D/3D */
39
46
  tags?: ThemeTags;
47
+ /** 효과음 결 — 없으면 기본 결(ui)·기본 크기 */
48
+ sfx?: ThemeSfx;
49
+ }
50
+
51
+ /**
52
+ * theme.json sfx — 그 세계가 내는 소리 결. 렌더가 장면 움직임에서 뽑은 소리 자리에 이 결의 파일을 깐다(레포 sfx/<set>/<역할>.wav).
53
+ * kf.json sfx 가 칸마다 덮고, kf.json sfx: false 나 kf render --sfx off 면 끈다
54
+ */
55
+ export interface ThemeSfx {
56
+ /** 소리 결 — sfx/tags.json 의 sets 이름(pop 뽁·통 · click 딸깍·째깍 · ui 기본) */
57
+ set: string;
58
+ /** 둘레 곡(소리 자리 앞뒤 0.2초) 크기 대비 dB — 0 이면 곡과 비슷하게. 역할마다 렌더의 역할 크기(드롭 +2 · 째깍 -4 …)를 더한다 */
59
+ db?: number;
60
+ /** 1초에 몇 개까지(2초 창으로 센다 — 0.5 면 2초에 하나) — 넘으면 드롭·끝·휙·착지… 차례로 남긴다 */
61
+ perSec?: number;
62
+ /** 이 역할만 낸다 — 없으면 다 */
63
+ only?: string[];
64
+ /** 잔소리(낱낱이 나타남·숫자 째깍·타자)도 낸다 — 기본은 장면 바뀜·드롭·주인공 착지·짚개가 핵심 값에 닿는 순간만 */
65
+ chatter?: boolean;
66
+ /** 소리마다 곡을 이만큼(dB, 기본 3) 100ms 남짓 눌러 자리를 낸다 */
67
+ duck?: number;
40
68
  }
41
69
 
42
70
  export type TextureKind = "none" | "grain" | "paper" | "noise" | "scan" | "halftone";
@@ -57,6 +85,11 @@ export interface ThemeVary {
57
85
  keep?: string[];
58
86
  /** 색상은 두고 명도·채도만 따라가는 색 열쇠(풀·물 같은 재료 색) */
59
87
  fixedHue?: string[];
88
+ /**
89
+ * 밝기마다 세계가 정해 둔 색 한 벌 — 브랜드가 라이트·다크를 따로 정한 세계(두 벌이 서로 거울상이 아니라 뒤집어 옮기면 정본 값이 안 나온다).
90
+ * 그 밝기 판은 이 벌을 원점으로 삼고, 안 적은 축(바탕 빛깔·글 명도·강조 색상)은 그 벌 값 그대로. 열쇠는 style.json colors 와 같다
91
+ */
92
+ palettes?: Partial<Record<"light" | "dark", Record<string, string>>>;
60
93
  /** 글꼴 짝 id(packages/themes/kit/fonts.json)·`tag:<태그>`·`base`(세계 글꼴) */
61
94
  fonts?: string[];
62
95
  /** 세 글꼴 스택을 짝의 고정폭 하나로(한 글꼴 HUD) — 그러면 monoAll 짝만 받는다 */
@@ -1,34 +1,16 @@
1
1
  // 변주 — 세계 하나에서 겉모습만 바꾼 판을 데이터로 뽑는다(SPEC 9 변주). 코드는 세계 것을 그대로 쓰고, 여기서는 style 위에 덮을 판만 짓는다.
2
- import { readFileSync } from "node:fs";
3
- import { fileURLToPath } from "node:url";
4
2
  import { rand, randRange, type KfStyle } from "@kasaframe/core";
5
3
  import { hueDist, labOf, parseColor } from "./color.ts";
4
+ import { type FontPair, fontPairs, titleWeight } from "./fonts.ts";
6
5
  import { lchOf, NEUTRAL_C, transformPalette } from "./palette.ts";
7
6
  import type { TextureKind, ThemeManifest, ThemeTags, ThemeVary, VariantManifest, VariantParams } from "./types.ts";
8
7
 
9
- export interface FontPair {
10
- id: string;
11
- name: string;
12
- ko: string;
13
- tags: string[];
14
- sans: string;
15
- display: string;
16
- mono: string;
17
- faces: NonNullable<KfStyle["fonts"]["faces"]>;
18
- weightDisplay: number;
19
- weightBody: number;
20
- tracking: string;
21
- monoAll?: boolean;
22
- }
23
-
24
- let pairs: FontPair[] | null = null;
25
- export const fontPairs = (): FontPair[] => (pairs ??= JSON.parse(readFileSync(fileURLToPath(new URL("../kit/fonts.json", import.meta.url)), "utf8")));
26
-
27
8
  /** 세계가 허락한 글꼴 짝 — 「base」는 세계 글꼴 그대로 */
28
9
  export function allowedFonts(vary: ThemeVary): string[] {
29
10
  const all = fontPairs().filter((p) => !vary.monoAll || p.monoAll);
30
11
  const want = vary.fonts ?? ["base"];
31
- const ids = want.flatMap((w) => (w === "base" ? ["base"] : w.startsWith("tag:") ? all.filter((p) => p.tags.includes(w.slice(4))).map((p) => p.id) : all.some((p) => p.id === w) ? [w] : []));
12
+ // tag:sans+geometric 은 두 태그를 다 가진 짝 — 짝이 수백이라 태그 하나로는 결이 다른 무리까지 딸려 온다
13
+ const ids = want.flatMap((w) => (w === "base" ? ["base"] : w.startsWith("tag:") ? all.filter((p) => w.slice(4).split("+").every((t) => p.tags.includes(t))).map((p) => p.id) : all.some((p) => p.id === w) ? [w] : []));
32
14
  return [...new Set(ids)];
33
15
  }
34
16
 
@@ -71,28 +53,40 @@ function sampleHue(seed: string, i: number, ranges: [number, number][]): number
71
53
  return ranges[0][0];
72
54
  }
73
55
 
56
+ /** 그 밝기의 원점 색 — 세계가 밝기마다 한 벌을 정해 뒀으면(vary.palettes) 그 벌, 세계 자신의 밝기면 세계 색. 안 정한 세계는 null(세계 색을 옮긴다) */
57
+ export function paletteOf(style: KfStyle, vary: ThemeVary, scheme: "light" | "dark"): KfStyle["colors"] | null {
58
+ if (!vary.palettes) return null;
59
+ if (scheme === style.scheme) return style.colors;
60
+ return (vary.palettes[scheme] as KfStyle["colors"] | undefined) ?? null;
61
+ }
62
+
74
63
  /** 손잡이 값 하나 — 세계가 안 받는 축은 세계 값 */
75
64
  export function sampleParams(style: KfStyle, vary: ThemeVary, seed: string, n: number): VariantParams {
76
65
  const base = baseParams(style);
77
66
  const r = (k: number, lo: number, hi: number) => randRange(seed, n * 32 + k, lo, hi);
78
67
  const pickOf = <T>(k: number, items: readonly T[]): T => items[Math.min(items.length - 1, Math.floor(rand(seed, n * 32 + k) * items.length))];
79
68
  const scheme = pickOf(0, vary.scheme ?? [style.scheme]);
80
- const bgR = vary.bg?.[scheme] ?? BG_L[scheme];
81
- const hue = vary.hue ? sampleHue(seed, n * 32 + 1, vary.hue) : base.hue;
69
+ const own = paletteOf(style, vary, scheme);
70
+ const origin = own ? baseParams({ ...style, scheme, colors: own }) : null;
71
+ const bgR = vary.bg?.[scheme] ?? (origin ? [origin.bgL, origin.bgL] : BG_L[scheme]);
72
+ const hue = vary.hue ? sampleHue(seed, n * 32 + 1, vary.hue) : (origin ?? base).hue;
82
73
  // 무채색 빛깔은 반쯤은 강조색 쪽(한 집안), 반쯤은 아무 쪽
83
74
  const tintH = rand(seed, n * 32 + 2) < 0.5 ? (hue + r(3, -30, 30) + 360) % 360 : r(4, 0, 360);
84
75
  const tex = pickOf(5, vary.texture ?? [base.texture.kind]);
85
76
  const chroma = vary.chroma ? r(10, vary.chroma[0], vary.chroma[1]) : 1;
86
77
  // 바탕이 색 잉크인 세계는 바탕이 강조색과 같은 각도로 돌아야 모눈·선과 한 벌로 남는다 — tint 축은 무채색 바탕 세계 것
87
- const tint = base.tint.c >= NEUTRAL_C
88
- ? { h: (base.tint.h + hue - base.hue + 360) % 360, c: base.tint.c * chroma }
89
- : { h: tintH, c: vary.tint ? r(7, vary.tint[0], vary.tint[1]) * (scheme === "dark" ? DARK_TINT : 1) : base.tint.c };
78
+ // 정해 둔 벌이 있으면 바탕 빛깔·글 명도는 그 벌의 것 — 브랜드 무채색(푸른 회색)에 아무 빛깔이나 얹지 않는다
79
+ const tint = origin && !vary.tint
80
+ ? origin.tint
81
+ : base.tint.c >= NEUTRAL_C
82
+ ? { h: (base.tint.h + hue - base.hue + 360) % 360, c: base.tint.c * chroma }
83
+ : { h: tintH, c: vary.tint ? r(7, vary.tint[0], vary.tint[1]) * (scheme === "dark" ? DARK_TINT : 1) : base.tint.c };
90
84
  const q = (v: number) => +v.toFixed(4);
91
85
  return {
92
86
  scheme,
93
87
  bgL: q(r(6, bgR[0], bgR[1])),
94
88
  tint: { h: q(tint.h), c: q(tint.c) },
95
- inkL: q(scheme === style.scheme && rand(seed, n * 32 + 8) < 0.5 ? base.inkL : r(9, INK_L[scheme][0], INK_L[scheme][1])),
89
+ inkL: q(origin ? origin.inkL : scheme === style.scheme && rand(seed, n * 32 + 8) < 0.5 ? base.inkL : r(9, INK_L[scheme][0], INK_L[scheme][1])),
96
90
  hue: q(hue),
97
91
  chroma: q(chroma),
98
92
  fonts: pickOf(11, allowedFonts(vary)),
@@ -107,13 +101,15 @@ export function sampleParams(style: KfStyle, vary: ThemeVary, seed: string, n: n
107
101
  /** 손잡이 값 → 세계 style 위에 덮을 판. 색이 검사를 못 넘으면 bad 에 까닭 */
108
102
  export function overlayOf(style: KfStyle, manifest: Pick<ThemeManifest, "vary">, p: VariantParams): { style: VariantManifest["style"]; bad: string[]; measured: Record<string, number> } {
109
103
  const vary = manifest.vary ?? {};
110
- const pal = transformPalette(style.colors, p, { keep: vary.keep, fixedHue: vary.fixedHue });
104
+ const pal = transformPalette(paletteOf(style, vary, p.scheme) ?? style.colors, p, { keep: vary.keep, fixedHue: vary.fixedHue });
111
105
  const out: VariantManifest["style"] = { scheme: p.scheme, colors: pal.colors as KfStyle["colors"] };
112
106
  if (p.fonts !== "base") {
113
107
  const f = fontPairs().find((x) => x.id === p.fonts);
114
108
  if (!f) return { style: out, bad: [`글꼴 짝 ${p.fonts} 이 없다`], measured: pal.measured };
115
- out.fonts = vary.monoAll ? { sans: f.mono, display: f.mono, mono: f.mono, faces: f.faces } : { sans: f.sans, display: f.display, mono: f.mono, faces: f.faces };
116
- out.type = { weightDisplay: f.weightDisplay, weightBody: f.weightBody, tracking: f.tracking };
109
+ // 라이선스·출처는 짝 목록의 것 — style.json 의 face 는 core 계약(family·src·weight) 그대로
110
+ const faces = f.faces.map(({ license: _l, source: _s, ...face }) => face);
111
+ out.fonts = vary.monoAll ? { sans: f.mono, display: f.mono, mono: f.mono, faces } : { sans: f.sans, display: f.display, mono: f.mono, faces };
112
+ out.type = { weightDisplay: titleWeight(f, vary.monoAll), weightBody: f.weightBody, tracking: f.tracking };
117
113
  }
118
114
  if (p.radius !== null) {
119
115
  const md0 = style.radius.md || 12;
@@ -265,6 +261,14 @@ export function nameVariant(params: VariantParams, taken: Set<string>, colors?:
265
261
  return { id, name, desc };
266
262
  }
267
263
 
264
+ // 글꼴 짝 태그 → 변주 분위기 낱말. kf theme suggest 가 요청 낱말을 이 낱말과도 견준다
265
+ const FONT_MOOD: [string, string][] = [
266
+ ["serif", "고전적"], ["classic", "고전적"], ["elegant", "우아한"], ["traditional", "전통"], ["brush", "붓글씨"], ["newspaper", "신문"],
267
+ ["rounded", "귀여운"], ["playful", "발랄한"], ["comic", "만화"], ["hand", "손글씨"], ["pixel", "레트로"], ["retro", "레트로"],
268
+ ["mono", "기술적"], ["tech", "기술적"], ["futuristic", "미래적"], ["modern", "모던"], ["industrial", "산업"], ["signage", "안내판"],
269
+ ["calm", "차분한"], ["strong", "강한"], ["neon", "네온"],
270
+ ];
271
+
268
272
  /** 변주 태그 — 세계 태그에 색·질감·글꼴이 주는 분위기를 더한다 */
269
273
  export function variantTags(world: ThemeTags, params: VariantParams, colors?: Record<string, string>): ThemeTags {
270
274
  const p = seen(params, colors);
@@ -277,10 +281,7 @@ export function variantTags(world: ThemeTags, params: VariantParams, colors?: Re
277
281
  if (["paper", "grain", "halftone", "noise"].includes(p.texture.kind)) mood.add("아날로그");
278
282
  if (p.texture.kind === "scan") mood.add("레트로");
279
283
  const tags = fontPairs().find((x) => x.id === p.fonts)?.tags ?? [];
280
- if (tags.includes("serif")) mood.add("고전적");
281
- if (tags.includes("rounded")) mood.add("귀여운");
282
- if (tags.includes("pixel")) mood.add("레트로");
283
- if (tags.includes("mono")) mood.add("기술적");
284
+ for (const [tag, word] of FONT_MOOD) if (tags.includes(tag)) mood.add(word);
284
285
  return { ...world, mood: [...mood], light: p.scheme };
285
286
  }
286
287
 
@@ -35,12 +35,12 @@
35
35
  },
36
36
  {
37
37
  "family": "JetBrains Mono",
38
- "src": "https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5/files/jetbrains-mono-latin-wght-normal.woff2",
38
+ "src": "https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5.3.0/files/jetbrains-mono-latin-wght-normal.woff2",
39
39
  "weight": "100 800"
40
40
  },
41
41
  {
42
42
  "family": "Jua",
43
- "src": "https://cdn.jsdelivr.net/gh/google/fonts@main/ofl/jua/Jua-Regular.ttf",
43
+ "src": "https://cdn.jsdelivr.net/gh/google/fonts@bd8f81ddb5c74d5c8897b36ad88b440266245103/ofl/jua/Jua-Regular.ttf",
44
44
  "weight": "400"
45
45
  }
46
46
  ]
package/sfx/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # 효과음 — 렌더가 장면 움직임 자리에 까는 짧은 소리
2
+
3
+ 곡·목소리 위 세 번째 층. 장면 코드를 안 고쳐도 라이브러리 부품이 움직임이 시작하는 순간을 `__kf.events` 에 `sfx` 로 남기고(`@kasaframe/core` `cue`), `kf render` 가 **뜻 있는 자리만** 적게 골라 테마가 고른 **결**의 파일을 둘레 곡과 비슷한 크기로 깔고, 그 순간 곡을 짧게 눌러 자리를 낸다. 곡과 달리 npm 묶음에 실린다(전부 CC0).
4
+
5
+ - 결(`sets`)마다 역할 하나에 파일 하나 — `sfx/<결>/<역할>.wav`(48kHz 모노 16비트, 꼭대기 -1dBFS). 원본·겹친 소리·라이선스·`lead`(파일 시작 → 꼭대기 초)·`level`(100ms 창 RMS 최댓값 dBFS — 섞을 때 크기를 맞추는 기준)는 `tags.json`.
6
+ - **곡에 안 묻히는 건 2–6kHz 다.** 600–2000Hz 에 몸이 있는 소리는 6dB 키워도 곡 아래였다(렌더 보고서의 가려짐). 그래서 몸이 낮은 소리(뽁·통·쿵)는 그 대역의 짧은 어택을 꼭대기에 맞춰 겹쳐 짓는다(아래 표의 `+`).
7
+ - 테마가 결과 크기를 고른다 — `theme.json` 의 `sfx: { set, db, perSec, only, chatter, duck }`. 없으면 `ui` 결·둘레 곡 -2dB·1초 1개·잔소리 없음·곡 3dB 누름. 프로젝트 `kf.json` 의 `sfx` 가 칸마다 덮고, `sfx: false` 나 `kf render|make --sfx off` 면 끈다(끄면 소리는 효과음 이전과 바이트까지 같다).
8
+ - 다른 폴더를 쓰려면 `KF_SFX_DIR=<폴더>` — 그 폴더에도 같은 꼴의 `tags.json`.
9
+ - 다시 짓기: Kenney 묶음 zip 여섯(`https://kenney.nl/assets/<ui-audio|interface-sounds|impact-sounds|digital-audio|rpg-audio|casino-audio>`)을 한 폴더에 풀고 `node tools/sfx/build.ts --src <그 폴더>`. 묶음마다 `License.txt` 에서 CC0 를 확인하고 없으면 멈춘다.
10
+
11
+ ## 결
12
+
13
+ | 결 | 소리 | 쓰는 세계 |
14
+ |---|---|---|
15
+ | `pop` | 물방울 뽁·나무 통·둥근 쿵에 또렷한 톡 어택 | kawaii-sticker(둘레 곡과 같은 크기, 1초에 하나까지) |
16
+ | `click` | 역할마다 작은 스위치·시계 소리만(전부 2–6kHz) | og-measure(딸깍·째깍만, 둘레 곡 -4dB, 2초에 하나까지) |
17
+ | `ui` | 가벼운 UI 소리 — 퉁김·휙·주먹 쿵에 또렷한 어택 | 결을 안 고른 세계 |
18
+
19
+ ## 역할 — 누가 저절로 남기나
20
+
21
+ 기본으로 까는 것은 뜻 있는 자리 — 장면 바뀜·드롭·주인공 착지·짚개가 요점에 닿는 순간. 부품이 잔소리(`minor`)로 남긴 것(표의 「잔소리」)은 `chatter: true` 일 때만 깐다.
22
+
23
+ | 역할 | 뜻 | 저절로 남기는 부품 |
24
+ |---|---|---|
25
+ | `appear` | 나타남 | 잔소리 — motion `enter`(rise·scaleIn·maskWipe·slide, fade·blurIn 은 소리 없이) · 패턴 판(panel) · og-measure 칸이 서는 순간 |
26
+ | `stick` | 톡 붙기 | kawaii 주인공 스티커(폭 400px 넘는 것 — 작은 이름표는 잔소리) · `stickOn` · 잔소리 — motion `enter("pop")` |
27
+ | `land` | 착지 | 패턴 `land` 슬롯·`slam`·숫자 굴림이 앉을 때 · og-measure 숫자 꽂힘 · 잔소리 — motion `enter("drop")` |
28
+ | `hop` | 통 뛰기 | 잔소리 — kawaii 스티커 `hops` |
29
+ | `whoosh` | 휙 전환 | 이음매(`transition3d` — 화면이 여럿이면 넘어갈 때마다) · `transition`(whip·zoomThrough·slide) · 컷 카메라(shotCam·trackCam) · 잔소리 — 떼어짐·테이프 |
30
+ | `tick` | 숫자 째깍 | 잔소리 — 패턴 숫자 굴림·카운터 · og-measure 계기판·점 |
31
+ | `select` | 짚기 딸깍 | 패턴 짚개가 요점으로 옮겨 갈 때 · og-measure 읽는 칸이 새 값에 닿을 때 |
32
+ | `type` | 타자 | 잔소리 — 패턴 `write` 슬롯(0.09초마다) · og-measure 로그 줄 |
33
+ | `drop` | 드롭 쿵 | motion `dropBurst`(slap·패턴 drop 슬롯) · beats.json 드롭 |
34
+ | `burst` | 팡 터짐 | kawaii `stickerBurst` |
35
+ | `end` | 끝 마무리 | og-measure 끝 도장 |
36
+
37
+ 손으로 지은 움직임은 장면에서 `ctx.sfx("<역할>", 장면 초)` — 잔소리로 치지 않는다.
38
+
39
+ ## 섞기
40
+
41
+ - 밀도: 같은 역할은 0.1초 안에 하나, 아무 소리끼리 0.25초 띄우고, 아무 2초 창에 `perSec`×2 개(적어도 하나)까지. 넘치면 드롭 > 끝 > 휙 > 착지 > 붙기·팡 > 뛰기 > 짚기 > 나타남 > 째깍 > 타자 차례로 남기고, 드롭 앞뒤 0.35초는 드롭만.
42
+ - 크기: 둘레 곡(소리 자리 앞뒤 0.2초) 크기 + `db` + 역할 크기(드롭 +2 … 째깍·타자 -4), 목소리가 있으면 4dB 더 낮게. 역할마다 저역을 걷는다(드롭 60Hz·그 밖 150–300Hz — 킥·베이스와 안 겹치게).
43
+ - 자리 내기: 소리마다 곡을 `duck` dB(기본 3) 소리 시작 10ms 앞부터 꼭대기 100ms 뒤까지 누른다.
44
+ - 가려짐: 소리가 차지하는 대역(제 가장 센 대역에서 10dB 안쪽) 가운데 곡을 가장 넘는 대역에서, 소리 순간(꼭대기 앞 10ms·뒤 90ms) 효과음 ÷ 눌린 곡이 4dB 가 안 되면 6dB 까지 더 키운다. 렌더 보고서 `sfx.hits` 에 소리마다 `band`·`smr`·`boost`·`over`(넓은 대역 크기 − 둘레 곡).
45
+
46
+ <!-- 파일 표 — tools/sfx/build.ts 가 짓는다 -->
47
+
48
+ | 파일 | 역할 | 길이 | 원본 | 라이선스 |
49
+ |---|---|---|---|---|
50
+ | `pop/appear.wav` | 나타남 | 0.15초 | Kenney Interface Sounds (1.0) — `drop_004.ogg` + Kenney Interface Sounds (1.0) — `select_001.ogg`(-6dB) | CC0 1.0 |
51
+ | `pop/stick.wav` | 톡 붙기 | 0.15초 | Kenney Interface Sounds (1.0) — `drop_002.ogg` + Kenney Interface Sounds (1.0) — `tick_004.ogg`(-4dB) | CC0 1.0 |
52
+ | `pop/land.wav` | 착지 | 0.12초 | Kenney Impact Sounds (1.0) — `impactWood_light_000.ogg` + Kenney Casino Audio (1.1) — `chip-lay-1.ogg`(-4dB) | CC0 1.0 |
53
+ | `pop/hop.wav` | 통 뛰기 | 0.30초 | Kenney Digital Audio — `phaseJump1.ogg` + Kenney UI SFX Set — `click5.ogg`(-6dB) | CC0 1.0 |
54
+ | `pop/whoosh.wav` | 휙 전환 | 0.25초 | Kenney Interface Sounds (1.0) — `maximize_002.ogg` | CC0 1.0 |
55
+ | `pop/tick.wav` | 숫자 째깍 | 0.02초 | Kenney Interface Sounds (1.0) — `tick_002.ogg` | CC0 1.0 |
56
+ | `pop/select.wav` | 짚기 딸깍 | 0.04초 | Kenney Interface Sounds (1.0) — `select_001.ogg` | CC0 1.0 |
57
+ | `pop/type.wav` | 타자 | 0.03초 | Kenney UI SFX Set — `click5.ogg` | CC0 1.0 |
58
+ | `pop/drop.wav` | 드롭 쿵 | 0.52초 | Kenney Impact Sounds (1.0) — `impactSoft_heavy_000.ogg` + Kenney Impact Sounds (1.0) — `impactMetal_light_000.ogg`(-3dB) | CC0 1.0 |
59
+ | `pop/burst.wav` | 팡 터짐 | 0.19초 | Kenney Digital Audio — `powerUp2.ogg` + Kenney Casino Audio (1.1) — `chips-collide-1.ogg`(-4dB) | CC0 1.0 |
60
+ | `pop/end.wav` | 끝 마무리 | 0.32초 | Kenney Interface Sounds (1.0) — `confirmation_003.ogg` | CC0 1.0 |
61
+ | `click/appear.wav` | 나타남 | 0.09초 | Kenney UI SFX Set — `click1.ogg` | CC0 1.0 |
62
+ | `click/stick.wav` | 톡 붙기 | 0.01초 | Kenney Interface Sounds (1.0) — `click_003.ogg` | CC0 1.0 |
63
+ | `click/land.wav` | 착지 | 0.14초 | Kenney Interface Sounds (1.0) — `switch_001.ogg` | CC0 1.0 |
64
+ | `click/hop.wav` | 통 뛰기 | 0.06초 | Kenney Interface Sounds (1.0) — `toggle_004.ogg` | CC0 1.0 |
65
+ | `click/whoosh.wav` | 휙 전환 | 0.22초 | Kenney Interface Sounds (1.0) — `scroll_004.ogg` | CC0 1.0 |
66
+ | `click/tick.wav` | 숫자 째깍 | 0.02초 | Kenney Interface Sounds (1.0) — `tick_001.ogg` | CC0 1.0 |
67
+ | `click/select.wav` | 짚기 딸깍 | 0.04초 | Kenney Interface Sounds (1.0) — `select_001.ogg` | CC0 1.0 |
68
+ | `click/type.wav` | 타자 | 0.05초 | Kenney UI SFX Set — `switch12.ogg` | CC0 1.0 |
69
+ | `click/drop.wav` | 드롭 쿵 | 0.21초 | Kenney RPG Audio — `metalLatch.ogg` | CC0 1.0 |
70
+ | `click/burst.wav` | 팡 터짐 | 0.13초 | Kenney Casino Audio (1.1) — `chip-lay-1.ogg` | CC0 1.0 |
71
+ | `click/end.wav` | 끝 마무리 | 0.11초 | Kenney Interface Sounds (1.0) — `toggle_002.ogg` | CC0 1.0 |
72
+ | `ui/appear.wav` | 나타남 | 0.13초 | Kenney Interface Sounds (1.0) — `pluck_001.ogg` + Kenney Interface Sounds (1.0) — `tick_004.ogg`(-6dB) | CC0 1.0 |
73
+ | `ui/stick.wav` | 톡 붙기 | 0.15초 | Kenney Interface Sounds (1.0) — `drop_001.ogg` + Kenney Interface Sounds (1.0) — `tick_004.ogg`(-6dB) | CC0 1.0 |
74
+ | `ui/land.wav` | 착지 | 0.15초 | Kenney Impact Sounds (1.0) — `impactGeneric_light_000.ogg` + Kenney Casino Audio (1.1) — `chip-lay-1.ogg`(-4dB) | CC0 1.0 |
75
+ | `ui/hop.wav` | 통 뛰기 | 0.14초 | Kenney Interface Sounds (1.0) — `pluck_002.ogg` + Kenney UI SFX Set — `click5.ogg`(-6dB) | CC0 1.0 |
76
+ | `ui/whoosh.wav` | 휙 전환 | 0.25초 | Kenney Interface Sounds (1.0) — `maximize_001.ogg` | CC0 1.0 |
77
+ | `ui/tick.wav` | 숫자 째깍 | 0.01초 | Kenney Interface Sounds (1.0) — `click_003.ogg` | CC0 1.0 |
78
+ | `ui/select.wav` | 짚기 딸깍 | 0.23초 | Kenney Interface Sounds (1.0) — `select_003.ogg` | CC0 1.0 |
79
+ | `ui/type.wav` | 타자 | 0.03초 | Kenney UI SFX Set — `click5.ogg` | CC0 1.0 |
80
+ | `ui/drop.wav` | 드롭 쿵 | 0.45초 | Kenney Impact Sounds (1.0) — `impactPunch_heavy_000.ogg` + Kenney Impact Sounds (1.0) — `impactMetal_light_000.ogg`(-3dB) | CC0 1.0 |
81
+ | `ui/burst.wav` | 팡 터짐 | 0.16초 | Kenney Casino Audio (1.1) — `chips-collide-1.ogg` | CC0 1.0 |
82
+ | `ui/end.wav` | 끝 마무리 | 0.14초 | Kenney Interface Sounds (1.0) — `switch_001.ogg` | CC0 1.0 |
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file