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,293 +1,293 @@
1
- // spotlight-hero-card —— 聚光灯扫过页面锁定一张卡 → 斜侧推进 → 卡片弹起悬浮 →
2
- // 轮廓光束两圈 → 贴回原位。单一主角式产品开场,把核心对象立成全片主角。
3
- //
4
- // 第二轮重设计(石墨剧场 · 钨丝聚光):
5
- // - look = graphite。真实页面截图(Q1,纹理不动)被放进一间关了灯的剧场:整页先压到 ~14% 亮度,
6
- // 只有聚光灯的光池里是页面本色;灯是暖钨丝白,带一道从画面上方打下来的体积光柱(光柱里有浮尘)。
7
- // 开灯是"啪"的一下:2f 亮起 → 1f 回闪 → 稳住,像舞台灯被推上闸。
8
- // - 光池游走 3 个中间站(操作员在找人)→ 锁定卡心:光池收拢 + 锁定脉冲 + 光池外再压暗一档。
9
- // - 相机:全页正视 → 18f 推进到左侧机位斜特写(rotY 34° 主导 + rotX 8°),推进后彻底锁死(R1 真静止)。
10
- // - 卡:rise(过冲)→ 悬停 sin bob → reseat(落地微压 + 一圈香槟色落地光)。悬浮时卡投在页面上的影子
11
- // 偏离光源方向、随高度变大变虚(主光方向统一:光从上方偏右来)。
12
- // - 轮廓光束改为香槟金 + 白芯(graphite 的 accent2),只给主角两圈(Q4):lap1 快而亮、lap2 慢而弱。
13
- // - 3D 注记(C3:同一 3D 空间、同一台相机):暗页上的白色粗黑体「Your product, / in motion.」(video-shotcraft 宣传语),
14
- // 关键词后长出香槟色马克条(字变墨色);卡 reseat 时注记也一起"落"回页面平面(translateZ 92→4),
15
- // 不再提前退场——结尾是一张完整的海报:聚光里的卡 + 页面上的一句话。
16
- //
17
- // 时间表(30fps,共 172f):
18
- // 0–6 暗场:页面 ~14% 亮度;f2–6 开灯(亮-回闪-稳)
19
- // 6–34 光池游走 3 站(smooth in-out,站间有 2–3f 停顿)
20
- // 34–44 锁定:光池收拢到卡 + 6% 脉冲,光池外压暗 0.80→0.90
21
- // 40–58 相机推进到斜侧特写(18f),高清卡纹理 40–46 交叉淡入
22
- // 56–66 卡弹起(10f 过冲);66–124 悬停 bob(周期 40f)
23
- // 68–82 光束 lap1(快、亮);88–108 lap2(慢、弱)
24
- // 70–84 注记入场(升起 + 解糊),84–96 马克条长出
25
- // 124–142 reseat(18f);注记同步落回页面;142 触地:落地光一圈 + 微压
26
- // 142–172 hold:相机锁死,只剩光柱里浮尘与光池极缓呼吸
27
- import React from 'react';
28
- import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion';
29
- import { PageCam2D, CamKey2D } from '../../_fixtures/PageCam2D';
30
- import { EASE, FONT, Grain, ramp } from '../../_fixtures/Polish';
31
- import { Dust, LOOKS, alpha } from '../../_fixtures/Look';
32
- import layout from '../../_textures/live-layout.json';
33
-
34
- export const SPOTLIGHT_HERO_CARD_DURATION = 172;
35
-
36
- const L = LOOKS.graphite;
37
- const GOLD = L.accent2; // 香槟金:光束 / 马克条 / 落地光
38
- const BEAM_CORE = 'rgba(255,250,238,0.98)';
39
- const LAMP = '255,238,212'; // 钨丝暖白
40
- const PATCH = 'oklch(97.5% 0.008 82)';
41
-
42
- const PAGE_H = layout.projects.pageH;
43
- const MAIN = 3;
44
- const CARD = layout.projects.cards[MAIN];
45
- const MCX = CARD.x + CARD.w / 2; // ≈ 960
46
- const MCY = CARD.y + CARD.h / 2; // 772
47
- const RADIUS = 16;
48
-
49
- // —— 节拍 ——
50
- const LOCK = 34;
51
- const PUSH0 = 40;
52
- const PUSH1 = 58;
53
- const RISE0 = 56;
54
- const RISE1 = 66;
55
- const RESEAT0 = 124;
56
- const LAND = 142;
57
-
58
- const CAM_KEYS: CamKey2D[] = [
59
- { frame: 0, cx: 960, cy: 600, zoom: 0.8, rotX: 0, rotY: 0, rotZ: 0, persp: 1200 },
60
- { frame: PUSH0, cx: 960, cy: 600, zoom: 0.8, rotX: 0, rotY: 0, rotZ: 0, persp: 1200 },
61
- { frame: PUSH1, cx: MCX - 105, cy: MCY - 10, zoom: 2.6, rotX: 8, rotY: 34, rotZ: 2, persp: 1200 },
62
- { frame: SPOTLIGHT_HERO_CARD_DURATION, cx: MCX - 105, cy: MCY - 10, zoom: 2.6, rotX: 8, rotY: 34, rotZ: 2, persp: 1200 },
63
- ];
64
- const PUSH_EASE = Easing.bezier(0.35, 0, 0.2, 1);
65
- const POP_EASE = Easing.bezier(0.2, 1.25, 0.3, 1);
66
- const RESEAT_EASE = Easing.bezier(0.4, 0, 0.3, 1.05);
67
-
68
- const clampOpt = { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } as const;
69
-
70
- // 页面相机的纯函数版(与 PageCam2D 同一套插值与 3D 坐标数学),供注记层复用同一台相机
71
- const camAt = (frame: number) => {
72
- let a = CAM_KEYS[0];
73
- let b = CAM_KEYS[CAM_KEYS.length - 1];
74
- for (let i = 0; i < CAM_KEYS.length - 1; i++) {
75
- if (frame >= CAM_KEYS[i].frame && frame <= CAM_KEYS[i + 1].frame) { a = CAM_KEYS[i]; b = CAM_KEYS[i + 1]; break; }
76
- }
77
- const t = a.frame === b.frame ? 1 : interpolate(frame, [a.frame, b.frame], [0, 1], { ...clampOpt, easing: PUSH_EASE });
78
- const m = (x?: number, y?: number) => (x ?? 0) + ((y ?? 0) - (x ?? 0)) * t;
79
- return { cx: m(a.cx, b.cx), cy: m(a.cy, b.cy), zoom: m(a.zoom, b.zoom), rotX: m(a.rotX, b.rotX), rotY: m(a.rotY, b.rotY), rotZ: m(a.rotZ, b.rotZ), persp: m(a.persp, b.persp) };
80
- };
81
- const NoteCam: React.FC<{ frame: number; children: React.ReactNode }> = ({ frame, children }) => {
82
- const c = camAt(frame);
83
- return (
84
- <AbsoluteFill style={{ overflow: 'hidden', pointerEvents: 'none' }}>
85
- <div style={{ position: 'absolute', inset: 0, perspective: `${c.persp * c.zoom}px`, perspectiveOrigin: '960px 540px' }}>
86
- <div style={{
87
- position: 'absolute', width: 1920, height: PAGE_H, zoom: c.zoom, transformOrigin: `${c.cx}px ${c.cy}px`, transformStyle: 'preserve-3d',
88
- transform: `translate(${960 / c.zoom - c.cx}px, ${540 / c.zoom - c.cy}px) rotateY(${c.rotY}deg) rotateX(${c.rotX}deg) rotateZ(${c.rotZ}deg)`,
89
- }}>
90
- {children}
91
- </div>
92
- </div>
93
- </AbsoluteFill>
94
- );
95
- };
96
-
97
- export const SpotlightHeroCard: React.FC = () => {
98
- const frame = useCurrentFrame();
99
-
100
- // --- 开灯:亮 → 回闪 → 稳(舞台灯推闸) ---
101
- const lamp = interpolate(frame, [1, 3, 4, 6], [0, 1, 0.62, 1], clampOpt);
102
-
103
- // --- 光池游走(屏幕空间 %):3 个中间站,站间短停 → 锁定卡心 → 随推进移到画面中 ---
104
- const ST = [4, 10, 13, 19, 22, 28, LOCK, PUSH1];
105
- const spotX = interpolate(frame, ST, [24, 24, 72, 72, 38, 38, 50, 60], { ...clampOpt, easing: EASE.smooth });
106
- const spotY = interpolate(frame, ST, [30, 30, 40, 40, 62, 62, 64, 55], { ...clampOpt, easing: EASE.smooth });
107
- const poolBase = interpolate(frame, [22, LOCK, PUSH1], [400, 300, 470], { ...clampOpt, easing: EASE.swift });
108
- const pulse = interpolate(frame, [LOCK, LOCK + 4, LOCK + 10], [0, 0.06, 0], clampOpt);
109
- const breathe = 1 + 0.015 * Math.sin((frame - LAND) / 14) * ramp(frame, LAND, 20, EASE.out);
110
- const poolRx = poolBase * (1 + pulse) * breathe;
111
- const poolRy = poolBase * interpolate(frame, [PUSH0, PUSH1], [0.8, 0.92], clampOpt) * (1 + pulse) * breathe;
112
- const dark = interpolate(frame, [0, LOCK, PUSH1], [0.9, 0.92, 0.94], clampOpt); // 光池外压暗
113
- // 锁定后:屏幕空间的圆光池 → 页面空间的"卡形光"(同一台相机、卡形软孔)。卡在 z 上高于这层暗场,
114
- // 所以卡面从边到边全亮、原色对比;衰减只发生在卡外。推进期间两套灯交叉过渡。
115
- const cardLight = ramp(frame, LOCK + 4, PUSH1 - LOCK - 4, EASE.smooth);
116
- const holdBreath = 1 + 0.012 * Math.sin((frame - LAND) / 14) * ramp(frame, LAND, 20, EASE.out);
117
-
118
- // --- 卡:rise → hover → reseat ---
119
- const rise = interpolate(frame, [RISE0, RISE1], [0, 1], { ...clampOpt, easing: POP_EASE });
120
- const reseat = interpolate(frame, [RESEAT0, LAND], [0, 1], { ...clampOpt, easing: RESEAT_EASE });
121
- const lift = rise * (1 - reseat);
122
- const bob = Math.sin(((frame - RISE1) / 40) * Math.PI * 2) * 4 * lift;
123
- const z = 110 * lift + bob;
124
- const landed = frame >= LAND;
125
- const press = interpolate(frame, [LAND - 4, LAND - 1, LAND], [1, 0.997, 1], clampOpt);
126
- // 投影:光从上方偏右来 → 影子落向左下,随高度变大变虚
127
- const shadow = `${-10 * lift}px ${10 * lift}px ${12 + 12 * lift}px rgba(10,8,6,${0.35 * lift}), ${-36 * lift}px ${48 * lift}px ${90 * lift}px rgba(10,8,6,${0.42 * lift})`;
128
-
129
- const slotVis = Math.min(1, rise * 2) * (1 - reseat);
130
- const landPulse = interpolate(frame, [LAND - 4, LAND, LAND + 14], [0, 1, 0], clampOpt);
131
- const slotEdge = Math.min(1, 0.45 * (1 - reseat)) + landPulse * 0.5;
132
-
133
- // --- 轮廓光束两圈 ---
134
- const beam1Prog = interpolate(frame, [68, 82], [0, 1], { ...clampOpt, easing: EASE.linear });
135
- const beam1On = frame >= 67 && frame <= 83;
136
- const beam2Prog = interpolate(frame, [88, 108], [0, 1], { ...clampOpt, easing: EASE.swift });
137
- const beam2On = frame >= 87 && frame <= 109;
138
- const beamTrail = interpolate(frame, [108, 122], [0.4, 0], clampOpt);
139
- const bw = CARD.w + 6;
140
- const bh = CARD.h + 6;
141
-
142
- const hiresIn = interpolate(frame, [PUSH0, PUSH0 + 6], [0, 1], clampOpt);
143
- const rimOn = 0.5 * Math.min(1, lift + ramp(frame, PUSH0, 16, EASE.linear));
144
-
145
- // --- 注记 ---
146
- const noteIn = ramp(frame, 70, 14, EASE.out);
147
- const noteSettle = interpolate(frame, [RESEAT0 - 4, LAND], [0, 1], { ...clampOpt, easing: RESEAT_EASE });
148
- const noteZ = 4 + (88 + Math.sin(((frame - 70) / 44) * Math.PI * 2) * 3) * (1 - noteSettle);
149
- const hl = ramp(frame, 84, 12, EASE.swift);
150
-
151
- // --- 体积光柱:光源在画面上方偏右,打到光池 ---
152
- const px = (spotX / 100) * 1920;
153
- const py = (spotY / 100) * 1080;
154
- const sx = px + 420;
155
- const sy = -720;
156
- const coneW = poolRx * 0.6;
157
- const cone = `${sx - 26}px ${sy}px, ${sx + 26}px ${sy}px, ${px + coneW}px ${py}px, ${px - coneW}px ${py}px`;
158
-
159
- return (
160
- <AbsoluteFill style={{ backgroundColor: L.bg[2] }}>
161
- <PageCam2D src="textures/live/projects-full.png" pageH={PAGE_H} keys={CAM_KEYS} ease={PUSH_EASE} bg={L.bg[1]}>
162
- {/* 倾斜平面近端(下缘)的一线轮廓光 */}
163
- <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 8, background: 'rgba(255,240,220,0.8)', filter: 'blur(6px)', opacity: rimOn, pointerEvents: 'none' }} />
164
-
165
- {/* 页面空间暗场:整页压暗,只在卡位挖一个卡形软孔(紧孔 σ22 + 一圈 15% 的宽溢光 σ60);translateZ(1) 垫在卡之下 */}
166
- {cardLight > 0.001 ? (
167
- <svg width={1920} height={PAGE_H} style={{ position: 'absolute', left: 0, top: 0, transform: 'translateZ(1px)', opacity: cardLight, pointerEvents: 'none' }}>
168
- <defs>
169
- <filter id="shc-tight" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="22" /></filter>
170
- <filter id="shc-wide" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="60" /></filter>
171
- <mask id="shc-hole" maskUnits="userSpaceOnUse" x={0} y={0} width={1920} height={PAGE_H}>
172
- <rect x={0} y={0} width={1920} height={PAGE_H} fill="white" />
173
- <rect x={CARD.x - 60} y={CARD.y - 50} width={CARD.w + 120} height={CARD.h + 100} rx={70} fill="#262626" filter="url(#shc-wide)" />
174
- <rect x={CARD.x - 14} y={CARD.y - 14} width={CARD.w + 28} height={CARD.h + 28} rx={RADIUS + 14} fill="black" filter="url(#shc-tight)" />
175
- </mask>
176
- </defs>
177
- <rect x={0} y={0} width={1920} height={PAGE_H} fill="rgb(14,12,10)" fillOpacity={Math.min(0.97, 0.94 * holdBreath)} mask="url(#shc-hole)" />
178
- </svg>
179
- ) : null}
180
-
181
- <div style={{ transformStyle: 'preserve-3d' }}>
182
- {/* 卡起飞后的原位补丁 + 香槟色呼吸描边 */}
183
- {slotVis > 0.02 || landPulse > 0.02 ? (
184
- <div style={{
185
- position: 'absolute', left: CARD.x - 2, top: CARD.y - 2, width: CARD.w + 4, height: CARD.h + 4, transform: 'translateZ(1.5px)',
186
- background: slotVis > 0.02 ? PATCH : 'transparent', borderRadius: RADIUS,
187
- boxShadow: `inset 0 0 26px rgba(150,110,40,${(0.14 * slotEdge).toFixed(3)})`, opacity: Math.max(slotVis, landPulse),
188
- }}>
189
- <div style={{ position: 'absolute', inset: 0, borderRadius: RADIUS, border: `1.5px solid ${GOLD}`, opacity: slotEdge, boxShadow: landPulse > 0.02 ? `0 0 ${(24 * landPulse).toFixed(1)}px ${alpha(GOLD, 0.8)}` : undefined }} />
190
- </div>
191
- ) : null}
192
-
193
- {/* 悬浮的卡 */}
194
- <div style={{
195
- position: 'absolute', left: CARD.x, top: CARD.y, width: CARD.w, height: CARD.h,
196
- transform: `translateZ(${(z + 2).toFixed(2)}px) scale(${press})`, transformOrigin: 'center center', transformStyle: 'preserve-3d',
197
- }}>
198
- <div style={{ position: 'absolute', inset: 0, borderRadius: RADIUS, overflow: 'hidden', boxShadow: landed ? 'none' : shadow }}>
199
- <Img src={staticFile(`textures/live/${CARD.file}`)} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }} />
200
- <Img src={staticFile('textures/live/card4-hires.png')} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block', opacity: hiresIn }} />
201
- {/* 悬浮时卡面受光:右上角暖光 → 左下渐暗 */}
202
- <div style={{ position: 'absolute', inset: 0, background: `linear-gradient(200deg, rgba(${LAMP},0.35), rgba(${LAMP},0) 45%, rgba(20,16,10,0.08) 100%)`, opacity: lift, pointerEvents: 'none' }} />
203
- </div>
204
- <div style={{ position: 'absolute', inset: 0, borderRadius: RADIUS, // 轮廓光:一圈暖白发丝边 + 极淡外溢,让卡的轮廓在暗页上读得清(锁定后亮起)
205
- boxShadow: `inset 0 0 0 1px rgba(255,255,255,${(0.7 * lift).toFixed(3)}), 0 0 0 1.5px rgba(255,236,205,${(0.7 * cardLight).toFixed(3)}), 0 0 44px rgba(255,214,160,${(0.18 * cardLight).toFixed(3)})`, pointerEvents: 'none' }} />
206
-
207
- {/* 轮廓光束:SVG 圆角矩形,pathLength=1 的行进弧段 */}
208
- {(beam1On || beam2On) && lift > 0.4 ? (
209
- <svg width={bw} height={bh} viewBox={`0 0 ${bw} ${bh}`} style={{
210
- position: 'absolute', left: -3, top: -3, overflow: 'visible', pointerEvents: 'none', opacity: beam1On ? 1 : 0.62,
211
- filter: `drop-shadow(0 0 6px ${alpha(GOLD, 0.9)}) drop-shadow(0 0 18px rgba(255,236,200,0.55))`,
212
- }}>
213
- <rect x={2} y={2} width={bw - 4} height={bh - 4} rx={RADIUS} fill="none" stroke={GOLD} strokeWidth={beam1On ? 5 : 3.5} strokeLinecap="round"
214
- pathLength={1} strokeDasharray="0.16 1" strokeDashoffset={-(beam1On ? beam1Prog : beam2Prog)} />
215
- <rect x={2} y={2} width={bw - 4} height={bh - 4} rx={RADIUS} fill="none" stroke={BEAM_CORE} strokeWidth={beam1On ? 2.5 : 1.75} strokeLinecap="round"
216
- pathLength={1} strokeDasharray="0.16 1" strokeDashoffset={-(beam1On ? beam1Prog : beam2Prog)} />
217
- </svg>
218
- ) : null}
219
- {beamTrail > 0.01 ? (
220
- <div style={{ position: 'absolute', inset: -3, borderRadius: RADIUS + 3, border: `1.5px solid ${GOLD}`, opacity: beamTrail, pointerEvents: 'none' }} />
221
- ) : null}
222
- </div>
223
- </div>
224
-
225
- </PageCam2D>
226
-
227
- {/* —— 灯光(屏幕空间)——
228
- ① 关灯:光池外 multiply 压暗到 ~14%(暖黑而非纯黑,保色相);
229
- ② 光池:钨丝暖白 soft-light 提亮中间调 + 极弱 screen 抬亮;
230
- ③ 体积光柱 + 柱内浮尘(screen)。 */}
231
- <AbsoluteFill style={{
232
- // 近高斯的衰减:中心完全透明 → 边缘压到 ~10% 亮度;多段 stop 让光池边缘软而不是一圈硬边
233
- background: `radial-gradient(${(poolRx * 1.35).toFixed(1)}px ${(poolRy * 1.35).toFixed(1)}px at ${spotX}% ${spotY}%, rgba(14,12,10,0) 0%, rgba(14,12,10,0) 26%, rgba(14,12,10,${(dark * 0.25).toFixed(3)}) 44%, rgba(14,12,10,${(dark * 0.62).toFixed(3)}) 62%, rgba(14,12,10,${(dark * 0.9).toFixed(3)}) 80%, rgba(14,12,10,${dark.toFixed(3)}) 100%)`,
234
- mixBlendMode: 'multiply', pointerEvents: 'none', opacity: lamp * (1 - cardLight),
235
- }} />
236
- {/* 开灯前:整页压暗(灯推闸时由它和上一层交接) */}
237
- <AbsoluteFill style={{ background: 'rgba(14,12,10,1)', mixBlendMode: 'multiply', opacity: 0.84 * (1 - lamp), pointerEvents: 'none' }} />
238
- {/* 光池里的钨丝暖色(soft-light,低强度——白卡不被打爆) */}
239
- <AbsoluteFill style={{
240
- background: `radial-gradient(${(poolRx * 1.2).toFixed(1)}px ${(poolRy * 1.2).toFixed(1)}px at ${spotX}% ${spotY}%, rgba(${LAMP},0.24) 0%, rgba(${LAMP},0.12) 50%, rgba(${LAMP},0) 80%)`,
241
- mixBlendMode: 'soft-light', pointerEvents: 'none', opacity: lamp * (1 - cardLight), // 锁定后退掉:卡上不叠任何泛光,文字保持原生对比
242
- }} />
243
- {/* 体积光柱:梯形 + 纵向渐变 + 大半径模糊;推进后光柱变淡(镜头离光源更近、柱身出画) */}
244
- <AbsoluteFill style={{ mixBlendMode: 'screen', pointerEvents: 'none', opacity: lamp * (1 - 0.45 * ramp(frame, PUSH0, 18, EASE.smooth)) }}>
245
- {/* 模糊放在外层、裁切放在内层:柱身边缘是软的 */}
246
- <div style={{ position: 'absolute', inset: 0, filter: 'blur(28px)' }}>
247
- <div style={{
248
- position: 'absolute', inset: 0, clipPath: `polygon(${cone})`,
249
- background: `linear-gradient(${(Math.atan2(py - sy, px - sx) * 180 / Math.PI - 90).toFixed(1)}deg, rgba(${LAMP},0.34) 0%, rgba(${LAMP},0.16) 60%, rgba(${LAMP},0.06) 100%)`,
250
- }} />
251
- </div>
252
- <div style={{ position: 'absolute', inset: 0, clipPath: `polygon(${cone})` }}>
253
- <Dust look={L} count={36} seed={4} drift={0.3} opacity={0.6} color="#fff1dc" />
254
- </div>
255
- </AbsoluteFill>
256
- {/* 注记层:与页面同一台相机(camAt 复刻 PageCam2D 的坐标数学),但画在灯光层之上——
257
- 它是"自发光"的字,不被关灯的 multiply 压暗;暗色衬底负责把背后的邻卡字压下去 */}
258
- <NoteCam frame={frame}>
259
- {/* 3D 注记:卡左侧,同一 3D 空间、同一台相机;reseat 时一起落回页面 */}
260
- {frame >= 70 ? (
261
- <div style={{ transformStyle: 'preserve-3d', pointerEvents: 'none' }}>
262
- {/* 注记投在页面上的软影(落回页面时收拢消失) */}
263
- <div style={{
264
- position: 'absolute', left: 520, top: 760, width: 240, height: 70, transform: 'translateZ(2px)',
265
- background: 'radial-gradient(ellipse at 50% 50%, rgba(0,0,0,0.55), transparent 70%)', filter: 'blur(12px)',
266
- opacity: 0.5 * noteIn * (1 - noteSettle),
267
- }} />
268
- {/* 暗色衬底:注记压在邻卡文字上,没有衬底就和背后的字打架(Q11);同一 3D 平面、同一台相机 */}
269
- <div style={{
270
- position: 'absolute', left: 400, top: 600, width: 380, height: 240, // 右缘止于卡左缘(x=781)之前,不压卡面
271
- transform: `translateZ(${(noteZ - 1).toFixed(2)}px) translateY(${((1 - noteIn) * 26).toFixed(2)}px)`,
272
- background: 'radial-gradient(ellipse 50% 50% at 52% 50%, rgba(16,14,12,0.97) 0%, rgba(16,14,12,0.9) 60%, rgba(16,14,12,0) 100%)',
273
- filter: 'blur(6px)', opacity: noteIn,
274
- }} />
275
- <div style={{
276
- position: 'absolute', left: 528, top: 662, width: 'max-content', whiteSpace: 'nowrap',
277
- transform: `translateZ(${noteZ.toFixed(2)}px) translateY(${((1 - noteIn) * 26).toFixed(2)}px)`,
278
- opacity: noteIn, filter: noteIn < 1 ? `blur(${((1 - noteIn) * 4).toFixed(2)}px)` : undefined,
279
- fontFamily: FONT.sans, letterSpacing: '-0.035em', lineHeight: 1.1,
280
- }}>
281
- <div style={{ fontSize: 34, fontWeight: 760, color: '#f6f3ec', textShadow: '0 2px 18px rgba(0,0,0,0.6)' }}>Your product,</div>
282
- <div style={{ position: 'relative', display: 'inline-block', marginTop: 2 }}>
283
- <div style={{ position: 'absolute', left: -6, top: '8%', bottom: '2%', width: `calc(${hl.toFixed(4)} * (100% + 12px))`, background: GOLD, borderRadius: 4 }} />
284
- <div style={{ position: 'relative', fontSize: 34, fontWeight: 760, color: hl > 0.55 ? '#14110c' : '#f6f3ec' }}>in motion.</div>
285
- </div>
286
- </div>
287
- </div>
288
- ) : null}
289
- </NoteCam>
290
- <Grain opacity={0.07} blend="soft-light" />
291
- </AbsoluteFill>
292
- );
293
- };
1
+ // spotlight-hero-card —— 聚光灯扫过页面锁定一张卡 → 斜侧推进 → 卡片弹起悬浮 →
2
+ // 轮廓光束两圈 → 贴回原位。单一主角式产品开场,把核心对象立成全片主角。
3
+ //
4
+ // 第二轮重设计(石墨剧场 · 钨丝聚光):
5
+ // - look = graphite。真实页面截图(Q1,纹理不动)被放进一间关了灯的剧场:整页先压到 ~14% 亮度,
6
+ // 只有聚光灯的光池里是页面本色;灯是暖钨丝白,带一道从画面上方打下来的体积光柱(光柱里有浮尘)。
7
+ // 开灯是"啪"的一下:2f 亮起 → 1f 回闪 → 稳住,像舞台灯被推上闸。
8
+ // - 光池游走 3 个中间站(操作员在找人)→ 锁定卡心:光池收拢 + 锁定脉冲 + 光池外再压暗一档。
9
+ // - 相机:全页正视 → 18f 推进到左侧机位斜特写(rotY 34° 主导 + rotX 8°),推进后彻底锁死(R1 真静止)。
10
+ // - 卡:rise(过冲)→ 悬停 sin bob → reseat(落地微压 + 一圈香槟色落地光)。悬浮时卡投在页面上的影子
11
+ // 偏离光源方向、随高度变大变虚(主光方向统一:光从上方偏右来)。
12
+ // - 轮廓光束改为香槟金 + 白芯(graphite 的 accent2),只给主角两圈(Q4):lap1 快而亮、lap2 慢而弱。
13
+ // - 3D 注记(C3:同一 3D 空间、同一台相机):暗页上的白色粗黑体「Your product, / in motion.」(video-shotcraft 宣传语),
14
+ // 关键词后长出香槟色马克条(字变墨色);卡 reseat 时注记也一起"落"回页面平面(translateZ 92→4),
15
+ // 不再提前退场——结尾是一张完整的海报:聚光里的卡 + 页面上的一句话。
16
+ //
17
+ // 时间表(30fps,共 172f):
18
+ // 0–6 暗场:页面 ~14% 亮度;f2–6 开灯(亮-回闪-稳)
19
+ // 6–34 光池游走 3 站(smooth in-out,站间有 2–3f 停顿)
20
+ // 34–44 锁定:光池收拢到卡 + 6% 脉冲,光池外压暗 0.80→0.90
21
+ // 40–58 相机推进到斜侧特写(18f),高清卡纹理 40–46 交叉淡入
22
+ // 56–66 卡弹起(10f 过冲);66–124 悬停 bob(周期 40f)
23
+ // 68–82 光束 lap1(快、亮);88–108 lap2(慢、弱)
24
+ // 70–84 注记入场(升起 + 解糊),84–96 马克条长出
25
+ // 124–142 reseat(18f);注记同步落回页面;142 触地:落地光一圈 + 微压
26
+ // 142–172 hold:相机锁死,只剩光柱里浮尘与光池极缓呼吸
27
+ import React from 'react';
28
+ import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion';
29
+ import { PageCam2D, CamKey2D } from '../../_fixtures/PageCam2D';
30
+ import { EASE, FONT, Grain, ramp } from '../../_fixtures/Polish';
31
+ import { Dust, LOOKS, alpha } from '../../_fixtures/Look';
32
+ import layout from '../../_textures/live-layout.json';
33
+
34
+ export const SPOTLIGHT_HERO_CARD_DURATION = 172;
35
+
36
+ const L = LOOKS.graphite;
37
+ const GOLD = L.accent2; // 香槟金:光束 / 马克条 / 落地光
38
+ const BEAM_CORE = 'rgba(255,250,238,0.98)';
39
+ const LAMP = '255,238,212'; // 钨丝暖白
40
+ const PATCH = 'oklch(97.5% 0.008 82)';
41
+
42
+ const PAGE_H = layout.projects.pageH;
43
+ const MAIN = 3;
44
+ const CARD = layout.projects.cards[MAIN];
45
+ const MCX = CARD.x + CARD.w / 2; // ≈ 960
46
+ const MCY = CARD.y + CARD.h / 2; // 772
47
+ const RADIUS = 16;
48
+
49
+ // —— 节拍 ——
50
+ const LOCK = 34;
51
+ const PUSH0 = 40;
52
+ const PUSH1 = 58;
53
+ const RISE0 = 56;
54
+ const RISE1 = 66;
55
+ const RESEAT0 = 124;
56
+ const LAND = 142;
57
+
58
+ const CAM_KEYS: CamKey2D[] = [
59
+ { frame: 0, cx: 960, cy: 600, zoom: 0.8, rotX: 0, rotY: 0, rotZ: 0, persp: 1200 },
60
+ { frame: PUSH0, cx: 960, cy: 600, zoom: 0.8, rotX: 0, rotY: 0, rotZ: 0, persp: 1200 },
61
+ { frame: PUSH1, cx: MCX - 105, cy: MCY - 10, zoom: 2.6, rotX: 8, rotY: 34, rotZ: 2, persp: 1200 },
62
+ { frame: SPOTLIGHT_HERO_CARD_DURATION, cx: MCX - 105, cy: MCY - 10, zoom: 2.6, rotX: 8, rotY: 34, rotZ: 2, persp: 1200 },
63
+ ];
64
+ const PUSH_EASE = Easing.bezier(0.35, 0, 0.2, 1);
65
+ const POP_EASE = Easing.bezier(0.2, 1.25, 0.3, 1);
66
+ const RESEAT_EASE = Easing.bezier(0.4, 0, 0.3, 1.05);
67
+
68
+ const clampOpt = { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } as const;
69
+
70
+ // 页面相机的纯函数版(与 PageCam2D 同一套插值与 3D 坐标数学),供注记层复用同一台相机
71
+ const camAt = (frame: number) => {
72
+ let a = CAM_KEYS[0];
73
+ let b = CAM_KEYS[CAM_KEYS.length - 1];
74
+ for (let i = 0; i < CAM_KEYS.length - 1; i++) {
75
+ if (frame >= CAM_KEYS[i].frame && frame <= CAM_KEYS[i + 1].frame) { a = CAM_KEYS[i]; b = CAM_KEYS[i + 1]; break; }
76
+ }
77
+ const t = a.frame === b.frame ? 1 : interpolate(frame, [a.frame, b.frame], [0, 1], { ...clampOpt, easing: PUSH_EASE });
78
+ const m = (x?: number, y?: number) => (x ?? 0) + ((y ?? 0) - (x ?? 0)) * t;
79
+ return { cx: m(a.cx, b.cx), cy: m(a.cy, b.cy), zoom: m(a.zoom, b.zoom), rotX: m(a.rotX, b.rotX), rotY: m(a.rotY, b.rotY), rotZ: m(a.rotZ, b.rotZ), persp: m(a.persp, b.persp) };
80
+ };
81
+ const NoteCam: React.FC<{ frame: number; children: React.ReactNode }> = ({ frame, children }) => {
82
+ const c = camAt(frame);
83
+ return (
84
+ <AbsoluteFill style={{ overflow: 'hidden', pointerEvents: 'none' }}>
85
+ <div style={{ position: 'absolute', inset: 0, perspective: `${c.persp * c.zoom}px`, perspectiveOrigin: '960px 540px' }}>
86
+ <div style={{
87
+ position: 'absolute', width: 1920, height: PAGE_H, zoom: c.zoom, transformOrigin: `${c.cx}px ${c.cy}px`, transformStyle: 'preserve-3d',
88
+ transform: `translate(${960 / c.zoom - c.cx}px, ${540 / c.zoom - c.cy}px) rotateY(${c.rotY}deg) rotateX(${c.rotX}deg) rotateZ(${c.rotZ}deg)`,
89
+ }}>
90
+ {children}
91
+ </div>
92
+ </div>
93
+ </AbsoluteFill>
94
+ );
95
+ };
96
+
97
+ export const SpotlightHeroCard: React.FC = () => {
98
+ const frame = useCurrentFrame();
99
+
100
+ // --- 开灯:亮 → 回闪 → 稳(舞台灯推闸) ---
101
+ const lamp = interpolate(frame, [1, 3, 4, 6], [0, 1, 0.62, 1], clampOpt);
102
+
103
+ // --- 光池游走(屏幕空间 %):3 个中间站,站间短停 → 锁定卡心 → 随推进移到画面中 ---
104
+ const ST = [4, 10, 13, 19, 22, 28, LOCK, PUSH1];
105
+ const spotX = interpolate(frame, ST, [24, 24, 72, 72, 38, 38, 50, 60], { ...clampOpt, easing: EASE.smooth });
106
+ const spotY = interpolate(frame, ST, [30, 30, 40, 40, 62, 62, 64, 55], { ...clampOpt, easing: EASE.smooth });
107
+ const poolBase = interpolate(frame, [22, LOCK, PUSH1], [400, 300, 470], { ...clampOpt, easing: EASE.swift });
108
+ const pulse = interpolate(frame, [LOCK, LOCK + 4, LOCK + 10], [0, 0.06, 0], clampOpt);
109
+ const breathe = 1 + 0.015 * Math.sin((frame - LAND) / 14) * ramp(frame, LAND, 20, EASE.out);
110
+ const poolRx = poolBase * (1 + pulse) * breathe;
111
+ const poolRy = poolBase * interpolate(frame, [PUSH0, PUSH1], [0.8, 0.92], clampOpt) * (1 + pulse) * breathe;
112
+ const dark = interpolate(frame, [0, LOCK, PUSH1], [0.9, 0.92, 0.94], clampOpt); // 光池外压暗
113
+ // 锁定后:屏幕空间的圆光池 → 页面空间的"卡形光"(同一台相机、卡形软孔)。卡在 z 上高于这层暗场,
114
+ // 所以卡面从边到边全亮、原色对比;衰减只发生在卡外。推进期间两套灯交叉过渡。
115
+ const cardLight = ramp(frame, LOCK + 4, PUSH1 - LOCK - 4, EASE.smooth);
116
+ const holdBreath = 1 + 0.012 * Math.sin((frame - LAND) / 14) * ramp(frame, LAND, 20, EASE.out);
117
+
118
+ // --- 卡:rise → hover → reseat ---
119
+ const rise = interpolate(frame, [RISE0, RISE1], [0, 1], { ...clampOpt, easing: POP_EASE });
120
+ const reseat = interpolate(frame, [RESEAT0, LAND], [0, 1], { ...clampOpt, easing: RESEAT_EASE });
121
+ const lift = rise * (1 - reseat);
122
+ const bob = Math.sin(((frame - RISE1) / 40) * Math.PI * 2) * 4 * lift;
123
+ const z = 110 * lift + bob;
124
+ const landed = frame >= LAND;
125
+ const press = interpolate(frame, [LAND - 4, LAND - 1, LAND], [1, 0.997, 1], clampOpt);
126
+ // 投影:光从上方偏右来 → 影子落向左下,随高度变大变虚
127
+ const shadow = `${-10 * lift}px ${10 * lift}px ${12 + 12 * lift}px rgba(10,8,6,${0.35 * lift}), ${-36 * lift}px ${48 * lift}px ${90 * lift}px rgba(10,8,6,${0.42 * lift})`;
128
+
129
+ const slotVis = Math.min(1, rise * 2) * (1 - reseat);
130
+ const landPulse = interpolate(frame, [LAND - 4, LAND, LAND + 14], [0, 1, 0], clampOpt);
131
+ const slotEdge = Math.min(1, 0.45 * (1 - reseat)) + landPulse * 0.5;
132
+
133
+ // --- 轮廓光束两圈 ---
134
+ const beam1Prog = interpolate(frame, [68, 82], [0, 1], { ...clampOpt, easing: EASE.linear });
135
+ const beam1On = frame >= 67 && frame <= 83;
136
+ const beam2Prog = interpolate(frame, [88, 108], [0, 1], { ...clampOpt, easing: EASE.swift });
137
+ const beam2On = frame >= 87 && frame <= 109;
138
+ const beamTrail = interpolate(frame, [108, 122], [0.4, 0], clampOpt);
139
+ const bw = CARD.w + 6;
140
+ const bh = CARD.h + 6;
141
+
142
+ const hiresIn = interpolate(frame, [PUSH0, PUSH0 + 6], [0, 1], clampOpt);
143
+ const rimOn = 0.5 * Math.min(1, lift + ramp(frame, PUSH0, 16, EASE.linear));
144
+
145
+ // --- 注记 ---
146
+ const noteIn = ramp(frame, 70, 14, EASE.out);
147
+ const noteSettle = interpolate(frame, [RESEAT0 - 4, LAND], [0, 1], { ...clampOpt, easing: RESEAT_EASE });
148
+ const noteZ = 4 + (88 + Math.sin(((frame - 70) / 44) * Math.PI * 2) * 3) * (1 - noteSettle);
149
+ const hl = ramp(frame, 84, 12, EASE.swift);
150
+
151
+ // --- 体积光柱:光源在画面上方偏右,打到光池 ---
152
+ const px = (spotX / 100) * 1920;
153
+ const py = (spotY / 100) * 1080;
154
+ const sx = px + 420;
155
+ const sy = -720;
156
+ const coneW = poolRx * 0.6;
157
+ const cone = `${sx - 26}px ${sy}px, ${sx + 26}px ${sy}px, ${px + coneW}px ${py}px, ${px - coneW}px ${py}px`;
158
+
159
+ return (
160
+ <AbsoluteFill style={{ backgroundColor: L.bg[2] }}>
161
+ <PageCam2D src="textures/live/projects-full.png" pageH={PAGE_H} keys={CAM_KEYS} ease={PUSH_EASE} bg={L.bg[1]}>
162
+ {/* 倾斜平面近端(下缘)的一线轮廓光 */}
163
+ <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 8, background: 'rgba(255,240,220,0.8)', filter: 'blur(6px)', opacity: rimOn, pointerEvents: 'none' }} />
164
+
165
+ {/* 页面空间暗场:整页压暗,只在卡位挖一个卡形软孔(紧孔 σ22 + 一圈 15% 的宽溢光 σ60);translateZ(1) 垫在卡之下 */}
166
+ {cardLight > 0.001 ? (
167
+ <svg width={1920} height={PAGE_H} style={{ position: 'absolute', left: 0, top: 0, transform: 'translateZ(1px)', opacity: cardLight, pointerEvents: 'none' }}>
168
+ <defs>
169
+ <filter id="shc-tight" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="22" /></filter>
170
+ <filter id="shc-wide" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="60" /></filter>
171
+ <mask id="shc-hole" maskUnits="userSpaceOnUse" x={0} y={0} width={1920} height={PAGE_H}>
172
+ <rect x={0} y={0} width={1920} height={PAGE_H} fill="white" />
173
+ <rect x={CARD.x - 60} y={CARD.y - 50} width={CARD.w + 120} height={CARD.h + 100} rx={70} fill="#262626" filter="url(#shc-wide)" />
174
+ <rect x={CARD.x - 14} y={CARD.y - 14} width={CARD.w + 28} height={CARD.h + 28} rx={RADIUS + 14} fill="black" filter="url(#shc-tight)" />
175
+ </mask>
176
+ </defs>
177
+ <rect x={0} y={0} width={1920} height={PAGE_H} fill="rgb(14,12,10)" fillOpacity={Math.min(0.97, 0.94 * holdBreath)} mask="url(#shc-hole)" />
178
+ </svg>
179
+ ) : null}
180
+
181
+ <div style={{ transformStyle: 'preserve-3d' }}>
182
+ {/* 卡起飞后的原位补丁 + 香槟色呼吸描边 */}
183
+ {slotVis > 0.02 || landPulse > 0.02 ? (
184
+ <div style={{
185
+ position: 'absolute', left: CARD.x - 2, top: CARD.y - 2, width: CARD.w + 4, height: CARD.h + 4, transform: 'translateZ(1.5px)',
186
+ background: slotVis > 0.02 ? PATCH : 'transparent', borderRadius: RADIUS,
187
+ boxShadow: `inset 0 0 26px rgba(150,110,40,${(0.14 * slotEdge).toFixed(3)})`, opacity: Math.max(slotVis, landPulse),
188
+ }}>
189
+ <div style={{ position: 'absolute', inset: 0, borderRadius: RADIUS, border: `1.5px solid ${GOLD}`, opacity: slotEdge, boxShadow: landPulse > 0.02 ? `0 0 ${(24 * landPulse).toFixed(1)}px ${alpha(GOLD, 0.8)}` : undefined }} />
190
+ </div>
191
+ ) : null}
192
+
193
+ {/* 悬浮的卡 */}
194
+ <div style={{
195
+ position: 'absolute', left: CARD.x, top: CARD.y, width: CARD.w, height: CARD.h,
196
+ transform: `translateZ(${(z + 2).toFixed(2)}px) scale(${press})`, transformOrigin: 'center center', transformStyle: 'preserve-3d',
197
+ }}>
198
+ <div style={{ position: 'absolute', inset: 0, borderRadius: RADIUS, overflow: 'hidden', boxShadow: landed ? 'none' : shadow }}>
199
+ <Img src={staticFile(`textures/live/${CARD.file}`)} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }} />
200
+ <Img src={staticFile('textures/live/card4-hires.png')} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block', opacity: hiresIn }} />
201
+ {/* 悬浮时卡面受光:右上角暖光 → 左下渐暗 */}
202
+ <div style={{ position: 'absolute', inset: 0, background: `linear-gradient(200deg, rgba(${LAMP},0.35), rgba(${LAMP},0) 45%, rgba(20,16,10,0.08) 100%)`, opacity: lift, pointerEvents: 'none' }} />
203
+ </div>
204
+ <div style={{ position: 'absolute', inset: 0, borderRadius: RADIUS, // 轮廓光:一圈暖白发丝边 + 极淡外溢,让卡的轮廓在暗页上读得清(锁定后亮起)
205
+ boxShadow: `inset 0 0 0 1px rgba(255,255,255,${(0.7 * lift).toFixed(3)}), 0 0 0 1.5px rgba(255,236,205,${(0.7 * cardLight).toFixed(3)}), 0 0 44px rgba(255,214,160,${(0.18 * cardLight).toFixed(3)})`, pointerEvents: 'none' }} />
206
+
207
+ {/* 轮廓光束:SVG 圆角矩形,pathLength=1 的行进弧段 */}
208
+ {(beam1On || beam2On) && lift > 0.4 ? (
209
+ <svg width={bw} height={bh} viewBox={`0 0 ${bw} ${bh}`} style={{
210
+ position: 'absolute', left: -3, top: -3, overflow: 'visible', pointerEvents: 'none', opacity: beam1On ? 1 : 0.62,
211
+ filter: `drop-shadow(0 0 6px ${alpha(GOLD, 0.9)}) drop-shadow(0 0 18px rgba(255,236,200,0.55))`,
212
+ }}>
213
+ <rect x={2} y={2} width={bw - 4} height={bh - 4} rx={RADIUS} fill="none" stroke={GOLD} strokeWidth={beam1On ? 5 : 3.5} strokeLinecap="round"
214
+ pathLength={1} strokeDasharray="0.16 1" strokeDashoffset={-(beam1On ? beam1Prog : beam2Prog)} />
215
+ <rect x={2} y={2} width={bw - 4} height={bh - 4} rx={RADIUS} fill="none" stroke={BEAM_CORE} strokeWidth={beam1On ? 2.5 : 1.75} strokeLinecap="round"
216
+ pathLength={1} strokeDasharray="0.16 1" strokeDashoffset={-(beam1On ? beam1Prog : beam2Prog)} />
217
+ </svg>
218
+ ) : null}
219
+ {beamTrail > 0.01 ? (
220
+ <div style={{ position: 'absolute', inset: -3, borderRadius: RADIUS + 3, border: `1.5px solid ${GOLD}`, opacity: beamTrail, pointerEvents: 'none' }} />
221
+ ) : null}
222
+ </div>
223
+ </div>
224
+
225
+ </PageCam2D>
226
+
227
+ {/* —— 灯光(屏幕空间)——
228
+ ① 关灯:光池外 multiply 压暗到 ~14%(暖黑而非纯黑,保色相);
229
+ ② 光池:钨丝暖白 soft-light 提亮中间调 + 极弱 screen 抬亮;
230
+ ③ 体积光柱 + 柱内浮尘(screen)。 */}
231
+ <AbsoluteFill style={{
232
+ // 近高斯的衰减:中心完全透明 → 边缘压到 ~10% 亮度;多段 stop 让光池边缘软而不是一圈硬边
233
+ background: `radial-gradient(${(poolRx * 1.35).toFixed(1)}px ${(poolRy * 1.35).toFixed(1)}px at ${spotX}% ${spotY}%, rgba(14,12,10,0) 0%, rgba(14,12,10,0) 26%, rgba(14,12,10,${(dark * 0.25).toFixed(3)}) 44%, rgba(14,12,10,${(dark * 0.62).toFixed(3)}) 62%, rgba(14,12,10,${(dark * 0.9).toFixed(3)}) 80%, rgba(14,12,10,${dark.toFixed(3)}) 100%)`,
234
+ mixBlendMode: 'multiply', pointerEvents: 'none', opacity: lamp * (1 - cardLight),
235
+ }} />
236
+ {/* 开灯前:整页压暗(灯推闸时由它和上一层交接) */}
237
+ <AbsoluteFill style={{ background: 'rgba(14,12,10,1)', mixBlendMode: 'multiply', opacity: 0.84 * (1 - lamp), pointerEvents: 'none' }} />
238
+ {/* 光池里的钨丝暖色(soft-light,低强度——白卡不被打爆) */}
239
+ <AbsoluteFill style={{
240
+ background: `radial-gradient(${(poolRx * 1.2).toFixed(1)}px ${(poolRy * 1.2).toFixed(1)}px at ${spotX}% ${spotY}%, rgba(${LAMP},0.24) 0%, rgba(${LAMP},0.12) 50%, rgba(${LAMP},0) 80%)`,
241
+ mixBlendMode: 'soft-light', pointerEvents: 'none', opacity: lamp * (1 - cardLight), // 锁定后退掉:卡上不叠任何泛光,文字保持原生对比
242
+ }} />
243
+ {/* 体积光柱:梯形 + 纵向渐变 + 大半径模糊;推进后光柱变淡(镜头离光源更近、柱身出画) */}
244
+ <AbsoluteFill style={{ mixBlendMode: 'screen', pointerEvents: 'none', opacity: lamp * (1 - 0.45 * ramp(frame, PUSH0, 18, EASE.smooth)) }}>
245
+ {/* 模糊放在外层、裁切放在内层:柱身边缘是软的 */}
246
+ <div style={{ position: 'absolute', inset: 0, filter: 'blur(28px)' }}>
247
+ <div style={{
248
+ position: 'absolute', inset: 0, clipPath: `polygon(${cone})`,
249
+ background: `linear-gradient(${(Math.atan2(py - sy, px - sx) * 180 / Math.PI - 90).toFixed(1)}deg, rgba(${LAMP},0.34) 0%, rgba(${LAMP},0.16) 60%, rgba(${LAMP},0.06) 100%)`,
250
+ }} />
251
+ </div>
252
+ <div style={{ position: 'absolute', inset: 0, clipPath: `polygon(${cone})` }}>
253
+ <Dust look={L} count={36} seed={4} drift={0.3} opacity={0.6} color="#fff1dc" />
254
+ </div>
255
+ </AbsoluteFill>
256
+ {/* 注记层:与页面同一台相机(camAt 复刻 PageCam2D 的坐标数学),但画在灯光层之上——
257
+ 它是"自发光"的字,不被关灯的 multiply 压暗;暗色衬底负责把背后的邻卡字压下去 */}
258
+ <NoteCam frame={frame}>
259
+ {/* 3D 注记:卡左侧,同一 3D 空间、同一台相机;reseat 时一起落回页面 */}
260
+ {frame >= 70 ? (
261
+ <div style={{ transformStyle: 'preserve-3d', pointerEvents: 'none' }}>
262
+ {/* 注记投在页面上的软影(落回页面时收拢消失) */}
263
+ <div style={{
264
+ position: 'absolute', left: 520, top: 760, width: 240, height: 70, transform: 'translateZ(2px)',
265
+ background: 'radial-gradient(ellipse at 50% 50%, rgba(0,0,0,0.55), transparent 70%)', filter: 'blur(12px)',
266
+ opacity: 0.5 * noteIn * (1 - noteSettle),
267
+ }} />
268
+ {/* 暗色衬底:注记压在邻卡文字上,没有衬底就和背后的字打架(Q11);同一 3D 平面、同一台相机 */}
269
+ <div style={{
270
+ position: 'absolute', left: 400, top: 600, width: 380, height: 240, // 右缘止于卡左缘(x=781)之前,不压卡面
271
+ transform: `translateZ(${(noteZ - 1).toFixed(2)}px) translateY(${((1 - noteIn) * 26).toFixed(2)}px)`,
272
+ background: 'radial-gradient(ellipse 50% 50% at 52% 50%, rgba(16,14,12,0.97) 0%, rgba(16,14,12,0.9) 60%, rgba(16,14,12,0) 100%)',
273
+ filter: 'blur(6px)', opacity: noteIn,
274
+ }} />
275
+ <div style={{
276
+ position: 'absolute', left: 528, top: 662, width: 'max-content', whiteSpace: 'nowrap',
277
+ transform: `translateZ(${noteZ.toFixed(2)}px) translateY(${((1 - noteIn) * 26).toFixed(2)}px)`,
278
+ opacity: noteIn, filter: noteIn < 1 ? `blur(${((1 - noteIn) * 4).toFixed(2)}px)` : undefined,
279
+ fontFamily: FONT.sans, letterSpacing: '-0.035em', lineHeight: 1.1,
280
+ }}>
281
+ <div style={{ fontSize: 34, fontWeight: 760, color: '#f6f3ec', textShadow: '0 2px 18px rgba(0,0,0,0.6)' }}>Your product,</div>
282
+ <div style={{ position: 'relative', display: 'inline-block', marginTop: 2 }}>
283
+ <div style={{ position: 'absolute', left: -6, top: '8%', bottom: '2%', width: `calc(${hl.toFixed(4)} * (100% + 12px))`, background: GOLD, borderRadius: 4 }} />
284
+ <div style={{ position: 'relative', fontSize: 34, fontWeight: 760, color: hl > 0.55 ? '#14110c' : '#f6f3ec' }}>in motion.</div>
285
+ </div>
286
+ </div>
287
+ </div>
288
+ ) : null}
289
+ </NoteCam>
290
+ <Grain opacity={0.07} blend="soft-light" />
291
+ </AbsoluteFill>
292
+ );
293
+ };