Moeeldouma's picture
Deploy Eldouma Graphics — Docker Space, bring-your-own-key demo
39d98a0 verified
Raw
History Blame Contribute Delete
17.7 kB
// @ts-nocheck
// ============================================================================
// MOTION GRAPHICS · OBSIDIAN ORBIT — Scene 10 / COPY DRAFT PROMPT (10s, 300f)
//
// "Keynote object-worship". ONE hero artifact: a glass slab whose face is the
// "Copy Draft Prompt" panel. A solid monolithic script block sits on the face
// under a primary CTA button. On the CLICK beat the button depresses, a prompt
// token flies off + a clipboard pulse rings out ("Copied"), and the solid
// script block FRACTURES — splitting along seams into a clean row of FOUR
// numbered scene cards. The breakdown made literal: one block of intent →
// discrete, ordered scenes. The WORLD orbits (never the camera) in slow
// hold→ease arcs; billboarded spec Callouts fire on leader lines ("STEP 1",
// "COPY DRAFT PROMPT", "4 SCENES"); the angle-tracked sheen rakes the turn; the
// slab settles front-on for the payoff with an impact + shockwave as the cards
// lock into their row.
//
// 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>
);
};
/* ============================================================================
COPY DRAFT PROMPT. Hero = the "Copy Draft Prompt" slab. A solid script block
under a primary CTA. On the CLICK the button depresses, a prompt token copies
(clipboard pulse), and the block fractures into a row of 4 numbered scene
cards — the breakdown made literal. World orbits, callouts fire, slab settles.
========================================================================== */
export const MgOrbitScene10CopyPrompt: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const t = frame / fps;
const CLICK = 4.6; // the click beat (seconds) — button press + copy
const LOCK = 7.8; // the apex lock-in beat — cards settle into their row
// --- face choreography -------------------------------------------------
const blockIn = beat(frame, fps, 0.8, 2.0, EASE.out); // solid script block lands
const btnIn = beat(frame, fps, 1.8, 2.8, EASE.backOut); // CTA button arrives
const btnHint = 0.5 + 0.5 * osc(t, 1.4); // gentle pre-click pulse
const press = beat(frame, fps, CLICK, CLICK + 0.18, EASE.out); // button depress
const release = beat(frame, fps, CLICK + 0.18, CLICK + 0.4, EASE.out);
const btnPress = press - release; // 0→1→0 quick depress
// clipboard "copied" pulse ring + token fly
const copyP = beat(frame, fps, CLICK, CLICK + 0.6, EASE.out);
const copyLife = clamp01(1 - (t - CLICK) / 1.2) * (t >= CLICK ? 1 : 0);
const tokenP = beat(frame, fps, CLICK + 0.02, CLICK + 0.55, EASE.expoOut);
// the FRACTURE: the solid block splits into the 4-card row after the click.
const fractureP = beat(frame, fps, CLICK + 0.18, CLICK + 1.6, EASE.expoOut);
// --- 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.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 lockRing = clamp01(stamp);
const ringPulse = 0.5 + 0.5 * osc(t, 3);
// hold→ease orbit: reads the face on the way in, a turn through the fracture,
// then a final arc that settles to centre (0°) right at the lock — the payoff.
const legs = [
{ arc: -18, hold: 0.6, travel: 2.2 },
{ arc: 24, hold: 1.0, travel: 2.4 },
{ arc: -6, hold: 0.5, travel: 1.7 }, // lands ~0° near LOCK
];
const scriptLines = [0.9, 0.72, 0.86, 0.64, 0.8];
// the four scene cards the block fractures into. seam = where the block was
// cut; offset = how far each shard slides out into its slot in the row.
const cards = [
{ n: 1, label: "INTRO" },
{ n: 2, label: "PROBLEM" },
{ n: 3, label: "DEMO" },
{ n: 4, label: "OUTRO" },
];
const HeroFace = (
<div
style={{
position: "absolute",
inset: 0,
padding: 36,
display: "flex",
flexDirection: "column",
gap: 22,
transform: `scale(${stampScale})`,
}}
>
{/* panel title bar */}
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
opacity: blockIn,
}}
>
<div
style={{
fontFamily: MONO,
fontSize: 13,
letterSpacing: 4,
color: C.textDim,
textTransform: "uppercase",
}}
>
draft-prompt.txt
</div>
<div
style={{
fontFamily: MONO,
fontSize: 12,
letterSpacing: 3,
color: C.accent2,
textTransform: "uppercase",
}}
>
{fractureP > 0.5 ? "4 SCENES" : "1 BLOCK"}
</div>
</div>
{/* the body region — holds the solid block, which fractures into cards */}
<div style={{ position: "relative", flex: 1 }}>
{/* SOLID SCRIPT BLOCK — one monolith of intent. Fades/contracts as it
fractures so the row of cards takes its place. */}
<div
style={{
position: "absolute",
inset: 0,
borderRadius: 16,
padding: 22,
background: `linear-gradient(135deg, ${withAlpha(
"#0c1018",
0.92,
)}, ${withAlpha("#070a11", 0.92)})`,
border: `1px solid ${C.glassBorder}`,
display: "flex",
flexDirection: "column",
gap: 14,
justifyContent: "center",
opacity: blockIn * clamp01(1 - fractureP * 1.6),
transform: `scale(${mix(1, 0.96, fractureP)})`,
boxShadow: `inset 0 0 50px ${withAlpha("#000", 0.4)}`,
}}
>
{scriptLines.map((w, i) => {
const lp = clamp01((blockIn - i * 0.1) / 0.6);
return (
<div
key={i}
style={{
height: 11,
width: `${w * 100 * lp}%`,
borderRadius: 6,
background:
i === 0
? withAlpha(C.accent2, 0.6)
: withAlpha("#ffffff", 0.18),
}}
/>
);
})}
</div>
{/* the FRACTURED ROW — 4 numbered scene cards split out of the block. */}
<div
style={{
position: "absolute",
inset: 0,
display: "grid",
gridTemplateColumns: "repeat(4, 1fr)",
gap: 14,
opacity: clamp01(fractureP * 1.4),
}}
>
{cards.map((card, i) => {
// each shard staggers out, sliding from the block centre to its slot
// and dropping its fracture seam — reads as a clean split.
const cp = clamp01((fractureP - i * 0.1) / 0.6);
const fromCenter = (i - 1.5) * 24; // pull toward centre pre-split
return (
<div
key={card.n}
style={{
borderRadius: 14,
padding: 16,
background: `linear-gradient(160deg, ${withAlpha(
C.accent2,
0.16,
)}, ${withAlpha("#0a0e16", 0.92)})`,
border: `1px solid ${withAlpha(C.accent, 0.45)}`,
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
opacity: cp,
transform: `translateX(${(1 - cp) * -fromCenter}px) translateY(${
(1 - cp) * 14
}px) scale(${mix(0.86, 1, cp)})`,
boxShadow: `0 8px 26px ${withAlpha("#000", 0.5)}, 0 0 ${(
16 * cp
).toFixed(0)}px ${withAlpha(C.accent, 0.2 * cp)}`,
}}
>
{/* numbered index — the ordered breakdown */}
<div
style={{
fontFamily: FONT,
fontWeight: 800,
fontSize: 40,
lineHeight: 0.9,
letterSpacing: "-0.03em",
background: ACCENT_GRAD,
WebkitBackgroundClip: "text",
backgroundClip: "text",
color: "transparent",
filter: `drop-shadow(0 0 12px ${withAlpha(C.accent, 0.4)})`,
}}
>
{card.n}
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
<div
style={{
height: 6,
width: "78%",
borderRadius: 3,
background: withAlpha("#ffffff", 0.22),
}}
/>
<div
style={{
height: 6,
width: "54%",
borderRadius: 3,
background: withAlpha("#ffffff", 0.14),
}}
/>
<div
style={{
fontFamily: MONO,
fontSize: 11,
letterSpacing: 2.5,
color: C.accent2,
textTransform: "uppercase",
marginTop: 4,
}}
>
{card.label}
</div>
</div>
</div>
);
})}
</div>
</div>
{/* PRIMARY CTA — "Copy Draft Prompt". Depresses on the click beat; a
prompt token flies off + a clipboard pulse rings out. */}
<div
style={{
position: "relative",
display: "flex",
alignItems: "center",
justifyContent: "center",
opacity: btnIn,
}}
>
<div
style={{
position: "relative",
display: "flex",
alignItems: "center",
gap: 14,
padding: "18px 34px",
borderRadius: 16,
background: ACCENT_GRAD,
boxShadow: `0 ${(10 - btnPress * 8).toFixed(
0,
)}px 30px ${withAlpha(C.accent, 0.45)}, inset 0 1px 0 ${withAlpha(
"#ffffff",
0.4,
)}, 0 0 ${(30 + 26 * btnHint * (1 - clamp01(t - CLICK))).toFixed(
0,
)}px ${withAlpha(C.accent, 0.3 + 0.25 * btnHint * (t < CLICK ? 1 : 0))}`,
transform: `translateY(${(btnPress * 4).toFixed(
1,
)}px) scale(${mix(1, 0.97, btnPress)})`,
}}
>
{/* clipboard glyph */}
<div
style={{
width: 22,
height: 26,
borderRadius: 5,
border: `2.5px solid #1a0d03`,
position: "relative",
flexShrink: 0,
}}
>
<div
style={{
position: "absolute",
top: -5,
left: "50%",
transform: "translateX(-50%)",
width: 12,
height: 6,
borderRadius: 3,
background: "#1a0d03",
}}
/>
</div>
<div
style={{
fontFamily: FONT,
fontWeight: 800,
fontSize: 27,
letterSpacing: "-0.01em",
color: "#1a0d03",
}}
>
{copyP > 0.4 && copyLife > 0.05 ? "Copied!" : "Copy Draft Prompt"}
</div>
</div>
{/* clipboard pulse ring radiating from the button on copy */}
<div
style={{
position: "absolute",
left: "50%",
top: "50%",
width: 120,
height: 120,
marginLeft: -60,
marginTop: -60,
borderRadius: "50%",
border: `2px solid ${withAlpha(C.accent2, 0.7 * copyLife)}`,
transform: `scale(${mix(0.4, 3.2, copyP)})`,
opacity: copyLife * (1 - copyP * 0.4),
pointerEvents: "none",
}}
/>
{/* the prompt token copying out — a small chip flying up to the clipboard */}
<div
style={{
position: "absolute",
left: "50%",
top: "50%",
transform: `translate(-50%, -50%) translateY(${(
-tokenP * 70
).toFixed(0)}px) scale(${mix(0.6, 1, tokenP)})`,
padding: "5px 12px",
borderRadius: 8,
background: withAlpha("#0a0e16", 0.95),
border: `1px solid ${withAlpha(C.accent, 0.6)}`,
fontFamily: MONO,
fontSize: 12,
letterSpacing: 2,
color: C.accent2,
opacity: copyLife,
boxShadow: `0 0 18px ${withAlpha(C.accent, 0.4)}`,
pointerEvents: "none",
whiteSpace: "nowrap",
}}
>
PROMPT
</div>
</div>
{/* the lock ring that snaps tight on the apex beat */}
<div
style={{
position: "absolute",
inset: 18,
borderRadius: 26,
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}>Copy Draft Prompt</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>
{/* click flash + apex impact / shockwave */}
<AbsoluteFill style={{ pointerEvents: "none", zIndex: 6 }}>
<GlowPulse
size={900}
color={withAlpha(C.accent2, 0.16 * copyLife)}
strength={copyLife}
/>
<GlowPulse
size={1200}
color={withAlpha(C.accent, 0.2 * flash)}
strength={flash}
/>
<Shockwave at={CLICK} size={620} />
<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={820} h={520} depth={22} layers={16} radius={28}>
{HeroFace}
</Extrude>
{/* billboarded spec callouts firing at orbit waypoints */}
<Callout
title="The Step"
value="STEP 1"
at={fps * 2.2}
x={0}
y={-330}
leader={120}
side="right"
/>
<Callout
title="The Action"
value="COPY DRAFT PROMPT"
at={fps * (CLICK + 0.2)}
x={480}
y={150}
leader={150}
side="right"
/>
<Callout
title="The Breakdown"
value="4 SCENES"
at={fps * (LOCK + 0.3)}
x={-490}
y={140}
leader={160}
side="left"
/>
</OrbitWorld>
{/* flat masked mirror sibling — re-renders the hero, simplified & matte */}
<Plinth.Reflection>
<Extrude w={820} h={520} depth={22} layers={10} radius={28} sheen={false}>
{HeroFace}
</Extrude>
</Plinth.Reflection>
</Plinth>
);
};
export default MgOrbitScene10CopyPrompt;