dsh-hyperframes 0.3.1 → 0.4.0
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/README.en.md +6 -5
- package/README.md +7 -6
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -0
- package/package.json +63 -63
- package/skills/embedded-captions/SKILL.md +28 -3
- package/skills/embedded-captions/references/aesthetic-principles.md +2 -3
- package/skills/embedded-captions/references/rail.md +1 -1
- package/skills/embedded-captions/scripts/check-occlusion.cjs +4 -1
- package/skills/embedded-captions/scripts/check-overflow.cjs +1 -0
- package/skills/embedded-captions/scripts/check-rail-climax.cjs +5 -1
- package/skills/embedded-captions/scripts/fixtures/heroless/theme.json +11 -0
- package/skills/embedded-captions/scripts/hf-cli.cjs +33 -0
- package/skills/embedded-captions/scripts/make-theme.cjs +95 -57
- package/skills/embedded-captions/scripts/make-theme.test.mjs +131 -0
- package/skills/embedded-captions/scripts/matte.cjs +1 -13
- package/skills/embedded-captions/scripts/measure-layout.cjs +2 -1
- package/skills/embedded-captions/scripts/preview-frames.cjs +39 -11
- package/skills/embedded-captions/scripts/preview-frames.test.mjs +24 -0
- package/skills/embedded-captions/scripts/render-and-composite.sh +8 -52
- package/skills/embedded-captions/scripts/safe-zones.cjs +4 -1
- package/skills/embedded-captions/scripts/transcribe.cjs +5 -14
- package/skills/embedded-captions/scripts/transcribe.test.mjs +41 -0
- package/skills/faceless-explainer/SKILL.md +20 -16
- package/skills/faceless-explainer/references/story-design.md +1 -1
- package/skills/faceless-explainer/scripts/assemble-index.mjs +6 -4
- package/skills/faceless-explainer/scripts/assemble-index.test.mjs +57 -2
- package/skills/faceless-explainer/scripts/audio.mjs +2 -0
- package/skills/faceless-explainer/scripts/build-frame.mjs +6 -3
- package/skills/faceless-explainer/scripts/captions.mjs +7 -4
- package/skills/faceless-explainer/scripts/frame-packets.mjs +4 -4
- package/skills/faceless-explainer/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/faceless-explainer/scripts/lib/captured-fonts.mjs +58 -0
- package/skills/{hyperframes-core → faceless-explainer}/scripts/lib/frame-packets-core.mjs +5 -23
- package/skills/faceless-explainer/scripts/lib/storyboard.mjs +1 -1
- package/skills/faceless-explainer/scripts/lib/transitions.json +3 -3
- package/skills/faceless-explainer/scripts/transitions.mjs +1 -0
- package/skills/faceless-explainer/scripts/transitions.test.mjs +2 -0
- package/skills/faceless-explainer/sub-agents/frame-worker.md +1 -1
- package/skills/figma/SKILL.md +2 -0
- package/skills/general-video/SKILL.md +13 -11
- package/skills/general-video/scripts/frame-packets.mjs +4 -4
- package/skills/general-video/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/general-video/sub-agents/frame-worker.md +1 -1
- package/skills/hyperframes/SKILL.md +40 -30
- package/skills/{hyperframes-core → hyperframes}/references/brief-contract.md +15 -15
- package/skills/{hyperframes-core → hyperframes}/references/brief-format.md +8 -8
- package/skills/hyperframes/references/capability-menu.md +2 -2
- package/skills/{hyperframes-core → hyperframes}/references/frame-worker-core.md +1 -1
- package/skills/hyperframes/references/intent-interview.md +16 -16
- package/skills/hyperframes/references/plugin-installation.md +43 -0
- package/skills/{hyperframes-core → hyperframes}/references/production-loop.md +11 -11
- package/skills/hyperframes/references/review-loop.md +37 -0
- package/skills/hyperframes/references/route-briefs.md +1 -1
- package/skills/hyperframes/references/routes/motion-graphics.md +1 -1
- package/skills/{hyperframes-core → hyperframes}/references/script-format.md +3 -3
- package/skills/hyperframes/references/skill-lifecycle.md +2 -0
- package/skills/{hyperframes-core → hyperframes}/references/storyboard-format.md +3 -34
- package/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
- package/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
- package/skills/hyperframes-animation/SKILL.md +5 -1
- package/skills/hyperframes-animation/adapters/gsap.md +1 -1
- package/skills/hyperframes-animation/adapters/lottie.md +15 -2
- package/skills/hyperframes-animation/adapters/three.md +14 -0
- package/skills/hyperframes-animation/blueprints/titlecard-reveal.md +1 -1
- package/skills/hyperframes-animation/references/motion-blur.md +133 -0
- package/skills/hyperframes-animation/rules/cursor-click-ripple.md +1 -1
- package/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +1 -1
- package/skills/hyperframes-animation/rules/hacker-flip-3d.md +1 -1
- package/skills/hyperframes-animation/rules/kinetic-beat-slam.md +2 -2
- package/skills/hyperframes-animation/rules/motion-blur-streak.md +1 -1
- package/skills/hyperframes-animation/rules/vertical-spring-ticker.md +1 -1
- package/skills/hyperframes-animation/scripts/package-loader.mjs +47 -16
- package/skills/hyperframes-animation/scripts/package-loader.test.mjs +52 -0
- package/skills/hyperframes-animation/techniques.md +1 -1
- package/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +3 -3
- package/skills/hyperframes-animation/transitions/css-push.md +4 -4
- package/skills/hyperframes-audio/SKILL.md +30 -22
- package/skills/hyperframes-audio/scripts/carve.mjs +6 -3
- package/skills/hyperframes-audio/scripts/carve.test.mjs +16 -1
- package/skills/hyperframes-cli/SKILL.md +44 -35
- package/skills/hyperframes-cli/references/init-and-scaffold.md +8 -6
- package/skills/hyperframes-cli/references/lint-validate-inspect.md +3 -3
- package/skills/hyperframes-cli/references/preview-render.md +35 -32
- package/skills/hyperframes-cli/references/upgrade-info-misc.md +50 -1
- package/skills/hyperframes-core/SKILL.md +30 -24
- package/skills/hyperframes-core/references/composition-patterns.md +3 -42
- package/skills/hyperframes-core/references/creator-editing-recipes.md +131 -7
- package/skills/hyperframes-core/references/data-attributes.md +11 -11
- package/skills/hyperframes-core/references/determinism-rules.md +2 -19
- package/skills/hyperframes-core/references/full-screen-motion.md +0 -9
- package/skills/hyperframes-core/references/minimal-composition.md +2 -2
- package/skills/hyperframes-core/references/sub-compositions.md +3 -66
- package/skills/hyperframes-core/references/tailwind.md +1 -20
- package/skills/hyperframes-core/references/tracks-and-clips.md +2 -6
- package/skills/hyperframes-core/references/variables-and-media.md +3 -3
- package/skills/hyperframes-creative/SKILL.md +2 -0
- package/skills/hyperframes-creative/references/house-style.md +15 -15
- package/skills/hyperframes-creative/references/story-spine.md +3 -1
- package/skills/hyperframes-creative/references/storyboard-recipe.md +57 -0
- package/skills/hyperframes-creative/references/typography.md +1 -1
- package/skills/hyperframes-creative/scripts/package-loader.mjs +47 -16
- package/skills/hyperframes-creative/scripts/package-loader.test.mjs +52 -0
- package/skills/hyperframes-keyframes/SKILL.md +4 -2
- package/skills/hyperframes-registry/SKILL.md +3 -1
- package/skills/hyperframes-registry/references/contributing.md +8 -2
- package/skills/hyperframes-registry/references/discovery.md +20 -34
- package/skills/hyperframes-studio/SKILL.md +77 -0
- package/skills/media-use/SKILL.md +14 -12
- package/skills/media-use/audio/references/captions/authoring.md +4 -0
- package/skills/media-use/audio/references/remove-background.md +1 -1
- package/skills/media-use/audio/references/tts-to-captions.md +11 -2
- package/skills/media-use/audio/references/tts.md +84 -6
- package/skills/media-use/audio/scripts/audio.mjs +15 -6
- package/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +113 -0
- package/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
- package/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
- package/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/media-use/audio/scripts/lib/bgm.mjs +2 -6
- package/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
- package/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
- package/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
- package/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
- package/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
- package/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
- package/skills/media-use/audio/scripts/lib/heygen.mjs +2 -1
- package/skills/media-use/audio/scripts/lib/tts.mjs +15 -3
- package/skills/media-use/audio/scripts/wait-bgm.mjs +8 -4
- package/skills/media-use/audio/scripts/wait-bgm.test.mjs +65 -0
- package/skills/media-use/references/audio.md +3 -2
- package/skills/media-use/references/grading.md +7 -7
- package/skills/media-use/references/media-treatment-recipes.md +1 -1
- package/skills/media-use/references/memory.md +2 -2
- package/skills/media-use/references/meta.md +2 -2
- package/skills/media-use/references/operations.md +15 -13
- package/skills/media-use/references/resolve.md +22 -11
- package/skills/media-use/references/setup-providers.md +11 -11
- package/skills/media-use/scripts/audio-duck.mjs +19 -27
- package/skills/media-use/scripts/compatibility.test.mjs +96 -0
- package/skills/media-use/scripts/lib/config-lock.mjs +45 -0
- package/skills/media-use/scripts/lib/duck.mjs +16 -10
- package/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
- package/skills/media-use/scripts/lib/media-home.mjs +20 -0
- package/skills/media-use/scripts/lib/npx-sync.mjs +28 -2
- package/skills/media-use/scripts/lib/prefs-store.mjs +2 -2
- package/skills/media-use/scripts/lib/recipe-store.mjs +2 -2
- package/skills/media-use/scripts/lib/telemetry.mjs +29 -41
- package/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
- package/skills/media-use/scripts/prefs.mjs +1 -1
- package/skills/media-use/scripts/recipe.mjs +1 -1
- package/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
- package/skills/media-use/scripts/resolve.mjs +27 -1267
- package/skills/media-use/scripts/transcribe.mjs +39 -25
- package/skills/media-use/scripts/transcribe.test.mjs +112 -0
- package/skills/media-use/scripts/transcript-cut.mjs +39 -8
- package/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
- package/skills/motion-graphics/SKILL.md +3 -1
- package/skills/motion-graphics/agents/builder.md +1 -0
- package/skills/motion-graphics/agents/director.md +2 -1
- package/skills/motion-graphics/catalog-map.md +25 -13
- package/skills/motion-graphics/categories/charts/module.md +2 -1
- package/skills/motion-graphics/categories/lower-thirds/module.md +4 -0
- package/skills/motion-graphics/categories/news/module.md +1 -1
- package/skills/motion-graphics/references/motion-vocabulary.md +4 -0
- package/skills/music-to-video/SKILL.md +8 -6
- package/skills/music-to-video/references/montage.md +3 -6
- package/skills/music-to-video/references/motion-primitives/3d-card-flip/index.html +10 -111
- package/skills/music-to-video/references/motion-primitives/3d-card-flip/scene.html +119 -0
- package/skills/music-to-video/references/motion-primitives/bg-flow-field/index.html +11 -284
- package/skills/music-to-video/references/motion-primitives/bg-flow-field/scene.html +294 -0
- package/skills/music-to-video/references/motion-primitives/binary-decrypt/index.html +10 -76
- package/skills/music-to-video/references/motion-primitives/binary-decrypt/scene.html +85 -0
- package/skills/music-to-video/references/motion-primitives/blur-resolve/index.html +10 -52
- package/skills/music-to-video/references/motion-primitives/blur-resolve/scene.html +60 -0
- package/skills/music-to-video/references/motion-primitives/braam-punch/index.html +10 -92
- package/skills/music-to-video/references/motion-primitives/braam-punch/scene.html +100 -0
- package/skills/music-to-video/references/motion-primitives/chromatic-split/index.html +10 -103
- package/skills/music-to-video/references/motion-primitives/chromatic-split/scene.html +111 -0
- package/skills/music-to-video/references/motion-primitives/chrome-sweep/index.html +10 -60
- package/skills/music-to-video/references/motion-primitives/chrome-sweep/scene.html +68 -0
- package/skills/music-to-video/references/motion-primitives/counting-punch/index.html +10 -110
- package/skills/music-to-video/references/motion-primitives/counting-punch/scene.html +119 -0
- package/skills/music-to-video/references/motion-primitives/crash-zoom-in/index.html +10 -112
- package/skills/music-to-video/references/motion-primitives/crash-zoom-in/scene.html +120 -0
- package/skills/music-to-video/references/motion-primitives/datamosh-smear/index.html +10 -121
- package/skills/music-to-video/references/motion-primitives/datamosh-smear/scene.html +131 -0
- package/skills/music-to-video/references/motion-primitives/directional-fill/index.html +10 -90
- package/skills/music-to-video/references/motion-primitives/directional-fill/scene.html +103 -0
- package/skills/music-to-video/references/motion-primitives/dolly-zoom/index.html +10 -94
- package/skills/music-to-video/references/motion-primitives/dolly-zoom/scene.html +102 -0
- package/skills/music-to-video/references/motion-primitives/electric-arc/index.html +10 -100
- package/skills/music-to-video/references/motion-primitives/electric-arc/scene.html +105 -0
- package/skills/music-to-video/references/motion-primitives/flash-cut/index.html +10 -89
- package/skills/music-to-video/references/motion-primitives/flash-cut/scene.html +97 -0
- package/skills/music-to-video/references/motion-primitives/gooey-metaball/index.html +10 -197
- package/skills/music-to-video/references/motion-primitives/gooey-metaball/scene.html +206 -0
- package/skills/music-to-video/references/motion-primitives/hard-cut/index.html +10 -74
- package/skills/music-to-video/references/motion-primitives/hard-cut/scene.html +82 -0
- package/skills/music-to-video/references/motion-primitives/hypercut-whip/index.html +10 -36
- package/skills/music-to-video/references/motion-primitives/hypercut-whip/scene.html +44 -0
- package/skills/music-to-video/references/motion-primitives/iris-open/index.html +10 -61
- package/skills/music-to-video/references/motion-primitives/iris-open/scene.html +69 -0
- package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/index.html +10 -55
- package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/scene.html +64 -0
- package/skills/music-to-video/references/motion-primitives/liquid-morph/index.html +10 -88
- package/skills/music-to-video/references/motion-primitives/liquid-morph/scene.html +96 -0
- package/skills/music-to-video/references/motion-primitives/mask-reveal/index.html +10 -66
- package/skills/music-to-video/references/motion-primitives/mask-reveal/scene.html +74 -0
- package/skills/music-to-video/references/motion-primitives/mosaic-pack/index.html +10 -81
- package/skills/music-to-video/references/motion-primitives/mosaic-pack/scene.html +89 -0
- package/skills/music-to-video/references/motion-primitives/neon-flicker/index.html +10 -65
- package/skills/music-to-video/references/motion-primitives/neon-flicker/scene.html +73 -0
- package/skills/music-to-video/references/motion-primitives/outline-to-fill/index.html +10 -74
- package/skills/music-to-video/references/motion-primitives/outline-to-fill/scene.html +82 -0
- package/skills/music-to-video/references/motion-primitives/palette-flip/index.html +10 -89
- package/skills/music-to-video/references/motion-primitives/palette-flip/scene.html +97 -0
- package/skills/music-to-video/references/motion-primitives/particle-burst/index.html +10 -98
- package/skills/music-to-video/references/motion-primitives/particle-burst/scene.html +106 -0
- package/skills/music-to-video/references/motion-primitives/pixel-dissolve/index.html +10 -78
- package/skills/music-to-video/references/motion-primitives/pixel-dissolve/scene.html +86 -0
- package/skills/music-to-video/references/motion-primitives/radial-burst-lines/index.html +10 -117
- package/skills/music-to-video/references/motion-primitives/radial-burst-lines/scene.html +130 -0
- package/skills/music-to-video/references/motion-primitives/screen-shake/index.html +10 -70
- package/skills/music-to-video/references/motion-primitives/screen-shake/scene.html +78 -0
- package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/index.html +10 -87
- package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/scene.html +100 -0
- package/skills/music-to-video/references/motion-primitives/spotlight-sweep/index.html +10 -94
- package/skills/music-to-video/references/motion-primitives/spotlight-sweep/scene.html +102 -0
- package/skills/music-to-video/references/motion-primitives/staggered-exit/index.html +10 -74
- package/skills/music-to-video/references/motion-primitives/staggered-exit/scene.html +82 -0
- package/skills/music-to-video/references/motion-primitives/text-spectral-rays/index.html +11 -271
- package/skills/music-to-video/references/motion-primitives/text-spectral-rays/scene.html +280 -0
- package/skills/music-to-video/references/motion-primitives/text-wave-distort/index.html +10 -92
- package/skills/music-to-video/references/motion-primitives/text-wave-distort/scene.html +106 -0
- package/skills/music-to-video/references/motion-primitives/tile-mosaic/index.html +10 -101
- package/skills/music-to-video/references/motion-primitives/tile-mosaic/scene.html +109 -0
- package/skills/music-to-video/references/motion-primitives/typewriter-reveal/index.html +10 -79
- package/skills/music-to-video/references/motion-primitives/typewriter-reveal/scene.html +91 -0
- package/skills/music-to-video/references/motion-primitives/word-grid-burst/index.html +10 -83
- package/skills/music-to-video/references/motion-primitives/word-grid-burst/scene.html +96 -0
- package/skills/music-to-video/references/planning.md +2 -2
- package/skills/music-to-video/scripts/lib/storyboard.mjs +1 -1
- package/skills/music-to-video/sub-agents/frame-worker.md +2 -2
- package/skills/pr-to-video/SKILL.md +20 -16
- package/skills/pr-to-video/references/code-vocabulary.md +14 -12
- package/skills/pr-to-video/references/story-design.md +1 -1
- package/skills/pr-to-video/scripts/assemble-index.mjs +6 -4
- package/skills/pr-to-video/scripts/assemble-index.test.mjs +57 -2
- package/skills/pr-to-video/scripts/audio.mjs +2 -0
- package/skills/pr-to-video/scripts/build-frame.mjs +6 -3
- package/skills/pr-to-video/scripts/captions.mjs +7 -4
- package/skills/pr-to-video/scripts/captions.test.mjs +41 -0
- package/skills/pr-to-video/scripts/frame-packets.mjs +4 -4
- package/skills/pr-to-video/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/pr-to-video/scripts/lib/captured-fonts.mjs +58 -0
- package/skills/pr-to-video/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/pr-to-video/scripts/lib/storyboard.mjs +1 -1
- package/skills/pr-to-video/scripts/lib/transitions.json +3 -3
- package/skills/pr-to-video/scripts/transitions.mjs +7 -5
- package/skills/pr-to-video/sub-agents/frame-worker.md +1 -1
- package/skills/product-launch-video/SKILL.md +20 -16
- package/skills/product-launch-video/references/story-design.md +1 -1
- package/skills/product-launch-video/scripts/assemble-index.mjs +6 -4
- package/skills/product-launch-video/scripts/assemble-index.test.mjs +57 -2
- package/skills/product-launch-video/scripts/audio.mjs +2 -0
- package/skills/product-launch-video/scripts/audio.test.mjs +16 -0
- package/skills/product-launch-video/scripts/build-frame-subsets.test.mjs +152 -0
- package/skills/product-launch-video/scripts/build-frame.mjs +6 -3
- package/skills/product-launch-video/scripts/captions.mjs +7 -4
- package/skills/product-launch-video/scripts/frame-packets.mjs +4 -4
- package/skills/product-launch-video/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/product-launch-video/scripts/lib/captured-fonts.mjs +58 -0
- package/skills/product-launch-video/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/product-launch-video/scripts/lib/storyboard.mjs +1 -1
- package/skills/product-launch-video/scripts/lib/transitions.json +3 -3
- package/skills/product-launch-video/scripts/transitions.mjs +7 -5
- package/skills/product-launch-video/scripts/transitions.test.mjs +68 -0
- package/skills/product-launch-video/sub-agents/frame-worker.md +1 -1
- package/skills/remotion-to-hyperframes/SKILL.md +7 -4
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/expected.json +5 -5
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/compositions/title.html +31 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/index.html +10 -25
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/README.md +8 -8
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/expected.json +9 -9
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-1.html +35 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-2.html +35 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-3.html +36 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/index.html +28 -71
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/expected.json +3 -3
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-1.html +52 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-2.html +99 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-3.html +55 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/index.html +13 -212
- package/skills/remotion-to-hyperframes/references/api-map.md +16 -16
- package/skills/remotion-to-hyperframes/references/limitations.md +7 -7
- package/skills/remotion-to-hyperframes/references/lottie.md +5 -7
- package/skills/remotion-to-hyperframes/references/media.md +3 -3
- package/skills/remotion-to-hyperframes/references/parameters.md +5 -0
- package/skills/remotion-to-hyperframes/references/sequencing.md +71 -18
- package/skills/slideshow/SKILL.md +4 -1
- package/skills/slideshow/references/standalone-harness.md +0 -3
- package/skills/talking-head-recut/SKILL.md +10 -1
- package/skills/hyperframes-core/references/review-loop.md +0 -41
- package/skills/media-use/scripts/lib/adopt.mjs +0 -128
- package/skills/media-use/scripts/lib/adopt.test.mjs +0 -95
- package/skills/media-use/scripts/lib/bgm-provider.mjs +0 -20
- package/skills/media-use/scripts/lib/brand-provider.mjs +0 -59
- package/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +0 -108
- package/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +0 -85
- package/skills/media-use/scripts/lib/cache.mjs +0 -150
- package/skills/media-use/scripts/lib/candidates.mjs +0 -91
- package/skills/media-use/scripts/lib/candidates.test.mjs +0 -155
- package/skills/media-use/scripts/lib/codex-provider.mjs +0 -161
- package/skills/media-use/scripts/lib/codex-provider.test.mjs +0 -34
- package/skills/media-use/scripts/lib/coverage.test.mjs +0 -117
- package/skills/media-use/scripts/lib/cube-build.mjs +0 -181
- package/skills/media-use/scripts/lib/cube-build.test.mjs +0 -80
- package/skills/media-use/scripts/lib/cube-validate.mjs +0 -198
- package/skills/media-use/scripts/lib/cube-validate.test.mjs +0 -125
- package/skills/media-use/scripts/lib/cutlist.test.mjs +0 -148
- package/skills/media-use/scripts/lib/duck.test.mjs +0 -118
- package/skills/media-use/scripts/lib/error-diffusion.test.mjs +0 -102
- package/skills/media-use/scripts/lib/freeze.mjs +0 -70
- package/skills/media-use/scripts/lib/freeze.test.mjs +0 -46
- package/skills/media-use/scripts/lib/grade-analyzer.mjs +0 -264
- package/skills/media-use/scripts/lib/grade-analyzer.test.mjs +0 -285
- package/skills/media-use/scripts/lib/heygen-cli.mjs +0 -191
- package/skills/media-use/scripts/lib/heygen-cli.test.mjs +0 -301
- package/skills/media-use/scripts/lib/heygen-search.mjs +0 -45
- package/skills/media-use/scripts/lib/heygen-search.test.mjs +0 -49
- package/skills/media-use/scripts/lib/heygen-video-provider.mjs +0 -127
- package/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +0 -344
- package/skills/media-use/scripts/lib/image-provider.mjs +0 -44
- package/skills/media-use/scripts/lib/local-models.mjs +0 -318
- package/skills/media-use/scripts/lib/local-models.test.mjs +0 -220
- package/skills/media-use/scripts/lib/local-run.mjs +0 -78
- package/skills/media-use/scripts/lib/local-run.test.mjs +0 -121
- package/skills/media-use/scripts/lib/logo-provider.mjs +0 -222
- package/skills/media-use/scripts/lib/logo-provider.test.mjs +0 -137
- package/skills/media-use/scripts/lib/ltx-video-provider.mjs +0 -94
- package/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +0 -316
- package/skills/media-use/scripts/lib/lut-preset-provider.mjs +0 -266
- package/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +0 -176
- package/skills/media-use/scripts/lib/manifest.test.mjs +0 -388
- package/skills/media-use/scripts/lib/match.mjs +0 -47
- package/skills/media-use/scripts/lib/mflux-provider.mjs +0 -128
- package/skills/media-use/scripts/lib/mflux-provider.test.mjs +0 -174
- package/skills/media-use/scripts/lib/misses.mjs +0 -49
- package/skills/media-use/scripts/lib/misses.test.mjs +0 -78
- package/skills/media-use/scripts/lib/npx-sync.test.mjs +0 -50
- package/skills/media-use/scripts/lib/parakeet-words.test.mjs +0 -44
- package/skills/media-use/scripts/lib/prefs-store.test.mjs +0 -189
- package/skills/media-use/scripts/lib/probe.mjs +0 -39
- package/skills/media-use/scripts/lib/probe.test.mjs +0 -31
- package/skills/media-use/scripts/lib/providers.mjs +0 -5
- package/skills/media-use/scripts/lib/recipe-store.test.mjs +0 -367
- package/skills/media-use/scripts/lib/registry.mjs +0 -218
- package/skills/media-use/scripts/lib/registry.test.mjs +0 -261
- package/skills/media-use/scripts/lib/search.mjs +0 -24
- package/skills/media-use/scripts/lib/search.test.mjs +0 -32
- package/skills/media-use/scripts/lib/sfx-provider.mjs +0 -23
- package/skills/media-use/scripts/lib/specs.mjs +0 -132
- package/skills/media-use/scripts/lib/specs.test.mjs +0 -157
- package/skills/media-use/scripts/lib/stats.mjs +0 -117
- package/skills/media-use/scripts/lib/stats.test.mjs +0 -165
- package/skills/media-use/scripts/lib/telemetry.test.mjs +0 -373
- package/skills/media-use/scripts/lib/tts-local-provider.mjs +0 -92
- package/skills/media-use/scripts/lib/tts-local-provider.test.mjs +0 -72
- package/skills/media-use/scripts/lib/usage.mjs +0 -57
- package/skills/media-use/scripts/lib/usage.test.mjs +0 -54
- package/skills/media-use/scripts/lib/voice-provider.mjs +0 -57
- package/skills/media-use/scripts/lib/voice-provider.test.mjs +0 -46
- package/skills/media-use/scripts/resolve.test.mjs +0 -1120
- /package/skills/{hyperframes-core → hyperframes}/references/subagent-dispatch.md +0 -0
|
@@ -3,13 +3,15 @@ name: music-to-video
|
|
|
3
3
|
description: "Turn a music track (an audio file, a video to pull audio from, or a track generated from a mood brief) into a beat-synced video — lyric video, slideshow, or kinetic promo. The music drives all pacing; any user-supplied images/videos are cut onto the same beat grid, and a complete video needs zero assets. Narrated pieces → the input-matched workflow (see /hyperframes). Unclear → /hyperframes."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
**Plugin installs:** Before setup or freshness commands, follow [plugin execution rules](../hyperframes/references/plugin-installation.md) when this skill is inside a HyperFrames plugin. Standalone installs keep the update instructions below.
|
|
7
|
+
|
|
6
8
|
> **First, keep this skill fresh — confirm with the user before running:** `npx hyperframes skills update music-to-video`. A fast no-op when everything is current; otherwise it refreshes this skill plus the core domain skills it depends on before you rely on them.
|
|
7
9
|
|
|
8
10
|
# music-to-video — one music-grounded, beat-synced video workflow
|
|
9
11
|
|
|
10
12
|
Use this skill to turn a **music track** into a beat-synced HyperFrames video. You analyze the track once, lay out the frames, fill in a per-frame plan, and build each frame as a composition. The input is a music track plus optional user images or videos — there is **no narration and no website capture**. Typography and templates are the floor (a complete video needs zero assets); any media the user supplies is cut in on the same beat grid.
|
|
11
13
|
|
|
12
|
-
You are the **orchestrator**. Work in `videos/<project>/`. Run the steps in order and pass each **Gate** before moving on. Two steps need the user: **Step 3** (plan approval) and **Step 6** (render approval) — both are checkpoint gates per `../hyperframes
|
|
14
|
+
You are the **orchestrator**. Work in `videos/<project>/`. Run the steps in order and pass each **Gate** before moving on. Two steps need the user: **Step 3** (plan approval) and **Step 6** (render approval) — both are checkpoint gates per `../hyperframes/references/brief-contract.md` (read it before Step 0): in autonomous mode, post the summary as a heads-up and proceed instead of waiting. Do every step yourself except **Step 4**, where you dispatch **one sub-agent per frame**. Keep design and motion rules out of this file — they live in `references/` and the `frame-worker` sub-agent.
|
|
13
15
|
|
|
14
16
|
`SKILL_DIR` = this skill directory. `PROJECT_DIR` = `videos/<project-name>/`.
|
|
15
17
|
|
|
@@ -91,14 +93,14 @@ Goal: Turn the skeleton into an approved, complete `STORYBOARD.md`.
|
|
|
91
93
|
Read [`references/planning.md`](references/planning.md), [`storyboard-format.md`](references/storyboard-format.md), [`template-catalog.md`](references/template-catalog.md), [`motion-primitive-catalog.md`](references/motion-primitive-catalog.md), and [`montage.md`](references/montage.md) (only if the user supplied assets). Editing the same file in place, do two things:
|
|
92
94
|
|
|
93
95
|
1. **Pick the brand.** Choose one preset from `../hyperframes-creative/frame-presets/` using the table in `../hyperframes-creative/references/design-spec.md` (match the track's mood; **only its fonts and colors matter** — templates own composition). Copy it into `frame.md` **unmodified** and fill the frontmatter `style` (font + a ≤4–6 swatch palette) from it.
|
|
94
|
-
2. **Fill every frame.** Decide its groups and give each a treatment: a matched template from the catalog (with bound params and real audiomap anchors), a free-compose from the primitive catalog, or an asset treatment that **obeys `pacing`**. Write the copy. You own WHAT (template / primitives + content + anchors); the frame-worker owns HOW — **never write millisecond tweens into the storyboard**.
|
|
96
|
+
2. **Fill every frame.** Decide its groups and give each a treatment: a matched template from the catalog (with bound params and real audiomap anchors), a free-compose from the primitive catalog, or an asset treatment that **obeys `pacing`**. **Before you free-compose a named look, search the live catalog for it**: for every look, effect, treatment or transition the user asked for — "CRT scanlines", "glitch", "film grain", "shimmer sweep" — run `npx hyperframes catalog --query "<the look, in plain English>" --json` and read the top results. `template-catalog.md` and `motion-primitive-catalog.md` list only this skill's own local materials; the search ranks the whole hosted registry (~400 blocks and components) and needs **nothing installed** — no project, no prior `add`, no account. Free-compose a look only after a search for it came back with nothing that fits. Write the copy. You own WHAT (template / primitives + content + anchors); the frame-worker owns HOW — **never write millisecond tweens into the storyboard**.
|
|
95
97
|
|
|
96
98
|
```bash
|
|
97
99
|
node <SKILL_DIR>/scripts/validate-plan.mjs --storyboard "$PROJECT_DIR/STORYBOARD.md" \
|
|
98
100
|
--audiomap "$PROJECT_DIR/audiomap.json" --templates <SKILL_DIR>/references/templates
|
|
99
101
|
```
|
|
100
102
|
|
|
101
|
-
Fix every `✗` (hard errors: duration mismatch, frames not tiling the track, a missing `src`); warnings are best-effort. Then
|
|
103
|
+
Fix every `✗` (hard errors: duration mismatch, frames not tiling the track, a missing `src`); warnings are best-effort. Then present the frame-by-frame summary in chat as a proposal (`../hyperframes/references/review-loop.md` § 1) and iterate on the user's replies until they approve; for `storyboard: yes`, also write it as `storyboard.html` (`../hyperframes-creative/references/storyboard-recipe.md` § 3) for them to open. In autonomous mode this is a checkpoint gate: post the summary as a heads-up and proceed (the `validate-plan.mjs` pass is a quality gate and still blocks).
|
|
102
104
|
|
|
103
105
|
**Gate:** `frame.md` is a verbatim preset copy; `validate-plan.mjs` exits 0; the user approved the plan (autonomous: the summary was posted as a heads-up).
|
|
104
106
|
|
|
@@ -108,7 +110,7 @@ Fix every `✗` (hard errors: duration mismatch, frames not tiling the track, a
|
|
|
108
110
|
|
|
109
111
|
Goal: Build every frame as a self-contained composition file.
|
|
110
112
|
|
|
111
|
-
Create `compositions/frames/`. Read [`sub-agents/frame-worker.md`](sub-agents/frame-worker.md) and `../hyperframes
|
|
113
|
+
Create `compositions/frames/`. Read [`sub-agents/frame-worker.md`](sub-agents/frame-worker.md) and `../hyperframes/references/subagent-dispatch.md`. Dispatch **one frame-worker per frame**, in parallel where possible (otherwise in waves). Each worker gets exactly one frame and this context:
|
|
112
114
|
|
|
113
115
|
```text
|
|
114
116
|
PROJECT_DIR: <abs path>
|
|
@@ -191,7 +193,7 @@ Inspect at `t=0`, each frame start, the strongest DROP / SURGE, every `hard_stop
|
|
|
191
193
|
| [`references/motion-primitive-catalog.md`](references/motion-primitive-catalog.md) | Step 3/4: L0 recipes for free-compose |
|
|
192
194
|
| [`references/montage.md`](references/montage.md) | Step 3/4: asset treatments (beat-cut / ken-burns) |
|
|
193
195
|
| [`sub-agents/frame-worker.md`](sub-agents/frame-worker.md) | Step 4: dispatch + build one frame |
|
|
194
|
-
| `../hyperframes
|
|
196
|
+
| `../hyperframes/references/subagent-dispatch.md` | Step 4: dispatch sub-agents safely |
|
|
195
197
|
| `../hyperframes-creative/references/design-spec.md` | Step 3: pick the preset (the brand) |
|
|
196
198
|
|
|
197
199
|
## Directory layout
|
|
@@ -202,7 +204,7 @@ music-to-video/
|
|
|
202
204
|
references/ frame-skeleton.md · planning.md · storyboard-format.md
|
|
203
205
|
template-catalog.md · motion-primitive-catalog.md · montage.md
|
|
204
206
|
templates/<id>/ { index.html (+ assets/ · program.json) } ← L1 catalog impls
|
|
205
|
-
motion-primitives/<id>/ { index.html } (+ ../assets/gsap.min.js shared by recipes) ← L0 catalog impls
|
|
207
|
+
motion-primitives/<id>/ { index.html (mounts the scene), scene.html (the sub-composition) } (+ ../assets/gsap.min.js shared by recipes) ← L0 catalog impls
|
|
206
208
|
scripts/ analyze-beatgrid.py · assemble-index.mjs · validate-plan.mjs · stage-assets.mjs · lib/storyboard.mjs
|
|
207
209
|
sub-agents/ frame-worker.md ← the one subagent (one per frame)
|
|
208
210
|
```
|
|
@@ -16,9 +16,7 @@ The asset-driven analogue of a per-onset typographic group: cut to a new clip on
|
|
|
16
16
|
(the frame's beats/onsets from the audiomap). Each clip is a `class="clip"` element
|
|
17
17
|
(`<img>` for a photo, **muted** `<video>` for a motion clip) placed at its anchor with
|
|
18
18
|
`data-start`/`data-duration`/`data-track-index` per the core clip contract. Between clips,
|
|
19
|
-
crossfade the outgoing content to `opacity:0` ending **at** the next anchor
|
|
20
|
-
**hard-kill** with a `tl.set(..., {opacity:0}, anchor)` — this pair is required (the
|
|
21
|
-
`gsap_exit_missing_hard_kill` lint rule; non-linear seeking otherwise bleeds stale frames).
|
|
19
|
+
crossfade the outgoing content to `opacity:0` ending **at** the next anchor.
|
|
22
20
|
Cut on the **strong** anchors; land a hero clip on a `key_moment`/downbeat.
|
|
23
21
|
|
|
24
22
|
### `ken_burns` — slow push on one clip (fits a `phrase_flow` frame)
|
|
@@ -52,7 +50,6 @@ bed. Use when the user wants their footage present but the message must stay rea
|
|
|
52
50
|
## Deferred hook (not v1)
|
|
53
51
|
|
|
54
52
|
A clip that should play **its own sound** (interview cut, lyric clip) needs a sibling
|
|
55
|
-
`<audio>` mounted at the **root** by the assembler, with the BGM ducked under it (
|
|
56
|
-
volume
|
|
57
|
-
clipEnd)`). The frame-worker mounts no audio. Keep clips muted in v1; wire clip-audio +
|
|
53
|
+
`<audio>` mounted at the **root** by the assembler, with the BGM ducked under it (a
|
|
54
|
+
`data-automation` volume lane on the BGM, see `creator-editing-recipes.md` in `hyperframes-core`). The frame-worker mounts no audio. Keep clips muted in v1; wire clip-audio +
|
|
58
55
|
ducking only when the user asks.
|
|
@@ -13,11 +13,6 @@
|
|
|
13
13
|
--hg-fg: #f5f5fa;
|
|
14
14
|
--hg-dim: #6b6b78;
|
|
15
15
|
}
|
|
16
|
-
* {
|
|
17
|
-
margin: 0;
|
|
18
|
-
padding: 0;
|
|
19
|
-
box-sizing: border-box;
|
|
20
|
-
}
|
|
21
16
|
html,
|
|
22
17
|
body {
|
|
23
18
|
margin: 0;
|
|
@@ -29,72 +24,6 @@
|
|
|
29
24
|
color: var(--hg-fg);
|
|
30
25
|
-webkit-font-smoothing: antialiased;
|
|
31
26
|
}
|
|
32
|
-
#scene {
|
|
33
|
-
position: absolute;
|
|
34
|
-
inset: 0;
|
|
35
|
-
width: 1920px;
|
|
36
|
-
height: 1080px;
|
|
37
|
-
}
|
|
38
|
-
.card-stage {
|
|
39
|
-
position: absolute;
|
|
40
|
-
inset: 0;
|
|
41
|
-
display: flex;
|
|
42
|
-
align-items: center;
|
|
43
|
-
justify-content: center;
|
|
44
|
-
perspective: 2400px;
|
|
45
|
-
}
|
|
46
|
-
.card {
|
|
47
|
-
position: relative;
|
|
48
|
-
width: 1000px;
|
|
49
|
-
height: 580px;
|
|
50
|
-
transform-style: preserve-3d;
|
|
51
|
-
will-change: transform;
|
|
52
|
-
}
|
|
53
|
-
.face {
|
|
54
|
-
position: absolute;
|
|
55
|
-
inset: 0;
|
|
56
|
-
backface-visibility: hidden;
|
|
57
|
-
display: flex;
|
|
58
|
-
align-items: center;
|
|
59
|
-
justify-content: center;
|
|
60
|
-
font-weight: 900;
|
|
61
|
-
font-size: 200px;
|
|
62
|
-
letter-spacing: -0.04em;
|
|
63
|
-
border-radius: 24px;
|
|
64
|
-
box-shadow:
|
|
65
|
-
0 40px 80px rgba(0, 0, 0, 0.5),
|
|
66
|
-
0 0 0 1px rgba(255, 255, 255, 0.08) inset;
|
|
67
|
-
}
|
|
68
|
-
.face.front {
|
|
69
|
-
background: linear-gradient(135deg, #1e1b3a 0%, #0a0a0f 100%);
|
|
70
|
-
color: var(--hg-fg);
|
|
71
|
-
}
|
|
72
|
-
.face.back {
|
|
73
|
-
background: linear-gradient(135deg, #7c3aed 0%, #a855f7 60%, #d946ef 100%);
|
|
74
|
-
color: var(--hg-fg);
|
|
75
|
-
transform: rotateY(180deg);
|
|
76
|
-
}
|
|
77
|
-
.face .meta {
|
|
78
|
-
position: absolute;
|
|
79
|
-
top: 36px;
|
|
80
|
-
left: 40px;
|
|
81
|
-
font-family: "JetBrains Mono", monospace;
|
|
82
|
-
font-weight: 600;
|
|
83
|
-
font-size: 18px;
|
|
84
|
-
letter-spacing: 0.16em;
|
|
85
|
-
opacity: 0.6;
|
|
86
|
-
}
|
|
87
|
-
.card-shadow {
|
|
88
|
-
position: absolute;
|
|
89
|
-
left: 50%;
|
|
90
|
-
bottom: 22%;
|
|
91
|
-
width: 1000px;
|
|
92
|
-
height: 80px;
|
|
93
|
-
background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.55) 0%, transparent 70%);
|
|
94
|
-
transform: translateX(-50%);
|
|
95
|
-
filter: blur(12px);
|
|
96
|
-
will-change: opacity, transform;
|
|
97
|
-
}
|
|
98
27
|
</style>
|
|
99
28
|
</head>
|
|
100
29
|
<body>
|
|
@@ -106,49 +35,19 @@
|
|
|
106
35
|
data-width="1920"
|
|
107
36
|
data-height="1080"
|
|
108
37
|
>
|
|
109
|
-
<div
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<div class="meta">v5 · LAUNCH</div>
|
|
119
|
-
v5.0
|
|
120
|
-
</div>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
38
|
+
<div
|
|
39
|
+
id="scene"
|
|
40
|
+
class="clip"
|
|
41
|
+
data-composition-id="3d-card-flip"
|
|
42
|
+
data-composition-src="scene.html"
|
|
43
|
+
data-start="0"
|
|
44
|
+
data-duration="2"
|
|
45
|
+
data-track-index="1"
|
|
46
|
+
></div>
|
|
124
47
|
</div>
|
|
125
48
|
<script>
|
|
126
49
|
window.__timelines = window.__timelines || {};
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
tl.fromTo(
|
|
130
|
-
"#card",
|
|
131
|
-
{ rotateY: 0, scale: 0.92, opacity: 0 },
|
|
132
|
-
{ rotateY: 0, scale: 1, opacity: 1, duration: 0.45, ease: "power3.out" },
|
|
133
|
-
0.15,
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
// Hold then flip
|
|
137
|
-
tl.to("#card", { rotateY: 180, duration: 1.0, ease: "power3.inOut" }, 0.7);
|
|
138
|
-
|
|
139
|
-
// Shadow squishes mid-flip
|
|
140
|
-
tl.to(
|
|
141
|
-
".card-shadow",
|
|
142
|
-
{ scaleX: 0.6, opacity: 0.4, duration: 0.5, ease: "power2.inOut" },
|
|
143
|
-
0.7,
|
|
144
|
-
);
|
|
145
|
-
tl.to(".card-shadow", { scaleX: 1, opacity: 0.7, duration: 0.5, ease: "power2.inOut" }, 1.2);
|
|
146
|
-
|
|
147
|
-
// Tiny landing settle
|
|
148
|
-
tl.to("#card", { scale: 1.02, duration: 0.12, ease: "power2.out" }, 1.68);
|
|
149
|
-
tl.to("#card", { scale: 1, duration: 0.3, ease: "elastic.out(1, 0.5)" }, 1.8);
|
|
150
|
-
|
|
151
|
-
window.__timelines["main"] = tl;
|
|
50
|
+
window.__timelines["main"] = gsap.timeline({ paused: true });
|
|
152
51
|
</script>
|
|
153
52
|
</body>
|
|
154
53
|
</html>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<template id="3d-card-flip-template">
|
|
2
|
+
<div data-composition-id="3d-card-flip" data-width="1920" data-height="1080" data-duration="2">
|
|
3
|
+
<style>
|
|
4
|
+
:root {
|
|
5
|
+
--hg-violet: #7c3aed;
|
|
6
|
+
--hg-violet-2: #a855f7;
|
|
7
|
+
--hg-bg: #0a0a0f;
|
|
8
|
+
--hg-fg: #f5f5fa;
|
|
9
|
+
--hg-dim: #6b6b78;
|
|
10
|
+
}
|
|
11
|
+
* {
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
}
|
|
16
|
+
.card-stage {
|
|
17
|
+
position: absolute;
|
|
18
|
+
inset: 0;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
perspective: 2400px;
|
|
23
|
+
}
|
|
24
|
+
.card {
|
|
25
|
+
position: relative;
|
|
26
|
+
width: 1000px;
|
|
27
|
+
height: 580px;
|
|
28
|
+
transform-style: preserve-3d;
|
|
29
|
+
will-change: transform;
|
|
30
|
+
}
|
|
31
|
+
.face {
|
|
32
|
+
position: absolute;
|
|
33
|
+
inset: 0;
|
|
34
|
+
backface-visibility: hidden;
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
font-weight: 900;
|
|
39
|
+
font-size: 200px;
|
|
40
|
+
letter-spacing: -0.04em;
|
|
41
|
+
border-radius: 24px;
|
|
42
|
+
box-shadow:
|
|
43
|
+
0 40px 80px rgba(0, 0, 0, 0.5),
|
|
44
|
+
0 0 0 1px rgba(255, 255, 255, 0.08) inset;
|
|
45
|
+
}
|
|
46
|
+
.face.front {
|
|
47
|
+
background: linear-gradient(135deg, #1e1b3a 0%, #0a0a0f 100%);
|
|
48
|
+
color: var(--hg-fg);
|
|
49
|
+
}
|
|
50
|
+
.face.back {
|
|
51
|
+
background: linear-gradient(135deg, #7c3aed 0%, #a855f7 60%, #d946ef 100%);
|
|
52
|
+
color: var(--hg-fg);
|
|
53
|
+
transform: rotateY(180deg);
|
|
54
|
+
}
|
|
55
|
+
.face .meta {
|
|
56
|
+
position: absolute;
|
|
57
|
+
top: 36px;
|
|
58
|
+
left: 40px;
|
|
59
|
+
font-family: "JetBrains Mono", monospace;
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
font-size: 18px;
|
|
62
|
+
letter-spacing: 0.16em;
|
|
63
|
+
opacity: 0.6;
|
|
64
|
+
}
|
|
65
|
+
.card-shadow {
|
|
66
|
+
position: absolute;
|
|
67
|
+
left: 50%;
|
|
68
|
+
bottom: 22%;
|
|
69
|
+
width: 1000px;
|
|
70
|
+
height: 80px;
|
|
71
|
+
background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.55) 0%, transparent 70%);
|
|
72
|
+
transform: translateX(-50%);
|
|
73
|
+
filter: blur(12px);
|
|
74
|
+
will-change: opacity, transform;
|
|
75
|
+
}
|
|
76
|
+
</style>
|
|
77
|
+
<div class="card-shadow"></div>
|
|
78
|
+
<div class="card-stage">
|
|
79
|
+
<div class="card" id="card">
|
|
80
|
+
<div class="face front">
|
|
81
|
+
<div class="meta">v4 · CURRENT</div>
|
|
82
|
+
PRODUCT
|
|
83
|
+
</div>
|
|
84
|
+
<div class="face back">
|
|
85
|
+
<div class="meta">v5 · LAUNCH</div>
|
|
86
|
+
v5.0
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
<script>
|
|
91
|
+
window.__timelines = window.__timelines || {};
|
|
92
|
+
const tl = gsap.timeline({ paused: true });
|
|
93
|
+
|
|
94
|
+
tl.fromTo(
|
|
95
|
+
"#card",
|
|
96
|
+
{ rotateY: 0, scale: 0.92, opacity: 0 },
|
|
97
|
+
{ rotateY: 0, scale: 1, opacity: 1, duration: 0.45, ease: "power3.out" },
|
|
98
|
+
0.15,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Hold then flip
|
|
102
|
+
tl.to("#card", { rotateY: 180, duration: 1.0, ease: "power3.inOut" }, 0.7);
|
|
103
|
+
|
|
104
|
+
// Shadow squishes mid-flip
|
|
105
|
+
tl.to(
|
|
106
|
+
".card-shadow",
|
|
107
|
+
{ scaleX: 0.6, opacity: 0.4, duration: 0.5, ease: "power2.inOut" },
|
|
108
|
+
0.7,
|
|
109
|
+
);
|
|
110
|
+
tl.to(".card-shadow", { scaleX: 1, opacity: 0.7, duration: 0.5, ease: "power2.inOut" }, 1.2);
|
|
111
|
+
|
|
112
|
+
// Tiny landing settle
|
|
113
|
+
tl.to("#card", { scale: 1.02, duration: 0.12, ease: "power2.out" }, 1.68);
|
|
114
|
+
tl.to("#card", { scale: 1, duration: 0.3, ease: "elastic.out(1, 0.5)" }, 1.8);
|
|
115
|
+
|
|
116
|
+
window.__timelines["3d-card-flip"] = tl;
|
|
117
|
+
</script>
|
|
118
|
+
</div>
|
|
119
|
+
</template>
|
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
|
-
<html
|
|
3
|
-
lang="en"
|
|
4
|
-
data-composition-variables='[
|
|
5
|
-
{"id":"bgColor", "type":"color", "label":"Page background", "default":"#050507"},
|
|
6
|
-
{"id":"colorLow", "type":"color", "label":"Flow — shadow tone", "default":"#0a1430"},
|
|
7
|
-
{"id":"colorMid", "type":"color", "label":"Flow — mid tone", "default":"#6a6f9e"},
|
|
8
|
-
{"id":"colorHigh", "type":"color", "label":"Flow — highlight tone", "default":"#e8f0ff"},
|
|
9
|
-
{"id":"accentColor","type":"color", "label":"Core / glow accent", "default":"#aee4ff"},
|
|
10
|
-
{"id":"flowSpeed", "type":"number", "label":"Flow speed", "default":1, "min":0.1, "max":3, "step":0.1}
|
|
11
|
-
]'
|
|
12
|
-
>
|
|
2
|
+
<html lang="en">
|
|
13
3
|
<head>
|
|
14
4
|
<meta charset="UTF-8" />
|
|
15
5
|
<meta name="viewport" content="width=1920, height=1080" />
|
|
@@ -23,11 +13,6 @@
|
|
|
23
13
|
--hg-fg: #f5f5fa;
|
|
24
14
|
--hg-dim: #6b6b78;
|
|
25
15
|
}
|
|
26
|
-
* {
|
|
27
|
-
margin: 0;
|
|
28
|
-
padding: 0;
|
|
29
|
-
box-sizing: border-box;
|
|
30
|
-
}
|
|
31
16
|
html,
|
|
32
17
|
body {
|
|
33
18
|
margin: 0;
|
|
@@ -39,31 +24,6 @@
|
|
|
39
24
|
color: var(--hg-fg);
|
|
40
25
|
-webkit-font-smoothing: antialiased;
|
|
41
26
|
}
|
|
42
|
-
#scene {
|
|
43
|
-
position: absolute;
|
|
44
|
-
inset: 0;
|
|
45
|
-
width: 1920px;
|
|
46
|
-
height: 1080px;
|
|
47
|
-
}
|
|
48
|
-
.field {
|
|
49
|
-
position: absolute;
|
|
50
|
-
inset: 0;
|
|
51
|
-
width: 1920px;
|
|
52
|
-
height: 1080px;
|
|
53
|
-
display: block;
|
|
54
|
-
}
|
|
55
|
-
.label {
|
|
56
|
-
position: absolute;
|
|
57
|
-
left: 48px;
|
|
58
|
-
bottom: 40px;
|
|
59
|
-
font-size: 22px;
|
|
60
|
-
font-weight: 600;
|
|
61
|
-
letter-spacing: 0.18em;
|
|
62
|
-
text-transform: uppercase;
|
|
63
|
-
color: rgba(255, 255, 255, 0.7);
|
|
64
|
-
mix-blend-mode: screen;
|
|
65
|
-
pointer-events: none;
|
|
66
|
-
}
|
|
67
27
|
</style>
|
|
68
28
|
</head>
|
|
69
29
|
<body>
|
|
@@ -75,252 +35,19 @@
|
|
|
75
35
|
data-width="1920"
|
|
76
36
|
data-height="1080"
|
|
77
37
|
>
|
|
78
|
-
<div
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
38
|
+
<div
|
|
39
|
+
id="scene"
|
|
40
|
+
class="clip"
|
|
41
|
+
data-composition-id="bg-flow-field"
|
|
42
|
+
data-composition-src="scene.html"
|
|
43
|
+
data-start="0"
|
|
44
|
+
data-duration="4"
|
|
45
|
+
data-track-index="1"
|
|
46
|
+
></div>
|
|
82
47
|
</div>
|
|
83
48
|
<script>
|
|
84
49
|
window.__timelines = window.__timelines || {};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// ── Variables (palette + speed); falls back to defaults standalone ──
|
|
88
|
-
const defaults = {
|
|
89
|
-
bgColor: "#050507",
|
|
90
|
-
colorLow: "#0a1430",
|
|
91
|
-
colorMid: "#6a6f9e",
|
|
92
|
-
colorHigh: "#e8f0ff",
|
|
93
|
-
accentColor: "#aee4ff",
|
|
94
|
-
flowSpeed: 1,
|
|
95
|
-
};
|
|
96
|
-
const vars = Object.assign(
|
|
97
|
-
{},
|
|
98
|
-
defaults,
|
|
99
|
-
window.__hyperframes && window.__hyperframes.getVariables
|
|
100
|
-
? window.__hyperframes.getVariables()
|
|
101
|
-
: {},
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
// sRGB hex -> linear-light [r,g,b] (shader works in linear, gamma-encodes at end)
|
|
105
|
-
function hexLin(hex) {
|
|
106
|
-
let h = String(hex).replace("#", "").trim();
|
|
107
|
-
if (h.length === 3) h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];
|
|
108
|
-
const r = parseInt(h.substr(0, 2), 16) / 255;
|
|
109
|
-
const g = parseInt(h.substr(2, 2), 16) / 255;
|
|
110
|
-
const b = parseInt(h.substr(4, 2), 16) / 255;
|
|
111
|
-
const lin = (c) => Math.pow(c, 2.2);
|
|
112
|
-
return [lin(r), lin(g), lin(b)];
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const canvas = document.querySelector(".field");
|
|
116
|
-
const gl = canvas.getContext("webgl", {
|
|
117
|
-
antialias: false,
|
|
118
|
-
alpha: false,
|
|
119
|
-
preserveDrawingBuffer: true,
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const VERT = [
|
|
123
|
-
"attribute vec2 position;",
|
|
124
|
-
"varying vec2 vUv;",
|
|
125
|
-
"void main(){",
|
|
126
|
-
" vUv = position * 0.5 + 0.5;",
|
|
127
|
-
" gl_Position = vec4(position, 0.0, 1.0);",
|
|
128
|
-
"}",
|
|
129
|
-
].join("\n");
|
|
130
|
-
|
|
131
|
-
// Curl-noise flow field — ported verbatim from the held-message-living-field
|
|
132
|
-
// template's "living field" background. All visible state comes from uniforms.
|
|
133
|
-
const FRAG = [
|
|
134
|
-
"precision highp float;",
|
|
135
|
-
"varying vec2 vUv;",
|
|
136
|
-
"uniform float uTime;",
|
|
137
|
-
"uniform float uPhase;",
|
|
138
|
-
"uniform float uReveal;",
|
|
139
|
-
"uniform float uChromAb;",
|
|
140
|
-
"uniform float uVignette;",
|
|
141
|
-
"uniform float uIntensity;",
|
|
142
|
-
"uniform float uSpeed;",
|
|
143
|
-
"uniform vec2 uResolution;",
|
|
144
|
-
"uniform vec3 uColLow;",
|
|
145
|
-
"uniform vec3 uColMid;",
|
|
146
|
-
"uniform vec3 uColHigh;",
|
|
147
|
-
"uniform vec3 uAccent;",
|
|
148
|
-
"float hash21(vec2 p){",
|
|
149
|
-
" p = fract(p * vec2(123.34, 456.21));",
|
|
150
|
-
" p += dot(p, p + 45.32);",
|
|
151
|
-
" return fract(p.x * p.y);",
|
|
152
|
-
"}",
|
|
153
|
-
"float noise2(vec2 p){",
|
|
154
|
-
" vec2 i = floor(p);",
|
|
155
|
-
" vec2 f = fract(p);",
|
|
156
|
-
" vec2 u = f * f * (3.0 - 2.0 * f);",
|
|
157
|
-
" float a = hash21(i);",
|
|
158
|
-
" float b = hash21(i + vec2(1.0, 0.0));",
|
|
159
|
-
" float c = hash21(i + vec2(0.0, 1.0));",
|
|
160
|
-
" float d = hash21(i + vec2(1.0, 1.0));",
|
|
161
|
-
" return mix(mix(a,b,u.x), mix(c,d,u.x), u.y);",
|
|
162
|
-
"}",
|
|
163
|
-
"float fbm(vec2 p){",
|
|
164
|
-
" float v = 0.0;",
|
|
165
|
-
" float a = 0.5;",
|
|
166
|
-
" for(int i=0;i<5;i++){",
|
|
167
|
-
" v += a * noise2(p);",
|
|
168
|
-
" p *= 2.02;",
|
|
169
|
-
" a *= 0.5;",
|
|
170
|
-
" }",
|
|
171
|
-
" return v;",
|
|
172
|
-
"}",
|
|
173
|
-
"vec2 curl(vec2 p, float t){",
|
|
174
|
-
" float e = 0.6;",
|
|
175
|
-
" float n1 = fbm(p + vec2(0.0, e) + t*0.18);",
|
|
176
|
-
" float n2 = fbm(p + vec2(0.0, -e) + t*0.18);",
|
|
177
|
-
" float n3 = fbm(p + vec2( e, 0.0) + t*0.18);",
|
|
178
|
-
" float n4 = fbm(p + vec2(-e, 0.0) + t*0.18);",
|
|
179
|
-
" return vec2(n1 - n2, -(n3 - n4));",
|
|
180
|
-
"}",
|
|
181
|
-
"vec3 palette(float t){",
|
|
182
|
-
" t = clamp(t, 0.0, 1.0);",
|
|
183
|
-
" vec3 lowMid = mix(uColLow, uColMid, smoothstep(0.0, 0.5, t));",
|
|
184
|
-
" return mix(lowMid, uColHigh, smoothstep(0.5, 1.0, t));",
|
|
185
|
-
"}",
|
|
186
|
-
"vec3 sampleField(vec2 uv, float t, float energy){",
|
|
187
|
-
" vec2 p = (uv - 0.5) * vec2(uResolution.x/uResolution.y, 1.0) * 2.4;",
|
|
188
|
-
" vec2 c = curl(p * 0.9, t);",
|
|
189
|
-
" vec2 q = p + c * (0.45 + 0.55 * energy);",
|
|
190
|
-
" float flow = fbm(q * 1.6 + vec2(t * 0.11, -t * 0.07));",
|
|
191
|
-
" float bands = sin(flow * 14.0 + t * 1.1);",
|
|
192
|
-
" bands = smoothstep(0.0, 1.0, 0.5 + 0.5 * bands);",
|
|
193
|
-
" float r = length(p);",
|
|
194
|
-
" float core = smoothstep(1.5, 0.05, r) * (0.6 + 0.4 * energy);",
|
|
195
|
-
" float glow = exp(-r * 1.6) * (0.55 + 0.45 * energy);",
|
|
196
|
-
" float k = clamp(flow * 0.85 + 0.15 * bands + 0.25 * core + 0.6 * glow, 0.0, 1.4);",
|
|
197
|
-
" vec3 col = palette(k * 0.9 + 0.1 * sin(t * 0.4));",
|
|
198
|
-
" col *= 0.7 + 0.6 * energy;",
|
|
199
|
-
" col += uAccent * core * 0.55;",
|
|
200
|
-
" return col;",
|
|
201
|
-
"}",
|
|
202
|
-
"void main(){",
|
|
203
|
-
" vec2 uv = vUv;",
|
|
204
|
-
" float t = uTime * uSpeed;",
|
|
205
|
-
" float e = uIntensity;",
|
|
206
|
-
" vec2 dir = normalize(uv - 0.5 + 1e-6);",
|
|
207
|
-
" float ca = uChromAb * (0.004 + 0.012 * length(uv - 0.5));",
|
|
208
|
-
" vec3 cR = sampleField(uv + dir * ca, t, e);",
|
|
209
|
-
" vec3 cG = sampleField(uv, t, e);",
|
|
210
|
-
" vec3 cB = sampleField(uv - dir * ca, t, e);",
|
|
211
|
-
" vec3 col = vec3(cR.r, cG.g, cB.b);",
|
|
212
|
-
" float lum = dot(col, vec3(0.299, 0.587, 0.114));",
|
|
213
|
-
" col = mix(vec3(lum), col, 1.05);",
|
|
214
|
-
" float rev = uReveal;",
|
|
215
|
-
" float sweep = smoothstep(0.0, 0.6, rev) * (1.0 - smoothstep(0.6, 1.0, rev));",
|
|
216
|
-
" col += uColHigh * sweep * 0.35;",
|
|
217
|
-
" vec3 phaseTint = mix(vec3(0.85, 0.92, 1.05), vec3(1.05, 0.95, 0.85), uPhase);",
|
|
218
|
-
" col *= phaseTint;",
|
|
219
|
-
" float v = length(uv - 0.5);",
|
|
220
|
-
" col *= 1.0 - smoothstep(0.45, 0.95, v) * uVignette;",
|
|
221
|
-
" col = col / (col + 1.0);",
|
|
222
|
-
" col = pow(col, vec3(1.0/2.2));",
|
|
223
|
-
" gl_FragColor = vec4(col, 1.0);",
|
|
224
|
-
"}",
|
|
225
|
-
].join("\n");
|
|
226
|
-
|
|
227
|
-
function compile(type, src) {
|
|
228
|
-
const s = gl.createShader(type);
|
|
229
|
-
gl.shaderSource(s, src);
|
|
230
|
-
gl.compileShader(s);
|
|
231
|
-
return s;
|
|
232
|
-
}
|
|
233
|
-
const prog = gl.createProgram();
|
|
234
|
-
gl.attachShader(prog, compile(gl.VERTEX_SHADER, VERT));
|
|
235
|
-
gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, FRAG));
|
|
236
|
-
gl.linkProgram(prog);
|
|
237
|
-
gl.useProgram(prog);
|
|
238
|
-
|
|
239
|
-
// full-screen triangle
|
|
240
|
-
const buf = gl.createBuffer();
|
|
241
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
242
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
|
|
243
|
-
const posLoc = gl.getAttribLocation(prog, "position");
|
|
244
|
-
gl.enableVertexAttribArray(posLoc);
|
|
245
|
-
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
|
|
246
|
-
gl.viewport(0, 0, 1920, 1080);
|
|
247
|
-
|
|
248
|
-
const L = (n) => gl.getUniformLocation(prog, n);
|
|
249
|
-
const uLoc = {
|
|
250
|
-
uTime: L("uTime"),
|
|
251
|
-
uPhase: L("uPhase"),
|
|
252
|
-
uReveal: L("uReveal"),
|
|
253
|
-
uChromAb: L("uChromAb"),
|
|
254
|
-
uVignette: L("uVignette"),
|
|
255
|
-
uIntensity: L("uIntensity"),
|
|
256
|
-
uSpeed: L("uSpeed"),
|
|
257
|
-
uResolution: L("uResolution"),
|
|
258
|
-
uColLow: L("uColLow"),
|
|
259
|
-
uColMid: L("uColMid"),
|
|
260
|
-
uColHigh: L("uColHigh"),
|
|
261
|
-
uAccent: L("uAccent"),
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// animated uniform state (GSAP tweens these .value fields)
|
|
265
|
-
const u = {
|
|
266
|
-
uTime: { value: 0 },
|
|
267
|
-
uPhase: { value: 0.1 },
|
|
268
|
-
uReveal: { value: 0 },
|
|
269
|
-
uChromAb: { value: 0 },
|
|
270
|
-
uVignette: { value: 0 },
|
|
271
|
-
uIntensity: { value: 0.3 },
|
|
272
|
-
};
|
|
273
|
-
const speed = Number(vars.flowSpeed) || 1;
|
|
274
|
-
const cLow = hexLin(vars.colorLow);
|
|
275
|
-
const cMid = hexLin(vars.colorMid);
|
|
276
|
-
const cHigh = hexLin(vars.colorHigh);
|
|
277
|
-
const cAcc = hexLin(vars.accentColor);
|
|
278
|
-
|
|
279
|
-
function render() {
|
|
280
|
-
gl.uniform1f(uLoc.uTime, u.uTime.value);
|
|
281
|
-
gl.uniform1f(uLoc.uPhase, u.uPhase.value);
|
|
282
|
-
gl.uniform1f(uLoc.uReveal, u.uReveal.value);
|
|
283
|
-
gl.uniform1f(uLoc.uChromAb, u.uChromAb.value);
|
|
284
|
-
gl.uniform1f(uLoc.uVignette, u.uVignette.value);
|
|
285
|
-
gl.uniform1f(uLoc.uIntensity, u.uIntensity.value);
|
|
286
|
-
gl.uniform1f(uLoc.uSpeed, speed);
|
|
287
|
-
gl.uniform2f(uLoc.uResolution, 1920, 1080);
|
|
288
|
-
gl.uniform3fv(uLoc.uColLow, cLow);
|
|
289
|
-
gl.uniform3fv(uLoc.uColMid, cMid);
|
|
290
|
-
gl.uniform3fv(uLoc.uColHigh, cHigh);
|
|
291
|
-
gl.uniform3fv(uLoc.uAccent, cAcc);
|
|
292
|
-
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
293
|
-
}
|
|
294
|
-
render(); // initial frame so a seek to 0 / first paint is correct
|
|
295
|
-
|
|
296
|
-
// ── Energy-envelope drive (the "living field" breath): all repaint is via
|
|
297
|
-
// onUpdate, so the field is fully determined by the timeline position — no
|
|
298
|
-
// requestAnimationFrame, seek-safe. ──
|
|
299
|
-
tl.eventCallback("onUpdate", render);
|
|
300
|
-
|
|
301
|
-
tl.to(u.uTime, { value: 4, duration: 4, ease: "none" }, 0);
|
|
302
|
-
|
|
303
|
-
// energy: settle-in → breathe → SURGE → settle dark for the hold
|
|
304
|
-
tl.to(u.uIntensity, { value: 0.6, duration: 1.2, ease: "sine.inOut" }, 0);
|
|
305
|
-
tl.to(u.uIntensity, { value: 1.0, duration: 0.7, ease: "power2.in" }, 1.3);
|
|
306
|
-
tl.to(u.uIntensity, { value: 0.35, duration: 2.0, ease: "power2.out" }, 2.0);
|
|
307
|
-
|
|
308
|
-
// chromatic light-leak: light at entry, spikes on the surge, then settles
|
|
309
|
-
tl.fromTo(u.uChromAb, { value: 0 }, { value: 0.4, duration: 1.2, ease: "sine.in" }, 0);
|
|
310
|
-
tl.to(u.uChromAb, { value: 1.4, duration: 0.5, ease: "power3.in" }, 1.4);
|
|
311
|
-
tl.to(u.uChromAb, { value: 0.2, duration: 1.6, ease: "power2.out" }, 1.9);
|
|
312
|
-
|
|
313
|
-
// a brief highlight sweep across the surge
|
|
314
|
-
tl.fromTo(u.uReveal, { value: 0 }, { value: 1, duration: 0.7, ease: "none" }, 1.3);
|
|
315
|
-
tl.set(u.uReveal, { value: 0 }, 2.0);
|
|
316
|
-
|
|
317
|
-
// colour-temperature drift
|
|
318
|
-
tl.to(u.uPhase, { value: 0.6, duration: 2.2, ease: "sine.inOut" }, 0.6);
|
|
319
|
-
|
|
320
|
-
// black mask settles the field to near-black + central glow for the hold
|
|
321
|
-
tl.to(u.uVignette, { value: 0.85, duration: 1.6, ease: "power2.out" }, 1.9);
|
|
322
|
-
|
|
323
|
-
window.__timelines["main"] = tl;
|
|
50
|
+
window.__timelines["main"] = gsap.timeline({ paused: true });
|
|
324
51
|
</script>
|
|
325
52
|
</body>
|
|
326
53
|
</html>
|