dsh-drawai 0.3.4 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (538) hide show
  1. package/LICENSE +4154 -0
  2. package/README.md +49 -11
  3. package/lib/audio-media.js +150 -0
  4. package/lib/audio-service.js +66 -0
  5. package/lib/canvas-format.js +134 -0
  6. package/lib/client.js +5090 -184
  7. package/lib/comfyui-default-workflow.mjs +1825 -0
  8. package/lib/comfyui-workflow.mjs +426 -0
  9. package/lib/document-commands.js +12 -0
  10. package/lib/document-core.js +29 -0
  11. package/lib/drawing-runner.js +6 -4
  12. package/lib/drawing-tasks.js +26 -0
  13. package/lib/ffmpeg-manager.js +1056 -0
  14. package/lib/imagegen.mjs +596 -0
  15. package/lib/index.js +1762 -129
  16. package/lib/media.js +26 -13
  17. package/lib/mgstyle-core.js +75 -0
  18. package/lib/motion/apply.js +181 -0
  19. package/lib/motion/asset-pack-lock.js +10 -0
  20. package/lib/motion/asset-pack.js +335 -0
  21. package/lib/motion/assets.js +291 -0
  22. package/lib/motion/audio.js +103 -0
  23. package/lib/motion/audiolevel.js +63 -0
  24. package/lib/motion/audiomix.js +144 -0
  25. package/lib/motion/beats.js +338 -0
  26. package/lib/motion/builtin-assets.js +62 -0
  27. package/lib/motion/canvas-spec.js +442 -0
  28. package/lib/motion/capture.js +95 -0
  29. package/lib/motion/cards.js +80 -0
  30. package/lib/motion/collect.js +449 -0
  31. package/lib/motion/delivery.js +140 -0
  32. package/lib/motion/edge-speech.py +90 -0
  33. package/lib/motion/entry.jsx +73 -0
  34. package/lib/motion/export.js +200 -0
  35. package/lib/motion/ffmpeg.js +43 -0
  36. package/lib/motion/fonts.js +71 -0
  37. package/lib/motion/jobs.js +117 -0
  38. package/lib/motion/json.js +4 -0
  39. package/lib/motion/media-catalog.js +59 -0
  40. package/lib/motion/mgstyles/BRIEF-TEMPLATE.md +63 -0
  41. package/lib/motion/mgstyles/briefs/01-flat-vector.md +104 -0
  42. package/lib/motion/mgstyles/briefs/02-line-art.md +97 -0
  43. package/lib/motion/mgstyles/briefs/03-isometric.md +108 -0
  44. package/lib/motion/mgstyles/briefs/05-cel-boil.md +145 -0
  45. package/lib/motion/mgstyles/briefs/06-collage.md +149 -0
  46. package/lib/motion/mgstyles/briefs/07-liquid.md +106 -0
  47. package/lib/motion/mgstyles/briefs/08-morph.md +111 -0
  48. package/lib/motion/mgstyles/briefs/09-bauhaus.md +150 -0
  49. package/lib/motion/mgstyles/briefs/10-synthwave.md +151 -0
  50. package/lib/motion/mgstyles/briefs/12-aurora-glass.md +147 -0
  51. package/lib/motion/mgstyles/briefs/18-hanazi.md +140 -0
  52. package/lib/motion/mgstyles/briefs/19-paperclip.md +156 -0
  53. package/lib/motion/mgstyles/briefs/20-pixel.md +118 -0
  54. package/lib/motion/mgstyles/briefs/22-hud.md +118 -0
  55. package/lib/motion/mgstyles/catalog.d/01-flat-vector.json +34 -0
  56. package/lib/motion/mgstyles/catalog.d/02-line-art.json +34 -0
  57. package/lib/motion/mgstyles/catalog.d/03-isometric.json +35 -0
  58. package/lib/motion/mgstyles/catalog.d/05-cel-boil.json +28 -0
  59. package/lib/motion/mgstyles/catalog.d/06-collage.json +28 -0
  60. package/lib/motion/mgstyles/catalog.d/07-liquid.json +28 -0
  61. package/lib/motion/mgstyles/catalog.d/08-morph.json +28 -0
  62. package/lib/motion/mgstyles/catalog.d/09-bauhaus.json +28 -0
  63. package/lib/motion/mgstyles/catalog.d/10-synthwave.json +28 -0
  64. package/lib/motion/mgstyles/catalog.d/12-aurora-glass.json +28 -0
  65. package/lib/motion/mgstyles/catalog.d/18-hanazi.json +28 -0
  66. package/lib/motion/mgstyles/catalog.d/19-paperclip.json +28 -0
  67. package/lib/motion/mgstyles/catalog.d/20-pixel.json +28 -0
  68. package/lib/motion/mgstyles/catalog.d/22-hud.json +28 -0
  69. package/lib/motion/mgstyles/catalog.json +1356 -0
  70. package/lib/motion/mgstyles/upstream/README.md +147 -0
  71. package/lib/motion/mgstyles/upstream/README.zh-CN.md +147 -0
  72. package/lib/motion/mgstyles/upstream/demos/01-flat-vector/cues.json +1 -0
  73. package/lib/motion/mgstyles/upstream/demos/01-flat-vector/index.html +712 -0
  74. package/lib/motion/mgstyles/upstream/demos/02-line-art/cues.json +331 -0
  75. package/lib/motion/mgstyles/upstream/demos/02-line-art/film.js +676 -0
  76. package/lib/motion/mgstyles/upstream/demos/02-line-art/index.html +18 -0
  77. package/lib/motion/mgstyles/upstream/demos/02-line-art/tools/dump_timing.mjs +26 -0
  78. package/lib/motion/mgstyles/upstream/demos/03-isometric/cues.json +109 -0
  79. package/lib/motion/mgstyles/upstream/demos/03-isometric/index.html +25 -0
  80. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/anim.js +82 -0
  81. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/main.js +219 -0
  82. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/night5.js +180 -0
  83. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/render.js +202 -0
  84. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/title.js +167 -0
  85. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/title5.js +294 -0
  86. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/ui.js +141 -0
  87. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/world.js +1399 -0
  88. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/cues.json +157 -0
  89. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/index.html +34 -0
  90. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/js/engine.js +326 -0
  91. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/js/scene.js +2036 -0
  92. package/lib/motion/mgstyles/upstream/demos/06-collage/assets/gen/layout.json +157 -0
  93. package/lib/motion/mgstyles/upstream/demos/06-collage/cues.json +80 -0
  94. package/lib/motion/mgstyles/upstream/demos/06-collage/index.html +889 -0
  95. package/lib/motion/mgstyles/upstream/demos/07-liquid/cues.json +100 -0
  96. package/lib/motion/mgstyles/upstream/demos/07-liquid/index.html +108 -0
  97. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/engine.js +153 -0
  98. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/links.js +64 -0
  99. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/lookdev.js +46 -0
  100. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/scene.js +963 -0
  101. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/shaders.js +647 -0
  102. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/textsdf.js +114 -0
  103. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/type.js +50 -0
  104. package/lib/motion/mgstyles/upstream/demos/08-morph/cues.json +131 -0
  105. package/lib/motion/mgstyles/upstream/demos/08-morph/glyphs.json +1 -0
  106. package/lib/motion/mgstyles/upstream/demos/08-morph/index.html +901 -0
  107. package/lib/motion/mgstyles/upstream/demos/09-bauhaus/cues.json +270 -0
  108. package/lib/motion/mgstyles/upstream/demos/09-bauhaus/film.js +697 -0
  109. package/lib/motion/mgstyles/upstream/demos/09-bauhaus/index.html +12 -0
  110. package/lib/motion/mgstyles/upstream/demos/10-synthwave/cues.json +44 -0
  111. package/lib/motion/mgstyles/upstream/demos/10-synthwave/index.html +1028 -0
  112. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/cues.json +67 -0
  113. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/index.html +16 -0
  114. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/main.js +967 -0
  115. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/shaders.js +468 -0
  116. package/lib/motion/mgstyles/upstream/demos/18-hanazi/cues.json +117 -0
  117. package/lib/motion/mgstyles/upstream/demos/18-hanazi/index.html +541 -0
  118. package/lib/motion/mgstyles/upstream/demos/19-paperclip/assets/countries-110m.json +1 -0
  119. package/lib/motion/mgstyles/upstream/demos/19-paperclip/assets/stickers/meta.json +34 -0
  120. package/lib/motion/mgstyles/upstream/demos/19-paperclip/cues.json +285 -0
  121. package/lib/motion/mgstyles/upstream/demos/19-paperclip/index.html +599 -0
  122. package/lib/motion/mgstyles/upstream/demos/20-pixel/cues.json +42 -0
  123. package/lib/motion/mgstyles/upstream/demos/20-pixel/film.js +914 -0
  124. package/lib/motion/mgstyles/upstream/demos/20-pixel/index.html +18 -0
  125. package/lib/motion/mgstyles/upstream/demos/22-hud/cues.json +108 -0
  126. package/lib/motion/mgstyles/upstream/demos/22-hud/index.html +125 -0
  127. package/lib/motion/mgstyles/upstream/demos/22-hud/js/holo.js +275 -0
  128. package/lib/motion/mgstyles/upstream/demos/22-hud/js/hud.js +855 -0
  129. package/lib/motion/mgstyles/upstream/demos/22-hud/js/post.js +150 -0
  130. package/lib/motion/mgstyles/upstream/demos/22-hud/js/util.js +65 -0
  131. package/lib/motion/mgstyles/upstream/demos/22-hud/js/v5.js +142 -0
  132. package/lib/motion/mgstyles/upstream/harness/render.mjs +319 -0
  133. package/lib/motion/mgstyles/upstream/manifest.json +269 -0
  134. package/lib/motion/mgstyles/upstream/prompts/01-flat-vector.md +98 -0
  135. package/lib/motion/mgstyles/upstream/prompts/02-line-art.md +95 -0
  136. package/lib/motion/mgstyles/upstream/prompts/03-isometric.md +97 -0
  137. package/lib/motion/mgstyles/upstream/prompts/05-cel-boil.md +95 -0
  138. package/lib/motion/mgstyles/upstream/prompts/06-collage.md +95 -0
  139. package/lib/motion/mgstyles/upstream/prompts/07-liquid.md +98 -0
  140. package/lib/motion/mgstyles/upstream/prompts/08-morph.md +95 -0
  141. package/lib/motion/mgstyles/upstream/prompts/09-bauhaus.md +96 -0
  142. package/lib/motion/mgstyles/upstream/prompts/10-synthwave.md +95 -0
  143. package/lib/motion/mgstyles/upstream/prompts/12-aurora-glass.md +96 -0
  144. package/lib/motion/mgstyles/upstream/prompts/18-hanazi.md +95 -0
  145. package/lib/motion/mgstyles/upstream/prompts/19-paperclip.md +96 -0
  146. package/lib/motion/mgstyles/upstream/prompts/20-pixel.md +96 -0
  147. package/lib/motion/mgstyles/upstream/prompts/22-hud.md +95 -0
  148. package/lib/motion/mgstyles/upstream/rubric.md +51 -0
  149. package/lib/motion/mgstyles/upstream/template.md +36 -0
  150. package/lib/motion/pixelqa.js +198 -0
  151. package/lib/motion/preview.js +97 -0
  152. package/lib/motion/project.js +395 -0
  153. package/lib/motion/qa.js +290 -0
  154. package/lib/motion/reference-media.jsx +10 -0
  155. package/lib/motion/render-settings.js +112 -0
  156. package/lib/motion/render.js +161 -0
  157. package/lib/motion/runtime/package-lock.json +3058 -0
  158. package/lib/motion/runtime/package.json +16 -0
  159. package/lib/motion/scene-kit.js +183 -0
  160. package/lib/motion/sfx.js +232 -0
  161. package/lib/motion/shotcraft/ClipCard.tsx +204 -0
  162. package/lib/motion/shotcraft/catalog.json +2461 -0
  163. package/lib/motion/shotcraft/upstream/SKILL.md +286 -0
  164. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -0
  165. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -0
  166. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -0
  167. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -0
  168. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -0
  169. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -0
  170. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -0
  171. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -0
  172. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -0
  173. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -0
  174. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -0
  175. package/lib/motion/shotcraft/upstream/assets/scripts/__pycache__/sfx-source.cpython-313.pyc +0 -0
  176. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -0
  177. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -0
  178. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -0
  179. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -0
  180. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -0
  181. package/lib/motion/shotcraft/upstream/demos/README.md +120 -0
  182. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -0
  183. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -0
  184. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -0
  185. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -0
  186. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -0
  187. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -0
  188. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +389 -0
  189. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -0
  190. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -0
  191. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -0
  192. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -0
  193. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -0
  194. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -0
  195. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -0
  196. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -0
  197. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -0
  198. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -0
  199. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -0
  200. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -0
  201. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -0
  202. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -0
  203. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -0
  204. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -0
  205. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -0
  206. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -0
  207. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -0
  208. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -0
  209. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -0
  210. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -0
  211. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -0
  212. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -0
  213. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -0
  214. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -0
  215. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -0
  216. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -0
  217. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -0
  218. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -0
  219. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -0
  220. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -0
  221. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -0
  222. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -0
  223. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -0
  224. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -0
  225. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -0
  226. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -0
  227. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -0
  228. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -0
  229. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -0
  230. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -0
  231. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -0
  232. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -0
  233. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -0
  234. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -0
  235. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -0
  236. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -0
  237. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -0
  238. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -0
  239. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -0
  240. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -0
  241. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -0
  242. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -0
  243. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -0
  244. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -0
  245. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -0
  246. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -0
  247. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -0
  248. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -0
  249. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -0
  250. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -0
  251. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -0
  252. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -0
  253. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -0
  254. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -0
  255. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -0
  256. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -0
  257. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -0
  258. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -0
  259. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -0
  260. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -0
  261. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -0
  262. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -0
  263. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -0
  264. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -0
  265. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -0
  266. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -0
  267. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -0
  268. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -0
  269. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -0
  270. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -0
  271. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -0
  272. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -0
  273. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -0
  274. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -0
  275. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -0
  276. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -0
  277. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -0
  278. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -0
  279. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -0
  280. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -0
  281. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -0
  282. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -0
  283. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -0
  284. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -0
  285. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -0
  286. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -0
  287. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -0
  288. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -0
  289. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -0
  290. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -0
  291. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -0
  292. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -0
  293. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -0
  294. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -0
  295. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -0
  296. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -0
  297. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -0
  298. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -0
  299. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -0
  300. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -0
  301. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -0
  302. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -0
  303. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -0
  304. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -0
  305. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -0
  306. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -0
  307. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -0
  308. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -0
  309. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -0
  310. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -0
  311. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -0
  312. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -0
  313. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -0
  314. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -0
  315. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -0
  316. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -0
  317. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -0
  318. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -0
  319. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -0
  320. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -0
  321. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -0
  322. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -0
  323. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -0
  324. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -0
  325. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -0
  326. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -0
  327. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -0
  328. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -0
  329. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -0
  330. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -0
  331. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -0
  332. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -0
  333. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -0
  334. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -0
  335. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -0
  336. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -0
  337. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -0
  338. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -0
  339. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -0
  340. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -0
  341. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -0
  342. package/lib/motion/shotcraft/upstream/manifest.json +2715 -0
  343. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -0
  344. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -0
  345. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -0
  346. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -0
  347. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -0
  348. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -0
  349. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -0
  350. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -0
  351. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -0
  352. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -0
  353. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -0
  354. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -0
  355. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -0
  356. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -0
  357. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -0
  358. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -0
  359. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -0
  360. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -0
  361. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -0
  362. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -0
  363. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -0
  364. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -0
  365. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -0
  366. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -0
  367. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -0
  368. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -0
  369. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -0
  370. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -0
  371. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -0
  372. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -0
  373. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -0
  374. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -0
  375. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -0
  376. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -0
  377. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -0
  378. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -0
  379. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -0
  380. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -0
  381. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -0
  382. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -0
  383. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -0
  384. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -0
  385. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -0
  386. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -0
  387. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -0
  388. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -0
  389. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -0
  390. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -0
  391. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -0
  392. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -0
  393. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -0
  394. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -0
  395. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -0
  396. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -0
  397. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -0
  398. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -0
  399. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -0
  400. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -0
  401. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -0
  402. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -0
  403. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -0
  404. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -0
  405. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -0
  406. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -0
  407. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -0
  408. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -0
  409. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -0
  410. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -0
  411. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -0
  412. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -0
  413. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -0
  414. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -0
  415. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -0
  416. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -0
  417. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -0
  418. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -0
  419. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -0
  420. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -0
  421. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -0
  422. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -0
  423. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -0
  424. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -0
  425. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -0
  426. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -0
  427. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -0
  428. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -0
  429. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -0
  430. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -0
  431. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -0
  432. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -0
  433. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -0
  434. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -0
  435. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -0
  436. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -0
  437. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -0
  438. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -0
  439. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -0
  440. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -0
  441. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -0
  442. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -0
  443. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -0
  444. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -0
  445. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -0
  446. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -0
  447. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -0
  448. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -0
  449. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -0
  450. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -0
  451. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -0
  452. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -0
  453. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -0
  454. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -0
  455. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -0
  456. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -0
  457. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -0
  458. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -0
  459. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -0
  460. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -0
  461. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -0
  462. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -0
  463. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -0
  464. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -0
  465. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -0
  466. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -0
  467. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -0
  468. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -0
  469. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -0
  470. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -0
  471. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -0
  472. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -0
  473. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -0
  474. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -0
  475. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -0
  476. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -0
  477. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -0
  478. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -0
  479. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -0
  480. package/lib/motion/shotcraft/upstream/template/package.json +20 -0
  481. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -0
  482. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -0
  483. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -0
  484. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -0
  485. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -0
  486. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -0
  487. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -0
  488. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -0
  489. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -0
  490. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -0
  491. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -0
  492. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -0
  493. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -0
  494. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -0
  495. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +389 -0
  496. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -0
  497. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -0
  498. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -0
  499. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -0
  500. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -0
  501. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -0
  502. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -0
  503. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -0
  504. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -0
  505. package/lib/motion/spec.js +113 -0
  506. package/lib/motion/style-engine.js +153 -0
  507. package/lib/motion/style-frames.js +271 -0
  508. package/lib/motion/sync.js +214 -0
  509. package/lib/motion/theme.js +121 -0
  510. package/lib/motion/video-runtime.js +192 -0
  511. package/lib/motion/voice.js +417 -0
  512. package/lib/motion-agent-files.js +82 -0
  513. package/lib/motion-agent-protocol.js +66 -0
  514. package/lib/motion-agent-tools.js +196 -0
  515. package/lib/motion-agent.js +171 -0
  516. package/lib/motion-capture.js +93 -0
  517. package/lib/motion-core.js +238 -0
  518. package/lib/motion-film-review.js +71 -0
  519. package/lib/motion-library.js +210 -0
  520. package/lib/motion-planner.js +254 -0
  521. package/lib/motion-project.js +87 -0
  522. package/lib/motion-render-worker.js +153 -0
  523. package/lib/motion-session.js +32 -0
  524. package/lib/motion-source.js +49 -0
  525. package/lib/motion-tasks.js +452 -0
  526. package/lib/motion-vision.js +44 -0
  527. package/lib/mxfile.js +27 -7
  528. package/lib/routing/node-runtime.js +14 -0
  529. package/lib/routing/router.js +211 -0
  530. package/lib/routing/vendor/README.md +96 -0
  531. package/lib/routing/vendor/libavoid-routing.js +753 -0
  532. package/lib/routing/vendor/libavoid.min.js +59 -0
  533. package/lib/shotcard-core.js +39 -0
  534. package/lib/shotcard-reference.js +56 -0
  535. package/lib/style-kernel.js +37 -3
  536. package/lib/task-patches.js +26 -2
  537. package/lib/video-export.js +49 -22
  538. package/package.json +34 -4
@@ -0,0 +1,541 @@
1
+ <!doctype html>
2
+ <html><head><meta charset="utf-8">
3
+ <link rel="stylesheet" href="/assets/fonts/fonts.css">
4
+ <style>
5
+ html,body{margin:0;background:#000;overflow:hidden}
6
+ #stage{position:relative;width:1080px;height:1920px;overflow:hidden;background:#1b1b22}
7
+ .shot{position:absolute;left:0;top:0;width:1080px;height:1920px;overflow:hidden;transform-origin:540px 960px}
8
+ .shot img{position:absolute;left:0;top:0;transform-origin:0 0;max-width:none}
9
+ .ear{visibility:hidden}
10
+ #cardwrap{position:absolute;left:0;top:0;width:1080px;height:1920px;transform-origin:0 0}
11
+ #cardborder{position:absolute;background:#fff;border-radius:36px}
12
+ #vig{position:absolute;left:0;top:0;width:1080px;height:1920px;pointer-events:none;
13
+ background:radial-gradient(ellipse 80% 62% at 50% 46%, rgba(0,0,0,0) 58%, rgba(28,8,30,.42) 100%)}
14
+ #flash{position:absolute;left:0;top:0;width:1080px;height:1920px;background:#fff;opacity:0}
15
+ #grain{position:absolute;left:0;top:0;width:1080px;height:1920px;background:url(/assets/textures/grain/grain_fine_2048.png);
16
+ mix-blend-mode:overlay;opacity:.09;pointer-events:none}
17
+ svg{position:absolute;left:0;top:0;overflow:visible}
18
+ #sun{position:absolute;left:0;top:0;width:1080px;height:1920px;mix-blend-mode:screen;background:radial-gradient(circle at 92% 6%, rgba(255,236,170,.85) 0, rgba(255,196,110,.35) 22%, rgba(255,170,90,0) 55%)}
19
+ #cutw{position:absolute;left:0;top:0;width:1080px;height:1920px;transform-origin:540px 1420px}
20
+ </style></head>
21
+ <body>
22
+ <div id="stage">
23
+ <svg id="bg" width="1080" height="1920" viewBox="0 0 1080 1920"></svg>
24
+ <div id="s1" class="shot"><img id="i1" src="/demos/18-hanazi/assets/white_dof.jpg"><img id="e6" class="ear" src="/demos/18-hanazi/assets/white_ear6.png"><img id="e11" class="ear" src="/demos/18-hanazi/assets/white_ear11.png"><img id="e16" class="ear" src="/demos/18-hanazi/assets/white_ear16.png"><div id="sun"></div></div>
25
+ <div id="s2" class="shot"><img id="i2" src="/demos/18-hanazi/assets/grey_r2.jpg"></div>
26
+ <div id="cardwrap">
27
+ <div id="cardborder"></div>
28
+ <div id="s3" class="shot">
29
+ <img id="i3" src="/demos/18-hanazi/assets/tux_r1.jpg"><canvas id="zb" width="1080" height="1920" style="position:absolute;left:0;top:0;filter:saturate(1.2) contrast(1.06)"></canvas>
30
+ <svg id="rays" width="1080" height="1920" viewBox="0 0 1080 1920"></svg>
31
+ <div id="cutw"><img id="hL06" src="/demos/18-hanazi/assets/hero_L06.png"><img id="hL12" src="/demos/18-hanazi/assets/hero_L12.png"><img id="hB0" src="/demos/18-hanazi/assets/hero_B0.png"><img id="hB1" src="/demos/18-hanazi/assets/hero_B1.png"><img id="hB2" src="/demos/18-hanazi/assets/hero_B2.png"><img id="hL135" src="/demos/18-hanazi/assets/hero_L135.png"></div>
32
+ </div>
33
+ </div>
34
+ <div id="vig"></div>
35
+ <svg id="fx" width="1080" height="1920" viewBox="0 0 1080 1920"></svg>
36
+ <div id="flash"></div>
37
+ <div id="grain"></div>
38
+ </div>
39
+ <script>
40
+ window.DEMO = { width: 1080, height: 1920, fps: 30, duration: 10, motionBlur: { samples: 1, shutter: 0.5 } };
41
+ const NS = 'http://www.w3.org/2000/svg', FR = 1 / 30;
42
+ const $ = id => document.getElementById(id);
43
+ const clamp = (x, a = 0, b = 1) => x < a ? a : x > b ? b : x;
44
+ const lerp = (a, b, u) => a + (b - a) * u;
45
+ const E = {
46
+ outCubic: u => 1 - Math.pow(1 - u, 3), inCubic: u => u * u * u, outQuart: u => 1 - Math.pow(1 - u, 4),
47
+ inOutCubic: u => u < .5 ? 4 * u * u * u : 1 - Math.pow(-2 * u + 2, 3) / 2, inOutSine: u => -(Math.cos(Math.PI * u) - 1) / 2,
48
+ inSine: u => 1 - Math.cos(u * Math.PI / 2), outExpo: u => u >= 1 ? 1 : 1 - Math.pow(2, -10 * u), outBack: u => 1 + 2.70158 * Math.pow(u - 1, 3) + 1.70158 * Math.pow(u - 1, 2), inQuad: u => u * u, outQuad: u => 1 - (1 - u) * (1 - u),
49
+ };
50
+ // damped spring step: zeta .517 / omega 22 -> peak 1.15 at frame 5, ~1.01 at frame 8
51
+ function spring(t, z = 0.517, w = 22) {
52
+ if (t <= 0) return 0; const wd = w * Math.sqrt(1 - z * z);
53
+ return 1 - Math.exp(-z * w * t) * (Math.cos(wd * t) + z * w / wd * Math.sin(wd * t));
54
+ }
55
+ function h1(i) { let x = Math.imul((i | 0) ^ 0x9e3779b9, 0x85ebca6b); x ^= x >>> 13; x = Math.imul(x, 0xc2b2ae35); x ^= x >>> 16; return (x >>> 0) / 4294967296; }
56
+ function rnd(seed) { let s = seed >>> 0; return () => { s = (s + 0x6D2B79F5) >>> 0; let t = s; t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; }
57
+ function vn(x, seed) { const i = Math.floor(x), f = x - i, u = f * f * (3 - 2 * f); return lerp(h1(i * 7919 + seed * 104729), h1((i + 1) * 7919 + seed * 104729), u) * 2 - 1; }
58
+ function hand(t, seed, a = 1) { return { x: a * (7 * vn(t * .9, seed) + 2.5 * vn(t * 2.3, seed + 11)), y: a * (6 * vn(t * .8, seed + 23) + 2 * vn(t * 2.6, seed + 37)), r: a * .32 * vn(t * .7, seed + 51) }; }
59
+ function kick(t, t0, A, k = 8, f = 12) {
60
+ const u = t - t0; if (u < 0 || u > 1.5) return { x: 0, y: 0, r: 0 }; const e = A * Math.exp(-k * u);
61
+ return { x: e * Math.sin(2 * Math.PI * f * u), y: e * .8 * Math.cos(2 * Math.PI * f * .83 * u + .7), r: e * .03 * Math.sin(2 * Math.PI * f * .6 * u) };
62
+ }
63
+ const addK = (...ks) => ks.reduce((a, k) => ({ x: a.x + k.x, y: a.y + k.y, r: a.r + k.r }), { x: 0, y: 0, r: 0 });
64
+ function el(tag, attrs = {}, parent) { const e = document.createElementNS(NS, tag); for (const k in attrs) e.setAttribute(k, attrs[k]); if (parent) parent.appendChild(e); return e; }
65
+ let gid = 0, DEFS;
66
+ function grad(stops, vertical = true) {
67
+ const id = 'g' + (gid++); const g = el('linearGradient', vertical ? { id, x1: 0, y1: 0, x2: 0, y2: 1 } : { id, x1: 0, y1: 0, x2: 1, y2: 0 }, DEFS);
68
+ stops.forEach(([o, c, a]) => el('stop', { offset: o, 'stop-color': c, 'stop-opacity': a ?? 1 }, g)); return `url(#${id})`;
69
+ }
70
+ const show = (e, v) => e.setAttribute('visibility', v ? 'visible' : 'hidden');
71
+ const disp = (e, v) => { e.style.display = v ? '' : 'none'; }; // hard-hides a whole group (children can't override)
72
+ const X = (e, x, y, r = 0, s = 1, sy) => e.setAttribute('transform', `translate(${x.toFixed(2)} ${y.toFixed(2)}) rotate(${r.toFixed(3)}) scale(${s.toFixed(4)} ${(sy ?? s).toFixed(4)})`);
73
+
74
+ /* ---------- 花字 component: extrude x2 -> outer colour stroke -> white stroke -> gradient fill -> gloss ---------- */
75
+ function HZ(parent, sp) {
76
+ const root = el('g', {}, parent);
77
+ if (sp.soft !== false) root.setAttribute('filter', sp.filter || 'url(#soft)');
78
+ const fillPaint = sp.fillStops ? grad(sp.fillStops) : sp.fill;
79
+ const gloss = sp.gloss ? grad([[0, '#fff', sp.gloss], [0.46, '#fff', 0], [1, '#fff', 0]]) : null;
80
+ const items = sp.chars.map(c => {
81
+ const g = el('g', {}, parent === root ? root : root);
82
+ const inner = el('g', sp.skew ? { transform: `skewX(${sp.skew})` } : {}, g);
83
+ const fs = c.size || sp.size, sc = fs / sp.size;
84
+ const base = { 'font-family': sp.font, 'font-size': fs, 'font-weight': sp.weight || 400, 'text-anchor': sp.anchor || 'middle', 'dominant-baseline': 'central', 'stroke-linejoin': 'round', 'stroke-linecap': 'round' };
85
+ const dy = (sp.dy || 0) * sc, W = 2 * ((sp.white || 0) + (sp.outer || 0)) * sc;
86
+ const mk = a => { const e = el('text', { ...base, ...a }, inner); e.textContent = c.ch; return e; };
87
+ if (sp.ext) { const ec = sp.extColor; mk({ y: dy + sp.ext * sc, x: (sp.extX || 0) * sc, fill: ec, stroke: ec, 'stroke-width': W }); mk({ y: dy + sp.ext * .5 * sc, x: (sp.extX || 0) * .5 * sc, fill: ec, stroke: ec, 'stroke-width': W }); }
88
+ if (sp.outer) mk({ y: dy, fill: sp.outerColor, stroke: sp.outerColor, 'stroke-width': W });
89
+ if (sp.white) mk({ y: dy, fill: sp.whiteColor || '#fff', stroke: sp.whiteColor || '#fff', 'stroke-width': 2 * sp.white * sc });
90
+ const f = mk({ y: dy, fill: c.fillStops ? grad(c.fillStops) : fillPaint });
91
+ if (gloss) mk({ y: dy, fill: gloss });
92
+ return { g, inner, x: c.x, y: c.y, rot: c.rot || 0, fillEl: f, t0: c.t0, drop: c.drop, r0: c.r0, ph: c.ph ?? (c.x * .013), bob: c.bob };
93
+ });
94
+ return { root, items };
95
+ }
96
+ // per-char pop: spring scale 0 -> 1.15 -> 1, drop-in, rotate-in, hold wiggle, optional pop-out at t1
97
+ function charXf(t, c, o = {}) {
98
+ const u = t - c.t0; if (u < 0) return null;
99
+ let s = spring(u, o.z ?? .517, o.w ?? 22);
100
+ let y = -(c.drop ?? o.drop ?? 0) * (1 - spring(u, .55, 20));
101
+ let r = (c.r0 ?? o.r0 ?? 0) * (1 - spring(u, .45, 18));
102
+ const hold = clamp((u - .22) / .35), wf = o.wf ?? 1.15;
103
+ r += hold * (o.wig ?? 1.8) * Math.sin(2 * Math.PI * wf * t + c.ph);
104
+ y += hold * (c.bob ?? o.bob ?? 3) * Math.sin(2 * Math.PI * wf * t + c.ph + 1.9);
105
+ s *= 1 + hold * (o.breath ?? .012) * Math.sin(2 * Math.PI * wf * 2 * t + c.ph * 1.7);
106
+ if (o.t1 != null && t >= o.t1) { const k = clamp((t - o.t1) / .17); if (k >= 1) return null; s *= k < .3 ? 1 + .12 * E.outQuad(k / .3) : 1.12 * (1 - E.inCubic((k - .3) / .7)); }
107
+ return { s, y, r };
108
+ }
109
+ function popOut(t, t1) { if (t < t1) return 1; const k = (t - t1) / .17; return k >= 1 ? 0 : k < .3 ? 1 + .12 * E.outQuad(k / .3) : 1.12 * (1 - E.inCubic((k - .3) / .7)); }
110
+ function driveHZ(t, hz, o = {}, off = { x: 0, y: 0 }) {
111
+ for (const c of hz.items) {
112
+ const f = charXf(t, c, o); if (!f || (o.until != null && t >= o.until) || (o.from != null && t < o.from)) { show(c.g, false); continue; }
113
+ show(c.g, true); X(c.g, c.x + off.x, c.y + f.y + off.y, c.rot + f.r, f.s);
114
+ }
115
+ }
116
+ /* ---------- decorations ---------- */
117
+ function sparkleD(r) { const k = r * .16; return `M0 ${-r}Q${k} ${-k} ${r} 0Q${k} ${k} 0 ${r}Q${-k} ${k} ${-r} 0Q${-k} ${-k} 0 ${-r}Z`; }
118
+ function burstD(cx, cy, rx, ry, n, seed, spike = .3) {
119
+ const R = rnd(seed); let d = '';
120
+ for (let i = 0; i < 2 * n; i++) {
121
+ const a = i / (2 * n) * Math.PI * 2 + (R() - .5) * .09, out = i % 2 === 0;
122
+ const k = out ? 1 + (R() - .45) * .26 : (1 - spike) + (R() - .5) * .07;
123
+ d += (i ? 'L' : 'M') + (cx + Math.cos(a) * rx * k).toFixed(1) + ' ' + (cy + Math.sin(a) * ry * k).toFixed(1);
124
+ }
125
+ return d + 'Z';
126
+ }
127
+ function focusD(cx, cy, seed, n = 120) {
128
+ const R = rnd(seed); let d = '';
129
+ for (let i = 0; i < n; i++) {
130
+ const a = i / n * Math.PI * 2 + (R() - .5) * (Math.PI * 2 / n) * .9, w = .0035 + R() * .011, ri = 470 + R() * 260, ro = 1600;
131
+ const p = (ang, rr) => (cx + Math.cos(ang) * rr).toFixed(1) + ' ' + (cy + Math.sin(ang) * rr * 1.18).toFixed(1);
132
+ d += `M${p(a, ri)}L${p(a - w, ro)}L${p(a + w, ro)}Z`;
133
+ }
134
+ return d;
135
+ }
136
+ function raysD(n, R) { let d = ''; for (let i = 0; i < n; i++) { const a0 = i / n * Math.PI * 2, a1 = a0 + Math.PI / n; d += `M0 0L${(Math.cos(a0) * R).toFixed(1)} ${(Math.sin(a0) * R).toFixed(1)}L${(Math.cos(a1) * R).toFixed(1)} ${(Math.sin(a1) * R).toFixed(1)}Z`; } return d; }
137
+ const DROP_D = 'M0 -64C9 -42 36 -12 36 14A36 36 0 0 1 -36 14C-36 -12 -9 -42 0 -64Z';
138
+ const PAW_D = 'M0 10c-20 0-34 14-34 28 0 12 12 16 34 16s34-4 34-16c0-14-14-28-34-28zM-30-4a11 14 0 1 0 .1 0zM30-4a11 14 0 1 0 .1 0zM-12-24a10 13 0 1 0 .1 0zM12-24a10 13 0 1 0 .1 0z';
139
+
140
+ /* ---------- photo plates ---------- */
141
+ const PL = {
142
+ i1: { iw: 1536, ih: 2048, fx: .775, fy: .44 },
143
+ i2: { iw: 3300, ih: 2200, fx: .565, fy: .6 },
144
+ i3: { iw: 2400, ih: 2400, fx: .585, fy: .40 },
145
+ hero: { iw: 1800, ih: 1800 },
146
+ };
147
+ function geom(P, Z, sx, sy, sh, fx = P.fx, fy = P.fy, free = false) {
148
+ const S = Math.max(1080 / P.iw, 1920 / P.ih) * 1.05 * Z, W = P.iw * S, H = P.ih * S, m = 14;
149
+ let x = sx - fx * W, y = sy - fy * H;
150
+ if (!free) { x = clamp(x, 1080 - W + m, -m); y = clamp(y, 1920 - H + m, -m); }
151
+ return { x: x + sh.x, y: y + sh.y, S };
152
+ }
153
+ function place(img, P, Z, sx, sy, sh, fx = P.fx, fy = P.fy, free = false) {
154
+ const g = geom(P, Z, sx, sy, sh, fx, fy, free);
155
+ img.style.width = P.iw + 'px'; img.style.height = P.ih + 'px';
156
+ img.style.transform = `translate(${g.x.toFixed(2)}px,${g.y.toFixed(2)}px) scale(${g.S.toFixed(5)})`;
157
+ }
158
+ const HERO = ['hL06', 'hL12', 'hB0', 'hB1', 'hB2', 'hL135'];
159
+ /* shot-3 plate (pre-drop): creep, 三连推 triple snap push onto the eyes (2-frame outExpo + 1-frame 3 % overshoot), tension creep + ramping shake */
160
+ function plate3(tt) {
161
+ let h = hand(tt, 3, 1), Z = lerp(1.0, 1.08, E.inSine(clamp((tt - C.wipe) / 1.25))), fe = 0;
162
+ C.push.forEach((p, k) => { if (tt >= p) { const u = tt - p, e = E.outExpo(clamp(u / (2 * FR)));
163
+ const last = k === C.push.length - 1, creep = last ? 1 + .16 * u : 1 + .03 * u, os = 1 + .03 * Math.exp(-Math.pow((u - 1.6 * FR) / (.9 * FR), 2));
164
+ Z = lerp(k ? C.pushZ[k - 1] : Z, C.pushZ[k], e) * creep * os; fe = lerp(k / 3, (k + 1) / 3, e); h = addK(h, kick(tt, p, 9 + 4 * k, 14, 13)); } });
165
+ const p3 = C.push[C.push.length - 1];
166
+ if (tt >= p3 + 2 * FR) { const a = lerp(2, 8, clamp((tt - p3 - 2 * FR) / (C.drop - p3 - 2 * FR))), q = Math.floor(tt * 30);
167
+ h = addK(h, { x: (h1(q * 3 + 1) - .5) * 2 * a, y: (h1(q * 3 + 2) - .5) * 2 * a, r: (h1(q * 3 + 3) - .5) * .5 * a / 8 }); }
168
+ const zi = 1 + .09 * (1 - E.outCubic(clamp((tt - C.wipe) / .5)));
169
+ return { g: geom(PL.i3, Z * zi, 540, lerp(760, 800, fe), h, lerp(PL.i3.fx, .578, fe), lerp(PL.i3.fy, .371, fe)), h };
170
+ }
171
+
172
+ let C, fx, rays, bgPat, B = {};
173
+ async function build() {
174
+ C = await (await fetch('/demos/18-hanazi/cues.json')).json();
175
+ for (const [f, w] of [['Resource Han Rounded', 900], ['Alimama ShuHeiTi', 700], ['Douyin Sans', 700], ['LXGW Marker Gothic', 400], ['ZCOOL KuaiLe', 400], ['Luckiest Guy', 400]])
176
+ await document.fonts.load(`${w} 100px "${f}"`, '今日份快乐?空气突然安静震惊!前方高能这发量合理吗绝子下期见~猫主认证喵呜日记小声正在光作用…()发量检测爆表正常MIAOWU EP.07★');
177
+ await document.fonts.ready;
178
+ const mctx = document.createElement('canvas').getContext('2d');
179
+ fx = $('fx');
180
+ DEFS = el('defs', {}, fx);
181
+ const f1 = el('filter', { id: 'soft', x: '-30%', y: '-30%', width: '160%', height: '175%' }, DEFS);
182
+ el('feDropShadow', { dx: 0, dy: 12, stdDeviation: 11, 'flood-color': '#1a0a28', 'flood-opacity': .36 }, f1);
183
+ const f1b = el('filter', { id: 'soft2', x: '-40%', y: '-30%', width: '180%', height: '175%' }, DEFS);
184
+ el('feDropShadow', { dx: 0, dy: 14, stdDeviation: 14, 'flood-color': '#0B1030', 'flood-opacity': .4 }, f1b);
185
+ const f2 = el('filter', { id: 'glow', x: '-50%', y: '-50%', width: '200%', height: '200%' }, DEFS);
186
+ el('feDropShadow', { dx: 0, dy: 0, stdDeviation: 7, 'flood-color': '#FFE14D', 'flood-opacity': .9 }, f2);
187
+ // stamp grunge: rough edge + speckle knock-outs
188
+ const f3 = el('filter', { id: 'rough', x: '-10%', y: '-10%', width: '120%', height: '120%' }, DEFS);
189
+ el('feTurbulence', { type: 'fractalNoise', baseFrequency: .045, numOctaves: 2, seed: 4, result: 'n' }, f3);
190
+ el('feDisplacementMap', { in: 'SourceGraphic', in2: 'n', scale: 7, xChannelSelector: 'R', yChannelSelector: 'G', result: 'd' }, f3);
191
+ el('feTurbulence', { type: 'fractalNoise', baseFrequency: .11, numOctaves: 3, seed: 9, result: 'sp' }, f3);
192
+ el('feColorMatrix', { in: 'sp', type: 'matrix', values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -18 0 0 0 12.6', result: 'spa' }, f3);
193
+ el('feComposite', { in: 'd', in2: 'spa', operator: 'in' }, f3);
194
+
195
+ /* end board: cyan stripes */
196
+ const bg = $('bg'); const bdefs = el('defs', {}, bg);
197
+ bgPat = el('pattern', { id: 'stripes', width: 92, height: 92, patternUnits: 'userSpaceOnUse' }, bdefs);
198
+ el('rect', { width: 92, height: 92, fill: '#2CCBF2' }, bgPat); el('rect', { width: 46, height: 92, fill: '#56D8F6' }, bgPat);
199
+ const rg = el('radialGradient', { id: 'bgglow', cx: .5, cy: .42, r: .6 }, bdefs);
200
+ el('stop', { offset: 0, 'stop-color': '#fff', 'stop-opacity': .55 }, rg); el('stop', { offset: 1, 'stop-color': '#fff', 'stop-opacity': 0 }, rg);
201
+ el('rect', { width: 1080, height: 1920, fill: 'url(#stripes)' }, bg);
202
+ el('rect', { width: 1080, height: 1920, fill: 'url(#bgglow)' }, bg);
203
+ // dotted confetti on the board
204
+ const Rb = rnd(77);
205
+ for (let i = 0; i < 26; i++) el('circle', { cx: Rb() * 1080, cy: Rb() * 1920, r: 5 + Rb() * 9, fill: ['#FFE14D', '#FF7FC8', '#fff'][i % 3], opacity: .85 }, bg);
206
+
207
+ /* hero rays behind the cut-out cat */
208
+ rays = $('rays'); const rdefs = el('defs', {}, rays);
209
+ const rg2 = el('radialGradient', { id: 'raycore' }, rdefs);
210
+ el('stop', { offset: 0, 'stop-color': '#fff', 'stop-opacity': .95 }, rg2); el('stop', { offset: .55, 'stop-color': '#FFF6C0', 'stop-opacity': .35 }, rg2); el('stop', { offset: 1, 'stop-color': '#FFF6C0', 'stop-opacity': 0 }, rg2);
211
+ el('rect', { width: 1080, height: 1920, fill: '#FFD23F' }, rays);
212
+ B.raysG = el('g', {}, rays); el('path', { d: raysD(20, 2400), fill: '#FF6FA5' }, B.raysG);
213
+ el('circle', { cx: 540, cy: 760, r: 760, fill: 'url(#raycore)' }, rays);
214
+
215
+ /* ---- candy wipe bands (shot 2 -> 3) ---- */
216
+ B.wipe = el('g', {}, fx);
217
+ B.wpat = [];
218
+ { const pt = el('pattern', { id: 'wp0', width: 128, height: 128, patternUnits: 'userSpaceOnUse' }, DEFS); B.wpat.push(pt);
219
+ el('rect', { width: 128, height: 128, fill: '#2CCBF2' }, pt); el('rect', { width: 58, height: 128, fill: '#FFFFFF' }, pt);
220
+ B.wband = el('g', {}, B.wipe); const BW = 1900, bar = 90, dv = 8;
221
+ el('rect', { x: -BW / 2, y: -1700, width: BW, height: 3400, fill: 'url(#wp0)' }, B.wband);
222
+ for (const sg of [-1, 1]) { let x = BW / 2; // body outward: navy | cyan | navy | lemon | navy | pink | navy edge (all opaque)
223
+ for (const c of ['#2CCBF2', '#FFE14D', '#FF3D7F']) { el('rect', { x: sg > 0 ? x : -x - dv, y: -1700, width: dv, height: 3400, fill: '#1E2A78' }, B.wband); x += dv;
224
+ el('rect', { x: sg > 0 ? x : -x - bar, y: -1700, width: bar, height: 3400, fill: c }, B.wband); x += bar; }
225
+ el('rect', { x: sg > 0 ? x : -x - 14, y: -1700, width: 14, height: 3400, fill: '#1E2A78' }, B.wband); } }
226
+
227
+ /* ---- focus lines + burst (hero) ---- */
228
+ B.focus = el('path', { fill: '#fff', opacity: .92 }, fx);
229
+ B.puff = [[330, 262, -118, 1], [800, 300, -62, 1], [150, 560, -160, 1.1], [936, 590, -20, 1.1], [96, 860, 178, 1], [986, 860, 2, 1], [226, 405, -140, .8], [888, 430, -40, .8]].map(([x, y, a, k], i) => {
230
+ const g = el('g', {}, fx), inner = el('g', {}, g);
231
+ for (const [w, c] of [[24, '#fff'], [11, '#1A1030']]) [-26, 0, 26].forEach((o, j) => el('path', { d: `M0 ${o}Q${34} ${o * 1.25 - 6} ${j === 1 ? 74 : 56} ${o * 1.6}`, fill: 'none', stroke: c, 'stroke-width': w, 'stroke-linecap': 'round' }, inner));
232
+ return { g, x, y, a, k, i }; });
233
+ B.burstBack = el('path', { fill: '#FF3D7F', stroke: '#1A1030', 'stroke-width': 9, 'stroke-linejoin': 'round' }, fx);
234
+ B.burst = el('path', { fill: '#FFF15A', stroke: '#1A1030', 'stroke-width': 10, 'stroke-linejoin': 'round' }, fx);
235
+
236
+ /* ---- SHOT 1 ---- */
237
+ const tx = [196, 368, 540, 712, 884], tdy = [6, -16, 10, -12, 4], tr = [-7, 4, -3, 6, -5];
238
+ B.title = HZ(fx, { font: 'Resource Han Rounded', weight: 900, size: 172, white: 13, outer: 12, outerColor: '#FF3D7F', ext: 16, extColor: '#A3124F', gloss: .55,
239
+ fillStops: [[0, '#FFFBD6'], [.42, '#FFE23A'], [1, '#FF9A1F']],
240
+ chars: [...'今日份快乐'].map((ch, i) => ({ ch, x: tx[i], y: 1515 + tdy[i], rot: tr[i], t0: C.title[i], drop: 90, r0: (i % 2 ? 16 : -16) })) });
241
+ B.sp1 = [[100, 1372, 36, .80], [990, 1395, 26, .867], [948, 1660, 40, .933], [140, 1690, 24, 1.0], [560, 1330, 18, 1.067]].map(([x, y, r, t0]) => ({ x, y, r, t0, e: el('path', { d: sparkleD(r), fill: '#fff', stroke: '#FFD23F', 'stroke-width': 3.5, filter: 'url(#glow)' }, fx) }));
242
+ B.asideG = el('g', {}, fx);
243
+ const aclip = el('clipPath', { id: 'aclip' }, DEFS); B.aclip = [el('rect', { x: 40, y: 330, width: 0, height: 80 }, aclip), el('rect', { x: 40, y: 410, width: 0, height: 100 }, aclip)];
244
+ B.aside = HZ(B.asideG, { font: 'LXGW Marker Gothic', size: 66, white: 0, outer: 7, outerColor: '#5A3A22', ext: 5, extColor: '#3A2412', fill: '#FFFFFF', anchor: 'start',
245
+ chars: [{ ch: '(小声)', x: 70, y: 372, size: 46 }, { ch: '正在光合作用…', x: 92, y: 452 }] });
246
+ B.aside.items[0].fillEl.setAttribute('fill', '#FFE88A');
247
+ B.aside.root.setAttribute('clip-path', 'url(#aclip)');
248
+ mctx.font = '46px "LXGW Marker Gothic"'; B.aw1 = mctx.measureText('(小声)').width; mctx.font = '66px "LXGW Marker Gothic"'; B.aw2 = mctx.measureText('正在光合作用…').width;
249
+ B.aside.items.forEach(c => X(c.g, c.x, c.y));
250
+ /* battery gag: 光合作用 = solar charging */
251
+ B.batt = el('g', { filter: 'url(#soft)' }, fx);
252
+ el('rect', { x: -89, y: -37, width: 180, height: 92, rx: 24, fill: '#0E1440' }, B.batt); el('rect', { x: 91, y: -11, width: 22, height: 40, rx: 7, fill: '#0E1440' }, B.batt);
253
+ el('rect', { x: 84, y: -20, width: 22, height: 40, rx: 7, fill: '#1E2A78' }, B.batt);
254
+ el('rect', { x: -96, y: -46, width: 180, height: 92, rx: 24, fill: '#fff', stroke: '#1E2A78', 'stroke-width': 9 }, B.batt);
255
+ B.bars = [0, 1, 2].map(j => { const g = el('g', {}, B.batt); el('rect', { x: -21, y: -29, width: 42, height: 58, rx: 10, fill: '#7BE35A', stroke: '#1E2A78', 'stroke-width': 4 }, g); el('rect', { x: -13, y: -21, width: 9, height: 28, rx: 4.5, fill: '#fff', opacity: .7 }, g); return g; });
256
+ B.bolt = el('g', {}, B.batt); el('path', { d: 'M10 -44L-24 6L-3 6L-13 44L24 -8L3 -8Z', fill: '#FFE14D', stroke: '#1E2A78', 'stroke-width': 7, 'stroke-linejoin': 'round' }, B.bolt);
257
+ B.battL = el('g', {}, B.batt); ['M112 -62L136 -92', 'M128 -34L164 -46', 'M78 -76L82 -110'].forEach(d => el('path', { d, stroke: '#1E2A78', 'stroke-width': 9, 'stroke-linecap': 'round', fill: 'none' }, B.battL));
258
+ B.battLbl = HZ(fx, { font: 'Douyin Sans', weight: 700, size: 50, white: 0, outer: 7, outerColor: '#1E2A78', ext: 6, extColor: '#0E1440', fill: '#fff',
259
+ chars: [{ ch: '充电中…', x: 222, y: 738, t0: C.battery + 3 * FR, drop: 12 }, { ch: '满电!', x: 214, y: 738, size: 60, t0: C.charge[2] + 2 * FR, drop: 0, r0: -10 }] });
260
+ B.battLbl.items[1].fillEl.setAttribute('fill', '#FFE14D');
261
+
262
+ /* ---- SHOT 2 ---- */
263
+ const qs = [[250, 560, 200, -14, [[0, '#E6FCFF'], [.45, '#3FD8FF'], [1, '#1A86F0']]], [478, 430, 245, 6, [[0, '#FFE6F3'], [.45, '#FF68AE'], [1, '#E0247A']]], [760, 330, 290, 15, [[0, '#FFFBD6'], [.45, '#FFE23A'], [1, '#FF9A1F']]]];
264
+ B.qm = HZ(fx, { font: 'Resource Han Rounded', weight: 900, size: 245, white: 12, outer: 11, outerColor: '#1E2A78', ext: 15, extColor: '#0E1440', gloss: .5,
265
+ chars: qs.map(([x, y, s, r, st], i) => ({ ch: '?', x, y, size: s, rot: r, fillStops: st, t0: C.qmarks[i], drop: 0, r0: -20 })) });
266
+ B.quiet = HZ(fx, { font: 'LXGW Marker Gothic', size: 100, white: 8, outer: 10, outerColor: '#1E2A78', ext: 9, extColor: '#0E1440', skew: -7, filter: 'url(#soft2)', fillStops: [[0, '#FFFFFF'], [1, '#A9C4E0']],
267
+ chars: [...'空气突然安静'].map((ch, i) => ({ ch, x: 150 + [0, 10, -6, 8, -4, 6][i], y: 760 + i * 112, rot: [-5, 3, -2, 4, -3, 2][i], t0: C.quiet[i] })) });
268
+ B.sweat = C.sweat.map((t0, i) => { const g = el('g', {}, fx); el('path', { d: DROP_D, fill: '#8EE8FF', stroke: '#1E2A78', 'stroke-width': 6, 'stroke-linejoin': 'round' }, g); el('ellipse', { cx: -12, cy: 6, rx: 7, ry: 12, fill: '#fff', transform: 'rotate(18 -12 6)' }, g); return { g, t0, x: [880, 968][i], y: [560, 700][i], s: [1.35, 1][i] }; });
269
+
270
+ /* ---- SHOT 3 ---- */
271
+ B.tag = el('g', {}, fx);
272
+ B.tagPill = el('g', {}, B.tag);
273
+ el('rect', { x: -118, y: -26, width: 250, height: 70, rx: 35, fill: '#0E1440' }, B.tagPill);
274
+ el('rect', { x: -125, y: -35, width: 250, height: 70, rx: 35, fill: '#FF3D7F', stroke: '#1E2A78', 'stroke-width': 7 }, B.tagPill);
275
+ { const e = el('text', { y: 2, 'font-family': 'Douyin Sans', 'font-weight': 700, 'font-size': 40, fill: '#fff', 'text-anchor': 'middle', 'dominant-baseline': 'central', 'letter-spacing': 6 }, B.tagPill); e.textContent = '本期嘉宾'; }
276
+ B.tagName = HZ(B.tag, { font: 'Resource Han Rounded', weight: 900, size: 164, white: 12, outer: 11, outerColor: '#1E2A78', ext: 14, extColor: '#0E1440', gloss: .5,
277
+ fillStops: [[0, '#7FE3FF'], [.5, '#2CCBF2'], [1, '#1E8FE0']],
278
+ chars: [{ ch: '警', x: 178, y: 1214, rot: -4, t0: C.tag[1], drop: 60, r0: -14 }, { ch: '长', x: 342, y: 1206, rot: 4, t0: C.tag[2], drop: 60, r0: 14 }] });
279
+ B.tagRib = el('g', {}, B.tag);
280
+ const ribD = 'M-150 -30L150 -30L138 -18L150 -6L138 6L150 18L150 30L-150 30L-138 18L-150 6L-138 -6L-150 -18Z';
281
+ el('path', { d: ribD, fill: '#0E1440', transform: 'translate(6 8)' }, B.tagRib);
282
+ el('path', { d: ribD, fill: '#FFE14D', stroke: '#1E2A78', 'stroke-width': 5, 'stroke-linejoin': 'round' }, B.tagRib);
283
+ { const e = el('text', { y: 2, 'font-family': 'LXGW Marker Gothic', 'font-size': 46, fill: '#1E2A78', 'text-anchor': 'middle', 'dominant-baseline': 'central', 'letter-spacing': 4 }, B.tagRib); e.textContent = '发量担当'; }
284
+
285
+ B.warn = el('g', {}, fx);
286
+ el('rect', { x: -420, y: -92, width: 840, height: 184, rx: 26, fill: '#1A1030' }, B.warn);
287
+ el('rect', { x: -408, y: -80, width: 816, height: 160, rx: 18, fill: '#FF2E4D' }, B.warn);
288
+ const hz = el('g', {}, B.warn); const clipR = el('clipPath', { id: 'wclip' }, DEFS); el('rect', { x: -408, y: -80, width: 816, height: 160, rx: 18 }, clipR); hz.setAttribute('clip-path', 'url(#wclip)');
289
+ for (let i = -12; i < 14; i++) { el('path', { d: `M${i * 64} -80l32 0l-26 22l-32 0z`, fill: '#FFE14D' }, hz); el('path', { d: `M${i * 64} 58l32 0l-26 22l-32 0z`, fill: '#FFE14D' }, hz); }
290
+ [-330, 330].forEach(x => { const g = el('g', { transform: `translate(${x} 0)` }, B.warn); el('path', { d: 'M0 -44L42 32L-42 32Z', fill: '#FFE14D', stroke: '#1A1030', 'stroke-width': 7, 'stroke-linejoin': 'round' }, g); el('rect', { x: -5, y: -18, width: 10, height: 30, rx: 4, fill: '#1A1030' }, g); el('circle', { cx: 0, cy: 22, r: 5.5, fill: '#1A1030' }, g); });
291
+ B.warnT = HZ(B.warn, { font: 'Alimama ShuHeiTi', weight: 700, size: 112, white: 0, outer: 7, outerColor: '#1A1030', ext: 7, extColor: '#1A1030', soft: false, fill: '#FFE14D',
292
+ chars: [...'前方高能'].map((ch, i) => ({ ch, x: -168 + i * 112, y: -2 })) });
293
+ B.warnT.items.forEach(c => X(c.g, c.x, c.y));
294
+ B.warnBlink = el('rect', { x: -408, y: -80, width: 816, height: 160, rx: 18, fill: '#fff', opacity: 0 }); B.warn.insertBefore(B.warnBlink, B.warnT.root);
295
+
296
+ const sx = [292, 548, 742, 826];
297
+ B.shock = HZ(fx, { font: 'Alimama ShuHeiTi', weight: 700, size: 250, white: 13, outer: 13, outerColor: '#1A1030', ext: 18, extColor: '#1A1030', extX: 6, skew: -8, gloss: .45,
298
+ fillStops: [[0, '#FF8A8A'], [.5, '#FF1E3C'], [1, '#C4001E']],
299
+ chars: [...'震惊!!'].map((ch, i) => ({ ch, x: sx[i], y: 1318 + [12, -10, -22, -34][i], rot: [-7, -3, 6, 12][i], t0: C.shock[Math.min(i, 2)] + (i === 3 ? FR : 0), drop: 0, r0: [-18, 14, 20, 24][i] })) });
300
+ const sub = [...'这发量合理吗?!']; B.sub = HZ(fx, { font: 'Douyin Sans', weight: 700, size: 92, white: 0, outer: 11, outerColor: '#16B9F0', ext: 10, extColor: '#0F2A6B', whiteColor: '#fff',
301
+ fill: '#FFFFFF', chars: sub.map((ch, i) => ({ ch, x: 540 - 3.3 * 90 + i * 90 + (i === 6 ? 10 : i === 7 ? -24 : 0), y: 1712 + (i % 2 ? -5 : 5), rot: 0, t0: C.subline + i * FR })) });
302
+ B.sub.root.setAttribute('transform', 'rotate(-3 540 1712)');
303
+ /* ---- 发量检测 meter sticker (second beat on the 7.00 brass stab) ---- */
304
+ B.meter = el('g', {}, fx);
305
+ { const g = B.meter, arcP = (a0, a1, r) => { const p = a => [Math.cos(a) * r, 58 + Math.sin(a) * r], [x0, y0] = p(a0), [x1, y1] = p(a1); return `M${x0.toFixed(1)} ${y0.toFixed(1)}A${r} ${r} 0 0 1 ${x1.toFixed(1)} ${y1.toFixed(1)}`; };
306
+ el('rect', { x: -161, y: -101, width: 340, height: 214, rx: 30, fill: '#1E2A78', opacity: .6 }, g);
307
+ el('rect', { x: -170, y: -112, width: 340, height: 214, rx: 30, fill: '#fff', stroke: '#1E2A78', 'stroke-width': 8 }, g);
308
+ [['#7BE35A', 1, 1.36], ['#FFE14D', 1.36, 1.7], ['#FF2E4D', 1.7, 2]].forEach(([c, a0, a1]) => el('path', { d: arcP(a0 * Math.PI, a1 * Math.PI, 100), fill: 'none', stroke: c, 'stroke-width': 34 }, g));
309
+ el('path', { d: arcP(Math.PI, 2 * Math.PI, 119), fill: 'none', stroke: '#1E2A78', 'stroke-width': 6, 'stroke-linecap': 'round' }, g);
310
+ for (let i = 0; i <= 10; i++) { const a = Math.PI * (1 + i / 10); el('path', { d: `M${(Math.cos(a) * 64).toFixed(1)} ${(58 + Math.sin(a) * 64).toFixed(1)}L${(Math.cos(a) * (i % 5 ? 76 : 82)).toFixed(1)} ${(58 + Math.sin(a) * (i % 5 ? 76 : 82)).toFixed(1)}`, stroke: '#1E2A78', 'stroke-width': i % 5 ? 4 : 6, 'stroke-linecap': 'round' }, g); }
311
+ const lb = (txt, x, c) => { const e = el('text', { x, y: 84, 'font-family': 'Douyin Sans', 'font-weight': 700, 'font-size': 26, fill: c, 'text-anchor': 'middle', 'dominant-baseline': 'central' }, g); e.textContent = txt; };
312
+ lb('正常', -100, '#1E2A78'); lb('爆表', 100, '#E8283C');
313
+ B.needle = el('g', {}, g); el('path', { d: 'M-11 0L0 -104L11 0Z', fill: '#1A1030', stroke: '#1A1030', 'stroke-width': 4, 'stroke-linejoin': 'round' }, B.needle);
314
+ el('circle', { cx: 0, cy: 58, r: 17, fill: '#FF3D7F', stroke: '#1A1030', 'stroke-width': 6 }, g);
315
+ const pill = el('g', { transform: 'translate(-58 -118) rotate(-4)' }, g);
316
+ el('rect', { x: -112, y: -30, width: 224, height: 62, rx: 31, fill: '#FF3D7F', stroke: '#1E2A78', 'stroke-width': 6 }, pill);
317
+ const pt = el('text', { y: 2, 'font-family': 'Douyin Sans', 'font-weight': 700, 'font-size': 40, fill: '#fff', 'text-anchor': 'middle', 'dominant-baseline': 'central', 'letter-spacing': 4 }, pill); pt.textContent = '发量检测'; }
318
+ B.bao = HZ(fx, { font: 'Alimama ShuHeiTi', weight: 700, size: 104, white: 10, outer: 9, outerColor: '#1A1030', ext: 11, extColor: '#1A1030', skew: -8, gloss: .45,
319
+ fillStops: [[0, '#FFF3A0'], [.5, '#FFE14D'], [1, '#FF9A1F']],
320
+ chars: [...'爆表!'].map((ch, i) => ({ ch, x: 796 + i * 92 - (i === 2 ? 22 : 0), y: 528 + [0, -12, -22][i], rot: [6, 10, 14][i], t0: C.bao + i * FR, drop: 0, r0: [-16, 14, 22][i] })) });
321
+
322
+ /* ---- END CARD ---- */
323
+ B.sp2 = [[118, 1228, 46, 8.13], [966, 1270, 36, 8.197], [1004, 1560, 28, 8.263], [80, 1580, 32, 8.33], [960, 410, 42, 8.6], [128, 470, 28, 8.667], [540, 300, 22, 8.733]].map(([x, y, r, t0]) => ({ x, y, r, t0, e: el('path', { d: sparkleD(r), fill: '#fff', stroke: '#FFD23F', 'stroke-width': 3.5, filter: 'url(#glow)' }, fx) }));
324
+ B.jue = HZ(fx, { font: 'Douyin Sans', weight: 700, size: 250, white: 16, outer: 13, outerColor: '#4A1A8C', ext: 18, extColor: '#2A0B5A', gloss: .55,
325
+ fillStops: [[0, '#FFF0FA'], [.45, '#FF7FC8'], [1, '#B04CFF']],
326
+ chars: [...'绝绝子'].map((ch, i) => ({ ch, x: [282, 540, 798][i], y: 1400 + [14, -16, 8][i], rot: [-9, 3, 10][i], t0: C.jue[i], drop: 110, r0: [-20, 16, 22][i] })) });
327
+ B.bye = HZ(fx, { font: 'Douyin Sans', weight: 700, size: 168, white: 12, outer: 11, outerColor: '#FF3D7F', ext: 15, extColor: '#A3124F', gloss: .5,
328
+ fillStops: [[0, '#FFE14D'], [1, '#FF9A1F']],
329
+ chars: [...'下期见~'].map((ch, i) => ({ ch, x: 290 + i * 166 + (i === 3 ? -14 : 0), y: 1722, rot: [-5, 3, -4, 7][i], t0: C.bye + i * 2 * FR, drop: 60, r0: [-14, 10, -10, 18][i], bob: i === 3 ? 14 : undefined })) });
330
+ // stamp 猫主子认证
331
+ B.stamp = el('g', {}, fx); const st = el('g', { filter: 'url(#rough)' }, B.stamp);
332
+ el('circle', { r: 150, fill: '#E8283C' }, st); el('circle', { r: 131, fill: 'none', stroke: '#fff', 'stroke-width': 5 }, st); el('circle', { r: 94, fill: 'none', stroke: '#fff', 'stroke-width': 3 }, st);
333
+ const arc = el('path', { id: 'arcT', d: 'M-112 0A112 112 0 0 1 112 0', fill: 'none' }, DEFS); const arc2 = el('path', { id: 'arcB', d: 'M-112 0A112 112 0 0 0 112 0', fill: 'none' }, DEFS);
334
+ const tp = (id, txt, dy) => { const tt = el('text', { 'font-family': 'Luckiest Guy', 'font-size': 29, fill: '#fff', 'letter-spacing': 3, dy }, st); const p = el('textPath', { href: '#' + id, startOffset: '50%', 'text-anchor': 'middle' }, tt); p.textContent = txt; };
335
+ tp('arcT', 'MIAOWU DIARY', 10); tp('arcB', '★ OFFICIAL ★', 22);
336
+ const t1 = el('text', { 'font-family': 'Alimama ShuHeiTi', 'font-weight': 700, 'font-size': 58, fill: '#fff', 'text-anchor': 'middle', 'dominant-baseline': 'central', y: -26 }, st); t1.textContent = '猫主子';
337
+ const t2 = el('text', { 'font-family': 'Alimama ShuHeiTi', 'font-weight': 700, 'font-size': 70, fill: '#fff', 'text-anchor': 'middle', 'dominant-baseline': 'central', y: 40, 'letter-spacing': 8 }, st); t2.textContent = '认证';
338
+
339
+ /* ---- program badge (persistent) ---- */
340
+ B.badgeArt = el('g', { id: 'badgeArt' }, DEFS); B.badge = el('g', {}, fx); B.bcl = Array.from({ length: 48 }, () => el('use', { href: '#badgeArt' }, B.badge));
341
+ el('path', { d: 'M24 18L44 -16L66 18Z M170 18L192 -16L212 18Z', fill: '#FFE14D', stroke: '#1E2A78', 'stroke-width': 7, 'stroke-linejoin': 'round' }, B.badgeArt);
342
+ el('rect', { x: 0, y: 8, width: 236, height: 86, rx: 30, fill: '#FFE14D', stroke: '#1E2A78', 'stroke-width': 7 }, B.badgeArt);
343
+ const bt = el('text', { x: 118, y: 53, 'font-family': 'ZCOOL KuaiLe', 'font-size': 52, fill: '#1E2A78', 'text-anchor': 'middle', 'dominant-baseline': 'central' }, B.badgeArt); bt.textContent = '喵呜日记';
344
+ const tag = el('g', { transform: 'translate(250 34) rotate(8)' }, B.badgeArt);
345
+ el('rect', { x: 0, y: 0, width: 108, height: 50, rx: 14, fill: '#FF3D7F', stroke: '#1E2A78', 'stroke-width': 6 }, tag);
346
+ const tg = el('text', { x: 54, y: 28, 'font-family': 'Luckiest Guy', 'font-size': 32, fill: '#fff', 'text-anchor': 'middle', 'dominant-baseline': 'central' }, tag); tg.textContent = 'EP.07';
347
+
348
+ fx.appendChild(B.wipe); fx.appendChild(B.badge); // wipe covers captions; program badge stays on top
349
+ await Promise.all(['i1', 'e6', 'e11', 'e16', 'i2', 'i3', ...HERO].map(id => $(id).decode()));
350
+ }
351
+
352
+ /* ---------- frame ---------- */
353
+ window.renderAt = async (t) => {
354
+ { const tf = Math.round(t * 30) / 30; // cut frames must be weight 0 or 1: no sub-sample may straddle a cut
355
+ for (const c of [C.scratch, C.drop, C.freeze]) { if (tf >= c - 1e-6 && t < c) t = c; else if (tf < c - 1e-6 && t >= c) t = c - 1e-4; } }
356
+ const fN = Math.round(t * 30), HOLD = C.freeze_hold, TPOP = C.freeze + HOLD, TOUT = C.freeze + 4 * FR;
357
+ const s1 = $('s1'), s2 = $('s2'), s3 = $('s3'), cw = $('cardwrap');
358
+ const inS1 = t < C.scratch, inS2 = t >= C.scratch && t < C.wipe, inS3 = t >= C.wipe;
359
+ s1.style.visibility = inS1 ? 'visible' : 'hidden';
360
+ s2.style.visibility = inS2 ? 'visible' : 'hidden';
361
+ cw.style.visibility = inS3 ? 'visible' : 'hidden';
362
+ $('bg').style.visibility = t >= C.freeze ? 'visible' : 'hidden';
363
+ const K6 = kick(t, C.drop, 26, 7, 11), K3 = kick(t, C.punch2, 10, 10, 13), K25 = kick(t, C.scratch, 12, 12, 14), K85 = kick(t, C.stamp, 14, 10, 13);
364
+
365
+ /* shot 1: sunbathing, slow push */
366
+ if (inS1) {
367
+ const up = t - C.charge[2], pz = up < 0 ? 0 : up < 2 * FR ? E.outQuad(up / (2 * FR)) : Math.exp(-(up - 2 * FR) * 6);
368
+ const h = addK(hand(t, 1, .8), kick(t, C.charge[2], 7, 12, 14)), Z = lerp(1.02, 1.1, E.inOutSine(clamp(t / 2.5))) * (1 + .15 * (1 - E.outExpo(clamp(t / (4 * FR))))) * (1 + .06 * pz);
369
+ place($('i1'), PL.i1, Z, 640, 900, h); $('sun').style.opacity = (.6 + .1 * Math.sin(t * 2.1)).toFixed(3); s1.style.transform = `rotate(${h.r}deg)`;
370
+ $('i1').style.filter = 'saturate(1.22) contrast(1.06) brightness(1.05)';
371
+ /* ear flick on the squeak (4 frames: 11/16/11/6 deg overlay sprites, same placement as #i1) */
372
+ const ef = fN - Math.round(C.ear * 30), ek = ef >= 0 && ef < 4 ? ['e11', 'e16', 'e11', 'e6'][ef] : '';
373
+ for (const id of ['e6', 'e11', 'e16']) { const on = id === ek; $(id).style.visibility = on ? 'visible' : 'hidden';
374
+ if (on) { place($(id), PL.i1, Z, 640, 900, h); $(id).style.filter = $('i1').style.filter; } }
375
+ } else for (const id of ['e6', 'e11', 'e16']) $(id).style.visibility = 'hidden';
376
+ /* shot 2: side-eye; snap settle on the cut, punch-in on the eyes at 3.0 */
377
+ if (inS2) {
378
+ const h = addK(hand(t, 2, 1), K25, K3);
379
+ const zc = 1 + .1 * Math.exp(-(t - C.scratch) * 14);
380
+ const zp = t < C.punch2 ? 0 : E.outQuart(clamp((t - C.punch2) / (4 * FR)));
381
+ const Z = zc * lerp(1.0, 1.36, zp) * (1 + .015 * (t - C.scratch));
382
+ place($('i2'), PL.i2, Z, lerp(540, 600, zp), lerp(1080, 1010, zp), h, lerp(PL.i2.fx, .64, zp), lerp(.6, .58, zp)); // punch into ONE staring eye s2.style.transform = `rotate(${h.r}deg)`;
383
+ $('i2').style.filter = 'saturate(1.08) contrast(1.08)';
384
+ }
385
+ /* shot 3: creep, anticipation pull-back, SNAP punch-in at the drop, freeze at 7.5 */
386
+ if (inS3) {
387
+ const tt = Math.min(t, C.freeze), hero = tt >= C.drop, zb = $('zb'), i3 = $('i3');
388
+ let h;
389
+ if (!hero) { // radial zoom-blur on snap frames: 16 in-page sub-samples of the frame's shutter, identical for every harness sample (no stepped copies)
390
+ const tf = Math.min(fN * FR, C.drop - 1e-4), a = plate3(tf - .25 * FR), b = plate3(Math.min(tf + .25 * FR, C.drop - 1e-4));
391
+ const P = plate3(tt); h = P.h;
392
+ if (Math.abs(b.g.S / a.g.S - 1) > .035) {
393
+ const cx = zb.getContext('2d'); cx.setTransform(1, 0, 0, 1, 0, 0); cx.clearRect(0, 0, 1080, 1920); const n = 16;
394
+ for (let i = 0; i < n; i++) { const g = plate3(Math.min(tf + (i / (n - 1) - .5) * .5 * FR, C.drop - 1e-4)).g; cx.globalAlpha = 1 / (i + 1); cx.drawImage(i3, g.x, g.y, PL.i3.iw * g.S, PL.i3.ih * g.S); }
395
+ zb.style.visibility = 'visible'; i3.style.visibility = 'hidden'; h = plate3(tf).h;
396
+ } else { zb.style.visibility = 'hidden'; i3.style.visibility = 'inherit';
397
+ i3.style.width = PL.i3.iw + 'px'; i3.style.height = PL.i3.ih + 'px'; i3.style.transform = `translate(${P.g.x.toFixed(2)}px,${P.g.y.toFixed(2)}px) scale(${P.g.S.toFixed(5)})`; }
398
+ } else { h = addK(hand(tt, 3, 1.3), kick(tt, C.drop, 26, 7, 11), kick(tt, C.meter, 14, 9, 13)); zb.style.visibility = 'hidden'; }
399
+ s3.style.transform = `rotate(${h.r}deg)`;
400
+ i3.style.filter = 'saturate(1.2) contrast(1.06)';
401
+ rays.style.visibility = hero ? 'visible' : 'hidden'; disp($('cutw'), hero);
402
+ if (hero) { const u = tt - C.drop, Zc = lerp(.8, .86, E.outCubic(clamp(u / 1.5))), fq = Math.round(tt * 30), fd = fq - Math.round(C.drop * 30), fm = fq - Math.round(C.meter * 30);
403
+ // 炸毛 sprites: grow 0.6 -> 1.2 overshoot -> boiled 1.0 (3 drawings @12 fps); the 7.00 re-hit puffs to 1.35
404
+ const pick = fm >= 0 && fm < 2 ? 'hL135' : (fm >= 2 && fm < 4) || (fd >= 2 && fd < 4) ? 'hL12' : fd < 2 ? 'hL06' : 'hB' + (Math.floor(tt * 12) % 3);
405
+ for (const id of HERO) { const on = id === pick; $(id).style.visibility = on ? 'visible' : 'hidden'; if (on) place($(id), PL.hero, Zc, 540, 880, h, .53, .51, true); }
406
+ const um = tt - C.meter, q = um >= 0 ? .06 * Math.exp(-um * 9) * Math.cos(um * 26) : 0, pop = 1 + .05 * Math.exp(-Math.max(0, u - FR) * 14);
407
+ $('cutw').style.transform = `scale(${(pop * (1 + q)).toFixed(4)},${(pop * (1 - .7 * q)).toFixed(4)})`; }
408
+ B.raysG.setAttribute('transform', `translate(540 760) rotate(${(8 + (tt - C.drop) * 14).toFixed(2)})`);
409
+ // freeze -> card
410
+ const uf = t - C.freeze, uh = (uf - HOLD) / (11 * FR);
411
+ const p = uf < HOLD ? 0 : uh < 1 ? E.inOutSine(uh) : 1 + .035 * Math.exp(-(uh - 1) * 2.2) * Math.sin((uh - 1) * 4.4), e = clamp(p, 0, 1.06);
412
+ const zf = uf >= 0 ? lerp(1, 1.03, E.outCubic(clamp(uf / HOLD))) : 1;
413
+ s3.style.filter = uf >= 0 ? `saturate(${lerp(.7, 1, clamp(p)).toFixed(3)})` : 'none';
414
+ const sc = lerp(zf, .72, p), rot = lerp(0, -4, p) + (t >= C.stamp ? K85.r * 12 : 0), ty = lerp(0, -40, p);
415
+ const kx = t >= C.stamp ? K85.x : 0, ky = t >= C.stamp ? K85.y : 0;
416
+ cw.style.transform = `translate(${kx}px,${ty + ky}px) translate(540px,960px) rotate(${rot}deg) scale(${sc}) translate(-540px,-960px)`;
417
+ const T = 190 * e, Bm = 560 * e, L = 70 * e, b = 30 * e;
418
+ s3.style.clipPath = p > 0 ? `inset(${T}px ${L}px ${Bm}px ${L}px round ${30 * e}px)` : 'none';
419
+ const cb = $('cardborder'); cb.style.display = p > 0 ? 'block' : 'none';
420
+ Object.assign(cb.style, { left: (L - b) + 'px', top: (T - b) + 'px', width: (1080 - 2 * L + 2 * b) + 'px', height: (1920 - T - Bm + 2 * b) + 'px', boxShadow: `0 ${34 * e}px ${60 * e}px rgba(8,40,70,${.4 * e})` });
421
+ }
422
+ bgPat.setAttribute('patternTransform', `rotate(-35) translate(${(t * 36) % 92} 0)`);
423
+
424
+ /* fx layer follows impacts */
425
+ const FK = t >= C.drop && t < C.freeze ? K6 : inS2 ? addK(K25, K3) : { x: 0, y: 0, r: 0 };
426
+ const off = { x: FK.x * .6, y: FK.y * .6 };
427
+
428
+ // title + sparkles (shot 1)
429
+ for (const [i, c] of B.title.items.entries()) { // pop-in, then a squash-and-hop wave on each quarter beat
430
+ const f = charXf(t, c, { wig: 2.2, bob: 4 }); if (!f || t >= C.scratch) { show(c.g, false); continue; } show(c.g, true);
431
+ let hy = 0, sq = 0;
432
+ for (const b of C.title_beats) { const u = t - b - i * 2 * FR, air = .24;
433
+ if (u > -.07 && u < 0) sq += .11 * (u + .07) / .07;
434
+ else if (u >= 0 && u < air) { const k = u / air; hy += 40 * 4 * k * (1 - k); sq += (k < .15 ? .11 * (1 - k / .15) : 0) - .07 * Math.sin(Math.PI * k); }
435
+ else if (u >= air && u < air + .16) { const w = (u - air) / .16; sq += .13 * Math.exp(-w * 3) * Math.cos(w * 7.5); } }
436
+ X(c.g, c.x + off.x, c.y + f.y - hy + off.y + 60 * sq, c.rot + f.r, f.s * (1 + sq), f.s * (1 - sq));
437
+ }
438
+ { const u = t - C.battery, v = u >= 0 && t < C.scratch; disp(B.batt, v); disp(B.battLbl.root, v);
439
+ if (v) { const full = t - C.charge[2]; let s = spring(u, .5, 22), sy = s;
440
+ if (full >= 0) { const w = Math.exp(-full * 9) * Math.sin(full * 40); s *= 1 + .13 * w; sy *= 1 - .13 * w; }
441
+ for (const [j, b] of B.bars.entries()) { const ub = t - C.charge[j]; show(b, ub >= 0); if (ub >= 0) { const k = spring(ub, .5, 28); X(b, -54 + j * 52, 29 - 29 * k, 0, 1, k); } }
442
+ X(B.bolt, -92, -40, -14 + 8 * Math.sin(2 * Math.PI * 2.2 * t), .9 + .1 * Math.sin(2 * Math.PI * 4.4 * t));
443
+ show(B.battL, full >= 0); if (full >= 0) B.battL.setAttribute('transform', `scale(${spring(full, .45, 26).toFixed(3)})`);
444
+ X(B.batt, 222 + off.x, 622 + 3 * Math.sin(2 * Math.PI * 1.1 * t) + off.y, lerp(-16, -5, spring(u, .45, 18)) + 1.6 * Math.sin(2 * Math.PI * .9 * t), s, sy); }
445
+ for (const [j, c] of B.battLbl.items.entries()) { const f = charXf(t, c, { wig: 1.2, bob: 2 }), vis = f && t < (j ? C.scratch : C.charge[2]); show(c.g, !!vis); if (vis) X(c.g, c.x + off.x, c.y + f.y + off.y, c.rot + f.r, f.s); } }
446
+ for (const sp of B.sp1) { const u = t - sp.t0; const v = u >= 0 && t < C.scratch; show(sp.e, v); if (v) X(sp.e, sp.x, sp.y, u * 40 + sp.x, spring(u, .4, 26) * (.8 + .2 * Math.sin(2 * Math.PI * 1.8 * t + sp.x))); }
447
+ { const u = t - C.aside, v = u >= 0 && t < C.scratch; show(B.asideG, v);
448
+ if (v) { const n = Math.floor(u * 30) + 1, k1 = clamp(n / 4), k2 = clamp((n - 4) / 7);
449
+ B.aclip[0].setAttribute('width', (k1 * (B.aw1 + 40)).toFixed(1)); B.aclip[1].setAttribute('width', (k2 * (B.aw2 + 70)).toFixed(1));
450
+ const s = .92 + .08 * spring(u, .6, 22), w = Math.sin(2 * Math.PI * .7 * t) * .8;
451
+ B.asideG.setAttribute('transform', `translate(${off.x} ${off.y}) rotate(${-4 + w} 300 420) translate(300 420) scale(${s}) translate(-300 -420)`); } }
452
+
453
+ // ??? hop on the beat
454
+ for (const [i, c] of B.qm.items.entries()) {
455
+ const f = charXf(t, c, { wig: 0, bob: 0 }); if (!f || t >= C.wipe) { show(c.g, false); continue; } show(c.g, true);
456
+ const u = t - c.t0, ph = ((t - 2.75 - i * .083) / .5 % 1 + 1) % 1, on = clamp((u - .2) / .15);
457
+ const hop = on * 46 * 4 * ph * (1 - ph), sq = on * Math.exp(-Math.pow(Math.min(ph, 1 - ph) / .07, 2));
458
+ X(c.g, c.x + off.x, c.y - hop + off.y, c.rot + f.r + on * 5 * Math.sin(2 * Math.PI * ph), f.s * (1 + .12 * sq), f.s * (1 - .14 * sq));
459
+ }
460
+ driveHZ(t, B.quiet, { until: C.wipe, z: .82, w: 34, wig: .6, bob: 1, wf: .6 }, off);
461
+ for (const d of B.sweat) {
462
+ const u = t - d.t0, v = u >= 0 && t < C.wipe; show(d.g, v); if (!v) continue;
463
+ const s = spring(u, .5, 24) * d.s, slide = 74 * E.inQuad(clamp((u - .15) / .75));
464
+ d.g.setAttribute('opacity', (1 - clamp((u - .75) / .2)).toFixed(3));
465
+ X(d.g, d.x + off.x, d.y + slide + off.y, 12, s * (1 - .05 * clamp(slide / 74)), s * (1 + .12 * clamp(slide / 74)));
466
+ }
467
+ // candy wipe
468
+ { const tw = fN * FR, u = (tw - (C.wipe - .23)) / .46, v = u > 0 && u < 1; show(B.wipe, v); // frame-quantised: crisp opaque graphic band, no translucent blur
469
+ if (v) { const c = lerp(2400, -2400, E.inOutSine(u)); B.wipe.setAttribute('transform', 'translate(540 960) rotate(-20)'); B.wband.setAttribute('transform', `translate(${c.toFixed(1)} 0)`);
470
+ B.wpat[0].setAttribute('patternTransform', `rotate(50) translate(${((tw * 30 * 60) % 128).toFixed(1)} 0)`); } }
471
+ // 嘉宾 name tag: slides in after the wipe, gets knocked by the banner slam, pops out to clear the stage before the drop
472
+ { const v = t >= C.tag[0] && t < C.tagOut + .2; disp(B.tag, v);
473
+ if (v) { const fl = t >= C.warn ? E.outBack(clamp((t - C.warn) / (4 * FR))) : 0, ud = t - C.warn - 4 * FR, sw = ud > 0 ? 6 * Math.exp(-ud * 5) * Math.sin(ud * 17) : 0;
474
+ B.tag.setAttribute('transform', `translate(0 ${(-60 * fl).toFixed(2)}) rotate(${(-12 * fl + sw).toFixed(3)} 110 1180)`);
475
+ const K = { x: 0, y: 0, r: 0 }, tOut = C.tagOut, out = t >= tOut ? clamp((t - tOut) / .17) : 0;
476
+ const oS = out <= 0 ? 1 : out < .3 ? 1 + .12 * E.outQuad(out / .3) : 1.12 * (1 - E.inCubic((out - .3) / .7)), u0 = t - C.tag[0];
477
+ X(B.tagPill, 215 - 260 * (1 - spring(u0, .62, 20)) + K.x, 1085 + K.y + 2 * Math.sin(2 * Math.PI * 1.1 * t + .5), -4 + 1.5 * Math.sin(2 * Math.PI * .9 * t) + K.r * 10, spring(u0, .5, 22) * oS);
478
+ for (const c of B.tagName.items) { const f = charXf(t, c, { wig: 2, bob: 3, t1: tOut + FR }); show(c.g, !!f); if (f) X(c.g, c.x + K.x, c.y + f.y + K.y, c.rot + f.r + K.r * 10, f.s); }
479
+ const ur = t - C.tag[3]; show(B.tagRib, ur >= 0);
480
+ if (ur >= 0) { const k = ur < .1 ? lerp(1.7, 1, E.inQuad(ur / .1)) : 1 - .06 * Math.exp(-(ur - .1) * 16) * Math.cos((ur - .1) * 44);
481
+ B.tagRib.setAttribute('opacity', clamp(ur / .05).toFixed(3));
482
+ X(B.tagRib, 330 + K.x, 1322 + K.y, -6 - (ur < .1 ? 8 * (1 - ur / .1) : 0) + Math.sin(2 * Math.PI * .8 * t) + K.r * 10, k * oS); } } }
483
+ // warning banner
484
+ { const u = t - C.warn, v = u >= 0 && t < C.drop; show(B.warn, v);
485
+ if (v) { const s = lerp(1.7, 1, spring(u, .5, 24)), r = lerp(-14, -5, spring(u, .45, 20)), jit = t > C.push[0] ? (h1(Math.floor(t * 15)) - .5) * 14 : 0;
486
+ X(B.warn, 540 + jit, 1470 + (t > C.push[0] ? (h1(Math.floor(t * 15) + 99) - .5) * 8 : 0), r, s);
487
+ const bl = C.warn_beeps.concat(C.push).some(b => t >= b && t < b + 2 * FR); B.warnBlink.setAttribute('opacity', bl ? .55 : 0); } }
488
+ // hero: focus lines, burst, 震惊!!, subline
489
+ { const hero = t >= C.drop && t < TOUT + .17, boil = Math.floor(Math.min(t, C.freeze) * 12) % 3, po = popOut(t, TOUT);
490
+ const fm = fN - Math.round(C.meter * 30), rh = fm >= 0 && fm < 3 ? [[10, -5], [-10, 6], [6, -3]][fm] : [0, 0]; // 3-frame re-hit shake on the 7.00 stab
491
+ const offH = { x: off.x + rh[0], y: off.y + rh[1] }, rb = fm >= 0 ? 1 + .1 * Math.exp(-(t - C.meter) * 12) : 1;
492
+ show(B.focus, hero && t < TOUT); show(B.burst, hero); show(B.burstBack, hero);
493
+ for (const pm of B.puff) { show(pm.g, hero); if (hero) { const u = t - C.drop - FR - pm.i * .5 * FR, k = spring(u, .45, 26), bj = Math.floor(Math.min(t, C.freeze) * 12) + pm.i * 7;
494
+ const d = 34 * (1 - clamp(k)) + 5 * Math.sin(2 * Math.PI * 1.3 * t + pm.i), ar = pm.a * Math.PI / 180;
495
+ X(pm.g, pm.x + off.x + d * Math.cos(ar) + (h1(bj) - .5) * 5, pm.y + off.y + d * Math.sin(ar) + (h1(bj + 3) - .5) * 5, pm.a + (h1(bj + 5) - .5) * 7, Math.max(0, k) * pm.k * po); } }
496
+ if (hero) {
497
+ const u = t - C.drop; B.focus.setAttribute('d', focusD(540, 700, 300 + boil)); B.focus.setAttribute('opacity', (.95 - .25 * clamp(u / .6)).toFixed(3));
498
+ const bs = spring(u + 2 * FR, .42, 24) * po * rb, cx = 540 + offH.x, cy = 1330 + offH.y;
499
+ B.burst.setAttribute('d', burstD(0, 0, 432, 288, 15, 100 + boil)); B.burstBack.setAttribute('d', burstD(0, 0, 452, 304, 15, 200 + boil));
500
+ X(B.burst, cx, cy, -5 + 1.2 * Math.sin(t * 7), bs); X(B.burstBack, cx + 16, cy + 18, -3, bs);
501
+ }
502
+ driveHZ(t, B.shock, { from: C.drop, t1: TOUT, wig: 2.4, bob: 3, wf: 1.6 }, offH);
503
+ driveHZ(t, B.sub, { t1: TOUT, z: .6, w: 28, wig: 1.2, bob: 2 }, off);
504
+ // 发量检测 meter: slams in on the 7.00 stab, needle whips 0 -> 爆表 in 4 frames (outBack), then buzzes against the stop
505
+ { const um = t - (C.meter - 3 * FR), v = um >= 0 && t < TOUT + .17; disp(B.meter, v); disp(B.bao.root, v);
506
+ if (v) { let s, o = 1; if (t < C.meter) { const k = um / (3 * FR); s = lerp(1.9, 1, E.inQuad(k)); o = clamp(k * 2.5); } else { const w = t - C.meter; s = 1 - .08 * Math.exp(-w * 16) * Math.cos(w * 44); }
507
+ s *= po; B.meter.setAttribute('opacity', o.toFixed(3)); const mk = kick(t, C.meter, 10, 10, 13);
508
+ X(B.meter, 826 + mk.x + off.x * .5, 318 + mk.y + off.y * .5, 7 + (t < C.meter ? 8 * (1 - um / (3 * FR)) : 0) + .8 * Math.sin(t * 2.6), s);
509
+ const wn = clamp((t - C.needle[0]) / (C.needle[1] - C.needle[0])), buzz = t >= C.needle[1] ? 3.5 * Math.sin(2 * Math.PI * 17 * t) * (.4 + .6 * Math.exp(-(t - C.needle[1]) * 5)) : 0;
510
+ B.needle.setAttribute('transform', `translate(0 58) rotate(${(lerp(-88, 96, E.outBack(wn)) + buzz).toFixed(2)})`);
511
+ driveHZ(t, B.bao, { t1: TOUT, wig: 3, bob: 3, wf: 1.8 }, { x: mk.x, y: mk.y }); } }
512
+ }
513
+ // end card
514
+ driveHZ(t, B.jue, { wig: 2.6, bob: 5, wf: 1.0 });
515
+ for (const sp of B.sp2) { const u = t - sp.t0; show(sp.e, u >= 0); if (u >= 0) X(sp.e, sp.x, sp.y, u * 50 + sp.y, spring(u, .4, 26) * (.78 + .22 * Math.sin(2 * Math.PI * 1.6 * t + sp.y))); }
516
+ driveHZ(t, B.bye, { wig: 2, bob: 7, wf: 1.2 });
517
+ { const u = t - (C.stamp - .13), v = u >= 0; show(B.stamp, v);
518
+ if (v) { let s, o = 1; if (t < C.stamp) { const k = u / .13; s = lerp(2.5, 1, E.inQuad(k)); o = clamp(k * 2.2); } else { const w = t - C.stamp; s = 1 - .09 * Math.exp(-w * 16) * Math.cos(w * 44); }
519
+ B.stamp.setAttribute('opacity', o); X(B.stamp, 812 + K85.x * .5, 1085 + K85.y * .5, -14 + (t < C.stamp ? -10 * (1 - u / .13) : 0) + .8 * Math.sin(t * 2.2), s); } }
520
+ // badge (persistent) with a tiny idle bob + ear twitch
521
+ { const bx = t => { let cxp = 224, cyp = 142 + 2 * Math.sin(t * 2.4), br = .6 * Math.sin(t * 1.7), bs = 1;
522
+ if (t < 10 * FR) { const a = clamp(t / (3 * FR)), k = E.outBack(clamp((t - 3 * FR) / (7 * FR)));
523
+ bs = lerp(lerp(2.4, 2.0, E.outQuad(a)), 1, k); cxp = lerp(540, 224, k); cyp = lerp(820, 142, k); br = lerp(-6, 0, k); }
524
+ const us = t - C.sting;
525
+ if (us >= 0 && us < .36) { const m = spring(us, .42, 30) * (1 - E.inCubic(clamp((us - .2) / .16)));
526
+ bs = lerp(1, 2.6, m); cxp = lerp(cxp, 540, clamp(m)); cyp = lerp(cyp, 940, clamp(m)); br = lerp(br, -4, clamp(m)); }
527
+ return [cxp - 170 * bs, cyp - 50 * bs, br, bs]; };
528
+ // fast frames: 24 in-page sub-samples across the shutter (frame-quantised, so every harness sample is identical -> one continuous smear)
529
+ const tf = fN * FR, a = bx(tf - .25 * FR), b = bx(tf + .25 * FR), fast = Math.hypot(b[0] - a[0], b[1] - a[1]) + 180 * Math.abs(b[3] - a[3]) > 8;
530
+ B.bcl.forEach((u, i) => { if (!fast && i) { show(u, false); return; } show(u, true);
531
+ const v = fast ? bx(tf + (i / 47 - .5) * .5 * FR) : bx(t); X(u, v[0], v[1], v[2], v[3]); u.setAttribute('opacity', fast ? (1 / (i + 1)).toFixed(4) : '1'); }); }
532
+ // flashes
533
+ let fl = fN === Math.round(C.drop * 30) ? 1 : fN === Math.round(C.freeze * 30) ? .85 : 0;
534
+ for (const p of C.push) if (fN === Math.round(p * 30)) fl = .2;
535
+ $('flash').style.opacity = fl.toFixed(3);
536
+ $('vig').style.opacity = t >= C.freeze ? .0 : 1;
537
+ const fi = Math.round(t * 30); $('grain').style.backgroundPosition = `${Math.floor(h1(fi) * 2048)}px ${Math.floor(h1(fi + 777) * 2048)}px`;
538
+ };
539
+ build().then(() => { window.__ready = true; });
540
+ </script>
541
+ </body></html>