// neon-frame-forerun v3 — additions on top of v2 per user feedback (five clickup04 screens): // each component/text inside the frame initially hovers above the page (lifted in 3D), casting a soft // same-shaped shadow on the panel while hovering, and they snap down in sync with the page // lighting-up sequence (FloatWrap pattern, matching screenshot ③: tab/components hovering with // offset shadows → ④ all snapped down). Already in v2: the strongly-perspective right-angle frame // runs from the midpoint of its left edge in both directions, the panel brightens in place, and the // background neon-tube frame cluster glows in the middle then dies out at the end. import React, { useId } from 'react'; import { AbsoluteFill, useCurrentFrame, interpolate, Easing } from 'remotion'; const easeFall = Easing.bezier(0.5, 0.05, 0.6, 1); // accelerating fall, soft landing at the end /* hover + same-shaped soft shadow: h=hover height(px). The body lifts up-left, leaving a blurred, darkened * same-shaped shadow in place; when h→0 they coincide and the shadow disappears (see batch 11 GrazeFaceTour FloatWrap) */ const FloatWrap: React.FC<{ h: number; children: React.ReactNode }> = ({ h, children }) => (
{h > 1 && (
{children}
)}
{children}
); /* land=snap-down completion moment (0..1), before that it accelerates down from height H */ const liftOf = (t: number, land: number, H: number) => { const FALL = 0.3; const p = Math.min(1, Math.max(0, (t - (land - FALL)) / FALL)); return (1 - easeFall(p)) * H; }; const mulberry32 = (a: number) => () => { let t = (a += 0x6d2b79f5); t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; const ink = '#3c3c3a'; const mid = '#9a9a98'; const line = '#e3e3e1'; const PW = 1330; const PH = 900; const PL = 1000; // normalized path length // right-angle rect path: starts from the midpoint of the left edge (matches screenshot ① left edge lighting first) const FRAME_D = `M 0 ${PH / 2} L 0 0 L ${PW} 0 L ${PW} ${PH} L 0 ${PH} Z`; const Chip: React.FC<{ w: number }> = ({ w }) => (
); /* t = snap-down progress (0..1). Components snap down from the air in page-display order * (sidebar top to bottom, main area top to bottom), staggered, casting same-shaped soft shadows * while hovering (matches screenshot ③ ghost → ④⑤ snapped down) */ const GrayHome: React.FC<{ t?: number }> = ({ t = 1 }) => { const L = (land: number, H = 72) => liftOf(t, land, H * 1.7); return (
{[76, 56, 96, 110, 66, 60].map((w, i) => (
))}
{[104, 126, 96, 118, 88].map((w, i) => (
))}
{[0, 1, 2, 3, 4, 5, 6].map((i) => ( ))}
{[54, 84, 50, 82].map((w, i) => (
))}
{[0, 1, 2, 3].map((i) => (
{[0, 1, 2].map((k) =>
)}
))}
); }; // background neon-tube frames: large, bright, scattered with perspective (screenshots ③④) type BgFrame = { x: number; y: number; w: number; h: number; hue: string; phase: number; period: number; skew: number }; const rng = mulberry32(20260718); const HUES = ['#b06af0', '#e879c9', '#f0a35c', '#6a7df0', '#e0679a', '#8a5cf0', '#c06af0']; const BG_FRAMES: BgFrame[] = Array.from({ length: 18 }).map(() => ({ x: rng() * 2000 - 120, y: rng() * 1100 - 60, w: 160 + rng() * 480, h: 70 + rng() * 220, hue: HUES[Math.floor(rng() * HUES.length)], phase: rng() * 90, period: 55 + rng() * 70, skew: -14 + rng() * 10, })); export const NeonFrameForerun: React.FC = () => { const frame = useCurrentFrame(); // filter/gradient IDs generated per instance so multiple instances in one scene don't cross-reference (useId's «:» is invalid in url(), so it's sanitized) const uid = useId().replace(/[^a-zA-Z0-9]/g, ''); // main frame trace: runs both ways from the midpoint of the left edge, taking shape over 26 frames (screenshot ①→②) const trace = interpolate(frame, [2, 28], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.bezier(0.3, 0.1, 0.3, 1), }); // panel develops in place: after the frame forms, content goes from near-black to dark gray (screenshot ②), then to full bright (screenshot ③) const lit = interpolate(frame, [24, 46, 78], [0.0, 0.3, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.bezier(0.35, 0, 0.3, 1), }); // main frame's standalone stroke visibility: after the panel lights up it merges into the panel rim glow (after screenshot ③ the thin line fades out, the blurry glow remains) const frameLine = interpolate(frame, [50, 90], [1, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const rimGlow = interpolate(frame, [28, 60, 108, 132], [0.9, 1, 0.75, 0.5], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); // background: fully lit in the middle (screenshots ③④) → dies out at the end (screenshot ⑤) const bgLit = interpolate(frame, [8, 44, 96, 128], [0.15, 1, 0.85, 0.06], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); // strong perspective → relaxed: steep angles while the frame flies in, settling after the panel lights up (screenshot ① trapezoid → ③④ gentle tilt) const settle = interpolate(frame, [0, 70], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.out(Easing.cubic), }); const rotY = -26 + 15 * settle; const rotX = 7 - 3 * settle; const rotZ = -9 + 4.5 * settle; const scale = 0.94 + 0.1 * settle; const headP = trace * (PL / 2); // component snap-down progress: advances in sync with the page lighting (lit 24→78), finishing slightly later — // "snap-down completes in sync with the page's reveal" const drop = interpolate(frame, [34, 98], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return ( {/* background neon-tube frame cluster */} {BG_FRAMES.map((b, i) => { const breath = 0.5 + 0.5 * Math.sin(((frame + b.phase) / b.period) * Math.PI * 2); const op = bgLit * (0.18 + 0.4 * breath); return ( ); })} {/* main body: strongly-perspective tilted frame + panel */}
{/* panel: brightens in place from dark (no movement or scaling) */}
0.55 ? 1 : 0, filter: `brightness(${Math.max(0.05, lit)})` }}> {/* cool-toned darkening overlay while unlit */}
{/* panel rim glow (takes over once the frame light merges in, strongest at the bottom edge — matches the pink light on the bottom/right edges of screenshots ③④) */}
{/* neon stroked frame: runs both ways from the midpoint of the left edge, right-angle corners */} {[1, -1].map((dir) => ( {/* blurry glow layer: kept throughout */} {/* bright-core thin line: fades out and merges into the rim once the panel lights up */} {/* running bright head */} {trace < 1 && ( )} ))}
); };