Spaces:
Running
Running
| // @ts-nocheck | |
| // ============================================================================ | |
| // MOTION GRAPHICS · OBSIDIAN ORBIT — Scene 07 / LOCAL LINK (9s, 270f) | |
| // | |
| // "Keynote object-worship". ONE hero artifact: the BROWSER slab. A thick glass | |
| // slab whose face is a browser frame — traffic-light dots, an address-bar pill, | |
| // an empty page. A cursor glides to the pill and PASTES a "localhost" link; on | |
| // the ENTER beat a LightSweep rakes across the page and the product DASHBOARD | |
| // reveals inside (sidebar + KPI cards + a chart). The WORLD orbits (never the | |
| // camera) in slow hold→ease arcs; spec Callouts billboard on drawn leader lines | |
| // ("localhost", "READY TO START"); the angle-tracked sheen rakes the turn. A | |
| // weighty lock-in settles the slab front-on on the payoff with an impact + | |
| // shockwave, then it holds — sheen tracking the final turn. | |
| // | |
| // Built ENTIRELY on the Plinth module (mirrors ObsidianOrbit.tsx + Scene03's | |
| // contract) + the shared Chronixel engine. CSS-3D only, deterministic, no WebGL. | |
| // ============================================================================ | |
| import React from "react"; | |
| import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion"; | |
| import { | |
| Plinth, | |
| OrbitWorld, | |
| Extrude, | |
| Callout, | |
| DustMotes, | |
| } from "../../plinth/plinth"; | |
| import { C, withAlpha, ACCENT_GRAD } from "../../chronixel/theme"; | |
| import { FONT, MONO } from "../../chronixel/fonts"; | |
| import { | |
| beat, | |
| clamp01, | |
| mix, | |
| osc, | |
| enter, | |
| springAt, | |
| EASE, | |
| SPRING, | |
| } from "../../chronixel/motion"; | |
| import { Shockwave, GlowPulse, LightSweep } from "../../chronixel/fx"; | |
| /* ---------------------------------------------------------------------------- | |
| A small mono eyebrow tag pinned top-left over the void — frames the beat. | |
| -------------------------------------------------------------------------- */ | |
| const Eyebrow: React.FC<{ at: number; children: React.ReactNode }> = ({ | |
| at, | |
| children, | |
| }) => { | |
| const frame = useCurrentFrame(); | |
| const { fps } = useVideoConfig(); | |
| return ( | |
| <div | |
| style={{ | |
| position: "absolute", | |
| left: 120, | |
| top: 120, | |
| display: "flex", | |
| alignItems: "center", | |
| gap: 14, | |
| fontFamily: MONO, | |
| fontSize: 15, | |
| letterSpacing: 5, | |
| textTransform: "uppercase", | |
| color: C.accent2, | |
| ...enter(frame, fps, at, { from: "left", dist: 32, blur: 0 }), | |
| }} | |
| > | |
| <span | |
| style={{ | |
| width: 30, | |
| height: 2, | |
| background: ACCENT_GRAD, | |
| boxShadow: `0 0 12px ${C.accentGlow}`, | |
| }} | |
| /> | |
| {children} | |
| </div> | |
| ); | |
| }; | |
| /* ============================================================================ | |
| LOCAL LINK. Hero = the BROWSER artifact. A glass slab whose face is a | |
| browser window: chrome draws on, a cursor pastes a "localhost" link into the | |
| address pill, ENTER fires a light sweep, and the product DASHBOARD reveals | |
| inside. The world orbits, callouts fire, then the slab LOCKS front-on with an | |
| impact on the payoff ("READY TO START"). | |
| ========================================================================== */ | |
| export const MgOrbitScene07LocalLink: React.FC = () => { | |
| const frame = useCurrentFrame(); | |
| const { fps } = useVideoConfig(); | |
| const t = frame / fps; | |
| // --- beat timeline (seconds) ------------------------------------------ | |
| const CHROME = 0.5; // browser chrome draws on | |
| const URLAT = 2.7; // cursor pastes the localhost URL | |
| const ENTER = 4.6; // enter key → page loads | |
| const LOCK = 6.9; // apex lock-in / settle on the dashboard payoff | |
| // --- face choreography ------------------------------------------------- | |
| const chromeP = beat(frame, fps, CHROME, CHROME + 1.0, EASE.backOut); // window builds | |
| const cursorP = beat(frame, fps, 1.4, URLAT, EASE.inOut); // cursor glides to the pill | |
| const urlP = clamp01((t - URLAT) / 0.9); // url chars paste/type in | |
| const pillFlash = beat(frame, fps, URLAT, URLAT + 0.35, EASE.out); // pill pulses on paste | |
| const reveal = beat(frame, fps, ENTER, ENTER + 1.0, EASE.expoOut); // dashboard wipes in | |
| // --- the lock-in: a weighty spring settle on the apex ------------------- | |
| const stamp = springAt(frame, fps, LOCK, SPRING.HEAVY); // 0→1 weighty settle | |
| const stampScale = mix(1.12, 1, clamp01(stamp)); // slams down to rest | |
| const flash = clamp01(1 - (t - LOCK) / 0.45) * (t >= LOCK ? 1 : 0); | |
| const riser = beat(frame, fps, LOCK - 1.4, LOCK, EASE.out); // build into apex | |
| const lockRing = clamp01(stamp); | |
| const ringPulse = 0.5 + 0.5 * osc(t, 3); | |
| // hold→ease orbit: reads the browser face on the way in, settles to 0° at the | |
| // lock — the snap-to-camera payoff on the live dashboard. | |
| const legs = [ | |
| { arc: -22, hold: 0.5, travel: 2.2 }, | |
| { arc: 26, hold: 1.0, travel: 2.6 }, | |
| { arc: -7, hold: 0.5, travel: 1.6 }, // lands ~0° near LOCK | |
| ]; | |
| // the localhost link, typed character-by-character into the pill. | |
| const URL = "http://localhost:3000"; | |
| const urlChars = Math.round(URL.length * urlP); | |
| // dashboard KPI cards + a tiny bar chart, revealed by the light sweep. | |
| const kpis = [ | |
| { label: "USERS", val: "12.4k" }, | |
| { label: "BUILD", val: "OK" }, | |
| { label: "UPTIME", val: "100%" }, | |
| ]; | |
| const bars = [0.42, 0.66, 0.5, 0.84, 0.6, 0.95]; | |
| const HeroFace = ( | |
| <div | |
| style={{ | |
| position: "absolute", | |
| inset: 0, | |
| padding: 18, | |
| display: "flex", | |
| flexDirection: "column", | |
| transform: `scale(${stampScale})`, | |
| }} | |
| > | |
| {/* browser window */} | |
| <div | |
| style={{ | |
| flex: 1, | |
| borderRadius: 16, | |
| overflow: "hidden", | |
| background: withAlpha("#06080e", 0.92), | |
| border: `1px solid ${C.glassBorder}`, | |
| display: "flex", | |
| flexDirection: "column", | |
| opacity: chromeP, | |
| transform: `translateY(${(1 - chromeP) * 16}px)`, | |
| boxShadow: `0 18px 50px ${withAlpha("#000", 0.55)}`, | |
| }} | |
| > | |
| {/* ---- title bar : traffic lights + address pill ---- */} | |
| <div | |
| style={{ | |
| display: "flex", | |
| alignItems: "center", | |
| gap: 14, | |
| padding: "12px 16px", | |
| background: withAlpha("#0c0f18", 0.95), | |
| borderBottom: `1px solid ${C.glassBorder}`, | |
| }} | |
| > | |
| <div style={{ display: "flex", gap: 8 }}> | |
| {["#ff5f57", "#febc2e", "#28c840"].map((c, i) => ( | |
| <div | |
| key={i} | |
| style={{ | |
| width: 12, | |
| height: 12, | |
| borderRadius: "50%", | |
| background: withAlpha(c, 0.9), | |
| }} | |
| /> | |
| ))} | |
| </div> | |
| {/* address-bar pill holding the localhost link */} | |
| <div | |
| style={{ | |
| flex: 1, | |
| height: 38, | |
| borderRadius: 19, | |
| display: "flex", | |
| alignItems: "center", | |
| gap: 10, | |
| padding: "0 16px", | |
| background: withAlpha("#10141f", 0.95), | |
| border: `1px solid ${withAlpha( | |
| C.accent, | |
| 0.25 + 0.5 * pillFlash, | |
| )}`, | |
| boxShadow: `0 0 ${18 * pillFlash}px ${withAlpha( | |
| C.accent, | |
| 0.4 * pillFlash, | |
| )}, inset 0 0 0 1px ${withAlpha("#fff", 0.03)}`, | |
| }} | |
| > | |
| {/* a small lock / local glyph */} | |
| <div | |
| style={{ | |
| width: 14, | |
| height: 14, | |
| borderRadius: 4, | |
| flexShrink: 0, | |
| background: ACCENT_GRAD, | |
| boxShadow: `0 0 8px ${C.accentGlow}`, | |
| }} | |
| /> | |
| <div | |
| style={{ | |
| fontFamily: MONO, | |
| fontSize: 18, | |
| letterSpacing: 0.5, | |
| color: urlChars > 0 ? C.text : C.textFaint, | |
| whiteSpace: "nowrap", | |
| }} | |
| > | |
| {urlChars > 0 ? URL.slice(0, urlChars) : "search or enter address"} | |
| {urlP > 0 && urlP < 1 ? ( | |
| <span style={{ color: C.accent }}>▎</span> | |
| ) : null} | |
| </div> | |
| </div> | |
| </div> | |
| {/* ---- page body : empty → dashboard reveal ---- */} | |
| <div style={{ position: "relative", flex: 1, overflow: "hidden" }}> | |
| {/* loading shimmer line that races across just before the reveal */} | |
| <div | |
| style={{ | |
| position: "absolute", | |
| left: 0, | |
| top: 0, | |
| height: 3, | |
| width: `${100 * clamp01((t - (ENTER - 0.25)) / 0.55)}%`, | |
| background: ACCENT_GRAD, | |
| boxShadow: `0 0 12px ${C.accentGlow}`, | |
| opacity: clamp01(1 - reveal) * (t > ENTER - 0.25 ? 1 : 0), | |
| }} | |
| /> | |
| {/* the DASHBOARD inside, wiped in by the light sweep */} | |
| <div | |
| style={{ | |
| position: "absolute", | |
| inset: 0, | |
| display: "grid", | |
| gridTemplateColumns: "150px 1fr", | |
| opacity: reveal, | |
| // a left→right reveal wipe synced to the load | |
| clipPath: `inset(0 ${(1 - reveal) * 100}% 0 0)`, | |
| }} | |
| > | |
| {/* sidebar */} | |
| <div | |
| style={{ | |
| background: withAlpha("#0a0e16", 0.9), | |
| borderRight: `1px solid ${C.glassBorder}`, | |
| padding: 18, | |
| display: "flex", | |
| flexDirection: "column", | |
| gap: 14, | |
| }} | |
| > | |
| <div | |
| style={{ | |
| fontFamily: FONT, | |
| fontWeight: 800, | |
| fontSize: 18, | |
| color: C.text, | |
| display: "flex", | |
| alignItems: "center", | |
| gap: 8, | |
| }} | |
| > | |
| <span | |
| style={{ | |
| width: 16, | |
| height: 16, | |
| borderRadius: 5, | |
| background: ACCENT_GRAD, | |
| boxShadow: `0 0 10px ${C.accentGlow}`, | |
| }} | |
| /> | |
| Dashboard | |
| </div> | |
| {[0, 1, 2, 3].map((i) => ( | |
| <div | |
| key={i} | |
| style={{ | |
| height: 9, | |
| width: `${[88, 70, 80, 58][i]}%`, | |
| borderRadius: 5, | |
| background: | |
| i === 0 | |
| ? withAlpha(C.accent2, 0.7) | |
| : withAlpha("#fff", 0.16), | |
| }} | |
| /> | |
| ))} | |
| </div> | |
| {/* main panel : KPI row + chart */} | |
| <div | |
| style={{ | |
| padding: 22, | |
| display: "flex", | |
| flexDirection: "column", | |
| gap: 18, | |
| }} | |
| > | |
| <div style={{ display: "flex", gap: 14 }}> | |
| {kpis.map((k, i) => ( | |
| <div | |
| key={i} | |
| style={{ | |
| flex: 1, | |
| borderRadius: 12, | |
| padding: "14px 16px", | |
| background: `linear-gradient(135deg, ${withAlpha( | |
| C.accent2, | |
| 0.16, | |
| )}, ${withAlpha("#0a0e16", 0.9)})`, | |
| border: `1px solid ${withAlpha(C.accent, 0.32)}`, | |
| }} | |
| > | |
| <div | |
| style={{ | |
| fontFamily: MONO, | |
| fontSize: 11, | |
| letterSpacing: 2, | |
| color: C.accent2, | |
| marginBottom: 6, | |
| }} | |
| > | |
| {k.label} | |
| </div> | |
| <div | |
| style={{ | |
| fontFamily: FONT, | |
| fontWeight: 800, | |
| fontSize: 30, | |
| lineHeight: 1, | |
| color: C.text, | |
| }} | |
| > | |
| {k.val} | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| {/* a tiny bar chart */} | |
| <div | |
| style={{ | |
| flex: 1, | |
| borderRadius: 12, | |
| background: withAlpha("#0a0e16", 0.7), | |
| border: `1px solid ${C.glassBorder}`, | |
| padding: 18, | |
| display: "flex", | |
| alignItems: "flex-end", | |
| gap: 14, | |
| }} | |
| > | |
| {bars.map((b, i) => { | |
| const grow = clamp01((reveal - i * 0.06) / 0.5); | |
| return ( | |
| <div | |
| key={i} | |
| style={{ | |
| flex: 1, | |
| height: `${b * 100 * grow}%`, | |
| borderRadius: "6px 6px 3px 3px", | |
| background: | |
| i === bars.length - 1 | |
| ? ACCENT_GRAD | |
| : withAlpha(C.accent, 0.45), | |
| boxShadow: | |
| i === bars.length - 1 | |
| ? `0 0 16px ${C.accentGlow}` | |
| : "none", | |
| }} | |
| /> | |
| ); | |
| })} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| {/* the cursor that glides over to the pill and pastes the link */} | |
| <div | |
| style={{ | |
| position: "absolute", | |
| left: mix(58, 30, cursorP) + "%", | |
| top: mix(70, 13.5, cursorP) + "%", | |
| width: 22, | |
| height: 22, | |
| opacity: clamp01(cursorP * 1.4) * clamp01(1 - reveal * 1.2), | |
| transform: `scale(${1 - 0.12 * pillFlash})`, | |
| pointerEvents: "none", | |
| filter: `drop-shadow(0 2px 4px ${withAlpha("#000", 0.6)})`, | |
| }} | |
| > | |
| <svg viewBox="0 0 24 24" width="22" height="22"> | |
| <path | |
| d="M3 2 L3 19 L8 14 L11 21 L14 20 L11 13 L18 13 Z" | |
| fill="#f4f1ea" | |
| stroke="#06080e" | |
| strokeWidth="1.2" | |
| /> | |
| </svg> | |
| </div> | |
| {/* the lock ring that snaps tight on the apex beat */} | |
| <div | |
| style={{ | |
| position: "absolute", | |
| inset: 10, | |
| borderRadius: 22, | |
| border: `2px solid ${withAlpha(C.accent, 0.3 + 0.45 * ringPulse)}`, | |
| opacity: lockRing, | |
| boxShadow: `0 0 30px ${withAlpha(C.accent, 0.3 * ringPulse)}`, | |
| pointerEvents: "none", | |
| }} | |
| /> | |
| </div> | |
| ); | |
| return ( | |
| <Plinth> | |
| <Eyebrow at={0.3}>Open The Dashboard</Eyebrow> | |
| {/* riser glow swelling behind the hero into the apex */} | |
| <AbsoluteFill style={{ pointerEvents: "none", zIndex: 1 }}> | |
| <GlowPulse | |
| size={1000} | |
| color={withAlpha(C.accent, 0.1 * riser)} | |
| strength={riser} | |
| /> | |
| </AbsoluteFill> | |
| {/* the ENTER → page-load light sweep, and the lock-in impact */} | |
| <AbsoluteFill style={{ pointerEvents: "none", zIndex: 6 }}> | |
| <LightSweep at={ENTER} dur={0.95} strength={0.18} /> | |
| <GlowPulse | |
| size={1200} | |
| color={withAlpha(C.accent, 0.2 * flash)} | |
| strength={flash} | |
| /> | |
| <Shockwave at={LOCK} size={820} /> | |
| <Shockwave at={LOCK + 0.08} size={1120} /> | |
| <LightSweep at={LOCK} dur={1.0} strength={0.14} /> | |
| </AbsoluteFill> | |
| <OrbitWorld legs={legs} perspective={2300} bobAmp={12}> | |
| <DustMotes layers={3} opacity={0.42} /> | |
| <Extrude w={820} h={520} depth={22} layers={16} radius={30}> | |
| {HeroFace} | |
| </Extrude> | |
| {/* billboarded spec callouts firing at orbit waypoints */} | |
| <Callout | |
| title="Your App" | |
| value="localhost" | |
| at={fps * (URLAT + 0.3)} | |
| x={470} | |
| y={-200} | |
| leader={140} | |
| side="right" | |
| /> | |
| <Callout | |
| title="Page Load" | |
| value="LIVE · INSTANT" | |
| at={fps * (ENTER + 0.4)} | |
| x={-490} | |
| y={60} | |
| leader={150} | |
| side="left" | |
| /> | |
| <Callout | |
| title="Status" | |
| value="READY TO START" | |
| at={fps * (LOCK + 0.3)} | |
| x={0} | |
| y={330} | |
| leader={120} | |
| side="right" | |
| /> | |
| </OrbitWorld> | |
| {/* flat masked mirror sibling — re-renders the hero, simplified & matte */} | |
| <Plinth.Reflection> | |
| <Extrude w={820} h={520} depth={22} layers={10} radius={30} sheen={false}> | |
| {HeroFace} | |
| </Extrude> | |
| </Plinth.Reflection> | |
| </Plinth> | |
| ); | |
| }; | |
| export default MgOrbitScene07LocalLink; |