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,359 +1,359 @@
1
- // mosaic-reframe — 12 张瓦片在三种排版间连续变形:规则网格 → feature mosaic → 对角瀑布串。
2
- // 位置 / 宽高 / 旋转各自独立插值(不走 transform 整体缩放),逐片错峰,段间留 hold。
3
- //
4
- // 第二轮重设计(暖沙 · 胶片分镜板):
5
- // - look = sand(米色 · 赤陶)。主体是 video-shotcraft 的一块分镜板(12 个镜头的定帧):12 张程序绘制的
6
- // "胶片照片"(落日海面 / 沙丘 / 拱门 / 雾山 / 泳池 / 柑橘静物 / 棕榈影 / 麦田八式,暖调统一),
7
- // 1920 原生坐标直接排版(不再从 480 设计坐标放大)。
8
- // - 因果:右上角分段控件 Grid / Mosaic / Cascade 是"布局的开关"——赤陶色指示胶囊先滑到下一档
9
- // (父先动),瓦片晚 4f 开始重排(子跟随),让观众看见"一次切换 → 整版重新思考"。
10
- // - 三态三种语气:A 规则网格(档案)→ B feature mosaic(首图占 3×2,压上衬线大字图注 = 策展)
11
- // → C 对角瀑布(每张变成带白边的相纸,-15° 起每张 +3° 递增旋转,像一手牌被摊开 = 态度),
12
- // C 态左下留白处升起衬线大标题「Every shot, in sequence.」,尾帧是一张完整的分镜海报。
13
- // - 运动:每片 x/y 用强 in-out(0.75,0,0.15,1)果断换位,w/h 晚 2f、旋转晚 4f 收敛(位置先到);
14
- // 换位途中按段进度 sin 包络"抬起"(放大 3.5% + 阴影变大变虚),落位贴回;B→C 旋转带一次轻过冲。
15
- // - 错峰:A→B 自左上主图起按序号波浪扫过(先密后疏);B→C 像发牌一样按序号依次摊开。
16
- //
17
- // 时间表(30fps,共 214f):
18
- // 0–22 预备:舞台、页眉与控件在场;12 张照片自左上沿对角线错峰升起(第 0 帧已有首张起始态)
19
- // 22–52 hold A:读网格(全程相机极缓推近 1→1.025)
20
- // 52–64 控件胶囊 Grid→Mosaic(snappy 12f)
21
- // 56–92 A→B 重排:每片 26f,错峰 10f;84–104 主图图注逐词升起
22
- // 92–128 hold B:读 mosaic
23
- // 128–140 控件胶囊 Mosaic→Cascade;图注 128 起退场
24
- // 132–176 B→C 摊牌:每片 30f,等间隔错峰 14f;相纸白边 0→14px;158–186 大标题逐词升起、副行淡入
25
- // 180–214 hold C:海报落定
26
- import React from 'react';
27
- import { useCurrentFrame } from 'remotion';
28
- import { EASE, FONT, Grain, bezier, mix, ramp, softShadow } from '../../_fixtures/Polish';
29
- import { LOOKS, SERIF, Stage, TextReveal, alpha, stagger, type } from '../../_fixtures/Look';
30
- import { BRAND, PITCH, ShotcraftMark } from '../../_fixtures/Brand';
31
-
32
- export const MOSAIC_REFRAME_DURATION = 214;
33
-
34
- const L = LOOKS.sand;
35
- const N = 12;
36
-
37
- // ───────────── 时间常量 ─────────────
38
- const T_AB = 52; // 控件切到 Mosaic
39
- const T_BC = 128; // 控件切到 Cascade
40
- const LAG = 4; // 瓦片晚于控件起跳的帧数(父先动、子跟随)
41
- const D_AB = 26;
42
- const D_BC = 30;
43
- const MOVE = bezier(0.75, 0, 0.15, 1); // 果断换位:慢起 → 急走 → 长尾软落
44
- const ROT_SETTLE = bezier(0.45, 0, 0.3, 1.22); // 旋转晚到并轻过冲一次
45
-
46
- // ───────────── 三套布局(1920×1080 原生像素)─────────────
47
- type Box = { x: number; y: number; w: number; h: number; rot: number };
48
- const X0 = 96, X1 = 1824, Y0 = 212, Y1 = 984; // 内容区:安全边距 96,页眉下方
49
-
50
- // A:4×3 规则网格
51
- const AG = 24;
52
- const AW = (X1 - X0 - 3 * AG) / 4, AH = (Y1 - Y0 - 2 * AG) / 3;
53
- const A: Box[] = Array.from({ length: N }, (_, i) => ({
54
- x: X0 + (i % 4) * (AW + AG), y: Y0 + Math.floor(i / 4) * (AH + AG), w: AW, h: AH, rot: 0,
55
- }));
56
-
57
- // B:6×4 单元格 feature mosaic,首片占 3×2
58
- const BG = 16;
59
- const UW = (X1 - X0 - 5 * BG) / 6, UH = (Y1 - Y0 - 3 * BG) / 4;
60
- const SLOTS: [number, number, number, number][] = [
61
- [0, 0, 3, 2], [3, 0, 1, 1], [4, 0, 1, 1], [5, 0, 1, 1], [3, 1, 2, 1], [5, 1, 1, 1],
62
- [0, 2, 1, 1], [1, 2, 2, 1], [3, 2, 1, 2], [4, 2, 2, 1], [0, 3, 3, 1], [4, 3, 2, 1],
63
- ];
64
- const B: Box[] = SLOTS.map(([c, r, cw, rh]) => ({
65
- x: X0 + c * (UW + BG), y: Y0 + r * (UH + BG), w: cw * UW + (cw - 1) * BG, h: rh * UH + (rh - 1) * BG, rot: 0,
66
- }));
67
-
68
- // C:对角瀑布串——竖幅相纸沿 (850,214)→(1724,930) 摊开,旋转 -15° 起每张 +3° 递增
69
- const CW = 300, CH = 372;
70
- const C: Box[] = Array.from({ length: N }, (_, i) => {
71
- const s = i / (N - 1);
72
- const cx = 850 + 874 * s, cy = 214 + 716 * s;
73
- return { x: cx - CW / 2, y: cy - CH / 2, w: CW, h: CH, rot: -15 + i * 3 };
74
- });
75
-
76
- // ───────────── 照片(程序插画,viewBox 160×100 + slice ≈ object-fit: cover)─────────────
77
- type Kind = 'sun' | 'dune' | 'arch' | 'ridge' | 'pool' | 'citrus' | 'palm' | 'field';
78
- const PHOTOS: { kind: Kind; v: number }[] = [
79
- { kind: 'sun', v: 0 }, { kind: 'dune', v: 0 }, { kind: 'pool', v: 0 }, { kind: 'arch', v: 0 },
80
- { kind: 'ridge', v: 0 }, { kind: 'citrus', v: 0 }, { kind: 'palm', v: 0 }, { kind: 'field', v: 0 },
81
- { kind: 'dune', v: 1 }, { kind: 'arch', v: 1 }, { kind: 'sun', v: 1 }, { kind: 'ridge', v: 1 },
82
- ];
83
-
84
- const Photo: React.FC<{ i: number }> = ({ i }) => {
85
- const { kind, v } = PHOTOS[i];
86
- const id = `mr${i}`;
87
- const g = (stops: [string, number][], vertical = true) => (
88
- <linearGradient id={`${id}g`} x1="0" y1="0" x2={vertical ? 0 : 1} y2={vertical ? 1 : 0}>
89
- {stops.map(([c, o], k) => <stop key={k} offset={o} stopColor={c} />)}
90
- </linearGradient>
91
- );
92
- let body: React.ReactNode = null;
93
- let defs: React.ReactNode = null;
94
- if (kind === 'sun') {
95
- const warm = v === 0;
96
- const sx = warm ? 126 : 80; // 主图的太阳偏右,给左下图注让位
97
- defs = g(warm ? [['#f6c58e', 0], ['#ec8f5b', 0.55], ['#d8643f', 1]] : [['#f4d3b0', 0], ['#e6a07a', 0.6], ['#c97a62', 1]]);
98
- body = (
99
- <>
100
- <rect width="160" height="64" fill={`url(#${id}g)`} />
101
- <circle cx={sx} cy="56" r={warm ? 15 : 11} fill="#fff1d6" />
102
- <circle cx={sx} cy="56" r={warm ? 26 : 20} fill="#fff1d6" opacity="0.18" />
103
- <rect y="60" width="160" height="40" fill={warm ? '#3e4a63' : '#5a5f78'} />
104
- <rect y="60" width="160" height="6" fill={warm ? '#566078' : '#6e728a'} opacity="0.8" />
105
- {[63, 67, 72, 78, 85].map((y, k) => (
106
- <rect key={k} x={sx - (16 - k * 2.2)} y={y} width={2 * (16 - k * 2.2)} height={1.2 + k * 0.2} rx="0.6" fill="#ffe2b4" opacity={0.75 - k * 0.12} />
107
- ))}
108
- </>
109
- );
110
- } else if (kind === 'dune') {
111
- const a = v === 0;
112
- defs = g(a ? [['#f3dcc0', 0], ['#ecc39a', 1]] : [['#e9d2c4', 0], ['#e1b6a0', 1]]);
113
- body = (
114
- <>
115
- <rect width="160" height="100" fill={`url(#${id}g)`} />
116
- <circle cx={a ? 118 : 40} cy="24" r="8" fill="#fff4e2" opacity="0.9" />
117
- <path d="M0 62 C 30 46, 60 44, 92 58 S 140 66, 160 52 V100 H0Z" fill={a ? '#dc9a68' : '#cf8f72'} />
118
- <path d="M0 74 C 40 60, 70 64, 100 76 S 140 82, 160 70 V100 H0Z" fill={a ? '#c4733f' : '#b4705a'} />
119
- <path d="M30 100 C 60 80, 100 78, 160 86 V100Z" fill={a ? '#8f4a2b' : '#7f4c3f'} />
120
- <path d="M0 62 C 30 46, 60 44, 92 58" fill="none" stroke="#fbe3c4" strokeWidth="0.8" opacity="0.7" />
121
- </>
122
- );
123
- } else if (kind === 'arch') {
124
- const a = v === 0;
125
- defs = g(a ? [['#efd2b4', 0], ['#e2b48f', 1]] : [['#e9c9c0', 0], ['#d9a497', 1]], false);
126
- body = (
127
- <>
128
- <rect width="160" height="100" fill={`url(#${id}g)`} />
129
- <path d="M58 100 V52 A22 22 0 0 1 102 52 V100Z" fill={a ? '#6e3f2b' : '#5d3a3a'} />
130
- <path d="M66 100 V56 A14 14 0 0 1 94 56 V100Z" fill={a ? '#f1c795' : '#f0c2a8'} opacity="0.9" />
131
- <polygon points="0,0 70,0 20,100 0,100" fill="#ffffff" opacity="0.12" />
132
- <polygon points="102,100 160,40 160,100" fill={a ? '#b97d58' : '#a8706a'} opacity="0.45" />
133
- <rect y="92" width="160" height="8" fill={a ? '#c08a62' : '#b1817a'} />
134
- </>
135
- );
136
- } else if (kind === 'ridge') {
137
- const a = v === 0;
138
- defs = g(a ? [['#e9e4dc', 0], ['#c9cfd6', 1]] : [['#efe0d0', 0], ['#d7c4b4', 1]]);
139
- body = (
140
- <>
141
- <rect width="160" height="100" fill={`url(#${id}g)`} />
142
- <polygon points="0,62 26,40 46,54 74,28 104,52 126,38 160,56 160,100 0,100" fill={a ? '#a9b4c2' : '#c4ab98'} />
143
- <polygon points="0,74 34,54 62,68 96,46 130,66 160,58 160,100 0,100" fill={a ? '#7d8ca0' : '#a5846c'} />
144
- <polygon points="0,86 40,70 84,84 120,68 160,80 160,100 0,100" fill={a ? '#4f5d72' : '#7a5a46'} />
145
- <rect y="56" width="160" height="10" fill="#ffffff" opacity="0.18" />
146
- </>
147
- );
148
- } else if (kind === 'pool') {
149
- defs = g([['#6cc3c1', 0], ['#2f8c96', 1]]);
150
- body = (
151
- <>
152
- <rect width="160" height="100" fill={`url(#${id}g)`} />
153
- <rect y="0" width="160" height="22" fill="#efe2cf" />
154
- <rect y="20" width="160" height="3" fill="#d9c7ad" />
155
- {[40, 62, 84].map((y, k) => <rect key={k} x="0" y={y} width="160" height="1.6" fill="#ffffff" opacity="0.35" />)}
156
- <path d="M10 50 Q 40 44 70 52 T 130 50" fill="none" stroke="#ffffff" strokeWidth="1.2" opacity="0.5" />
157
- <path d="M30 72 Q 60 66 90 74 T 150 72" fill="none" stroke="#ffffff" strokeWidth="1" opacity="0.4" />
158
- <polygon points="100,23 160,23 160,100 130,100" fill="#1c5f6c" opacity="0.35" />
159
- </>
160
- );
161
- } else if (kind === 'citrus') {
162
- defs = g([['#f1e3cc', 0], ['#e6d1b2', 1]]);
163
- body = (
164
- <>
165
- <rect width="160" height="100" fill={`url(#${id}g)`} />
166
- <rect y="64" width="160" height="36" fill="#c67a45" />
167
- <rect y="64" width="160" height="2" fill="#e29a63" />
168
- <ellipse cx="74" cy="78" rx="44" ry="5" fill="#8d4f2a" opacity="0.4" />
169
- <circle cx="64" cy="60" r="15" fill="#ef8a36" />
170
- <circle cx="90" cy="64" r="11" fill="#f3a246" />
171
- <circle cx="59" cy="55" r="4" fill="#ffd29a" opacity="0.7" />
172
- <circle cx="87" cy="60" r="3" fill="#ffe0b0" opacity="0.7" />
173
- <path d="M64 45 q 5 -6 11 -4 q -4 6 -11 4z" fill="#5d7a4a" />
174
- </>
175
- );
176
- } else if (kind === 'palm') {
177
- defs = g([['#ecc2aa', 0], ['#e0a68c', 1]], false);
178
- body = (
179
- <>
180
- <rect width="160" height="100" fill={`url(#${id}g)`} />
181
- {[0, 1, 2, 3, 4, 5].map((k) => (
182
- <path key={k} d={`M40 10 Q ${60 + k * 14} ${10 + k * 10} ${78 + k * 16} ${28 + k * 14}`} fill="none" stroke="#b97862" strokeWidth={5 - k * 0.4} strokeLinecap="round" opacity="0.55" />
183
- ))}
184
- <path d="M40 10 L 34 100" stroke="#b97862" strokeWidth="3" opacity="0.5" />
185
- <rect y="88" width="160" height="12" fill="#c98d74" />
186
- </>
187
- );
188
- } else {
189
- defs = g([['#f3e1c0', 0], ['#e9c992', 1]]);
190
- body = (
191
- <>
192
- <rect width="160" height="100" fill={`url(#${id}g)`} />
193
- <rect y="0" width="160" height="40" fill="#e8d7bd" />
194
- <circle cx="128" cy="20" r="7" fill="#fff3dc" />
195
- {Array.from({ length: 9 }, (_, k) => (
196
- <path key={k} d={`M80 40 L ${-60 + k * 35} 100`} stroke="#c49a52" strokeWidth={1.4 + k * 0.1} opacity="0.55" />
197
- ))}
198
- <path d="M0 40 H160" stroke="#b9925a" strokeWidth="1" opacity="0.6" />
199
- </>
200
- );
201
- }
202
- return (
203
- <svg width="100%" height="100%" viewBox="0 0 160 100" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, display: 'block' }}>
204
- <defs>{defs}</defs>
205
- {body}
206
- </svg>
207
- );
208
- };
209
-
210
- // ───────────── 分段控件(布局开关)─────────────
211
- const SEG = ['Grid', 'Mosaic', 'Cascade'];
212
- const SEG_W = 168, SEG_H = 60, SEG_PAD = 6;
213
- const Segmented: React.FC<{ frame: number }> = ({ frame }) => {
214
- const p1 = ramp(frame, T_AB, 12, EASE.snappy);
215
- const p2 = ramp(frame, T_BC, 12, EASE.snappy);
216
- const pos = p1 + p2; // 0 → 1 → 2
217
- // 胶囊在途中横向拉长(像被拽过去),到位收回
218
- const stretch = 1 + 0.18 * (Math.sin(Math.PI * p1) + Math.sin(Math.PI * p2));
219
- const press = (k: number, t: number) => 1 - 0.05 * Math.sin(Math.PI * ramp(frame, t - 3, 8, EASE.linear)) * (k > 0 ? 1 : 0);
220
- return (
221
- <div style={{
222
- position: 'absolute', right: 96, top: 92, width: SEG_W * 3 + SEG_PAD * 2, height: SEG_H + SEG_PAD * 2, borderRadius: 999,
223
- background: alpha('#ffffff', 0.55), boxShadow: `inset 0 0 0 1px ${L.line}, ${softShadow(6, { color: L.shadow, strength: 0.6 })}`,
224
- }}>
225
- <div style={{
226
- position: 'absolute', top: SEG_PAD, left: SEG_PAD + pos * SEG_W, width: SEG_W, height: SEG_H, borderRadius: 999,
227
- background: L.accent, transform: `scaleX(${stretch.toFixed(4)})`,
228
- boxShadow: `0 6px 16px -6px ${alpha(L.accent, 0.7)}, inset 0 1px 0 rgba(255,255,255,0.25)`,
229
- }} />
230
- {SEG.map((s, k) => {
231
- const on = Math.max(0, 1 - Math.abs(pos - k));
232
- return (
233
- <div key={s} style={{
234
- position: 'absolute', top: SEG_PAD, left: SEG_PAD + k * SEG_W, width: SEG_W, height: SEG_H,
235
- display: 'flex', alignItems: 'center', justifyContent: 'center',
236
- ...type(30, 600), letterSpacing: '-0.01em',
237
- color: on > 0.5 ? L.onAccent : L.ink2,
238
- transform: `scale(${(k === 1 ? press(1, T_AB) : k === 2 ? press(2, T_BC) : 1).toFixed(4)})`,
239
- }}>{s}</div>
240
- );
241
- })}
242
- </div>
243
- );
244
- };
245
-
246
- // 瓦片在某帧的几何:A→B、B→C 两段各自的进度,位置 / 宽高 / 旋转错开收敛
247
- const tileAt = (frame: number, i: number) => {
248
- const sAB = T_AB + LAG + stagger(i, N, 10, EASE.out);
249
- const sBC = T_BC + LAG + stagger(i, N, 14, EASE.linear); // 发牌:等间隔依次摊开
250
- const pAB = ramp(frame, sAB, D_AB, MOVE);
251
- const pBC = ramp(frame, sBC, D_BC, MOVE);
252
- const sAB2 = ramp(frame, sAB + 2, D_AB, MOVE); // 宽高晚 2f
253
- const sBC2 = ramp(frame, sBC + 2, D_BC, MOVE);
254
- const rBC = ramp(frame, sBC + 4, D_BC, ROT_SETTLE); // 旋转晚 4f + 过冲
255
- const a = A[i], b = B[i], c = C[i];
256
- // 以中心插值位置(宽高变化时中心走直线,不会"先长后跑")
257
- const cxA = a.x + a.w / 2, cyA = a.y + a.h / 2, cxB = b.x + b.w / 2, cyB = b.y + b.h / 2, cxC = c.x + c.w / 2, cyC = c.y + c.h / 2;
258
- const cx = mix(mix(cxA, cxB, pAB), cxC, pBC);
259
- const cy = mix(mix(cyA, cyB, pAB), cyC, pBC);
260
- const w = mix(mix(a.w, b.w, sAB2), c.w, sBC2);
261
- const h = mix(mix(a.h, b.h, sAB2), c.h, sBC2);
262
- const rot = mix(0, c.rot, rBC);
263
- const lift = Math.max(Math.sin(Math.PI * pAB), Math.sin(Math.PI * pBC));
264
- return { cx, cy, w, h, rot, lift, pBC: sBC2, moving: pBC > 0 };
265
- };
266
-
267
- export const MosaicReframe: React.FC = () => {
268
- const frame = useCurrentFrame();
269
- const cam = mix(1, 1.025, ramp(frame, 0, 214, EASE.smooth)); // 全程极缓推近
270
-
271
- // 主图图注(B 态):84f 起逐词升起,128f 起退场
272
- const capOut = ramp(frame, T_BC, 10, EASE.exit);
273
- // C 态大标题
274
- const HEAD = 158;
275
-
276
- const tiles = Array.from({ length: N }, (_, i) => ({ i, ...tileAt(frame, i) }));
277
- // 叠放次序:B→C 起按序号(后发的牌压在上面);之前主图最高
278
- const inC = frame >= T_BC + LAG;
279
- const z = (i: number) => (inC ? 10 + i : i === 0 ? 30 : 10);
280
-
281
- return (
282
- <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', fontFamily: FONT.sans }}>
283
- <Stage look={L} keyLight={{ x: 0.28, y: 0.02 }} fill={{ x: 0.9, y: 0.95 }} />
284
-
285
- <div style={{ position: 'absolute', inset: 0, transform: `scale(${cam.toFixed(5)})`, transformOrigin: '50% 46%' }}>
286
- {/* 页眉:品牌标志 + 小写字标 + 分镜板名(标志按亮底 light 版;字标与分镜名同一基线)。
287
- 总宽压在 x≈620 以内——C 态首张相纸的左上角在 x≈650,页眉再长会被它盖住 */}
288
- <div style={{ position: 'absolute', left: 96, top: 92, height: 72, display: 'flex', alignItems: 'center', gap: 18, color: L.ink }}>
289
- <ShotcraftMark size={50} tone="light" />
290
- <div style={{ display: 'flex', alignItems: 'baseline', gap: 20 }}>
291
- <span style={{ fontFamily: BRAND.font, fontSize: 36, fontWeight: 700, letterSpacing: '0.03em', lineHeight: 1 }}>{BRAND.name}</span>
292
- <span style={{ ...type(32, 450), color: L.ink2 }}>Storyboard</span>
293
- </div>
294
- </div>
295
- <Segmented frame={frame} />
296
-
297
- {/* C 态大标题(左下留白处) */}
298
- <div style={{ position: 'absolute', left: 96, top: 676, color: L.ink }}>
299
- <div style={{ ...type(124, 500, { serif: true }), letterSpacing: '-0.035em', lineHeight: 1.0 }}>
300
- <TextReveal text="Every shot," start={HEAD} by="word" variant="rise" each={20} gap={5} />
301
- <br />
302
- <TextReveal text="in sequence." start={HEAD + 6} by="word" variant="rise" each={20} gap={5}
303
- unitStyle={() => ({ fontStyle: 'italic', color: L.accent })} />
304
- </div>
305
- <div style={{
306
- ...type(32, 450), color: L.ink2, marginTop: 26,
307
- opacity: ramp(frame, HEAD + 14, 16, EASE.out), transform: `translateY(${mix(12, 0, ramp(frame, HEAD + 14, 18, EASE.snappy)).toFixed(2)}px)`,
308
- }}>{PITCH.en.taglines[4]}</div>
309
- </div>
310
-
311
- {tiles.map(({ i, cx, cy, w, h, rot, lift, pBC }) => {
312
- // 开场:沿对角线错峰升起(从左上到右下)
313
- const order = (i % 4) + Math.floor(i / 4);
314
- const inP = ramp(frame, stagger(order, 6, 14, EASE.out) - 2, 16, EASE.snappy);
315
- const pad = 14 * pBC; // 相纸白边
316
- const radius = mix(16, 6, pBC);
317
- const scale = mix(0.94, 1, inP) * (1 + 0.035 * lift);
318
- const elev = 6 + 34 * lift + 8 * pBC;
319
- return (
320
- <div key={i} style={{
321
- position: 'absolute', left: cx - w / 2, top: cy - h / 2 + (1 - inP) * 40, width: w, height: h,
322
- transform: `rotate(${rot.toFixed(3)}deg) scale(${scale.toFixed(4)})`,
323
- opacity: inP, zIndex: z(i), borderRadius: radius,
324
- background: L.surface, boxShadow: softShadow(elev, { color: L.shadow, strength: 0.9 + 0.5 * pBC }),
325
- }}>
326
- <div style={{ position: 'absolute', inset: pad, borderRadius: Math.max(2, radius - pad * 0.7), overflow: 'hidden' }}>
327
- <Photo i={i} />
328
- {/* 照片内缘一圈极淡暗边:像冲印的晕影,让亮色照片在米色底上立得住 */}
329
- <div style={{ position: 'absolute', inset: 0, boxShadow: 'inset 0 0 0 1px rgba(60,30,10,0.10), inset 0 -60px 80px -40px rgba(40,20,10,0.18)' }} />
330
- {i === 0 && (
331
- <div style={{
332
- position: 'absolute', inset: 0,
333
- background: 'linear-gradient(200deg, rgba(30,18,10,0) 40%, rgba(30,18,10,0.6) 100%)',
334
- opacity: ramp(frame, T_AB + LAG + 16, 14, EASE.out) * (1 - capOut),
335
- }} />
336
- )}
337
- </div>
338
- {/* 主图图注:B 态的策展语气 */}
339
- {i === 0 && frame >= T_AB + LAG + 20 && capOut < 1 && (
340
- <div style={{ position: 'absolute', left: 44, bottom: 36, color: '#fff8ee', opacity: 1 - capOut }}>
341
- <div style={{ ...type(30, 650, { caps: true }), letterSpacing: '0.16em', color: '#ffd9b8', marginBottom: 10 }}>
342
- <TextReveal text="Featured shot" start={T_AB + LAG + 22} by="word" variant="blur" each={14} />
343
- </div>
344
- <div style={{ ...type(84, 500, { serif: true }), letterSpacing: '-0.03em', textShadow: '0 2px 18px rgba(30,15,5,0.35)' }}>
345
- <TextReveal text="Golden Hour" start={T_AB + LAG + 26} by="word" variant="rise" each={18} gap={5} />
346
- </div>
347
- <div style={{ ...type(32, 450), color: 'rgba(255,248,238,0.82)', marginTop: 8, opacity: ramp(frame, T_AB + LAG + 34, 14, EASE.out) }}>
348
- Shot 01 · Crash zoom · 4.5 s
349
- </div>
350
- </div>
351
- )}
352
- </div>
353
- );
354
- })}
355
- </div>
356
- <Grain opacity={0.05} blend="overlay" />
357
- </div>
358
- );
359
- };
1
+ // mosaic-reframe — 12 张瓦片在三种排版间连续变形:规则网格 → feature mosaic → 对角瀑布串。
2
+ // 位置 / 宽高 / 旋转各自独立插值(不走 transform 整体缩放),逐片错峰,段间留 hold。
3
+ //
4
+ // 第二轮重设计(暖沙 · 胶片分镜板):
5
+ // - look = sand(米色 · 赤陶)。主体是 video-shotcraft 的一块分镜板(12 个镜头的定帧):12 张程序绘制的
6
+ // "胶片照片"(落日海面 / 沙丘 / 拱门 / 雾山 / 泳池 / 柑橘静物 / 棕榈影 / 麦田八式,暖调统一),
7
+ // 1920 原生坐标直接排版(不再从 480 设计坐标放大)。
8
+ // - 因果:右上角分段控件 Grid / Mosaic / Cascade 是"布局的开关"——赤陶色指示胶囊先滑到下一档
9
+ // (父先动),瓦片晚 4f 开始重排(子跟随),让观众看见"一次切换 → 整版重新思考"。
10
+ // - 三态三种语气:A 规则网格(档案)→ B feature mosaic(首图占 3×2,压上衬线大字图注 = 策展)
11
+ // → C 对角瀑布(每张变成带白边的相纸,-15° 起每张 +3° 递增旋转,像一手牌被摊开 = 态度),
12
+ // C 态左下留白处升起衬线大标题「Every shot, in sequence.」,尾帧是一张完整的分镜海报。
13
+ // - 运动:每片 x/y 用强 in-out(0.75,0,0.15,1)果断换位,w/h 晚 2f、旋转晚 4f 收敛(位置先到);
14
+ // 换位途中按段进度 sin 包络"抬起"(放大 3.5% + 阴影变大变虚),落位贴回;B→C 旋转带一次轻过冲。
15
+ // - 错峰:A→B 自左上主图起按序号波浪扫过(先密后疏);B→C 像发牌一样按序号依次摊开。
16
+ //
17
+ // 时间表(30fps,共 214f):
18
+ // 0–22 预备:舞台、页眉与控件在场;12 张照片自左上沿对角线错峰升起(第 0 帧已有首张起始态)
19
+ // 22–52 hold A:读网格(全程相机极缓推近 1→1.025)
20
+ // 52–64 控件胶囊 Grid→Mosaic(snappy 12f)
21
+ // 56–92 A→B 重排:每片 26f,错峰 10f;84–104 主图图注逐词升起
22
+ // 92–128 hold B:读 mosaic
23
+ // 128–140 控件胶囊 Mosaic→Cascade;图注 128 起退场
24
+ // 132–176 B→C 摊牌:每片 30f,等间隔错峰 14f;相纸白边 0→14px;158–186 大标题逐词升起、副行淡入
25
+ // 180–214 hold C:海报落定
26
+ import React from 'react';
27
+ import { useCurrentFrame } from 'remotion';
28
+ import { EASE, FONT, Grain, bezier, mix, ramp, softShadow } from '../../_fixtures/Polish';
29
+ import { LOOKS, SERIF, Stage, TextReveal, alpha, stagger, type } from '../../_fixtures/Look';
30
+ import { BRAND, PITCH, ShotcraftMark } from '../../_fixtures/Brand';
31
+
32
+ export const MOSAIC_REFRAME_DURATION = 214;
33
+
34
+ const L = LOOKS.sand;
35
+ const N = 12;
36
+
37
+ // ───────────── 时间常量 ─────────────
38
+ const T_AB = 52; // 控件切到 Mosaic
39
+ const T_BC = 128; // 控件切到 Cascade
40
+ const LAG = 4; // 瓦片晚于控件起跳的帧数(父先动、子跟随)
41
+ const D_AB = 26;
42
+ const D_BC = 30;
43
+ const MOVE = bezier(0.75, 0, 0.15, 1); // 果断换位:慢起 → 急走 → 长尾软落
44
+ const ROT_SETTLE = bezier(0.45, 0, 0.3, 1.22); // 旋转晚到并轻过冲一次
45
+
46
+ // ───────────── 三套布局(1920×1080 原生像素)─────────────
47
+ type Box = { x: number; y: number; w: number; h: number; rot: number };
48
+ const X0 = 96, X1 = 1824, Y0 = 212, Y1 = 984; // 内容区:安全边距 96,页眉下方
49
+
50
+ // A:4×3 规则网格
51
+ const AG = 24;
52
+ const AW = (X1 - X0 - 3 * AG) / 4, AH = (Y1 - Y0 - 2 * AG) / 3;
53
+ const A: Box[] = Array.from({ length: N }, (_, i) => ({
54
+ x: X0 + (i % 4) * (AW + AG), y: Y0 + Math.floor(i / 4) * (AH + AG), w: AW, h: AH, rot: 0,
55
+ }));
56
+
57
+ // B:6×4 单元格 feature mosaic,首片占 3×2
58
+ const BG = 16;
59
+ const UW = (X1 - X0 - 5 * BG) / 6, UH = (Y1 - Y0 - 3 * BG) / 4;
60
+ const SLOTS: [number, number, number, number][] = [
61
+ [0, 0, 3, 2], [3, 0, 1, 1], [4, 0, 1, 1], [5, 0, 1, 1], [3, 1, 2, 1], [5, 1, 1, 1],
62
+ [0, 2, 1, 1], [1, 2, 2, 1], [3, 2, 1, 2], [4, 2, 2, 1], [0, 3, 3, 1], [4, 3, 2, 1],
63
+ ];
64
+ const B: Box[] = SLOTS.map(([c, r, cw, rh]) => ({
65
+ x: X0 + c * (UW + BG), y: Y0 + r * (UH + BG), w: cw * UW + (cw - 1) * BG, h: rh * UH + (rh - 1) * BG, rot: 0,
66
+ }));
67
+
68
+ // C:对角瀑布串——竖幅相纸沿 (850,214)→(1724,930) 摊开,旋转 -15° 起每张 +3° 递增
69
+ const CW = 300, CH = 372;
70
+ const C: Box[] = Array.from({ length: N }, (_, i) => {
71
+ const s = i / (N - 1);
72
+ const cx = 850 + 874 * s, cy = 214 + 716 * s;
73
+ return { x: cx - CW / 2, y: cy - CH / 2, w: CW, h: CH, rot: -15 + i * 3 };
74
+ });
75
+
76
+ // ───────────── 照片(程序插画,viewBox 160×100 + slice ≈ object-fit: cover)─────────────
77
+ type Kind = 'sun' | 'dune' | 'arch' | 'ridge' | 'pool' | 'citrus' | 'palm' | 'field';
78
+ const PHOTOS: { kind: Kind; v: number }[] = [
79
+ { kind: 'sun', v: 0 }, { kind: 'dune', v: 0 }, { kind: 'pool', v: 0 }, { kind: 'arch', v: 0 },
80
+ { kind: 'ridge', v: 0 }, { kind: 'citrus', v: 0 }, { kind: 'palm', v: 0 }, { kind: 'field', v: 0 },
81
+ { kind: 'dune', v: 1 }, { kind: 'arch', v: 1 }, { kind: 'sun', v: 1 }, { kind: 'ridge', v: 1 },
82
+ ];
83
+
84
+ const Photo: React.FC<{ i: number }> = ({ i }) => {
85
+ const { kind, v } = PHOTOS[i];
86
+ const id = `mr${i}`;
87
+ const g = (stops: [string, number][], vertical = true) => (
88
+ <linearGradient id={`${id}g`} x1="0" y1="0" x2={vertical ? 0 : 1} y2={vertical ? 1 : 0}>
89
+ {stops.map(([c, o], k) => <stop key={k} offset={o} stopColor={c} />)}
90
+ </linearGradient>
91
+ );
92
+ let body: React.ReactNode = null;
93
+ let defs: React.ReactNode = null;
94
+ if (kind === 'sun') {
95
+ const warm = v === 0;
96
+ const sx = warm ? 126 : 80; // 主图的太阳偏右,给左下图注让位
97
+ defs = g(warm ? [['#f6c58e', 0], ['#ec8f5b', 0.55], ['#d8643f', 1]] : [['#f4d3b0', 0], ['#e6a07a', 0.6], ['#c97a62', 1]]);
98
+ body = (
99
+ <>
100
+ <rect width="160" height="64" fill={`url(#${id}g)`} />
101
+ <circle cx={sx} cy="56" r={warm ? 15 : 11} fill="#fff1d6" />
102
+ <circle cx={sx} cy="56" r={warm ? 26 : 20} fill="#fff1d6" opacity="0.18" />
103
+ <rect y="60" width="160" height="40" fill={warm ? '#3e4a63' : '#5a5f78'} />
104
+ <rect y="60" width="160" height="6" fill={warm ? '#566078' : '#6e728a'} opacity="0.8" />
105
+ {[63, 67, 72, 78, 85].map((y, k) => (
106
+ <rect key={k} x={sx - (16 - k * 2.2)} y={y} width={2 * (16 - k * 2.2)} height={1.2 + k * 0.2} rx="0.6" fill="#ffe2b4" opacity={0.75 - k * 0.12} />
107
+ ))}
108
+ </>
109
+ );
110
+ } else if (kind === 'dune') {
111
+ const a = v === 0;
112
+ defs = g(a ? [['#f3dcc0', 0], ['#ecc39a', 1]] : [['#e9d2c4', 0], ['#e1b6a0', 1]]);
113
+ body = (
114
+ <>
115
+ <rect width="160" height="100" fill={`url(#${id}g)`} />
116
+ <circle cx={a ? 118 : 40} cy="24" r="8" fill="#fff4e2" opacity="0.9" />
117
+ <path d="M0 62 C 30 46, 60 44, 92 58 S 140 66, 160 52 V100 H0Z" fill={a ? '#dc9a68' : '#cf8f72'} />
118
+ <path d="M0 74 C 40 60, 70 64, 100 76 S 140 82, 160 70 V100 H0Z" fill={a ? '#c4733f' : '#b4705a'} />
119
+ <path d="M30 100 C 60 80, 100 78, 160 86 V100Z" fill={a ? '#8f4a2b' : '#7f4c3f'} />
120
+ <path d="M0 62 C 30 46, 60 44, 92 58" fill="none" stroke="#fbe3c4" strokeWidth="0.8" opacity="0.7" />
121
+ </>
122
+ );
123
+ } else if (kind === 'arch') {
124
+ const a = v === 0;
125
+ defs = g(a ? [['#efd2b4', 0], ['#e2b48f', 1]] : [['#e9c9c0', 0], ['#d9a497', 1]], false);
126
+ body = (
127
+ <>
128
+ <rect width="160" height="100" fill={`url(#${id}g)`} />
129
+ <path d="M58 100 V52 A22 22 0 0 1 102 52 V100Z" fill={a ? '#6e3f2b' : '#5d3a3a'} />
130
+ <path d="M66 100 V56 A14 14 0 0 1 94 56 V100Z" fill={a ? '#f1c795' : '#f0c2a8'} opacity="0.9" />
131
+ <polygon points="0,0 70,0 20,100 0,100" fill="#ffffff" opacity="0.12" />
132
+ <polygon points="102,100 160,40 160,100" fill={a ? '#b97d58' : '#a8706a'} opacity="0.45" />
133
+ <rect y="92" width="160" height="8" fill={a ? '#c08a62' : '#b1817a'} />
134
+ </>
135
+ );
136
+ } else if (kind === 'ridge') {
137
+ const a = v === 0;
138
+ defs = g(a ? [['#e9e4dc', 0], ['#c9cfd6', 1]] : [['#efe0d0', 0], ['#d7c4b4', 1]]);
139
+ body = (
140
+ <>
141
+ <rect width="160" height="100" fill={`url(#${id}g)`} />
142
+ <polygon points="0,62 26,40 46,54 74,28 104,52 126,38 160,56 160,100 0,100" fill={a ? '#a9b4c2' : '#c4ab98'} />
143
+ <polygon points="0,74 34,54 62,68 96,46 130,66 160,58 160,100 0,100" fill={a ? '#7d8ca0' : '#a5846c'} />
144
+ <polygon points="0,86 40,70 84,84 120,68 160,80 160,100 0,100" fill={a ? '#4f5d72' : '#7a5a46'} />
145
+ <rect y="56" width="160" height="10" fill="#ffffff" opacity="0.18" />
146
+ </>
147
+ );
148
+ } else if (kind === 'pool') {
149
+ defs = g([['#6cc3c1', 0], ['#2f8c96', 1]]);
150
+ body = (
151
+ <>
152
+ <rect width="160" height="100" fill={`url(#${id}g)`} />
153
+ <rect y="0" width="160" height="22" fill="#efe2cf" />
154
+ <rect y="20" width="160" height="3" fill="#d9c7ad" />
155
+ {[40, 62, 84].map((y, k) => <rect key={k} x="0" y={y} width="160" height="1.6" fill="#ffffff" opacity="0.35" />)}
156
+ <path d="M10 50 Q 40 44 70 52 T 130 50" fill="none" stroke="#ffffff" strokeWidth="1.2" opacity="0.5" />
157
+ <path d="M30 72 Q 60 66 90 74 T 150 72" fill="none" stroke="#ffffff" strokeWidth="1" opacity="0.4" />
158
+ <polygon points="100,23 160,23 160,100 130,100" fill="#1c5f6c" opacity="0.35" />
159
+ </>
160
+ );
161
+ } else if (kind === 'citrus') {
162
+ defs = g([['#f1e3cc', 0], ['#e6d1b2', 1]]);
163
+ body = (
164
+ <>
165
+ <rect width="160" height="100" fill={`url(#${id}g)`} />
166
+ <rect y="64" width="160" height="36" fill="#c67a45" />
167
+ <rect y="64" width="160" height="2" fill="#e29a63" />
168
+ <ellipse cx="74" cy="78" rx="44" ry="5" fill="#8d4f2a" opacity="0.4" />
169
+ <circle cx="64" cy="60" r="15" fill="#ef8a36" />
170
+ <circle cx="90" cy="64" r="11" fill="#f3a246" />
171
+ <circle cx="59" cy="55" r="4" fill="#ffd29a" opacity="0.7" />
172
+ <circle cx="87" cy="60" r="3" fill="#ffe0b0" opacity="0.7" />
173
+ <path d="M64 45 q 5 -6 11 -4 q -4 6 -11 4z" fill="#5d7a4a" />
174
+ </>
175
+ );
176
+ } else if (kind === 'palm') {
177
+ defs = g([['#ecc2aa', 0], ['#e0a68c', 1]], false);
178
+ body = (
179
+ <>
180
+ <rect width="160" height="100" fill={`url(#${id}g)`} />
181
+ {[0, 1, 2, 3, 4, 5].map((k) => (
182
+ <path key={k} d={`M40 10 Q ${60 + k * 14} ${10 + k * 10} ${78 + k * 16} ${28 + k * 14}`} fill="none" stroke="#b97862" strokeWidth={5 - k * 0.4} strokeLinecap="round" opacity="0.55" />
183
+ ))}
184
+ <path d="M40 10 L 34 100" stroke="#b97862" strokeWidth="3" opacity="0.5" />
185
+ <rect y="88" width="160" height="12" fill="#c98d74" />
186
+ </>
187
+ );
188
+ } else {
189
+ defs = g([['#f3e1c0', 0], ['#e9c992', 1]]);
190
+ body = (
191
+ <>
192
+ <rect width="160" height="100" fill={`url(#${id}g)`} />
193
+ <rect y="0" width="160" height="40" fill="#e8d7bd" />
194
+ <circle cx="128" cy="20" r="7" fill="#fff3dc" />
195
+ {Array.from({ length: 9 }, (_, k) => (
196
+ <path key={k} d={`M80 40 L ${-60 + k * 35} 100`} stroke="#c49a52" strokeWidth={1.4 + k * 0.1} opacity="0.55" />
197
+ ))}
198
+ <path d="M0 40 H160" stroke="#b9925a" strokeWidth="1" opacity="0.6" />
199
+ </>
200
+ );
201
+ }
202
+ return (
203
+ <svg width="100%" height="100%" viewBox="0 0 160 100" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, display: 'block' }}>
204
+ <defs>{defs}</defs>
205
+ {body}
206
+ </svg>
207
+ );
208
+ };
209
+
210
+ // ───────────── 分段控件(布局开关)─────────────
211
+ const SEG = ['Grid', 'Mosaic', 'Cascade'];
212
+ const SEG_W = 168, SEG_H = 60, SEG_PAD = 6;
213
+ const Segmented: React.FC<{ frame: number }> = ({ frame }) => {
214
+ const p1 = ramp(frame, T_AB, 12, EASE.snappy);
215
+ const p2 = ramp(frame, T_BC, 12, EASE.snappy);
216
+ const pos = p1 + p2; // 0 → 1 → 2
217
+ // 胶囊在途中横向拉长(像被拽过去),到位收回
218
+ const stretch = 1 + 0.18 * (Math.sin(Math.PI * p1) + Math.sin(Math.PI * p2));
219
+ const press = (k: number, t: number) => 1 - 0.05 * Math.sin(Math.PI * ramp(frame, t - 3, 8, EASE.linear)) * (k > 0 ? 1 : 0);
220
+ return (
221
+ <div style={{
222
+ position: 'absolute', right: 96, top: 92, width: SEG_W * 3 + SEG_PAD * 2, height: SEG_H + SEG_PAD * 2, borderRadius: 999,
223
+ background: alpha('#ffffff', 0.55), boxShadow: `inset 0 0 0 1px ${L.line}, ${softShadow(6, { color: L.shadow, strength: 0.6 })}`,
224
+ }}>
225
+ <div style={{
226
+ position: 'absolute', top: SEG_PAD, left: SEG_PAD + pos * SEG_W, width: SEG_W, height: SEG_H, borderRadius: 999,
227
+ background: L.accent, transform: `scaleX(${stretch.toFixed(4)})`,
228
+ boxShadow: `0 6px 16px -6px ${alpha(L.accent, 0.7)}, inset 0 1px 0 rgba(255,255,255,0.25)`,
229
+ }} />
230
+ {SEG.map((s, k) => {
231
+ const on = Math.max(0, 1 - Math.abs(pos - k));
232
+ return (
233
+ <div key={s} style={{
234
+ position: 'absolute', top: SEG_PAD, left: SEG_PAD + k * SEG_W, width: SEG_W, height: SEG_H,
235
+ display: 'flex', alignItems: 'center', justifyContent: 'center',
236
+ ...type(30, 600), letterSpacing: '-0.01em',
237
+ color: on > 0.5 ? L.onAccent : L.ink2,
238
+ transform: `scale(${(k === 1 ? press(1, T_AB) : k === 2 ? press(2, T_BC) : 1).toFixed(4)})`,
239
+ }}>{s}</div>
240
+ );
241
+ })}
242
+ </div>
243
+ );
244
+ };
245
+
246
+ // 瓦片在某帧的几何:A→B、B→C 两段各自的进度,位置 / 宽高 / 旋转错开收敛
247
+ const tileAt = (frame: number, i: number) => {
248
+ const sAB = T_AB + LAG + stagger(i, N, 10, EASE.out);
249
+ const sBC = T_BC + LAG + stagger(i, N, 14, EASE.linear); // 发牌:等间隔依次摊开
250
+ const pAB = ramp(frame, sAB, D_AB, MOVE);
251
+ const pBC = ramp(frame, sBC, D_BC, MOVE);
252
+ const sAB2 = ramp(frame, sAB + 2, D_AB, MOVE); // 宽高晚 2f
253
+ const sBC2 = ramp(frame, sBC + 2, D_BC, MOVE);
254
+ const rBC = ramp(frame, sBC + 4, D_BC, ROT_SETTLE); // 旋转晚 4f + 过冲
255
+ const a = A[i], b = B[i], c = C[i];
256
+ // 以中心插值位置(宽高变化时中心走直线,不会"先长后跑")
257
+ const cxA = a.x + a.w / 2, cyA = a.y + a.h / 2, cxB = b.x + b.w / 2, cyB = b.y + b.h / 2, cxC = c.x + c.w / 2, cyC = c.y + c.h / 2;
258
+ const cx = mix(mix(cxA, cxB, pAB), cxC, pBC);
259
+ const cy = mix(mix(cyA, cyB, pAB), cyC, pBC);
260
+ const w = mix(mix(a.w, b.w, sAB2), c.w, sBC2);
261
+ const h = mix(mix(a.h, b.h, sAB2), c.h, sBC2);
262
+ const rot = mix(0, c.rot, rBC);
263
+ const lift = Math.max(Math.sin(Math.PI * pAB), Math.sin(Math.PI * pBC));
264
+ return { cx, cy, w, h, rot, lift, pBC: sBC2, moving: pBC > 0 };
265
+ };
266
+
267
+ export const MosaicReframe: React.FC = () => {
268
+ const frame = useCurrentFrame();
269
+ const cam = mix(1, 1.025, ramp(frame, 0, 214, EASE.smooth)); // 全程极缓推近
270
+
271
+ // 主图图注(B 态):84f 起逐词升起,128f 起退场
272
+ const capOut = ramp(frame, T_BC, 10, EASE.exit);
273
+ // C 态大标题
274
+ const HEAD = 158;
275
+
276
+ const tiles = Array.from({ length: N }, (_, i) => ({ i, ...tileAt(frame, i) }));
277
+ // 叠放次序:B→C 起按序号(后发的牌压在上面);之前主图最高
278
+ const inC = frame >= T_BC + LAG;
279
+ const z = (i: number) => (inC ? 10 + i : i === 0 ? 30 : 10);
280
+
281
+ return (
282
+ <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', fontFamily: FONT.sans }}>
283
+ <Stage look={L} keyLight={{ x: 0.28, y: 0.02 }} fill={{ x: 0.9, y: 0.95 }} />
284
+
285
+ <div style={{ position: 'absolute', inset: 0, transform: `scale(${cam.toFixed(5)})`, transformOrigin: '50% 46%' }}>
286
+ {/* 页眉:品牌标志 + 小写字标 + 分镜板名(标志按亮底 light 版;字标与分镜名同一基线)。
287
+ 总宽压在 x≈620 以内——C 态首张相纸的左上角在 x≈650,页眉再长会被它盖住 */}
288
+ <div style={{ position: 'absolute', left: 96, top: 92, height: 72, display: 'flex', alignItems: 'center', gap: 18, color: L.ink }}>
289
+ <ShotcraftMark size={50} tone="light" />
290
+ <div style={{ display: 'flex', alignItems: 'baseline', gap: 20 }}>
291
+ <span style={{ fontFamily: BRAND.font, fontSize: 36, fontWeight: 700, letterSpacing: '0.03em', lineHeight: 1 }}>{BRAND.name}</span>
292
+ <span style={{ ...type(32, 450), color: L.ink2 }}>Storyboard</span>
293
+ </div>
294
+ </div>
295
+ <Segmented frame={frame} />
296
+
297
+ {/* C 态大标题(左下留白处) */}
298
+ <div style={{ position: 'absolute', left: 96, top: 676, color: L.ink }}>
299
+ <div style={{ ...type(124, 500, { serif: true }), letterSpacing: '-0.035em', lineHeight: 1.0 }}>
300
+ <TextReveal text="Every shot," start={HEAD} by="word" variant="rise" each={20} gap={5} />
301
+ <br />
302
+ <TextReveal text="in sequence." start={HEAD + 6} by="word" variant="rise" each={20} gap={5}
303
+ unitStyle={() => ({ fontStyle: 'italic', color: L.accent })} />
304
+ </div>
305
+ <div style={{
306
+ ...type(32, 450), color: L.ink2, marginTop: 26,
307
+ opacity: ramp(frame, HEAD + 14, 16, EASE.out), transform: `translateY(${mix(12, 0, ramp(frame, HEAD + 14, 18, EASE.snappy)).toFixed(2)}px)`,
308
+ }}>{PITCH.en.taglines[4]}</div>
309
+ </div>
310
+
311
+ {tiles.map(({ i, cx, cy, w, h, rot, lift, pBC }) => {
312
+ // 开场:沿对角线错峰升起(从左上到右下)
313
+ const order = (i % 4) + Math.floor(i / 4);
314
+ const inP = ramp(frame, stagger(order, 6, 14, EASE.out) - 2, 16, EASE.snappy);
315
+ const pad = 14 * pBC; // 相纸白边
316
+ const radius = mix(16, 6, pBC);
317
+ const scale = mix(0.94, 1, inP) * (1 + 0.035 * lift);
318
+ const elev = 6 + 34 * lift + 8 * pBC;
319
+ return (
320
+ <div key={i} style={{
321
+ position: 'absolute', left: cx - w / 2, top: cy - h / 2 + (1 - inP) * 40, width: w, height: h,
322
+ transform: `rotate(${rot.toFixed(3)}deg) scale(${scale.toFixed(4)})`,
323
+ opacity: inP, zIndex: z(i), borderRadius: radius,
324
+ background: L.surface, boxShadow: softShadow(elev, { color: L.shadow, strength: 0.9 + 0.5 * pBC }),
325
+ }}>
326
+ <div style={{ position: 'absolute', inset: pad, borderRadius: Math.max(2, radius - pad * 0.7), overflow: 'hidden' }}>
327
+ <Photo i={i} />
328
+ {/* 照片内缘一圈极淡暗边:像冲印的晕影,让亮色照片在米色底上立得住 */}
329
+ <div style={{ position: 'absolute', inset: 0, boxShadow: 'inset 0 0 0 1px rgba(60,30,10,0.10), inset 0 -60px 80px -40px rgba(40,20,10,0.18)' }} />
330
+ {i === 0 && (
331
+ <div style={{
332
+ position: 'absolute', inset: 0,
333
+ background: 'linear-gradient(200deg, rgba(30,18,10,0) 40%, rgba(30,18,10,0.6) 100%)',
334
+ opacity: ramp(frame, T_AB + LAG + 16, 14, EASE.out) * (1 - capOut),
335
+ }} />
336
+ )}
337
+ </div>
338
+ {/* 主图图注:B 态的策展语气 */}
339
+ {i === 0 && frame >= T_AB + LAG + 20 && capOut < 1 && (
340
+ <div style={{ position: 'absolute', left: 44, bottom: 36, color: '#fff8ee', opacity: 1 - capOut }}>
341
+ <div style={{ ...type(30, 650, { caps: true }), letterSpacing: '0.16em', color: '#ffd9b8', marginBottom: 10 }}>
342
+ <TextReveal text="Featured shot" start={T_AB + LAG + 22} by="word" variant="blur" each={14} />
343
+ </div>
344
+ <div style={{ ...type(84, 500, { serif: true }), letterSpacing: '-0.03em', textShadow: '0 2px 18px rgba(30,15,5,0.35)' }}>
345
+ <TextReveal text="Golden Hour" start={T_AB + LAG + 26} by="word" variant="rise" each={18} gap={5} />
346
+ </div>
347
+ <div style={{ ...type(32, 450), color: 'rgba(255,248,238,0.82)', marginTop: 8, opacity: ramp(frame, T_AB + LAG + 34, 14, EASE.out) }}>
348
+ Shot 01 · Crash zoom · 4.5 s
349
+ </div>
350
+ </div>
351
+ )}
352
+ </div>
353
+ );
354
+ })}
355
+ </div>
356
+ <Grain opacity={0.05} blend="overlay" />
357
+ </div>
358
+ );
359
+ };