@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.
- package/MANUAL.md +94 -84
- package/package.json +1 -1
- package/product.json +2 -1
- package/skills/aicut/SKILL.md +4 -4
- package/skills/aicut/references/commands.md +15 -15
- package/skills/aicut/references/film-format.md +1 -1
- package/skills/aicut/references/recipes.md +4 -4
- package/skills/aicut/references/troubleshooting.md +2 -2
- package/skills/aicut-motion/SKILL.md +75 -9
- package/skills/aicut-motion/THIRD_PARTY_NOTICES.md +14 -0
- package/skills/aicut-motion/assets/atlas/lib/harness.js +116 -0
- package/skills/aicut-motion/assets/atlas/lib/sound.js +274 -0
- package/skills/aicut-motion/assets/atlas/styles/001-flat-vector-science/code.js +937 -0
- package/skills/aicut-motion/assets/atlas/styles/001-flat-vector-science/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/001-flat-vector-science/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/002-watercolor-wash/code.js +909 -0
- package/skills/aicut-motion/assets/atlas/styles/002-watercolor-wash/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/002-watercolor-wash/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/003-shadow-puppet-theatre/code.js +881 -0
- package/skills/aicut-motion/assets/atlas/styles/003-shadow-puppet-theatre/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/003-shadow-puppet-theatre/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/004-whiteboard-explainer/code.js +897 -0
- package/skills/aicut-motion/assets/atlas/styles/004-whiteboard-explainer/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/004-whiteboard-explainer/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/005-psychedelic-poster/code.js +814 -0
- package/skills/aicut-motion/assets/atlas/styles/005-psychedelic-poster/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/005-psychedelic-poster/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/006-tech-glow-explainer/code.js +990 -0
- package/skills/aicut-motion/assets/atlas/styles/006-tech-glow-explainer/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/006-tech-glow-explainer/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/007-papercraft-models/code.js +994 -0
- package/skills/aicut-motion/assets/atlas/styles/007-papercraft-models/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/007-papercraft-models/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/008-1940s-film-noir/code.js +792 -0
- package/skills/aicut-motion/assets/atlas/styles/008-1940s-film-noir/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/008-1940s-film-noir/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/009-manim-style-math/code.js +840 -0
- package/skills/aicut-motion/assets/atlas/styles/009-manim-style-math/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/009-manim-style-math/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/010-illuminated-manuscript/code.js +1126 -0
- package/skills/aicut-motion/assets/atlas/styles/010-illuminated-manuscript/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/010-illuminated-manuscript/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/011-editorial-essay-collage/code.js +854 -0
- package/skills/aicut-motion/assets/atlas/styles/011-editorial-essay-collage/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/011-editorial-essay-collage/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/012-bioluminescent-deep-sea/code.js +1124 -0
- package/skills/aicut-motion/assets/atlas/styles/012-bioluminescent-deep-sea/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/012-bioluminescent-deep-sea/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/013-product-launch-reveal/code.js +728 -0
- package/skills/aicut-motion/assets/atlas/styles/013-product-launch-reveal/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/013-product-launch-reveal/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/014-halftone-pop-panel/code.js +664 -0
- package/skills/aicut-motion/assets/atlas/styles/014-halftone-pop-panel/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/014-halftone-pop-panel/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/015-isometric-pastel/code.js +991 -0
- package/skills/aicut-motion/assets/atlas/styles/015-isometric-pastel/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/015-isometric-pastel/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/016-oscilloscope-vector-art/code.js +801 -0
- package/skills/aicut-motion/assets/atlas/styles/016-oscilloscope-vector-art/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/016-oscilloscope-vector-art/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/017-risograph-zine/code.js +692 -0
- package/skills/aicut-motion/assets/atlas/styles/017-risograph-zine/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/017-risograph-zine/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/018-claymation-set/code.js +756 -0
- package/skills/aicut-motion/assets/atlas/styles/018-claymation-set/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/018-claymation-set/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/019-neon-sign-at-night/code.js +922 -0
- package/skills/aicut-motion/assets/atlas/styles/019-neon-sign-at-night/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/019-neon-sign-at-night/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/020-kawaii-anime/code.js +852 -0
- package/skills/aicut-motion/assets/atlas/styles/020-kawaii-anime/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/020-kawaii-anime/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/021-ukiyo-e-woodblock/code.js +724 -0
- package/skills/aicut-motion/assets/atlas/styles/021-ukiyo-e-woodblock/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/021-ukiyo-e-woodblock/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/022-16-bit-pixel-odyssey/code.js +793 -0
- package/skills/aicut-motion/assets/atlas/styles/022-16-bit-pixel-odyssey/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/022-16-bit-pixel-odyssey/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/023-chalkboard-lesson/code.js +846 -0
- package/skills/aicut-motion/assets/atlas/styles/023-chalkboard-lesson/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/023-chalkboard-lesson/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/024-cut-paper-diorama/code.js +1008 -0
- package/skills/aicut-motion/assets/atlas/styles/024-cut-paper-diorama/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/024-cut-paper-diorama/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/025-cathedral-glass/code.js +680 -0
- package/skills/aicut-motion/assets/atlas/styles/025-cathedral-glass/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/025-cathedral-glass/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/026-editorial-chart/code.js +633 -0
- package/skills/aicut-motion/assets/atlas/styles/026-editorial-chart/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/026-editorial-chart/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/027-synthwave-outrun/code.js +757 -0
- package/skills/aicut-motion/assets/atlas/styles/027-synthwave-outrun/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/027-synthwave-outrun/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/028-origami-studio/code.js +828 -0
- package/skills/aicut-motion/assets/atlas/styles/028-origami-studio/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/028-origami-studio/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/029-linocut-relief-print/code.js +697 -0
- package/skills/aicut-motion/assets/atlas/styles/029-linocut-relief-print/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/029-linocut-relief-print/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/030-holographic-foil-card/code.js +687 -0
- package/skills/aicut-motion/assets/atlas/styles/030-holographic-foil-card/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/030-holographic-foil-card/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/031-voxel-diorama/code.js +727 -0
- package/skills/aicut-motion/assets/atlas/styles/031-voxel-diorama/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/031-voxel-diorama/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/032-sumi-e-ink-wash/code.js +903 -0
- package/skills/aicut-motion/assets/atlas/styles/032-sumi-e-ink-wash/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/032-sumi-e-ink-wash/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/033-etch-a-sketch-toy/code.js +662 -0
- package/skills/aicut-motion/assets/atlas/styles/033-etch-a-sketch-toy/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/033-etch-a-sketch-toy/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/034-cosmic-star-chart/code.js +951 -0
- package/skills/aicut-motion/assets/atlas/styles/034-cosmic-star-chart/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/034-cosmic-star-chart/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/035-punk-zine-collage/code.js +759 -0
- package/skills/aicut-motion/assets/atlas/styles/035-punk-zine-collage/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/035-punk-zine-collage/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/036-thermal-camera/code.js +738 -0
- package/skills/aicut-motion/assets/atlas/styles/036-thermal-camera/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/036-thermal-camera/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/037-engineering-blueprint/code.js +793 -0
- package/skills/aicut-motion/assets/atlas/styles/037-engineering-blueprint/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/037-engineering-blueprint/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/038-impasto-night/code.js +673 -0
- package/skills/aicut-motion/assets/atlas/styles/038-impasto-night/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/038-impasto-night/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/039-win95-desktop/code.js +907 -0
- package/skills/aicut-motion/assets/atlas/styles/039-win95-desktop/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/039-win95-desktop/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/040-low-poly-faceted/code.js +833 -0
- package/skills/aicut-motion/assets/atlas/styles/040-low-poly-faceted/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/040-low-poly-faceted/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/041-manga-page/code.js +845 -0
- package/skills/aicut-motion/assets/atlas/styles/041-manga-page/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/041-manga-page/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/042-wood-type-letterpress/code.js +496 -0
- package/skills/aicut-motion/assets/atlas/styles/042-wood-type-letterpress/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/042-wood-type-letterpress/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/043-light-painting/code.js +635 -0
- package/skills/aicut-motion/assets/atlas/styles/043-light-painting/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/043-light-painting/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/044-felt-patchwork/code.js +799 -0
- package/skills/aicut-motion/assets/atlas/styles/044-felt-patchwork/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/044-felt-patchwork/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/045-phosphor-terminal/code.js +547 -0
- package/skills/aicut-motion/assets/atlas/styles/045-phosphor-terminal/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/045-phosphor-terminal/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/046-glassmorphism-ui/code.js +592 -0
- package/skills/aicut-motion/assets/atlas/styles/046-glassmorphism-ui/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/046-glassmorphism-ui/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/047-tarot-card/code.js +768 -0
- package/skills/aicut-motion/assets/atlas/styles/047-tarot-card/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/047-tarot-card/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/048-transit-map/code.js +666 -0
- package/skills/aicut-motion/assets/atlas/styles/048-transit-map/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/048-transit-map/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/049-gouache-travel-poster/code.js +559 -0
- package/skills/aicut-motion/assets/atlas/styles/049-gouache-travel-poster/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/049-gouache-travel-poster/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/050-napkin-sketch/code.js +943 -0
- package/skills/aicut-motion/assets/atlas/styles/050-napkin-sketch/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/050-napkin-sketch/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/051-art-deco-foil/code.js +606 -0
- package/skills/aicut-motion/assets/atlas/styles/051-art-deco-foil/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/051-art-deco-foil/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/052-radiograph-on-lightbox/code.js +730 -0
- package/skills/aicut-motion/assets/atlas/styles/052-radiograph-on-lightbox/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/052-radiograph-on-lightbox/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/053-vaporwave/code.js +782 -0
- package/skills/aicut-motion/assets/atlas/styles/053-vaporwave/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/053-vaporwave/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/054-ebru-paper-marbling/code.js +504 -0
- package/skills/aicut-motion/assets/atlas/styles/054-ebru-paper-marbling/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/054-ebru-paper-marbling/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/055-isotype-pictograms/code.js +517 -0
- package/skills/aicut-motion/assets/atlas/styles/055-isotype-pictograms/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/055-isotype-pictograms/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/056-soft-3d-clay/code.js +713 -0
- package/skills/aicut-motion/assets/atlas/styles/056-soft-3d-clay/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/056-soft-3d-clay/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/057-cross-stitch-sampler/code.js +717 -0
- package/skills/aicut-motion/assets/atlas/styles/057-cross-stitch-sampler/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/057-cross-stitch-sampler/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/058-constructivist-propaganda/code.js +540 -0
- package/skills/aicut-motion/assets/atlas/styles/058-constructivist-propaganda/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/058-constructivist-propaganda/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/059-pocket-monochrome/code.js +524 -0
- package/skills/aicut-motion/assets/atlas/styles/059-pocket-monochrome/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/059-pocket-monochrome/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/060-botanical-plate/code.js +934 -0
- package/skills/aicut-motion/assets/atlas/styles/060-botanical-plate/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/060-botanical-plate/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/061-kinetic-type/code.js +690 -0
- package/skills/aicut-motion/assets/atlas/styles/061-kinetic-type/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/061-kinetic-type/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/062-byzantine-mosaic/code.js +612 -0
- package/skills/aicut-motion/assets/atlas/styles/062-byzantine-mosaic/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/062-byzantine-mosaic/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/063-y2k-liquid-chrome/code.js +666 -0
- package/skills/aicut-motion/assets/atlas/styles/063-y2k-liquid-chrome/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/063-y2k-liquid-chrome/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/064-sticky-note-wall/code.js +651 -0
- package/skills/aicut-motion/assets/atlas/styles/064-sticky-note-wall/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/064-sticky-note-wall/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/065-vintage-newsprint/code.js +656 -0
- package/skills/aicut-motion/assets/atlas/styles/065-vintage-newsprint/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/065-vintage-newsprint/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/066-hidden-line-wireframe/code.js +672 -0
- package/skills/aicut-motion/assets/atlas/styles/066-hidden-line-wireframe/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/066-hidden-line-wireframe/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/067-memphis-group/code.js +548 -0
- package/skills/aicut-motion/assets/atlas/styles/067-memphis-group/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/067-memphis-group/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/068-ballpoint-notebook/code.js +989 -0
- package/skills/aicut-motion/assets/atlas/styles/068-ballpoint-notebook/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/068-ballpoint-notebook/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/069-op-art-sphere/code.js +440 -0
- package/skills/aicut-motion/assets/atlas/styles/069-op-art-sphere/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/069-op-art-sphere/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/070-topographic-survey/code.js +895 -0
- package/skills/aicut-motion/assets/atlas/styles/070-topographic-survey/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/070-topographic-survey/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/071-pointillist-afternoon/code.js +563 -0
- package/skills/aicut-motion/assets/atlas/styles/071-pointillist-afternoon/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/071-pointillist-afternoon/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/072-vector-arcade-1980/code.js +627 -0
- package/skills/aicut-motion/assets/atlas/styles/072-vector-arcade-1980/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/072-vector-arcade-1980/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/073-patent-drawing/code.js +1096 -0
- package/skills/aicut-motion/assets/atlas/styles/073-patent-drawing/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/073-patent-drawing/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/074-bauhaus-poster/code.js +595 -0
- package/skills/aicut-motion/assets/atlas/styles/074-bauhaus-poster/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/074-bauhaus-poster/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/075-bitmap-paint-doodle/code.js +665 -0
- package/skills/aicut-motion/assets/atlas/styles/075-bitmap-paint-doodle/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/075-bitmap-paint-doodle/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/076-nail-thread-string-art/code.js +645 -0
- package/skills/aicut-motion/assets/atlas/styles/076-nail-thread-string-art/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/076-nail-thread-string-art/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/077-ridgeline/code.js +436 -0
- package/skills/aicut-motion/assets/atlas/styles/077-ridgeline/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/077-ridgeline/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/078-sketchbook-graphite/code.js +1237 -0
- package/skills/aicut-motion/assets/atlas/styles/078-sketchbook-graphite/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/078-sketchbook-graphite/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/079-teletext-page/code.js +622 -0
- package/skills/aicut-motion/assets/atlas/styles/079-teletext-page/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/079-teletext-page/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/080-silkscreen-grid/code.js +524 -0
- package/skills/aicut-motion/assets/atlas/styles/080-silkscreen-grid/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/080-silkscreen-grid/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/081-guilloch-security-print/code.js +689 -0
- package/skills/aicut-motion/assets/atlas/styles/081-guilloch-security-print/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/081-guilloch-security-print/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/082-ascii-demoscene/code.js +574 -0
- package/skills/aicut-motion/assets/atlas/styles/082-ascii-demoscene/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/082-ascii-demoscene/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/083-international-typographic-style/code.js +469 -0
- package/skills/aicut-motion/assets/atlas/styles/083-international-typographic-style/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/083-international-typographic-style/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/084-flow-field/code.js +531 -0
- package/skills/aicut-motion/assets/atlas/styles/084-flow-field/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/084-flow-field/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/085-macpaint-1984/code.js +675 -0
- package/skills/aicut-motion/assets/atlas/styles/085-macpaint-1984/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/085-macpaint-1984/style.json +13 -0
- package/skills/aicut-motion/assets/atlas/styles/086-multi-scale-truchet/code.js +609 -0
- package/skills/aicut-motion/assets/atlas/styles/086-multi-scale-truchet/poster.jpg +0 -0
- package/skills/aicut-motion/assets/atlas/styles/086-multi-scale-truchet/style.json +13 -0
- package/skills/aicut-motion/references/design-systems/README.md +1 -1
- package/skills/aicut-motion/references/motion-delivery.md +55 -0
- package/skills/aicut-motion/references/pages.md +1 -1
- package/skills/aicut-motion/references/style-index.json +690 -0
- package/skills/aicut-motion/references/style-research.md +73 -0
- package/skills/aicut-motion/references/style-selection.md +71 -0
- package/skills/aicut-motion/scripts/atlas-viewer.html +195 -0
- package/skills/aicut-motion/scripts/atlas.mjs +109 -0
- package/studio/client.mjs +3 -3
- package/studio/server/fetch-github.mjs +14 -3
- package/studio/server/server.mjs +71 -6
- package/studio/server/skill-summaries.mjs +60 -0
- package/studio/server/skills.mjs +121 -7
- package/studio/server/styles-store.mjs +235 -0
- package/studio/server/template-posters.mjs +2 -2
- package/studio/server/templates-page.mjs +93 -93
- package/studio/server/templates.mjs +32 -7
- package/studio/ui/dist/assets/ExportCenter-DasulhAv.js +1 -0
- package/studio/ui/dist/assets/SettingsModal-BZw0Hz2_.js +2 -0
- package/studio/ui/dist/assets/apple-touch-icon-ClxQ7j-O.png +0 -0
- package/studio/ui/dist/assets/es-C8XPZARI.js +1 -0
- package/studio/ui/dist/assets/favicon-Blwx8Trs.png +0 -0
- package/studio/ui/dist/assets/index-BjJVmBzB.js +1623 -0
- package/studio/ui/dist/assets/index-C3BfKZFO.css +1 -0
- package/studio/ui/dist/assets/ja-BeNkdaEj.js +1 -0
- package/studio/ui/dist/assets/ko-DcTVhdzK.js +1 -0
- package/studio/ui/dist/assets/zh-CN-Cg51ctbL.js +1 -0
- package/studio/ui/dist/index.html +4 -3
- package/studio/ui/dist/assets/ExportCenter-F-2vF-lQ.js +0 -1
- package/studio/ui/dist/assets/SettingsModal-BgVYguNu.js +0 -2
- package/studio/ui/dist/assets/es-BRUzvuoM.js +0 -1
- package/studio/ui/dist/assets/index-Bhg-9dA3.css +0 -1
- package/studio/ui/dist/assets/index-CWur1Iw9.js +0 -1625
- package/studio/ui/dist/assets/ja-Cth-uDcW.js +0 -1
- package/studio/ui/dist/assets/ko-upvw591D.js +0 -1
- package/studio/ui/dist/assets/zh-CN-BCfJFazB.js +0 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": 41,
|
|
3
|
+
"name": "Manga Page",
|
|
4
|
+
"nameZh": "漫画分镜页",
|
|
5
|
+
"family": "Illustration",
|
|
6
|
+
"familyZh": "插画",
|
|
7
|
+
"description": "A black-and-white manga page: slanted panel gutters, brush-tapered ink, radiating focus lines, true halftone screentone gradients, katakana sound effects with white knock-out borders and hand-lettered speech balloons.",
|
|
8
|
+
"motionNotes": "Motion: Panels land one after another with a camera shake; focus lines \"boil\" every couple of frames and the ゴゴゴ letters tremble.",
|
|
9
|
+
"explainerNotes": "Explainer: A three-page manga: panels slam in on twos, page turns carry the story, bold outlined arrows and katakana SFX (ドドド, ブー, カチカチ, ピンポーン, グングン) mark cause and effect, numbers count in narration boxes, and focus-line bursts hit the key beats.",
|
|
10
|
+
"code": "code.js",
|
|
11
|
+
"registeredAs": "manga-panel",
|
|
12
|
+
"source": "https://www.futurepedia.io/resources/ai-style-atlas/view"
|
|
13
|
+
}
|
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
{
|
|
2
|
+
// ---------- Wood-type letterpress broadside: 2 inks, per-block wear, wood grain, deboss ----------
|
|
3
|
+
const PAPER = [238, 226, 198];
|
|
4
|
+
const INKS = { black: [30, 27, 26], red: [206, 58, 36] };
|
|
5
|
+
|
|
6
|
+
// cream rag stock: cloudy formation, irregular (patchy) fibre streaks and fine tooth, slight warm/cool drift
|
|
7
|
+
const paperBase = (px, W, H_) => {
|
|
8
|
+
const nz = H.makeNoise(17), img = px.createImageData(W, H_), d = img.data;
|
|
9
|
+
// low-frequency fields on a 4px grid (bilinear), fine streak + tooth per pixel
|
|
10
|
+
const GS = 4, gw = Math.ceil(W / GS) + 2, gh = Math.ceil(H_ / GS) + 2, G = new Float32Array(gw * gh * 3);
|
|
11
|
+
for (let gy = 0; gy < gh; gy++) for (let gx = 0; gx < gw; gx++) { const x = gx * GS, y = gy * GS, j = (gy * gw + gx) * 3; G[j] = nz.fbm2(x * 0.006, y * 0.006, 4); G[j + 1] = nz.fbm2(x * 0.035, y * 0.028, 2); G[j + 2] = 0.5 + 0.5 * nz.n2(x * 0.01 + 40, y * 0.01); }
|
|
12
|
+
for (let y = 0; y < H_; y++) {
|
|
13
|
+
const gy = (y / GS) | 0, fy = (y % GS) / GS;
|
|
14
|
+
for (let x = 0; x < W; x++) {
|
|
15
|
+
const gx = (x / GS) | 0, fx = (x % GS) / GS, j00 = (gy * gw + gx) * 3, j01 = j00 + 3, j10 = j00 + gw * 3, j11 = j10 + 3;
|
|
16
|
+
const bl = (c) => (G[j00 + c] * (1 - fx) + G[j01 + c] * fx) * (1 - fy) + (G[j10 + c] * (1 - fx) + G[j11 + c] * fx) * fy;
|
|
17
|
+
const cl = bl(0), md = bl(1), streak = nz.n2(x * 0.16, y * 0.035) * bl(2);
|
|
18
|
+
let h = (Math.imul(x, 374761393) + Math.imul(y, 668265263)) | 0; h = Math.imul(h ^ (h >>> 13), 1274126177); h ^= h >>> 16;
|
|
19
|
+
const v = 1 + cl * 0.045 + md * 0.018 + streak * 0.022 + ((h >>> 0) / 4294967296 - 0.5) * 0.035, warm = cl * 6, i = (y * W + x) * 4;
|
|
20
|
+
d[i] = PAPER[0] * v + warm; d[i + 1] = PAPER[1] * v + warm * 0.4; d[i + 2] = PAPER[2] * v - warm * 0.6; d[i + 3] = 255;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
px.putImageData(img, 0, 0);
|
|
24
|
+
};
|
|
25
|
+
let HP = null; // hero paper cache
|
|
26
|
+
|
|
27
|
+
// each glyph/ornament is a separate "block": colour encodes (id, density, grain phase)
|
|
28
|
+
let nextId = 1, CT = 0;
|
|
29
|
+
// timing: a block is invisible (but still consumes its random draws) until pressed, then lands with a small 'kiss'
|
|
30
|
+
const stamp = (x, t0) => { x.globalAlpha = CT >= t0 ? 1 : 0; return 1 + 0.14 * (1 - H.ease.out(H.clamp((CT - t0) / 0.1))); };
|
|
31
|
+
const blockStyle = (r, dens, grain) => `rgb(${(nextId++ % 250) + 1},${Math.round(dens * 255)},${grain ? Math.round(r.range(30, 255)) : 0})`;
|
|
32
|
+
|
|
33
|
+
const setType = (x, r, text, font, cx, baseline, targetW, capH, opt = {}) => {
|
|
34
|
+
const sp = opt.spacing || 0, grain = opt.grain !== false;
|
|
35
|
+
x.font = `${font.split('|')[0]} 200px ${font.split('|')[1]}`;
|
|
36
|
+
const capM = x.measureText('H'), cap = capM.actualBoundingBoxAscent;
|
|
37
|
+
const ws = [...text].map((ch) => x.measureText(ch).width);
|
|
38
|
+
const total = ws.reduce((a, b) => a + b, 0) + sp * (ws.length - 1);
|
|
39
|
+
const sx = targetW / total, sy = capH / cap;
|
|
40
|
+
let acc = cx - targetW / 2;
|
|
41
|
+
[...text].forEach((ch, i) => {
|
|
42
|
+
const w = ws[i] * sx;
|
|
43
|
+
if (ch !== ' ') {
|
|
44
|
+
x.save();
|
|
45
|
+
const k = stamp(x, (opt.t0 ?? 0) + i * (opt.dt ?? 0));
|
|
46
|
+
x.translate(acc + w / 2, baseline + r.range(-1.6, 1.6) * (opt.jit ?? 1));
|
|
47
|
+
x.rotate(r.range(-0.006, 0.006) * (opt.jit ?? 1)); x.translate(0, -capH / 2); x.scale(k, k); x.translate(0, capH / 2); x.scale(sx, sy);
|
|
48
|
+
x.fillStyle = blockStyle(r, r.range(0.72, 1), grain);
|
|
49
|
+
x.textAlign = 'center'; x.textBaseline = 'alphabetic';
|
|
50
|
+
x.fillText(ch, 0, 0);
|
|
51
|
+
x.restore();
|
|
52
|
+
}
|
|
53
|
+
x.globalAlpha = 1;
|
|
54
|
+
acc += w + sp * sx;
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const rule = (x, r, x0, x1, y, h, t0 = 0) => { x.fillStyle = blockStyle(r, r.range(0.85, 1), false); stamp(x, t0); x.fillRect(x0, y, x1 - x0, h); x.globalAlpha = 1; };
|
|
59
|
+
const diamond = (x, r, cx, cy, s0, t0 = 0) => { x.fillStyle = blockStyle(r, r.range(0.8, 1), false); const s = s0 * stamp(x, t0); x.beginPath(); x.moveTo(cx, cy - s); x.lineTo(cx + s * 0.7, cy); x.lineTo(cx, cy + s); x.lineTo(cx - s * 0.7, cy); x.closePath(); x.fill(); x.globalAlpha = 1; };
|
|
60
|
+
const star = (x, r, cx, cy, s0, t0 = 0) => { x.fillStyle = blockStyle(r, r.range(0.8, 1), false); const s = s0 * stamp(x, t0); x.beginPath(); for (let i = 0; i < 10; i++) { const a = -Math.PI / 2 + (i * Math.PI) / 5, rr = i % 2 ? s * 0.42 : s; x.lineTo(cx + Math.cos(a) * rr, cy + Math.sin(a) * rr); } x.closePath(); x.fill(); x.globalAlpha = 1; };
|
|
61
|
+
const gear = (x, r, cx, cy, R0, teeth, rot, t0 = 0) => {
|
|
62
|
+
x.fillStyle = blockStyle(r, r.range(0.85, 1), true);
|
|
63
|
+
const R = R0 * stamp(x, t0);
|
|
64
|
+
x.beginPath();
|
|
65
|
+
for (let i = 0; i < teeth * 4; i++) {
|
|
66
|
+
const a = rot + (i / (teeth * 4)) * Math.PI * 2, q = i % 4, rr = q === 0 || q === 1 ? R : R * 0.8;
|
|
67
|
+
x.lineTo(cx + Math.cos(a) * rr, cy + Math.sin(a) * rr);
|
|
68
|
+
}
|
|
69
|
+
x.closePath();
|
|
70
|
+
x.moveTo(cx + R * 0.32, cy); x.arc(cx, cy, R * 0.32, 0, Math.PI * 2, true);
|
|
71
|
+
x.fill('evenodd');
|
|
72
|
+
// spokes cut-outs
|
|
73
|
+
x.save(); x.globalCompositeOperation = 'destination-out';
|
|
74
|
+
for (let i = 0; i < 4; i++) { const a = rot + i * Math.PI / 2 + Math.PI / 4; x.beginPath(); x.arc(cx + Math.cos(a) * R * 0.52, cy + Math.sin(a) * R * 0.52, R * 0.13, 0, 7); x.fill(); }
|
|
75
|
+
x.restore(); x.globalAlpha = 1;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// ================= EXPLAINER: five proofs pulled off the press, one per beat =================
|
|
79
|
+
const XE2 = H.ease, xcl = H.clamp, xseg = (t, a, b) => xcl((t - a) / (b - a));
|
|
80
|
+
const SHEETS = [0, 2.3, 5.95, 10.45, 12.85], SWAP = 0.6;
|
|
81
|
+
let LPX = null;
|
|
82
|
+
const lph = (x, y, s) => { let h = (Math.imul(x, 374761393) + Math.imul(y, 668265263) + Math.imul(s, 1442695041)) | 0; h = Math.imul(h ^ (h >>> 13), 1274126177); h ^= h >>> 16; return (h >>> 0) / 4294967296; };
|
|
83
|
+
const fmtC = (n) => Math.round(n).toLocaleString('en-US');
|
|
84
|
+
|
|
85
|
+
// a stock cut (engraved block) of a cat or dog: black silhouette with white cuts
|
|
86
|
+
const stockCut = (x, r, kind, cx, cy, s, t0) => {
|
|
87
|
+
x.fillStyle = blockStyle(r, r.range(0.85, 1), true); const k = stamp(x, t0);
|
|
88
|
+
x.save(); x.translate(cx, cy); x.scale(s * k / 100, s * k / 100);
|
|
89
|
+
x.beginPath(); x.roundRect(-50, -50, 100, 100, 6); x.fill();
|
|
90
|
+
x.globalCompositeOperation = 'destination-out'; x.lineWidth = 5; x.strokeRect(-43, -43, 86, 86);
|
|
91
|
+
x.beginPath(); x.arc(0, 4, 28, 0, 7); x.fill();
|
|
92
|
+
if (kind === 'cat') { x.beginPath(); x.moveTo(-26, -6); x.lineTo(-22, -38); x.lineTo(-4, -22); x.closePath(); x.moveTo(26, -6); x.lineTo(22, -38); x.lineTo(4, -22); x.closePath(); x.fill(); }
|
|
93
|
+
if (kind === 'dog') { // a proper reversed cut: long lop ears hang outside the head, all cut from the block
|
|
94
|
+
for (const sg of [-1, 1]) { x.save(); x.translate(sg * 29, 8); x.rotate(-sg * 0.22); x.beginPath(); x.ellipse(0, 0, 10, 24, 0, 0, 7); x.fill(); x.restore(); }
|
|
95
|
+
}
|
|
96
|
+
x.globalCompositeOperation = 'source-over';
|
|
97
|
+
if (kind === 'dog') { // engraved lines left standing: ear seams, muzzle outline, mouth
|
|
98
|
+
x.strokeStyle = x.fillStyle; x.lineCap = 'round'; x.lineWidth = 3.2;
|
|
99
|
+
for (const sg of [-1, 1]) { const c0 = sg > 0 ? 0 : Math.PI; x.beginPath(); x.arc(0, 4, 28, c0 - 0.95, c0 + 0.95); x.stroke(); }
|
|
100
|
+
x.lineWidth = 2.6; x.beginPath(); x.ellipse(0, 15, 12, 9, 0, 0.15 * Math.PI, 0.85 * Math.PI); x.stroke();
|
|
101
|
+
x.beginPath(); x.moveTo(0, 14); x.lineTo(0, 19); x.stroke();
|
|
102
|
+
}
|
|
103
|
+
x.beginPath(); x.arc(-10, 0, 4, 0, 7); x.arc(10, 0, 4, 0, 7); x.fill(); x.beginPath(); x.ellipse(0, kind === 'dog' ? 11 : 12, kind === 'dog' ? 6.5 : 5, kind === 'dog' ? 4.5 : 3.5, 0, 0, 7); x.fill();
|
|
104
|
+
if (kind === 'cat') { x.lineWidth = 2.5; x.strokeStyle = x.fillStyle; x.beginPath(); for (const sg of [-1, 1]) { x.moveTo(sg * 8, 16); x.lineTo(sg * 26, 13); x.moveTo(sg * 8, 20); x.lineTo(sg * 25, 23); } x.stroke(); }
|
|
105
|
+
x.restore(); x.globalAlpha = 1;
|
|
106
|
+
};
|
|
107
|
+
// an arrow assembled from short rule pieces locked up one after another (draws on)
|
|
108
|
+
const dashArrow = (x, r, P, t0, dur, n = 12, w = 7) => {
|
|
109
|
+
for (let i = 0; i < n; i++) {
|
|
110
|
+
const s0 = i / n, s1 = (i + 0.62) / n, a = P(s0), b = P(s1);
|
|
111
|
+
x.fillStyle = blockStyle(r, r.range(0.85, 1), false); stamp(x, t0 + dur * (i / n));
|
|
112
|
+
const ang = Math.atan2(b[1] - a[1], b[0] - a[0]), len = Math.hypot(b[0] - a[0], b[1] - a[1]);
|
|
113
|
+
x.save(); x.translate(a[0], a[1]); x.rotate(ang); x.fillRect(0, -w / 2, len, w); x.restore();
|
|
114
|
+
}
|
|
115
|
+
const e = P(1), p = P(0.97), ang = Math.atan2(e[1] - p[1], e[0] - p[0]);
|
|
116
|
+
x.fillStyle = blockStyle(r, 1, false); stamp(x, t0 + dur);
|
|
117
|
+
x.save(); x.translate(e[0], e[1]); x.rotate(ang); x.beginPath(); x.moveTo(w * 2.4, 0); x.lineTo(-w * 1.6, -w * 2.2); x.lineTo(-w * 1.6, w * 2.2); x.closePath(); x.fill(); x.restore();
|
|
118
|
+
x.globalAlpha = 1;
|
|
119
|
+
};
|
|
120
|
+
const qP = (x0, y0, cx, cy, x1, y1) => (s) => [(1 - s) * (1 - s) * x0 + 2 * (1 - s) * s * cx + s * s * x1, (1 - s) * (1 - s) * y0 + 2 * (1 - s) * s * cy + s * s * y1];
|
|
121
|
+
const runningHead = (b, rd, r, T0) => {
|
|
122
|
+
setType(rd, r, 'HOW DOES AI LEARN?', '400|"Rubik Mono One"', 640, 56, 520, 22, { spacing: 22, grain: false, jit: 0.3, t0: T0 + 0.05 });
|
|
123
|
+
rule(b, r, 58, 1222, 22, 5, T0); rule(b, r, 58, 1222, 72, 2, T0 + 0.05);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// build the forme for sheet si at time t: black into b, red into rd
|
|
127
|
+
const forme = (si, b, rd, t) => {
|
|
128
|
+
const r = H.rng(500 + si * 37), rc = H.rng(900 + si);
|
|
129
|
+
const T0 = SHEETS[si] + (si ? SWAP * 0.6 : 0.1);
|
|
130
|
+
const stepT = (a, z) => Math.floor(xcl(t, a, z) * 6) / 6; // counters re-set and re-stamped 6x a second
|
|
131
|
+
if (si === 0) {
|
|
132
|
+
rule(b, r, 58, 1222, 40, 8, 0.1); rule(b, r, 58, 1222, 54, 2.5, 0.15);
|
|
133
|
+
setType(b, r, 'HOW DOES', '400|"Anton"', 640, 300, 900, 190, { spacing: 10, t0: 0.25, dt: 0.09 });
|
|
134
|
+
setType(rd, r, 'AI LEARN?', '400|"Abril Fatface"', 640, 520, 820, 150, { spacing: 6, t0: 1.05, dt: 0.07 });
|
|
135
|
+
rule(b, r, 58, 1222, 650, 2.5, 1.7); rule(b, r, 58, 1222, 660, 8, 1.72);
|
|
136
|
+
}
|
|
137
|
+
if (si === 1) {
|
|
138
|
+
runningHead(b, rd, r, T0);
|
|
139
|
+
[['cat', 160, 230], ['dog', 330, 230], ['dog', 160, 440], ['cat', 330, 440]].forEach(([kind, cx, cy], i) => {
|
|
140
|
+
stockCut(b, r, kind, cx, cy, 140, T0 + 0.35 + i * 0.32);
|
|
141
|
+
setType(rd, r, kind.toUpperCase(), '400|"Bebas Neue"', cx, cy + 106, 70, 30, { grain: false, spacing: 8, t0: T0 + 0.5 + i * 0.32, jit: 0.3 });
|
|
142
|
+
});
|
|
143
|
+
dashArrow(b, r, qP(440, 335, 560, 300, 700, 335), T0 + 1.3, 0.55);
|
|
144
|
+
// examples stepping along the arrow into the model, re-set on every move (stop-motion conveyor)
|
|
145
|
+
if (t > T0 + 1.9 && t < 5.7) { const ph = Math.floor((t - T0 - 1.9) * 5); [0.2, 0.5, 0.8].forEach((u, j) => { const q = qP(440, 300, 560, 265, 700, 300)(u); const kind = (ph + j) % 3 === 1 ? 'dog' : 'cat'; stockCut(b, H.rng(ph * 7 + j), kind, q[0], q[1] - 20, 60 - j * 8, 0); }); }
|
|
146
|
+
gear(b, r, 900, 320, 105, 12, 0.2 + t * 0.8, T0 + 1.0); gear(b, r, 1045, 215, 50, 9, -0.1 - t * 1.6, T0 + 1.1);
|
|
147
|
+
setType(rd, r, 'THE MODEL', '400|"Rubik Mono One"', 920, 480, 260, 24, { grain: false, spacing: 12, t0: T0 + 1.15, jit: 0.3 });
|
|
148
|
+
const st = stepT(T0 + 1.1, 5.6), v = 1e6 * Math.pow(xseg(st, T0 + 1.1, 5.3), 2.3);
|
|
149
|
+
if (t > T0 + 1.1) { const s = fmtC(v); setType(b, rc, s, '400|"Anton"', 820, 640, s.length * 42, 80, { spacing: 6, t0: st, jit: 0.5 }); }
|
|
150
|
+
setType(rd, r, 'EXAMPLES', '400|"Bebas Neue"', 820, 690, 200, 32, { spacing: 10, grain: false, t0: T0 + 1.2, jit: 0.3 });
|
|
151
|
+
}
|
|
152
|
+
if (si === 2) {
|
|
153
|
+
runningHead(b, rd, r, T0);
|
|
154
|
+
const right = t > 9.15;
|
|
155
|
+
stockCut(b, r, 'cat', 170, 330, 170, T0 + 0.3);
|
|
156
|
+
setType(rd, r, 'NEW PICTURE', '400|"Bebas Neue"', 170, 460, 170, 30, { spacing: 6, grain: false, t0: T0 + 0.4, jit: 0.3 });
|
|
157
|
+
dashArrow(b, r, qP(280, 330, 340, 300, 400, 330), T0 + 0.55, 0.3, 6);
|
|
158
|
+
setType(b, r, 'GUESS', '400|"Bebas Neue"', 600, 180, 160, 40, { spacing: 8, grain: false, t0: T0 + 0.6 });
|
|
159
|
+
if (!right) setType(b, r, 'DOG?', '400|"Anton"', 600, 390, 300, 150, { spacing: 8, t0: T0 + 0.85, dt: 0.06 });
|
|
160
|
+
else setType(b, rc, 'CAT', '400|"Anton"', 600, 390, 260, 150, { spacing: 8, t0: 9.15, dt: 0.06 });
|
|
161
|
+
dashArrow(b, r, qP(780, 330, 840, 300, 900, 330), T0 + 1.25, 0.3, 6);
|
|
162
|
+
setType(b, r, 'CHECK', '400|"Bebas Neue"', 1060, 180, 160, 40, { spacing: 8, grain: false, t0: T0 + 1.35 });
|
|
163
|
+
setType(rd, r, right ? 'RIGHT!' : "IT'S A CAT", '400|"Bebas Neue"', 1060, 350, right ? 200 : 250, 60, { spacing: 6, t0: right ? 9.3 : T0 + 1.5 });
|
|
164
|
+
// emphasis: a rubber-stamp overprint across the wrong guess
|
|
165
|
+
if (!right && t > 7.75) {
|
|
166
|
+
rd.save(); rd.translate(640, 440); rd.rotate(-0.14);
|
|
167
|
+
const k = 0.75 * stamp(rd, 7.75) * (1 + 0.25 * (1 - XE2.out(xseg(t, 7.75, 7.95))));
|
|
168
|
+
rd.scale(k, k); rd.fillStyle = blockStyle(r, 0.85, false); rd.lineWidth = 10; rd.strokeStyle = rd.fillStyle; rd.strokeRect(-190, -62, 380, 124);
|
|
169
|
+
rd.font = '400 92px "Rubik Mono One"'; rd.textAlign = 'center'; rd.textBaseline = 'middle'; rd.fillText('WRONG', 0, 6); rd.restore(); rd.globalAlpha = 1;
|
|
170
|
+
}
|
|
171
|
+
// ADJUST: the return path set as a curve of rule pieces, gears turning
|
|
172
|
+
dashArrow(b, r, qP(1060, 420, 1000, 600, 720, 560), 8.05, 0.45, 12);
|
|
173
|
+
setType(b, r, 'ADJUST', '400|"Bebas Neue"', 960, 640, 190, 46, { spacing: 8, grain: false, t0: 8.3 });
|
|
174
|
+
const turn = XE2.inOut(xseg(t, 8.35, 9.0)) * 3;
|
|
175
|
+
gear(b, r, 560, 545, 55, 10, 0.2 + turn, 8.25); gear(b, r, 640, 600, 32, 8, -0.3 - turn * 1.7, 8.32);
|
|
176
|
+
if (right) { rd.fillStyle = blockStyle(r, 1, false); const k = stamp(rd, 9.3); rd.save(); rd.translate(1060, 260); rd.scale(k, k); rd.lineWidth = 16; rd.lineCap = 'butt'; rd.lineJoin = 'miter'; rd.strokeStyle = rd.fillStyle; rd.beginPath(); rd.moveTo(-34, 0); rd.lineTo(-10, 26); rd.lineTo(38, -32); rd.stroke(); rd.restore(); rd.globalAlpha = 1; }
|
|
177
|
+
}
|
|
178
|
+
if (si === 3) {
|
|
179
|
+
runningHead(b, rd, r, T0);
|
|
180
|
+
// bar chart built from stacked square blocks, locked up course by course
|
|
181
|
+
const target = [61, 70, 78, 84, 89, 93, 95, 97];
|
|
182
|
+
for (let c = 0; c < 8; c++) {
|
|
183
|
+
const nb = Math.round((target[c] - 50) / 4);
|
|
184
|
+
for (let j = 0; j < nb; j++) {
|
|
185
|
+
const tt = T0 + 0.3 + c * 0.17 + j * 0.022, x0 = 110 + c * 64, y0 = 560 - (j + 1) * 34;
|
|
186
|
+
(c >= 6 ? rd : b).fillStyle = blockStyle(r, r.range(0.85, 1), false); stamp(c >= 6 ? rd : b, tt);
|
|
187
|
+
(c >= 6 ? rd : b).fillRect(x0, y0 + 3, 50, 28); (c >= 6 ? rd : b).globalAlpha = 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
rule(b, r, 96, 640, 566, 5, T0 + 0.2);
|
|
191
|
+
setType(b, r, 'TRAINING ROUNDS', '400|"Bebas Neue"', 368, 610, 300, 30, { spacing: 8, grain: false, t0: T0 + 0.25 });
|
|
192
|
+
setType(rd, r, 'ACCURACY', '400|"Rubik Mono One"', 960, 200, 330, 32, { spacing: 18, grain: false, t0: T0 + 0.3 });
|
|
193
|
+
const st = stepT(T0 + 0.35, 12.05), v = Math.round(61 + 36 * XE2.inOut(xseg(st, T0 + 0.35, 12.05)));
|
|
194
|
+
setType(b, rc, v + '%', '400|"Anton"', 960, 440, 380, 200, { spacing: 8, t0: st, jit: 0.4 });
|
|
195
|
+
if (t > 12.1) { rule(rd, r, 770, 1150, 470, 10, 12.1); rule(rd, r, 770, 1150, 486, 3, 12.15); [[760, 250], [1160, 250], [760, 410], [1160, 410]].forEach(([a, c2], i) => star(rd, r, a, c2, 22, 12.2 + i * 0.06)); }
|
|
196
|
+
}
|
|
197
|
+
if (si === 4) {
|
|
198
|
+
runningHead(b, rd, r, T0);
|
|
199
|
+
setType(b, r, 'MORE EXAMPLES', '400|"Anton"', 640, 270, 1060, 150, { spacing: 8, t0: T0 + 0.1, dt: 0.025 });
|
|
200
|
+
dashArrow(b, r, qP(640, 300, 640, 330, 640, 380), T0 + 0.45, 0.15, 3, 12);
|
|
201
|
+
setType(rd, r, 'BETTER GUESSES', '400|"Abril Fatface"', 640, 560, 1000, 120, { spacing: 4, t0: T0 + 0.6, dt: 0.025 });
|
|
202
|
+
for (let i = 0; i < 17; i++) diamond(rd, r, 640 + (i - 8) * 34, 640, i % 2 ? 5 : 8, T0 + 1.05 + Math.abs(i - 8) * 0.02);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const printSheet = (W, H_, si, t) => {
|
|
207
|
+
if (!LPX) {
|
|
208
|
+
const pc = H.layer(W, H_), px = pc.getContext('2d'), r = H.rng(2026);
|
|
209
|
+
paperBase(px, W, H_);
|
|
210
|
+
for (let i = 0; i < 260; i++) { const x0 = r.range(0, W), y0 = r.range(0, H_), a = r.range(0, 6.28), l = r.range(4, 22); px.strokeStyle = `rgba(${r.chance(0.5) ? '120,95,60' : '255,250,235'},${r.range(0.1, 0.3)})`; px.lineWidth = r.range(0.4, 1.1); px.beginPath(); px.moveTo(x0, y0); px.quadraticCurveTo(x0 + Math.cos(a + 0.5) * l * 0.6, y0 + Math.sin(a + 0.5) * l * 0.6, x0 + Math.cos(a) * l, y0 + Math.sin(a) * l); px.stroke(); }
|
|
211
|
+
H.vignette(px, W, H_, 0.18, '120,85,40');
|
|
212
|
+
const nz = H.makeNoise(33), GW = 427, GH = 240, fld = new Float32Array(GW * GH * 3);
|
|
213
|
+
for (let y = 0; y < GH; y++) for (let x = 0; x < GW; x++) { const j = (y * GW + x) * 3; fld[j] = nz.fbm2(x * 0.05, y * 0.05, 3); fld[j + 1] = nz.fbm2(x * 0.6, y * 0.6, 2); fld[j + 2] = nz.fbm2(x * 0.012, y * 0.35, 2); }
|
|
214
|
+
LPX = { paper: px.getImageData(0, 0, W, H_).data, fld, GW, GH, nz };
|
|
215
|
+
}
|
|
216
|
+
const { paper, fld, GW, GH, nz } = LPX;
|
|
217
|
+
nextId = 1; CT = t;
|
|
218
|
+
const blk = H.layer(W, H_), b = blk.getContext('2d'), red = H.layer(W, H_), rd = red.getContext('2d');
|
|
219
|
+
forme(si, b, rd, t);
|
|
220
|
+
const redShift = H.layer(W, H_), rs = redShift.getContext('2d'); rs.translate(W / 2, H_ / 2); rs.rotate([0.0015, -0.0011, 0.0013, -0.0015, 0.0009][si]); rs.translate(-W / 2, -H_ / 2); rs.drawImage(red, 2.5, -1.5);
|
|
221
|
+
const bk = b.getImageData(0, 0, W, H_).data, rk = rs.getImageData(0, 0, W, H_).data;
|
|
222
|
+
const blurOf = (c, px) => { const o = H.layer(W, H_), ox = o.getContext('2d'); ox.filter = `blur(${px}px)`; ox.drawImage(c, 0, 0); return ox.getImageData(0, 0, W, H_).data; };
|
|
223
|
+
const both = H.layer(W, H_), bx = both.getContext('2d'); bx.drawImage(blk, 0, 0); bx.drawImage(redShift, 0, 0);
|
|
224
|
+
const bb = blurOf(both, 2.2), bkB = blurOf(blk, 1.6), rkB = blurOf(redShift, 1.6);
|
|
225
|
+
const samp = (x, y, c) => fld[(((y * GH / H_) | 0) * GW + ((x * GW / W) | 0)) * 3 + c];
|
|
226
|
+
const inkPass = (i, x, y, m, mB, s) => {
|
|
227
|
+
const a = m[i + 3] / 255; if (a < 0.02) return 0;
|
|
228
|
+
const dens0 = m[i + 1] / 255, phase = m[i + 2] / 255, broad = samp(x, y, 0), fine = samp(x, y, 1), ab = mB[i + 3] / 255;
|
|
229
|
+
let cov = xcl((Math.min(a, ab * 1.15) - (0.5 + fine * 0.45 + (lph(x, y, s) - 0.5) * 0.2)) * 2.6 + 0.5);
|
|
230
|
+
if (cov <= 0) return 0;
|
|
231
|
+
let dens = (0.25 + dens0 * 0.85) * (0.97 + broad * 0.22) + (lph(x, y, s + 1) - 0.5) * 0.08;
|
|
232
|
+
const sq = xcl((a - ab) * 3.5); // ink squeezed to the rim of the block
|
|
233
|
+
if (phase > 0) { const gv = Math.sin((y + samp(x, y, 2) * 40 + phase * 30) * 0.9 + Math.sin(x * 0.01 + phase * 9) * 2.5); dens *= 1 - 0.3 * H.smooth(0.55, 1, gv * 0.5 + nz.n2(x * 0.004 + phase * 7, y * 0.22) * 0.8); }
|
|
234
|
+
if (lph(x, y, s + 2) < 0.004 + Math.max(0, -broad - 0.15) * 0.35 + Math.max(0, fine - 0.3) * 0.2) dens *= 0.25;
|
|
235
|
+
dens = dens * (1 - sq * 0.5) + sq * 0.5 * Math.max(dens, 1.06) + sq * 0.12;
|
|
236
|
+
return cov * xcl(dens);
|
|
237
|
+
};
|
|
238
|
+
const out = new ImageData(W, H_), d = out.data;
|
|
239
|
+
for (let y = 0; y < H_; y++) for (let x = 0; x < W; x++) {
|
|
240
|
+
const i = (y * W + x) * 4;
|
|
241
|
+
let cr = paper[i], cg = paper[i + 1], cb = paper[i + 2];
|
|
242
|
+
const gA = (y > 2 && y < H_ - 3 && x > 2 && x < W - 3) ? bb[i + 3 + (W + 1) * 8] - bb[i + 3 - (W + 1) * 8] : 0;
|
|
243
|
+
// directional bite: shadowed upper-left wall, only a soft light on the lower-right (no pale all-round halo)
|
|
244
|
+
const k = (1 - Math.max(gA, 0) / 255 * 0.14 - Math.min(gA, 0) / 255 * 0.04) * (1 - (bb[i + 3] / 255) * 0.05); cr *= k; cg *= k; cb *= k;
|
|
245
|
+
const cR = inkPass(i, x, y, rk, rkB, 10);
|
|
246
|
+
if (cR) { cr *= 1 - cR * (1 - INKS.red[0] / 255); cg *= 1 - cR * (1 - INKS.red[1] / 255); cb *= 1 - cR * (1 - INKS.red[2] / 255); }
|
|
247
|
+
const cK = inkPass(i, x, y, bk, bkB, 20);
|
|
248
|
+
if (cK) { cr = cr * (1 - cK) + INKS.black[0] * cK; cg = cg * (1 - cK) + INKS.black[1] * cK; cb = cb * (1 - cK) + INKS.black[2] * cK; }
|
|
249
|
+
d[i] = cr; d[i + 1] = cg; d[i + 2] = cb; d[i + 3] = 255;
|
|
250
|
+
}
|
|
251
|
+
const c = H.layer(W, H_); c.getContext('2d').putImageData(out, 0, 0);
|
|
252
|
+
return c;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const lpExplainer = (ctx, W, H_, t) => {
|
|
256
|
+
let cur = 0; for (let i = 0; i < SHEETS.length; i++) if (t >= SHEETS[i]) cur = i;
|
|
257
|
+
const sw = cur > 0 ? xseg(t, SHEETS[cur], SHEETS[cur] + SWAP) : 1;
|
|
258
|
+
ctx.fillStyle = '#26221e'; ctx.fillRect(0, 0, W, H_); // the press bed
|
|
259
|
+
// fresh sheet already on the bed, drops the last few px as it is laid down
|
|
260
|
+
const drop = 1 - XE2.out(sw);
|
|
261
|
+
ctx.save(); ctx.translate(W / 2, H_ / 2); ctx.scale(1 - drop * 0.03, 1 - drop * 0.03); ctx.translate(-W / 2, -H_ / 2);
|
|
262
|
+
ctx.drawImage(printSheet(W, H_, cur, t), 0, 0); ctx.restore();
|
|
263
|
+
if (sw < 1) {
|
|
264
|
+
// the finished proof is lifted off the forme and carried away
|
|
265
|
+
const u = XE2.in(sw), old = printSheet(W, H_, cur - 1, SHEETS[cur] - 0.001);
|
|
266
|
+
ctx.save(); ctx.translate(W / 2 - u * 1500, H_ / 2 - u * 260); ctx.rotate(-u * 0.12); ctx.scale(1 + u * 0.04, 1 + u * 0.04);
|
|
267
|
+
ctx.shadowColor = 'rgba(0,0,0,0.45)'; ctx.shadowBlur = 30 * u + 4; ctx.shadowOffsetY = 18 * u + 2;
|
|
268
|
+
ctx.drawImage(old, -W / 2, -H_ / 2); ctx.restore();
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
registerStyle({
|
|
273
|
+
id: 'letterpress',
|
|
274
|
+
name: 'Wood Type Letterpress',
|
|
275
|
+
category: 'Print',
|
|
276
|
+
description: 'A two-ink wood-type broadside on cream stock: mixed display faces set block by block, each letter inked a little differently, wood grain and worn edges in the solids, ink squeezed to the rims and the whole forme bitten into the paper.',
|
|
277
|
+
motion: 'The forme is proofed block by block — rules first, then each wood letter lands with a heavy kiss of the platen, red and black alternating down the sheet — and the gears keep turning as the impression deepens.',
|
|
278
|
+
fonts: ['400 200px "Anton"', '400 200px "Abril Fatface"', '400 200px "Rubik Mono One"', '400 200px "Bebas Neue"'],
|
|
279
|
+
duration: 5,
|
|
280
|
+
frameT: 4.8,
|
|
281
|
+
readsPixels: true,
|
|
282
|
+
explainerDuration: 15.5,
|
|
283
|
+
explainerNote: 'Every beat is a new proof: the finished sheet is lifted off the press and a fresh one is laid down, then wood type, stock cuts of a cat and a dog, and arrows set from short rule pieces lock up block by block with a kiss of the platen; counters are re-set and re-stamped six times a second, and the wrong guess gets a red rubber-stamp WRONG.',
|
|
284
|
+
explainer(ctx, W, H_, t) { lpExplainer(ctx, W, H_, t); },
|
|
285
|
+
// Sound: a hand press in a print shop. Every block that locks up gets a wooden "kiss" of the platen (letters,
|
|
286
|
+
// stock cuts, rules), rule-piece arrows tick together piece by piece, counters re-stamp on their 6 fps steps,
|
|
287
|
+
// the bar chart rattles up in stacks of quoins, each new sheet is peeled off the forme and a fresh one laid
|
|
288
|
+
// down, WRONG is a rubber stamp, and the big moments are the full weight of the press.
|
|
289
|
+
// Timings mirror SHEETS / SWAP / forme() above (T0 = SHEETS[si] + SWAP*0.6, per-block t0s, stepT on sixths).
|
|
290
|
+
// Voiceover mode: room bed drops; per-letter kisses, rule pieces, counter re-stamps and small labels are minor.
|
|
291
|
+
explainerSound(k) {
|
|
292
|
+
const D = 15.5, T0 = (si) => SHEETS[si] + (si ? SWAP * 0.6 : 0.1);
|
|
293
|
+
const pan = (px) => xcl((px / 1280) * 2 - 1, -1, 1) * 0.6;
|
|
294
|
+
const when = (t0, t1, ease, u) => { for (let i = 0; i <= 400; i++) { const t = t0 + ((t1 - t0) * i) / 400; if (ease(i / 400) >= u - 1e-6) return t; } return t1; };
|
|
295
|
+
// the platen kisses a wood block: short woody thunk, heavier for big blocks
|
|
296
|
+
const kiss = (t, g, p, minor) => {
|
|
297
|
+
const o = { minor: !!minor };
|
|
298
|
+
k.tone(t, { ...o, f: [[0, 150], [0.05, 72]], dur: 0.08, gain: 0.3 * g, pan: p });
|
|
299
|
+
k.noise(t, { ...o, dur: 0.04, filter: 'bandpass', f: 650, q: 1.2, gain: 0.3 * g, a: 0.001, pan: p });
|
|
300
|
+
k.noise(t, { ...o, dur: 0.01, filter: 'bandpass', f: 1800, q: 1, gain: 0.08 * g, a: 0.001, pan: p });
|
|
301
|
+
};
|
|
302
|
+
const word = (t0, dt, n, g, x0, x1) => { for (let i = 0; i < n; i++) kiss(t0 + i * dt, g, pan(x0 + (x1 - x0) * (i / Math.max(1, n - 1))), true); };
|
|
303
|
+
// a metal rule piece dropped into the chase: tiny dry tick
|
|
304
|
+
const piece = (t, g, p) => k.noise(t, { minor: true, dur: 0.015, filter: 'bandpass', f: 1500, q: 1.5, gain: 0.22 * g, a: 0.001, pan: p });
|
|
305
|
+
const arrow = (t0, dur, n, p0, p1) => { for (let i = 0; i < n; i += n > 6 ? 2 : 1) piece(t0 + dur * (i / n), 0.9, p0 + (p1 - p0) * (i / n)); kiss(t0 + dur, 0.55, p1, true); };
|
|
306
|
+
// proof off, fresh sheet on: tacky peel, the sheet carried away, the next one settling on the bed
|
|
307
|
+
const swap = (t) => {
|
|
308
|
+
k.withMinor(() => { for (let x = 0; x < 0.16; x += 0.012) k.noise(t + x, { dur: 0.006, filter: 'bandpass', f: 1700, q: 1, gain: 0.14 * (1 - x / 0.16), a: 0.001, pan: -0.2 }); });
|
|
309
|
+
k.play('paper', t + 0.05, { dur: 0.45, gain: 1.1, pan: -0.4 });
|
|
310
|
+
k.noise(t + 0.05, { dur: 0.45, color: 'pink', filter: 'bandpass', f: [[0, 500], [0.45, 1100]], q: 0.7, gain: 0.14, a: 0.15, pan: -0.5 }); // air of the sheet carried off
|
|
311
|
+
k.noise(t + 0.3, { dur: 0.25, color: 'pink', filter: 'lowpass', f: [[0, 900], [0.25, 300]], gain: 0.16, a: 0.03 });
|
|
312
|
+
k.play('slap', t + 0.24, { gain: 0.3 }); // fresh sheet settles on the bed
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
k.bed('room', 0, D, { gain: 0.22 });
|
|
316
|
+
|
|
317
|
+
// ---- sheet 1: HOOK. rules, HOW DOES (dt .09, space skipped), AI LEARN? in red (dt .07), closing rules
|
|
318
|
+
kiss(0.1, 0.7, 0); kiss(0.15, 0.4, 0, true);
|
|
319
|
+
[0, 1, 2, 4, 5, 6, 7].forEach((i) => kiss(0.25 + i * 0.09, 0.85, pan(190 + i * 129), true));
|
|
320
|
+
[0, 1, 3, 4, 5, 6, 7, 8].forEach((i) => kiss(1.05 + i * 0.07, 0.85, pan(230 + i * 102), true));
|
|
321
|
+
k.play('press', 1.7, { gain: 0.55 }); // closing rules lock the forme up
|
|
322
|
+
|
|
323
|
+
// ---- sheet 2: DATA
|
|
324
|
+
swap(SHEETS[1]);
|
|
325
|
+
kiss(T0(1), 0.6, 0); // running head
|
|
326
|
+
for (let i = 0; i < 4; i++) { kiss(T0(1) + 0.35 + i * 0.32, 1.0, pan(i % 2 ? 330 : 160)); kiss(T0(1) + 0.5 + i * 0.32, 0.4, pan(i % 2 ? 330 : 160), true); } // stock cuts + labels
|
|
327
|
+
kiss(T0(1) + 1.0, 1.0, pan(900)); kiss(T0(1) + 1.1, 0.6, pan(1045), true); // the model's gears
|
|
328
|
+
kiss(T0(1) + 1.15, 0.45, pan(920), true); // THE MODEL
|
|
329
|
+
arrow(T0(1) + 1.3, 0.55, 12, pan(440), pan(700));
|
|
330
|
+
// counter re-set on sixths of a second from 3.83 to 5.5; 1,000,000 first lands on the 5.333 step
|
|
331
|
+
for (let n = Math.ceil((T0(1) + 1.1) * 6); n <= 33; n++) { const t = n / 6; if (Math.abs(t - 32 / 6) < 1e-6) continue; kiss(t, 0.5, pan(820), true); }
|
|
332
|
+
k.play('press', 32 / 6, { gain: 0.85, pan: pan(820) }); // 1,000,000
|
|
333
|
+
|
|
334
|
+
// ---- sheet 3: GUESS / CHECK
|
|
335
|
+
swap(SHEETS[2]);
|
|
336
|
+
kiss(T0(2), 0.6, 0);
|
|
337
|
+
kiss(T0(2) + 0.3, 1.0, pan(170)); // cat cut
|
|
338
|
+
kiss(T0(2) + 0.4, 0.4, pan(170), true); // NEW PICTURE
|
|
339
|
+
arrow(T0(2) + 0.55, 0.3, 6, pan(280), pan(400));
|
|
340
|
+
kiss(T0(2) + 0.6, 0.45, pan(600), true); // GUESS
|
|
341
|
+
word(T0(2) + 0.85, 0.06, 4, 0.9, 480, 720); // DOG?
|
|
342
|
+
arrow(T0(2) + 1.25, 0.3, 6, pan(780), pan(900));
|
|
343
|
+
kiss(T0(2) + 1.35, 0.45, pan(1060), true); // CHECK
|
|
344
|
+
kiss(T0(2) + 1.5, 0.6, pan(1060), true); // IT'S A CAT
|
|
345
|
+
k.play('stamp', 7.75, { gain: 0.95, pan: pan(640) }); // red rubber-stamp WRONG
|
|
346
|
+
k.play('error', 7.93, { f: 'E3', gain: 0.7, pan: pan(640) });
|
|
347
|
+
arrow(8.05, 0.45, 12, pan(1060), pan(720));
|
|
348
|
+
kiss(8.25, 0.8, pan(560)); kiss(8.32, 0.5, pan(640), true); // gears
|
|
349
|
+
kiss(8.3, 0.45, pan(960), true); // ADJUST
|
|
350
|
+
for (let i = 1; i <= 3; i++) k.play('tock', when(8.35, 9.0, XE2.inOut, (i - 0.5) / 3), { f: 420 + i * 20, gain: 0.32, pan: pan(600), minor: true }); // gears turn
|
|
351
|
+
word(9.15, 0.06, 3, 1.0, 500, 700); // CAT re-set
|
|
352
|
+
kiss(9.3, 0.7, pan(1060));
|
|
353
|
+
k.play('success', 9.38, { f: 'C5', gain: 0.55, pan: pan(1060) }); // RIGHT! + tick
|
|
354
|
+
|
|
355
|
+
// ---- sheet 4: ACCURACY
|
|
356
|
+
swap(SHEETS[3]);
|
|
357
|
+
kiss(T0(3), 0.6, 0);
|
|
358
|
+
kiss(T0(3) + 0.2, 0.5, pan(368), true); kiss(T0(3) + 0.3, 0.45, pan(960), true); // base rule / ACCURACY
|
|
359
|
+
// each bar is a stack of blocks locked up 22 ms apart: one short rattle per column
|
|
360
|
+
[3, 5, 7, 9, 10, 11, 11, 12].forEach((nb, c) => { const t0 = T0(3) + 0.3 + c * 0.17, p = pan(135 + c * 64); kiss(t0, 0.6, p, true); for (let j = 1; j < nb; j += 2) piece(t0 + j * 0.022, 0.7, p); });
|
|
361
|
+
for (let n = Math.ceil((T0(3) + 0.35) * 6); n <= 72; n++) kiss(n / 6, 0.45, pan(960), true); // % re-stamped on sixths
|
|
362
|
+
// 97%: the red rules bite in under it, stars follow. The biggest hit: full weight of the press
|
|
363
|
+
k.play('impact', 12.1, { gain: 1.1, pan: pan(960) });
|
|
364
|
+
k.play('press', 12.1, { gain: 1.0, pan: pan(960) });
|
|
365
|
+
[12.2, 12.26, 12.32, 12.38].forEach((t, i) => kiss(t, 0.45, pan(i % 2 ? 1160 : 760), true));
|
|
366
|
+
|
|
367
|
+
// ---- sheet 5: TAKEAWAY
|
|
368
|
+
swap(SHEETS[4]);
|
|
369
|
+
kiss(T0(4), 0.6, 0);
|
|
370
|
+
kiss(T0(4) + 0.1, 0.9, pan(200)); for (let i = 2; i < 13; i += 2) kiss(T0(4) + 0.1 + i * 0.025, 0.55, pan(200 + i * 75), true); // MORE EXAMPLES runs in
|
|
371
|
+
arrow(T0(4) + 0.45, 0.15, 3, 0, 0);
|
|
372
|
+
kiss(T0(4) + 0.6, 0.9, pan(200)); for (let i = 2; i < 14; i += 2) kiss(T0(4) + 0.6 + i * 0.025, 0.55, pan(200 + i * 68), true); // BETTER GUESSES
|
|
373
|
+
k.play('press', T0(4) + 0.95, { gain: 0.6 }); // the takeaway is locked up
|
|
374
|
+
['C4', 'G4', 'C5', 'E5'].forEach((f, i) => k.play('ding', T0(4) + 1.08 + i * 0.06, { f, gain: 0.36 - i * 0.05, pan: (i - 1.5) * 0.2 }));
|
|
375
|
+
for (let i = 0; i <= 8; i += 2) { const t = T0(4) + 1.05 + i * 0.02; piece(t, 0.6, -i * 0.05); piece(t, 0.6, i * 0.05); } // diamond ornaments, centre out
|
|
376
|
+
},
|
|
377
|
+
draw(ctx, W, H_, t) {
|
|
378
|
+
nextId = 1; CT = t;
|
|
379
|
+
const r = H.rng(2026);
|
|
380
|
+
const press = 0.35 + 0.65 * H.ease.out(H.clamp((t - 0.2) / 3.4)); // impression strength ramps in
|
|
381
|
+
const blk = H.layer(W, H_), b = blk.getContext('2d');
|
|
382
|
+
const red = H.layer(W, H_), rd = red.getContext('2d');
|
|
383
|
+
const L = 58, R = 1222;
|
|
384
|
+
|
|
385
|
+
// ---- black forme ----
|
|
386
|
+
rule(b, r, L, R, 28, 8, 0.12); rule(b, r, L, R, 42, 2.5, 0.18);
|
|
387
|
+
setType(b, r, 'THINKING', '400|"Anton"', 640, 318, 1110, 196, { spacing: 10, t0: 0.85, dt: 0.1 });
|
|
388
|
+
setType(b, r, 'LIVE DEMONSTRATION', '400|"Bebas Neue"', 640, 552, 800, 54, { spacing: 18, jit: 0.6, t0: 2.45, dt: 0.025 });
|
|
389
|
+
gear(b, r, 218, 398, 48, 10, 0.2 + t * 0.3, 2.28); gear(b, r, 1062, 398, 48, 10, -0.1 - t * 0.3, 2.28);
|
|
390
|
+
gear(b, r, 162, 432, 24, 8, 0.5 - t * 0.6, 2.36); gear(b, r, 1118, 432, 24, 8, 0.1 + t * 0.6, 2.36);
|
|
391
|
+
rule(b, r, L, R, 666, 2.5, 3.5); rule(b, r, L, R, 676, 8, 3.44);
|
|
392
|
+
// thin side rules with diamond terminals framing 'LIVE DEMONSTRATION'
|
|
393
|
+
rule(b, r, L + 10, 220, 525, 2, 2.42); rule(b, r, 1060, R - 10, 525, 2, 2.42);
|
|
394
|
+
|
|
395
|
+
// ---- red forme ----
|
|
396
|
+
setType(rd, r, 'NOW SHOWING', '400|"Rubik Mono One"', 640, 98, 420, 25, { spacing: 30, grain: false, jit: 0.4, t0: 0.38, dt: 0.035 });
|
|
397
|
+
star(rd, r, 392, 86, 15, 0.32); star(rd, r, 888, 86, 15, 0.76);
|
|
398
|
+
setType(rd, r, 'MACHINES', '400|"Abril Fatface"', 640, 448, 680, 98, { spacing: 6, t0: 1.75, dt: 0.065 });
|
|
399
|
+
for (let i = 0; i < 17; i++) diamond(rd, r, 640 + (i - 8) * 34, 590, i % 2 ? 5 : 8, 2.92 + Math.abs(i - 8) * 0.03);
|
|
400
|
+
setType(rd, r, 'ADMISSION FREE', '400|"Rubik Mono One"', 640, 638, 360, 20, { spacing: 24, grain: false, jit: 0.4, t0: 3.2, dt: 0.02 });
|
|
401
|
+
diamond(rd, r, 230, 525, 8, 2.5); diamond(rd, r, 1050, 525, 8, 2.5);
|
|
402
|
+
rule(rd, r, L, R, 15, 4, 0.24); rule(rd, r, L, R, 689, 4, 3.56);
|
|
403
|
+
|
|
404
|
+
// ---- paper (static: built once, the random draws are still consumed so everything after is unchanged) ----
|
|
405
|
+
const fib = [], fox = [];
|
|
406
|
+
for (let i = 0; i < 260; i++) fib.push([r.range(0, W), r.range(0, H_), r.range(0, 6.28), r.range(4, 22), r.chance(0.5), r.range(0.1, 0.3), r.range(0.4, 1.1)]);
|
|
407
|
+
for (let i = 0; i < 14; i++) fox.push([r.range(0, W), r.range(0, H_), r.range(2, 9)]);
|
|
408
|
+
if (!HP || HP.width !== W || HP.height !== H_) {
|
|
409
|
+
HP = H.layer(W, H_); const pc = HP.getContext('2d');
|
|
410
|
+
paperBase(pc, W, H_);
|
|
411
|
+
for (const [x0, y0, a, l, dk, al, lw] of fib) {
|
|
412
|
+
pc.strokeStyle = `rgba(${dk ? '120,95,60' : '255,250,235'},${al})`; pc.lineWidth = lw;
|
|
413
|
+
pc.beginPath(); pc.moveTo(x0, y0); pc.quadraticCurveTo(x0 + Math.cos(a + 0.5) * l * 0.6, y0 + Math.sin(a + 0.5) * l * 0.6, x0 + Math.cos(a) * l, y0 + Math.sin(a) * l); pc.stroke();
|
|
414
|
+
}
|
|
415
|
+
// foxing
|
|
416
|
+
for (const [x0, y0, rr] of fox) { const g = pc.createRadialGradient(x0, y0, 0, x0, y0, rr); g.addColorStop(0, 'rgba(150,100,50,0.22)'); g.addColorStop(1, 'rgba(150,100,50,0)'); pc.fillStyle = g; pc.fillRect(x0 - rr, y0 - rr, rr * 2, rr * 2); }
|
|
417
|
+
H.vignette(pc, W, H_, 0.18, '120,85,40');
|
|
418
|
+
}
|
|
419
|
+
ctx.drawImage(HP, 0, 0);
|
|
420
|
+
|
|
421
|
+
// ---- masks ----
|
|
422
|
+
const dx = 2.5, dy = -1.5; // red forme slightly out of register
|
|
423
|
+
const redShift = H.layer(W, H_), rs = redShift.getContext('2d'); rs.translate(W / 2, H_ / 2); rs.rotate(0.0015); rs.translate(-W / 2, -H_ / 2); rs.drawImage(red, dx, dy);
|
|
424
|
+
const bk = b.getImageData(0, 0, W, H_).data, rk = rs.getImageData(0, 0, W, H_).data;
|
|
425
|
+
const blurOf = (c, px) => { const o = H.layer(W, H_), ox = o.getContext('2d'); ox.filter = `blur(${px}px)`; ox.drawImage(c, 0, 0); return ox.getImageData(0, 0, W, H_).data; };
|
|
426
|
+
const both = H.layer(W, H_), bx = both.getContext('2d'); bx.drawImage(blk, 0, 0); bx.drawImage(redShift, 0, 0);
|
|
427
|
+
const bb = blurOf(both, 2.2); // impression relief
|
|
428
|
+
const bkB = blurOf(blk, 1.6), rkB = blurOf(redShift, 1.6); // for ink-squash rims
|
|
429
|
+
|
|
430
|
+
const nz = H.makeNoise(33);
|
|
431
|
+
// low-res noise fields
|
|
432
|
+
const GW = 427, GH = 240, fld = new Float32Array(GW * GH * 3);
|
|
433
|
+
for (let y = 0; y < GH; y++) for (let x = 0; x < GW; x++) {
|
|
434
|
+
const j = (y * GW + x) * 3;
|
|
435
|
+
fld[j] = nz.fbm2(x * 0.05, y * 0.05, 3); // broad ink patchiness
|
|
436
|
+
fld[j + 1] = nz.fbm2(x * 0.6, y * 0.6, 2); // fine edge wear
|
|
437
|
+
fld[j + 2] = nz.fbm2(x * 0.012, y * 0.35, 2); // wood grain warp (stretched in x)
|
|
438
|
+
}
|
|
439
|
+
const samp = (x, y, c) => fld[(((y * GH / H_) | 0) * GW + ((x * GW / W) | 0)) * 3 + c];
|
|
440
|
+
const hash = (x, y, s) => { let h = (Math.imul(x, 374761393) + Math.imul(y, 668265263) + Math.imul(s, 1442695041)) | 0; h = Math.imul(h ^ (h >>> 13), 1274126177); h ^= h >>> 16; return (h >>> 0) / 4294967296; };
|
|
441
|
+
|
|
442
|
+
const img = ctx.getImageData(0, 0, W, H_), d = img.data;
|
|
443
|
+
const inkPass = (i, x, y, m, mB, ink, s, rr, gg, bl) => {
|
|
444
|
+
const a = m[i + 3] / 255; if (a < 0.02) return null;
|
|
445
|
+
const dens0 = m[i + 1] / 255, phase = m[i + 2] / 255;
|
|
446
|
+
const broad = samp(x, y, 0), fine = samp(x, y, 1);
|
|
447
|
+
// worn, slightly ragged edges
|
|
448
|
+
const ab = mB[i + 3] / 255;
|
|
449
|
+
const thr = 0.5 + fine * 0.45 + (hash(x, y, s) - 0.5) * 0.2;
|
|
450
|
+
let cov = H.clamp((Math.min(a, ab * 1.15) - thr) * 2.6 + 0.5);
|
|
451
|
+
if (cov <= 0) return null;
|
|
452
|
+
let dens = (0.25 + dens0 * 0.85) * (0.97 + broad * 0.22) + (hash(x, y, s + 1) - 0.5) * 0.08;
|
|
453
|
+
// ink squash: darker rim just inside the edges
|
|
454
|
+
const rim = H.clamp((a - mB[i + 3] / 255) * 3.5);
|
|
455
|
+
// wood grain in the big blocks
|
|
456
|
+
if (phase > 0) {
|
|
457
|
+
const gv = Math.sin((y + samp(x, y, 2) * 40 + phase * 30) * 0.9 + Math.sin(x * 0.01 + phase * 9) * 2.5);
|
|
458
|
+
const gv2 = nz.n2(x * 0.004 + phase * 7, y * 0.22);
|
|
459
|
+
dens *= 1 - 0.32 * H.smooth(0.55, 1, gv * 0.5 + gv2 * 0.8);
|
|
460
|
+
// a low spot on the block that took less ink
|
|
461
|
+
dens *= 1 - 0.3 * H.smooth(0.2, 0.7, broad + (phase - 0.5) * 0.6);
|
|
462
|
+
}
|
|
463
|
+
// pinholes / speckle
|
|
464
|
+
if (hash(x, y, s + 2) < 0.004 + Math.max(0, -broad - 0.15) * 0.35 + Math.max(0, fine - 0.3) * 0.2) dens *= 0.25;
|
|
465
|
+
// ink squeezed out to the rim: the edge prints solid and slightly heavier even where the face is grainy
|
|
466
|
+
dens = dens * (1 - rim * 0.5) + rim * 0.5 * Math.max(dens, 1.06) + rim * 0.12;
|
|
467
|
+
cov *= H.clamp(dens);
|
|
468
|
+
return cov;
|
|
469
|
+
};
|
|
470
|
+
for (let y = 0; y < H_; y++) for (let x = 0; x < W; x++) {
|
|
471
|
+
const i = (y * W + x) * 4;
|
|
472
|
+
let cr = d[i], cg = d[i + 1], cb = d[i + 2];
|
|
473
|
+
// deboss: impressed areas shade like a shallow relief lit from top-left
|
|
474
|
+
const gA = (y > 2 && y < H_ - 3 && x > 2 && x < W - 3) ? bb[i + 3 + (W + 1) * 8] - bb[i + 3 - (W + 1) * 8] : 0;
|
|
475
|
+
// directional bite: shadowed upper-left wall, only a soft light on the lower-right (no pale all-round halo)
|
|
476
|
+
const sh = 1 - (Math.max(gA, 0) / 255 * 0.14 + Math.min(gA, 0) / 255 * 0.04) * press;
|
|
477
|
+
const inside = bb[i + 3] / 255;
|
|
478
|
+
const dep = 1 - inside * 0.05 * press;
|
|
479
|
+
let k = sh * dep; cr *= k; cg *= k; cb *= k;
|
|
480
|
+
const cR = inkPass(i, x, y, rk, rkB, INKS.red, 10);
|
|
481
|
+
if (cR) { cr = cr * (1 - cR) + cr * (INKS.red[0] / 255) * cR; cg = cg * (1 - cR) + cg * (INKS.red[1] / 255) * cR; cb = cb * (1 - cR) + cb * (INKS.red[2] / 255) * cR; }
|
|
482
|
+
const cK = inkPass(i, x, y, bk, bkB, INKS.black, 20);
|
|
483
|
+
if (cK) { const kk = cK; cr = cr * (1 - kk) + INKS.black[0] * kk; cg = cg * (1 - kk) + INKS.black[1] * kk; cb = cb * (1 - kk) + INKS.black[2] * kk; }
|
|
484
|
+
d[i] = cr; d[i + 1] = cg; d[i + 2] = cb;
|
|
485
|
+
}
|
|
486
|
+
ctx.putImageData(img, 0, 0);
|
|
487
|
+
// stray ink specks from dirty furniture
|
|
488
|
+
for (let i = 0; i < 40; i++) { ctx.fillStyle = `rgba(30,27,26,${r.range(0.2, 0.6)})`; ctx.beginPath(); ctx.arc(r.range(40, W - 40), r.range(40, H_ - 40), r.range(0.5, 1.6), 0, 7); ctx.fill(); }
|
|
489
|
+
const z = 1 + 0.025 * H.ease.inOut(H.clamp((t - 3.0) / 2.0));
|
|
490
|
+
if (z > 1.0001) {
|
|
491
|
+
const cp = H.layer(W, H_); cp.getContext('2d').drawImage(ctx.canvas, 0, 0, W, H_);
|
|
492
|
+
ctx.drawImage(cp, 640 - 640 / z, 330 - 330 / z, W / z, H_ / z, 0, 0, W, H_);
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": 42,
|
|
3
|
+
"name": "Wood Type Letterpress",
|
|
4
|
+
"nameZh": "木活字凸版印刷",
|
|
5
|
+
"family": "Print",
|
|
6
|
+
"familyZh": "印刷质感",
|
|
7
|
+
"description": "A two-ink wood-type broadside on cream stock: mixed display faces set block by block, each letter inked a little differently, wood grain and worn edges in the solids, ink squeezed to the rims and the whole forme bitten into the paper.",
|
|
8
|
+
"motionNotes": "Motion: The forme is proofed block by block — rules first, then each wood letter lands with a heavy kiss of the platen, red and black alternating down the sheet — and the gears keep turning as the impression deepens.",
|
|
9
|
+
"explainerNotes": "Explainer: Every beat is a new proof: the finished sheet is lifted off the press and a fresh one is laid down, then wood type, stock cuts of a cat and a dog, and arrows set from short rule pieces lock up block by block with a kiss of the platen; counters are re-set and re-stamped six times a second, and the wrong guess gets a red rubber-stamp WRONG.",
|
|
10
|
+
"code": "code.js",
|
|
11
|
+
"registeredAs": "letterpress",
|
|
12
|
+
"source": "https://www.futurepedia.io/resources/ai-style-atlas/view"
|
|
13
|
+
}
|