dsh-drawai 0.4.1 → 0.4.3

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 (365) hide show
  1. package/README.md +96 -253
  2. package/lib/client.js +28 -7
  3. package/lib/index.js +474 -97
  4. package/lib/motion/asset-pack.js +109 -50
  5. package/lib/motion/assets.js +291 -291
  6. package/lib/motion/demo-assets-lock.js +10 -0
  7. package/lib/motion/mgstyles/vendor/README.md +28 -0
  8. package/lib/motion/mgstyles/vendor/modules/d3/LICENSE +13 -0
  9. package/lib/motion/mgstyles/vendor/modules/d3/dist/d3.min.js +2 -0
  10. package/lib/motion/mgstyles/vendor/modules/opentype.js/LICENSE +20 -0
  11. package/lib/motion/mgstyles/vendor/modules/opentype.js/dist/opentype.mjs +14460 -0
  12. package/lib/motion/mgstyles/vendor/modules/simplex-noise/LICENSE +21 -0
  13. package/lib/motion/mgstyles/vendor/modules/simplex-noise/dist/esm/simplex-noise.js +466 -0
  14. package/lib/motion/mgstyles/vendor/modules/topojson-client/LICENSE +13 -0
  15. package/lib/motion/mgstyles/vendor/modules/topojson-client/dist/topojson-client.min.js +2 -0
  16. package/lib/motion/preview.js +10 -3
  17. package/lib/motion/render.js +19 -1
  18. package/lib/motion/shotcraft/upstream/SKILL.md +286 -286
  19. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -54
  20. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -200
  21. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -45
  22. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -20
  23. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -65
  24. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -151
  25. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -129
  26. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -75
  27. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -40
  28. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -11
  29. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -10
  30. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -49
  31. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -210
  32. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -423
  33. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -170
  34. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -157
  35. package/lib/motion/shotcraft/upstream/demos/README.md +120 -120
  36. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -112
  37. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -647
  38. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -316
  39. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -82
  40. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -115
  41. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -243
  42. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +388 -388
  43. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -250
  44. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -305
  45. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -246
  46. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -390
  47. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -138
  48. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -542
  49. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -315
  50. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -299
  51. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -173
  52. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -348
  53. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -366
  54. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -279
  55. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -184
  56. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -390
  57. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -155
  58. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -303
  59. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -290
  60. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -278
  61. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -307
  62. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -215
  63. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -299
  64. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -232
  65. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -290
  66. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -273
  67. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -167
  68. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -536
  69. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -164
  70. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -175
  71. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -197
  72. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -241
  73. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -279
  74. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -230
  75. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -345
  76. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -275
  77. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -229
  78. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -312
  79. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -222
  80. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -295
  81. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -329
  82. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -315
  83. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -264
  84. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -260
  85. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -263
  86. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -123
  87. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -187
  88. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -175
  89. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -305
  90. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -350
  91. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -352
  92. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -218
  93. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -297
  94. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -157
  95. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -218
  96. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -202
  97. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -265
  98. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -457
  99. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -446
  100. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -249
  101. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -278
  102. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -332
  103. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -358
  104. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -201
  105. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -200
  106. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -208
  107. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -341
  108. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -389
  109. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -293
  110. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -183
  111. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -245
  112. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -222
  113. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -223
  114. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -217
  115. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -343
  116. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -357
  117. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -187
  118. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -333
  119. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -274
  120. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -270
  121. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -430
  122. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -252
  123. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -106
  124. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -288
  125. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -362
  126. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -168
  127. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -310
  128. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -261
  129. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -459
  130. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -294
  131. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -161
  132. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -248
  133. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -359
  134. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -227
  135. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -162
  136. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -248
  137. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -186
  138. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -355
  139. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -272
  140. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -262
  141. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -217
  142. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -285
  143. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -205
  144. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -178
  145. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -147
  146. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -143
  147. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -134
  148. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -217
  149. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -198
  150. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -221
  151. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -312
  152. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -261
  153. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -121
  154. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -153
  155. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -179
  156. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -140
  157. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -309
  158. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -191
  159. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -292
  160. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -135
  161. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -124
  162. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -255
  163. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -173
  164. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -225
  165. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -141
  166. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -137
  167. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -147
  168. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -409
  169. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -280
  170. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -271
  171. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -385
  172. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -312
  173. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -303
  174. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -77
  175. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -311
  176. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -307
  177. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -349
  178. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -255
  179. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -244
  180. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -217
  181. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -652
  182. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -153
  183. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -238
  184. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -324
  185. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -354
  186. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -101
  187. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -129
  188. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -297
  189. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -57
  190. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -155
  191. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -175
  192. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -153
  193. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -146
  194. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -226
  195. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -1
  196. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -193
  197. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -121
  198. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -199
  199. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -183
  200. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -257
  201. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -382
  202. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -111
  203. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -50
  204. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -95
  205. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -41
  206. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -52
  207. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -39
  208. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -39
  209. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -57
  210. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -51
  211. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -46
  212. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -52
  213. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -43
  214. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -42
  215. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -48
  216. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -52
  217. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -45
  218. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -46
  219. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -44
  220. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -63
  221. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -54
  222. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -58
  223. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -35
  224. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -53
  225. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -42
  226. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -50
  227. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -46
  228. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -56
  229. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -49
  230. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -50
  231. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -53
  232. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -53
  233. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -55
  234. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -52
  235. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -60
  236. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -57
  237. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -51
  238. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -41
  239. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -53
  240. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -60
  241. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -55
  242. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -57
  243. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -47
  244. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -37
  245. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -54
  246. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -36
  247. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -56
  248. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -56
  249. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -40
  250. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -60
  251. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -57
  252. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -73
  253. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -87
  254. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -55
  255. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -50
  256. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -59
  257. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -38
  258. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -38
  259. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -59
  260. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -39
  261. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -61
  262. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -52
  263. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -50
  264. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -66
  265. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -43
  266. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -38
  267. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -38
  268. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -56
  269. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -44
  270. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -38
  271. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -63
  272. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -57
  273. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -63
  274. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -58
  275. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -45
  276. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -55
  277. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -49
  278. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -42
  279. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -42
  280. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -45
  281. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -48
  282. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -55
  283. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -43
  284. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -41
  285. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -42
  286. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -59
  287. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -55
  288. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -65
  289. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -42
  290. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -64
  291. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -64
  292. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -54
  293. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -91
  294. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -51
  295. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -66
  296. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -38
  297. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -66
  298. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -58
  299. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -61
  300. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -64
  301. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -45
  302. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -41
  303. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -51
  304. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -42
  305. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -63
  306. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -57
  307. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -75
  308. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -59
  309. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -67
  310. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -60
  311. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -66
  312. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -40
  313. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -45
  314. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -62
  315. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -55
  316. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -37
  317. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -55
  318. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -50
  319. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -43
  320. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -55
  321. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -51
  322. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -51
  323. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -56
  324. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -49
  325. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -57
  326. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -36
  327. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -64
  328. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -47
  329. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -170
  330. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -157
  331. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -103
  332. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -44
  333. package/lib/motion/shotcraft/upstream/template/package.json +20 -20
  334. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -6
  335. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -17
  336. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -65
  337. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -48
  338. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -24
  339. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -192
  340. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -111
  341. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -150
  342. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -158
  343. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -468
  344. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -552
  345. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -411
  346. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -200
  347. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -324
  348. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +388 -388
  349. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -4
  350. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -7
  351. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -68
  352. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -1
  353. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -24
  354. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -74
  355. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -91
  356. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -213
  357. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -15
  358. package/lib/motion/style-frames.js +47 -12
  359. package/lib/motion-project.js +22 -3
  360. package/lib/motion-render-worker.js +31 -9
  361. package/lib/routing/router.js +12 -1
  362. package/lib/style-kernel.js +16 -6
  363. package/lib/video-trace-pool.js +128 -128
  364. package/package.json +1 -1
  365. package/LICENSE +0 -4175
@@ -1,312 +1,312 @@
1
- // radial-ripple-phone-chips — 同心波纹手机:四层同心圆错相呼吸如水波,中央手机屏内 feed 自动缓滚,
2
- // 两侧 chip 先后 spring pop 入场并悬浮。三层动作各自极慢,叠起来让产品定格镜头"活着"。
3
- //
4
- // 第二轮重设计(暖沙 · 手机上的 video-shotcraft 镜头库):
5
- // - look = sand。同心圆是四层由深到浅的暖沙色圆盘(2240/1760/1280/840px,铺满画面并出画),
6
- // 每层有受光上沿与发丝外缘,像沙地上被风吹出的一圈圈涟漪 / 声波;中心一团暖白柔光托住手机。
7
- // - 主体:按 1080p 原生尺寸搭的手机(430×900,占画高 83%),暖钛金属边框 + 黑边 + 灵动岛 + 侧键 +
8
- // 玻璃斜反光 + 两层落地投影。屏内是为镜头设计的镜头配方 feed:大标题「Shot library」、带几何插画缩略图的
9
- // 镜头卡(镜头名 / 分类 / 时长 / 预览进度)、底部常驻迷你预览条(成片配乐在走、波形在跳)。
10
- // feed 匀速自动滚动(自动播放语义,不加缓动)。
11
- // - 两侧 chip:白色大胶囊(36px 字 + 赤陶色图标圆),从手机侧边弹出(spring 过冲一次),
12
- // 落位后才渐渐介入 ±8px 的悬浮;左「Shot recipe cards」先、右「Remotion render」后,错开 30f。
13
- // - 收尾海报:左下角镜刻标志 + 字标「video-shotcraft — Every shot, tuned in one place.」在两枚 chip 都落定后升起。
14
- //
15
- // 时间表(30fps,共 168f):
16
- // 0–26 预备:同心圆第 1 帧就在呼吸;手机从下方 90px 升起落位(snappy,投影同步收紧)
17
- // 13–165 feed 匀速滚动 0→−560px(t 0.08→0.98);迷你播放条进度匀速推进
18
- // 37–57 左 chip pop(spring damping 13,scale 0.8→1 + 从手机侧边外移 28px)
19
- // 67–87 右 chip pop
20
- // 90–112 品牌字标逐词升起
21
- // 112–168 hold:同心圆、feed、chip 悬浮持续极缓运动(无死帧,不加手持抖动)
22
- import React from 'react';
23
- import { useCurrentFrame } from 'remotion';
24
- import { EASE, FONT, ramp } from '../../_fixtures/Polish';
25
- import { LOOKS, Stage, TextReveal, alpha, springAt, type } from '../../_fixtures/Look';
26
- import { BRAND, ShotcraftMark } from '../../_fixtures/Brand';
27
-
28
- export const RADIAL_RIPPLE_PHONE_CHIPS_DURATION = 168; // 5600ms @30fps
29
-
30
- const L = LOOKS.sand;
31
- const DUR = RADIAL_RIPPLE_PHONE_CHIPS_DURATION;
32
- // 模板强调色:落地时按项目品牌色只换这一个变量(屏内封面 / 进度 / chip 图标都跟它走)
33
- const ACCENT = L.accent; // 赤陶 #c4552d
34
- const SANS = FONT.sans;
35
-
36
- // 同心圆(外深内浅,从大到小叠放),相邻层相位差 1.7 rad
37
- const RINGS = [
38
- { size: 2240, color: '#dccbb4' },
39
- { size: 1760, color: '#e4d6c3' },
40
- { size: 1280, color: '#ebe0d1' },
41
- { size: 840, color: '#f2eadf' },
42
- ].map((r, i) => ({ ...r, phase: i * 1.7 }));
43
-
44
- // 手机几何(画布像素)
45
- const PW = 430;
46
- const PH = 900;
47
- const FRAME = 12; // 金属边框
48
- const BLACK = 9; // 屏幕黑边
49
- const PX = (1920 - PW) / 2;
50
- const PY = (1080 - PH) / 2;
51
- const CHIP_GAP = 64; // chip 与手机外缘的间距
52
-
53
- // 镜头库 feed(video-shotcraft 的镜头配方卡;prog = 预览进度)
54
- type Ep = { title: string; show: string; len: string; prog: number; art: number };
55
- const EPS: Ep[] = [
56
- { title: 'Graze face tour', show: 'Camera', len: '4.0 s', prog: 0.62, art: 0 },
57
- { title: 'Riso print hit', show: 'Effects', len: '4.0 s', prog: 0, art: 1 },
58
- { title: 'Text as mask', show: 'Opening', len: '3.2 s', prog: 0.18, art: 2 },
59
- { title: 'Timeline travel', show: 'Data', len: '5.0 s', prog: 0, art: 3 },
60
- { title: 'Grain dissolve', show: 'Outro', len: '3.6 s', prog: 0, art: 0 },
61
- { title: 'Cursor flyover', show: 'Camera', len: '4.8 s', prog: 0.4, art: 1 },
62
- { title: 'Logo sting', show: 'Outro', len: '3.0 s', prog: 0, art: 3 },
63
- { title: 'Exploded view', show: 'Camera', len: '5.0 s', prog: 0, art: 2 },
64
- ];
65
-
66
- // 封面插画:四套几何(太阳 / 等高线 / 圆面包 / 轨道),配色限 sand 的赤陶 + 钴蓝 + 中性
67
- const Art: React.FC<{ k: number; size: number }> = ({ k, size }) => {
68
- const s = size;
69
- const base: React.CSSProperties = { position: 'relative', width: s, height: s, borderRadius: s * 0.2, overflow: 'hidden', flex: 'none' };
70
- if (k === 0)
71
- return (
72
- <div style={{ ...base, background: `linear-gradient(160deg, ${ACCENT} 0%, #e48c5f 100%)` }}>
73
- <div style={{ position: 'absolute', left: s * 0.24, top: s * 0.2, width: s * 0.52, height: s * 0.52, borderRadius: '50%', background: '#fbe7d3' }} />
74
- <div style={{ position: 'absolute', left: -s * 0.2, right: -s * 0.2, top: s * 0.62, height: s * 0.7, borderRadius: '50%', background: '#8f3a1e' }} />
75
- </div>
76
- );
77
- if (k === 1)
78
- return (
79
- <div style={{ ...base, background: `linear-gradient(160deg, ${L.accent2} 0%, #7f9cc0 100%)` }}>
80
- {[0.9, 0.66, 0.42].map((r, i) => (
81
- <div key={i} style={{
82
- position: 'absolute', left: s * (0.5 - r / 2) + s * 0.12, top: s * (0.5 - r / 2) + s * 0.1, width: s * r, height: s * r * 0.8,
83
- borderRadius: '50%', border: `${Math.max(2, s * 0.03)}px solid rgba(255,255,255,${0.35 + i * 0.2})`, boxSizing: 'border-box',
84
- }} />
85
- ))}
86
- </div>
87
- );
88
- if (k === 2)
89
- return (
90
- <div style={{ ...base, background: 'linear-gradient(160deg, #e9dcc8 0%, #d6c3a6 100%)' }}>
91
- <div style={{ position: 'absolute', left: s * 0.16, top: s * 0.3, width: s * 0.68, height: s * 0.48, borderRadius: `${s * 0.34}px ${s * 0.34}px ${s * 0.1}px ${s * 0.1}px`, background: '#b8743f' }} />
92
- {[0, 1, 2].map((i) => (
93
- <div key={i} style={{ position: 'absolute', left: s * (0.3 + i * 0.15), top: s * 0.38, width: s * 0.05, height: s * 0.2, borderRadius: s, background: '#f3e2c8', transform: 'rotate(24deg)' }} />
94
- ))}
95
- </div>
96
- );
97
- return (
98
- <div style={{ ...base, background: 'linear-gradient(160deg, #2b231d 0%, #4a3b30 100%)' }}>
99
- <div style={{ position: 'absolute', left: 0, right: 0, top: s * 0.56, height: s * 0.06, background: ACCENT }} />
100
- <div style={{ position: 'absolute', left: 0, right: 0, top: s * 0.68, height: s * 0.03, background: alpha('#f3e2c8', 0.5) }} />
101
- <div style={{ position: 'absolute', left: s * 0.62, top: s * 0.16, width: s * 0.16, height: s * 0.16, borderRadius: '50%', background: '#f3e2c8' }} />
102
- </div>
103
- );
104
- };
105
-
106
- const Feed: React.FC = () => (
107
- <div style={{ padding: '76px 16px 0', fontFamily: SANS, color: L.ink }}>
108
- <div style={{ fontSize: 17, fontWeight: 650, letterSpacing: '0.06em', color: L.ink3, textTransform: 'uppercase', marginLeft: 4 }}>Today · 3 new shots</div>
109
- <div style={{ fontSize: 44, fontWeight: 780, letterSpacing: '-0.035em', lineHeight: 1.05, marginLeft: 2, marginTop: 4 }}>Shot library</div>
110
- {/* 精选大卡 */}
111
- <div style={{ position: 'relative', marginTop: 20, height: 210, borderRadius: 26, overflow: 'hidden', background: `linear-gradient(150deg, #3a2c22 0%, #6b4a33 100%)` }}>
112
- <div style={{ position: 'absolute', right: -40, top: -50, width: 230, height: 230, borderRadius: '50%', background: `radial-gradient(circle, ${alpha('#ffb27a', 0.9)} 0%, ${alpha(ACCENT, 0.6)} 45%, ${alpha(ACCENT, 0)} 70%)` }} />
113
- <div style={{ position: 'absolute', left: 22, top: 22, fontSize: 15, fontWeight: 700, letterSpacing: '0.1em', color: alpha('#fbe7d3', 0.7) }}>NEW RECIPE</div>
114
- <div style={{ position: 'absolute', left: 22, bottom: 50, fontSize: 30, fontWeight: 760, letterSpacing: '-0.03em', color: '#fff6ec', lineHeight: 1.05, width: 260 }}>Crash zoom punch</div>
115
- <div style={{ position: 'absolute', left: 22, bottom: 22, fontSize: 17, fontWeight: 500, color: alpha('#fbe7d3', 0.75) }}>Camera move · 2 styles · 1.2 s</div>
116
- </div>
117
- <div style={{ fontSize: 22, fontWeight: 720, letterSpacing: '-0.02em', margin: '26px 4px 12px' }}>Recipes</div>
118
- {EPS.map((e, i) => (
119
- <div key={i} style={{
120
- display: 'flex', alignItems: 'center', gap: 14, padding: 12, marginBottom: 12, borderRadius: 22,
121
- background: '#fffcf7', boxShadow: '0 0 0 1px rgba(70,45,20,0.06), 0 2px 6px rgba(58,36,16,0.05)',
122
- }}>
123
- <Art k={e.art} size={76} />
124
- <div style={{ minWidth: 0, flex: 1 }}>
125
- <div style={{ fontSize: 22, fontWeight: 680, letterSpacing: '-0.02em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', lineHeight: 1.2 }}>{e.title}</div>
126
- <div style={{ fontSize: 17, color: L.ink2, marginTop: 4, lineHeight: 1.2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{e.len} · {e.show}</div>
127
- <div style={{ marginTop: 10, height: 5, borderRadius: 3, background: '#efe6da', width: 150 }}>
128
- {e.prog > 0 && <div style={{ width: `${e.prog * 100}%`, height: '100%', borderRadius: 3, background: ACCENT }} />}
129
- </div>
130
- </div>
131
- <div style={{ width: 40, height: 40, borderRadius: 20, flex: 'none', background: e.prog > 0 ? ACCENT : '#f1e9de', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
132
- <svg width={16} height={16} viewBox="0 0 16 16"><path d="M5 3 L13 8 L5 13 Z" fill={e.prog > 0 ? '#fff8f0' : L.ink} /></svg>
133
- </div>
134
- </div>
135
- ))}
136
- </div>
137
- );
138
-
139
- // chip 图标
140
- const ChipIcon: React.FC<{ kind: 'download' | 'chapters' }> = ({ kind }) => (
141
- <div style={{ width: 60, height: 60, borderRadius: 30, flex: 'none', background: ACCENT, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: `inset 0 1px 0 ${alpha('#ffffff', 0.3)}` }}>
142
- <svg width={30} height={30} viewBox="0 0 24 24" fill="none" stroke="#fff8f0" strokeWidth={2.4} strokeLinecap="round" strokeLinejoin="round">
143
- {kind === 'download' ? (
144
- <>
145
- <path d="M12 4 V15" />
146
- <path d="M7 10.5 L12 15.5 L17 10.5" />
147
- <path d="M5 19.5 H19" />
148
- </>
149
- ) : (
150
- <>
151
- <path d="M9 6 H20 M9 12 H20 M9 18 H16" />
152
- <circle cx={4.5} cy={6} r={1.2} fill="#fff8f0" />
153
- <circle cx={4.5} cy={12} r={1.2} fill="#fff8f0" />
154
- <circle cx={4.5} cy={18} r={1.2} fill="#fff8f0" />
155
- </>
156
- )}
157
- </svg>
158
- </div>
159
- );
160
-
161
- export const RadialRipplePhoneChips: React.FC = () => {
162
- const f = useCurrentFrame();
163
- const t = f / (DUR - 1);
164
-
165
- // 手机入场:从下方 90px 升起,投影随落位收紧
166
- const rise = ramp(f, 0, 26, EASE.snappy);
167
- const phoneY = (1 - rise) * 90;
168
- const phoneOp = Math.min(1, rise * 2.2);
169
-
170
- // feed 匀速自动滚动(t 0.08→0.98)
171
- const scrollP = Math.min(1, Math.max(0, (t - 0.08) / 0.9));
172
- const scrollY = -560 * scrollP;
173
-
174
- // chip:spring pop + 从手机侧边外移,落位后才渐入悬浮
175
- const chip = (t0: number, ph: number, side: -1 | 1): React.CSSProperties => {
176
- const s = springAt(f, t0, { damping: 13, stiffness: 190 });
177
- const slide = ramp(f, t0, 20, EASE.snappy);
178
- const floatIn = ramp(f, t0 + 18, 24, EASE.smooth);
179
- const fl = Math.sin(t * Math.PI * 2 * 2 + ph) * 8 * floatIn;
180
- return {
181
- opacity: Math.min(1, Math.max(0, (f - t0) / 5)),
182
- transform: `translateX(${(side * (1 - slide) * -28).toFixed(2)}px) translateY(${fl.toFixed(2)}px) scale(${(0.8 + 0.2 * s).toFixed(4)})`,
183
- transformOrigin: side < 0 ? 'right center' : 'left center',
184
- };
185
- };
186
- const chipBase: React.CSSProperties = {
187
- position: 'absolute', display: 'flex', alignItems: 'center', gap: 20, padding: '14px 34px 14px 14px', borderRadius: 999,
188
- background: 'linear-gradient(180deg, #fffdf9 0%, #fbf5ec 100%)', color: L.ink, whiteSpace: 'nowrap',
189
- ...type(36, 650), letterSpacing: '-0.02em',
190
- boxShadow: `inset 0 1px 0 #ffffff, 0 0 0 1px ${alpha(L.shadow, 0.06)}, 0 3px 6px ${alpha(L.shadow, 0.08)}, 0 26px 50px -16px ${alpha(L.shadow, 0.32)}`,
191
- };
192
-
193
- const playP = 0.34 + 0.05 * t; // 迷你播放条进度
194
- const wordmark = 90;
195
-
196
- return (
197
- <div style={{ width: 1920, height: 1080, position: 'relative', overflow: 'hidden' }}>
198
- <Stage look={L} keyLight={{ x: 0.4, y: 0.0 }} fill={null} vignette={0.2} grain={0.05}>
199
- {/* 同心圆:各层错相极缓呼吸;受光上沿 + 白色发丝外缘,像涟漪的反光 */}
200
- {RINGS.map(({ size, color, phase }, i) => (
201
- <div key={i} style={{
202
- position: 'absolute', left: 960 - size / 2, top: 540 - size / 2, width: size, height: size, borderRadius: '50%',
203
- background: `linear-gradient(180deg, rgba(255,250,240,0.42) 0%, rgba(255,250,240,0) 40%), ${color}`,
204
- boxShadow: `inset 0 2px 0 rgba(255,252,246,0.85), 0 0 0 1.5px rgba(255,250,242,0.55), 0 -4px 22px rgba(255,248,236,0.4), 0 10px 40px ${alpha(L.shadow, 0.06 + i * 0.015)}`,
205
- transform: `scale(${(1 + 0.06 * Math.sin(t * Math.PI * 2 * 1.5 + phase)).toFixed(5)})`,
206
- }} />
207
- ))}
208
- {/* 中心暖白柔光:把视觉重心收到手机 */}
209
- <div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(ellipse 26% 44% at 50% 50%, rgba(255,250,240,0.7) 0%, rgba(255,250,240,0) 100%)' }} />
210
- </Stage>
211
-
212
- {/* 手机(含投影、侧键)整体上升 */}
213
- <div style={{ position: 'absolute', left: PX, top: PY, width: PW, height: PH, transform: `translateY(${phoneY.toFixed(2)}px)`, opacity: phoneOp }}>
214
- {/* 落地投影:贴近实影 + 远处大柔影(随落位收紧) */}
215
- <div style={{
216
- position: 'absolute', inset: 0, borderRadius: 70,
217
- boxShadow: `0 4px 10px ${alpha(L.shadow, 0.2)}, 0 ${40 + (1 - rise) * 30}px ${80 + (1 - rise) * 40}px -20px ${alpha(L.shadow, 0.42)}, 0 90px 140px -40px ${alpha(L.shadow, 0.25)}`,
218
- }} />
219
- {/* 侧键 */}
220
- {[{ side: -1, y: 190, h: 64 }, { side: -1, y: 272, h: 64 }, { side: 1, y: 230, h: 104 }].map((b, i) => (
221
- <div key={i} style={{
222
- position: 'absolute', top: b.y, width: 5, height: b.h, borderRadius: 3,
223
- left: b.side < 0 ? -3.5 : PW - 1.5, background: 'linear-gradient(90deg, #8a7d6e, #c9bcaa, #8a7d6e)',
224
- }} />
225
- ))}
226
- {/* 暖钛边框 */}
227
- <div style={{
228
- position: 'absolute', inset: 0, borderRadius: 70, padding: FRAME,
229
- background: 'linear-gradient(145deg, #d9cdbb 0%, #9d907f 30%, #c7baa7 55%, #7c705f 80%, #b5a894 100%)',
230
- boxShadow: 'inset 0 0 0 1.5px rgba(255,255,255,0.35), inset 0 0 0 3px rgba(60,48,36,0.25)',
231
- }}>
232
- {/* 黑边 */}
233
- <div style={{ position: 'relative', width: '100%', height: '100%', borderRadius: 58, background: '#0d0b09', padding: BLACK, boxSizing: 'border-box' }}>
234
- {/* 屏幕 */}
235
- <div style={{ position: 'relative', width: '100%', height: '100%', borderRadius: 50, background: '#f7f0e6', overflow: 'hidden' }}>
236
- <div style={{ position: 'absolute', left: 0, top: 0, width: '100%', transform: `translateY(${scrollY.toFixed(2)}px)` }}>
237
- <Feed />
238
- </div>
239
- {/* 状态栏:固定在顶,底下一层渐隐让内容自然没入 */}
240
- <div style={{ position: 'absolute', left: 0, right: 0, top: 0, height: 70, background: 'linear-gradient(180deg, rgba(247,240,230,1) 55%, rgba(247,240,230,0))' }} />
241
- <div style={{ position: 'absolute', left: 38, top: 20, font: `650 19px ${SANS}`, color: L.ink, letterSpacing: '-0.01em' }}>9:41</div>
242
- <div style={{ position: 'absolute', right: 32, top: 23, display: 'flex', gap: 3, alignItems: 'flex-end' }}>
243
- {[6, 9, 12].map((h, i) => <div key={i} style={{ width: 4, height: h, borderRadius: 1, background: L.ink }} />)}
244
- <div style={{ marginLeft: 6, width: 26, height: 13, borderRadius: 4, border: `1.5px solid ${alpha(L.ink, 0.45)}`, boxSizing: 'border-box', padding: 1.5 }}>
245
- <div style={{ width: '74%', height: '100%', borderRadius: 2, background: L.ink }} />
246
- </div>
247
- </div>
248
- {/* 灵动岛 */}
249
- <div style={{ position: 'absolute', left: '50%', top: 14, width: 118, height: 34, marginLeft: -59, borderRadius: 17, background: '#0b0a09' }} />
250
- {/* 底部托底:屏幕底色渐变,滚到播放条下面的内容自然没入 */}
251
- <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 170, background: 'linear-gradient(180deg, rgba(247,240,230,0) 0%, rgba(247,240,230,0.92) 40%, #f7f0e6 70%)' }} />
252
- {/* 迷你播放条:固定在底 */}
253
- <div style={{
254
- position: 'absolute', left: 14, right: 14, bottom: 34, height: 92, borderRadius: 26, overflow: 'hidden',
255
- background: 'linear-gradient(180deg, #2c241e 0%, #221b16 100%)', boxShadow: `0 14px 30px -10px ${alpha(L.shadow, 0.5)}`,
256
- display: 'flex', alignItems: 'center', gap: 14, padding: '0 16px', boxSizing: 'border-box', fontFamily: SANS,
257
- }}>
258
- <Art k={0} size={62} />
259
- <div style={{ flex: 1, minWidth: 0 }}>
260
- <div style={{ fontSize: 19, fontWeight: 680, color: '#fff6ec', letterSpacing: '-0.015em', whiteSpace: 'nowrap' }}>Launch film · preview</div>
261
- {/* 波形:随帧轻跳(确定性) */}
262
- <div style={{ display: 'flex', alignItems: 'center', gap: 3, height: 22, marginTop: 6 }}>
263
- {Array.from({ length: 22 }, (_, k) => {
264
- const amp = 0.35 + 0.65 * Math.abs(Math.sin(k * 1.37 + f * 0.21) * Math.cos(k * 0.53 - f * 0.09));
265
- return <div key={k} style={{ width: 3, height: 4 + amp * 16, borderRadius: 2, background: k / 22 < playP ? '#ffb27a' : alpha('#fff6ec', 0.3) }} />;
266
- })}
267
- </div>
268
- </div>
269
- <div style={{ width: 50, height: 50, borderRadius: 25, background: '#fff6ec', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: 'none' }}>
270
- <div style={{ display: 'flex', gap: 5 }}>
271
- <div style={{ width: 5, height: 18, borderRadius: 2, background: '#221b16' }} />
272
- <div style={{ width: 5, height: 18, borderRadius: 2, background: '#221b16' }} />
273
- </div>
274
- </div>
275
- <div style={{ position: 'absolute', left: 0, bottom: 0, height: 3, width: `${(playP * 100).toFixed(2)}%`, background: ACCENT }} />
276
- </div>
277
- {/* home 条 */}
278
- <div style={{ position: 'absolute', left: '50%', bottom: 10, width: 140, height: 5, marginLeft: -70, borderRadius: 3, background: alpha(L.ink, 0.75) }} />
279
- {/* 玻璃斜反光(静态) */}
280
- <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', background: 'linear-gradient(118deg, rgba(255,255,255,0) 32%, rgba(255,255,255,0.14) 44%, rgba(255,255,255,0) 56%)' }} />
281
- </div>
282
- </div>
283
- </div>
284
- </div>
285
-
286
- {/* 两侧 chip:左先右后,从手机侧边弹出 */}
287
- <div style={{ ...chipBase, top: 330, right: 1920 - PX + CHIP_GAP, ...chip(37, 0, -1) }}>
288
- <ChipIcon kind="chapters" />
289
- Shot recipe cards
290
- </div>
291
- <div style={{ ...chipBase, top: 610, left: PX + PW + CHIP_GAP, ...chip(67, 1.8, 1) }}>
292
- <ChipIcon kind="download" />
293
- Remotion render
294
- </div>
295
-
296
- {/* 品牌字标(收尾海报):镜刻标志与字标同拍升起 */}
297
- <div style={{ position: 'absolute', left: 120, bottom: 104, color: L.ink }}>
298
- <div style={{ display: 'flex', alignItems: 'center', gap: 22 }}>
299
- <div style={{ opacity: ramp(f, wordmark, 10, EASE.out), transform: `translateY(${((1 - ramp(f, wordmark, 18, EASE.snappy)) * 30).toFixed(2)}px)` }}>
300
- <ShotcraftMark size={86} tone="light" style={{ margin: '-10px 0' }} />
301
- </div>
302
- <div style={{ ...type(54, 700), fontFamily: BRAND.font, letterSpacing: '0.01em' }}>
303
- <TextReveal text={BRAND.name} by="word" variant="rise" start={wordmark} each={18} />
304
- </div>
305
- </div>
306
- <div style={{ ...type(32, 450), color: L.ink2, marginTop: 6 }}>
307
- <TextReveal text="Every shot, tuned in one place." by="word" variant="blur" start={wordmark + 8} each={16} gap={4} />
308
- </div>
309
- </div>
310
- </div>
311
- );
312
- };
1
+ // radial-ripple-phone-chips — 同心波纹手机:四层同心圆错相呼吸如水波,中央手机屏内 feed 自动缓滚,
2
+ // 两侧 chip 先后 spring pop 入场并悬浮。三层动作各自极慢,叠起来让产品定格镜头"活着"。
3
+ //
4
+ // 第二轮重设计(暖沙 · 手机上的 video-shotcraft 镜头库):
5
+ // - look = sand。同心圆是四层由深到浅的暖沙色圆盘(2240/1760/1280/840px,铺满画面并出画),
6
+ // 每层有受光上沿与发丝外缘,像沙地上被风吹出的一圈圈涟漪 / 声波;中心一团暖白柔光托住手机。
7
+ // - 主体:按 1080p 原生尺寸搭的手机(430×900,占画高 83%),暖钛金属边框 + 黑边 + 灵动岛 + 侧键 +
8
+ // 玻璃斜反光 + 两层落地投影。屏内是为镜头设计的镜头配方 feed:大标题「Shot library」、带几何插画缩略图的
9
+ // 镜头卡(镜头名 / 分类 / 时长 / 预览进度)、底部常驻迷你预览条(成片配乐在走、波形在跳)。
10
+ // feed 匀速自动滚动(自动播放语义,不加缓动)。
11
+ // - 两侧 chip:白色大胶囊(36px 字 + 赤陶色图标圆),从手机侧边弹出(spring 过冲一次),
12
+ // 落位后才渐渐介入 ±8px 的悬浮;左「Shot recipe cards」先、右「Remotion render」后,错开 30f。
13
+ // - 收尾海报:左下角镜刻标志 + 字标「video-shotcraft — Every shot, tuned in one place.」在两枚 chip 都落定后升起。
14
+ //
15
+ // 时间表(30fps,共 168f):
16
+ // 0–26 预备:同心圆第 1 帧就在呼吸;手机从下方 90px 升起落位(snappy,投影同步收紧)
17
+ // 13–165 feed 匀速滚动 0→−560px(t 0.08→0.98);迷你播放条进度匀速推进
18
+ // 37–57 左 chip pop(spring damping 13,scale 0.8→1 + 从手机侧边外移 28px)
19
+ // 67–87 右 chip pop
20
+ // 90–112 品牌字标逐词升起
21
+ // 112–168 hold:同心圆、feed、chip 悬浮持续极缓运动(无死帧,不加手持抖动)
22
+ import React from 'react';
23
+ import { useCurrentFrame } from 'remotion';
24
+ import { EASE, FONT, ramp } from '../../_fixtures/Polish';
25
+ import { LOOKS, Stage, TextReveal, alpha, springAt, type } from '../../_fixtures/Look';
26
+ import { BRAND, ShotcraftMark } from '../../_fixtures/Brand';
27
+
28
+ export const RADIAL_RIPPLE_PHONE_CHIPS_DURATION = 168; // 5600ms @30fps
29
+
30
+ const L = LOOKS.sand;
31
+ const DUR = RADIAL_RIPPLE_PHONE_CHIPS_DURATION;
32
+ // 模板强调色:落地时按项目品牌色只换这一个变量(屏内封面 / 进度 / chip 图标都跟它走)
33
+ const ACCENT = L.accent; // 赤陶 #c4552d
34
+ const SANS = FONT.sans;
35
+
36
+ // 同心圆(外深内浅,从大到小叠放),相邻层相位差 1.7 rad
37
+ const RINGS = [
38
+ { size: 2240, color: '#dccbb4' },
39
+ { size: 1760, color: '#e4d6c3' },
40
+ { size: 1280, color: '#ebe0d1' },
41
+ { size: 840, color: '#f2eadf' },
42
+ ].map((r, i) => ({ ...r, phase: i * 1.7 }));
43
+
44
+ // 手机几何(画布像素)
45
+ const PW = 430;
46
+ const PH = 900;
47
+ const FRAME = 12; // 金属边框
48
+ const BLACK = 9; // 屏幕黑边
49
+ const PX = (1920 - PW) / 2;
50
+ const PY = (1080 - PH) / 2;
51
+ const CHIP_GAP = 64; // chip 与手机外缘的间距
52
+
53
+ // 镜头库 feed(video-shotcraft 的镜头配方卡;prog = 预览进度)
54
+ type Ep = { title: string; show: string; len: string; prog: number; art: number };
55
+ const EPS: Ep[] = [
56
+ { title: 'Graze face tour', show: 'Camera', len: '4.0 s', prog: 0.62, art: 0 },
57
+ { title: 'Riso print hit', show: 'Effects', len: '4.0 s', prog: 0, art: 1 },
58
+ { title: 'Text as mask', show: 'Opening', len: '3.2 s', prog: 0.18, art: 2 },
59
+ { title: 'Timeline travel', show: 'Data', len: '5.0 s', prog: 0, art: 3 },
60
+ { title: 'Grain dissolve', show: 'Outro', len: '3.6 s', prog: 0, art: 0 },
61
+ { title: 'Cursor flyover', show: 'Camera', len: '4.8 s', prog: 0.4, art: 1 },
62
+ { title: 'Logo sting', show: 'Outro', len: '3.0 s', prog: 0, art: 3 },
63
+ { title: 'Exploded view', show: 'Camera', len: '5.0 s', prog: 0, art: 2 },
64
+ ];
65
+
66
+ // 封面插画:四套几何(太阳 / 等高线 / 圆面包 / 轨道),配色限 sand 的赤陶 + 钴蓝 + 中性
67
+ const Art: React.FC<{ k: number; size: number }> = ({ k, size }) => {
68
+ const s = size;
69
+ const base: React.CSSProperties = { position: 'relative', width: s, height: s, borderRadius: s * 0.2, overflow: 'hidden', flex: 'none' };
70
+ if (k === 0)
71
+ return (
72
+ <div style={{ ...base, background: `linear-gradient(160deg, ${ACCENT} 0%, #e48c5f 100%)` }}>
73
+ <div style={{ position: 'absolute', left: s * 0.24, top: s * 0.2, width: s * 0.52, height: s * 0.52, borderRadius: '50%', background: '#fbe7d3' }} />
74
+ <div style={{ position: 'absolute', left: -s * 0.2, right: -s * 0.2, top: s * 0.62, height: s * 0.7, borderRadius: '50%', background: '#8f3a1e' }} />
75
+ </div>
76
+ );
77
+ if (k === 1)
78
+ return (
79
+ <div style={{ ...base, background: `linear-gradient(160deg, ${L.accent2} 0%, #7f9cc0 100%)` }}>
80
+ {[0.9, 0.66, 0.42].map((r, i) => (
81
+ <div key={i} style={{
82
+ position: 'absolute', left: s * (0.5 - r / 2) + s * 0.12, top: s * (0.5 - r / 2) + s * 0.1, width: s * r, height: s * r * 0.8,
83
+ borderRadius: '50%', border: `${Math.max(2, s * 0.03)}px solid rgba(255,255,255,${0.35 + i * 0.2})`, boxSizing: 'border-box',
84
+ }} />
85
+ ))}
86
+ </div>
87
+ );
88
+ if (k === 2)
89
+ return (
90
+ <div style={{ ...base, background: 'linear-gradient(160deg, #e9dcc8 0%, #d6c3a6 100%)' }}>
91
+ <div style={{ position: 'absolute', left: s * 0.16, top: s * 0.3, width: s * 0.68, height: s * 0.48, borderRadius: `${s * 0.34}px ${s * 0.34}px ${s * 0.1}px ${s * 0.1}px`, background: '#b8743f' }} />
92
+ {[0, 1, 2].map((i) => (
93
+ <div key={i} style={{ position: 'absolute', left: s * (0.3 + i * 0.15), top: s * 0.38, width: s * 0.05, height: s * 0.2, borderRadius: s, background: '#f3e2c8', transform: 'rotate(24deg)' }} />
94
+ ))}
95
+ </div>
96
+ );
97
+ return (
98
+ <div style={{ ...base, background: 'linear-gradient(160deg, #2b231d 0%, #4a3b30 100%)' }}>
99
+ <div style={{ position: 'absolute', left: 0, right: 0, top: s * 0.56, height: s * 0.06, background: ACCENT }} />
100
+ <div style={{ position: 'absolute', left: 0, right: 0, top: s * 0.68, height: s * 0.03, background: alpha('#f3e2c8', 0.5) }} />
101
+ <div style={{ position: 'absolute', left: s * 0.62, top: s * 0.16, width: s * 0.16, height: s * 0.16, borderRadius: '50%', background: '#f3e2c8' }} />
102
+ </div>
103
+ );
104
+ };
105
+
106
+ const Feed: React.FC = () => (
107
+ <div style={{ padding: '76px 16px 0', fontFamily: SANS, color: L.ink }}>
108
+ <div style={{ fontSize: 17, fontWeight: 650, letterSpacing: '0.06em', color: L.ink3, textTransform: 'uppercase', marginLeft: 4 }}>Today · 3 new shots</div>
109
+ <div style={{ fontSize: 44, fontWeight: 780, letterSpacing: '-0.035em', lineHeight: 1.05, marginLeft: 2, marginTop: 4 }}>Shot library</div>
110
+ {/* 精选大卡 */}
111
+ <div style={{ position: 'relative', marginTop: 20, height: 210, borderRadius: 26, overflow: 'hidden', background: `linear-gradient(150deg, #3a2c22 0%, #6b4a33 100%)` }}>
112
+ <div style={{ position: 'absolute', right: -40, top: -50, width: 230, height: 230, borderRadius: '50%', background: `radial-gradient(circle, ${alpha('#ffb27a', 0.9)} 0%, ${alpha(ACCENT, 0.6)} 45%, ${alpha(ACCENT, 0)} 70%)` }} />
113
+ <div style={{ position: 'absolute', left: 22, top: 22, fontSize: 15, fontWeight: 700, letterSpacing: '0.1em', color: alpha('#fbe7d3', 0.7) }}>NEW RECIPE</div>
114
+ <div style={{ position: 'absolute', left: 22, bottom: 50, fontSize: 30, fontWeight: 760, letterSpacing: '-0.03em', color: '#fff6ec', lineHeight: 1.05, width: 260 }}>Crash zoom punch</div>
115
+ <div style={{ position: 'absolute', left: 22, bottom: 22, fontSize: 17, fontWeight: 500, color: alpha('#fbe7d3', 0.75) }}>Camera move · 2 styles · 1.2 s</div>
116
+ </div>
117
+ <div style={{ fontSize: 22, fontWeight: 720, letterSpacing: '-0.02em', margin: '26px 4px 12px' }}>Recipes</div>
118
+ {EPS.map((e, i) => (
119
+ <div key={i} style={{
120
+ display: 'flex', alignItems: 'center', gap: 14, padding: 12, marginBottom: 12, borderRadius: 22,
121
+ background: '#fffcf7', boxShadow: '0 0 0 1px rgba(70,45,20,0.06), 0 2px 6px rgba(58,36,16,0.05)',
122
+ }}>
123
+ <Art k={e.art} size={76} />
124
+ <div style={{ minWidth: 0, flex: 1 }}>
125
+ <div style={{ fontSize: 22, fontWeight: 680, letterSpacing: '-0.02em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', lineHeight: 1.2 }}>{e.title}</div>
126
+ <div style={{ fontSize: 17, color: L.ink2, marginTop: 4, lineHeight: 1.2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{e.len} · {e.show}</div>
127
+ <div style={{ marginTop: 10, height: 5, borderRadius: 3, background: '#efe6da', width: 150 }}>
128
+ {e.prog > 0 && <div style={{ width: `${e.prog * 100}%`, height: '100%', borderRadius: 3, background: ACCENT }} />}
129
+ </div>
130
+ </div>
131
+ <div style={{ width: 40, height: 40, borderRadius: 20, flex: 'none', background: e.prog > 0 ? ACCENT : '#f1e9de', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
132
+ <svg width={16} height={16} viewBox="0 0 16 16"><path d="M5 3 L13 8 L5 13 Z" fill={e.prog > 0 ? '#fff8f0' : L.ink} /></svg>
133
+ </div>
134
+ </div>
135
+ ))}
136
+ </div>
137
+ );
138
+
139
+ // chip 图标
140
+ const ChipIcon: React.FC<{ kind: 'download' | 'chapters' }> = ({ kind }) => (
141
+ <div style={{ width: 60, height: 60, borderRadius: 30, flex: 'none', background: ACCENT, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: `inset 0 1px 0 ${alpha('#ffffff', 0.3)}` }}>
142
+ <svg width={30} height={30} viewBox="0 0 24 24" fill="none" stroke="#fff8f0" strokeWidth={2.4} strokeLinecap="round" strokeLinejoin="round">
143
+ {kind === 'download' ? (
144
+ <>
145
+ <path d="M12 4 V15" />
146
+ <path d="M7 10.5 L12 15.5 L17 10.5" />
147
+ <path d="M5 19.5 H19" />
148
+ </>
149
+ ) : (
150
+ <>
151
+ <path d="M9 6 H20 M9 12 H20 M9 18 H16" />
152
+ <circle cx={4.5} cy={6} r={1.2} fill="#fff8f0" />
153
+ <circle cx={4.5} cy={12} r={1.2} fill="#fff8f0" />
154
+ <circle cx={4.5} cy={18} r={1.2} fill="#fff8f0" />
155
+ </>
156
+ )}
157
+ </svg>
158
+ </div>
159
+ );
160
+
161
+ export const RadialRipplePhoneChips: React.FC = () => {
162
+ const f = useCurrentFrame();
163
+ const t = f / (DUR - 1);
164
+
165
+ // 手机入场:从下方 90px 升起,投影随落位收紧
166
+ const rise = ramp(f, 0, 26, EASE.snappy);
167
+ const phoneY = (1 - rise) * 90;
168
+ const phoneOp = Math.min(1, rise * 2.2);
169
+
170
+ // feed 匀速自动滚动(t 0.08→0.98)
171
+ const scrollP = Math.min(1, Math.max(0, (t - 0.08) / 0.9));
172
+ const scrollY = -560 * scrollP;
173
+
174
+ // chip:spring pop + 从手机侧边外移,落位后才渐入悬浮
175
+ const chip = (t0: number, ph: number, side: -1 | 1): React.CSSProperties => {
176
+ const s = springAt(f, t0, { damping: 13, stiffness: 190 });
177
+ const slide = ramp(f, t0, 20, EASE.snappy);
178
+ const floatIn = ramp(f, t0 + 18, 24, EASE.smooth);
179
+ const fl = Math.sin(t * Math.PI * 2 * 2 + ph) * 8 * floatIn;
180
+ return {
181
+ opacity: Math.min(1, Math.max(0, (f - t0) / 5)),
182
+ transform: `translateX(${(side * (1 - slide) * -28).toFixed(2)}px) translateY(${fl.toFixed(2)}px) scale(${(0.8 + 0.2 * s).toFixed(4)})`,
183
+ transformOrigin: side < 0 ? 'right center' : 'left center',
184
+ };
185
+ };
186
+ const chipBase: React.CSSProperties = {
187
+ position: 'absolute', display: 'flex', alignItems: 'center', gap: 20, padding: '14px 34px 14px 14px', borderRadius: 999,
188
+ background: 'linear-gradient(180deg, #fffdf9 0%, #fbf5ec 100%)', color: L.ink, whiteSpace: 'nowrap',
189
+ ...type(36, 650), letterSpacing: '-0.02em',
190
+ boxShadow: `inset 0 1px 0 #ffffff, 0 0 0 1px ${alpha(L.shadow, 0.06)}, 0 3px 6px ${alpha(L.shadow, 0.08)}, 0 26px 50px -16px ${alpha(L.shadow, 0.32)}`,
191
+ };
192
+
193
+ const playP = 0.34 + 0.05 * t; // 迷你播放条进度
194
+ const wordmark = 90;
195
+
196
+ return (
197
+ <div style={{ width: 1920, height: 1080, position: 'relative', overflow: 'hidden' }}>
198
+ <Stage look={L} keyLight={{ x: 0.4, y: 0.0 }} fill={null} vignette={0.2} grain={0.05}>
199
+ {/* 同心圆:各层错相极缓呼吸;受光上沿 + 白色发丝外缘,像涟漪的反光 */}
200
+ {RINGS.map(({ size, color, phase }, i) => (
201
+ <div key={i} style={{
202
+ position: 'absolute', left: 960 - size / 2, top: 540 - size / 2, width: size, height: size, borderRadius: '50%',
203
+ background: `linear-gradient(180deg, rgba(255,250,240,0.42) 0%, rgba(255,250,240,0) 40%), ${color}`,
204
+ boxShadow: `inset 0 2px 0 rgba(255,252,246,0.85), 0 0 0 1.5px rgba(255,250,242,0.55), 0 -4px 22px rgba(255,248,236,0.4), 0 10px 40px ${alpha(L.shadow, 0.06 + i * 0.015)}`,
205
+ transform: `scale(${(1 + 0.06 * Math.sin(t * Math.PI * 2 * 1.5 + phase)).toFixed(5)})`,
206
+ }} />
207
+ ))}
208
+ {/* 中心暖白柔光:把视觉重心收到手机 */}
209
+ <div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(ellipse 26% 44% at 50% 50%, rgba(255,250,240,0.7) 0%, rgba(255,250,240,0) 100%)' }} />
210
+ </Stage>
211
+
212
+ {/* 手机(含投影、侧键)整体上升 */}
213
+ <div style={{ position: 'absolute', left: PX, top: PY, width: PW, height: PH, transform: `translateY(${phoneY.toFixed(2)}px)`, opacity: phoneOp }}>
214
+ {/* 落地投影:贴近实影 + 远处大柔影(随落位收紧) */}
215
+ <div style={{
216
+ position: 'absolute', inset: 0, borderRadius: 70,
217
+ boxShadow: `0 4px 10px ${alpha(L.shadow, 0.2)}, 0 ${40 + (1 - rise) * 30}px ${80 + (1 - rise) * 40}px -20px ${alpha(L.shadow, 0.42)}, 0 90px 140px -40px ${alpha(L.shadow, 0.25)}`,
218
+ }} />
219
+ {/* 侧键 */}
220
+ {[{ side: -1, y: 190, h: 64 }, { side: -1, y: 272, h: 64 }, { side: 1, y: 230, h: 104 }].map((b, i) => (
221
+ <div key={i} style={{
222
+ position: 'absolute', top: b.y, width: 5, height: b.h, borderRadius: 3,
223
+ left: b.side < 0 ? -3.5 : PW - 1.5, background: 'linear-gradient(90deg, #8a7d6e, #c9bcaa, #8a7d6e)',
224
+ }} />
225
+ ))}
226
+ {/* 暖钛边框 */}
227
+ <div style={{
228
+ position: 'absolute', inset: 0, borderRadius: 70, padding: FRAME,
229
+ background: 'linear-gradient(145deg, #d9cdbb 0%, #9d907f 30%, #c7baa7 55%, #7c705f 80%, #b5a894 100%)',
230
+ boxShadow: 'inset 0 0 0 1.5px rgba(255,255,255,0.35), inset 0 0 0 3px rgba(60,48,36,0.25)',
231
+ }}>
232
+ {/* 黑边 */}
233
+ <div style={{ position: 'relative', width: '100%', height: '100%', borderRadius: 58, background: '#0d0b09', padding: BLACK, boxSizing: 'border-box' }}>
234
+ {/* 屏幕 */}
235
+ <div style={{ position: 'relative', width: '100%', height: '100%', borderRadius: 50, background: '#f7f0e6', overflow: 'hidden' }}>
236
+ <div style={{ position: 'absolute', left: 0, top: 0, width: '100%', transform: `translateY(${scrollY.toFixed(2)}px)` }}>
237
+ <Feed />
238
+ </div>
239
+ {/* 状态栏:固定在顶,底下一层渐隐让内容自然没入 */}
240
+ <div style={{ position: 'absolute', left: 0, right: 0, top: 0, height: 70, background: 'linear-gradient(180deg, rgba(247,240,230,1) 55%, rgba(247,240,230,0))' }} />
241
+ <div style={{ position: 'absolute', left: 38, top: 20, font: `650 19px ${SANS}`, color: L.ink, letterSpacing: '-0.01em' }}>9:41</div>
242
+ <div style={{ position: 'absolute', right: 32, top: 23, display: 'flex', gap: 3, alignItems: 'flex-end' }}>
243
+ {[6, 9, 12].map((h, i) => <div key={i} style={{ width: 4, height: h, borderRadius: 1, background: L.ink }} />)}
244
+ <div style={{ marginLeft: 6, width: 26, height: 13, borderRadius: 4, border: `1.5px solid ${alpha(L.ink, 0.45)}`, boxSizing: 'border-box', padding: 1.5 }}>
245
+ <div style={{ width: '74%', height: '100%', borderRadius: 2, background: L.ink }} />
246
+ </div>
247
+ </div>
248
+ {/* 灵动岛 */}
249
+ <div style={{ position: 'absolute', left: '50%', top: 14, width: 118, height: 34, marginLeft: -59, borderRadius: 17, background: '#0b0a09' }} />
250
+ {/* 底部托底:屏幕底色渐变,滚到播放条下面的内容自然没入 */}
251
+ <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 170, background: 'linear-gradient(180deg, rgba(247,240,230,0) 0%, rgba(247,240,230,0.92) 40%, #f7f0e6 70%)' }} />
252
+ {/* 迷你播放条:固定在底 */}
253
+ <div style={{
254
+ position: 'absolute', left: 14, right: 14, bottom: 34, height: 92, borderRadius: 26, overflow: 'hidden',
255
+ background: 'linear-gradient(180deg, #2c241e 0%, #221b16 100%)', boxShadow: `0 14px 30px -10px ${alpha(L.shadow, 0.5)}`,
256
+ display: 'flex', alignItems: 'center', gap: 14, padding: '0 16px', boxSizing: 'border-box', fontFamily: SANS,
257
+ }}>
258
+ <Art k={0} size={62} />
259
+ <div style={{ flex: 1, minWidth: 0 }}>
260
+ <div style={{ fontSize: 19, fontWeight: 680, color: '#fff6ec', letterSpacing: '-0.015em', whiteSpace: 'nowrap' }}>Launch film · preview</div>
261
+ {/* 波形:随帧轻跳(确定性) */}
262
+ <div style={{ display: 'flex', alignItems: 'center', gap: 3, height: 22, marginTop: 6 }}>
263
+ {Array.from({ length: 22 }, (_, k) => {
264
+ const amp = 0.35 + 0.65 * Math.abs(Math.sin(k * 1.37 + f * 0.21) * Math.cos(k * 0.53 - f * 0.09));
265
+ return <div key={k} style={{ width: 3, height: 4 + amp * 16, borderRadius: 2, background: k / 22 < playP ? '#ffb27a' : alpha('#fff6ec', 0.3) }} />;
266
+ })}
267
+ </div>
268
+ </div>
269
+ <div style={{ width: 50, height: 50, borderRadius: 25, background: '#fff6ec', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: 'none' }}>
270
+ <div style={{ display: 'flex', gap: 5 }}>
271
+ <div style={{ width: 5, height: 18, borderRadius: 2, background: '#221b16' }} />
272
+ <div style={{ width: 5, height: 18, borderRadius: 2, background: '#221b16' }} />
273
+ </div>
274
+ </div>
275
+ <div style={{ position: 'absolute', left: 0, bottom: 0, height: 3, width: `${(playP * 100).toFixed(2)}%`, background: ACCENT }} />
276
+ </div>
277
+ {/* home 条 */}
278
+ <div style={{ position: 'absolute', left: '50%', bottom: 10, width: 140, height: 5, marginLeft: -70, borderRadius: 3, background: alpha(L.ink, 0.75) }} />
279
+ {/* 玻璃斜反光(静态) */}
280
+ <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', background: 'linear-gradient(118deg, rgba(255,255,255,0) 32%, rgba(255,255,255,0.14) 44%, rgba(255,255,255,0) 56%)' }} />
281
+ </div>
282
+ </div>
283
+ </div>
284
+ </div>
285
+
286
+ {/* 两侧 chip:左先右后,从手机侧边弹出 */}
287
+ <div style={{ ...chipBase, top: 330, right: 1920 - PX + CHIP_GAP, ...chip(37, 0, -1) }}>
288
+ <ChipIcon kind="chapters" />
289
+ Shot recipe cards
290
+ </div>
291
+ <div style={{ ...chipBase, top: 610, left: PX + PW + CHIP_GAP, ...chip(67, 1.8, 1) }}>
292
+ <ChipIcon kind="download" />
293
+ Remotion render
294
+ </div>
295
+
296
+ {/* 品牌字标(收尾海报):镜刻标志与字标同拍升起 */}
297
+ <div style={{ position: 'absolute', left: 120, bottom: 104, color: L.ink }}>
298
+ <div style={{ display: 'flex', alignItems: 'center', gap: 22 }}>
299
+ <div style={{ opacity: ramp(f, wordmark, 10, EASE.out), transform: `translateY(${((1 - ramp(f, wordmark, 18, EASE.snappy)) * 30).toFixed(2)}px)` }}>
300
+ <ShotcraftMark size={86} tone="light" style={{ margin: '-10px 0' }} />
301
+ </div>
302
+ <div style={{ ...type(54, 700), fontFamily: BRAND.font, letterSpacing: '0.01em' }}>
303
+ <TextReveal text={BRAND.name} by="word" variant="rise" start={wordmark} each={18} />
304
+ </div>
305
+ </div>
306
+ <div style={{ ...type(32, 450), color: L.ink2, marginTop: 6 }}>
307
+ <TextReveal text="Every shot, tuned in one place." by="word" variant="blur" start={wordmark + 8} each={16} gap={4} />
308
+ </div>
309
+ </div>
310
+ </div>
311
+ );
312
+ };