@autoaiai/aicut 0.1.7 → 0.1.13

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 (306) hide show
  1. package/MANUAL.md +94 -84
  2. package/package.json +1 -1
  3. package/product.json +2 -1
  4. package/skills/aicut/SKILL.md +4 -4
  5. package/skills/aicut/references/commands.md +15 -15
  6. package/skills/aicut/references/film-format.md +1 -1
  7. package/skills/aicut/references/recipes.md +4 -4
  8. package/skills/aicut/references/troubleshooting.md +2 -2
  9. package/skills/aicut-motion/SKILL.md +75 -9
  10. package/skills/aicut-motion/THIRD_PARTY_NOTICES.md +14 -0
  11. package/skills/aicut-motion/assets/atlas/lib/harness.js +116 -0
  12. package/skills/aicut-motion/assets/atlas/lib/sound.js +274 -0
  13. package/skills/aicut-motion/assets/atlas/styles/001-flat-vector-science/code.js +937 -0
  14. package/skills/aicut-motion/assets/atlas/styles/001-flat-vector-science/poster.jpg +0 -0
  15. package/skills/aicut-motion/assets/atlas/styles/001-flat-vector-science/style.json +13 -0
  16. package/skills/aicut-motion/assets/atlas/styles/002-watercolor-wash/code.js +909 -0
  17. package/skills/aicut-motion/assets/atlas/styles/002-watercolor-wash/poster.jpg +0 -0
  18. package/skills/aicut-motion/assets/atlas/styles/002-watercolor-wash/style.json +13 -0
  19. package/skills/aicut-motion/assets/atlas/styles/003-shadow-puppet-theatre/code.js +881 -0
  20. package/skills/aicut-motion/assets/atlas/styles/003-shadow-puppet-theatre/poster.jpg +0 -0
  21. package/skills/aicut-motion/assets/atlas/styles/003-shadow-puppet-theatre/style.json +13 -0
  22. package/skills/aicut-motion/assets/atlas/styles/004-whiteboard-explainer/code.js +897 -0
  23. package/skills/aicut-motion/assets/atlas/styles/004-whiteboard-explainer/poster.jpg +0 -0
  24. package/skills/aicut-motion/assets/atlas/styles/004-whiteboard-explainer/style.json +13 -0
  25. package/skills/aicut-motion/assets/atlas/styles/005-psychedelic-poster/code.js +814 -0
  26. package/skills/aicut-motion/assets/atlas/styles/005-psychedelic-poster/poster.jpg +0 -0
  27. package/skills/aicut-motion/assets/atlas/styles/005-psychedelic-poster/style.json +13 -0
  28. package/skills/aicut-motion/assets/atlas/styles/006-tech-glow-explainer/code.js +990 -0
  29. package/skills/aicut-motion/assets/atlas/styles/006-tech-glow-explainer/poster.jpg +0 -0
  30. package/skills/aicut-motion/assets/atlas/styles/006-tech-glow-explainer/style.json +13 -0
  31. package/skills/aicut-motion/assets/atlas/styles/007-papercraft-models/code.js +994 -0
  32. package/skills/aicut-motion/assets/atlas/styles/007-papercraft-models/poster.jpg +0 -0
  33. package/skills/aicut-motion/assets/atlas/styles/007-papercraft-models/style.json +13 -0
  34. package/skills/aicut-motion/assets/atlas/styles/008-1940s-film-noir/code.js +792 -0
  35. package/skills/aicut-motion/assets/atlas/styles/008-1940s-film-noir/poster.jpg +0 -0
  36. package/skills/aicut-motion/assets/atlas/styles/008-1940s-film-noir/style.json +13 -0
  37. package/skills/aicut-motion/assets/atlas/styles/009-manim-style-math/code.js +840 -0
  38. package/skills/aicut-motion/assets/atlas/styles/009-manim-style-math/poster.jpg +0 -0
  39. package/skills/aicut-motion/assets/atlas/styles/009-manim-style-math/style.json +13 -0
  40. package/skills/aicut-motion/assets/atlas/styles/010-illuminated-manuscript/code.js +1126 -0
  41. package/skills/aicut-motion/assets/atlas/styles/010-illuminated-manuscript/poster.jpg +0 -0
  42. package/skills/aicut-motion/assets/atlas/styles/010-illuminated-manuscript/style.json +13 -0
  43. package/skills/aicut-motion/assets/atlas/styles/011-editorial-essay-collage/code.js +854 -0
  44. package/skills/aicut-motion/assets/atlas/styles/011-editorial-essay-collage/poster.jpg +0 -0
  45. package/skills/aicut-motion/assets/atlas/styles/011-editorial-essay-collage/style.json +13 -0
  46. package/skills/aicut-motion/assets/atlas/styles/012-bioluminescent-deep-sea/code.js +1124 -0
  47. package/skills/aicut-motion/assets/atlas/styles/012-bioluminescent-deep-sea/poster.jpg +0 -0
  48. package/skills/aicut-motion/assets/atlas/styles/012-bioluminescent-deep-sea/style.json +13 -0
  49. package/skills/aicut-motion/assets/atlas/styles/013-product-launch-reveal/code.js +728 -0
  50. package/skills/aicut-motion/assets/atlas/styles/013-product-launch-reveal/poster.jpg +0 -0
  51. package/skills/aicut-motion/assets/atlas/styles/013-product-launch-reveal/style.json +13 -0
  52. package/skills/aicut-motion/assets/atlas/styles/014-halftone-pop-panel/code.js +664 -0
  53. package/skills/aicut-motion/assets/atlas/styles/014-halftone-pop-panel/poster.jpg +0 -0
  54. package/skills/aicut-motion/assets/atlas/styles/014-halftone-pop-panel/style.json +13 -0
  55. package/skills/aicut-motion/assets/atlas/styles/015-isometric-pastel/code.js +991 -0
  56. package/skills/aicut-motion/assets/atlas/styles/015-isometric-pastel/poster.jpg +0 -0
  57. package/skills/aicut-motion/assets/atlas/styles/015-isometric-pastel/style.json +13 -0
  58. package/skills/aicut-motion/assets/atlas/styles/016-oscilloscope-vector-art/code.js +801 -0
  59. package/skills/aicut-motion/assets/atlas/styles/016-oscilloscope-vector-art/poster.jpg +0 -0
  60. package/skills/aicut-motion/assets/atlas/styles/016-oscilloscope-vector-art/style.json +13 -0
  61. package/skills/aicut-motion/assets/atlas/styles/017-risograph-zine/code.js +692 -0
  62. package/skills/aicut-motion/assets/atlas/styles/017-risograph-zine/poster.jpg +0 -0
  63. package/skills/aicut-motion/assets/atlas/styles/017-risograph-zine/style.json +13 -0
  64. package/skills/aicut-motion/assets/atlas/styles/018-claymation-set/code.js +756 -0
  65. package/skills/aicut-motion/assets/atlas/styles/018-claymation-set/poster.jpg +0 -0
  66. package/skills/aicut-motion/assets/atlas/styles/018-claymation-set/style.json +13 -0
  67. package/skills/aicut-motion/assets/atlas/styles/019-neon-sign-at-night/code.js +922 -0
  68. package/skills/aicut-motion/assets/atlas/styles/019-neon-sign-at-night/poster.jpg +0 -0
  69. package/skills/aicut-motion/assets/atlas/styles/019-neon-sign-at-night/style.json +13 -0
  70. package/skills/aicut-motion/assets/atlas/styles/020-kawaii-anime/code.js +852 -0
  71. package/skills/aicut-motion/assets/atlas/styles/020-kawaii-anime/poster.jpg +0 -0
  72. package/skills/aicut-motion/assets/atlas/styles/020-kawaii-anime/style.json +13 -0
  73. package/skills/aicut-motion/assets/atlas/styles/021-ukiyo-e-woodblock/code.js +724 -0
  74. package/skills/aicut-motion/assets/atlas/styles/021-ukiyo-e-woodblock/poster.jpg +0 -0
  75. package/skills/aicut-motion/assets/atlas/styles/021-ukiyo-e-woodblock/style.json +13 -0
  76. package/skills/aicut-motion/assets/atlas/styles/022-16-bit-pixel-odyssey/code.js +793 -0
  77. package/skills/aicut-motion/assets/atlas/styles/022-16-bit-pixel-odyssey/poster.jpg +0 -0
  78. package/skills/aicut-motion/assets/atlas/styles/022-16-bit-pixel-odyssey/style.json +13 -0
  79. package/skills/aicut-motion/assets/atlas/styles/023-chalkboard-lesson/code.js +846 -0
  80. package/skills/aicut-motion/assets/atlas/styles/023-chalkboard-lesson/poster.jpg +0 -0
  81. package/skills/aicut-motion/assets/atlas/styles/023-chalkboard-lesson/style.json +13 -0
  82. package/skills/aicut-motion/assets/atlas/styles/024-cut-paper-diorama/code.js +1008 -0
  83. package/skills/aicut-motion/assets/atlas/styles/024-cut-paper-diorama/poster.jpg +0 -0
  84. package/skills/aicut-motion/assets/atlas/styles/024-cut-paper-diorama/style.json +13 -0
  85. package/skills/aicut-motion/assets/atlas/styles/025-cathedral-glass/code.js +680 -0
  86. package/skills/aicut-motion/assets/atlas/styles/025-cathedral-glass/poster.jpg +0 -0
  87. package/skills/aicut-motion/assets/atlas/styles/025-cathedral-glass/style.json +13 -0
  88. package/skills/aicut-motion/assets/atlas/styles/026-editorial-chart/code.js +633 -0
  89. package/skills/aicut-motion/assets/atlas/styles/026-editorial-chart/poster.jpg +0 -0
  90. package/skills/aicut-motion/assets/atlas/styles/026-editorial-chart/style.json +13 -0
  91. package/skills/aicut-motion/assets/atlas/styles/027-synthwave-outrun/code.js +757 -0
  92. package/skills/aicut-motion/assets/atlas/styles/027-synthwave-outrun/poster.jpg +0 -0
  93. package/skills/aicut-motion/assets/atlas/styles/027-synthwave-outrun/style.json +13 -0
  94. package/skills/aicut-motion/assets/atlas/styles/028-origami-studio/code.js +828 -0
  95. package/skills/aicut-motion/assets/atlas/styles/028-origami-studio/poster.jpg +0 -0
  96. package/skills/aicut-motion/assets/atlas/styles/028-origami-studio/style.json +13 -0
  97. package/skills/aicut-motion/assets/atlas/styles/029-linocut-relief-print/code.js +697 -0
  98. package/skills/aicut-motion/assets/atlas/styles/029-linocut-relief-print/poster.jpg +0 -0
  99. package/skills/aicut-motion/assets/atlas/styles/029-linocut-relief-print/style.json +13 -0
  100. package/skills/aicut-motion/assets/atlas/styles/030-holographic-foil-card/code.js +687 -0
  101. package/skills/aicut-motion/assets/atlas/styles/030-holographic-foil-card/poster.jpg +0 -0
  102. package/skills/aicut-motion/assets/atlas/styles/030-holographic-foil-card/style.json +13 -0
  103. package/skills/aicut-motion/assets/atlas/styles/031-voxel-diorama/code.js +727 -0
  104. package/skills/aicut-motion/assets/atlas/styles/031-voxel-diorama/poster.jpg +0 -0
  105. package/skills/aicut-motion/assets/atlas/styles/031-voxel-diorama/style.json +13 -0
  106. package/skills/aicut-motion/assets/atlas/styles/032-sumi-e-ink-wash/code.js +903 -0
  107. package/skills/aicut-motion/assets/atlas/styles/032-sumi-e-ink-wash/poster.jpg +0 -0
  108. package/skills/aicut-motion/assets/atlas/styles/032-sumi-e-ink-wash/style.json +13 -0
  109. package/skills/aicut-motion/assets/atlas/styles/033-etch-a-sketch-toy/code.js +662 -0
  110. package/skills/aicut-motion/assets/atlas/styles/033-etch-a-sketch-toy/poster.jpg +0 -0
  111. package/skills/aicut-motion/assets/atlas/styles/033-etch-a-sketch-toy/style.json +13 -0
  112. package/skills/aicut-motion/assets/atlas/styles/034-cosmic-star-chart/code.js +951 -0
  113. package/skills/aicut-motion/assets/atlas/styles/034-cosmic-star-chart/poster.jpg +0 -0
  114. package/skills/aicut-motion/assets/atlas/styles/034-cosmic-star-chart/style.json +13 -0
  115. package/skills/aicut-motion/assets/atlas/styles/035-punk-zine-collage/code.js +759 -0
  116. package/skills/aicut-motion/assets/atlas/styles/035-punk-zine-collage/poster.jpg +0 -0
  117. package/skills/aicut-motion/assets/atlas/styles/035-punk-zine-collage/style.json +13 -0
  118. package/skills/aicut-motion/assets/atlas/styles/036-thermal-camera/code.js +738 -0
  119. package/skills/aicut-motion/assets/atlas/styles/036-thermal-camera/poster.jpg +0 -0
  120. package/skills/aicut-motion/assets/atlas/styles/036-thermal-camera/style.json +13 -0
  121. package/skills/aicut-motion/assets/atlas/styles/037-engineering-blueprint/code.js +793 -0
  122. package/skills/aicut-motion/assets/atlas/styles/037-engineering-blueprint/poster.jpg +0 -0
  123. package/skills/aicut-motion/assets/atlas/styles/037-engineering-blueprint/style.json +13 -0
  124. package/skills/aicut-motion/assets/atlas/styles/038-impasto-night/code.js +673 -0
  125. package/skills/aicut-motion/assets/atlas/styles/038-impasto-night/poster.jpg +0 -0
  126. package/skills/aicut-motion/assets/atlas/styles/038-impasto-night/style.json +13 -0
  127. package/skills/aicut-motion/assets/atlas/styles/039-win95-desktop/code.js +907 -0
  128. package/skills/aicut-motion/assets/atlas/styles/039-win95-desktop/poster.jpg +0 -0
  129. package/skills/aicut-motion/assets/atlas/styles/039-win95-desktop/style.json +13 -0
  130. package/skills/aicut-motion/assets/atlas/styles/040-low-poly-faceted/code.js +833 -0
  131. package/skills/aicut-motion/assets/atlas/styles/040-low-poly-faceted/poster.jpg +0 -0
  132. package/skills/aicut-motion/assets/atlas/styles/040-low-poly-faceted/style.json +13 -0
  133. package/skills/aicut-motion/assets/atlas/styles/041-manga-page/code.js +845 -0
  134. package/skills/aicut-motion/assets/atlas/styles/041-manga-page/poster.jpg +0 -0
  135. package/skills/aicut-motion/assets/atlas/styles/041-manga-page/style.json +13 -0
  136. package/skills/aicut-motion/assets/atlas/styles/042-wood-type-letterpress/code.js +496 -0
  137. package/skills/aicut-motion/assets/atlas/styles/042-wood-type-letterpress/poster.jpg +0 -0
  138. package/skills/aicut-motion/assets/atlas/styles/042-wood-type-letterpress/style.json +13 -0
  139. package/skills/aicut-motion/assets/atlas/styles/043-light-painting/code.js +635 -0
  140. package/skills/aicut-motion/assets/atlas/styles/043-light-painting/poster.jpg +0 -0
  141. package/skills/aicut-motion/assets/atlas/styles/043-light-painting/style.json +13 -0
  142. package/skills/aicut-motion/assets/atlas/styles/044-felt-patchwork/code.js +799 -0
  143. package/skills/aicut-motion/assets/atlas/styles/044-felt-patchwork/poster.jpg +0 -0
  144. package/skills/aicut-motion/assets/atlas/styles/044-felt-patchwork/style.json +13 -0
  145. package/skills/aicut-motion/assets/atlas/styles/045-phosphor-terminal/code.js +547 -0
  146. package/skills/aicut-motion/assets/atlas/styles/045-phosphor-terminal/poster.jpg +0 -0
  147. package/skills/aicut-motion/assets/atlas/styles/045-phosphor-terminal/style.json +13 -0
  148. package/skills/aicut-motion/assets/atlas/styles/046-glassmorphism-ui/code.js +592 -0
  149. package/skills/aicut-motion/assets/atlas/styles/046-glassmorphism-ui/poster.jpg +0 -0
  150. package/skills/aicut-motion/assets/atlas/styles/046-glassmorphism-ui/style.json +13 -0
  151. package/skills/aicut-motion/assets/atlas/styles/047-tarot-card/code.js +768 -0
  152. package/skills/aicut-motion/assets/atlas/styles/047-tarot-card/poster.jpg +0 -0
  153. package/skills/aicut-motion/assets/atlas/styles/047-tarot-card/style.json +13 -0
  154. package/skills/aicut-motion/assets/atlas/styles/048-transit-map/code.js +666 -0
  155. package/skills/aicut-motion/assets/atlas/styles/048-transit-map/poster.jpg +0 -0
  156. package/skills/aicut-motion/assets/atlas/styles/048-transit-map/style.json +13 -0
  157. package/skills/aicut-motion/assets/atlas/styles/049-gouache-travel-poster/code.js +559 -0
  158. package/skills/aicut-motion/assets/atlas/styles/049-gouache-travel-poster/poster.jpg +0 -0
  159. package/skills/aicut-motion/assets/atlas/styles/049-gouache-travel-poster/style.json +13 -0
  160. package/skills/aicut-motion/assets/atlas/styles/050-napkin-sketch/code.js +943 -0
  161. package/skills/aicut-motion/assets/atlas/styles/050-napkin-sketch/poster.jpg +0 -0
  162. package/skills/aicut-motion/assets/atlas/styles/050-napkin-sketch/style.json +13 -0
  163. package/skills/aicut-motion/assets/atlas/styles/051-art-deco-foil/code.js +606 -0
  164. package/skills/aicut-motion/assets/atlas/styles/051-art-deco-foil/poster.jpg +0 -0
  165. package/skills/aicut-motion/assets/atlas/styles/051-art-deco-foil/style.json +13 -0
  166. package/skills/aicut-motion/assets/atlas/styles/052-radiograph-on-lightbox/code.js +730 -0
  167. package/skills/aicut-motion/assets/atlas/styles/052-radiograph-on-lightbox/poster.jpg +0 -0
  168. package/skills/aicut-motion/assets/atlas/styles/052-radiograph-on-lightbox/style.json +13 -0
  169. package/skills/aicut-motion/assets/atlas/styles/053-vaporwave/code.js +782 -0
  170. package/skills/aicut-motion/assets/atlas/styles/053-vaporwave/poster.jpg +0 -0
  171. package/skills/aicut-motion/assets/atlas/styles/053-vaporwave/style.json +13 -0
  172. package/skills/aicut-motion/assets/atlas/styles/054-ebru-paper-marbling/code.js +504 -0
  173. package/skills/aicut-motion/assets/atlas/styles/054-ebru-paper-marbling/poster.jpg +0 -0
  174. package/skills/aicut-motion/assets/atlas/styles/054-ebru-paper-marbling/style.json +13 -0
  175. package/skills/aicut-motion/assets/atlas/styles/055-isotype-pictograms/code.js +517 -0
  176. package/skills/aicut-motion/assets/atlas/styles/055-isotype-pictograms/poster.jpg +0 -0
  177. package/skills/aicut-motion/assets/atlas/styles/055-isotype-pictograms/style.json +13 -0
  178. package/skills/aicut-motion/assets/atlas/styles/056-soft-3d-clay/code.js +713 -0
  179. package/skills/aicut-motion/assets/atlas/styles/056-soft-3d-clay/poster.jpg +0 -0
  180. package/skills/aicut-motion/assets/atlas/styles/056-soft-3d-clay/style.json +13 -0
  181. package/skills/aicut-motion/assets/atlas/styles/057-cross-stitch-sampler/code.js +717 -0
  182. package/skills/aicut-motion/assets/atlas/styles/057-cross-stitch-sampler/poster.jpg +0 -0
  183. package/skills/aicut-motion/assets/atlas/styles/057-cross-stitch-sampler/style.json +13 -0
  184. package/skills/aicut-motion/assets/atlas/styles/058-constructivist-propaganda/code.js +540 -0
  185. package/skills/aicut-motion/assets/atlas/styles/058-constructivist-propaganda/poster.jpg +0 -0
  186. package/skills/aicut-motion/assets/atlas/styles/058-constructivist-propaganda/style.json +13 -0
  187. package/skills/aicut-motion/assets/atlas/styles/059-pocket-monochrome/code.js +524 -0
  188. package/skills/aicut-motion/assets/atlas/styles/059-pocket-monochrome/poster.jpg +0 -0
  189. package/skills/aicut-motion/assets/atlas/styles/059-pocket-monochrome/style.json +13 -0
  190. package/skills/aicut-motion/assets/atlas/styles/060-botanical-plate/code.js +934 -0
  191. package/skills/aicut-motion/assets/atlas/styles/060-botanical-plate/poster.jpg +0 -0
  192. package/skills/aicut-motion/assets/atlas/styles/060-botanical-plate/style.json +13 -0
  193. package/skills/aicut-motion/assets/atlas/styles/061-kinetic-type/code.js +690 -0
  194. package/skills/aicut-motion/assets/atlas/styles/061-kinetic-type/poster.jpg +0 -0
  195. package/skills/aicut-motion/assets/atlas/styles/061-kinetic-type/style.json +13 -0
  196. package/skills/aicut-motion/assets/atlas/styles/062-byzantine-mosaic/code.js +612 -0
  197. package/skills/aicut-motion/assets/atlas/styles/062-byzantine-mosaic/poster.jpg +0 -0
  198. package/skills/aicut-motion/assets/atlas/styles/062-byzantine-mosaic/style.json +13 -0
  199. package/skills/aicut-motion/assets/atlas/styles/063-y2k-liquid-chrome/code.js +666 -0
  200. package/skills/aicut-motion/assets/atlas/styles/063-y2k-liquid-chrome/poster.jpg +0 -0
  201. package/skills/aicut-motion/assets/atlas/styles/063-y2k-liquid-chrome/style.json +13 -0
  202. package/skills/aicut-motion/assets/atlas/styles/064-sticky-note-wall/code.js +651 -0
  203. package/skills/aicut-motion/assets/atlas/styles/064-sticky-note-wall/poster.jpg +0 -0
  204. package/skills/aicut-motion/assets/atlas/styles/064-sticky-note-wall/style.json +13 -0
  205. package/skills/aicut-motion/assets/atlas/styles/065-vintage-newsprint/code.js +656 -0
  206. package/skills/aicut-motion/assets/atlas/styles/065-vintage-newsprint/poster.jpg +0 -0
  207. package/skills/aicut-motion/assets/atlas/styles/065-vintage-newsprint/style.json +13 -0
  208. package/skills/aicut-motion/assets/atlas/styles/066-hidden-line-wireframe/code.js +672 -0
  209. package/skills/aicut-motion/assets/atlas/styles/066-hidden-line-wireframe/poster.jpg +0 -0
  210. package/skills/aicut-motion/assets/atlas/styles/066-hidden-line-wireframe/style.json +13 -0
  211. package/skills/aicut-motion/assets/atlas/styles/067-memphis-group/code.js +548 -0
  212. package/skills/aicut-motion/assets/atlas/styles/067-memphis-group/poster.jpg +0 -0
  213. package/skills/aicut-motion/assets/atlas/styles/067-memphis-group/style.json +13 -0
  214. package/skills/aicut-motion/assets/atlas/styles/068-ballpoint-notebook/code.js +989 -0
  215. package/skills/aicut-motion/assets/atlas/styles/068-ballpoint-notebook/poster.jpg +0 -0
  216. package/skills/aicut-motion/assets/atlas/styles/068-ballpoint-notebook/style.json +13 -0
  217. package/skills/aicut-motion/assets/atlas/styles/069-op-art-sphere/code.js +440 -0
  218. package/skills/aicut-motion/assets/atlas/styles/069-op-art-sphere/poster.jpg +0 -0
  219. package/skills/aicut-motion/assets/atlas/styles/069-op-art-sphere/style.json +13 -0
  220. package/skills/aicut-motion/assets/atlas/styles/070-topographic-survey/code.js +895 -0
  221. package/skills/aicut-motion/assets/atlas/styles/070-topographic-survey/poster.jpg +0 -0
  222. package/skills/aicut-motion/assets/atlas/styles/070-topographic-survey/style.json +13 -0
  223. package/skills/aicut-motion/assets/atlas/styles/071-pointillist-afternoon/code.js +563 -0
  224. package/skills/aicut-motion/assets/atlas/styles/071-pointillist-afternoon/poster.jpg +0 -0
  225. package/skills/aicut-motion/assets/atlas/styles/071-pointillist-afternoon/style.json +13 -0
  226. package/skills/aicut-motion/assets/atlas/styles/072-vector-arcade-1980/code.js +627 -0
  227. package/skills/aicut-motion/assets/atlas/styles/072-vector-arcade-1980/poster.jpg +0 -0
  228. package/skills/aicut-motion/assets/atlas/styles/072-vector-arcade-1980/style.json +13 -0
  229. package/skills/aicut-motion/assets/atlas/styles/073-patent-drawing/code.js +1096 -0
  230. package/skills/aicut-motion/assets/atlas/styles/073-patent-drawing/poster.jpg +0 -0
  231. package/skills/aicut-motion/assets/atlas/styles/073-patent-drawing/style.json +13 -0
  232. package/skills/aicut-motion/assets/atlas/styles/074-bauhaus-poster/code.js +595 -0
  233. package/skills/aicut-motion/assets/atlas/styles/074-bauhaus-poster/poster.jpg +0 -0
  234. package/skills/aicut-motion/assets/atlas/styles/074-bauhaus-poster/style.json +13 -0
  235. package/skills/aicut-motion/assets/atlas/styles/075-bitmap-paint-doodle/code.js +665 -0
  236. package/skills/aicut-motion/assets/atlas/styles/075-bitmap-paint-doodle/poster.jpg +0 -0
  237. package/skills/aicut-motion/assets/atlas/styles/075-bitmap-paint-doodle/style.json +13 -0
  238. package/skills/aicut-motion/assets/atlas/styles/076-nail-thread-string-art/code.js +645 -0
  239. package/skills/aicut-motion/assets/atlas/styles/076-nail-thread-string-art/poster.jpg +0 -0
  240. package/skills/aicut-motion/assets/atlas/styles/076-nail-thread-string-art/style.json +13 -0
  241. package/skills/aicut-motion/assets/atlas/styles/077-ridgeline/code.js +436 -0
  242. package/skills/aicut-motion/assets/atlas/styles/077-ridgeline/poster.jpg +0 -0
  243. package/skills/aicut-motion/assets/atlas/styles/077-ridgeline/style.json +13 -0
  244. package/skills/aicut-motion/assets/atlas/styles/078-sketchbook-graphite/code.js +1237 -0
  245. package/skills/aicut-motion/assets/atlas/styles/078-sketchbook-graphite/poster.jpg +0 -0
  246. package/skills/aicut-motion/assets/atlas/styles/078-sketchbook-graphite/style.json +13 -0
  247. package/skills/aicut-motion/assets/atlas/styles/079-teletext-page/code.js +622 -0
  248. package/skills/aicut-motion/assets/atlas/styles/079-teletext-page/poster.jpg +0 -0
  249. package/skills/aicut-motion/assets/atlas/styles/079-teletext-page/style.json +13 -0
  250. package/skills/aicut-motion/assets/atlas/styles/080-silkscreen-grid/code.js +524 -0
  251. package/skills/aicut-motion/assets/atlas/styles/080-silkscreen-grid/poster.jpg +0 -0
  252. package/skills/aicut-motion/assets/atlas/styles/080-silkscreen-grid/style.json +13 -0
  253. package/skills/aicut-motion/assets/atlas/styles/081-guilloch-security-print/code.js +689 -0
  254. package/skills/aicut-motion/assets/atlas/styles/081-guilloch-security-print/poster.jpg +0 -0
  255. package/skills/aicut-motion/assets/atlas/styles/081-guilloch-security-print/style.json +13 -0
  256. package/skills/aicut-motion/assets/atlas/styles/082-ascii-demoscene/code.js +574 -0
  257. package/skills/aicut-motion/assets/atlas/styles/082-ascii-demoscene/poster.jpg +0 -0
  258. package/skills/aicut-motion/assets/atlas/styles/082-ascii-demoscene/style.json +13 -0
  259. package/skills/aicut-motion/assets/atlas/styles/083-international-typographic-style/code.js +469 -0
  260. package/skills/aicut-motion/assets/atlas/styles/083-international-typographic-style/poster.jpg +0 -0
  261. package/skills/aicut-motion/assets/atlas/styles/083-international-typographic-style/style.json +13 -0
  262. package/skills/aicut-motion/assets/atlas/styles/084-flow-field/code.js +531 -0
  263. package/skills/aicut-motion/assets/atlas/styles/084-flow-field/poster.jpg +0 -0
  264. package/skills/aicut-motion/assets/atlas/styles/084-flow-field/style.json +13 -0
  265. package/skills/aicut-motion/assets/atlas/styles/085-macpaint-1984/code.js +675 -0
  266. package/skills/aicut-motion/assets/atlas/styles/085-macpaint-1984/poster.jpg +0 -0
  267. package/skills/aicut-motion/assets/atlas/styles/085-macpaint-1984/style.json +13 -0
  268. package/skills/aicut-motion/assets/atlas/styles/086-multi-scale-truchet/code.js +609 -0
  269. package/skills/aicut-motion/assets/atlas/styles/086-multi-scale-truchet/poster.jpg +0 -0
  270. package/skills/aicut-motion/assets/atlas/styles/086-multi-scale-truchet/style.json +13 -0
  271. package/skills/aicut-motion/references/design-systems/README.md +1 -1
  272. package/skills/aicut-motion/references/motion-delivery.md +55 -0
  273. package/skills/aicut-motion/references/pages.md +1 -1
  274. package/skills/aicut-motion/references/style-index.json +690 -0
  275. package/skills/aicut-motion/references/style-research.md +73 -0
  276. package/skills/aicut-motion/references/style-selection.md +71 -0
  277. package/skills/aicut-motion/scripts/atlas-viewer.html +195 -0
  278. package/skills/aicut-motion/scripts/atlas.mjs +109 -0
  279. package/studio/client.mjs +3 -3
  280. package/studio/server/fetch-github.mjs +14 -3
  281. package/studio/server/server.mjs +71 -6
  282. package/studio/server/skill-summaries.mjs +60 -0
  283. package/studio/server/skills.mjs +121 -7
  284. package/studio/server/styles-store.mjs +235 -0
  285. package/studio/server/template-posters.mjs +2 -2
  286. package/studio/server/templates-page.mjs +93 -93
  287. package/studio/server/templates.mjs +32 -7
  288. package/studio/ui/dist/assets/ExportCenter-DasulhAv.js +1 -0
  289. package/studio/ui/dist/assets/SettingsModal-BZw0Hz2_.js +2 -0
  290. package/studio/ui/dist/assets/apple-touch-icon-ClxQ7j-O.png +0 -0
  291. package/studio/ui/dist/assets/es-C8XPZARI.js +1 -0
  292. package/studio/ui/dist/assets/favicon-Blwx8Trs.png +0 -0
  293. package/studio/ui/dist/assets/index-BjJVmBzB.js +1623 -0
  294. package/studio/ui/dist/assets/index-C3BfKZFO.css +1 -0
  295. package/studio/ui/dist/assets/ja-BeNkdaEj.js +1 -0
  296. package/studio/ui/dist/assets/ko-DcTVhdzK.js +1 -0
  297. package/studio/ui/dist/assets/zh-CN-Cg51ctbL.js +1 -0
  298. package/studio/ui/dist/index.html +4 -3
  299. package/studio/ui/dist/assets/ExportCenter-F-2vF-lQ.js +0 -1
  300. package/studio/ui/dist/assets/SettingsModal-BgVYguNu.js +0 -2
  301. package/studio/ui/dist/assets/es-BRUzvuoM.js +0 -1
  302. package/studio/ui/dist/assets/index-Bhg-9dA3.css +0 -1
  303. package/studio/ui/dist/assets/index-CWur1Iw9.js +0 -1625
  304. package/studio/ui/dist/assets/ja-Cth-uDcW.js +0 -1
  305. package/studio/ui/dist/assets/ko-upvw591D.js +0 -1
  306. package/studio/ui/dist/assets/zh-CN-BCfJFazB.js +0 -1
@@ -0,0 +1,469 @@
1
+ {
2
+ const fieldNoise = (w, h, seed, cell, oct, sx = 1, sy = 1) => {
3
+ const nz = H.makeNoise(seed), gw = Math.ceil(w / cell) + 2, gh = Math.ceil(h / cell) + 2, g = new Float32Array(gw * gh);
4
+ for (let j = 0; j < gh; j++) for (let i = 0; i < gw; i++) g[j * gw + i] = nz.fbm2(i * 0.35 * sx, j * 0.35 * sy, oct);
5
+ const out = new Float32Array(w * h);
6
+ for (let y = 0; y < h; y++) {
7
+ const fy = y / cell, j = fy | 0, ty = fy - j;
8
+ for (let x = 0; x < w; x++) {
9
+ const fx = x / cell, i = fx | 0, tx = fx - i, k = j * gw + i;
10
+ const a = g[k] + (g[k + 1] - g[k]) * tx, b = g[k + gw] + (g[k + gw + 1] - g[k + gw]) * tx;
11
+ out[y * w + x] = a + (b - a) * ty;
12
+ }
13
+ }
14
+ return out;
15
+ };
16
+
17
+ const RED = '#e2231a', BLACK = '#141414', PAPER = '#f1efe9';
18
+
19
+ // ===================== EXPLAINER: "How does AI learn?" =====================
20
+ // A Zürich-school information sequence: every page hangs on the same 12-column grid; pages change with a
21
+ // column-by-column red wipe; arrows are hairline rules with solid heads; numbers are set in Inter 800.
22
+ const EXF = {};
23
+ const exField = (k, ...a) => { const kk = k + a[0] + 'x' + a[1]; return EXF[kk] || (EXF[kk] = fieldNoise(...a)); }; // cached per size
24
+ // ink dropouts: fixed-seed single-pixel specks plus a few offset "hickeys" (tiny donuts of missing ink)
25
+ const speckMask = (w, h) => {
26
+ const key = 'speck' + w + 'x' + h; if (EXF[key]) return EXF[key];
27
+ const m = new Float32Array(w * h), r = H.rng(12);
28
+ for (let p = 0; p < m.length; p++) if (r() < 0.0015) m[p] = 0.5;
29
+ const rh = H.rng(1212);
30
+ for (let k = 0; k < 70; k++) {
31
+ const cx = rh.range(4, w - 4), cy = rh.range(4, h - 4), ro = rh.range(1.6, 3.2);
32
+ for (let y = Math.floor(cy - ro - 1); y <= cy + ro + 1; y++) for (let x = Math.floor(cx - ro - 1); x <= cx + ro + 1; x++) {
33
+ const dd = Math.hypot(x - cx, y - cy), ring = Math.max(0, 1 - Math.abs(dd - ro * 0.75) / (ro * 0.4)), core = dd < ro * 0.3 ? 0.35 : 0;
34
+ const v = Math.min(0.85, ring * 0.8 + core); if (v > m[y * w + x]) m[y * w + x] = v;
35
+ }
36
+ }
37
+ return (EXF[key] = m);
38
+ };
39
+ const pict = (c, kind, x, y, s, col = BLACK, eye = PAPER) => { // isotype-like pictograms
40
+ c.fillStyle = col;
41
+ if (kind === 'cat') {
42
+ c.beginPath(); c.moveTo(x - s * 0.3, y - s * 0.02); c.lineTo(x - s * 0.27, y - s * 0.4); c.lineTo(x - s * 0.05, y - s * 0.2); c.closePath(); c.fill();
43
+ c.beginPath(); c.moveTo(x + s * 0.3, y - s * 0.02); c.lineTo(x + s * 0.27, y - s * 0.4); c.lineTo(x + s * 0.05, y - s * 0.2); c.closePath(); c.fill();
44
+ c.beginPath(); c.arc(x, y + s * 0.06, s * 0.3, 0, 7); c.fill();
45
+ } else {
46
+ c.beginPath(); c.arc(x, y + s * 0.02, s * 0.28, 0, 7); c.fill();
47
+ c.beginPath(); c.ellipse(x - s * 0.3, y + s * 0.04, s * 0.1, s * 0.22, 0.35, 0, 7); c.fill();
48
+ c.beginPath(); c.ellipse(x + s * 0.3, y + s * 0.04, s * 0.1, s * 0.22, -0.35, 0, 7); c.fill();
49
+ c.beginPath(); c.ellipse(x, y + s * 0.22, s * 0.13, s * 0.1, 0, 0, 7); c.fill();
50
+ }
51
+ if (s > 30) { c.fillStyle = eye; c.beginPath(); c.arc(x - s * 0.1, y + s * 0.02, s * 0.045, 0, 7); c.arc(x + s * 0.1, y + s * 0.02, s * 0.045, 0, 7); c.fill(); }
52
+ };
53
+ const rule = (c, x0, y0, x1, y1, p, w = 2, col = BLACK, head = true) => { // hairline arrow
54
+ if (p <= 0) return;
55
+ const x = H.lerp(x0, x1, p), y = H.lerp(y0, y1, p), a = Math.atan2(y1 - y0, x1 - x0);
56
+ c.strokeStyle = col; c.fillStyle = col; c.lineWidth = w; c.lineCap = 'butt';
57
+ const hl = 14 + w * 2.6;
58
+ c.beginPath(); c.moveTo(x0, y0); c.lineTo(x - Math.cos(a) * hl * 0.6, y - Math.sin(a) * hl * 0.6); c.stroke();
59
+ if (head) { c.beginPath(); c.moveTo(x, y); c.lineTo(x - Math.cos(a - 0.42) * hl, y - Math.sin(a - 0.42) * hl); c.lineTo(x - Math.cos(a + 0.42) * hl, y - Math.sin(a + 0.42) * hl); c.closePath(); c.fill(); }
60
+ };
61
+
62
+ const explainSwiss = (ctx, W, HH, t) => {
63
+ const M = 48, PITCH = 100, COLW = 84, colX = (i) => M + i * PITCH, E = H.ease, cl = H.clamp;
64
+ const S = (a, b) => cl((t - a) / (b - a), 0, 1);
65
+ const txt = (s, x, y, size, wgt = 400, col = BLACK, ls = 0) => { c.font = `${wgt} ${size}px "Inter"`; c.letterSpacing = ls + 'px'; c.fillStyle = col; c.fillText(s, x, y); c.letterSpacing = '0px'; };
66
+ ctx.fillStyle = PAPER; ctx.fillRect(0, 0, W, HH);
67
+ const L = H.layer(W, HH), c = L.getContext('2d'); c.textBaseline = 'alphabetic';
68
+
69
+ // page changes: column-by-column wipe, content swaps while fully covered
70
+ const WIPES = [5.8, 10.3, 12.7], swap = (w) => w + 0.58;
71
+ const page = t < swap(WIPES[0]) ? 0 : t < swap(WIPES[1]) ? 1 : t < swap(WIPES[2]) ? 2 : 3;
72
+
73
+ // ---------- running header (the hook shrinks into it) ----------
74
+ const hp = E.inOut(S(1.7, 2.4));
75
+ {
76
+ const fs = H.lerp(150, 28, hp), x = M - fs * 0.05, y1 = H.lerp(HH - M - 150 * 0.86, M + 22, hp), y2 = H.lerp(HH - M, M + 22, hp);
77
+ c.font = `800 ${fs}px "Inter"`; c.letterSpacing = `${-(fs * 0.045).toFixed(1)}px`; c.fillStyle = BLACK;
78
+ const rise = (s, d, x, yb) => { const p = E.inOut(S(d, d + 0.5)); if (p <= 0) return; c.save(); if (hp === 0) { c.beginPath(); c.rect(0, yb - fs * 0.9, W, fs * 0.98); c.clip(); } c.fillText(s, x, yb + (1 - p) * fs * 0.9); c.restore(); };
79
+ if (hp < 1) { rise('How does', 0.15, x, y1); rise('AI learn?', 0.35, x + (c.measureText('How does ').width) * hp, y2); }
80
+ else c.fillText('How does AI learn?', x, M + 22);
81
+ c.letterSpacing = '0px';
82
+ if (hp < 0.5) { c.globalAlpha = 1 - hp * 2; txt('Lecture 05', colX(0), M + 14, 13, 600); txt('Machine learning, explained', colX(2), M + 14, 13); txt('in five steps', colX(2), M + 31, 13); c.globalAlpha = 1;
83
+ const rp = E.back(S(0.5, 1.0)); c.fillStyle = RED; c.beginPath(); c.arc(colX(9) + 42, 250, 150 * rp, 0, 7); c.fill();
84
+ c.strokeStyle = BLACK; c.lineWidth = 8; for (let k = 0; k < 4; k++) { const a0 = k * 1.4 + t * 0.6; c.beginPath(); c.arc(colX(9) + 42, 250, 60 + k * 26, a0, a0 + 1.6 * E.out(S(0.7 + k * 0.1, 1.3))); c.stroke(); }
85
+ }
86
+ c.fillStyle = BLACK; c.fillRect(colX(0), M - 6, (colX(11) + COLW - colX(0)) * E.inOut(S(0, 0.7)), 3);
87
+ if (hp >= 1) { const sec = ['01 Data', '02 Learning loop', '03 Progress', '04 Summary'][page]; c.textAlign = 'right'; txt(sec, colX(11) + COLW, M + 22, 28, 600, page === 3 ? BLACK : RED); c.textAlign = 'left'; }
88
+ }
89
+
90
+ // ---------- page 0: data ----------
91
+ if (page === 0 && t > 2.3) {
92
+ const top = 130;
93
+ c.fillStyle = BLACK; c.fillRect(colX(0), top, (colX(5) + COLW - colX(0)) * E.out(S(2.4, 2.9)), 2);
94
+ txt('Training data: labelled examples', colX(0), top + 32, 28, 600);
95
+ // two large annotated examples with leader rules landing on them
96
+ pict(c, 'cat', colX(0) + 42, top + 100, 84 * E.back(S(2.6, 2.9)));
97
+ pict(c, 'dog', colX(2) + 42, top + 100, 84 * E.back(S(2.75, 3.05)));
98
+ const lp1 = E.out(S(3.0, 3.3)), lp2 = E.out(S(3.15, 3.45));
99
+ rule(c, colX(1) + 40, top + 60, colX(0) + 70, top + 78, lp1, 1.5); if (lp1 >= 1) txt('cat', colX(1) + 44, top + 68, 28, 800, RED);
100
+ rule(c, colX(3) + 40, top + 60, colX(2) + 72, top + 80, lp2, 1.5); if (lp2 >= 1) txt('dog', colX(3) + 44, top + 68, 28, 800, RED);
101
+ // matrix of examples filling in reading order
102
+ const mx = colX(0), my = top + 180, cell = 36, cols = 16, rows = 8, nShow = Math.floor(cols * rows * Math.pow(S(3.2, 5.5), 0.8));
103
+ for (let i = 0; i < nShow; i++) { const k = H.rng(i * 13 + 5)() < 0.5 ? 'cat' : 'dog'; pict(c, k, mx + (i % cols) * cell + 16, my + Math.floor(i / cols) * cell + 16, 30); }
104
+ // flow into the model
105
+ rule(c, colX(6) + 10, my + 120, colX(7) - 10, my + 120, E.out(S(3.4, 3.8)), 2);
106
+ for (let k = 0; k < 4; k++) { const u = ((t * 1.6 + k / 4) % 1); if (t > 3.8) { c.fillStyle = BLACK; c.fillRect(H.lerp(colX(6) + 10, colX(7) - 24, u) - 4, my + 116, 8, 8); } }
107
+ const ms = E.out(S(2.9, 3.4)), bx = colX(7), by = my + 20;
108
+ c.fillStyle = BLACK; c.fillRect(bx, by, (COLW * 3 + 32) * ms, 230);
109
+ if (ms >= 1) { // mini network knocked out of the black block
110
+ c.strokeStyle = PAPER; c.lineWidth = 1.2; const xs = [bx + 50, bx + 142, bx + 234], ys = [[50, 115, 180], [38, 88, 140, 192], [88, 140]];
111
+ for (let a = 0; a < 2; a++) for (const y0 of ys[a]) for (const y1 of ys[a + 1]) { c.beginPath(); c.moveTo(xs[a], by + y0); c.lineTo(xs[a + 1], by + y1); c.stroke(); }
112
+ c.fillStyle = PAPER; ys.forEach((col, a) => col.forEach((y) => { c.beginPath(); c.arc(xs[a], by + y, 8, 0, 7); c.fill(); }));
113
+ txt('Model', bx, by + 266, 30, 800);
114
+ }
115
+ // counter
116
+ const cp = S(3.0, 5.6), n = cp < 1 ? Math.pow(cp, 3) * 1e6 : 1e6;
117
+ if (t > 3.0) { c.font = '800 96px "Inter"'; c.letterSpacing = '-5px'; c.fillStyle = RED; c.fillText(Math.round(n).toLocaleString('en-US'), colX(7) - 6, top + 92); c.letterSpacing = '0px';
118
+ c.fillStyle = BLACK; c.fillRect(colX(7), top, (colX(11) + COLW - colX(7)) * E.out(S(2.9, 3.3)), 2); txt('examples', colX(7), top + 142, 28, 800); txt('seen in training', colX(9), top + 142, 28, 400); }
119
+ }
120
+
121
+ // ---------- page 1: guess -> check -> adjust ----------
122
+ if (page === 1) {
123
+ const t0 = swap(WIPES[0]);
124
+ // step bar
125
+ const steps = ['Guess', 'Check', 'Adjust'], act = t < 7.6 ? 0 : t < 8.3 ? 1 : t < 9.3 ? 2 : Math.floor((t - 9.3) * 2.5) % 3;
126
+ steps.forEach((s, i) => {
127
+ const x = colX(i * 3), p = E.out(S(t0 + 0.1 + i * 0.12, t0 + 0.4 + i * 0.12)); if (p <= 0) return;
128
+ const on = i === act;
129
+ c.fillStyle = on ? RED : BLACK; c.fillRect(x, 130, (COLW * 3 + 32) * p, on ? 6 : 2);
130
+ txt(`${i + 1}`, x, 176, 28, 800, on ? RED : BLACK); txt(s, x + 30, 176, 28, 800, BLACK, -1);
131
+ });
132
+ // loop return rule: Adjust -> back to Guess
133
+ { const p = E.inOut(S(9.0, 9.5)), y = 196, x1 = colX(0) + 10, x0 = colX(8) + 20;
134
+ if (p > 0) { c.strokeStyle = BLACK; c.lineWidth = 1.5; c.beginPath(); c.moveTo(x0, y - 8); c.lineTo(x0, y); c.lineTo(H.lerp(x0, x1, p), y); c.stroke(); if (p >= 1) rule(c, x1, y, x1, y - 12, 1, 1.5); }
135
+ if (p >= 1) txt('repeat', colX(4), y + 32, 28, 800, RED); }
136
+ // network
137
+ const adj = E.inOut(S(8.35, 9.2)), layers = [[0, 3], [1, 4], [2, 4], [3, 2]], LX = [colX(2) + 40, colX(4) + 20, colX(6), colX(7) + 80], cy = 440;
138
+ const nodes = layers.map(([li, n]) => Array.from({ length: n }, (_, k) => [LX[li], cy + (k - (n - 1) / 2) * 76]));
139
+ const r = H.rng(808);
140
+ for (let a = 0; a < 3; a++) for (const p0 of nodes[a]) for (const p1 of nodes[a + 1]) {
141
+ const w0 = r.range(0.4, 3.2), w1 = r.range(0.4, 4.5), w = H.lerp(w0, w1, adj);
142
+ c.strokeStyle = adj > 0 && adj < 1 ? RED : BLACK; c.lineWidth = w; c.beginPath(); c.moveTo(p0[0], p0[1]); c.lineTo(p1[0], p1[1]); c.stroke();
143
+ }
144
+ const np = E.back(S(t0 + 0.2, t0 + 0.5));
145
+ nodes.forEach((col) => col.forEach(([x, y]) => { c.fillStyle = BLACK; c.beginPath(); c.arc(x, y, 11 * np, 0, 7); c.fill(); c.fillStyle = PAPER; c.beginPath(); c.arc(x, y, 5 * np, 0, 7); c.fill(); }));
146
+ // forward pass pulses (guess) and the error travelling back (adjust)
147
+ const pulse = (ts, dir, col) => { const u = S(ts, ts + 0.6); if (u <= 0 || u >= 1) return; const f = dir > 0 ? u : 1 - u, xx = H.lerp(LX[0], LX[3], f); c.fillStyle = col; for (const k of [-1, 0, 1]) { c.beginPath(); c.arc(xx, cy + k * 72 + Math.sin(f * 9 + k) * 10, 7, 0, 7); c.fill(); } };
148
+ pulse(7.0, 1, BLACK); pulse(7.85, -1, RED); pulse(9.35, 1, BLACK);
149
+ // input picture
150
+ pict(c, 'cat', colX(0) + 84, cy, 130 * E.back(S(t0 + 0.15, t0 + 0.5)));
151
+ if (S(t0 + 0.4, t0 + 0.6) > 0) txt('New picture', colX(0), cy + 108, 28, 600);
152
+ rule(c, colX(1) + 70, cy, LX[0] - 18, cy, E.out(S(t0 + 0.4, t0 + 0.7)), 2);
153
+ // outputs: two labelled nodes; guess, check, correct
154
+ const oN = nodes[3];
155
+ txt('dog', oN[0][0] + 24, oN[0][1] + 10, 28, 600); txt('cat', oN[1][0] + 24, oN[1][1] + 10, 28, 600);
156
+ const ox = colX(9) + 40;
157
+ if (t > 7.5 && t < 9.4) {
158
+ txt('dog?', ox, cy - 20, 54, 800, BLACK, -2);
159
+ const sp = E.out(S(7.75, 7.95)); // check: struck out in red + cross
160
+ if (sp > 0) { c.fillStyle = RED; c.fillRect(ox - 6, cy - 42, 140 * sp, 7); }
161
+ const xp = E.out(S(7.8, 8.0)); if (xp > 0) { c.save(); c.translate(ox + 175, cy - 40); c.rotate(Math.PI / 4); c.fillStyle = RED; c.fillRect(-26 * xp, -5, 52 * xp, 10); c.fillRect(-5, -26 * xp, 10, 52 * xp); c.restore(); }
162
+ if (t > 7.95) { txt('Wrong —', ox, cy + 22, 28, 800, RED); txt('it is a cat.', ox, cy + 54, 28, 800, RED); }
163
+ if (t > 8.35) txt('Error flows back,', ox, cy + 100, 28, 400), txt('weights adjust.', ox, cy + 132, 28, 400);
164
+ }
165
+ if (t >= 9.4) {
166
+ const p = E.out(S(9.6, 9.9));
167
+ txt('cat', ox, cy - 20, 54, 800, BLACK, -2);
168
+ if (p > 0) { c.save(); c.translate(ox + 120, cy - 34); c.strokeStyle = BLACK; c.lineWidth = 9; c.lineCap = 'butt'; c.beginPath(); c.moveTo(-14, 0); c.lineTo(0, 14 * p); c.lineTo(30 * p, -26 * p); c.stroke(); c.restore();
169
+ c.fillStyle = RED; c.fillRect(ox, cy - 8, 92 * p, 6); txt('Correct.', ox, cy + 34, 28, 800); }
170
+ }
171
+ // highlight the chosen output node
172
+ const sel = t < 9.4 ? oN[0] : oN[1];
173
+ if (t > 7.5) { c.strokeStyle = t < 9.4 ? RED : BLACK; c.lineWidth = 3; c.beginPath(); c.arc(sel[0], sel[1], 19, 0, 7); c.stroke(); }
174
+ }
175
+
176
+ // ---------- page 2: progress ----------
177
+ if (page === 2) {
178
+ const t0 = swap(WIPES[1]), gx = colX(0) + 40, gy = 600, gw = colX(7) + COLW - gx, gh = 380;
179
+ c.fillStyle = BLACK; c.fillRect(gx, gy, gw * E.out(S(t0, t0 + 0.3)), 2); c.fillRect(gx, gy - gh * E.out(S(t0, t0 + 0.3)), 2, gh * E.out(S(t0, t0 + 0.3)));
180
+ for (let k = 0; k <= 5; k++) { const v = 50 + k * 10, y = gy - (v - 50) / 50 * gh; c.fillStyle = 'rgba(20,20,20,0.18)'; c.fillRect(gx, y, gw, 1); c.textAlign = 'right'; txt(v + '%', gx - 10, y + 7, 20, 400); c.textAlign = 'left'; }
181
+ txt('Accuracy', gx, gy - gh - 14, 28, 800); c.textAlign = 'right'; txt('Training rounds →', gx + gw, gy + 38, 28, 600); c.textAlign = 'left';
182
+ const prog = E.inOut(S(t0 + 0.2, 12.2)), N = 40, pts = [];
183
+ for (let i = 0; i <= N; i++) { const u = i / N, acc = 61 + 36 * (1 - Math.pow(1 - u, 2.2)) + Math.sin(i * 2.3) * 1.2 * (1 - u); pts.push([gx + u * gw, gy - (acc - 50) / 50 * gh]); }
184
+ const m = Math.floor(prog * N);
185
+ c.strokeStyle = RED; c.lineWidth = 5; c.lineJoin = 'round'; c.beginPath(); for (let i = 0; i <= m; i++) i ? c.lineTo(...pts[i]) : c.moveTo(...pts[i]); c.stroke();
186
+ if (m > 0) { c.fillStyle = RED; c.beginPath(); c.arc(pts[m][0], pts[m][1], 8, 0, 7); c.fill(); }
187
+ const acc = Math.round(H.lerp(61, 97, prog));
188
+ const em = E.out(S(12.15, 12.35)); // emphasis: red block slams behind the final number
189
+ if (em > 0) { c.fillStyle = RED; c.fillRect(colX(8) - 8, 236, (colX(11) + COLW - colX(8) + 16) * em, 190); }
190
+ c.font = '800 150px "Inter"'; c.letterSpacing = '-8px'; c.fillStyle = em >= 1 ? PAPER : BLACK; c.fillText(acc + '%', colX(8), 390); c.letterSpacing = '0px';
191
+ txt('Accuracy per round', colX(8), 222, 28, 600); txt('61% → 97%', colX(8), 470, 36, 800, BLACK, -1);
192
+ }
193
+
194
+ // ---------- page 3: takeaway ----------
195
+ if (page === 3) {
196
+ const t0 = swap(WIPES[2]);
197
+ c.font = '800 112px "Inter"'; c.letterSpacing = '-5px'; c.fillStyle = BLACK;
198
+ const r1 = E.inOut(S(t0, t0 + 0.4)), r2 = E.inOut(S(t0 + 0.15, t0 + 0.55));
199
+ c.save(); c.beginPath(); c.rect(0, 190, W, 154); c.clip(); c.fillText('More examples', M - 5, 318 + (1 - r1) * 130); c.restore();
200
+ c.save(); c.beginPath(); c.rect(0, 344, W, 150); c.clip(); c.fillText('better guesses.', M - 5 + 160, 458 + (1 - r2) * 130); c.restore();
201
+ c.letterSpacing = '0px';
202
+ rule(c, M + 6, 410, M + 140, 410, E.out(S(t0 + 0.3, t0 + 0.6)), 12, RED);
203
+ c.fillStyle = BLACK; c.fillRect(colX(0), 560, (colX(11) + COLW - colX(0)) * E.out(S(t0 + 0.3, t0 + 0.8)), 2);
204
+ if (t > t0 + 0.6) { txt('1,000,000 examples', colX(0), 598, 28, 600); txt('Guess · Check · Adjust', colX(4), 598, 28, 600); txt('61% → 97% accuracy', colX(8), 598, 28, 600, RED); }
205
+ }
206
+
207
+ // ---------- the column wipes ----------
208
+ for (const w of WIPES) {
209
+ if (t < w || t > w + 1.2) continue;
210
+ c.fillStyle = w === WIPES[2] ? BLACK : RED;
211
+ for (let i = 0; i < 12; i++) { const a = E.inOut(S(w + i * 0.025, w + i * 0.025 + 0.28)), b = E.inOut(S(w + 0.6 + i * 0.025, w + 0.88 + i * 0.025)); const x = i * W / 12; if (a > b) c.fillRect(x, b * HH, W / 12 + 1, (a - b) * HH); }
212
+ }
213
+
214
+ // ---------- offset-print finish ----------
215
+ const img = c.getImageData(0, 0, W, HH), d = img.data, n1 = exField('n1', W, HH, 3, 3, 2), n2 = exField('n2', W, HH, 8, 60, 3), sm = speckMask(W, HH);
216
+ for (let i = 0, p = 0; i < d.length; i += 4, p++) { if (!d[i + 3]) continue; d[i + 3] *= Math.max(0, 1 - 0.07 * Math.max(0, n1[p] * 1.5 + n2[p]) - sm[p]); }
217
+ c.putImageData(img, 0, 0);
218
+ ctx.save(); ctx.globalAlpha = 0.12; ctx.filter = 'blur(1.2px)'; ctx.drawImage(L, 0, 0); ctx.restore();
219
+ ctx.save(); ctx.globalCompositeOperation = 'multiply'; ctx.drawImage(L, 0, 0); ctx.restore();
220
+ const pi = ctx.getImageData(0, 0, W, HH), pd = pi.data, fib = exField('fib', W, HH, 21, 2, 2, 3, 0.6), lo = exField('lo', W, HH, 22, 30, 3), rg = H.rng(99 + Math.floor(t * 12));
221
+ for (let i = 0, p = 0; i < pd.length; i += 4, p++) { const s = 1 + fib[p] * 0.022 + lo[p] * 0.02 + (rg() - 0.5) * 0.03; pd[i] *= s; pd[i + 1] *= s; pd[i + 2] *= s; }
222
+ ctx.putImageData(pi, 0, 0);
223
+ H.vignette(ctx, W, HH, 0.07, '40,30,20');
224
+ };
225
+
226
+ registerStyle({
227
+ id: 'swiss-grid',
228
+ name: 'International Typographic Style',
229
+ category: 'Art & Design Movements',
230
+ description: 'A 1960s Zürich-school concert-style poster: strict 12-column modular grid, enormous flush-left grotesk set tight, an asymmetric field of rotating concentric arc segments over a red disc, and small precise info blocks hung from the grid — red, black and white only.',
231
+ motion: 'Rules draw out along the grid, the red disc opens and the ring segments spin in and decelerate until they lock onto a 22.5° module; the headline rises line by line out of its baseline masks and the info blocks step in column by column, then the rings drift like a slow mechanical score.',
232
+ fonts: ['800 180px "Inter"', '600 13px "Inter"', '400 13px "Inter"'],
233
+ frameT: 4.6,
234
+ duration: 5,
235
+ readsPixels: true,
236
+ explainerDuration: 15,
237
+ explainerNote: 'A Zürich-school information sequence on the same 12-column grid: the headline shrinks into a running header, pages change with a column-by-column red wipe, hairline rules with solid heads carry cause and flow, numbers count in Inter 800 and the key result gets a red block slammed behind it.',
238
+ explainer(ctx, W, HH, t) { explainSwiss(ctx, W, HH, t); },
239
+ // Sound: clean and exact. Page wipes are a riffle of 12 sheets falling column by column (left to right), set type
240
+ // lands with a dry tap, hairline rules get a faint ruling-pen draw, counters click like a fine mechanical counter,
241
+ // and the few tonal moments (wrong, correct, 97%, takeaway) are plain soft sine chimes. Times copied from explainSwiss().
242
+ explainerSound(k) {
243
+ const D = 15, E = H.ease, cl = H.clamp;
244
+ const S = (t, a, b) => cl((t - a) / (b - a), 0, 1);
245
+ const M = 48, PITCH = 100, colX = (i) => M + i * PITCH; // grid, as in explainSwiss
246
+ const pan = (px) => cl((px / 1280) * 2 - 1, -1, 1) * 0.7;
247
+ const when = (a, b, ease, u) => { for (let i = 0; i <= 400; i++) if (ease(i / 400) >= u - 1e-6) return a + ((b - a) * i) / 400; return b; };
248
+ const backLand = (a, b) => a + (b - a) * 0.37; // back ease first reaches full size at 37%
249
+ const WIPES = [5.8, 10.3, 12.7], swap = (w) => w + 0.58;
250
+ // dry tap: set type or a pictogram landing on the sheet
251
+ const tap = (t, g, p, minor = true) => { k.noise(t, { dur: 0.03, filter: 'bandpass', f: 1700, q: 1.2, gain: 0.3 * g, a: 0.001, pan: p, minor }); k.tone(t, { f: 190, dur: 0.05, gain: 0.12 * g, pan: p, minor }); };
252
+ // fine mechanical counter click
253
+ const cnt = (t, g, p) => k.withMinor(() => { k.noise(t, { dur: 0.018, filter: 'bandpass', f: 3000, q: 2, gain: 0.34 * g, a: 0.001, pan: p }); k.tone(t, { f: 700, type: 'triangle', dur: 0.025, gain: 0.04 * g, pan: p }); });
254
+ // ruling pen along a hairline: faint, smooth, low
255
+ const ruleDraw = (t, dur, g, p) => k.noise(t, { dur: dur + 0.05, color: 'pink', filter: 'bandpass', f: [[0, 800], [dur, 1200]], q: 1, gain: 0.06 * g, a: dur * 0.3, pan: p, minor: true });
256
+ // the column wipe: 12 sheets drop one after another, left to right, landing at w + i*0.025 + 0.28
257
+ const riffle = (w, g) => {
258
+ k.noise(w + 0.05, { dur: 0.55, color: 'pink', filter: 'bandpass', f: [[0, 500], [0.3, 1100], [0.55, 600]], q: 0.8, gain: 0.05 * g, a: 0.22 });
259
+ for (let i = 0; i < 12; i++) { const ti = w + i * 0.025 + 0.28, p = (i / 11 - 0.5) * 1.4;
260
+ k.noise(ti, { dur: 0.035, filter: 'bandpass', f: 1300 + (i % 3) * 180, q: 1, gain: 0.24 * g, a: 0.002, pan: p }); k.tone(ti, { f: 150, dur: 0.05, gain: 0.05 * g, pan: p }); }
261
+ };
262
+ // plain soft sine chime (kept low: no high pings)
263
+ const chime = (t, n, g, p, minor) => { const f = k.hz(n); k.tone(t, { f, dur: 1.1, gain: 0.16 * g, a: 0.004, pan: p, verb: 0.25, minor }); k.tone(t, { f: f * 2, dur: 0.35, gain: 0.03 * g, a: 0.003, pan: p, minor }); };
264
+
265
+ k.bed('room', 0, D, { gain: 0.3 });
266
+
267
+ // ---- hook: header rule (0-0.7), headline rises line by line (inOut 0.15-0.65, 0.35-0.85), red disc (back 0.5-1.0)
268
+ ruleDraw(0.0, 0.65, 1, -0.2);
269
+ tap(when(0.15, 0.65, E.inOut, 0.97), 1.1, -0.5, false);
270
+ tap(when(0.35, 0.85, E.inOut, 0.97), 1.1, -0.3, false);
271
+ k.play('thud', backLand(0.5, 1.0), { f: 120, gain: 0.45, pan: pan(942) });
272
+ tap(backLand(0.5, 1.0), 0.6, pan(942));
273
+ // headline shrinks into the running header (1.7-2.4): a soft slide
274
+ k.noise(1.7, { dur: 0.7, color: 'pink', filter: 'bandpass', f: [[0, 350], [0.7, 800]], q: 0.7, gain: 0.07, a: 0.3, pan: -0.4, minor: true });
275
+
276
+ // ---- page 0: DATA
277
+ ruleDraw(2.4, 0.5, 1, pan(300));
278
+ tap(backLand(2.6, 2.9), 0.9, pan(90)); // cat pictogram
279
+ tap(backLand(2.75, 3.05), 0.9, pan(290)); // dog pictogram
280
+ k.play('tock', when(2.9, 3.4, E.out, 0.97), { f: 330, gain: 0.5, pan: pan(900), minor: true }); // model block set
281
+ tap(3.32, 0.8, pan(184)); tap(3.46, 0.8, pan(384)); // "cat" / "dog" labels at the leader heads
282
+ // matrix fills in reading order: a soft tap each time a row of 16 completes (n = 128 * S(3.2,5.5)^0.8)
283
+ const rows = []; for (let r = 1; r <= 8; r++) rows.push(3.2 + 2.3 * Math.pow(r / 8, 1.25));
284
+ rows.forEach((t) => { if (Math.abs(t - 3.32) > 0.08 && Math.abs(t - 3.46) > 0.08) tap(t, 0.45, pan(330), true); });
285
+ // counter n = S(3.0,5.6)^3 * 1e6: clicks speeding up, keeping clear of the row taps
286
+ for (let t = 3.05; t < 5.52; ) { const s = S(t, 3.0, 5.6); if (![...rows, 3.32, 3.46].some((r) => t > r - 0.07 && t < r + 0.08)) cnt(t, 0.8 + 0.3 * s, pan(900)); t += 0.16 - 0.075 * s; }
287
+ k.play('thud', 5.6, { f: 150, gain: 0.55, pan: pan(900) }); tap(5.6, 1.2, pan(900), false); // 1,000,000 set
288
+
289
+ // ---- page wipes
290
+ riffle(WIPES[0], 1); riffle(WIPES[0] + 0.6, 0.6); // red columns fall, then lift off the new page
291
+ riffle(WIPES[1], 1); riffle(WIPES[1] + 0.6, 0.6);
292
+ riffle(WIPES[2], 1); riffle(WIPES[2] + 0.6, 0.6);
293
+
294
+ // ---- page 1: GUESS / CHECK / ADJUST (t0 = swap(5.8) = 6.38)
295
+ const p1 = swap(WIPES[0]);
296
+ tap(backLand(p1 + 0.15, p1 + 0.5), 0.8, pan(130)); // cat picture + nodes
297
+ // forward pass (7.0-7.6): a quiet travelling sweep left -> right
298
+ k.noise(7.0, { dur: 0.6, color: 'pink', filter: 'bandpass', f: [[0, 600], [0.6, 1500]], q: 1.5, gain: 0.07, a: 0.2, pan: 0.1, minor: true });
299
+ tap(7.5, 1, pan(980), false); // "dog?" set, output node ringed
300
+ // check (7.75-8.0): red strike, cross — the wrong guess
301
+ k.noise(7.75, { dur: 0.12, filter: 'bandpass', f: [[0, 900], [0.12, 2200]], q: 0.8, gain: 0.18, a: 0.01, pan: pan(1060) });
302
+ k.play('thud', 7.82, { f: 110, gain: 0.7, pan: pan(1150) });
303
+ k.tone(7.82, { f: 'A2', type: 'triangle', dur: 0.5, gain: 0.16, a: 0.005, filter: 'lowpass', f2: 900, pan: pan(1150) });
304
+ k.tone(7.82, { f: 'Bb2', type: 'triangle', dur: 0.5, gain: 0.14, a: 0.005, filter: 'lowpass', f2: 900, pan: pan(1150) });
305
+ // error flows back right -> left (7.85-8.45)
306
+ k.noise(7.9, { dur: 0.55, color: 'pink', filter: 'bandpass', f: [[0, 1400], [0.55, 500]], q: 1.5, gain: 0.08, a: 0.15, pan: -0.1, minor: true });
307
+ // weights re-set (inOut 8.35-9.2): fine detents, at least 90 ms apart
308
+ for (let i = 1, lt = 0; i <= 8; i++) { const t = when(8.35, 9.2, E.inOut, i / 8); if (t - lt < 0.09) continue; lt = t; cnt(t, 0.9, pan(500)); }
309
+ ruleDraw(9.0, 0.5, 1, pan(500)); // loop return rule
310
+ tap(9.5, 0.8, pan(450)); // "repeat"
311
+ tap(9.4, 0.8, pan(980)); // "cat" set
312
+ // the correction: check mark + red rule + "Correct." (9.6-9.9)
313
+ chime(9.62, 'C5', 1, pan(1100)); chime(9.72, 'G5', 0.9, pan(1100));
314
+
315
+ // ---- page 2: PROGRESS (t0 = swap(10.3) = 10.88)
316
+ const p2 = swap(WIPES[1]);
317
+ ruleDraw(p2, 0.3, 1, pan(400));
318
+ k.play('stroke', p2 + 0.2, { material: 'pen', dur: 12.2 - p2 - 0.2, gain: 0.18, pan: pan(400), minor: true }); // red line inks along
319
+ for (let t = p2 + 0.22, last = 61, lt = -1; t < 12.12; t += 1 / 120) {
320
+ const v = Math.round(H.lerp(61, 97, E.inOut(S(t, p2 + 0.2, 12.2))));
321
+ if (v !== last && t - lt >= 1 / 11) { cnt(t, 0.9, pan(1000)); last = v; lt = t; }
322
+ }
323
+ // 97%: the red block slams in behind the number (12.15-12.35) — the biggest hit
324
+ const slam = when(12.15, 12.35, E.out, 0.9);
325
+ k.play('impact', slam, { gain: 1.2, pan: pan(1000) });
326
+ k.play('thud', slam, { f: 140, gain: 0.6, pan: pan(1000) });
327
+ ['C4', 'G4', 'C5'].forEach((n, i) => chime(slam + 0.01, n, 0.8, pan(1000) + (i - 1) * 0.15));
328
+
329
+ // ---- page 3: TAKEAWAY (t0 = swap(12.7) = 13.28): two lines rise in, red rule, hairline, footnotes
330
+ const p3 = swap(WIPES[2]);
331
+ tap(when(p3, p3 + 0.4, E.inOut, 0.97), 1, -0.3, false);
332
+ tap(when(p3 + 0.15, p3 + 0.55, E.inOut, 0.97), 1, 0.1, false);
333
+ ruleDraw(p3 + 0.3, 0.5, 1, 0);
334
+ ['C4', 'E4', 'G4', 'C5'].forEach((n, i) => chime(p3 + 0.6 + i * 0.06, n, 0.55 - i * 0.06, (i - 1.5) * 0.25)); // resolves as the footnotes set
335
+ },
336
+ draw(ctx, W, HH, t) {
337
+ const M = 48, PITCH = 100, COLW = 84;
338
+ const colX = (i) => M + i * PITCH;
339
+ const P = (d, dur = 0.6) => H.ease.out(H.clamp((t - d) / dur, 0, 1));
340
+
341
+ // ---------- paper ----------
342
+ ctx.fillStyle = PAPER; ctx.fillRect(0, 0, W, HH);
343
+
344
+ // ---------- art layer (all inks) ----------
345
+ const L = H.layer(W, HH), c = L.getContext('2d');
346
+
347
+ // red disc
348
+ const ox = 958, oy = 262;
349
+ c.fillStyle = RED;
350
+ c.beginPath(); c.arc(ox, oy, 205 * P(0.2, 0.8), 0, Math.PI * 2); c.fill();
351
+
352
+ // concentric arc segments (the "score")
353
+ const rr = H.rng(404);
354
+ c.strokeStyle = BLACK; c.lineCap = 'butt';
355
+ for (let k = 0; k < 17; k++) {
356
+ const rad = 46 + k * 19;
357
+ const lw = H.lerp(12, 5, k / 16);
358
+ const Q = Math.PI / 8; // angles snap to a 22.5° module at the hero frame
359
+ const len = rr.int(2, 9) * Q;
360
+ const spd = rr.range(-0.4, 0.4);
361
+ // the rings spin in and decelerate onto the module (locked at t=3.2), then drift very slowly
362
+ const settle = t < 3.2 ? -Math.pow(3.2 - t, 2) * 0.9 : (t - 3.2) * 0.05;
363
+ const a0 = rr.int(0, 15) * Q + settle * spd * 2.2;
364
+ const grow = P(0.4 + k * 0.06, 0.9);
365
+ c.lineWidth = lw;
366
+ c.beginPath(); c.arc(ox, oy, rad, a0, a0 + len * grow); c.stroke();
367
+ if (rr() < 0.45) { // a second, shorter segment on the same ring
368
+ const b0 = a0 + len + rr.int(1, 3) * Q;
369
+ c.beginPath(); c.arc(ox, oy, rad, b0, b0 + rr.int(1, 3) * Q * grow); c.stroke();
370
+ }
371
+ }
372
+ // one red ring segment outside the disc, bleeding off the top edge
373
+ c.strokeStyle = RED; c.lineWidth = 6;
374
+ { const g = P(1.3, 0.8); if (g > 0) { c.beginPath(); c.arc(ox, oy, 46 + 17 * 19, -Math.PI * 0.95 + t * 0.12, -Math.PI * 0.95 + t * 0.12 + Math.PI * 0.6 * g); c.stroke(); } }
375
+ // centre point
376
+ const cp = H.ease.back(H.clamp((t - 0.9) / 0.35, 0, 1));
377
+ c.fillStyle = PAPER; c.beginPath(); c.arc(ox, oy, 14 * cp, 0, 7); c.fill();
378
+ c.fillStyle = BLACK; c.beginPath(); c.arc(ox, oy, 6 * cp, 0, 7); c.fill();
379
+
380
+ // ---------- headline: huge, flush left, tight ----------
381
+ c.fillStyle = BLACK; c.textBaseline = 'alphabetic';
382
+ c.letterSpacing = '0px';
383
+ c.font = '800 100px "Inter"';
384
+ const targetW = colX(7) + COLW - M; // span cols 0..7
385
+ c.letterSpacing = '-5px';
386
+ const w100 = c.measureText('Networks').width;
387
+ const fs = Math.floor(100 * targetW / w100);
388
+ c.font = `800 ${fs}px "Inter"`; c.letterSpacing = `${-(fs * 0.045).toFixed(1)}px`;
389
+ const baseB = HH - M - 2, lead = fs * 0.84;
390
+ // each line rises out of its own baseline mask
391
+ const rise = (txt, d, yb) => { const p = H.ease.inOut(H.clamp((t - d) / 0.55, 0, 1)); if (p <= 0) return; c.save(); c.beginPath(); c.rect(0, yb - fs * 0.86, W, fs * 0.86 + fs * 0.06); c.clip(); c.fillText(txt, M - fs * 0.055, yb + (1 - p) * fs * 0.9); c.restore(); };
392
+ rise('Neural', 0.95, baseB - lead);
393
+ rise('Networks', 1.15, baseB);
394
+ c.letterSpacing = '0px';
395
+
396
+ // ---------- grid-hung info blocks ----------
397
+ const small = (txt, x, y, wgt = 400, col = BLACK) => { c.font = `${wgt} 13px "Inter"`; c.fillStyle = col; c.fillText(txt, x, y); };
398
+ const LH = 17;
399
+ const top = M + 12;
400
+ const blk = (d) => { const p = P(d, 0.3); c.restore(); c.save(); c.globalAlpha = p; c.translate(0, (1 - p) * 10); };
401
+ c.save();
402
+ c.fillStyle = BLACK; c.fillRect(colX(0), M - 2, (colX(5) + COLW - colX(0)) * H.ease.inOut(H.clamp(t / 0.6, 0, 1)), 3);
403
+ blk(1.65);
404
+ small('Lecture series', colX(0), top + 14, 600);
405
+ small('Machine', colX(0), top + 14 + LH);
406
+ small('Intelligence', colX(0), top + 14 + LH * 2);
407
+
408
+ blk(1.77);
409
+ small('Thursday', colX(2), top + 14, 600);
410
+ small('14 November 2026', colX(2), top + 14 + LH);
411
+ small('19.30 h', colX(2), top + 14 + LH * 2);
412
+
413
+ blk(1.89);
414
+ small('Auditorium E1', colX(4), top + 14, 600);
415
+ small('School of Design', colX(4), top + 14 + LH);
416
+ small('Free admission', colX(4), top + 14 + LH * 2);
417
+
418
+ // big red issue number on grid
419
+ blk(1.7);
420
+ c.font = `800 64px "Inter"`; c.letterSpacing = '-3px'; c.fillStyle = RED;
421
+ c.fillText('04', colX(0) - 3, top + 14 + LH * 2 + 72);
422
+ c.letterSpacing = '0px';
423
+ blk(2.05);
424
+ small('How machines learn', colX(2), top + 14 + LH * 4 + 6, 600);
425
+ small('to see patterns —', colX(2), top + 14 + LH * 5 + 6);
426
+ small('weights, layers and', colX(2), top + 14 + LH * 6 + 6);
427
+ small('the gradient descent.', colX(2), top + 14 + LH * 7 + 6);
428
+
429
+ // bottom-right block under the arc field
430
+ const by = HH - M - LH * 3 + 4;
431
+ c.restore(); c.save();
432
+ c.fillStyle = BLACK; c.fillRect(colX(9), by - 22, (colX(11) + COLW - colX(9)) * H.ease.inOut(H.clamp((t - 0.15) / 0.6, 0, 1)), 3);
433
+ blk(2.2);
434
+ small('Talk 04 / 12', colX(9), by, 600);
435
+ small('Layers, signals,', colX(9), by + LH);
436
+ small('feedback', colX(9), by + LH * 2);
437
+ blk(2.32);
438
+ small('Speaker', colX(11) - 16, by, 600);
439
+ small('Dr. A. Lenz', colX(11) - 16, by + LH);
440
+ small('Zürich', colX(11) - 16, by + LH * 2);
441
+ // tiny vertical colophon on the right margin
442
+ blk(2.5);
443
+ c.save(); c.translate(W - 20, M); c.rotate(Math.PI / 2); small('Printed in Switzerland · Offset 2-colour · 128 × 90.5 cm', 0, 0, 400); c.restore();
444
+ c.restore(); c.globalAlpha = 1;
445
+
446
+ // ---------- offset-print finish on the ink layer ----------
447
+ const img = c.getImageData(0, 0, W, HH), d = img.data;
448
+ const n1 = exField('n1', W, HH, 3, 3, 2), n2 = exField('n2', W, HH, 8, 60, 3), r = H.rng(12);
449
+ for (let i = 0, p = 0; i < d.length; i += 4, p++) {
450
+ if (!d[i + 3]) continue;
451
+ const a = 1 - 0.07 * Math.max(0, n1[p] * 1.5 + n2[p]) - (r() < 0.0015 ? 0.5 : 0);
452
+ d[i + 3] *= a;
453
+ }
454
+ c.putImageData(img, 0, 0);
455
+ // slight dot gain halo: draw the layer once blurred faint, then crisp
456
+ ctx.save(); ctx.globalAlpha = 0.12; ctx.filter = 'blur(1.2px)'; ctx.drawImage(L, 0, 0); ctx.restore();
457
+ ctx.save(); ctx.globalCompositeOperation = 'multiply'; ctx.drawImage(L, 0, 0); ctx.restore();
458
+
459
+ // paper fibre + grain
460
+ const pi = ctx.getImageData(0, 0, W, HH), pd = pi.data, fib = exField('fib', W, HH, 21, 2, 2, 3, 0.6), lo = exField('lo', W, HH, 22, 30, 3), rg = H.rng(99);
461
+ for (let i = 0, p = 0; i < pd.length; i += 4, p++) {
462
+ const s = 1 + fib[p] * 0.022 + lo[p] * 0.02 + (rg() - 0.5) * 0.035;
463
+ pd[i] *= s; pd[i + 1] *= s; pd[i + 2] *= s;
464
+ }
465
+ ctx.putImageData(pi, 0, 0);
466
+ H.vignette(ctx, W, HH, 0.07, '40,30,20');
467
+ },
468
+ });
469
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": 83,
3
+ "name": "International Typographic Style",
4
+ "nameZh": "国际主义字体设计",
5
+ "family": "Art & Design Movements",
6
+ "familyZh": "艺术与设计流派",
7
+ "description": "A 1960s Zürich-school concert-style poster: strict 12-column modular grid, enormous flush-left grotesk set tight, an asymmetric field of rotating concentric arc segments over a red disc, and small precise info blocks hung from the grid — red, black and white only.",
8
+ "motionNotes": "Motion: Rules draw out along the grid, the red disc opens and the ring segments spin in and decelerate until they lock onto a 22.5° module; the headline rises line by line out of its baseline masks and the info blocks step in column by column, then the rings drift like a slow mechanical score.",
9
+ "explainerNotes": "Explainer: A Zürich-school information sequence on the same 12-column grid: the headline shrinks into a running header, pages change with a column-by-column red wipe, hairline rules with solid heads carry cause and flow, numbers count in Inter 800 and the key result gets a red block slammed behind it.",
10
+ "code": "code.js",
11
+ "registeredAs": "swiss-grid",
12
+ "source": "https://www.futurepedia.io/resources/ai-style-atlas/view"
13
+ }