kasaframe 0.0.0-stage → 0.1.3

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 (442) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +148 -0
  3. package/README.md +92 -2
  4. package/app/package.json +12 -0
  5. package/app/server/engine.ts +533 -0
  6. package/app/server/main.ts +209 -0
  7. package/app/web/env.d.ts +2 -0
  8. package/app/web/icons.ts +31 -0
  9. package/app/web/index.html +21 -0
  10. package/app/web/main.ts +1195 -0
  11. package/app/web/style.css +463 -0
  12. package/bin/hooks.mjs +64 -0
  13. package/bin/kf.mjs +32 -0
  14. package/docs/AGENTS.md +286 -0
  15. package/music/README.md +37 -0
  16. package/package.json +44 -4
  17. package/packages/adapters/package.json +36 -0
  18. package/packages/adapters/src/css.ts +11 -0
  19. package/packages/adapters/src/gsap.ts +26 -0
  20. package/packages/adapters/src/index.ts +9 -0
  21. package/packages/adapters/src/lottie.ts +22 -0
  22. package/packages/adapters/src/media.ts +59 -0
  23. package/packages/adapters/src/page.ts +229 -0
  24. package/packages/adapters/src/project.ts +214 -0
  25. package/packages/adapters/src/react.ts +36 -0
  26. package/packages/adapters/src/svelte.ts +22 -0
  27. package/packages/adapters/src/three.ts +18 -0
  28. package/packages/adapters/src/vue.ts +27 -0
  29. package/packages/check/package.json +19 -0
  30. package/packages/check/src/check.ts +280 -0
  31. package/packages/check/src/cli.ts +70 -0
  32. package/packages/check/src/image.ts +146 -0
  33. package/packages/check/src/index.ts +9 -0
  34. package/packages/check/src/ocr.swift +37 -0
  35. package/packages/check/src/probe.ts +328 -0
  36. package/packages/check/src/report.ts +44 -0
  37. package/packages/check/src/rules/assets.ts +45 -0
  38. package/packages/check/src/rules/beats.ts +212 -0
  39. package/packages/check/src/rules/camera.ts +217 -0
  40. package/packages/check/src/rules/captions.ts +49 -0
  41. package/packages/check/src/rules/flash.ts +235 -0
  42. package/packages/check/src/rules/frames.ts +136 -0
  43. package/packages/check/src/rules/layout.ts +281 -0
  44. package/packages/check/src/rules/page.ts +87 -0
  45. package/packages/check/src/rules/runs.ts +20 -0
  46. package/packages/check/src/rules/text.ts +326 -0
  47. package/packages/check/src/scan.ts +240 -0
  48. package/packages/check/src/serve.ts +67 -0
  49. package/packages/check/src/types.ts +80 -0
  50. package/packages/check/src/video.ts +137 -0
  51. package/packages/cli/package.json +30 -0
  52. package/packages/cli/src/blur.ts +80 -0
  53. package/packages/cli/src/browser.ts +203 -0
  54. package/packages/cli/src/command.ts +44 -0
  55. package/packages/cli/src/commands/app.ts +25 -0
  56. package/packages/cli/src/commands/beats.ts +36 -0
  57. package/packages/cli/src/commands/bench.ts +123 -0
  58. package/packages/cli/src/commands/blender.ts +293 -0
  59. package/packages/cli/src/commands/check.ts +25 -0
  60. package/packages/cli/src/commands/direct.ts +210 -0
  61. package/packages/cli/src/commands/doctor.ts +30 -0
  62. package/packages/cli/src/commands/gen.ts +173 -0
  63. package/packages/cli/src/commands/look.ts +46 -0
  64. package/packages/cli/src/commands/lyrics.ts +157 -0
  65. package/packages/cli/src/commands/make.ts +1121 -0
  66. package/packages/cli/src/commands/music.ts +78 -0
  67. package/packages/cli/src/commands/narrate.ts +238 -0
  68. package/packages/cli/src/commands/new.ts +185 -0
  69. package/packages/cli/src/commands/preview.ts +43 -0
  70. package/packages/cli/src/commands/render.ts +250 -0
  71. package/packages/cli/src/commands/series.ts +110 -0
  72. package/packages/cli/src/commands/setup.ts +102 -0
  73. package/packages/cli/src/commands/sheet.ts +114 -0
  74. package/packages/cli/src/commands/skill.ts +43 -0
  75. package/packages/cli/src/commands/still.ts +40 -0
  76. package/packages/cli/src/commands/theme.ts +172 -0
  77. package/packages/cli/src/commands/transitions.ts +40 -0
  78. package/packages/cli/src/deps.ts +122 -0
  79. package/packages/cli/src/ffmpeg.ts +81 -0
  80. package/packages/cli/src/index.ts +8 -0
  81. package/packages/cli/src/kf.ts +64 -0
  82. package/packages/cli/src/lock.ts +72 -0
  83. package/packages/cli/src/mix.ts +131 -0
  84. package/packages/cli/src/out.ts +13 -0
  85. package/packages/cli/src/pool.ts +34 -0
  86. package/packages/cli/src/segments.ts +402 -0
  87. package/packages/cli/src/serve.ts +124 -0
  88. package/packages/clock/package.json +14 -0
  89. package/packages/clock/src/index.ts +25 -0
  90. package/packages/clock/src/install.ts +351 -0
  91. package/packages/clock/src/types.ts +45 -0
  92. package/packages/core/package.json +9 -0
  93. package/packages/core/src/beats.ts +283 -0
  94. package/packages/core/src/ease.ts +87 -0
  95. package/packages/core/src/frame.ts +99 -0
  96. package/packages/core/src/index.ts +27 -0
  97. package/packages/core/src/project.ts +157 -0
  98. package/packages/core/src/rand.ts +56 -0
  99. package/packages/core/src/spring.ts +52 -0
  100. package/packages/core/src/style.ts +100 -0
  101. package/packages/core/src/time.ts +88 -0
  102. package/packages/director/package.json +23 -0
  103. package/packages/director/src/assemble.ts +361 -0
  104. package/packages/director/src/brief.ts +122 -0
  105. package/packages/director/src/catalog.ts +49 -0
  106. package/packages/director/src/content.ts +343 -0
  107. package/packages/director/src/fallback.ts +58 -0
  108. package/packages/director/src/index.ts +13 -0
  109. package/packages/director/src/pattern.ts +90 -0
  110. package/packages/director/src/patterns/fill/cells.ts +115 -0
  111. package/packages/director/src/patterns/formula/stack.ts +93 -0
  112. package/packages/director/src/patterns/util.ts +58 -0
  113. package/packages/director/src/scene.ts +62 -0
  114. package/packages/director/src/select.ts +163 -0
  115. package/packages/director/src/transitions.ts +115 -0
  116. package/packages/gen/PROVIDERS.md +90 -0
  117. package/packages/gen/package.json +9 -0
  118. package/packages/gen/src/ask.ts +132 -0
  119. package/packages/gen/src/audio.ts +91 -0
  120. package/packages/gen/src/blender.ts +54 -0
  121. package/packages/gen/src/capabilities.ts +151 -0
  122. package/packages/gen/src/generate.ts +206 -0
  123. package/packages/gen/src/image/codex.ts +117 -0
  124. package/packages/gen/src/image/og.ts +133 -0
  125. package/packages/gen/src/index.ts +26 -0
  126. package/packages/gen/src/keys.ts +86 -0
  127. package/packages/gen/src/media.ts +150 -0
  128. package/packages/gen/src/music/elevenlabs.ts +41 -0
  129. package/packages/gen/src/music/index.ts +120 -0
  130. package/packages/gen/src/music/library.ts +73 -0
  131. package/packages/gen/src/music/lyria.ts +52 -0
  132. package/packages/gen/src/music/types.ts +28 -0
  133. package/packages/gen/src/plan.ts +106 -0
  134. package/packages/gen/src/registry.ts +54 -0
  135. package/packages/gen/src/seam.ts +103 -0
  136. package/packages/gen/src/tts/dashscope.ts +64 -0
  137. package/packages/gen/src/tts/elevenlabs.ts +84 -0
  138. package/packages/gen/src/tts/gemini.ts +73 -0
  139. package/packages/gen/src/tts/index.ts +241 -0
  140. package/packages/gen/src/tts/local.ts +42 -0
  141. package/packages/gen/src/tts/types.ts +44 -0
  142. package/packages/gen/src/types.ts +90 -0
  143. package/packages/gen/src/video/fal.ts +140 -0
  144. package/packages/gen/src/video/h3.ts +112 -0
  145. package/packages/gen/src/video/http.ts +44 -0
  146. package/packages/gen/src/video/ltx.ts +60 -0
  147. package/packages/gen/src/video/minimax.ts +55 -0
  148. package/packages/gen/src/video/veo.ts +71 -0
  149. package/packages/jizura/package.json +16 -0
  150. package/packages/jizura/src/deny.ts +73 -0
  151. package/packages/jizura/src/index.ts +7 -0
  152. package/packages/jizura/src/install.ts +269 -0
  153. package/packages/jizura/src/layer.ts +325 -0
  154. package/packages/jizura/src/lyrics.ts +81 -0
  155. package/packages/jizura/src/pin.ts +8 -0
  156. package/packages/jizura/src/vendor.ts +140 -0
  157. package/packages/jizura/src/vite.ts +63 -0
  158. package/packages/jizura/vendor/JIZURA_LICENSE.txt +21 -0
  159. package/packages/jizura/vendor/NOTICE +43 -0
  160. package/packages/jizura/vendor/engine.json +47 -0
  161. package/packages/jizura/vendor/fonts/BlackHanSans-Regular.woff2 +0 -0
  162. package/packages/jizura/vendor/fonts/DotGothic16-Regular.woff2 +0 -0
  163. package/packages/jizura/vendor/fonts/GowunBatang-Bold.woff2 +0 -0
  164. package/packages/jizura/vendor/fonts/IBMPlexMono-Medium.ttf +0 -0
  165. package/packages/jizura/vendor/fonts/IBMPlexMono-SemiBold.ttf +0 -0
  166. package/packages/jizura/vendor/fonts/NotoSansKR-VF.woff2 +0 -0
  167. package/packages/jizura/vendor/fonts/NotoSerifKR-VF.woff2 +0 -0
  168. package/packages/jizura/vendor/fonts/OFL-blackhansans.txt +93 -0
  169. package/packages/jizura/vendor/fonts/OFL-dotgothic16.txt +93 -0
  170. package/packages/jizura/vendor/fonts/OFL-gowunbatang.txt +94 -0
  171. package/packages/jizura/vendor/fonts/OFL-ibmplexmono.txt +93 -0
  172. package/packages/jizura/vendor/fonts/OFL-notosanskr.txt +93 -0
  173. package/packages/jizura/vendor/fonts/OFL-notoserifkr.txt +94 -0
  174. package/packages/jizura/vendor/fonts/fonts.json +52 -0
  175. package/packages/jizura/vendor/jizura_engine.js +35024 -0
  176. package/packages/motion/README.md +153 -0
  177. package/packages/motion/package.json +30 -0
  178. package/packages/motion/src/camera.ts +97 -0
  179. package/packages/motion/src/captions.ts +487 -0
  180. package/packages/motion/src/enter.ts +128 -0
  181. package/packages/motion/src/hangul.ts +129 -0
  182. package/packages/motion/src/impact.ts +100 -0
  183. package/packages/motion/src/index.ts +17 -0
  184. package/packages/motion/src/moves/brushWipe.ts +103 -0
  185. package/packages/motion/src/moves/cloneArray.ts +111 -0
  186. package/packages/motion/src/moves/curtains.ts +81 -0
  187. package/packages/motion/src/moves/dress.ts +191 -0
  188. package/packages/motion/src/moves/echoStack.ts +70 -0
  189. package/packages/motion/src/moves/fit.ts +70 -0
  190. package/packages/motion/src/moves/flood.ts +61 -0
  191. package/packages/motion/src/moves/ghostStack.ts +88 -0
  192. package/packages/motion/src/moves/gridFloor.ts +100 -0
  193. package/packages/motion/src/moves/imageSwarm.ts +113 -0
  194. package/packages/motion/src/moves/index.ts +38 -0
  195. package/packages/motion/src/moves/irisBlades.ts +113 -0
  196. package/packages/motion/src/moves/karaokeLine.ts +108 -0
  197. package/packages/motion/src/moves/ledBoard.ts +94 -0
  198. package/packages/motion/src/moves/liquidTab.ts +72 -0
  199. package/packages/motion/src/moves/markerWrite.ts +63 -0
  200. package/packages/motion/src/moves/menu.ts +138 -0
  201. package/packages/motion/src/moves/morphBox.ts +96 -0
  202. package/packages/motion/src/moves/neonSign.ts +78 -0
  203. package/packages/motion/src/moves/panelPop.ts +78 -0
  204. package/packages/motion/src/moves/paperTear.ts +75 -0
  205. package/packages/motion/src/moves/path.ts +64 -0
  206. package/packages/motion/src/moves/pathText.ts +107 -0
  207. package/packages/motion/src/moves/pointSphere.ts +109 -0
  208. package/packages/motion/src/moves/ransomLetters.ts +73 -0
  209. package/packages/motion/src/moves/shapeMorph.ts +143 -0
  210. package/packages/motion/src/moves/slamWords.ts +96 -0
  211. package/packages/motion/src/moves/sparkTrail.ts +130 -0
  212. package/packages/motion/src/moves/speedLines.ts +91 -0
  213. package/packages/motion/src/moves/splitFlap.ts +149 -0
  214. package/packages/motion/src/moves/stepWords.ts +128 -0
  215. package/packages/motion/src/moves/strikeOut.ts +98 -0
  216. package/packages/motion/src/moves/sunburst.ts +58 -0
  217. package/packages/motion/src/moves/tickerRows.ts +91 -0
  218. package/packages/motion/src/moves/tokenPicker.ts +115 -0
  219. package/packages/motion/src/moves/truchet.ts +85 -0
  220. package/packages/motion/src/moves/wordWall.ts +78 -0
  221. package/packages/motion/src/moves/worldRoll.ts +32 -0
  222. package/packages/motion/src/particles.ts +102 -0
  223. package/packages/motion/src/react/index.tsx +21 -0
  224. package/packages/motion/src/react/parts.tsx +431 -0
  225. package/packages/motion/src/react/time.tsx +97 -0
  226. package/packages/motion/src/text.ts +103 -0
  227. package/packages/motion/src/transition.ts +82 -0
  228. package/packages/motion/src/transition3d/cards.ts +65 -0
  229. package/packages/motion/src/transition3d/chain.ts +84 -0
  230. package/packages/motion/src/transition3d/dive.ts +181 -0
  231. package/packages/motion/src/transition3d/fold.ts +110 -0
  232. package/packages/motion/src/transition3d/gl.ts +219 -0
  233. package/packages/motion/src/transition3d/index.ts +235 -0
  234. package/packages/motion/src/transition3d/live.ts +70 -0
  235. package/packages/motion/src/transition3d/portal.ts +115 -0
  236. package/packages/motion/src/transition3d/react.tsx +29 -0
  237. package/packages/motion/src/transition3d/rig.ts +600 -0
  238. package/packages/motion/src/transition3d/shatter.ts +104 -0
  239. package/packages/motion/src/transition3d/space.ts +173 -0
  240. package/packages/motion/src/transition3d/whip.ts +78 -0
  241. package/packages/motion/src/transition3d/world.ts +737 -0
  242. package/packages/motion/src/transition3d/zoomOut.ts +114 -0
  243. package/packages/motion/src/transitions2d/catalog.ts +127 -0
  244. package/packages/motion/src/transitions2d/css.d.ts +2 -0
  245. package/packages/motion/src/transitions2d/cult-ui/LICENSE.md +9 -0
  246. package/packages/motion/src/transitions2d/cult-ui/RollingNumber.tsx +43 -0
  247. package/packages/motion/src/transitions2d/gl-transitions/LICENSE +25 -0
  248. package/packages/motion/src/transitions2d/gl-transitions/shaders.ts +1931 -0
  249. package/packages/motion/src/transitions2d/index.ts +2 -0
  250. package/packages/motion/src/transitions2d/kokonutui/LICENSE +21 -0
  251. package/packages/motion/src/transitions2d/kokonutui/MatrixText.css +16 -0
  252. package/packages/motion/src/transitions2d/kokonutui/MatrixText.tsx +94 -0
  253. package/packages/motion/src/transitions2d/magicui/HyperText.css +15 -0
  254. package/packages/motion/src/transitions2d/magicui/HyperText.tsx +115 -0
  255. package/packages/motion/src/transitions2d/magicui/LICENSE.md +21 -0
  256. package/packages/motion/src/transitions2d/magicui/MorphingText.css +25 -0
  257. package/packages/motion/src/transitions2d/magicui/MorphingText.tsx +130 -0
  258. package/packages/motion/src/transitions2d/magicui/WordRotate.tsx +42 -0
  259. package/packages/motion/src/transitions2d/react.ts +13 -0
  260. package/packages/motion/src/transitions2d/skiper-ui/ClipDiv.css +39 -0
  261. package/packages/motion/src/transitions2d/skiper-ui/ClipDiv.tsx +32 -0
  262. package/packages/motion/src/transitions2d/smoothui/LICENSE +21 -0
  263. package/packages/motion/src/transitions2d/smoothui/SharedAxisY.tsx +50 -0
  264. package/packages/motion/src/transitions2d/smoothui/TextMorph.tsx +90 -0
  265. package/packages/motion/src/transitions2d/smoothui/shaders.ts +223 -0
  266. package/packages/motion/src/transitions2d/unlumen/LICENSE +21 -0
  267. package/packages/motion/src/transitions2d/unlumen/ScrambleText.tsx +114 -0
  268. package/packages/motion/src/transitions2d/vengeance-ui/LICENSE +21 -0
  269. package/packages/motion/src/transitions2d/vengeance-ui/MorphText.css +69 -0
  270. package/packages/motion/src/transitions2d/vengeance-ui/MorphText.tsx +45 -0
  271. package/packages/motion/src/type.ts +131 -0
  272. package/packages/motion/src/ui.ts +172 -0
  273. package/packages/patterns/package.json +15 -0
  274. package/packages/patterns/src/bars/rank.ts +119 -0
  275. package/packages/patterns/src/before-after/shrink.ts +127 -0
  276. package/packages/patterns/src/before-after/strike.ts +125 -0
  277. package/packages/patterns/src/code/terminal.ts +133 -0
  278. package/packages/patterns/src/compare/bars.ts +142 -0
  279. package/packages/patterns/src/compare/duel.ts +103 -0
  280. package/packages/patterns/src/end/lockup.ts +85 -0
  281. package/packages/patterns/src/end/slam.ts +91 -0
  282. package/packages/patterns/src/flow/graph.ts +250 -0
  283. package/packages/patterns/src/hook-number/counter.ts +101 -0
  284. package/packages/patterns/src/hook-number/roll.ts +179 -0
  285. package/packages/patterns/src/hook-number/slam.ts +91 -0
  286. package/packages/patterns/src/index.ts +38 -0
  287. package/packages/patterns/src/kit.ts +449 -0
  288. package/packages/patterns/src/limit/gauge.ts +117 -0
  289. package/packages/patterns/src/list/cards.ts +131 -0
  290. package/packages/patterns/src/list/cycle.ts +22 -0
  291. package/packages/patterns/src/media/panels.ts +100 -0
  292. package/packages/patterns/src/objects.ts +234 -0
  293. package/packages/patterns/src/quote/karaoke.ts +126 -0
  294. package/packages/patterns/src/quote/slam.ts +22 -0
  295. package/packages/patterns/src/screen/focus.ts +85 -0
  296. package/packages/patterns/src/steps/path.ts +137 -0
  297. package/packages/patterns/src/steps/stack.ts +111 -0
  298. package/packages/patterns/src/term-reveal/chips.ts +92 -0
  299. package/packages/patterns/src/term-reveal/expand.ts +127 -0
  300. package/packages/patterns/src/timeline/axis.ts +144 -0
  301. package/packages/patterns/src/title/mask.ts +85 -0
  302. package/packages/patterns/src/title/slam.ts +23 -0
  303. package/packages/patterns/src/toggle-sim/switch.ts +92 -0
  304. package/packages/patterns/src/trend/columns.ts +108 -0
  305. package/packages/patterns/src/trend/draw.ts +140 -0
  306. package/packages/patterns/src/types.ts +67 -0
  307. package/packages/patterns/src/words/moves.ts +42 -0
  308. package/packages/patterns/src/words/slam.ts +4 -0
  309. package/packages/plan/package.json +15 -0
  310. package/packages/plan/src/asks.ts +256 -0
  311. package/packages/plan/src/brief.ts +383 -0
  312. package/packages/plan/src/captions.ts +78 -0
  313. package/packages/plan/src/detect.ts +93 -0
  314. package/packages/plan/src/index.ts +27 -0
  315. package/packages/plan/src/layout.ts +176 -0
  316. package/packages/plan/src/llm.ts +172 -0
  317. package/packages/plan/src/look.ts +222 -0
  318. package/packages/plan/src/plan.ts +179 -0
  319. package/packages/plan/src/request.ts +55 -0
  320. package/packages/plan/src/series.ts +76 -0
  321. package/packages/plan/src/studio.ts +53 -0
  322. package/packages/plan/src/templates.ts +42 -0
  323. package/packages/plan/src/themes.ts +48 -0
  324. package/packages/plan/src/types.ts +157 -0
  325. package/packages/studio/package.json +12 -0
  326. package/packages/studio/src/index.ts +1 -0
  327. package/packages/studio/src/plugin.ts +236 -0
  328. package/packages/studio/src/ui/main.ts +503 -0
  329. package/packages/studio/src/ui/studio.css +165 -0
  330. package/packages/studio/src/ui/timeline.ts +317 -0
  331. package/packages/themes/kit/THEME-MAKE.md +68 -0
  332. package/packages/themes/kit/THEME.md +30 -0
  333. package/packages/themes/kit/briefs/og-intro-15s/brief.json +16 -0
  334. package/packages/themes/kit/briefs/og-intro-15s/facts.ts +29 -0
  335. package/packages/themes/kit/briefs/og-intro-15s/logo.svg +12 -0
  336. package/packages/themes/kit/effects.ts +5 -0
  337. package/packages/themes/kit/sample/index.html +11 -0
  338. package/packages/themes/kit/sample/main.ts +9 -0
  339. package/packages/themes/kit/sample/scenes/scene.ts +15 -0
  340. package/packages/themes/package.json +19 -0
  341. package/packages/themes/src/factory.ts +296 -0
  342. package/packages/themes/src/fx.ts +14 -0
  343. package/packages/themes/src/index.ts +114 -0
  344. package/packages/themes/src/slotkit.ts +79 -0
  345. package/packages/themes/src/slots.ts +46 -0
  346. package/packages/themes/src/stage3d.ts +197 -0
  347. package/packages/themes/src/types.ts +58 -0
  348. package/presets/kawaii-pastel.json +94 -0
  349. package/presets/neutral-dark.json +82 -0
  350. package/presets/og.json +98 -0
  351. package/series/og-shorts.json +14 -0
  352. package/skills/kasaframe/SKILL.md +33 -0
  353. package/templates/_shared/project/index.html +11 -0
  354. package/templates/_shared/project/lib/react.ts +22 -0
  355. package/templates/_shared/project/lib/stage.ts +292 -0
  356. package/templates/_shared/project/main.ts +9 -0
  357. package/templates/_shared/scenes/default.ts +21 -0
  358. package/templates/_shared/scenes/drop.ts +33 -0
  359. package/templates/_shared/scenes/end.ts +26 -0
  360. package/templates/_shared/scenes/hook.ts +18 -0
  361. package/templates/_shared/scenes/seam.ts +41 -0
  362. package/templates/_shared/scenes/step.ts +49 -0
  363. package/templates/ad/preview.png +0 -0
  364. package/templates/ad/template.json +151 -0
  365. package/templates/demo/preview.png +0 -0
  366. package/templates/demo/template.json +141 -0
  367. package/templates/explainer/preview.png +0 -0
  368. package/templates/explainer/template.json +193 -0
  369. package/templates/launch/preview.png +0 -0
  370. package/templates/launch/template.json +163 -0
  371. package/templates/mv/preview.png +0 -0
  372. package/templates/mv/scenes/default.ts +98 -0
  373. package/templates/mv/template.json +178 -0
  374. package/templates/promo/preview.png +0 -0
  375. package/templates/promo/template.json +185 -0
  376. package/templates/shorts/preview.png +0 -0
  377. package/templates/shorts/scenes/hook.ts +37 -0
  378. package/templates/shorts/template.json +196 -0
  379. package/templates/square/preview.png +0 -0
  380. package/templates/square/template.json +133 -0
  381. package/themes/debug-hud/THEME.md +39 -0
  382. package/themes/debug-hud/effects.ts +389 -0
  383. package/themes/debug-hud/sample/assets/og/logo.svg +12 -0
  384. package/themes/debug-hud/sample/beats.json +1 -0
  385. package/themes/debug-hud/sample/index.html +11 -0
  386. package/themes/debug-hud/sample/kf.json +59 -0
  387. package/themes/debug-hud/sample/lib/hudkit.ts +49 -0
  388. package/themes/debug-hud/sample/lib/og.ts +29 -0
  389. package/themes/debug-hud/sample/main.ts +9 -0
  390. package/themes/debug-hud/sample/scenes/end.ts +62 -0
  391. package/themes/debug-hud/sample/scenes/gather.ts +67 -0
  392. package/themes/debug-hud/sample/scenes/models.ts +70 -0
  393. package/themes/debug-hud/sample/scenes/price.ts +79 -0
  394. package/themes/debug-hud/sample/style.json +91 -0
  395. package/themes/debug-hud/slots.ts +99 -0
  396. package/themes/debug-hud/still.png +0 -0
  397. package/themes/debug-hud/style.json +91 -0
  398. package/themes/debug-hud/theme.json +68 -0
  399. package/themes/og-measure/THEME.md +47 -0
  400. package/themes/og-measure/effects.ts +432 -0
  401. package/themes/og-measure/sample/assets/brand/og-logo-full.svg +12 -0
  402. package/themes/og-measure/sample/assets/brand/og-logo.svg +12 -0
  403. package/themes/og-measure/sample/assets/data/measure.json +353 -0
  404. package/themes/og-measure/sample/beats.json +1 -0
  405. package/themes/og-measure/sample/index.html +11 -0
  406. package/themes/og-measure/sample/kf.json +66 -0
  407. package/themes/og-measure/sample/lib/data.ts +62 -0
  408. package/themes/og-measure/sample/main.ts +9 -0
  409. package/themes/og-measure/sample/measure.ts +78 -0
  410. package/themes/og-measure/sample/scenes/end.ts +47 -0
  411. package/themes/og-measure/sample/scenes/gather.ts +51 -0
  412. package/themes/og-measure/sample/scenes/models.ts +34 -0
  413. package/themes/og-measure/sample/scenes/one.ts +39 -0
  414. package/themes/og-measure/sample/scenes/price.ts +56 -0
  415. package/themes/og-measure/sample/style.json +97 -0
  416. package/themes/og-measure/slots.ts +88 -0
  417. package/themes/og-measure/still.png +0 -0
  418. package/themes/og-measure/style.json +97 -0
  419. package/themes/og-measure/theme.json +79 -0
  420. package/themes/riso-zine/THEME.md +43 -0
  421. package/themes/riso-zine/effects.ts +321 -0
  422. package/themes/riso-zine/sample/assets/og/logo.svg +12 -0
  423. package/themes/riso-zine/sample/beats.json +1 -0
  424. package/themes/riso-zine/sample/index.html +11 -0
  425. package/themes/riso-zine/sample/kf.json +59 -0
  426. package/themes/riso-zine/sample/lib/og.ts +29 -0
  427. package/themes/riso-zine/sample/lib/shot.ts +86 -0
  428. package/themes/riso-zine/sample/lib/zine.ts +42 -0
  429. package/themes/riso-zine/sample/main.ts +9 -0
  430. package/themes/riso-zine/sample/scenes/end.ts +61 -0
  431. package/themes/riso-zine/sample/scenes/gather.ts +62 -0
  432. package/themes/riso-zine/sample/scenes/models.ts +52 -0
  433. package/themes/riso-zine/sample/scenes/price.ts +82 -0
  434. package/themes/riso-zine/sample/style.json +99 -0
  435. package/themes/riso-zine/slots.ts +81 -0
  436. package/themes/riso-zine/still.png +0 -0
  437. package/themes/riso-zine/style.json +99 -0
  438. package/themes/riso-zine/theme.json +75 -0
  439. package/tools/beats/beats.py +372 -0
  440. package/tools/beats/requirements.txt +3 -0
  441. package/tools/lyrics/align.py +164 -0
  442. package/tools/lyrics/requirements.txt +9 -0
@@ -0,0 +1,62 @@
1
+ import type { SceneCtx } from "@kasaframe/core";
2
+ import { paperGrain } from "../../effects.ts";
3
+ import { OG } from "../lib/og.ts";
4
+ import { sheets, type Word } from "../lib/shot.ts";
5
+ import { blobs, layer } from "../lib/zine.ts";
6
+
7
+ // 회사 아홉이 흩어진 자리 [x, y, 크기] — 화면을 고르게 덮게 손으로 놓았다
8
+ const SPOT: [number, number, number][] = [
9
+ [100, 90, 170], [900, 140, 130], [1240, 330, 160],
10
+ [180, 420, 160], [720, 470, 190], [1450, 640, 150],
11
+ [120, 760, 130], [640, 800, 130], [1300, 880, 110],
12
+ ];
13
+ const WAVE = [0, 1, 2, 0, 1, 2, 0, 1, 2];
14
+
15
+ export default {
16
+ build(root: HTMLElement, ctx: SceneCtx) {
17
+ const paper = paperGrain(layer(root), { ctx });
18
+ const art = layer(root);
19
+ const names: Word[] = OG.providers.map(([name], i) => ({ text: name, x: SPOT[i][0], y: SPOT[i][1], size: SPOT[i][2] }));
20
+ const cells = OG.providers.map(([name, n], i) => {
21
+ const x = 120 + (i % 3) * 600;
22
+ const y = 80 + Math.floor(i / 3) * 310;
23
+ return { name, n, x, y };
24
+ });
25
+ const pages = sheets(art, ctx, [
26
+ {
27
+ // 박마다 셋씩 흩어져 찍히고 넷째 박에 핑크로 한 번 더
28
+ plates: [
29
+ ...[0, 1, 2].map((k) => ({ beat: k, ink: "blue" as const, words: names.filter((_, i) => WAVE[i] === k) })),
30
+ { beat: 3, ink: "pink", words: names, px: 7 },
31
+ ],
32
+ tones: [{ beat: 1, x: 0, y: 0, w: 1920, h: 1080, ink: "pink", angle: 75, pitch: 20, value: blobs([[0.2, 0.25, 0.22], [0.75, 0.3, 0.18], [0.45, 0.6, 0.2], [0.85, 0.75, 0.2], [0.15, 0.82, 0.16]]) }],
33
+ },
34
+ {
35
+ // 회사별 모델 수 — 줄마다 한 박, 넷째 박에 숫자만 핑크로 겹친다
36
+ plates: [
37
+ ...[0, 1, 2].map((r) => ({
38
+ beat: r,
39
+ ink: "blue" as const,
40
+ words: cells.slice(r * 3, r * 3 + 3).flatMap((c) => [
41
+ { text: String(c.n), x: c.x, y: c.y, size: 210 },
42
+ { text: c.name, x: c.x + 4, y: c.y + 200, size: 48, font: "sans" as const, weight: 800 },
43
+ ]),
44
+ })),
45
+ { beat: 3, ink: "pink", words: cells.map((c) => ({ text: String(c.n), x: c.x, y: c.y, size: 210 })), px: 8 },
46
+ ],
47
+ tones: [{ beat: 0, x: 0, y: 0, w: 1920, h: 1080, ink: "pink", angle: 75, pitch: 14, reveal: "sweep", dir: "down", dur: 1.0, value: (u, v) => {
48
+ const c = cells[Math.min(2, Math.floor(v * 3.48)) * 3 + Math.min(2, Math.floor(u * 3.2))];
49
+ const lu = u * 1920 - c.x;
50
+ const lv = v * 1080 - c.y;
51
+ return lv > 190 && lv < 260 && lu > 0 && lu < (480 * c.n) / 41 ? 0.6 : 0;
52
+ } }],
53
+ },
54
+ ]);
55
+ const mottle = paperGrain(layer(root), { ctx, mode: "mottle" });
56
+ return (t: number) => {
57
+ paper(t);
58
+ for (const p of pages) p(t);
59
+ mottle(t);
60
+ };
61
+ },
62
+ };
@@ -0,0 +1,52 @@
1
+ import type { SceneCtx } from "@kasaframe/core";
2
+ import { paperGrain } from "../../effects.ts";
3
+ import { OG } from "../lib/og.ts";
4
+ import { sheets } from "../lib/shot.ts";
5
+ import { layer, rings } from "../lib/zine.ts";
6
+
7
+ export default {
8
+ build(root: HTMLElement, ctx: SceneCtx) {
9
+ const paper = paperGrain(layer(root), { ctx, seed: "models" });
10
+ const art = layer(root);
11
+ const FULL = { x: 0, y: 0, w: 1920, h: 1080 };
12
+ const pages = sheets(art, ctx, [
13
+ {
14
+ // 한 주소 — 블루 주소, 핑크 띠, 엔드포인트, 핑크 /v1
15
+ plates: [
16
+ { beat: 0, ink: "blue", words: [{ text: "apis.opengateway.ai", size: 150, y: 110 }, { text: "/v1", size: 420, y: 300 }] },
17
+ { beat: 2, ink: "blue", words: OG.endpoints.map((e, i) => ({ text: `POST /v1${e}`, x: 140 + (i % 2) * 860, y: 790 + Math.floor(i / 2) * 80, size: 50, font: "mono" as const, weight: 600 })) },
18
+ { beat: 3, ink: "pink", words: [{ text: "/v1", size: 420, y: 300 }], px: 9 },
19
+ ],
20
+ tones: [{ beat: 1, x: 0, y: 300, w: 1920, h: 440, ink: "pink", angle: 75, pitch: 16, reveal: "sweep", dir: "right", dur: 0.3, value: (u) => ((u * 22) % 1 < 0.5 ? 0.55 : 0.08) }],
21
+ },
22
+ {
23
+ // 같은 주소에 모델만 박마다 바뀐다 — 앞 판은 걷고 새 판을 찍는다
24
+ plates: [
25
+ { beat: 0, ink: "blue", words: [{ text: "POST /v1/chat/completions", size: 52, y: 90, font: "mono", weight: 600 }] },
26
+ ...OG.ids.slice(0, 4).map((id, k) => {
27
+ const [who, model] = id.split("/");
28
+ return { beat: k, until: k + 1, ink: "blue" as const, words: [{ text: who, size: 300, y: 220 }, { text: model, size: 96, y: 620 }] };
29
+ }),
30
+ ...OG.ids.slice(0, 4).map((id, k) => ({ beat: k, until: k + 1, ink: "pink" as const, px: 8, words: [{ text: id.split("/")[0], size: 300, y: 220 }] })),
31
+ ],
32
+ tones: [{ beat: 0, ...FULL, ink: "pink", angle: 75, pitch: 22, value: rings(0.5, 10) }],
33
+ },
34
+ {
35
+ // OpenAI·Anthropic 두 형식 — 두 판이 겹쳐 보라, 드롭 앞 망점이 아래서 차오른다
36
+ plates: [
37
+ { beat: 0, ink: "blue", words: [{ text: "OpenAI", size: 280, x: 130, y: 120 }] },
38
+ { beat: 1, ink: "pink", words: [{ text: "Anthropic", size: 260, x: 220, y: 430 }] },
39
+ { beat: 1, ink: "blue", words: [{ text: "Anthropic", size: 260, x: 220, y: 430 }], px: 6 },
40
+ { beat: 2, ink: "blue", words: [{ text: "/chat/completions /messages", size: 56, y: 800, font: "mono", weight: 600 }] },
41
+ ],
42
+ tones: [{ beat: 3, x: 0, y: 560, w: 1920, h: 480, ink: "pink", angle: 75, pitch: 16, value: (_, v) => 0.06 + 0.85 * v ** 1.4 }],
43
+ },
44
+ ]);
45
+ const mottle = paperGrain(layer(root), { ctx, mode: "mottle", seed: "models-m" });
46
+ return (t: number) => {
47
+ paper(t);
48
+ for (const p of pages) p(t);
49
+ mottle(t);
50
+ };
51
+ },
52
+ };
@@ -0,0 +1,82 @@
1
+ import { applyStyle, type SceneCtx } from "@kasaframe/core";
2
+ import { dropPlate, paperGrain } from "../../effects.ts";
3
+ import { OG } from "../lib/og.ts";
4
+ import { sheets } from "../lib/shot.ts";
5
+ import { layer, rings } from "../lib/zine.ts";
6
+
7
+ // 하루 시계 — 00시가 위, 시계 방향. 00–10시 창은 진하게
8
+ const DIAL = { x: 120, y: 100, w: 880, h: 880 };
9
+ const dial = (u: number, v: number) => {
10
+ const dx = u - 0.5;
11
+ const dy = v - 0.5;
12
+ const d = Math.hypot(dx, dy);
13
+ if (d < 0.3 || d > 0.47) return 0;
14
+ const hour = Math.floor((((Math.atan2(dx, -dy) / (Math.PI * 2)) + 1) % 1) * 24);
15
+ return hour >= OG.night.from && hour < OG.night.to ? 0.9 : 0.22;
16
+ };
17
+ const hourAt = (h: number, r: number): [number, number] => {
18
+ const a = (h / 24) * Math.PI * 2;
19
+ return [DIAL.x + DIAL.w / 2 + Math.sin(a) * r, DIAL.y + DIAL.h / 2 - Math.cos(a) * r];
20
+ };
21
+
22
+ export default {
23
+ build(root: HTMLElement, ctx: SceneCtx) {
24
+ const paper = paperGrain(layer(root), { ctx, seed: "price" });
25
+ const cam = layer(root);
26
+ const FULL = { x: 0, y: 0, w: 1920, h: 1080 };
27
+ const [ds, glm] = [OG.deepseek, OG.glm];
28
+ // 드롭 구간이라 망점이 박마다 부푼다(beatPulse drops-only)
29
+ const pages = sheets(
30
+ cam,
31
+ ctx,
32
+ [
33
+ {
34
+ plates: [
35
+ { beat: 0, ink: "blue", words: [{ text: String(OG.models), size: 760, y: 20 }] },
36
+ { beat: 1, ink: "pink", words: [{ text: String(OG.models), size: 760, y: 20 }], px: 10 },
37
+ { beat: 2, ink: "blue", words: [{ text: "한 주소", size: 150, y: 760 }] },
38
+ { beat: 3, ink: "blue", words: [{ text: OG.host, size: 46, y: 950, font: "mono", weight: 600 }] },
39
+ ],
40
+ tones: [{ beat: 0, ...FULL, ink: "pink", angle: 75, pitch: 22, value: rings(0.5, 12) }],
41
+ },
42
+ {
43
+ plates: [
44
+ {
45
+ beat: 0,
46
+ ink: "blue",
47
+ words: [0, 6, 12, 18].map((h) => {
48
+ const [x, y] = hourAt(h, 470 * 0.88);
49
+ return { text: String(h).padStart(2, "0"), x: x - 40, y: y - 30, size: 60, font: "mono" as const, weight: 700 };
50
+ }),
51
+ },
52
+ { beat: 2, ink: "blue", words: [{ text: "00:00-10:00", size: 120, x: 1060, y: 160 }, { text: OG.night.tz, size: 90, x: 1060, y: 300 }] },
53
+ { beat: 3, ink: "blue", words: [{ text: ds.off, size: 300, x: 1060, y: 520 }] },
54
+ { beat: 3, ink: "pink", words: [{ text: ds.off, size: 300, x: 1060, y: 520 }], px: 9 },
55
+ ],
56
+ tones: [{ beat: 1, ...DIAL, ink: "pink", angle: 75, pitch: 14, value: dial }],
57
+ },
58
+ {
59
+ plates: [
60
+ { beat: 0, ink: "blue", words: [{ text: ds.id, size: 52, x: 120, y: 80, font: "mono", weight: 600 }, { text: "입력", size: 80, x: 120, y: 250, font: "sans", weight: 800 }, { text: ds.input[0], size: 150, x: 330, y: 220 }] },
61
+ { beat: 1, ink: "blue", words: [{ text: ds.input[1], size: 300, x: 960, y: 150 }] },
62
+ { beat: 2, ink: "blue", words: [{ text: "출력", size: 80, x: 120, y: 640, font: "sans", weight: 800 }, { text: ds.output[0], size: 150, x: 330, y: 610 }, { text: ds.output[1], size: 300, x: 960, y: 540 }] },
63
+ { beat: 3, ink: "pink", words: [{ text: ds.input[1], size: 300, x: 960, y: 150 }, { text: ds.output[1], size: 300, x: 960, y: 540 }], px: 8 },
64
+ { beat: 3, ink: "blue", words: [{ text: `${glm.id} ${glm.off}`, size: 48, x: 120, y: 950, font: "mono", weight: 600 }] },
65
+ ],
66
+ // 정가 위에 핑크 줄 — 지운 값
67
+ tones: [{ beat: 1, x: 320, y: 290, w: 560, h: 30, ink: "pink", angle: 75, pitch: 8, reveal: "sweep", dir: "right", dur: 0.15, value: () => 0.9 }, { beat: 2, x: 320, y: 680, w: 560, h: 30, ink: "pink", angle: 75, pitch: 8, reveal: "sweep", dir: "right", dur: 0.15, value: () => 0.9 }],
68
+ },
69
+ ],
70
+ { pulse: true },
71
+ );
72
+ const plate = dropPlate(layer(root), { ctx, drop: 0, origin: [960, 400] });
73
+ const mottle = paperGrain(layer(root), { ctx, mode: "mottle", seed: "price-m" });
74
+ return (t: number) => {
75
+ paper(t);
76
+ for (const p of pages) p(t);
77
+ const s = plate(t);
78
+ applyStyle(cam, s.shake);
79
+ mottle(t);
80
+ };
81
+ },
82
+ };
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "riso-zine",
3
+ "label": "리소 잡지 — 잉크 판을 한 장씩 찍는다",
4
+ "scheme": "light",
5
+ "colors": {
6
+ "bg": "#F2EDE4",
7
+ "surface": "#FAF7F1",
8
+ "raised": "#E9E2D4",
9
+ "line": "#CFC5B3",
10
+ "ink": "#3255A4",
11
+ "inkSoft": "#3255A4",
12
+ "dim": "#5B74B0",
13
+ "accent": "#FF48B0",
14
+ "accentSoft": "#FFB3DA",
15
+ "accentText": "#3255A4",
16
+ "onAccent": "#F2EDE4",
17
+ "success": "#3255A4",
18
+ "danger": "#FF48B0",
19
+ "warning": "#FF48B0",
20
+ "blue": "#3255A4",
21
+ "pink": "#FF48B0",
22
+ "paper": "#F2EDE4"
23
+ },
24
+ "fonts": {
25
+ "sans": "\"Pretendard Variable\", Pretendard, \"Noto Sans KR\", \"Apple SD Gothic Neo\", sans-serif",
26
+ "display": "\"Black Han Sans\", \"Pretendard Variable\", Pretendard, \"Noto Sans KR\", \"Apple SD Gothic Neo\", sans-serif",
27
+ "mono": "\"JetBrains Mono\", ui-monospace, \"SF Mono\", \"Pretendard Variable\", \"Noto Sans KR\", \"Apple SD Gothic Neo\", monospace",
28
+ "faces": [
29
+ {
30
+ "family": "Black Han Sans",
31
+ "src": "https://cdn.jsdelivr.net/gh/google/fonts@main/ofl/blackhansans/BlackHanSans-Regular.ttf",
32
+ "weight": "400"
33
+ },
34
+ {
35
+ "family": "Pretendard Variable",
36
+ "src": "https://cdn.jsdelivr.net/npm/pretendard@1.3.9/dist/web/variable/woff2/PretendardVariable.woff2",
37
+ "weight": "45 920"
38
+ },
39
+ {
40
+ "family": "JetBrains Mono",
41
+ "src": "https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5/files/jetbrains-mono-latin-wght-normal.woff2",
42
+ "weight": "100 800"
43
+ }
44
+ ]
45
+ },
46
+ "type": {
47
+ "hero": 220,
48
+ "title": 110,
49
+ "body": 44,
50
+ "caption": 32,
51
+ "weightDisplay": 400,
52
+ "weightBody": 600,
53
+ "tracking": "-0.01em"
54
+ },
55
+ "radius": {
56
+ "sm": 0,
57
+ "md": 0,
58
+ "lg": 0,
59
+ "pill": 999
60
+ },
61
+ "shadow": {
62
+ "soft": "none",
63
+ "lift": "none"
64
+ },
65
+ "motion": {
66
+ "beatPulse": "drops-only",
67
+ "shake": {
68
+ "on": [
69
+ "drop"
70
+ ],
71
+ "maxPerPhrase": 1,
72
+ "maxPx": 10
73
+ },
74
+ "cameraMove": "off",
75
+ "repeatSameMove": false,
76
+ "maxFreezeSec": 0.5,
77
+ "enter": "fade",
78
+ "ease": "linear",
79
+ "durations": {
80
+ "fast": 0.083,
81
+ "base": 0.25,
82
+ "slow": 0.5
83
+ }
84
+ },
85
+ "theme": {
86
+ "inks": [
87
+ "#F2EDE4 신문 종이",
88
+ "#3255A4 미디엄 블루 판",
89
+ "#FF48B0 형광 핑크 판 — 겹치면 곱하기로 보라"
90
+ ],
91
+ "texture": "종이결(섬유·얼룩)이 초당 8번 바뀌며 끓는다. 판마다 2–4px 어긋남, 망점(각도 블루 15° 핑크 75°), 잉크는 곱하기로 겹친다. 그라데이션은 망점으로만",
92
+ "movement": "초당 12장으로 끊어 움직인다(on twos). 판은 박에서 찍히고, 찍히는 순간 한 장 어긋났다가 제자리 근처로 앉는다. 미끄러지는 보간·흐림 없음"
93
+ },
94
+ "notes": [
95
+ "리소그래프 잉크 이름: Medium Blue #3255A4 · Fluorescent Pink #FF48B0.",
96
+ "핑크 한 판으로 작은 글을 쓰지 않는다(종이 위 2.6:1). 글은 블루 판, 큰 글은 두 판을 겹쳐 보라 테두리가 생기게.",
97
+ "카메라 이동 없음 — 종이는 책상에 놓여 있다."
98
+ ]
99
+ }
@@ -0,0 +1,81 @@
1
+ import { clamp, randRange, spring, type Style } from "@kasaframe/core";
2
+ import type { ThemeSlots } from "@kasaframe/themes/slots";
3
+ import { layer, letters, partial, shownCount, strokePath, traceCanvas } from "@kasaframe/themes/slotkit";
4
+ import { dropPlate, misregister, paperGrain, printFrames } from "./effects.ts";
5
+
6
+ // 장면 문법 패턴이 테마 이름 없이 부르는 자리 — 잉크 판을 한 장씩 찍는 결로. 움직임은 printFrames 로 초당 12장에 끊는다
7
+ export const slots: ThemeSlots = {
8
+ surface(el, { ctx, seed }) {
9
+ return paperGrain(el, { ctx, seed });
10
+ },
11
+
12
+ // 판 두 장 — 블루 테두리 판이 먼저, 핑크 면 판이 한 장 늦게 어긋나 찍힌다. 둘 다 곱하기라 겹친 곳이 보라
13
+ panel(el, { at, seed, tone }) {
14
+ const box = layer(el, "inset:0", true);
15
+ const face = layer(box, `inset:0;mix-blend-mode:multiply;background:${tone === "accent" ? "var(--kf-accent)" : "color-mix(in srgb, var(--kf-accent) 22%, transparent)"}`);
16
+ const edge = layer(box, "inset:0;mix-blend-mode:multiply;border:6px solid var(--kf-ink)");
17
+ const late = at + 1 / 12;
18
+ return (t) => {
19
+ box.style.visibility = t >= at ? "visible" : "hidden";
20
+ edge.style.transform = toTransform(misregister(t, { seed: `${seed}:edge`, px: 3, at }));
21
+ face.style.visibility = t >= late ? "visible" : "hidden";
22
+ face.style.transform = toTransform(misregister(t, { seed: `${seed}:face`, px: 7, at: late }));
23
+ };
24
+ },
25
+
26
+ // 판이 크게 어긋나 찍혔다가 두 장 만에 제자리 — 배율도 초당 12장으로 끊어 내려앉는다
27
+ land(_el, { at, seed }) {
28
+ return (t): Style => {
29
+ if (t < at) return {};
30
+ const q = printFrames(t - at);
31
+ if (q > 0.5) return {};
32
+ const m = misregister(t, { seed, px: 10, at, boil: 0 });
33
+ const k = 1 - clamp(q / 0.5);
34
+ return { x: (m.x ?? 0) * k, y: (m.y ?? 0) * k, scale: spring(q, { from: 1.12, to: 1, stiffness: 300, damping: 18 }) };
35
+ };
36
+ },
37
+
38
+ // 글자가 한 장씩 찍히고, 핑크 판 그림자가 어긋나 비친다(앉은 뒤에도 인쇄 결로 끓는다)
39
+ write(el, { text, at, dur, seed }) {
40
+ const spans = letters(el, text);
41
+ return (t) => {
42
+ const n = shownCount(spans.length, printFrames(t), at, dur);
43
+ spans.forEach((s, i) => (s.style.visibility = i < n ? "visible" : "hidden"));
44
+ const m = misregister(t, { seed, px: 3, at });
45
+ el.style.textShadow = `${(m.x ?? 0).toFixed(1)}px ${(m.y ?? 0).toFixed(1)}px 0 color-mix(in srgb, var(--kf-accent) 75%, transparent)`;
46
+ };
47
+ },
48
+
49
+ // 블루 선이 드럼처럼 끊어 그어지고, 핑크 판 선이 어긋나 뒤따른다
50
+ trace(el, { points, at, dur, seed, tone }) {
51
+ const { g, clear } = traceCanvas(el, points);
52
+ const blue = getComputedStyle(el).getPropertyValue("--kf-ink").trim() || "#3255A4";
53
+ const pink = getComputedStyle(el).getPropertyValue("--kf-accent").trim() || "#FF48B0";
54
+ const dx = randRange(seed, 0, -5, 5);
55
+ const dy = randRange(seed, 1, -5, 5);
56
+ return (t) => {
57
+ clear();
58
+ const p = clamp(printFrames(t - at) / Math.max(0.05, dur));
59
+ if (p <= 0) return;
60
+ g.lineCap = "round";
61
+ g.lineJoin = "round";
62
+ g.globalCompositeOperation = "multiply";
63
+ g.lineWidth = 10;
64
+ g.strokeStyle = tone === "accent" ? pink : blue;
65
+ strokePath(g, partial(points, p));
66
+ g.save();
67
+ g.translate(dx, dy);
68
+ g.strokeStyle = tone === "accent" ? blue : pink;
69
+ g.globalAlpha = 0.7;
70
+ strokePath(g, partial(points, clamp(p - 0.08)));
71
+ g.restore();
72
+ g.globalAlpha = 1;
73
+ };
74
+ },
75
+
76
+ drop(el, { ctx, drop }) {
77
+ return dropPlate(el, { ctx, drop });
78
+ },
79
+ };
80
+
81
+ const toTransform = (s: Style): string => `translate(${(s.x ?? 0).toFixed(2)}px, ${(s.y ?? 0).toFixed(2)}px)`;
Binary file
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "riso-zine",
3
+ "label": "리소 잡지 — 잉크 판을 한 장씩 찍는다",
4
+ "scheme": "light",
5
+ "colors": {
6
+ "bg": "#F2EDE4",
7
+ "surface": "#FAF7F1",
8
+ "raised": "#E9E2D4",
9
+ "line": "#CFC5B3",
10
+ "ink": "#3255A4",
11
+ "inkSoft": "#3255A4",
12
+ "dim": "#5B74B0",
13
+ "accent": "#FF48B0",
14
+ "accentSoft": "#FFB3DA",
15
+ "accentText": "#3255A4",
16
+ "onAccent": "#F2EDE4",
17
+ "success": "#3255A4",
18
+ "danger": "#FF48B0",
19
+ "warning": "#FF48B0",
20
+ "blue": "#3255A4",
21
+ "pink": "#FF48B0",
22
+ "paper": "#F2EDE4"
23
+ },
24
+ "fonts": {
25
+ "sans": "\"Pretendard Variable\", Pretendard, \"Noto Sans KR\", \"Apple SD Gothic Neo\", sans-serif",
26
+ "display": "\"Black Han Sans\", \"Pretendard Variable\", Pretendard, \"Noto Sans KR\", \"Apple SD Gothic Neo\", sans-serif",
27
+ "mono": "\"JetBrains Mono\", ui-monospace, \"SF Mono\", \"Pretendard Variable\", \"Noto Sans KR\", \"Apple SD Gothic Neo\", monospace",
28
+ "faces": [
29
+ {
30
+ "family": "Black Han Sans",
31
+ "src": "https://cdn.jsdelivr.net/gh/google/fonts@main/ofl/blackhansans/BlackHanSans-Regular.ttf",
32
+ "weight": "400"
33
+ },
34
+ {
35
+ "family": "Pretendard Variable",
36
+ "src": "https://cdn.jsdelivr.net/npm/pretendard@1.3.9/dist/web/variable/woff2/PretendardVariable.woff2",
37
+ "weight": "45 920"
38
+ },
39
+ {
40
+ "family": "JetBrains Mono",
41
+ "src": "https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5/files/jetbrains-mono-latin-wght-normal.woff2",
42
+ "weight": "100 800"
43
+ }
44
+ ]
45
+ },
46
+ "type": {
47
+ "hero": 220,
48
+ "title": 110,
49
+ "body": 44,
50
+ "caption": 32,
51
+ "weightDisplay": 400,
52
+ "weightBody": 600,
53
+ "tracking": "-0.01em"
54
+ },
55
+ "radius": {
56
+ "sm": 0,
57
+ "md": 0,
58
+ "lg": 0,
59
+ "pill": 999
60
+ },
61
+ "shadow": {
62
+ "soft": "none",
63
+ "lift": "none"
64
+ },
65
+ "motion": {
66
+ "beatPulse": "drops-only",
67
+ "shake": {
68
+ "on": [
69
+ "drop"
70
+ ],
71
+ "maxPerPhrase": 1,
72
+ "maxPx": 10
73
+ },
74
+ "cameraMove": "off",
75
+ "repeatSameMove": false,
76
+ "maxFreezeSec": 0.5,
77
+ "enter": "fade",
78
+ "ease": "linear",
79
+ "durations": {
80
+ "fast": 0.083,
81
+ "base": 0.25,
82
+ "slow": 0.5
83
+ }
84
+ },
85
+ "theme": {
86
+ "inks": [
87
+ "#F2EDE4 신문 종이",
88
+ "#3255A4 미디엄 블루 판",
89
+ "#FF48B0 형광 핑크 판 — 겹치면 곱하기로 보라"
90
+ ],
91
+ "texture": "종이결(섬유·얼룩)이 초당 8번 바뀌며 끓는다. 판마다 2–4px 어긋남, 망점(각도 블루 15° 핑크 75°), 잉크는 곱하기로 겹친다. 그라데이션은 망점으로만",
92
+ "movement": "초당 12장으로 끊어 움직인다(on twos). 판은 박에서 찍히고, 찍히는 순간 한 장 어긋났다가 제자리 근처로 앉는다. 미끄러지는 보간·흐림 없음"
93
+ },
94
+ "notes": [
95
+ "리소그래프 잉크 이름: Medium Blue #3255A4 · Fluorescent Pink #FF48B0.",
96
+ "핑크 한 판으로 작은 글을 쓰지 않는다(종이 위 2.6:1). 글은 블루 판, 큰 글은 두 판을 겹쳐 보라 테두리가 생기게.",
97
+ "카메라 이동 없음 — 종이는 책상에 놓여 있다."
98
+ ]
99
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "id": "riso-zine",
3
+ "name": "리소 잡지",
4
+ "metaphor": "잉크 판을 한 장씩 찍어 화면을 인쇄한다",
5
+ "status": "approved",
6
+ "approvedAt": "2026-10-08",
7
+ "purposes": [
8
+ "promo",
9
+ "mv",
10
+ "square",
11
+ "shorts",
12
+ "launch"
13
+ ],
14
+ "aspect": [
15
+ "16:9",
16
+ "1:1",
17
+ "9:16"
18
+ ],
19
+ "effects": [
20
+ {
21
+ "name": "printFrames",
22
+ "kind": "value",
23
+ "does": "t 를 초당 12장으로 끊는다 — 손으로 짠 움직임도 이걸 거쳐 인쇄물처럼 끊긴다",
24
+ "use": "const tq = printFrames(t)"
25
+ },
26
+ {
27
+ "name": "misregister",
28
+ "kind": "value",
29
+ "does": "판 어긋남 — 시드로 정한 ±px 에 머물고 찍히는 두 장은 더 어긋났다 앉는다, 초당 12번 끓는다",
30
+ "use": "applyStyle(el, misregister(t, { seed: \"title-pink\", px: 6, at: 1.4 }))"
31
+ },
32
+ {
33
+ "name": "plateStamp",
34
+ "kind": "layer",
35
+ "does": "같은 그림을 잉크 판 여러 장으로 찍는다 — 곱하기로 겹쳐 블루+핑크가 보라, 어긋난 가장자리에 두 색",
36
+ "use": "const title = plateStamp(el, { ctx, plates: [{ ink: \"blue\", at: 0 }, { ink: \"pink\", at: 1.4, px: 7 }], build: (p) => { p.textContent = \"170\" } })"
37
+ },
38
+ {
39
+ "name": "halftone",
40
+ "kind": "layer",
41
+ "does": "망점 판 — 값이 클수록 점이 크다, grow 로 자라거나 sweep 으로 드럼이 지나간 줄부터 찍힌다, 드롭 구간에선 박마다 부푼다",
42
+ "use": "const dots = halftone(el, { ctx, x, y, w, h, ink: \"pink\", angle: 75, value: (u, v) => 1 - v, at: 1.4 })"
43
+ },
44
+ {
45
+ "name": "paperGrain",
46
+ "kind": "layer",
47
+ "does": "종이결 — paper 는 바탕·섬유·티끌, mottle 은 잉크 위 흰 반점. 초당 12번 끓어 멈춘 화면이 안 생긴다",
48
+ "use": "const paper = paperGrain(el, { ctx }); const mottle = paperGrain(top, { ctx, mode: \"mottle\" })"
49
+ },
50
+ {
51
+ "name": "sheetDrift",
52
+ "kind": "value",
53
+ "does": "종이 밀림 — 판면이 드럼에 물려 한 방향으로 끌려가며 조금 돈다(초당 12장), 다 찍힌 판면도 쉬지 않는다",
54
+ "use": "applyStyle(sheet, sheetDrift(t, { from: bar, seed: \"p3\", dur: 1.41 }))"
55
+ },
56
+ {
57
+ "name": "drumPass",
58
+ "kind": "value",
59
+ "does": "드럼이 종이 위를 지나가며 판이 찍힌다 — 지나간 쪽만 보이는 clip(초당 24장)",
60
+ "use": "plateStamp(el, { …, style: (t) => drumPass(t, { at: 2.8, dir: \"right\" }) })"
61
+ },
62
+ {
63
+ "name": "sheetFeed",
64
+ "kind": "layer",
65
+ "does": "장면 끝에 새 종이가 들어와 앞 장을 덮는다 — 다음 장면은 빈 종이에서 판을 찍기 시작",
66
+ "use": "const feed = sheetFeed(el, { ctx, at: ctx.dur - 0.42, from: \"bottom\" })"
67
+ },
68
+ {
69
+ "name": "dropPlate",
70
+ "kind": "layer",
71
+ "does": "드롭 — 핑크 판이 통째로 찍혔다 걷히고 망점 고리가 퍼진다, 흔들림을 돌려준다",
72
+ "use": "const s = plate(t); applyStyle(content, s.shake) // plate = dropPlate(el, { ctx, drop: 0 })"
73
+ }
74
+ ]
75
+ }