dsh-drawai 0.4.2 → 0.4.4

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 (379) hide show
  1. package/README.md +7 -5
  2. package/lib/client.js +142 -16
  3. package/lib/index.js +7945 -7719
  4. package/lib/motion/asset-pack.js +394 -394
  5. package/lib/motion/assets.js +291 -291
  6. package/lib/motion/demo-assets-lock.js +10 -10
  7. package/lib/motion/mgstyles/briefs/23-ink-wash.md +147 -0
  8. package/lib/motion/mgstyles/catalog.d/23-ink-wash.json +28 -0
  9. package/lib/motion/mgstyles/catalog.json +127 -14
  10. package/lib/motion/mgstyles/upstream/demos/23-ink-wash/brush.js +149 -0
  11. package/lib/motion/mgstyles/upstream/demos/23-ink-wash/film.js +202 -0
  12. package/lib/motion/mgstyles/upstream/manifest.json +28 -3
  13. package/lib/motion/mgstyles/upstream/prompts/23-ink-wash.md +59 -0
  14. package/lib/motion/mgstyles/vendor/README.md +28 -28
  15. package/lib/motion/mgstyles/vendor/modules/d3/LICENSE +13 -13
  16. package/lib/motion/mgstyles/vendor/modules/d3/dist/d3.min.js +2 -2
  17. package/lib/motion/mgstyles/vendor/modules/opentype.js/LICENSE +20 -20
  18. package/lib/motion/mgstyles/vendor/modules/opentype.js/dist/opentype.mjs +14460 -14460
  19. package/lib/motion/mgstyles/vendor/modules/simplex-noise/LICENSE +21 -21
  20. package/lib/motion/mgstyles/vendor/modules/simplex-noise/dist/esm/simplex-noise.js +465 -465
  21. package/lib/motion/mgstyles/vendor/modules/topojson-client/LICENSE +13 -13
  22. package/lib/motion/mgstyles/vendor/modules/topojson-client/dist/topojson-client.min.js +2 -2
  23. package/lib/motion/project.js +5 -1
  24. package/lib/motion/qa.js +116 -6
  25. package/lib/motion/render.js +179 -179
  26. package/lib/motion/scene-kit.js +1 -1
  27. package/lib/motion/shotcraft/upstream/SKILL.md +286 -286
  28. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -54
  29. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -200
  30. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -45
  31. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -20
  32. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -65
  33. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -151
  34. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -129
  35. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -75
  36. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -40
  37. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -11
  38. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -10
  39. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -49
  40. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -210
  41. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -423
  42. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -170
  43. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -157
  44. package/lib/motion/shotcraft/upstream/demos/README.md +120 -120
  45. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -112
  46. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -647
  47. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -316
  48. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -82
  49. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -115
  50. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -243
  51. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +388 -388
  52. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -250
  53. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -305
  54. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -246
  55. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -390
  56. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -138
  57. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -542
  58. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -315
  59. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -299
  60. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -173
  61. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -348
  62. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -366
  63. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -279
  64. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -184
  65. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -390
  66. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -155
  67. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -303
  68. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -290
  69. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -278
  70. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -307
  71. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -215
  72. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -299
  73. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -232
  74. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -290
  75. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -273
  76. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -167
  77. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -536
  78. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -164
  79. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -175
  80. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -197
  81. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -241
  82. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -279
  83. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -230
  84. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -345
  85. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -275
  86. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -229
  87. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -312
  88. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -222
  89. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -295
  90. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -329
  91. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -315
  92. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -264
  93. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -260
  94. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -263
  95. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -123
  96. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -187
  97. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -175
  98. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -305
  99. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -350
  100. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -352
  101. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -218
  102. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -297
  103. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -157
  104. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -218
  105. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -202
  106. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -265
  107. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -457
  108. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -446
  109. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -249
  110. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -278
  111. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -332
  112. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -358
  113. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -201
  114. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -200
  115. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -208
  116. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -341
  117. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -389
  118. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -293
  119. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -183
  120. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -245
  121. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -222
  122. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -223
  123. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -217
  124. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -343
  125. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -357
  126. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -187
  127. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -333
  128. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -274
  129. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -270
  130. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -430
  131. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -252
  132. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -106
  133. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -288
  134. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -362
  135. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -168
  136. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -310
  137. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -261
  138. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -459
  139. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -294
  140. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -161
  141. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -248
  142. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -359
  143. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -227
  144. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -162
  145. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -248
  146. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -186
  147. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -355
  148. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -272
  149. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -262
  150. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -217
  151. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -285
  152. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -205
  153. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -178
  154. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -147
  155. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -143
  156. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -134
  157. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -217
  158. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -198
  159. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -221
  160. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -312
  161. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -261
  162. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -121
  163. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -153
  164. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -179
  165. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -140
  166. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -309
  167. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -191
  168. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -292
  169. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -135
  170. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -124
  171. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -255
  172. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -173
  173. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -225
  174. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -141
  175. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -137
  176. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -147
  177. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -409
  178. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -280
  179. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -271
  180. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -385
  181. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -312
  182. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -303
  183. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -77
  184. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -311
  185. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -307
  186. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -349
  187. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -255
  188. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -244
  189. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -217
  190. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -652
  191. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -153
  192. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -238
  193. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -324
  194. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -354
  195. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -101
  196. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -129
  197. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -297
  198. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -57
  199. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -155
  200. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -175
  201. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -153
  202. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -146
  203. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -226
  204. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -1
  205. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -193
  206. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -121
  207. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -199
  208. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -183
  209. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -257
  210. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -382
  211. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -111
  212. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -50
  213. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -95
  214. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -41
  215. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -52
  216. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -39
  217. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -39
  218. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -57
  219. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -51
  220. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -46
  221. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -52
  222. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -43
  223. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -42
  224. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -48
  225. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -52
  226. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -45
  227. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -46
  228. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -44
  229. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -63
  230. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -54
  231. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -58
  232. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -35
  233. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -53
  234. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -42
  235. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -50
  236. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -46
  237. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -56
  238. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -49
  239. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -50
  240. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -53
  241. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -53
  242. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -55
  243. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -52
  244. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -60
  245. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -57
  246. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -51
  247. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -41
  248. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -53
  249. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -60
  250. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -55
  251. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -57
  252. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -47
  253. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -37
  254. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -54
  255. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -36
  256. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -56
  257. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -56
  258. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -40
  259. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -60
  260. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -57
  261. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -73
  262. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -87
  263. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -55
  264. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -50
  265. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -59
  266. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -38
  267. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -38
  268. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -59
  269. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -39
  270. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -61
  271. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -52
  272. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -50
  273. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -66
  274. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -43
  275. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -38
  276. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -38
  277. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -56
  278. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -44
  279. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -38
  280. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -63
  281. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -57
  282. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -63
  283. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -58
  284. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -45
  285. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -55
  286. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -49
  287. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -42
  288. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -42
  289. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -45
  290. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -48
  291. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -55
  292. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -43
  293. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -41
  294. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -42
  295. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -59
  296. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -55
  297. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -65
  298. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -42
  299. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -64
  300. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -64
  301. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -54
  302. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -91
  303. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -51
  304. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -66
  305. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -38
  306. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -66
  307. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -58
  308. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -61
  309. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -64
  310. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -45
  311. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -41
  312. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -51
  313. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -42
  314. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -63
  315. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -57
  316. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -75
  317. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -59
  318. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -67
  319. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -60
  320. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -66
  321. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -40
  322. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -45
  323. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -62
  324. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -55
  325. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -37
  326. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -55
  327. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -50
  328. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -43
  329. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -55
  330. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -51
  331. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -51
  332. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -56
  333. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -49
  334. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -57
  335. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -36
  336. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -64
  337. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -47
  338. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -170
  339. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -157
  340. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -103
  341. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -44
  342. package/lib/motion/shotcraft/upstream/template/package.json +20 -20
  343. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -6
  344. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -17
  345. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -65
  346. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -48
  347. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -24
  348. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -192
  349. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -111
  350. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -150
  351. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -158
  352. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -468
  353. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -552
  354. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -411
  355. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -200
  356. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -324
  357. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +388 -388
  358. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -4
  359. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -7
  360. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -68
  361. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -1
  362. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -24
  363. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -74
  364. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -91
  365. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -213
  366. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -15
  367. package/lib/motion/style-frames.js +306 -306
  368. package/lib/motion/sync.js +214 -214
  369. package/lib/motion-library.js +1 -1
  370. package/lib/motion-project.js +105 -105
  371. package/lib/motion-render-worker.js +174 -174
  372. package/lib/routing/router.js +222 -222
  373. package/lib/routing/vendor/README.md +96 -96
  374. package/lib/routing/vendor/libavoid-routing.js +753 -753
  375. package/lib/routing/vendor/libavoid.min.js +59 -59
  376. package/lib/svg-export.js +1344 -0
  377. package/lib/video-trace-pool.js +128 -128
  378. package/package.json +3 -2
  379. package/LICENSE +0 -4175
@@ -1,345 +1,345 @@
1
- // hit-counter 连招计数:三张功能卡接连砸入槽位,每次命中 = 全局顿帧 2f + 落点伤害数字上浮渐隐
2
- // + 右上角 ×N combo 跳字(脉冲 / 倾斜 / 字号逐次加码)。组合:hitstop + damage-number-pop + combo-counter。
3
- //
4
- // 第二轮重设计(钴蓝街机海报 · 构建工具更新日):
5
- // - look = custom「cobalt arcade」:满版高饱和钴蓝色场(不是深海军蓝暗场)+ 白卡 + 街机黄。
6
- // 格斗游戏 combo UI 的语言直接拿来讲"功能连招":伤害数字是黄色斜体 900 字重 + 硬投影(漫画式错位影),
7
- // 计数器是 150→210px 的斜体「×N」,底下三格热度条逐格点亮。
8
- // - 内容:video-shotcraft 的三项能力,每一击的"伤害"= 做一支宣传片省下的制作时间(−2 h / −1 day / −3 days,示意值),
9
- // 三击打完收尾一行「Up to a week back on every promo.」——游戏梗落到真实收益上。
10
- // - 顿帧是全局的:背景斜纹滚动、浮尘、卡片、特效全部由同一个 remap 时间 t 驱动,命中时整幅画面一起冻 2f;
11
- // 只有卡面闪白与槽位受光用真实帧(冻结期间也要发生)。
12
- // - 触地:卡按速度竖向拉伸 + 运动模糊 → 触地压扁回弹(指数回落)→ 白色冲击环外扩 + 黄色火花八向迸射 + 槽底受光。
13
- //
14
- // 时间表(动画时间 t,30fps;真实帧 = t + 已冻结帧):
15
- // 0–22 建立:钴蓝场、三个虚线槽位(01/02/03)、眉题、暗色 ×0 计数器
16
- // 20/48/76 → 30/58/86 三张卡各 10f ease-in(quad) 砸落(间隔 28f 的均匀连招节拍)
17
- // 每命中 全局顿帧 2f;伤害数字打在卡面上 scale 1.45→1 + 上浮 150px 出卡沿,4f 后 12f 渐隐;计数器 exp(−t/2.4) 回落
18
- // 100–124 收尾行逐词升起,"a week" 用街机黄
19
- // 124–176 hold:背景斜纹极缓滚动,干净海报
20
- import React from 'react';
21
- import { AbsoluteFill, useCurrentFrame } from 'remotion';
22
- import { EASE, FONT, Grain, SpeedBlur, Vignette, bezier, mix, ramp } from '../../_fixtures/Polish';
23
- import { TextReveal, alpha, type } from '../../_fixtures/Look';
24
- import { BRAND, ShotcraftMark } from '../../_fixtures/Brand';
25
-
26
- export const HIT_COUNTER_DURATION = 176;
27
-
28
- // 自定义 look「cobalt arcade」
29
- const C = {
30
- bg0: '#1b3fd6', bg1: '#1230b0', bg2: '#0a1d78',
31
- card: '#f7f8ff', ink: '#0b1240', ink2: '#4a5488', ink3: '#8a93bf',
32
- hit: '#ffd23f', // 街机黄:只给伤害数字 / 计数器 / 火花 / 关键收益
33
- deep: '#06104a', // 硬投影色
34
- };
35
-
36
- const HITS_T = [30, 58, 86]; // 命中时刻(动画时间)
37
- const STOP = 2; // 每次顿帧帧数
38
- const HITS_REAL = HITS_T.map((h, i) => h + i * STOP); // 真实命中帧 = 动画命中帧 + 已冻结帧
39
-
40
- const SLOT_W = 480;
41
- const SLOT_H = 330;
42
- const SLOT_Y = 446;
43
- const GAP = 60;
44
- const SLOT_XS = [0, 1, 2].map((i) => 960 - (SLOT_W * 3 + GAP * 2) / 2 + i * (SLOT_W + GAP));
45
- const DROP_FROM = -460;
46
- const inQuad = bezier(0.55, 0.085, 0.68, 0.53);
47
-
48
- const DMG = ['−2 h', '−1 day', '−3 days'];
49
- const DMG_SIZE = [88, 104, 124]; // 伤害数字逐击加大
50
- const PULSE = [1.3, 1.45, 1.6];
51
- const TILT = [-2, -4, -6];
52
- const COUNTER_SIZE = [140, 166, 196];
53
-
54
- const FEATURES = [
55
- { icon: 'recipe', name: 'Shot recipes', desc: 'Pick a move, not a blank canvas.', note: 'per shot' },
56
- { icon: 'beat', name: 'Beat-synced cuts', desc: 'Every cut lands on the music.', note: 'per edit' },
57
- { icon: 'layers', name: '2.5D camera', desc: 'Real pages, filmed in depth.', note: 'per promo' },
58
- ];
59
-
60
- const Icon: React.FC<{ name: string }> = ({ name }) => {
61
- const sw = { fill: 'none', stroke: C.bg1, strokeWidth: 2, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
62
- return (
63
- <svg width={34} height={34} viewBox="0 0 24 24">
64
- {/* 镜头配方卡 */}
65
- {name === 'recipe' && (
66
- <>
67
- <rect x="4" y="3.5" width="16" height="17" rx="2.5" {...sw} />
68
- <path d="M8 8.5h8M8 12h8M8 15.5h5" {...sw} />
69
- </>
70
- )}
71
- {/* 踩点:波形 */}
72
- {name === 'beat' && <path d="M3 12h1.5M7 8.5v7M11 4.5v15M15 8v8M19 10.5v3M21 12h0.5" {...sw} />}
73
- {/* 2.5D:层叠景深 */}
74
- {name === 'layers' && (
75
- <>
76
- <path d="M3 8.5L12 4l9 4.5-9 4.5-9-4.5z" {...sw} />
77
- <path d="M3 12.5l9 4.5 9-4.5M3 16.5L12 21l9-4.5" {...sw} />
78
- </>
79
- )}
80
- </svg>
81
- );
82
- };
83
-
84
- // saved = 伤害数字飘走后,收益「落」进卡片页脚的进度(0–1)
85
- const FeatureCard: React.FC<{ i: number; elev: number; saved: number }> = ({ i, elev, saved }) => {
86
- const f = FEATURES[i];
87
- return (
88
- <div
89
- style={{
90
- width: SLOT_W, height: SLOT_H, boxSizing: 'border-box', borderRadius: 26, padding: '34px 38px 32px',
91
- background: `linear-gradient(180deg, #ffffff 0%, ${C.card} 100%)`,
92
- boxShadow: `inset 0 1px 0 #fff, 0 ${(2 + elev * 0.4).toFixed(1)}px ${(4 + elev * 0.6).toFixed(1)}px ${alpha(C.deep, 0.25)}, 0 ${(10 + elev * 0.8).toFixed(1)}px ${(30 + elev * 1.4).toFixed(1)}px -8px ${alpha(C.deep, 0.5)}`,
93
- display: 'flex', flexDirection: 'column', fontFamily: FONT.sans, color: C.ink,
94
- }}
95
- >
96
- <div style={{ display: 'flex', alignItems: 'center' }}>
97
- <div style={{ width: 62, height: 62, borderRadius: 18, background: alpha(C.bg0, 0.1), display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
98
- <Icon name={f.icon} />
99
- </div>
100
- <div style={{ marginLeft: 'auto', ...type(26, 600, { mono: true }), color: C.ink3 }}>0{i + 1}</div>
101
- </div>
102
- <div style={{ marginTop: 30, ...type(48, 760), letterSpacing: '-0.035em', lineHeight: 1.02 }}>{f.name}</div>
103
- <div style={{ marginTop: 12, ...type(30, 450), lineHeight: 1.3, color: C.ink2 }}>{f.desc}</div>
104
- <div
105
- style={{
106
- marginTop: 'auto', paddingTop: 18, borderTop: `1px solid ${alpha(C.ink, 0.1)}`, display: 'flex', alignItems: 'baseline',
107
- opacity: saved, transform: `translateY(${mix(10, 0, saved).toFixed(1)}px)`,
108
- }}
109
- >
110
- <span style={{ ...type(32, 800), fontStyle: 'italic', letterSpacing: '-0.02em', color: C.bg1 }}>{DMG[i]}</span>
111
- <span style={{ marginLeft: 'auto', ...type(26, 500), color: C.ink3 }}>{f.note}</span>
112
- </div>
113
- </div>
114
- );
115
- };
116
-
117
- const dropY = (t: number, hit: number) => mix(DROP_FROM, SLOT_Y, ramp(t, hit - 10, 10, inQuad));
118
-
119
- const hash = (n: number) => {
120
- const x = Math.sin(n * 127.1 + 311.7) * 43758.5453;
121
- return x - Math.floor(x);
122
- };
123
-
124
- export const HitCounter: React.FC = () => {
125
- const frame = useCurrentFrame();
126
-
127
- // —— 全局帧 remap:每个真实命中帧起冻结 2f ——
128
- const remap = (fr: number) => {
129
- let t = fr;
130
- for (const h of HITS_REAL) t -= Math.min(Math.max(fr - h, 0), STOP);
131
- return t;
132
- };
133
- const t = remap(frame);
134
- const count = HITS_T.filter((h) => t >= h).length;
135
-
136
- // —— 计数器 ——
137
- let cScale = 1;
138
- let cRot = 0;
139
- let cSize = 130;
140
- if (count > 0) {
141
- const i = count - 1;
142
- const since = t - HITS_T[i];
143
- cScale = 1 + (PULSE[i] - 1) * Math.exp(-since / 2.4);
144
- cRot = TILT[i];
145
- cSize = COUNTER_SIZE[i];
146
- }
147
- const stamp = count > 0 ? 1 - ramp(t, HITS_T[count - 1], 7, EASE.out) : 0;
148
-
149
- // 背景斜纹滚动(t 驱动 → 顿帧时一起冻住)
150
- const stripeShift = t * 2.2;
151
-
152
- return (
153
- <AbsoluteFill style={{ overflow: 'hidden', fontFamily: FONT.sans, background: `linear-gradient(170deg, ${C.bg0} 0%, ${C.bg1} 55%, ${C.bg2} 100%)` }}>
154
- {/* 背景:主光 + 斜纹(速度线的静态版)+ 网点 */}
155
- <div style={{ position: 'absolute', inset: 0, background: `radial-gradient(ellipse 60% 55% at 38% 30%, ${alpha('#6f8dff', 0.45)} 0%, ${alpha('#6f8dff', 0)} 70%)` }} />
156
- <div
157
- style={{
158
- position: 'absolute', inset: -200, opacity: 0.1,
159
- backgroundImage: 'repeating-linear-gradient(-58deg, #ffffff 0px, #ffffff 2px, transparent 2px, transparent 46px)',
160
- transform: `translateX(${(stripeShift % 54.2).toFixed(2)}px)`,
161
- }}
162
- />
163
- <div
164
- style={{
165
- position: 'absolute', inset: 0, opacity: 0.14,
166
- backgroundImage: `radial-gradient(circle, ${C.deep} 1.4px, transparent 1.6px)`, backgroundSize: '18px 18px',
167
- WebkitMaskImage: 'linear-gradient(180deg, transparent 40%, #000 100%)', maskImage: 'linear-gradient(180deg, transparent 40%, #000 100%)',
168
- }}
169
- />
170
-
171
- {/* 眉题 */}
172
- <div style={{ position: 'absolute', left: 120, top: 104, display: 'flex', alignItems: 'center', gap: 18, opacity: ramp(frame, 0, 14, EASE.out) }}>
173
- <ShotcraftMark size={52} tone="dark" />
174
- <div style={{ ...type(34, 760), color: '#fff', letterSpacing: '-0.02em' }}>{BRAND.name}</div>
175
- <div style={{ ...type(24, 650, { caps: true }), color: alpha('#ffffff', 0.62), letterSpacing: '0.24em', marginLeft: 8 }}>What’s new</div>
176
- </div>
177
-
178
- {/* 槽位:虚线 + 大号序号,建立期就立预期 */}
179
- {SLOT_XS.map((x, i) => {
180
- const near = ramp(t, HITS_T[i] - 10, 10, inQuad);
181
- const df = frame - HITS_REAL[i];
182
- const glowA = df >= 0 ? Math.exp(-df / 6) : 0; // 槽底受光(真实帧)
183
- return (
184
- <React.Fragment key={`slot-${i}`}>
185
- <div
186
- style={{
187
- position: 'absolute', left: x, top: SLOT_Y, width: SLOT_W, height: SLOT_H, borderRadius: 26, boxSizing: 'border-box',
188
- border: `2px dashed ${alpha('#ffffff', 0.28)}`, background: alpha(C.deep, 0.16),
189
- display: 'flex', alignItems: 'center', justifyContent: 'center',
190
- ...type(120, 800), color: alpha('#ffffff', 0.1), letterSpacing: '-0.04em',
191
- }}
192
- >
193
- 0{i + 1}
194
- </div>
195
- {near > 0 && t < HITS_T[i] && (
196
- <div
197
- style={{
198
- position: 'absolute', left: x + 40 - (1 - near) * 40, top: SLOT_Y + 50, width: SLOT_W - 80 + (1 - near) * 80, height: SLOT_H - 40,
199
- borderRadius: 30, background: C.deep, filter: `blur(${mix(44, 16, near).toFixed(1)}px)`, opacity: mix(0.05, 0.5, near),
200
- }}
201
- />
202
- )}
203
- {glowA > 0.02 && (
204
- <div
205
- style={{
206
- position: 'absolute', left: x - 120, top: SLOT_Y + SLOT_H - 80, width: SLOT_W + 240, height: 200, borderRadius: '50%',
207
- background: `radial-gradient(ellipse 50% 50% at 50% 50%, ${alpha(C.hit, 0.45 * glowA)} 0%, ${alpha(C.hit, 0)} 70%)`,
208
- }}
209
- />
210
- )}
211
- </React.Fragment>
212
- );
213
- })}
214
-
215
- {/* 三张功能卡 */}
216
- {HITS_T.map((hit, i) => {
217
- if (t < hit - 10) return null;
218
- const y = dropY(t, hit);
219
- const vy = t < hit ? dropY(t + 0.5, hit) - dropY(t - 0.5, hit) : 0;
220
- const speed = Math.min(1, vy / 200);
221
- const s = t - hit;
222
- const squash = s >= 0 ? 0.07 * Math.exp(-s / 1.6) : 0;
223
- const sy = 1 + speed * 0.06 - squash;
224
- const sx = 1 - speed * 0.025 + squash * 0.5;
225
- const elev = s >= 0 ? 6 : mix(6, 60, (SLOT_Y - y) / (SLOT_Y - DROP_FROM));
226
- const df = frame - HITS_REAL[i];
227
- const flash = df >= 0 && df < STOP + 4 ? (df < STOP ? 0.7 : 0.7 * (1 - (df - STOP + 1) / 5)) : 0;
228
- return (
229
- <SpeedBlur key={`card-${i}`} vx={0} vy={vy} amount={0.12} max={24}>
230
- <div style={{ position: 'absolute', left: SLOT_XS[i], top: y, transform: `scale(${sx.toFixed(4)}, ${sy.toFixed(4)})`, transformOrigin: 'bottom center' }}>
231
- <FeatureCard i={i} elev={elev} saved={ramp(t, hit + 12, 12, EASE.snappy)} />
232
- {flash > 0 && <div style={{ position: 'absolute', inset: 0, borderRadius: 26, background: '#ffffff', opacity: flash }} />}
233
- </div>
234
- </SpeedBlur>
235
- );
236
- })}
237
-
238
- {/* 触地冲击:白色冲击环 + 八向黄色火花(t 驱动,顿帧时冻住) */}
239
- {HITS_T.map((hit, i) => {
240
- const s = t - hit;
241
- if (s < 0 || s > 16) return null;
242
- const ring = ramp(t, hit, 14, EASE.out);
243
- const grow = mix(0, 46 + i * 10, ring);
244
- const x0 = SLOT_XS[i];
245
- const cx = x0 + SLOT_W / 2;
246
- const cy = SLOT_Y + SLOT_H / 2;
247
- const burst = ramp(t, hit, 12, EASE.snappy);
248
- const n = 10 + i * 3; // 火花逐击加码
249
- return (
250
- <React.Fragment key={`fx-${i}`}>
251
- <div
252
- style={{
253
- position: 'absolute', left: x0 - grow, top: SLOT_Y - grow * 0.7, width: SLOT_W + grow * 2, height: SLOT_H + grow * 1.4,
254
- borderRadius: 26 + grow * 0.6, boxSizing: 'border-box', border: `${mix(5, 1, ring).toFixed(2)}px solid #ffffff`, opacity: (1 - ring) * 0.8,
255
- }}
256
- />
257
- <svg width={1920} height={1080} style={{ position: 'absolute', left: 0, top: 0, overflow: 'visible' }}>
258
- {Array.from({ length: n }, (_, k) => {
259
- const ang = (k / n) * Math.PI * 2 + hash(i * 31 + k) * 0.4;
260
- const rx = SLOT_W * 0.52;
261
- const ry = SLOT_H * 0.56;
262
- const r0 = mix(1, 1.08 + hash(k + i * 7) * 0.15, burst);
263
- const r1 = mix(1.04, 1.3 + hash(k * 3 + i) * 0.35 + i * 0.06, Math.min(1, burst * 1.2));
264
- return (
265
- <line
266
- key={k}
267
- x1={cx + Math.cos(ang) * rx * r0} y1={cy + Math.sin(ang) * ry * r0}
268
- x2={cx + Math.cos(ang) * rx * r1} y2={cy + Math.sin(ang) * ry * r1}
269
- stroke={k % 3 === 0 ? '#ffffff' : C.hit} strokeWidth={mix(7, 2, burst)} strokeLinecap="round"
270
- opacity={Math.min(1, burst * 6) * (1 - burst)}
271
- />
272
- );
273
- })}
274
- </svg>
275
- </React.Fragment>
276
- );
277
- })}
278
-
279
- {/* 伤害数字:黄色斜体 + 漫画式硬投影 */}
280
- {HITS_T.map((hit, i) => {
281
- const s = t - hit;
282
- if (s < 0 || s > 17) return null;
283
- const scale = mix(1.45, 1, ramp(t, hit, 5, EASE.snappy));
284
- const rise = mix(0, -150, ramp(t, hit, 16, EASE.out));
285
- const opacity = s < 4 ? 1 : 1 - ramp(t, hit + 4, 12, EASE.swift);
286
- return (
287
- <div
288
- key={`dmg-${i}`}
289
- style={{
290
- // 落点在卡面中下部(打在目标身上),上浮出卡沿:不与右上角计数器抢位置
291
- position: 'absolute', left: SLOT_XS[i] + SLOT_W / 2, top: SLOT_Y + SLOT_H * 0.62 - DMG_SIZE[i] + rise,
292
- transform: `translateX(-50%) scale(${scale.toFixed(3)}) skewX(-8deg)`, transformOrigin: 'center bottom', opacity,
293
- ...type(DMG_SIZE[i], 900), fontStyle: 'italic', letterSpacing: '-0.04em', lineHeight: 1, color: C.hit, whiteSpace: 'nowrap',
294
- textShadow: `6px 6px 0 ${C.deep}`,
295
- }}
296
- >
297
- {DMG[i]}
298
- </div>
299
- );
300
- })}
301
-
302
- {/* 右上角 combo 计数器 */}
303
- <div
304
- style={{
305
- position: 'absolute', right: 120, top: 64, width: 400, height: 280,
306
- transform: `scale(${cScale.toFixed(4)}) rotate(${cRot}deg)`, transformOrigin: '90% 20%',
307
- display: 'flex', flexDirection: 'column', alignItems: 'flex-end',
308
- }}
309
- >
310
- <div style={{ ...type(26, 800, { caps: true }), letterSpacing: '0.3em', color: count ? '#ffffff' : alpha('#ffffff', 0.4), fontStyle: 'italic' }}>Combo</div>
311
- <div
312
- style={{
313
- ...type(cSize, 900), fontStyle: 'italic', letterSpacing: '-0.05em', lineHeight: 0.9, whiteSpace: 'nowrap',
314
- color: count ? C.hit : alpha('#ffffff', 0.22), textShadow: count ? `7px 7px 0 ${C.deep}` : 'none',
315
- transform: `translateY(${(-stamp * 0.14 * cSize).toFixed(1)}px) skewX(-6deg)`, marginTop: 6,
316
- }}
317
- >
318
- ×{count}
319
- </div>
320
- <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
321
- {[0, 1, 2].map((k) => (
322
- <div key={k} style={{ width: 56, height: 10, borderRadius: 5, background: k < count ? C.hit : alpha('#ffffff', 0.18), boxShadow: k < count ? `3px 3px 0 ${C.deep}` : 'none' }} />
323
- ))}
324
- </div>
325
- </div>
326
-
327
- {/* 收尾:真实收益 */}
328
- <div style={{ position: 'absolute', left: 0, right: 0, top: 866, textAlign: 'center' }}>
329
- <TextReveal
330
- text="Up to a week back on every promo."
331
- by="word"
332
- variant="rise"
333
- start={HITS_REAL[2] + 14}
334
- each={18}
335
- gap={3}
336
- style={{ ...type(60, 760), letterSpacing: '-0.03em', color: '#ffffff' }}
337
- unitStyle={(k) => (k === 2 || k === 3 ? { color: C.hit } : {})}
338
- />
339
- </div>
340
-
341
- <Vignette strength={0.42} inner={0.45} color={C.deep} />
342
- <Grain opacity={0.07} blend="soft-light" />
343
- </AbsoluteFill>
344
- );
345
- };
1
+ // hit-counter 连招计数:三张功能卡接连砸入槽位,每次命中 = 全局顿帧 2f + 落点伤害数字上浮渐隐
2
+ // + 右上角 ×N combo 跳字(脉冲 / 倾斜 / 字号逐次加码)。组合:hitstop + damage-number-pop + combo-counter。
3
+ //
4
+ // 第二轮重设计(钴蓝街机海报 · 构建工具更新日):
5
+ // - look = custom「cobalt arcade」:满版高饱和钴蓝色场(不是深海军蓝暗场)+ 白卡 + 街机黄。
6
+ // 格斗游戏 combo UI 的语言直接拿来讲"功能连招":伤害数字是黄色斜体 900 字重 + 硬投影(漫画式错位影),
7
+ // 计数器是 150→210px 的斜体「×N」,底下三格热度条逐格点亮。
8
+ // - 内容:video-shotcraft 的三项能力,每一击的"伤害"= 做一支宣传片省下的制作时间(−2 h / −1 day / −3 days,示意值),
9
+ // 三击打完收尾一行「Up to a week back on every promo.」——游戏梗落到真实收益上。
10
+ // - 顿帧是全局的:背景斜纹滚动、浮尘、卡片、特效全部由同一个 remap 时间 t 驱动,命中时整幅画面一起冻 2f;
11
+ // 只有卡面闪白与槽位受光用真实帧(冻结期间也要发生)。
12
+ // - 触地:卡按速度竖向拉伸 + 运动模糊 → 触地压扁回弹(指数回落)→ 白色冲击环外扩 + 黄色火花八向迸射 + 槽底受光。
13
+ //
14
+ // 时间表(动画时间 t,30fps;真实帧 = t + 已冻结帧):
15
+ // 0–22 建立:钴蓝场、三个虚线槽位(01/02/03)、眉题、暗色 ×0 计数器
16
+ // 20/48/76 → 30/58/86 三张卡各 10f ease-in(quad) 砸落(间隔 28f 的均匀连招节拍)
17
+ // 每命中 全局顿帧 2f;伤害数字打在卡面上 scale 1.45→1 + 上浮 150px 出卡沿,4f 后 12f 渐隐;计数器 exp(−t/2.4) 回落
18
+ // 100–124 收尾行逐词升起,"a week" 用街机黄
19
+ // 124–176 hold:背景斜纹极缓滚动,干净海报
20
+ import React from 'react';
21
+ import { AbsoluteFill, useCurrentFrame } from 'remotion';
22
+ import { EASE, FONT, Grain, SpeedBlur, Vignette, bezier, mix, ramp } from '../../_fixtures/Polish';
23
+ import { TextReveal, alpha, type } from '../../_fixtures/Look';
24
+ import { BRAND, ShotcraftMark } from '../../_fixtures/Brand';
25
+
26
+ export const HIT_COUNTER_DURATION = 176;
27
+
28
+ // 自定义 look「cobalt arcade」
29
+ const C = {
30
+ bg0: '#1b3fd6', bg1: '#1230b0', bg2: '#0a1d78',
31
+ card: '#f7f8ff', ink: '#0b1240', ink2: '#4a5488', ink3: '#8a93bf',
32
+ hit: '#ffd23f', // 街机黄:只给伤害数字 / 计数器 / 火花 / 关键收益
33
+ deep: '#06104a', // 硬投影色
34
+ };
35
+
36
+ const HITS_T = [30, 58, 86]; // 命中时刻(动画时间)
37
+ const STOP = 2; // 每次顿帧帧数
38
+ const HITS_REAL = HITS_T.map((h, i) => h + i * STOP); // 真实命中帧 = 动画命中帧 + 已冻结帧
39
+
40
+ const SLOT_W = 480;
41
+ const SLOT_H = 330;
42
+ const SLOT_Y = 446;
43
+ const GAP = 60;
44
+ const SLOT_XS = [0, 1, 2].map((i) => 960 - (SLOT_W * 3 + GAP * 2) / 2 + i * (SLOT_W + GAP));
45
+ const DROP_FROM = -460;
46
+ const inQuad = bezier(0.55, 0.085, 0.68, 0.53);
47
+
48
+ const DMG = ['−2 h', '−1 day', '−3 days'];
49
+ const DMG_SIZE = [88, 104, 124]; // 伤害数字逐击加大
50
+ const PULSE = [1.3, 1.45, 1.6];
51
+ const TILT = [-2, -4, -6];
52
+ const COUNTER_SIZE = [140, 166, 196];
53
+
54
+ const FEATURES = [
55
+ { icon: 'recipe', name: 'Shot recipes', desc: 'Pick a move, not a blank canvas.', note: 'per shot' },
56
+ { icon: 'beat', name: 'Beat-synced cuts', desc: 'Every cut lands on the music.', note: 'per edit' },
57
+ { icon: 'layers', name: '2.5D camera', desc: 'Real pages, filmed in depth.', note: 'per promo' },
58
+ ];
59
+
60
+ const Icon: React.FC<{ name: string }> = ({ name }) => {
61
+ const sw = { fill: 'none', stroke: C.bg1, strokeWidth: 2, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
62
+ return (
63
+ <svg width={34} height={34} viewBox="0 0 24 24">
64
+ {/* 镜头配方卡 */}
65
+ {name === 'recipe' && (
66
+ <>
67
+ <rect x="4" y="3.5" width="16" height="17" rx="2.5" {...sw} />
68
+ <path d="M8 8.5h8M8 12h8M8 15.5h5" {...sw} />
69
+ </>
70
+ )}
71
+ {/* 踩点:波形 */}
72
+ {name === 'beat' && <path d="M3 12h1.5M7 8.5v7M11 4.5v15M15 8v8M19 10.5v3M21 12h0.5" {...sw} />}
73
+ {/* 2.5D:层叠景深 */}
74
+ {name === 'layers' && (
75
+ <>
76
+ <path d="M3 8.5L12 4l9 4.5-9 4.5-9-4.5z" {...sw} />
77
+ <path d="M3 12.5l9 4.5 9-4.5M3 16.5L12 21l9-4.5" {...sw} />
78
+ </>
79
+ )}
80
+ </svg>
81
+ );
82
+ };
83
+
84
+ // saved = 伤害数字飘走后,收益「落」进卡片页脚的进度(0–1)
85
+ const FeatureCard: React.FC<{ i: number; elev: number; saved: number }> = ({ i, elev, saved }) => {
86
+ const f = FEATURES[i];
87
+ return (
88
+ <div
89
+ style={{
90
+ width: SLOT_W, height: SLOT_H, boxSizing: 'border-box', borderRadius: 26, padding: '34px 38px 32px',
91
+ background: `linear-gradient(180deg, #ffffff 0%, ${C.card} 100%)`,
92
+ boxShadow: `inset 0 1px 0 #fff, 0 ${(2 + elev * 0.4).toFixed(1)}px ${(4 + elev * 0.6).toFixed(1)}px ${alpha(C.deep, 0.25)}, 0 ${(10 + elev * 0.8).toFixed(1)}px ${(30 + elev * 1.4).toFixed(1)}px -8px ${alpha(C.deep, 0.5)}`,
93
+ display: 'flex', flexDirection: 'column', fontFamily: FONT.sans, color: C.ink,
94
+ }}
95
+ >
96
+ <div style={{ display: 'flex', alignItems: 'center' }}>
97
+ <div style={{ width: 62, height: 62, borderRadius: 18, background: alpha(C.bg0, 0.1), display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
98
+ <Icon name={f.icon} />
99
+ </div>
100
+ <div style={{ marginLeft: 'auto', ...type(26, 600, { mono: true }), color: C.ink3 }}>0{i + 1}</div>
101
+ </div>
102
+ <div style={{ marginTop: 30, ...type(48, 760), letterSpacing: '-0.035em', lineHeight: 1.02 }}>{f.name}</div>
103
+ <div style={{ marginTop: 12, ...type(30, 450), lineHeight: 1.3, color: C.ink2 }}>{f.desc}</div>
104
+ <div
105
+ style={{
106
+ marginTop: 'auto', paddingTop: 18, borderTop: `1px solid ${alpha(C.ink, 0.1)}`, display: 'flex', alignItems: 'baseline',
107
+ opacity: saved, transform: `translateY(${mix(10, 0, saved).toFixed(1)}px)`,
108
+ }}
109
+ >
110
+ <span style={{ ...type(32, 800), fontStyle: 'italic', letterSpacing: '-0.02em', color: C.bg1 }}>{DMG[i]}</span>
111
+ <span style={{ marginLeft: 'auto', ...type(26, 500), color: C.ink3 }}>{f.note}</span>
112
+ </div>
113
+ </div>
114
+ );
115
+ };
116
+
117
+ const dropY = (t: number, hit: number) => mix(DROP_FROM, SLOT_Y, ramp(t, hit - 10, 10, inQuad));
118
+
119
+ const hash = (n: number) => {
120
+ const x = Math.sin(n * 127.1 + 311.7) * 43758.5453;
121
+ return x - Math.floor(x);
122
+ };
123
+
124
+ export const HitCounter: React.FC = () => {
125
+ const frame = useCurrentFrame();
126
+
127
+ // —— 全局帧 remap:每个真实命中帧起冻结 2f ——
128
+ const remap = (fr: number) => {
129
+ let t = fr;
130
+ for (const h of HITS_REAL) t -= Math.min(Math.max(fr - h, 0), STOP);
131
+ return t;
132
+ };
133
+ const t = remap(frame);
134
+ const count = HITS_T.filter((h) => t >= h).length;
135
+
136
+ // —— 计数器 ——
137
+ let cScale = 1;
138
+ let cRot = 0;
139
+ let cSize = 130;
140
+ if (count > 0) {
141
+ const i = count - 1;
142
+ const since = t - HITS_T[i];
143
+ cScale = 1 + (PULSE[i] - 1) * Math.exp(-since / 2.4);
144
+ cRot = TILT[i];
145
+ cSize = COUNTER_SIZE[i];
146
+ }
147
+ const stamp = count > 0 ? 1 - ramp(t, HITS_T[count - 1], 7, EASE.out) : 0;
148
+
149
+ // 背景斜纹滚动(t 驱动 → 顿帧时一起冻住)
150
+ const stripeShift = t * 2.2;
151
+
152
+ return (
153
+ <AbsoluteFill style={{ overflow: 'hidden', fontFamily: FONT.sans, background: `linear-gradient(170deg, ${C.bg0} 0%, ${C.bg1} 55%, ${C.bg2} 100%)` }}>
154
+ {/* 背景:主光 + 斜纹(速度线的静态版)+ 网点 */}
155
+ <div style={{ position: 'absolute', inset: 0, background: `radial-gradient(ellipse 60% 55% at 38% 30%, ${alpha('#6f8dff', 0.45)} 0%, ${alpha('#6f8dff', 0)} 70%)` }} />
156
+ <div
157
+ style={{
158
+ position: 'absolute', inset: -200, opacity: 0.1,
159
+ backgroundImage: 'repeating-linear-gradient(-58deg, #ffffff 0px, #ffffff 2px, transparent 2px, transparent 46px)',
160
+ transform: `translateX(${(stripeShift % 54.2).toFixed(2)}px)`,
161
+ }}
162
+ />
163
+ <div
164
+ style={{
165
+ position: 'absolute', inset: 0, opacity: 0.14,
166
+ backgroundImage: `radial-gradient(circle, ${C.deep} 1.4px, transparent 1.6px)`, backgroundSize: '18px 18px',
167
+ WebkitMaskImage: 'linear-gradient(180deg, transparent 40%, #000 100%)', maskImage: 'linear-gradient(180deg, transparent 40%, #000 100%)',
168
+ }}
169
+ />
170
+
171
+ {/* 眉题 */}
172
+ <div style={{ position: 'absolute', left: 120, top: 104, display: 'flex', alignItems: 'center', gap: 18, opacity: ramp(frame, 0, 14, EASE.out) }}>
173
+ <ShotcraftMark size={52} tone="dark" />
174
+ <div style={{ ...type(34, 760), color: '#fff', letterSpacing: '-0.02em' }}>{BRAND.name}</div>
175
+ <div style={{ ...type(24, 650, { caps: true }), color: alpha('#ffffff', 0.62), letterSpacing: '0.24em', marginLeft: 8 }}>What’s new</div>
176
+ </div>
177
+
178
+ {/* 槽位:虚线 + 大号序号,建立期就立预期 */}
179
+ {SLOT_XS.map((x, i) => {
180
+ const near = ramp(t, HITS_T[i] - 10, 10, inQuad);
181
+ const df = frame - HITS_REAL[i];
182
+ const glowA = df >= 0 ? Math.exp(-df / 6) : 0; // 槽底受光(真实帧)
183
+ return (
184
+ <React.Fragment key={`slot-${i}`}>
185
+ <div
186
+ style={{
187
+ position: 'absolute', left: x, top: SLOT_Y, width: SLOT_W, height: SLOT_H, borderRadius: 26, boxSizing: 'border-box',
188
+ border: `2px dashed ${alpha('#ffffff', 0.28)}`, background: alpha(C.deep, 0.16),
189
+ display: 'flex', alignItems: 'center', justifyContent: 'center',
190
+ ...type(120, 800), color: alpha('#ffffff', 0.1), letterSpacing: '-0.04em',
191
+ }}
192
+ >
193
+ 0{i + 1}
194
+ </div>
195
+ {near > 0 && t < HITS_T[i] && (
196
+ <div
197
+ style={{
198
+ position: 'absolute', left: x + 40 - (1 - near) * 40, top: SLOT_Y + 50, width: SLOT_W - 80 + (1 - near) * 80, height: SLOT_H - 40,
199
+ borderRadius: 30, background: C.deep, filter: `blur(${mix(44, 16, near).toFixed(1)}px)`, opacity: mix(0.05, 0.5, near),
200
+ }}
201
+ />
202
+ )}
203
+ {glowA > 0.02 && (
204
+ <div
205
+ style={{
206
+ position: 'absolute', left: x - 120, top: SLOT_Y + SLOT_H - 80, width: SLOT_W + 240, height: 200, borderRadius: '50%',
207
+ background: `radial-gradient(ellipse 50% 50% at 50% 50%, ${alpha(C.hit, 0.45 * glowA)} 0%, ${alpha(C.hit, 0)} 70%)`,
208
+ }}
209
+ />
210
+ )}
211
+ </React.Fragment>
212
+ );
213
+ })}
214
+
215
+ {/* 三张功能卡 */}
216
+ {HITS_T.map((hit, i) => {
217
+ if (t < hit - 10) return null;
218
+ const y = dropY(t, hit);
219
+ const vy = t < hit ? dropY(t + 0.5, hit) - dropY(t - 0.5, hit) : 0;
220
+ const speed = Math.min(1, vy / 200);
221
+ const s = t - hit;
222
+ const squash = s >= 0 ? 0.07 * Math.exp(-s / 1.6) : 0;
223
+ const sy = 1 + speed * 0.06 - squash;
224
+ const sx = 1 - speed * 0.025 + squash * 0.5;
225
+ const elev = s >= 0 ? 6 : mix(6, 60, (SLOT_Y - y) / (SLOT_Y - DROP_FROM));
226
+ const df = frame - HITS_REAL[i];
227
+ const flash = df >= 0 && df < STOP + 4 ? (df < STOP ? 0.7 : 0.7 * (1 - (df - STOP + 1) / 5)) : 0;
228
+ return (
229
+ <SpeedBlur key={`card-${i}`} vx={0} vy={vy} amount={0.12} max={24}>
230
+ <div style={{ position: 'absolute', left: SLOT_XS[i], top: y, transform: `scale(${sx.toFixed(4)}, ${sy.toFixed(4)})`, transformOrigin: 'bottom center' }}>
231
+ <FeatureCard i={i} elev={elev} saved={ramp(t, hit + 12, 12, EASE.snappy)} />
232
+ {flash > 0 && <div style={{ position: 'absolute', inset: 0, borderRadius: 26, background: '#ffffff', opacity: flash }} />}
233
+ </div>
234
+ </SpeedBlur>
235
+ );
236
+ })}
237
+
238
+ {/* 触地冲击:白色冲击环 + 八向黄色火花(t 驱动,顿帧时冻住) */}
239
+ {HITS_T.map((hit, i) => {
240
+ const s = t - hit;
241
+ if (s < 0 || s > 16) return null;
242
+ const ring = ramp(t, hit, 14, EASE.out);
243
+ const grow = mix(0, 46 + i * 10, ring);
244
+ const x0 = SLOT_XS[i];
245
+ const cx = x0 + SLOT_W / 2;
246
+ const cy = SLOT_Y + SLOT_H / 2;
247
+ const burst = ramp(t, hit, 12, EASE.snappy);
248
+ const n = 10 + i * 3; // 火花逐击加码
249
+ return (
250
+ <React.Fragment key={`fx-${i}`}>
251
+ <div
252
+ style={{
253
+ position: 'absolute', left: x0 - grow, top: SLOT_Y - grow * 0.7, width: SLOT_W + grow * 2, height: SLOT_H + grow * 1.4,
254
+ borderRadius: 26 + grow * 0.6, boxSizing: 'border-box', border: `${mix(5, 1, ring).toFixed(2)}px solid #ffffff`, opacity: (1 - ring) * 0.8,
255
+ }}
256
+ />
257
+ <svg width={1920} height={1080} style={{ position: 'absolute', left: 0, top: 0, overflow: 'visible' }}>
258
+ {Array.from({ length: n }, (_, k) => {
259
+ const ang = (k / n) * Math.PI * 2 + hash(i * 31 + k) * 0.4;
260
+ const rx = SLOT_W * 0.52;
261
+ const ry = SLOT_H * 0.56;
262
+ const r0 = mix(1, 1.08 + hash(k + i * 7) * 0.15, burst);
263
+ const r1 = mix(1.04, 1.3 + hash(k * 3 + i) * 0.35 + i * 0.06, Math.min(1, burst * 1.2));
264
+ return (
265
+ <line
266
+ key={k}
267
+ x1={cx + Math.cos(ang) * rx * r0} y1={cy + Math.sin(ang) * ry * r0}
268
+ x2={cx + Math.cos(ang) * rx * r1} y2={cy + Math.sin(ang) * ry * r1}
269
+ stroke={k % 3 === 0 ? '#ffffff' : C.hit} strokeWidth={mix(7, 2, burst)} strokeLinecap="round"
270
+ opacity={Math.min(1, burst * 6) * (1 - burst)}
271
+ />
272
+ );
273
+ })}
274
+ </svg>
275
+ </React.Fragment>
276
+ );
277
+ })}
278
+
279
+ {/* 伤害数字:黄色斜体 + 漫画式硬投影 */}
280
+ {HITS_T.map((hit, i) => {
281
+ const s = t - hit;
282
+ if (s < 0 || s > 17) return null;
283
+ const scale = mix(1.45, 1, ramp(t, hit, 5, EASE.snappy));
284
+ const rise = mix(0, -150, ramp(t, hit, 16, EASE.out));
285
+ const opacity = s < 4 ? 1 : 1 - ramp(t, hit + 4, 12, EASE.swift);
286
+ return (
287
+ <div
288
+ key={`dmg-${i}`}
289
+ style={{
290
+ // 落点在卡面中下部(打在目标身上),上浮出卡沿:不与右上角计数器抢位置
291
+ position: 'absolute', left: SLOT_XS[i] + SLOT_W / 2, top: SLOT_Y + SLOT_H * 0.62 - DMG_SIZE[i] + rise,
292
+ transform: `translateX(-50%) scale(${scale.toFixed(3)}) skewX(-8deg)`, transformOrigin: 'center bottom', opacity,
293
+ ...type(DMG_SIZE[i], 900), fontStyle: 'italic', letterSpacing: '-0.04em', lineHeight: 1, color: C.hit, whiteSpace: 'nowrap',
294
+ textShadow: `6px 6px 0 ${C.deep}`,
295
+ }}
296
+ >
297
+ {DMG[i]}
298
+ </div>
299
+ );
300
+ })}
301
+
302
+ {/* 右上角 combo 计数器 */}
303
+ <div
304
+ style={{
305
+ position: 'absolute', right: 120, top: 64, width: 400, height: 280,
306
+ transform: `scale(${cScale.toFixed(4)}) rotate(${cRot}deg)`, transformOrigin: '90% 20%',
307
+ display: 'flex', flexDirection: 'column', alignItems: 'flex-end',
308
+ }}
309
+ >
310
+ <div style={{ ...type(26, 800, { caps: true }), letterSpacing: '0.3em', color: count ? '#ffffff' : alpha('#ffffff', 0.4), fontStyle: 'italic' }}>Combo</div>
311
+ <div
312
+ style={{
313
+ ...type(cSize, 900), fontStyle: 'italic', letterSpacing: '-0.05em', lineHeight: 0.9, whiteSpace: 'nowrap',
314
+ color: count ? C.hit : alpha('#ffffff', 0.22), textShadow: count ? `7px 7px 0 ${C.deep}` : 'none',
315
+ transform: `translateY(${(-stamp * 0.14 * cSize).toFixed(1)}px) skewX(-6deg)`, marginTop: 6,
316
+ }}
317
+ >
318
+ ×{count}
319
+ </div>
320
+ <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
321
+ {[0, 1, 2].map((k) => (
322
+ <div key={k} style={{ width: 56, height: 10, borderRadius: 5, background: k < count ? C.hit : alpha('#ffffff', 0.18), boxShadow: k < count ? `3px 3px 0 ${C.deep}` : 'none' }} />
323
+ ))}
324
+ </div>
325
+ </div>
326
+
327
+ {/* 收尾:真实收益 */}
328
+ <div style={{ position: 'absolute', left: 0, right: 0, top: 866, textAlign: 'center' }}>
329
+ <TextReveal
330
+ text="Up to a week back on every promo."
331
+ by="word"
332
+ variant="rise"
333
+ start={HITS_REAL[2] + 14}
334
+ each={18}
335
+ gap={3}
336
+ style={{ ...type(60, 760), letterSpacing: '-0.03em', color: '#ffffff' }}
337
+ unitStyle={(k) => (k === 2 || k === 3 ? { color: C.hit } : {})}
338
+ />
339
+ </div>
340
+
341
+ <Vignette strength={0.42} inner={0.45} color={C.deep} />
342
+ <Grain opacity={0.07} blend="soft-light" />
343
+ </AbsoluteFill>
344
+ );
345
+ };