@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,517 @@
1
+ {
2
+ // ISOTYPE (Neurath / Arntz, Vienna Method) pictorial statistics.
3
+ const PAPER = '#EFE7D4', INK = '#26231F', BLUE = '#294C63', RED = '#C2432C', OCHRE = '#D49A33';
4
+
5
+ // Arntz-style standing figure in a 26 x 44 box, origin top-left
6
+ function person(ctx, x, y, s) {
7
+ ctx.save(); ctx.translate(x, y); ctx.scale(s, s);
8
+ ctx.beginPath();
9
+ ctx.arc(13, 5.2, 5.2, 0, Math.PI * 2);
10
+ // torso with arms (one silhouette), rounded shoulders
11
+ ctx.moveTo(4.5, 12.5);
12
+ ctx.quadraticCurveTo(13, 10.6, 21.5, 12.5);
13
+ ctx.quadraticCurveTo(25.5, 13.4, 25.5, 17.5);
14
+ ctx.lineTo(25.5, 28.5); ctx.lineTo(22.5, 28.5); ctx.lineTo(22.2, 19.5);
15
+ ctx.lineTo(21.0, 19.5); ctx.lineTo(20.8, 28.5);
16
+ // legs
17
+ ctx.lineTo(20.8, 44); ctx.lineTo(14.2, 44); ctx.lineTo(13.6, 30.5); ctx.lineTo(12.4, 30.5); ctx.lineTo(11.8, 44); ctx.lineTo(5.2, 44);
18
+ ctx.lineTo(5.2, 28.5); ctx.lineTo(5.0, 19.5); ctx.lineTo(3.8, 19.5); ctx.lineTo(3.5, 28.5); ctx.lineTo(0.5, 28.5);
19
+ ctx.lineTo(0.5, 17.5); ctx.quadraticCurveTo(0.5, 13.4, 4.5, 12.5);
20
+ ctx.closePath();
21
+ ctx.fill();
22
+ ctx.restore();
23
+ }
24
+
25
+ // compute unit: Arntz-style computer (monitor + keyboard) in a 32 x 44 box
26
+ function chip(ctx, x, y, s, bg) {
27
+ const ink = ctx.fillStyle;
28
+ ctx.save(); ctx.translate(x, y); ctx.scale(s, s);
29
+ // monitor body
30
+ ctx.beginPath();
31
+ ctx.moveTo(2, 4); ctx.lineTo(30, 4); ctx.quadraticCurveTo(32, 4, 32, 6); ctx.lineTo(32, 27);
32
+ ctx.quadraticCurveTo(32, 29, 30, 29); ctx.lineTo(2, 29); ctx.quadraticCurveTo(0, 29, 0, 27); ctx.lineTo(0, 6);
33
+ ctx.quadraticCurveTo(0, 4, 2, 4); ctx.closePath(); ctx.fill();
34
+ // neck + foot
35
+ ctx.fillRect(12.5, 29, 7, 5); ctx.fillRect(8, 33, 16, 2.5);
36
+ // keyboard slab
37
+ ctx.beginPath(); ctx.moveTo(3, 44); ctx.lineTo(6, 38.5); ctx.lineTo(26, 38.5); ctx.lineTo(29, 44); ctx.closePath(); ctx.fill();
38
+ // screen (negative space) with a single bright prompt line
39
+ ctx.fillStyle = bg; ctx.fillRect(4, 8, 24, 17);
40
+ ctx.fillStyle = ink; ctx.fillRect(7, 11, 10, 2.6); ctx.fillRect(7, 16, 14, 2.6); ctx.fillRect(7, 21, 6, 2.6);
41
+ ctx.restore();
42
+ }
43
+
44
+ // data-centre (factory-like silhouette) for the key
45
+ function factory(ctx, x, y, s) {
46
+ ctx.save(); ctx.translate(x, y); ctx.scale(s, s);
47
+ ctx.beginPath();
48
+ ctx.moveTo(0, 44); ctx.lineTo(0, 22); ctx.lineTo(9, 16); ctx.lineTo(9, 22); ctx.lineTo(18, 16); ctx.lineTo(18, 22);
49
+ ctx.lineTo(27, 16); ctx.lineTo(27, 6); ctx.lineTo(33, 6); ctx.lineTo(33, 44); ctx.closePath();
50
+ ctx.fill(); ctx.restore();
51
+ }
52
+
53
+ // ---- explainer pictograms (Arntz-style flat silhouettes) ----
54
+ function catPic(ctx, x, y, s, bg) {
55
+ ctx.save(); ctx.translate(x, y); ctx.scale(s, s);
56
+ ctx.beginPath(); ctx.arc(14, 12, 7.5, 0, 7);
57
+ ctx.moveTo(7.2, 9); ctx.lineTo(8, -0.5); ctx.lineTo(13, 5); ctx.closePath();
58
+ ctx.moveTo(20.8, 9); ctx.lineTo(20, -0.5); ctx.lineTo(15, 5); ctx.closePath();
59
+ ctx.moveTo(8.5, 19); ctx.bezierCurveTo(1, 28, 2, 44, 5, 44); ctx.lineTo(23, 44); ctx.bezierCurveTo(26, 44, 27, 28, 19.5, 19); ctx.closePath();
60
+ ctx.fill();
61
+ ctx.lineWidth = 3.4; ctx.lineCap = 'round'; ctx.strokeStyle = ctx.fillStyle;
62
+ ctx.beginPath(); ctx.moveTo(22, 42); ctx.quadraticCurveTo(32, 40, 29, 28); ctx.stroke();
63
+ ctx.fillStyle = bg; ctx.fillRect(13.3, 31, 1.4, 13);
64
+ ctx.beginPath(); ctx.arc(11, 11.5, 1.3, 0, 7); ctx.arc(17, 11.5, 1.3, 0, 7); ctx.fill();
65
+ ctx.restore();
66
+ }
67
+ function dogPic(ctx, x, y, s, bg) {
68
+ ctx.save(); ctx.translate(x, y); ctx.scale(s, s);
69
+ ctx.beginPath();
70
+ ctx.moveTo(7, 6); ctx.quadraticCurveTo(7, 1, 13, 1); ctx.lineTo(19, 1); ctx.quadraticCurveTo(23, 1, 23, 6); ctx.lineTo(23, 9); ctx.lineTo(30, 10); ctx.quadraticCurveTo(32, 14, 29, 17); ctx.lineTo(21, 18);
71
+ ctx.bezierCurveTo(27, 26, 27, 44, 24, 44); ctx.lineTo(5, 44); ctx.bezierCurveTo(2, 44, 1, 28, 8, 18); ctx.quadraticCurveTo(6, 12, 7, 6); ctx.closePath();
72
+ ctx.fill();
73
+ ctx.lineWidth = 3.4; ctx.lineCap = 'round'; ctx.strokeStyle = ctx.fillStyle;
74
+ ctx.beginPath(); ctx.moveTo(5, 40); ctx.quadraticCurveTo(-3, 36, -1, 27); ctx.stroke();
75
+ ctx.fillStyle = bg; ctx.fillRect(14.3, 31, 1.4, 13);
76
+ ctx.beginPath(); ctx.arc(18, 7.5, 1.4, 0, 7); ctx.fill();
77
+ ctx.beginPath(); ctx.moveTo(8, 4); ctx.quadraticCurveTo(4, 9, 7, 16); ctx.lineTo(9.5, 15); ctx.quadraticCurveTo(8.5, 9, 10.5, 5); ctx.closePath(); ctx.fill();
78
+ ctx.restore();
79
+ }
80
+ // flat ISOTYPE arrow (shaft + head), optionally curved via a quadratic control point
81
+ function flatArrow(ctx, x0, y0, x1, y1, w, p = 1, cx = null, cy = null) {
82
+ if (p <= 0) return;
83
+ const pts = [];
84
+ const n = 30;
85
+ for (let k = 0; k <= n * p; k++) {
86
+ const u = k / n;
87
+ if (cx === null) pts.push([H.lerp(x0, x1, u), H.lerp(y0, y1, u)]);
88
+ else { const a = (1 - u) * (1 - u), b = 2 * u * (1 - u), c = u * u; pts.push([a * x0 + b * cx + c * x1, a * y0 + b * cy + c * y1]); }
89
+ }
90
+ if (pts.length < 2) return;
91
+ const [ex, ey] = pts[pts.length - 1], [px, py] = pts[pts.length - 2];
92
+ const an = Math.atan2(ey - py, ex - px);
93
+ ctx.save(); ctx.lineWidth = w; ctx.lineCap = 'butt'; ctx.lineJoin = 'round'; ctx.strokeStyle = ctx.fillStyle;
94
+ ctx.beginPath(); pts.slice(0, -1).forEach(([x, y], i) => (i ? ctx.lineTo(x, y) : ctx.moveTo(x, y)));
95
+ ctx.lineTo(ex - Math.cos(an) * w * 0.9, ey - Math.sin(an) * w * 0.9); ctx.stroke();
96
+ ctx.beginPath(); ctx.moveTo(ex + Math.cos(an) * w * 0.9, ey + Math.sin(an) * w * 0.9);
97
+ ctx.lineTo(ex - Math.cos(an) * w * 0.9 + Math.cos(an + Math.PI / 2) * w * 1.25, ey - Math.sin(an) * w * 0.9 + Math.sin(an + Math.PI / 2) * w * 1.25);
98
+ ctx.lineTo(ex - Math.cos(an) * w * 0.9 - Math.cos(an + Math.PI / 2) * w * 1.25, ey - Math.sin(an) * w * 0.9 - Math.sin(an + Math.PI / 2) * w * 1.25);
99
+ ctx.closePath(); ctx.fill(); ctx.restore();
100
+ }
101
+ function checkPic(ctx, x, y, s) { ctx.save(); ctx.translate(x, y); ctx.scale(s, s); ctx.lineWidth = 7; ctx.lineCap = 'butt'; ctx.lineJoin = 'miter'; ctx.strokeStyle = ctx.fillStyle; ctx.beginPath(); ctx.moveTo(2, 22); ctx.lineTo(11, 31); ctx.lineTo(30, 6); ctx.stroke(); ctx.restore(); }
102
+ function crossPic(ctx, x, y, s) { ctx.save(); ctx.translate(x, y); ctx.scale(s, s); ctx.lineWidth = 7; ctx.lineCap = 'butt'; ctx.strokeStyle = ctx.fillStyle; ctx.beginPath(); ctx.moveTo(3, 3); ctx.lineTo(29, 29); ctx.moveTo(29, 3); ctx.lineTo(3, 29); ctx.stroke(); ctx.restore(); }
103
+
104
+ const ROWS = [
105
+ { yr: '2000', p: 4.5, c: 0.25 },
106
+ { yr: '2005', p: 5.25, c: 0.5 },
107
+ { yr: '2010', p: 6.5, c: 1.5 },
108
+ { yr: '2015', p: 7.75, c: 3.5 },
109
+ { yr: '2020', p: 9.25, c: 7.25 },
110
+ { yr: '2025', p: 10.5, c: 13.5 },
111
+ ];
112
+
113
+ // ---- litho finish, cached once per size ----
114
+ // paper mottle: one fbm per 4x4 px, drawn upscaled with smoothing (no blocky squares, no per-frame noise)
115
+ const MOTTLE = {};
116
+ function mottle(W, H_, oct) {
117
+ const key = W + 'x' + H_ + 'x' + oct;
118
+ if (MOTTLE[key]) return MOTTLE[key];
119
+ const w = Math.ceil(W / 4), h = Math.ceil(H_ / 4), L = H.layer(w, h), c = L.getContext('2d'), id = c.createImageData(w, h);
120
+ const nz = H.makeNoise(4);
121
+ for (let j = 0; j < h; j++) for (let i = 0; i < w; i++) {
122
+ const v = nz.fbm2((i * 4 + 2) * 0.006, (j * 4 + 2) * 0.006, oct), o = (j * w + i) * 4;
123
+ id.data[o] = 150; id.data[o + 1] = 120; id.data[o + 2] = 80; id.data[o + 3] = v > 0.05 ? Math.min(255, (v - 0.05) * 0.06 * 255) : 0;
124
+ }
125
+ c.putImageData(id, 0, 0);
126
+ return (MOTTLE[key] = L);
127
+ }
128
+ function lithoFinish(ctx, W, H_, oct) {
129
+ ctx.save(); ctx.globalCompositeOperation = 'multiply'; ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = 'high';
130
+ ctx.drawImage(mottle(W, H_, oct), 0, 0, W, H_); ctx.restore();
131
+ }
132
+ // ink film wear: where the litho ink did not fully take. Low-frequency density drift + fine pinholes and a few
133
+ // dry streaks, removed from the ink layer with destination-out so paper shows through the flat fills.
134
+ const WEAR = {};
135
+ function wear(W, H_) {
136
+ const key = W + 'x' + H_;
137
+ if (WEAR[key]) return WEAR[key];
138
+ const L = H.layer(W, H_), c = L.getContext('2d');
139
+ const w = Math.ceil(W / 3), h = Math.ceil(H_ / 3), S = H.layer(w, h), sc = S.getContext('2d'), id = sc.createImageData(w, h);
140
+ const nz = H.makeNoise(23), rf = H.rng(5);
141
+ for (let j = 0; j < h; j++) for (let i = 0; i < w; i++) {
142
+ const v = nz.fbm2(i * 0.05, j * 0.05, 3), f = nz.n2(i * 0.6 + 40, j * 0.6), o = (j * w + i) * 4;
143
+ // coarse density drift + an 'orange-peel' fine stipple where the ink film is thin
144
+ const a = Math.max(0, v * 0.5 + 0.5 - 0.4) * 0.34 + Math.max(0, f) * 0.07 + rf() * 0.035;
145
+ id.data[o + 3] = Math.min(255, a * 255);
146
+ }
147
+ sc.putImageData(id, 0, 0);
148
+ c.imageSmoothingEnabled = true; c.drawImage(S, 0, 0, W, H_);
149
+ const r = H.rng(77);
150
+ c.fillStyle = '#000';
151
+ for (let n = 0; n < W * H_ * 0.0016; n++) { // pinholes
152
+ const x = r() * W, y = r() * H_, rr = 0.5 + r() * r() * 1.4;
153
+ c.globalAlpha = 0.25 + r() * 0.55; c.beginPath(); c.arc(x, y, rr, 0, 7); c.fill();
154
+ }
155
+ c.globalAlpha = 0.09;
156
+ for (let n = 0; n < 140; n++) { // faint horizontal roller streaks
157
+ const x = r() * W, y = r() * H_; c.fillRect(x, y, 20 + r() * 90, 0.8 + r() * 0.8);
158
+ }
159
+ c.globalAlpha = 1;
160
+ return (WEAR[key] = L);
161
+ }
162
+ const INKL = {};
163
+ function inkLayer(W, H_) {
164
+ const key = W + 'x' + H_;
165
+ const L = INKL[key] || (INKL[key] = H.layer(W, H_)), c = L.getContext('2d');
166
+ c.setTransform(1, 0, 0, 1, 0, 0); c.globalAlpha = 1; c.globalCompositeOperation = 'source-over'; c.clearRect(0, 0, W, H_);
167
+ return L;
168
+ }
169
+ function printInk(out, L, W, H_) {
170
+ const c = L.getContext('2d');
171
+ c.save(); c.setTransform(1, 0, 0, 1, 0, 0); c.globalAlpha = 1; c.globalCompositeOperation = 'destination-out'; c.drawImage(wear(W, H_), 0, 0); c.restore();
172
+ out.save(); out.setTransform(1, 0, 0, 1, 0, 0); out.drawImage(L, 0, 0); out.restore();
173
+ }
174
+
175
+ function spaced(ctx, str, x, y, track, align) {
176
+ let w = 0; for (const ch of str) w += ctx.measureText(ch).width + track; w -= track;
177
+ let cx = align === 'center' ? x - w / 2 : align === 'right' ? x - w : x;
178
+ ctx.textAlign = 'left';
179
+ for (const ch of str) { ctx.fillText(ch, cx, y); cx += ctx.measureText(ch).width + track; }
180
+ }
181
+
182
+ registerStyle({
183
+ id: 'isotype',
184
+ name: 'ISOTYPE Pictograms',
185
+ category: 'Data & Information',
186
+ description: 'Vienna Method pictorial statistics: rows of identical flat pictograms where each symbol is a fixed quantity, partial symbols for remainders, three muted litho inks on a strict grid with geometric sans lettering.',
187
+ motion: 'Title and key set first, the year column drops in, then symbols are stamped out row by row from the centre in stepped, rubber-stamp timing, the 2025 row of machines racing ahead; the litho paper breathes in the hold.',
188
+ fonts: ['700 40px "Space Grotesk"', '400 18px "Space Grotesk"', '700 26px "Space Grotesk"', '400 14px "Space Grotesk"', '700 14px "Space Grotesk"', '700 96px "Space Grotesk"', '700 32px "Space Grotesk"', '400 24px "Space Grotesk"'],
189
+ duration: 5.5,
190
+ frameT: 5.4,
191
+ readsPixels: true,
192
+ draw(ctx, W, H_, t) {
193
+ H.paper(ctx, W, H_, PAPER, 11, 0.02);
194
+ const OUT = ctx, IL = inkLayer(W, H_); ctx = IL.getContext('2d');
195
+
196
+ const CX = 640, colHalf = 56, pitch = 36, rowH = 66, top = 214;
197
+ const s = 1.0;
198
+ // stepped clock: the stamping runs "on twos" at 12 fps like a mechanical counter
199
+ const ts = Math.floor(t * 12) / 12;
200
+ const seg = (a, b) => H.clamp((ts - a) / (b - a));
201
+ // per-icon stamp: invisible -> oversized impression (one step) -> settled
202
+ const stampAt = (start) => (ts < start ? 0 : ts < start + 1 / 12 ? 0.5 : 1);
203
+
204
+ // ---- title block ----
205
+ ctx.fillStyle = INK; ctx.textBaseline = 'alphabetic';
206
+ ctx.globalAlpha = seg(0, 0.34);
207
+ ctx.font = '700 40px "Space Grotesk"'; spaced(ctx, 'PEOPLE AND MACHINES', CX, 86 - (1 - seg(0, 0.34)) * 8, 5, 'center');
208
+ ctx.globalAlpha = seg(0.25, 0.6);
209
+ ctx.font = '400 18px "Space Grotesk"';
210
+ spaced(ctx, 'Workers and machines for AI in the computing industry, 2000–2025', CX, 120, 0.6, 'center');
211
+ ctx.globalAlpha = 1;
212
+ const rp = H.ease.out(seg(0.3, 0.75));
213
+ ctx.fillStyle = INK; ctx.fillRect(CX - 300 * rp, 140, 600 * rp, 2);
214
+
215
+ // ---- column heads with keys ----
216
+ ctx.globalAlpha = seg(0.5, 0.84);
217
+ ctx.font = '700 14px "Space Grotesk"';
218
+ ctx.fillStyle = BLUE; person(ctx, CX - colHalf - 30, 156, 0.62);
219
+ ctx.fillStyle = INK; spaced(ctx, 'WORKERS', CX - colHalf - 40, 176, 2.5, 'right');
220
+ ctx.font = '400 14px "Space Grotesk"'; spaced(ctx, 'each figure = 1 million', CX - colHalf - 40, 194, 0.4, 'right');
221
+ ctx.fillStyle = RED; chip(ctx, CX + colHalf + 6, 156, 0.62, PAPER);
222
+ ctx.fillStyle = INK; ctx.font = '700 14px "Space Grotesk"'; spaced(ctx, 'AI COMPUTERS', CX + colHalf + 40, 176, 2.5, 'left');
223
+ ctx.font = '400 14px "Space Grotesk"'; spaced(ctx, 'each machine = 100,000', CX + colHalf + 40, 194, 0.4, 'left');
224
+ ctx.globalAlpha = 1;
225
+
226
+ // ---- centre year column drops in ----
227
+ const colP = H.ease.out(seg(0.6, 1.1));
228
+ ctx.fillStyle = OCHRE;
229
+ ctx.fillRect(CX - colHalf + 8, top - 6, (colHalf - 8) * 2, (ROWS.length * rowH - 2) * colP);
230
+
231
+ // row timing: each row stamps outward from the column, rows in sequence
232
+ const DT = 0.042;
233
+ let rowStart = 1.15;
234
+ ROWS.forEach((row, ri) => {
235
+ const y = top + ri * rowH;
236
+ const t0 = rowStart; rowStart += Math.max(Math.ceil(row.p), Math.ceil(row.c)) * DT + 0.05;
237
+ // year
238
+ if (ts >= 0.75 + ri * 0.06) { ctx.fillStyle = INK; ctx.font = '700 26px "Space Grotesk"'; spaced(ctx, row.yr, CX, y + 36, 1.5, 'center'); }
239
+ // row hairline
240
+ const hp = seg(t0 - 0.15, t0 + 0.35);
241
+ if (ri && hp > 0) { ctx.fillStyle = 'rgba(38,35,31,0.18)'; const lw = (CX - colHalf - 70) * hp; ctx.fillRect(CX - colHalf - lw, y - 4, lw, 1); ctx.fillRect(CX + colHalf, y - 4, (W - 70 - CX - colHalf) * hp, 1); }
242
+
243
+ // workers, growing leftward from the column; partial symbol on the outer end shows its inner part
244
+ const pn = Math.ceil(row.p);
245
+ for (let k = 0; k < pn; k++) {
246
+ const frac = Math.min(1, row.p - k), a = stampAt(t0 + k * DT);
247
+ if (a <= 0) continue;
248
+ const x = CX - colHalf - 14 - (k + 1) * pitch + (pitch - 26 * s) / 2;
249
+ ctx.save();
250
+ if (frac < 1) { ctx.beginPath(); ctx.rect(x + 26 * s * (1 - frac), y, 26 * s * frac + 1, 60); ctx.clip(); }
251
+ ctx.fillStyle = BLUE;
252
+ if (a < 1) { ctx.translate(x + 13, y + 28); ctx.scale(1.14, 1.14); ctx.translate(-x - 13, -y - 28); ctx.globalAlpha = 0.8; }
253
+ person(ctx, x, y + 6, s);
254
+ ctx.restore();
255
+ }
256
+ // chips, growing rightward
257
+ const cn = Math.ceil(row.c);
258
+ for (let k = 0; k < cn; k++) {
259
+ const frac = Math.min(1, row.c - k), a = stampAt(t0 + k * DT);
260
+ if (a <= 0) continue;
261
+ const cs = 0.88, x = CX + colHalf + 14 + k * pitch + (pitch - 32 * cs) / 2;
262
+ ctx.save();
263
+ if (frac < 1) { ctx.beginPath(); ctx.rect(x - 1, y, 32 * cs * frac + 1, 60); ctx.clip(); }
264
+ ctx.fillStyle = RED;
265
+ if (a < 1) { ctx.translate(x + 14, y + 30); ctx.scale(1.14, 1.14); ctx.translate(-x - 14, -y - 30); ctx.globalAlpha = 0.8; }
266
+ chip(ctx, x, y + 6 + 44 * (1 - cs), cs, PAPER);
267
+ ctx.restore();
268
+ }
269
+ });
270
+
271
+ // ---- footer ----
272
+ const fy = top + ROWS.length * rowH + 14;
273
+ const fp = H.ease.out(seg(rowStart, rowStart + 0.4));
274
+ ctx.fillStyle = INK; ctx.fillRect(70, fy, (W - 140) * fp, 2);
275
+ ctx.globalAlpha = seg(rowStart + 0.2, rowStart + 0.6);
276
+ ctx.font = '400 14px "Space Grotesk"'; ctx.fillStyle = INK;
277
+ spaced(ctx, 'Partial symbols show fractions of a unit. Figures are illustrative.', 70, fy + 28, 0.3, 'left');
278
+ ctx.font = '700 14px "Space Grotesk"';
279
+ spaced(ctx, 'AFTER THE VIENNA METHOD', W - 70, fy + 28, 2.2, 'right');
280
+ ctx.globalAlpha = 1;
281
+
282
+ // ---- litho finish: ink film printed onto the paper, slight mottling + grain ----
283
+ printInk(OUT, IL, W, H_); ctx = OUT;
284
+ lithoFinish(ctx, W, H_, 3);
285
+ H.grain(ctx, W, H_, 0.05, 9 + Math.floor(t * 8));
286
+ },
287
+ // Sound: rubber stamps on a chart sheet laid on a wooden table. Every pictogram is a stamp landing on the
288
+ // 12 fps frame it appears (stamp(st) shows at ceil(st*12)/12), numerals advance with a numbering-machine clack,
289
+ // the camera pans are the long sheet sliding on the table. Times mirror explainer() below.
290
+ explainerSound(k) {
291
+ const D = 15;
292
+ const sf = (st) => Math.ceil(st * 12 - 1e-6) / 12; // first frame a stamp(st) / ts >= st is visible
293
+ const pan = (px) => H.clamp((px / 1280) * 2 - 1, -1, 1) * 0.6; // screen x
294
+ // small rubber stamp: a soft pat of rubber on paper with a little table body
295
+ const pat = (t, g = 1, p = 0) => k.withMinor(() => {
296
+ k.noise(t, { dur: 0.04, filter: 'bandpass', f: 950, q: 0.9, gain: 0.3 * g, a: 0.002, pan: p });
297
+ k.tone(t, { f: [[0, 150], [0.06, 70]], dur: 0.08, gain: 0.22 * g, pan: p });
298
+ });
299
+ // big rubber stamp (pictogram blocks, crosses, ticks): the kit stamp, a bit softer and woodier
300
+ const thump = (t, g = 1, p = 0, minor = false) => k.play('stamp', t, { gain: 0.55 * g, pan: p, minor });
301
+ // numbering machine advancing a digit wheel
302
+ const numb = (t, g = 1, p = 0) => k.withMinor(() => {
303
+ k.noise(t, { dur: 0.022, filter: 'bandpass', f: 2100, q: 1.8, gain: 0.26 * g, a: 0.001, pan: p });
304
+ k.tone(t, { f: 410, type: 'triangle', dur: 0.03, gain: 0.06 * g, pan: p });
305
+ });
306
+ // the long sheet slides under the camera: smooth, low, no rustle
307
+ const slide = (t0, t1) => k.noise(t0, { dur: t1 - t0 + 0.1, color: 'brown', filter: 'bandpass', f: [[0, 220], [(t1 - t0) * 0.5, 420], [t1 - t0 + 0.1, 200]], q: 0.6, gain: 0.22, a: (t1 - t0) * 0.45 });
308
+ // flat arrow printed in steps: a short soft brayer pass
309
+ const arrow = (t0, t1, p) => k.noise(sf(t0), { dur: t1 - t0, color: 'brown', filter: 'bandpass', f: 330, q: 1.4, gain: 0.25, a: 0.04, pan: p, minor: true });
310
+
311
+ k.bed('room', 0, D, { gain: 0.4 });
312
+
313
+ // ---- title stamps on, subtitle, rule; then the title slides to the corner (1.5 -> 2.3, smooth time)
314
+ thump(0.0, 0.7);
315
+ pat(sf(0.3), 0.6); // subtitle
316
+ k.noise(1.5, { dur: 0.8, color: 'brown', filter: 'bandpass', f: [[0, 260], [0.8, 380]], q: 0.6, gain: 0.12, a: 0.3, minor: true });
317
+
318
+ // ---- panel A: 20 symbols stamped in order (cats ochre top row, dogs blue bottom row)
319
+ for (let i = 0; i < 20; i++) {
320
+ const kk = Math.floor(i / 2), r = i % 2, t = sf(2.35 + i * 0.09);
321
+ pat(t, 0.75 + 0.25 * ((i * 7) % 5) / 4, pan(150 + kk * 52));
322
+ }
323
+ // numeral re-stamped in 50,000 steps (val changes on the 12 fps grid)
324
+ {
325
+ let last = -1;
326
+ for (let f = Math.ceil(2.5 * 12); f / 12 <= 4.9; f++) {
327
+ const ts = f / 12, n = Math.round(1e6 * H.clamp((ts - 2.5) / 2.3) / 0.05) * 0.05, v = Math.min(1e6, Math.round(n / 50000) * 50000);
328
+ if (v !== last) { if (v < 1e6) numb(ts, 0.8 + 0.3 * v / 1e6, pan(160)); else { k.play('tock', ts, { f: 300, gain: 0.55, pan: pan(160) }); thump(ts, 0.45, pan(160)); } last = v; }
329
+ }
330
+ }
331
+ thump(sf(4.1), 1, pan(1000)); // THE MODEL chip
332
+ arrow(4.4, 5.0, pan(775));
333
+ slide(5.9, 6.6);
334
+
335
+ // ---- panel B: guess, check, adjust
336
+ thump(sf(6.8), 0.9, pan(130)); // GUESS block inks + the new picture
337
+ arrow(7.0, 7.3, pan(260));
338
+ arrow(7.4, 7.7, pan(575));
339
+ thump(sf(7.7), 0.7, pan(800), true); // guess box "DOG?"
340
+ thump(sf(7.9), 1.3, pan(1010)); // red cross: the wrong guess
341
+ k.tone(sf(7.9), { f: 'D3', type: 'triangle', dur: 0.26, gain: 0.22, hold: 0.08, filter: 'lowpass', f2: 900, pan: pan(1010) });
342
+ k.tone(sf(7.9) + 0.15, { f: 'A2', type: 'triangle', dur: 0.18, gain: 0.2, hold: 0.06, filter: 'lowpass', f2: 700, pan: pan(1010) });
343
+ thump(sf(8.2), 1.0, pan(800)); // CHECK block + ANSWER: CAT
344
+ k.noise(sf(8.4), { dur: 0.6, color: 'brown', filter: 'bandpass', f: [[0, 300], [0.6, 240]], q: 1.2, gain: 0.2, a: 0.05, pan: pan(640), minor: true }); // red error arrow curls back
345
+ pat(sf(8.6), 0.8, pan(760)); // ERROR
346
+ thump(sf(8.9), 0.7, pan(-0.2), true); // ADJUST block
347
+ { // dials turn on the stepped clock: a ratchet click each frame they move
348
+ for (let f = Math.ceil(8.9 * 12) + 1; f / 12 <= 9.6; f++) k.play('tock', f / 12, { f: 560 + (f % 3) * 40, gain: 0.32, pan: pan(410), minor: true });
349
+ }
350
+ thump(sf(9.6), 0.6, pan(130), true); // GUESS again
351
+ thump(sf(9.7), 0.8, pan(800), true); // box re-stamped "CAT"
352
+ thump(sf(9.8), 1.0, pan(1010)); // blue tick
353
+ k.play('success', sf(9.8), { f: 'E5', gain: 0.45, pan: pan(1010) });
354
+ slide(10.3, 10.9);
355
+
356
+ // ---- panel C: rows of tick symbols stamp in while the sheet arrives
357
+ pat(sf(10.4), 0.6, -0.4); // RIGHT ANSWERS OUT OF 10
358
+ for (let r = 0; r < 4; r++) {
359
+ const st0 = 10.5 + r * 0.45, frames = new Set();
360
+ for (let q = 0; q < 10; q++) frames.add(sf(st0 + q * 0.03));
361
+ [...frames].forEach((t, j) => pat(t, 0.9 - j * 0.1, -0.3 + j * 0.25));
362
+ if (r > 0) numb(sf(st0), 1.1, 0.75); // hero accuracy re-stamped 61 -> 76 -> 89
363
+ }
364
+ // ROUND 1,000 row: hero numeral stamps 97%: the big hit
365
+ thump(sf(11.85), 1.0, 0.75);
366
+ k.play('impact', sf(11.85), { gain: 0.6, pan: 0.6 });
367
+ k.play('ding', sf(11.85) + 0.02, { f: 'C5', gain: 0.45, pan: 0.6 });
368
+ k.play('roller', sf(12.9), { dur: 0.3, gain: 0.35, minor: true }); // ochre band printed under the best row
369
+
370
+ // ---- takeaway: full-width black block stamped (13.25 appears), then resolves
371
+ thump(sf(13.2), 1.2);
372
+ k.play('press', sf(13.2) + 0.08, { gain: 0.3 });
373
+ ['F4', 'C5', 'A5'].forEach((f, i) => k.play('ding', 13.5 + i * 0.08, { f, gain: 0.38 - i * 0.06, pan: (i - 1) * 0.25 }));
374
+ },
375
+ explainerDuration: 15,
376
+ explainerNote: 'A Vienna-Method picture-statistic told across one long chart sheet the camera pans along: symbols are stamped in stepped 12 fps timing, flat Isotype arrows show flow, numerals are stamped and re-stamped, and accuracy is counted in rows of tick symbols with partial symbols for fractions.',
377
+ explainer(ctx, W, H_, t) {
378
+ const ts = Math.floor(t * 12) / 12; // stepped clock for stamping
379
+ const S = (a, b) => H.clamp((ts - a) / (b - a));
380
+ const stamp = (st) => (ts < st ? 0 : ts < st + 1 / 12 ? 0.5 : 1);
381
+ const big = (a, fn, cx, cy) => { if (a <= 0) return; ctx.save(); if (a < 1) { ctx.translate(cx, cy); ctx.scale(1.15, 1.15); ctx.translate(-cx, -cy); ctx.globalAlpha = 0.8; } fn(); ctx.restore(); };
382
+ const T = (str, x, y, size, align = 'left', col = INK, track = 2, weight = 700) => { ctx.fillStyle = col; ctx.font = `${weight} ${size}px "Space Grotesk"`; spaced(ctx, str, x, y, track, align); };
383
+ H.paper(ctx, W, H_, PAPER, 11, 0.02);
384
+ const OUT = ctx, IL = inkLayer(W, H_); ctx = IL.getContext('2d');
385
+
386
+ // ---- camera: a smooth pan along one long sheet (3 panels) ----
387
+ const PK = [[0, 0], [5.9, 0], [6.6, 1280], [10.3, 1280], [10.9, 2560], [15, 2560]];
388
+ let px = 2560;
389
+ for (let i = 0; i < PK.length - 1; i++) if (t >= PK[i][0] && t <= PK[i + 1][0]) { px = H.lerp(PK[i][1], PK[i + 1][1], H.ease.inOut((t - PK[i][0]) / (PK[i + 1][0] - PK[i][0]))); break; }
390
+ ctx.save(); ctx.translate(-px, 0);
391
+ ctx.textBaseline = 'alphabetic';
392
+
393
+ // ===== panel A: data =====
394
+ {
395
+ const rowY = [150, 250], N = 10, pitch = 52, x0 = 150, sc = 1.4;
396
+ if (ts >= 2.4) { T('CAT', 40, rowY[0] + 44, 30); T('DOG', 40, rowY[1] + 44, 30); }
397
+ for (let r = 0; r < 2; r++) for (let k = 0; k < N; k++) {
398
+ const st = 2.35 + (k * 2 + r) * 0.09, a = stamp(st);
399
+ const x = x0 + k * pitch, y = rowY[r];
400
+ ctx.fillStyle = r ? BLUE : OCHRE;
401
+ big(a, () => (r ? dogPic(ctx, x + 2.5, y + 44 * sc * 0.12, sc * 0.88, PAPER) : catPic(ctx, x, y, sc, PAPER)), x + 20, y + 30);
402
+ }
403
+ if (ts >= 2.5) T('each symbol = 50,000 labelled pictures', 40, 370, 24, 'left', INK, 0.4, 400);
404
+ if (ts >= 2.5) {
405
+ const n = Math.round(1e6 * S(2.5, 4.8) / 0.05) * 0.05;
406
+ const val = Math.min(1e6, Math.round(n / 50000) * 50000);
407
+ T(val.toLocaleString('en-US'), 36, 486, 96, 'left', INK, 3);
408
+ T('EXAMPLES', 40, 530, 28, 'left', INK, 4);
409
+ }
410
+ ctx.fillStyle = INK; flatArrow(ctx, 690, 250, 860, 250, 30, S(4.4, 5.0));
411
+ const ma = stamp(4.1);
412
+ ctx.fillStyle = RED; big(ma, () => chip(ctx, 880, 130, 7.6, PAPER), 1000, 300);
413
+ if (ts >= 4.2) T('THE MODEL', 1002, 500, 34, 'center', INK, 4);
414
+ if (ts > 5.0 && ts < 6.4) for (let k = 0; k < 3; k++) {
415
+ const u = ((ts - 5.0) * 1.6 + k / 3) % 1, x = 700 + u * 140;
416
+ ctx.fillStyle = k % 2 ? BLUE : OCHRE; ctx.globalAlpha = 0.9;
417
+ (k % 2 ? dogPic : catPic)(ctx, x, 186, 0.85, INK);
418
+ ctx.globalAlpha = 1;
419
+ }
420
+ }
421
+
422
+ // ===== panel B: guess, check, adjust (x 1280..2560) =====
423
+ {
424
+ const X = 1280;
425
+ const active = ts < 6.8 ? -1 : ts < 8.2 ? 0 : ts < 8.9 ? 1 : ts < 9.6 ? 2 : 0;
426
+ ['GUESS', 'CHECK', 'ADJUST'].forEach((s, i) => {
427
+ const bx = X + 300 + i * 300, by = 100;
428
+ ctx.fillStyle = i === active ? INK : 'rgba(38,35,31,0.12)'; ctx.fillRect(bx, by, 240, 66);
429
+ T(s, bx + 120, by + 45, 32, 'center', i === active ? PAPER : INK, 4);
430
+ if (i < 2) { ctx.fillStyle = INK; flatArrow(ctx, bx + 246, by + 33, bx + 294, by + 33, 12, 1); }
431
+ });
432
+ ctx.fillStyle = OCHRE; big(stamp(6.8), () => catPic(ctx, X + 76, 230, 3.6, PAPER), X + 126, 310);
433
+ if (ts >= 6.8) T('NEW PICTURE', X + 136, 432, 28, 'center', INK, 2.5);
434
+ ctx.fillStyle = INK; flatArrow(ctx, X + 222, 320, X + 304, 320, 24, S(7.0, 7.3));
435
+ ctx.fillStyle = RED; chip(ctx, X + 320, 196, 5.8, PAPER);
436
+ const turn = H.ease.inOut(S(8.9, 9.6));
437
+ for (let i = 0; i < 3; i++) {
438
+ const dx = X + 352 + i * 62, dy = 490;
439
+ ctx.fillStyle = INK; ctx.beginPath(); ctx.arc(dx, dy, 22, 0, 7); ctx.fill();
440
+ const a0 = [-2.2, -0.6, -1.5][i], a1 = [-0.9, -2.0, -0.4][i], a = H.lerp(a0, a1, turn);
441
+ ctx.strokeStyle = PAPER; ctx.lineWidth = 6; ctx.beginPath(); ctx.moveTo(dx, dy); ctx.lineTo(dx + Math.cos(a) * 16, dy + Math.sin(a) * 16); ctx.stroke();
442
+ }
443
+ if (ts >= 6.8) T('SETTINGS', X + 414, 554, 28, 'center', INK, 3);
444
+ ctx.fillStyle = INK; flatArrow(ctx, X + 520, 320, X + 630, 320, 24, S(7.4, 7.7));
445
+ const g2 = ts >= 9.7;
446
+ if (ts >= 7.7) {
447
+ const flash = ts < 8.2 && Math.floor(ts * 6) % 2 === 0;
448
+ ctx.fillStyle = flash ? RED : INK; ctx.fillRect(X + 650, 262, 300, 120);
449
+ T(g2 ? 'CAT' : 'DOG?', X + 800, 344, 64, 'center', PAPER, 4);
450
+ T('ITS GUESS', X + 800, 250, 28, 'center', INK, 3);
451
+ if (!g2) { ctx.fillStyle = RED; big(stamp(7.9), () => crossPic(ctx, X + 968, 282, 2.5), X + 1008, 322); }
452
+ else { ctx.fillStyle = BLUE; big(stamp(9.8), () => checkPic(ctx, X + 968, 276, 2.6), X + 1010, 318); }
453
+ }
454
+ if (ts >= 8.2 && ts < 9.7) {
455
+ ctx.fillStyle = OCHRE; ctx.fillRect(X + 650, 400, 300, 62);
456
+ T('ANSWER: CAT', X + 800, 442, 30, 'center', INK, 3);
457
+ ctx.fillStyle = RED; flatArrow(ctx, X + 760, 470, X + 520, 520, 18, S(8.4, 9.0), X + 700, 640);
458
+ if (ts >= 8.6) T('ERROR', X + 760, 640, 32, 'center', RED, 4);
459
+ }
460
+ if (ts >= 8.9 && ts < 9.9) T('TURN THE DIALS', X + 414, 610, 28, 'center', INK, 3);
461
+ }
462
+
463
+ // ===== panel C: progress (x 2560..3840); rows start stamping while the sheet slides in =====
464
+ {
465
+ const X = 2560;
466
+ const rows = [['ROUND 1', 6.1], ['ROUND 10', 7.6], ['ROUND 100', 8.9], ['ROUND 1,000', 9.7]];
467
+ if (ts >= 10.4) T('RIGHT ANSWERS OUT OF 10', X + 40, 132, 26, 'left', INK, 2.5);
468
+ rows.forEach(([lab, v], r) => {
469
+ const y = 170 + r * 100, st0 = 10.5 + r * 0.45;
470
+ if (ts < st0) return;
471
+ if (r === 3 && ts >= 12.9) { ctx.fillStyle = 'rgba(212,154,51,0.35)'; ctx.fillRect(X + 30, y - 8, 1220, 94); }
472
+ T(lab, X + 40, y + 52, 28, 'left', INK, 2);
473
+ for (let k = 0; k < 10; k++) {
474
+ const x = X + 290 + k * 70, frac = H.clamp(v - k), a = stamp(st0 + k * 0.03);
475
+ if (a <= 0) continue;
476
+ ctx.save();
477
+ if (frac < 1) { ctx.save(); ctx.beginPath(); ctx.rect(x - 4 + 62 * frac, y, 62 * (1 - frac) + 4, 80); ctx.clip(); ctx.globalAlpha = 0.16; ctx.fillStyle = INK; checkPic(ctx, x, y + 10, 1.75); ctx.restore(); }
478
+ if (frac > 0) { ctx.beginPath(); ctx.rect(x - 4, y, 62 * frac, 80); ctx.clip(); ctx.fillStyle = BLUE; checkPic(ctx, x, y + 10, 1.75); }
479
+ ctx.restore();
480
+ }
481
+ T(Math.round(v * 10) + '%', X + 1010, y + 54, 38, 'left', INK, 1);
482
+ });
483
+ // hero accuracy counter, stamped step by step
484
+ if (ts >= 10.5) {
485
+ const steps = [61, 61, 76, 89, 97];
486
+ const ci = Math.min(4, Math.floor((ts - 10.5) / 0.45) + 1);
487
+ T('ACCURACY', X + 1240, 100, 28, 'right', RED, 3);
488
+ T(steps[ci] + '%', X + 1240, 174, 72, 'right', RED, 2);
489
+ }
490
+ }
491
+ ctx.restore();
492
+
493
+ // ---- header: the question, big first, then set in the top corner ----
494
+ {
495
+ const d = H.ease.inOut(H.clamp((t - 1.5) / 0.8));
496
+ const x = H.lerp(640, 40, d), y = H.lerp(340, 60, d), size = H.lerp(84, 30, d);
497
+ ctx.globalAlpha = S(0, 0.25);
498
+ T('HOW DOES AI LEARN?', x, y, size, d > 0.5 ? 'left' : 'center', INK, H.lerp(8, 3, d));
499
+ if (d < 1) { ctx.globalAlpha = (1 - d) * S(0.3, 0.6); T('a picture statistic in three steps', 640, 400, 30, 'center', INK, 0.8, 400); }
500
+ ctx.globalAlpha = 1;
501
+ // header rule only in panel A (later panels use their own top rows)
502
+ const rw = H.lerp(800, 560, d);
503
+ ctx.fillStyle = INK; ctx.fillRect(H.lerp(240, 40, d), H.lerp(440, 76, d), rw * S(0.2, 0.6) * (1 - H.clamp((px - 300) / 300)), 3);
504
+ }
505
+ if (ts >= 13.2) {
506
+ const a = stamp(13.2);
507
+ big(a, () => {
508
+ ctx.fillStyle = INK; ctx.fillRect(40, 600, 1200, 92);
509
+ T('MORE EXAMPLES → BETTER GUESSES', 640, 662, 46, 'center', PAPER, 3);
510
+ }, 640, 646);
511
+ }
512
+ printInk(OUT, IL, W, H_); ctx = OUT;
513
+ lithoFinish(ctx, W, H_, 2);
514
+ H.grain(ctx, W, H_, 0.05, 9 + Math.floor(t * 8));
515
+ },
516
+ });
517
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": 55,
3
+ "name": "ISOTYPE Pictograms",
4
+ "nameZh": "ISOTYPE 图形符号",
5
+ "family": "Data & Information",
6
+ "familyZh": "数据与信息",
7
+ "description": "Vienna Method pictorial statistics: rows of identical flat pictograms where each symbol is a fixed quantity, partial symbols for remainders, three muted litho inks on a strict grid with geometric sans lettering.",
8
+ "motionNotes": "Motion: Title and key set first, the year column drops in, then symbols are stamped out row by row from the centre in stepped, rubber-stamp timing, the 2025 row of machines racing ahead; the litho paper breathes in the hold.",
9
+ "explainerNotes": "Explainer: A Vienna-Method picture-statistic told across one long chart sheet the camera pans along: symbols are stamped in stepped 12 fps timing, flat Isotype arrows show flow, numerals are stamped and re-stamped, and accuracy is counted in rows of tick symbols with partial symbols for fractions.",
10
+ "code": "code.js",
11
+ "registeredAs": "isotype",
12
+ "source": "https://www.futurepedia.io/resources/ai-style-atlas/view"
13
+ }