dsh-drawai 0.4.2 → 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 (366) hide show
  1. package/README.md +4 -3
  2. package/lib/index.js +7777 -7719
  3. package/lib/motion/asset-pack.js +394 -394
  4. package/lib/motion/assets.js +291 -291
  5. package/lib/motion/demo-assets-lock.js +10 -10
  6. package/lib/motion/mgstyles/vendor/README.md +28 -28
  7. package/lib/motion/mgstyles/vendor/modules/d3/LICENSE +13 -13
  8. package/lib/motion/mgstyles/vendor/modules/d3/dist/d3.min.js +2 -2
  9. package/lib/motion/mgstyles/vendor/modules/opentype.js/LICENSE +20 -20
  10. package/lib/motion/mgstyles/vendor/modules/opentype.js/dist/opentype.mjs +14460 -14460
  11. package/lib/motion/mgstyles/vendor/modules/simplex-noise/LICENSE +21 -21
  12. package/lib/motion/mgstyles/vendor/modules/simplex-noise/dist/esm/simplex-noise.js +465 -465
  13. package/lib/motion/mgstyles/vendor/modules/topojson-client/LICENSE +13 -13
  14. package/lib/motion/mgstyles/vendor/modules/topojson-client/dist/topojson-client.min.js +2 -2
  15. package/lib/motion/render.js +179 -179
  16. package/lib/motion/shotcraft/upstream/SKILL.md +286 -286
  17. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -54
  18. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -200
  19. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -45
  20. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -20
  21. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -65
  22. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -151
  23. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -129
  24. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -75
  25. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -40
  26. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -11
  27. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -10
  28. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -49
  29. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -210
  30. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -423
  31. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -170
  32. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -157
  33. package/lib/motion/shotcraft/upstream/demos/README.md +120 -120
  34. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -112
  35. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -647
  36. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -316
  37. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -82
  38. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -115
  39. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -243
  40. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +388 -388
  41. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -250
  42. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -305
  43. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -246
  44. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -390
  45. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -138
  46. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -542
  47. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -315
  48. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -299
  49. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -173
  50. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -348
  51. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -366
  52. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -279
  53. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -184
  54. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -390
  55. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -155
  56. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -303
  57. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -290
  58. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -278
  59. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -307
  60. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -215
  61. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -299
  62. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -232
  63. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -290
  64. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -273
  65. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -167
  66. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -536
  67. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -164
  68. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -175
  69. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -197
  70. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -241
  71. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -279
  72. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -230
  73. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -345
  74. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -275
  75. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -229
  76. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -312
  77. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -222
  78. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -295
  79. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -329
  80. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -315
  81. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -264
  82. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -260
  83. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -263
  84. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -123
  85. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -187
  86. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -175
  87. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -305
  88. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -350
  89. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -352
  90. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -218
  91. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -297
  92. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -157
  93. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -218
  94. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -202
  95. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -265
  96. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -457
  97. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -446
  98. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -249
  99. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -278
  100. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -332
  101. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -358
  102. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -201
  103. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -200
  104. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -208
  105. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -341
  106. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -389
  107. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -293
  108. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -183
  109. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -245
  110. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -222
  111. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -223
  112. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -217
  113. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -343
  114. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -357
  115. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -187
  116. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -333
  117. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -274
  118. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -270
  119. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -430
  120. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -252
  121. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -106
  122. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -288
  123. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -362
  124. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -168
  125. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -310
  126. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -261
  127. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -459
  128. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -294
  129. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -161
  130. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -248
  131. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -359
  132. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -227
  133. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -162
  134. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -248
  135. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -186
  136. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -355
  137. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -272
  138. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -262
  139. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -217
  140. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -285
  141. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -205
  142. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -178
  143. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -147
  144. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -143
  145. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -134
  146. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -217
  147. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -198
  148. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -221
  149. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -312
  150. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -261
  151. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -121
  152. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -153
  153. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -179
  154. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -140
  155. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -309
  156. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -191
  157. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -292
  158. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -135
  159. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -124
  160. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -255
  161. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -173
  162. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -225
  163. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -141
  164. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -137
  165. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -147
  166. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -409
  167. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -280
  168. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -271
  169. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -385
  170. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -312
  171. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -303
  172. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -77
  173. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -311
  174. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -307
  175. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -349
  176. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -255
  177. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -244
  178. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -217
  179. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -652
  180. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -153
  181. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -238
  182. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -324
  183. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -354
  184. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -101
  185. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -129
  186. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -297
  187. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -57
  188. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -155
  189. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -175
  190. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -153
  191. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -146
  192. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -226
  193. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -1
  194. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -193
  195. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -121
  196. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -199
  197. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -183
  198. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -257
  199. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -382
  200. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -111
  201. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -50
  202. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -95
  203. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -41
  204. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -52
  205. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -39
  206. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -39
  207. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -57
  208. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -51
  209. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -46
  210. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -52
  211. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -43
  212. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -42
  213. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -48
  214. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -52
  215. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -45
  216. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -46
  217. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -44
  218. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -63
  219. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -54
  220. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -58
  221. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -35
  222. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -53
  223. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -42
  224. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -50
  225. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -46
  226. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -56
  227. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -49
  228. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -50
  229. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -53
  230. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -53
  231. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -55
  232. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -52
  233. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -60
  234. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -57
  235. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -51
  236. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -41
  237. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -53
  238. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -60
  239. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -55
  240. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -57
  241. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -47
  242. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -37
  243. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -54
  244. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -36
  245. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -56
  246. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -56
  247. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -40
  248. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -60
  249. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -57
  250. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -73
  251. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -87
  252. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -55
  253. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -50
  254. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -59
  255. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -38
  256. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -38
  257. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -59
  258. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -39
  259. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -61
  260. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -52
  261. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -50
  262. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -66
  263. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -43
  264. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -38
  265. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -38
  266. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -56
  267. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -44
  268. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -38
  269. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -63
  270. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -57
  271. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -63
  272. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -58
  273. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -45
  274. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -55
  275. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -49
  276. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -42
  277. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -42
  278. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -45
  279. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -48
  280. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -55
  281. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -43
  282. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -41
  283. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -42
  284. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -59
  285. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -55
  286. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -65
  287. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -42
  288. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -64
  289. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -64
  290. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -54
  291. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -91
  292. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -51
  293. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -66
  294. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -38
  295. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -66
  296. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -58
  297. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -61
  298. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -64
  299. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -45
  300. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -41
  301. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -51
  302. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -42
  303. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -63
  304. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -57
  305. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -75
  306. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -59
  307. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -67
  308. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -60
  309. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -66
  310. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -40
  311. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -45
  312. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -62
  313. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -55
  314. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -37
  315. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -55
  316. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -50
  317. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -43
  318. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -55
  319. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -51
  320. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -51
  321. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -56
  322. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -49
  323. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -57
  324. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -36
  325. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -64
  326. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -47
  327. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -170
  328. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -157
  329. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -103
  330. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -44
  331. package/lib/motion/shotcraft/upstream/template/package.json +20 -20
  332. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -6
  333. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -17
  334. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -65
  335. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -48
  336. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -24
  337. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -192
  338. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -111
  339. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -150
  340. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -158
  341. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -468
  342. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -552
  343. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -411
  344. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -200
  345. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -324
  346. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +388 -388
  347. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -4
  348. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -7
  349. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -68
  350. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -1
  351. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -24
  352. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -74
  353. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -91
  354. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -213
  355. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -15
  356. package/lib/motion/style-frames.js +306 -306
  357. package/lib/motion/sync.js +214 -214
  358. package/lib/motion-project.js +105 -105
  359. package/lib/motion-render-worker.js +174 -174
  360. package/lib/routing/router.js +222 -222
  361. package/lib/routing/vendor/README.md +96 -96
  362. package/lib/routing/vendor/libavoid-routing.js +753 -753
  363. package/lib/routing/vendor/libavoid.min.js +59 -59
  364. package/lib/video-trace-pool.js +128 -128
  365. package/package.json +1 -1
  366. package/LICENSE +0 -4175
@@ -1,468 +1,468 @@
1
- import { useVisualTheme, themePaint, themeAsset, sceneDefaults } from '../../themes/visual-theme';
2
- import { Img, interpolate, useCurrentFrame, Easing, getRemotionEnvironment } from 'remotion';
3
- import { PageCam, CamKey } from './PageCam';
4
- import layout from '../live-layout.json';
5
-
6
- const cards = layout.projects.cards;
7
- const PAGE_H = layout.projects.pageH;
8
-
9
- const HOVER_H = 40; // px above the slot (translateZ) a card hovers at mid-dive
10
- const SETTLE_EASE = Easing.bezier(0.3, 0, 0.25, 1.15); // slight overshoot / compress
11
- const DIVE_EASE = Easing.bezier(0.3, 0, 0.2, 1); // decelerate into the hover
12
- const SLIDE_EASE = Easing.bezier(0.35, 0, 0.2, 1); // nano-lab card slide to the top slot
13
-
14
- // page paper colors, sampled from the rendered projects-empty texture
15
-
16
- // ---- 16 "overflow" extras extend the grid DOWNWARD (no hovering, no overlap):
17
- // fill the empty 3rd column of the y=1402 row, then five new rows below the
18
- // texture at y=1795…3367, columns matching the real grid. ----
19
- const COLS = [408, 781.328125, 1154.65625];
20
- const CARD_W = 357.328125;
21
- const EXTRA_ROWS = [1795, 2188, 2581, 2974, 3367];
22
- const PAPER_EXT = { x: 0, y: PAGE_H, w: 1920, h: 2036 }; // paper extension below the texture (flush bottom 3782)
23
-
24
- const extras = Array.from({ length: 16 }, (_, i) => ({
25
- file: `card${((i * 3 + 2) % 10) + 1}.png`, // deterministic, neighbors differ
26
- x: i === 0 ? COLS[2] : COLS[(i - 1) % 3],
27
- y: i === 0 ? 1402 : EXTRA_ROWS[Math.floor((i - 1) / 3)],
28
- w: CARD_W,
29
- h: 312,
30
- title: '',
31
- }));
32
-
33
- // ---- the DECK: all 26 cards start stacked in one pile at the page's top
34
- // right. The shot opens on a rotating 3D close-up of the pile (0–35), pulls
35
- // back to reveal the page (35–62), and the cards deal themselves to their
36
- // slots in reading order (y, then x) on a hard-accelerating cadence — the gap
37
- // between departures shrinks from 4f to 0.2f (gap_k = 4 − 0.1584k), so the
38
- // dealing goes from deliberate to a blur. First departs at 36 (mid pull-back),
39
- // last ≈88, lands ≈96. Pile poses carry a small deterministic jitter and each
40
- // card keeps a stack height (top of pile = first to leave). ----
41
- const PILE = { x: 1430, y: 240 };
42
- const N_CARDS = 26;
43
- const DEAL_START = 36;
44
- const STACK_STEP = 3; // px of physical height per card — the pile reads as a real stack
45
-
46
- // dark-metal backdrop for the opening close-up: covers everything in the page
47
- // plane, with a warm spotlight pooled on the pile; fades out with the pull-back
48
- const METAL_FADE = [34, 56] as const;
49
- // Real-time preview stand-in for the metal (Player / Studio / workbench — anything that is
50
- // not the final render). The procedural gradients below cover a 9000×9000 plane that
51
- // Chromium has to re-rasterize every frame while PageCam's `zoom` changes; in real time
52
- // the raster never keeps up, the plane drops in and out, and the close-up strobes between
53
- // dark table and white page (measured: ~20 blank-outs in the first 2s). A flat fill needs
54
- // no raster at all. Same geometry, same fade — only the paint differs; the render still
55
- // paints the brushed metal. Tone = median of the rendered table (#373637 sampled).
56
-
57
- const grid = [
58
- ...cards.map((c) => ({ file: c.file, x: c.x, y: c.y, w: c.w, h: c.h, title: c.title })),
59
- ...extras,
60
- ]
61
- .sort((a, b) => a.y - b.y || a.x - b.x)
62
- .map((c, k) => ({
63
- ...c,
64
- cue: DEAL_START + 4 * k - 0.0792 * k * (k - 1),
65
- // pile pose: tiny alternating offsets + roll, stacked top-down by k
66
- px: PILE.x + (((k * 7) % 9) - 4) * 2,
67
- py: PILE.y + (((k * 5) % 7) - 3) * 2,
68
- protZ: ((k * 11) % 7) - 3,
69
- pz: (N_CARDS - k) * STACK_STEP, // physical stack height; k=0 rides on top
70
- }));
71
-
72
- // ---- the search target: nano-lab slides up to the first-row slot on filter ----
73
- const nanoIdx = grid.findIndex((c) => c.title.includes('nano-lab'));
74
- const nano = grid[nanoIdx];
75
- const NANO_TO = { x: 408, y: 247 }; // first-row slot the filtered card slides into
76
- const CLICK_C = { x: 586, y: 391 }; // click point on the settled result card
77
-
78
- // filter departure rank for the 19 non-target cards (reading order)
79
- const leaveRank = new Map<number, number>();
80
- grid.forEach((_, i) => {
81
- if (i !== nanoIdx) leaveRank.set(i, leaveRank.size);
82
- });
83
-
84
- // search box (page-space CSS px) + typing beats
85
- const SEARCH = { x: 408, y: 130, w: 1016, h: 44 };
86
- /** Context-level defaults, editable per clip in the workbench. `query` is only the
87
- * typed text; the card that survives the filter is still the nano-lab card from layout. */
88
- export const SCENE_FLYIN_DEFAULTS = {
89
- query: 'nano-lab',
90
- accent: '#ae6700', // oklch(58% 0.13 65)
91
- };
92
- type SceneFlyInProps = Partial<typeof SCENE_FLYIN_DEFAULTS>;
93
- const TYPE_START = 128; // 3 frames per character → last char at ≈149
94
- const FILTER_START = 160; // beat of rest after typing, then the grid filters
95
-
96
- // pile centre for the opening close-up
97
- const PILE_CX = PILE.x + CARD_W / 2;
98
- const PILE_CY = PILE.y + 156;
99
-
100
- // Narrative: the shot opens on a rotating 3D CLOSE-UP of the 26-card pile
101
- // (orbiting from a left-oblique to a right-oblique look), pulls back to
102
- // reveal the page as the pile starts dealing cards to their grid slots, each
103
- // departure faster than the last, extending the grid far below the page fold
104
- // → the camera scrolls down chasing the dealing, FASTER each leg, arriving
105
- // straight at the bottom → rests half a second on the full board → swooshes
106
- // back up to the search box → "nano-lab" is typed (unhurried), a breath, then
107
- // the grid filters down to one card which slides into the first row → a click
108
- // ripple fires and the camera pushes into the card, handing off to detail.
109
- const CAM_KEYS: CamKey[] = [
110
- { frame: 0, cx: PILE_CX - 30, cy: PILE_CY + 60, zoom: 1.95, rotX: 46, rotY: -30, rotZ: 9, persp: 1100 }, // low side view of the stack, left-oblique
111
- { frame: 34, cx: PILE_CX + 30, cy: PILE_CY + 40, zoom: 1.85, rotX: 42, rotY: 26, rotZ: -7, persp: 1100 }, // orbit around the pile to a right-oblique
112
- { frame: 62, cx: 960, cy: 900, zoom: 0.88, rotX: 26, rotY: 0, rotZ: 2, persp: 1300 }, // pull back — dashboard revealed, dealing underway
113
- { frame: 82, cx: 950, cy: 1900, zoom: 0.78, rotX: 14, rotY: 0, rotZ: 0, persp: 1300 }, // speeding up (~50 px/f)
114
- { frame: 98, cx: 960, cy: 3032, zoom: 0.72, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // fastest leg (~70 px/f), arrives straight at the paper's flush bottom
115
- { frame: 113, cx: 960, cy: 3032, zoom: 0.72, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // 0.5s REST on the full board
116
- { frame: 124, cx: 960, cy: 380, zoom: 0.9, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // swoosh back up to the search/filter header
117
- { frame: 174, cx: 960, cy: 380, zoom: 0.9, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // hold through typing, breath, filter, slide
118
- { frame: 190, cx: CLICK_C.x, cy: CLICK_C.y, zoom: 2.2, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // push into the clicked card, carried through the white flash
119
- ];
120
-
121
- export const SceneFlyIn: React.FC<SceneFlyInProps> = (props) => {
122
- const theme = useVisualTheme();
123
- const paperStyle = theme.id === 'ink-press';
124
- const paint = (css: string) => themePaint(theme, css);
125
- const asset = (src: string) => themeAsset(theme, src);
126
- const PAPER = paint('#f9f6f1'); // page background (bottom rows)
127
- const FIELD = paint('#fefcf9'); // search-box interior
128
- const METAL_PREVIEW = paint('#383638');
129
- const { query: QUERY, accent } = { ...sceneDefaults(theme, 'table', SCENE_FLYIN_DEFAULTS), ...props };
130
- const frame = useCurrentFrame();
131
- const { isRendering } = getRemotionEnvironment();
132
-
133
- // DOF fades out over the straightening leg of the scroll (82 → 98)
134
- const dofStrength = interpolate(frame, [82, 98], [5, 0], {
135
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
136
- });
137
-
138
- // typed characters: one every 3 frames from TYPE_START (unhurried typing)
139
- const typedCount = frame < TYPE_START
140
- ? 0
141
- : Math.min(QUERY.length, Math.floor((frame - TYPE_START) / 3) + 1);
142
- // caret: solid while typing, then blinks on an 8-frame cycle until the click
143
- const caretOn =
144
- frame >= TYPE_START - 2 &&
145
- frame <= 185 &&
146
- (frame <= TYPE_START + 24 || Math.floor((frame - (TYPE_START + 24)) / 8) % 2 === 0);
147
-
148
- return (
149
- <PageCam
150
- src="textures/live/projects-empty.png"
151
- pageH={PAGE_H}
152
- keys={CAM_KEYS}
153
- ease={Easing.bezier(0.33, 0, 0.15, 1)}
154
- dof={dofStrength > 0.1 ? { focusY: 260, strength: dofStrength } : undefined}
155
- >
156
- {/* ---- dark brushed-metal table under the opening pile close-up: a huge
157
- plane (covers the viewport at any oblique angle) with a warm
158
- spotlight pooled on the stack; fades away as the camera pulls
159
- back and the dashboard page takes over ---- */}
160
- {frame < METAL_FADE[1] ? (
161
- <div
162
- style={{
163
- position: 'absolute',
164
- left: -3000,
165
- top: -3000,
166
- width: 9000,
167
- height: 9000,
168
- opacity: interpolate(frame, [METAL_FADE[0], METAL_FADE[1]], [1, 0], {
169
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
170
- }),
171
- background: !paperStyle ? theme.stage : isRendering ? [
172
- // warm key light pooled on the pile
173
- paint(`radial-gradient(1300px 900px at ${3000 + PILE_CX}px ${3000 + PILE_CY}px, rgba(255,214,150,0.20), rgba(255,190,120,0.06) 40%, transparent 68%)`),
174
- // brushed-metal grain: fine anisotropic streaks
175
- paint('repeating-linear-gradient(100deg, rgba(255,255,255,0.028) 0px, rgba(255,255,255,0.028) 1px, transparent 2px, transparent 7px)'),
176
- paint('repeating-linear-gradient(100deg, rgba(0,0,0,0.16) 0px, rgba(0,0,0,0.16) 2px, transparent 4px, transparent 13px)'),
177
- // broad steel sheen
178
- paint('linear-gradient(115deg, #2a2d33 0%, #383c44 28%, #22242a 55%, #33363e 78%, #1d1f24 100%)'),
179
- ].join(', ') : METAL_PREVIEW,
180
- pointerEvents: 'none',
181
- }}
182
- />
183
- ) : null}
184
-
185
- {/* ---- paper extension: the page grows past the texture so the three
186
- extra rows sit on paper, not on the void ---- */}
187
- <div
188
- style={{
189
- position: 'absolute',
190
- left: PAPER_EXT.x,
191
- top: PAPER_EXT.y,
192
- width: PAPER_EXT.w,
193
- height: PAPER_EXT.h,
194
- background: PAPER,
195
- pointerEvents: 'none',
196
- }}
197
- />
198
-
199
- {/* ---- filter clean-up: paper patch over the stale section headers /
200
- counts baked into the texture below y=500, revealed 84–92 ---- */}
201
- {frame >= FILTER_START ? (
202
- <div
203
- style={{
204
- position: 'absolute',
205
- left: 0,
206
- top: 500,
207
- width: 1920,
208
- height: PAGE_H - 500,
209
- background: PAPER,
210
- opacity: interpolate(frame, [FILTER_START, FILTER_START + 8], [0, 1], {
211
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
212
- }),
213
- pointerEvents: 'none',
214
- }}
215
- />
216
- ) : null}
217
-
218
- {/* ---- 26 cards: visible pile at top right from frame 0, each card
219
- deals itself to its slot (arc flight, roll resolving) on an
220
- accelerating cadence; on filter the 25 non-matches fade+sink
221
- away and nano-lab slides up to row one ---- */}
222
- {grid.map((c, i) => {
223
- const { cue } = c;
224
- const radius = 16;
225
- const isNano = i === nanoIdx;
226
-
227
- // --- filter fade-out for the 25 non-target cards (staggered, 5f) ---
228
- const outCue = isNano ? Infinity : FILTER_START + leaveRank.get(i)! * 0.4;
229
- if (frame >= outCue + 5) return null;
230
- const outT = isNano
231
- ? 0
232
- : interpolate(frame, [outCue, outCue + 5], [0, 1], {
233
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.inOut(Easing.quad),
234
- });
235
-
236
- // --- beat 1: deal (cue → cue+8): from the pile pose (px,py, stack
237
- // height pz, small roll) to the hover pose over the slot. The flight
238
- // arcs UP first (z bulge) like a card snapped off the top of a deck. ---
239
- const diveT = interpolate(frame, [cue, cue + 8], [0, 1], {
240
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: DIVE_EASE,
241
- });
242
-
243
- // --- beat 2: settle (cue+8 → cue+12): Z from HOVER_H down to 0 ---
244
- const settleT = interpolate(frame, [cue + 8, cue + 12], [0, 1], {
245
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: SETTLE_EASE,
246
- });
247
-
248
- // in-flight pose: pile → slot, roll resolving to 0 by touchdown-hover.
249
- const dx = (c.px - c.x) * (1 - diveT);
250
- const dy = (c.py - c.y) * (1 - diveT);
251
- const rotFlight = c.protZ * (1 - diveT);
252
-
253
- // depth: stack height → arc bulge (+90 at mid-flight) → hover → settle 0.
254
- const arc = Math.sin(diveT * Math.PI) * 90;
255
- const zDive = interpolate(diveT, [0, 1], [c.pz, HOVER_H]) + arc;
256
- const z = frame < cue ? c.pz : zDive * (1 - settleT); // pile height before the deal
257
-
258
- // scale: in the pile 1, snap up 1.06 mid-flight, settle back to 1
259
- const dealScale = 1 + Math.sin(diveT * Math.PI) * 0.06;
260
- const press = interpolate(frame, [cue + 10, cue + 11, cue + 12], [1, 0.996, 1], {
261
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
262
- });
263
- const scale = dealScale * press;
264
-
265
- // --- nano-lab slide (104 → 114): glide from (408,1402) to the first-row
266
- // slot with a light float (scale 1→1.02→1, small Z lift, wider shadow) ---
267
- const slideT = isNano
268
- ? interpolate(frame, [FILTER_START, FILTER_START + 10], [0, 1], {
269
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: SLIDE_EASE,
270
- })
271
- : 0;
272
- const slideDy = (NANO_TO.y - nano.y) * slideT;
273
- const slideDx = (NANO_TO.x - nano.x) * slideT;
274
- const float = Math.sin(slideT * Math.PI); // 0→1→0 across the slide
275
- const slideScale = 1 + 0.02 * float;
276
- const slideZ = 18 * float;
277
-
278
- // once fully settled, force an exact identity so the card sits flush
279
- // with its slot on the tilted board (no residual sub-px drift).
280
- const landed = frame >= cue + 12;
281
- const inPile = frame < cue;
282
- const transform = isNano && frame >= FILTER_START
283
- ? `translate3d(${slideDx}px, ${slideDy}px, ${slideZ}px) scale(${slideScale})`
284
- : outT > 0
285
- ? `translate3d(0px, ${8 * outT}px, 0px)`
286
- : landed
287
- ? 'translate3d(0px, 0px, 0px)'
288
- : inPile
289
- ? `translate3d(${c.px - c.x}px, ${c.py - c.y}px, ${c.pz}px) rotateZ(${c.protZ}deg)`
290
- : `translate3d(${dx}px, ${dy}px, ${z}px) rotateZ(${rotFlight}deg) scale(${scale})`;
291
-
292
- // shadow: stacked cards carry almost none (they sit on each other),
293
- // airborne large/soft, tight when flush, widening on the slide
294
- const shadow = isNano && frame >= FILTER_START
295
- ? paint(`0 ${2 + 14 * float}px ${6 + 26 * float}px rgba(60,45,30,${0.08 + 0.1 * float})`)
296
- : landed
297
- ? paint('0 2px 6px rgba(60,45,30,.08)')
298
- : inPile
299
- ? paint('0 1px 3px rgba(60,45,30,.14)')
300
- : paint(`0 ${36 - 30 * settleT}px ${70 - 60 * settleT}px rgba(60,45,30,${0.3 - 0.22 * settleT})`);
301
-
302
- // motion-blur ghost during the deal: a faint blurred copy trailing the flight path
303
- const showGhost = diveT > 0.02 && diveT < 0.98;
304
- const ghostLagX = (c.px - c.x) * 0.05;
305
- const ghostLagY = (c.py - c.y) * 0.05;
306
-
307
- return (
308
- <div key={`${c.file}-${i}`} style={{ transformStyle: 'preserve-3d' }}>
309
- {showGhost ? (
310
- <div
311
- style={{
312
- position: 'absolute',
313
- left: c.x,
314
- top: c.y,
315
- width: c.w,
316
- height: c.h,
317
- transform: `translate3d(${dx + ghostLagX}px, ${dy + ghostLagY}px, ${z}px) rotateZ(${rotFlight}deg) scale(${scale})`,
318
- transformOrigin: 'center center',
319
- opacity: 0.25 * (1 - diveT),
320
- filter: 'blur(6px)',
321
- borderRadius: radius,
322
- overflow: 'hidden',
323
- pointerEvents: 'none',
324
- }}
325
- >
326
- <Img
327
- src={asset(`textures/live/${c.file}`)}
328
- style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }}
329
- />
330
- </div>
331
- ) : null}
332
-
333
- <div
334
- style={{
335
- position: 'absolute',
336
- left: c.x,
337
- top: c.y,
338
- width: c.w,
339
- height: c.h,
340
- transform,
341
- transformOrigin: 'center center',
342
- boxShadow: shadow,
343
- borderRadius: radius,
344
- opacity: 1 - outT,
345
- overflow: 'hidden',
346
- }}
347
- >
348
- <Img
349
- src={asset(`textures/live/${c.file}`)}
350
- style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }}
351
- />
352
- </div>
353
- </div>
354
- );
355
- })}
356
-
357
- {/* ---- search box: paper patch over the placeholder text (keeps the
358
- magnifier icon), then "nano-lab" typed in with a blinking caret ---- */}
359
- {frame >= 118 ? (
360
- <div
361
- style={{
362
- position: 'absolute',
363
- left: 440,
364
- top: SEARCH.y + 4,
365
- width: SEARCH.x + SEARCH.w - 448,
366
- height: SEARCH.h - 8,
367
- background: FIELD,
368
- opacity: interpolate(frame, [118, 124], [0, 1], {
369
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
370
- }),
371
- pointerEvents: 'none',
372
- }}
373
- />
374
- ) : null}
375
- {frame >= TYPE_START - 2 ? (
376
- <div
377
- style={{
378
- position: 'absolute',
379
- left: 448,
380
- top: SEARCH.y,
381
- height: SEARCH.h,
382
- display: 'flex',
383
- alignItems: 'center',
384
- fontFamily: (paperStyle ? 'ui-sans-serif, system-ui, -apple-system, sans-serif' : theme.font),
385
- fontSize: 15,
386
- letterSpacing: 0.2,
387
- color: paint('oklch(25% 0.006 82)'),
388
- pointerEvents: 'none',
389
- }}
390
- >
391
- <span>{QUERY.slice(0, typedCount)}</span>
392
- {caretOn ? (
393
- <span
394
- style={{
395
- display: 'inline-block',
396
- width: 2,
397
- height: 20,
398
- marginLeft: 2,
399
- background: accent,
400
- }}
401
- />
402
- ) : null}
403
- </div>
404
- ) : null}
405
-
406
- {/* ---- click ripple on the filtered card: two concentric amber rings ---- */}
407
- {[0, 1].map((r) => {
408
- const start = 176 + r * 3;
409
- if (frame < start || frame > start + 10) return null;
410
- const t = interpolate(frame, [start, start + 10], [0, 1], {
411
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.out(Easing.cubic),
412
- });
413
- const rad = interpolate(t, [0, 1], [14, r === 0 ? 54 : 78]);
414
- return (
415
- <div
416
- key={`ripple-${r}`}
417
- style={{
418
- position: 'absolute',
419
- left: CLICK_C.x - rad,
420
- top: CLICK_C.y - rad,
421
- width: rad * 2,
422
- height: rad * 2,
423
- borderRadius: '50%',
424
- border: `2px solid ${accent}`,
425
- opacity: 1 - t,
426
- pointerEvents: 'none',
427
- }}
428
- />
429
- );
430
- })}
431
-
432
- {/* ---- selected-card amber outline, lit from the click until the cut ---- */}
433
- {frame >= 178 ? (
434
- <div
435
- style={{
436
- position: 'absolute',
437
- left: NANO_TO.x - 6,
438
- top: NANO_TO.y - 6,
439
- width: nano.w + 12,
440
- height: nano.h + 12,
441
- borderRadius: 16,
442
- border: `3px solid ${accent}`,
443
- boxShadow: paint('0 0 40px rgba(180,120,50,0.5)'),
444
- opacity: interpolate(frame, [178, 181], [0.5, 1], {
445
- extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
446
- }),
447
- pointerEvents: 'none',
448
- }}
449
- />
450
- ) : null}
451
-
452
- {/* near-edge rim light along the extended board's leading (bottom) edge */}
453
- <div
454
- style={{
455
- position: 'absolute',
456
- left: 0,
457
- right: 0,
458
- top: PAPER_EXT.y + PAPER_EXT.h - 8,
459
- height: 8,
460
- background: paint('rgba(255,255,255,0.85)'),
461
- filter: 'blur(6px)',
462
- opacity: 0.5,
463
- pointerEvents: 'none',
464
- }}
465
- />
466
- </PageCam>
467
- );
468
- };
1
+ import { useVisualTheme, themePaint, themeAsset, sceneDefaults } from '../../themes/visual-theme';
2
+ import { Img, interpolate, useCurrentFrame, Easing, getRemotionEnvironment } from 'remotion';
3
+ import { PageCam, CamKey } from './PageCam';
4
+ import layout from '../live-layout.json';
5
+
6
+ const cards = layout.projects.cards;
7
+ const PAGE_H = layout.projects.pageH;
8
+
9
+ const HOVER_H = 40; // px above the slot (translateZ) a card hovers at mid-dive
10
+ const SETTLE_EASE = Easing.bezier(0.3, 0, 0.25, 1.15); // slight overshoot / compress
11
+ const DIVE_EASE = Easing.bezier(0.3, 0, 0.2, 1); // decelerate into the hover
12
+ const SLIDE_EASE = Easing.bezier(0.35, 0, 0.2, 1); // nano-lab card slide to the top slot
13
+
14
+ // page paper colors, sampled from the rendered projects-empty texture
15
+
16
+ // ---- 16 "overflow" extras extend the grid DOWNWARD (no hovering, no overlap):
17
+ // fill the empty 3rd column of the y=1402 row, then five new rows below the
18
+ // texture at y=1795…3367, columns matching the real grid. ----
19
+ const COLS = [408, 781.328125, 1154.65625];
20
+ const CARD_W = 357.328125;
21
+ const EXTRA_ROWS = [1795, 2188, 2581, 2974, 3367];
22
+ const PAPER_EXT = { x: 0, y: PAGE_H, w: 1920, h: 2036 }; // paper extension below the texture (flush bottom 3782)
23
+
24
+ const extras = Array.from({ length: 16 }, (_, i) => ({
25
+ file: `card${((i * 3 + 2) % 10) + 1}.png`, // deterministic, neighbors differ
26
+ x: i === 0 ? COLS[2] : COLS[(i - 1) % 3],
27
+ y: i === 0 ? 1402 : EXTRA_ROWS[Math.floor((i - 1) / 3)],
28
+ w: CARD_W,
29
+ h: 312,
30
+ title: '',
31
+ }));
32
+
33
+ // ---- the DECK: all 26 cards start stacked in one pile at the page's top
34
+ // right. The shot opens on a rotating 3D close-up of the pile (0–35), pulls
35
+ // back to reveal the page (35–62), and the cards deal themselves to their
36
+ // slots in reading order (y, then x) on a hard-accelerating cadence — the gap
37
+ // between departures shrinks from 4f to 0.2f (gap_k = 4 − 0.1584k), so the
38
+ // dealing goes from deliberate to a blur. First departs at 36 (mid pull-back),
39
+ // last ≈88, lands ≈96. Pile poses carry a small deterministic jitter and each
40
+ // card keeps a stack height (top of pile = first to leave). ----
41
+ const PILE = { x: 1430, y: 240 };
42
+ const N_CARDS = 26;
43
+ const DEAL_START = 36;
44
+ const STACK_STEP = 3; // px of physical height per card — the pile reads as a real stack
45
+
46
+ // dark-metal backdrop for the opening close-up: covers everything in the page
47
+ // plane, with a warm spotlight pooled on the pile; fades out with the pull-back
48
+ const METAL_FADE = [34, 56] as const;
49
+ // Real-time preview stand-in for the metal (Player / Studio / workbench — anything that is
50
+ // not the final render). The procedural gradients below cover a 9000×9000 plane that
51
+ // Chromium has to re-rasterize every frame while PageCam's `zoom` changes; in real time
52
+ // the raster never keeps up, the plane drops in and out, and the close-up strobes between
53
+ // dark table and white page (measured: ~20 blank-outs in the first 2s). A flat fill needs
54
+ // no raster at all. Same geometry, same fade — only the paint differs; the render still
55
+ // paints the brushed metal. Tone = median of the rendered table (#373637 sampled).
56
+
57
+ const grid = [
58
+ ...cards.map((c) => ({ file: c.file, x: c.x, y: c.y, w: c.w, h: c.h, title: c.title })),
59
+ ...extras,
60
+ ]
61
+ .sort((a, b) => a.y - b.y || a.x - b.x)
62
+ .map((c, k) => ({
63
+ ...c,
64
+ cue: DEAL_START + 4 * k - 0.0792 * k * (k - 1),
65
+ // pile pose: tiny alternating offsets + roll, stacked top-down by k
66
+ px: PILE.x + (((k * 7) % 9) - 4) * 2,
67
+ py: PILE.y + (((k * 5) % 7) - 3) * 2,
68
+ protZ: ((k * 11) % 7) - 3,
69
+ pz: (N_CARDS - k) * STACK_STEP, // physical stack height; k=0 rides on top
70
+ }));
71
+
72
+ // ---- the search target: nano-lab slides up to the first-row slot on filter ----
73
+ const nanoIdx = grid.findIndex((c) => c.title.includes('nano-lab'));
74
+ const nano = grid[nanoIdx];
75
+ const NANO_TO = { x: 408, y: 247 }; // first-row slot the filtered card slides into
76
+ const CLICK_C = { x: 586, y: 391 }; // click point on the settled result card
77
+
78
+ // filter departure rank for the 19 non-target cards (reading order)
79
+ const leaveRank = new Map<number, number>();
80
+ grid.forEach((_, i) => {
81
+ if (i !== nanoIdx) leaveRank.set(i, leaveRank.size);
82
+ });
83
+
84
+ // search box (page-space CSS px) + typing beats
85
+ const SEARCH = { x: 408, y: 130, w: 1016, h: 44 };
86
+ /** Context-level defaults, editable per clip in the workbench. `query` is only the
87
+ * typed text; the card that survives the filter is still the nano-lab card from layout. */
88
+ export const SCENE_FLYIN_DEFAULTS = {
89
+ query: 'nano-lab',
90
+ accent: '#ae6700', // oklch(58% 0.13 65)
91
+ };
92
+ type SceneFlyInProps = Partial<typeof SCENE_FLYIN_DEFAULTS>;
93
+ const TYPE_START = 128; // 3 frames per character → last char at ≈149
94
+ const FILTER_START = 160; // beat of rest after typing, then the grid filters
95
+
96
+ // pile centre for the opening close-up
97
+ const PILE_CX = PILE.x + CARD_W / 2;
98
+ const PILE_CY = PILE.y + 156;
99
+
100
+ // Narrative: the shot opens on a rotating 3D CLOSE-UP of the 26-card pile
101
+ // (orbiting from a left-oblique to a right-oblique look), pulls back to
102
+ // reveal the page as the pile starts dealing cards to their grid slots, each
103
+ // departure faster than the last, extending the grid far below the page fold
104
+ // → the camera scrolls down chasing the dealing, FASTER each leg, arriving
105
+ // straight at the bottom → rests half a second on the full board → swooshes
106
+ // back up to the search box → "nano-lab" is typed (unhurried), a breath, then
107
+ // the grid filters down to one card which slides into the first row → a click
108
+ // ripple fires and the camera pushes into the card, handing off to detail.
109
+ const CAM_KEYS: CamKey[] = [
110
+ { frame: 0, cx: PILE_CX - 30, cy: PILE_CY + 60, zoom: 1.95, rotX: 46, rotY: -30, rotZ: 9, persp: 1100 }, // low side view of the stack, left-oblique
111
+ { frame: 34, cx: PILE_CX + 30, cy: PILE_CY + 40, zoom: 1.85, rotX: 42, rotY: 26, rotZ: -7, persp: 1100 }, // orbit around the pile to a right-oblique
112
+ { frame: 62, cx: 960, cy: 900, zoom: 0.88, rotX: 26, rotY: 0, rotZ: 2, persp: 1300 }, // pull back — dashboard revealed, dealing underway
113
+ { frame: 82, cx: 950, cy: 1900, zoom: 0.78, rotX: 14, rotY: 0, rotZ: 0, persp: 1300 }, // speeding up (~50 px/f)
114
+ { frame: 98, cx: 960, cy: 3032, zoom: 0.72, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // fastest leg (~70 px/f), arrives straight at the paper's flush bottom
115
+ { frame: 113, cx: 960, cy: 3032, zoom: 0.72, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // 0.5s REST on the full board
116
+ { frame: 124, cx: 960, cy: 380, zoom: 0.9, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // swoosh back up to the search/filter header
117
+ { frame: 174, cx: 960, cy: 380, zoom: 0.9, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // hold through typing, breath, filter, slide
118
+ { frame: 190, cx: CLICK_C.x, cy: CLICK_C.y, zoom: 2.2, rotX: 0, rotY: 0, rotZ: 0, persp: 1300 }, // push into the clicked card, carried through the white flash
119
+ ];
120
+
121
+ export const SceneFlyIn: React.FC<SceneFlyInProps> = (props) => {
122
+ const theme = useVisualTheme();
123
+ const paperStyle = theme.id === 'ink-press';
124
+ const paint = (css: string) => themePaint(theme, css);
125
+ const asset = (src: string) => themeAsset(theme, src);
126
+ const PAPER = paint('#f9f6f1'); // page background (bottom rows)
127
+ const FIELD = paint('#fefcf9'); // search-box interior
128
+ const METAL_PREVIEW = paint('#383638');
129
+ const { query: QUERY, accent } = { ...sceneDefaults(theme, 'table', SCENE_FLYIN_DEFAULTS), ...props };
130
+ const frame = useCurrentFrame();
131
+ const { isRendering } = getRemotionEnvironment();
132
+
133
+ // DOF fades out over the straightening leg of the scroll (82 → 98)
134
+ const dofStrength = interpolate(frame, [82, 98], [5, 0], {
135
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
136
+ });
137
+
138
+ // typed characters: one every 3 frames from TYPE_START (unhurried typing)
139
+ const typedCount = frame < TYPE_START
140
+ ? 0
141
+ : Math.min(QUERY.length, Math.floor((frame - TYPE_START) / 3) + 1);
142
+ // caret: solid while typing, then blinks on an 8-frame cycle until the click
143
+ const caretOn =
144
+ frame >= TYPE_START - 2 &&
145
+ frame <= 185 &&
146
+ (frame <= TYPE_START + 24 || Math.floor((frame - (TYPE_START + 24)) / 8) % 2 === 0);
147
+
148
+ return (
149
+ <PageCam
150
+ src="textures/live/projects-empty.png"
151
+ pageH={PAGE_H}
152
+ keys={CAM_KEYS}
153
+ ease={Easing.bezier(0.33, 0, 0.15, 1)}
154
+ dof={dofStrength > 0.1 ? { focusY: 260, strength: dofStrength } : undefined}
155
+ >
156
+ {/* ---- dark brushed-metal table under the opening pile close-up: a huge
157
+ plane (covers the viewport at any oblique angle) with a warm
158
+ spotlight pooled on the stack; fades away as the camera pulls
159
+ back and the dashboard page takes over ---- */}
160
+ {frame < METAL_FADE[1] ? (
161
+ <div
162
+ style={{
163
+ position: 'absolute',
164
+ left: -3000,
165
+ top: -3000,
166
+ width: 9000,
167
+ height: 9000,
168
+ opacity: interpolate(frame, [METAL_FADE[0], METAL_FADE[1]], [1, 0], {
169
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
170
+ }),
171
+ background: !paperStyle ? theme.stage : isRendering ? [
172
+ // warm key light pooled on the pile
173
+ paint(`radial-gradient(1300px 900px at ${3000 + PILE_CX}px ${3000 + PILE_CY}px, rgba(255,214,150,0.20), rgba(255,190,120,0.06) 40%, transparent 68%)`),
174
+ // brushed-metal grain: fine anisotropic streaks
175
+ paint('repeating-linear-gradient(100deg, rgba(255,255,255,0.028) 0px, rgba(255,255,255,0.028) 1px, transparent 2px, transparent 7px)'),
176
+ paint('repeating-linear-gradient(100deg, rgba(0,0,0,0.16) 0px, rgba(0,0,0,0.16) 2px, transparent 4px, transparent 13px)'),
177
+ // broad steel sheen
178
+ paint('linear-gradient(115deg, #2a2d33 0%, #383c44 28%, #22242a 55%, #33363e 78%, #1d1f24 100%)'),
179
+ ].join(', ') : METAL_PREVIEW,
180
+ pointerEvents: 'none',
181
+ }}
182
+ />
183
+ ) : null}
184
+
185
+ {/* ---- paper extension: the page grows past the texture so the three
186
+ extra rows sit on paper, not on the void ---- */}
187
+ <div
188
+ style={{
189
+ position: 'absolute',
190
+ left: PAPER_EXT.x,
191
+ top: PAPER_EXT.y,
192
+ width: PAPER_EXT.w,
193
+ height: PAPER_EXT.h,
194
+ background: PAPER,
195
+ pointerEvents: 'none',
196
+ }}
197
+ />
198
+
199
+ {/* ---- filter clean-up: paper patch over the stale section headers /
200
+ counts baked into the texture below y=500, revealed 84–92 ---- */}
201
+ {frame >= FILTER_START ? (
202
+ <div
203
+ style={{
204
+ position: 'absolute',
205
+ left: 0,
206
+ top: 500,
207
+ width: 1920,
208
+ height: PAGE_H - 500,
209
+ background: PAPER,
210
+ opacity: interpolate(frame, [FILTER_START, FILTER_START + 8], [0, 1], {
211
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
212
+ }),
213
+ pointerEvents: 'none',
214
+ }}
215
+ />
216
+ ) : null}
217
+
218
+ {/* ---- 26 cards: visible pile at top right from frame 0, each card
219
+ deals itself to its slot (arc flight, roll resolving) on an
220
+ accelerating cadence; on filter the 25 non-matches fade+sink
221
+ away and nano-lab slides up to row one ---- */}
222
+ {grid.map((c, i) => {
223
+ const { cue } = c;
224
+ const radius = 16;
225
+ const isNano = i === nanoIdx;
226
+
227
+ // --- filter fade-out for the 25 non-target cards (staggered, 5f) ---
228
+ const outCue = isNano ? Infinity : FILTER_START + leaveRank.get(i)! * 0.4;
229
+ if (frame >= outCue + 5) return null;
230
+ const outT = isNano
231
+ ? 0
232
+ : interpolate(frame, [outCue, outCue + 5], [0, 1], {
233
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.inOut(Easing.quad),
234
+ });
235
+
236
+ // --- beat 1: deal (cue → cue+8): from the pile pose (px,py, stack
237
+ // height pz, small roll) to the hover pose over the slot. The flight
238
+ // arcs UP first (z bulge) like a card snapped off the top of a deck. ---
239
+ const diveT = interpolate(frame, [cue, cue + 8], [0, 1], {
240
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: DIVE_EASE,
241
+ });
242
+
243
+ // --- beat 2: settle (cue+8 → cue+12): Z from HOVER_H down to 0 ---
244
+ const settleT = interpolate(frame, [cue + 8, cue + 12], [0, 1], {
245
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: SETTLE_EASE,
246
+ });
247
+
248
+ // in-flight pose: pile → slot, roll resolving to 0 by touchdown-hover.
249
+ const dx = (c.px - c.x) * (1 - diveT);
250
+ const dy = (c.py - c.y) * (1 - diveT);
251
+ const rotFlight = c.protZ * (1 - diveT);
252
+
253
+ // depth: stack height → arc bulge (+90 at mid-flight) → hover → settle 0.
254
+ const arc = Math.sin(diveT * Math.PI) * 90;
255
+ const zDive = interpolate(diveT, [0, 1], [c.pz, HOVER_H]) + arc;
256
+ const z = frame < cue ? c.pz : zDive * (1 - settleT); // pile height before the deal
257
+
258
+ // scale: in the pile 1, snap up 1.06 mid-flight, settle back to 1
259
+ const dealScale = 1 + Math.sin(diveT * Math.PI) * 0.06;
260
+ const press = interpolate(frame, [cue + 10, cue + 11, cue + 12], [1, 0.996, 1], {
261
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
262
+ });
263
+ const scale = dealScale * press;
264
+
265
+ // --- nano-lab slide (104 → 114): glide from (408,1402) to the first-row
266
+ // slot with a light float (scale 1→1.02→1, small Z lift, wider shadow) ---
267
+ const slideT = isNano
268
+ ? interpolate(frame, [FILTER_START, FILTER_START + 10], [0, 1], {
269
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: SLIDE_EASE,
270
+ })
271
+ : 0;
272
+ const slideDy = (NANO_TO.y - nano.y) * slideT;
273
+ const slideDx = (NANO_TO.x - nano.x) * slideT;
274
+ const float = Math.sin(slideT * Math.PI); // 0→1→0 across the slide
275
+ const slideScale = 1 + 0.02 * float;
276
+ const slideZ = 18 * float;
277
+
278
+ // once fully settled, force an exact identity so the card sits flush
279
+ // with its slot on the tilted board (no residual sub-px drift).
280
+ const landed = frame >= cue + 12;
281
+ const inPile = frame < cue;
282
+ const transform = isNano && frame >= FILTER_START
283
+ ? `translate3d(${slideDx}px, ${slideDy}px, ${slideZ}px) scale(${slideScale})`
284
+ : outT > 0
285
+ ? `translate3d(0px, ${8 * outT}px, 0px)`
286
+ : landed
287
+ ? 'translate3d(0px, 0px, 0px)'
288
+ : inPile
289
+ ? `translate3d(${c.px - c.x}px, ${c.py - c.y}px, ${c.pz}px) rotateZ(${c.protZ}deg)`
290
+ : `translate3d(${dx}px, ${dy}px, ${z}px) rotateZ(${rotFlight}deg) scale(${scale})`;
291
+
292
+ // shadow: stacked cards carry almost none (they sit on each other),
293
+ // airborne large/soft, tight when flush, widening on the slide
294
+ const shadow = isNano && frame >= FILTER_START
295
+ ? paint(`0 ${2 + 14 * float}px ${6 + 26 * float}px rgba(60,45,30,${0.08 + 0.1 * float})`)
296
+ : landed
297
+ ? paint('0 2px 6px rgba(60,45,30,.08)')
298
+ : inPile
299
+ ? paint('0 1px 3px rgba(60,45,30,.14)')
300
+ : paint(`0 ${36 - 30 * settleT}px ${70 - 60 * settleT}px rgba(60,45,30,${0.3 - 0.22 * settleT})`);
301
+
302
+ // motion-blur ghost during the deal: a faint blurred copy trailing the flight path
303
+ const showGhost = diveT > 0.02 && diveT < 0.98;
304
+ const ghostLagX = (c.px - c.x) * 0.05;
305
+ const ghostLagY = (c.py - c.y) * 0.05;
306
+
307
+ return (
308
+ <div key={`${c.file}-${i}`} style={{ transformStyle: 'preserve-3d' }}>
309
+ {showGhost ? (
310
+ <div
311
+ style={{
312
+ position: 'absolute',
313
+ left: c.x,
314
+ top: c.y,
315
+ width: c.w,
316
+ height: c.h,
317
+ transform: `translate3d(${dx + ghostLagX}px, ${dy + ghostLagY}px, ${z}px) rotateZ(${rotFlight}deg) scale(${scale})`,
318
+ transformOrigin: 'center center',
319
+ opacity: 0.25 * (1 - diveT),
320
+ filter: 'blur(6px)',
321
+ borderRadius: radius,
322
+ overflow: 'hidden',
323
+ pointerEvents: 'none',
324
+ }}
325
+ >
326
+ <Img
327
+ src={asset(`textures/live/${c.file}`)}
328
+ style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }}
329
+ />
330
+ </div>
331
+ ) : null}
332
+
333
+ <div
334
+ style={{
335
+ position: 'absolute',
336
+ left: c.x,
337
+ top: c.y,
338
+ width: c.w,
339
+ height: c.h,
340
+ transform,
341
+ transformOrigin: 'center center',
342
+ boxShadow: shadow,
343
+ borderRadius: radius,
344
+ opacity: 1 - outT,
345
+ overflow: 'hidden',
346
+ }}
347
+ >
348
+ <Img
349
+ src={asset(`textures/live/${c.file}`)}
350
+ style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }}
351
+ />
352
+ </div>
353
+ </div>
354
+ );
355
+ })}
356
+
357
+ {/* ---- search box: paper patch over the placeholder text (keeps the
358
+ magnifier icon), then "nano-lab" typed in with a blinking caret ---- */}
359
+ {frame >= 118 ? (
360
+ <div
361
+ style={{
362
+ position: 'absolute',
363
+ left: 440,
364
+ top: SEARCH.y + 4,
365
+ width: SEARCH.x + SEARCH.w - 448,
366
+ height: SEARCH.h - 8,
367
+ background: FIELD,
368
+ opacity: interpolate(frame, [118, 124], [0, 1], {
369
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
370
+ }),
371
+ pointerEvents: 'none',
372
+ }}
373
+ />
374
+ ) : null}
375
+ {frame >= TYPE_START - 2 ? (
376
+ <div
377
+ style={{
378
+ position: 'absolute',
379
+ left: 448,
380
+ top: SEARCH.y,
381
+ height: SEARCH.h,
382
+ display: 'flex',
383
+ alignItems: 'center',
384
+ fontFamily: (paperStyle ? 'ui-sans-serif, system-ui, -apple-system, sans-serif' : theme.font),
385
+ fontSize: 15,
386
+ letterSpacing: 0.2,
387
+ color: paint('oklch(25% 0.006 82)'),
388
+ pointerEvents: 'none',
389
+ }}
390
+ >
391
+ <span>{QUERY.slice(0, typedCount)}</span>
392
+ {caretOn ? (
393
+ <span
394
+ style={{
395
+ display: 'inline-block',
396
+ width: 2,
397
+ height: 20,
398
+ marginLeft: 2,
399
+ background: accent,
400
+ }}
401
+ />
402
+ ) : null}
403
+ </div>
404
+ ) : null}
405
+
406
+ {/* ---- click ripple on the filtered card: two concentric amber rings ---- */}
407
+ {[0, 1].map((r) => {
408
+ const start = 176 + r * 3;
409
+ if (frame < start || frame > start + 10) return null;
410
+ const t = interpolate(frame, [start, start + 10], [0, 1], {
411
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.out(Easing.cubic),
412
+ });
413
+ const rad = interpolate(t, [0, 1], [14, r === 0 ? 54 : 78]);
414
+ return (
415
+ <div
416
+ key={`ripple-${r}`}
417
+ style={{
418
+ position: 'absolute',
419
+ left: CLICK_C.x - rad,
420
+ top: CLICK_C.y - rad,
421
+ width: rad * 2,
422
+ height: rad * 2,
423
+ borderRadius: '50%',
424
+ border: `2px solid ${accent}`,
425
+ opacity: 1 - t,
426
+ pointerEvents: 'none',
427
+ }}
428
+ />
429
+ );
430
+ })}
431
+
432
+ {/* ---- selected-card amber outline, lit from the click until the cut ---- */}
433
+ {frame >= 178 ? (
434
+ <div
435
+ style={{
436
+ position: 'absolute',
437
+ left: NANO_TO.x - 6,
438
+ top: NANO_TO.y - 6,
439
+ width: nano.w + 12,
440
+ height: nano.h + 12,
441
+ borderRadius: 16,
442
+ border: `3px solid ${accent}`,
443
+ boxShadow: paint('0 0 40px rgba(180,120,50,0.5)'),
444
+ opacity: interpolate(frame, [178, 181], [0.5, 1], {
445
+ extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
446
+ }),
447
+ pointerEvents: 'none',
448
+ }}
449
+ />
450
+ ) : null}
451
+
452
+ {/* near-edge rim light along the extended board's leading (bottom) edge */}
453
+ <div
454
+ style={{
455
+ position: 'absolute',
456
+ left: 0,
457
+ right: 0,
458
+ top: PAPER_EXT.y + PAPER_EXT.h - 8,
459
+ height: 8,
460
+ background: paint('rgba(255,255,255,0.85)'),
461
+ filter: 'blur(6px)',
462
+ opacity: 0.5,
463
+ pointerEvents: 'none',
464
+ }}
465
+ />
466
+ </PageCam>
467
+ );
468
+ };