Moeeldouma's picture
Deploy Eldouma Graphics — Docker Space, bring-your-own-key demo
39d98a0 verified
Raw
History Blame Contribute Delete
16.6 kB
// @ts-nocheck
// ============================================================================
// MOTION GRAPHICS · OBSIDIAN ORBIT — Scene 09 / DROP THE SCRIPT (11s, 330f)
//
// "Keynote object-worship". ONE hero artifact: the EPISODE-FOLDER slab — a thick
// glass slab whose FACE is an episode workspace (a folder header + an empty
// dropzone). A raw ".txt" script card DROPS onto its face from above and docks
// with a pop; a scan-line then SWEEPS across the text as the UI reads it,
// lighting each line in turn; a READY check pulses on once the read completes.
// The WORLD orbits (never the camera) in slow hold→ease arcs; spec Callouts
// billboard on drawn leader lines at waypoints ("DROP SCRIPT", "AUTO-READ");
// the angle-tracked sheen rakes the turn. A riser builds into the settle where
// the slab LOCKS straight-on with an impact + shockwave as the ready-check
// lands — the payoff — then idles, sheen tracking the final turn.
//
// Built ENTIRELY on the Plinth module (mirrors ObsidianOrbit.tsx'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>
);
};
/* ============================================================================
DROP THE SCRIPT. Hero = the EPISODE-FOLDER artifact. A raw .txt card drops
onto the slab face, a scan-line reads the text line-by-line, a ready-check
pulses on. The world orbits in, callouts fire, then the slab LOCKS front-on
with an impact as the read completes.
========================================================================== */
export const MgOrbitScene09DropScript: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const t = frame / fps;
const LOCK = 8.0; // the settle / payoff beat (seconds)
// --- face choreography -------------------------------------------------
const folderP = beat(frame, fps, 0.5, 1.6, EASE.out); // workspace fades in
const DROP = 2.4; // the .txt card docks onto the face (seconds)
const dropSpring = springAt(frame, fps, DROP, SPRING.SNAPPY); // card settle
const dropIn = clamp01((t - (DROP - 0.7)) / 0.7); // card travel/visibility
const dropY = mix(-360, 0, clamp01(dropSpring)); // falls from above to dock
const dropScale = mix(1.12, 1, clamp01(dropSpring)); // slight overshoot
// scan-line read: sweeps top→bottom across the docked card's text.
const SCAN_START = 3.3;
const SCAN_END = 6.0;
const scanP = beat(frame, fps, SCAN_START, SCAN_END, EASE.inOut); // 0→1 sweep
// ready-check: pulses on once the read finishes, lands hard on the lock.
const checkSpring = springAt(frame, fps, LOCK, SPRING.HEAVY); // weighty pop-in
const checkP = clamp01(checkSpring);
const checkPulse = 0.5 + 0.5 * osc(t, 2.2);
// --- the lock-in: a weighty spring settle on the payoff -----------------
const stamp = springAt(frame, fps, LOCK, SPRING.HEAVY); // 0→1 weighty settle
const stampScale = mix(1.1, 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 ringPulse = 0.5 + 0.5 * osc(t, 3);
// hold→ease orbit so the slab reads its face on the way in, then a final arc
// that settles to centre (0°) right at the lock — the snap-to-camera payoff.
const legs = [
{ arc: -18, hold: 0.6, travel: 2.6 },
{ arc: 26, hold: 1.2, travel: 2.8 },
{ arc: -8, hold: 0.5, travel: 1.8 }, // lands ~0° near LOCK
];
// the script card's text lines — each lights as the scan-line crosses it.
const scriptLines = [0.9, 0.66, 0.84, 0.5, 0.74, 0.58];
const HeroFace = (
<div
style={{
position: "absolute",
inset: 0,
padding: 36,
display: "flex",
flexDirection: "column",
gap: 18,
transform: `scale(${stampScale})`,
}}
>
{/* episode folder header — the workspace identity */}
<div
style={{
display: "flex",
alignItems: "center",
gap: 14,
opacity: folderP,
}}
>
{/* folder glyph */}
<div
style={{
position: "relative",
width: 44,
height: 34,
borderRadius: 6,
background: `linear-gradient(135deg, ${withAlpha(
C.accent2,
0.85,
)}, ${C.accentDeep})`,
boxShadow: `0 0 18px ${withAlpha(C.accent, 0.4)}`,
}}
>
<div
style={{
position: "absolute",
left: 4,
top: -6,
width: 20,
height: 10,
borderRadius: "5px 5px 0 0",
background: withAlpha(C.accent2, 0.85),
}}
/>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
<div
style={{
fontFamily: MONO,
fontSize: 12,
letterSpacing: 3,
textTransform: "uppercase",
color: C.textDim,
}}
>
Episode 09
</div>
<div
style={{
fontFamily: FONT,
fontWeight: 800,
fontSize: 22,
lineHeight: 1,
letterSpacing: "-0.01em",
color: C.text,
}}
>
Motion Graphics
</div>
</div>
</div>
{/* the dropzone — where the .txt card docks */}
<div
style={{
position: "relative",
flex: 1,
borderRadius: 16,
border: `1.5px dashed ${withAlpha(
C.accent,
mix(0.5, 0.18, clamp01(dropSpring)),
)}`,
background: withAlpha("#070a11", 0.5),
overflow: "hidden",
opacity: folderP,
}}
>
{/* idle dropzone hint — fades as the card arrives */}
<div
style={{
position: "absolute",
inset: 0,
display: "flex",
alignItems: "center",
justifyContent: "center",
fontFamily: MONO,
fontSize: 13,
letterSpacing: 4,
textTransform: "uppercase",
color: withAlpha(C.accent2, 0.6),
opacity: clamp01(1 - dropIn * 1.4),
}}
>
drop .txt here
</div>
{/* the raw .txt script card — falls in and docks */}
<div
style={{
position: "absolute",
inset: 16,
borderRadius: 12,
background: `linear-gradient(135deg, ${withAlpha(
"#0e1320",
0.96,
)}, ${withAlpha("#070a11", 0.96)})`,
border: `1px solid ${withAlpha(C.accent, 0.4)}`,
boxShadow: `0 18px 50px ${withAlpha("#000", 0.6)}, 0 0 24px ${withAlpha(
C.accent,
0.2 * dropIn,
)}`,
padding: 18,
display: "flex",
flexDirection: "column",
gap: 13,
opacity: dropIn,
transform: `translateY(${dropY.toFixed(1)}px) scale(${dropScale.toFixed(
3,
)})`,
}}
>
{/* card filename */}
<div
style={{
display: "flex",
alignItems: "center",
gap: 8,
fontFamily: MONO,
fontSize: 12,
letterSpacing: 2.5,
textTransform: "uppercase",
color: C.accent2,
}}
>
<span
style={{
width: 18,
height: 22,
borderRadius: 3,
border: `1px solid ${withAlpha(C.accent2, 0.6)}`,
display: "inline-block",
}}
/>
script.txt
</div>
{/* the text lines — each lights as the scan-line passes it */}
<div
style={{
position: "relative",
flex: 1,
display: "flex",
flexDirection: "column",
gap: 11,
justifyContent: "center",
}}
>
{scriptLines.map((w, i) => {
const lineFrac = (i + 0.5) / scriptLines.length;
const read = clamp01((scanP - lineFrac) * 6 + 1); // lit once passed
return (
<div
key={i}
style={{
height: 9,
width: `${w * 100}%`,
borderRadius: 5,
background:
read > 0.01
? `linear-gradient(90deg, ${withAlpha(
C.accent2,
mix(0.2, 0.85, read),
)}, ${withAlpha("#ffffff", mix(0.1, 0.35, read))})`
: withAlpha("#ffffff", 0.18),
boxShadow:
read > 0.4
? `0 0 12px ${withAlpha(C.accent, 0.4 * read)}`
: "none",
}}
/>
);
})}
{/* the scan-line sweeping down the text as the UI reads it */}
<div
style={{
position: "absolute",
left: -6,
right: -6,
top: `${(scanP * 100).toFixed(1)}%`,
height: 2,
transform: "translateY(-1px)",
background: `linear-gradient(90deg, transparent, ${C.accent2}, transparent)`,
boxShadow: `0 0 16px ${C.accentGlow}`,
opacity:
scanP > 0.001 && scanP < 0.999
? 1
: clamp01((t - SCAN_START) / 0.2) *
clamp01((SCAN_END + 0.15 - t) / 0.2),
}}
/>
</div>
{/* read-progress bar at the card's foot */}
<div
style={{
height: 4,
borderRadius: 2,
background: withAlpha("#ffffff", 0.08),
overflow: "hidden",
}}
>
<div
style={{
height: "100%",
width: `${(scanP * 100).toFixed(1)}%`,
background: ACCENT_GRAD,
boxShadow: `0 0 10px ${C.accentGlow}`,
}}
/>
</div>
</div>
{/* the READY check — pulses on once the read completes */}
<div
style={{
position: "absolute",
right: 16,
bottom: 16,
display: "flex",
alignItems: "center",
gap: 10,
padding: "8px 14px 8px 10px",
borderRadius: 999,
background: withAlpha("#070a11", 0.85),
border: `1px solid ${withAlpha(
C.accent,
0.4 + 0.4 * checkPulse,
)}`,
boxShadow: `0 0 ${(18 + 14 * checkPulse).toFixed(
0,
)}px ${withAlpha(C.accent, 0.35 * checkP * checkPulse)}`,
opacity: checkP,
transform: `scale(${mix(0.7, 1, checkP)})`,
}}
>
<div
style={{
width: 26,
height: 26,
borderRadius: "50%",
background: ACCENT_GRAD,
display: "flex",
alignItems: "center",
justifyContent: "center",
boxShadow: `inset 0 0 10px ${withAlpha("#ffffff", 0.4)}`,
}}
>
{/* check mark */}
<svg width="15" height="15" viewBox="0 0 15 15">
<path
d="M3 8 L6.2 11 L12 4"
fill="none"
stroke="#1a0d03"
strokeWidth="2.4"
strokeLinecap="round"
strokeLinejoin="round"
style={{
strokeDasharray: 20,
strokeDashoffset: mix(20, 0, checkP),
}}
/>
</svg>
</div>
<span
style={{
fontFamily: MONO,
fontSize: 12,
letterSpacing: 3,
textTransform: "uppercase",
color: C.text,
}}
>
Ready
</span>
</div>
</div>
{/* the lock ring that snaps tight on the payoff beat */}
<div
style={{
position: "absolute",
inset: 18,
borderRadius: 26,
border: `2px solid ${withAlpha(C.accent, 0.28 + 0.42 * ringPulse)}`,
opacity: clamp01(stamp),
boxShadow: `0 0 30px ${withAlpha(C.accent, 0.3 * ringPulse)}`,
pointerEvents: "none",
}}
/>
</div>
);
return (
<Plinth>
<Eyebrow at={0.3}>Drop The Script</Eyebrow>
{/* riser glow swelling behind the hero into the payoff */}
<AbsoluteFill style={{ pointerEvents: "none", zIndex: 1 }}>
<GlowPulse
size={1000}
color={withAlpha(C.accent, 0.1 * riser)}
strength={riser}
/>
</AbsoluteFill>
{/* impact flash + shockwave on the ready/lock payoff */}
<AbsoluteFill style={{ pointerEvents: "none", zIndex: 6 }}>
<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.16} />
</AbsoluteFill>
<OrbitWorld legs={legs} perspective={2300} bobAmp={12}>
<DustMotes layers={3} opacity={0.42} />
<Extrude w={720} h={460} depth={22} layers={16} radius={28}>
{HeroFace}
</Extrude>
{/* billboarded spec callouts firing at orbit waypoints */}
<Callout
title="The Input"
value="DROP SCRIPT"
at={fps * (DROP + 0.2)}
x={0}
y={-310}
leader={120}
side="right"
/>
<Callout
title="The Engine"
value="AUTO-READ"
at={fps * (SCAN_START + 0.6)}
x={460}
y={120}
leader={150}
side="right"
/>
<Callout
title="The Output"
value="READY"
at={fps * (LOCK + 0.3)}
x={-470}
y={140}
leader={160}
side="left"
/>
</OrbitWorld>
{/* flat masked mirror sibling — re-renders the hero, simplified & matte */}
<Plinth.Reflection>
<Extrude w={720} h={460} depth={22} layers={10} radius={28} sheen={false}>
{HeroFace}
</Extrude>
</Plinth.Reflection>
</Plinth>
);
};
export default MgOrbitScene09DropScript;