// KarlaPay — Scenes // Brand: #FF6A1A orange, #0D0F14 bg, Satoshi + Caveat // Arc (30s): Logo build → Problem → Carla (orb/waveform) → Result → Tagline/CTA const BG = '#0D0F14'; const ORANGE = '#FF6A1A'; const INK = '#FFFFFF'; const MUTED = '#6B7280'; const PANEL = '#14171F'; const LINE = '#2A2F3A'; const SATOSHI = '"Satoshi", "Inter", system-ui, sans-serif'; const CAVEAT = '"Caveat", "Brush Script MT", cursive'; const MONO = '"JetBrains Mono", ui-monospace, monospace'; // ───────────────────────────────────────────────────────────────────────────── // Ambient background — subtle radial orange glow + grid function AmbientBG() { const t = useTime(); const pulse = 0.7 + 0.3 * Math.sin(t * 0.8); return (
{/* Orange glow */}
{/* Faint grid */}
); } // ───────────────────────────────────────────────────────────────────────────── // SCENE 1 — Logo build (0.0 → 5.0s) // "Karla" writes on in Caveat, then "pay" joins with a fade, tagline follows. function SceneLogo() { const { localTime, progress } = useSprite(); // Handwriting reveal: clip-path sweeps left→right over Caveat "Karla" const writeDur = 1.9; const writeT = clamp(localTime / writeDur, 0, 1); const writeEased = Easing.easeInOutCubic(writeT); // "pay" appears at 1.8s const payStart = 1.9; const payT = clamp((localTime - payStart) / 0.6, 0, 1); const payEased = Easing.easeOutCubic(payT); // Tagline at 2.7s const tagStart = 2.7; const tagT = clamp((localTime - tagStart) / 0.7, 0, 1); const tagEased = Easing.easeOutCubic(tagT); // Exit at end const exitStart = 4.3; const exitT = clamp((localTime - exitStart) / 0.7, 0, 1); const exitEased = Easing.easeInCubic(exitT); const exitOpacity = 1 - exitT; const exitScale = 1 - exitEased * 0.04; return (
{/* Wordmark */}
{/* "Karla" in Caveat — clipped reveal */}
Karla
{/* "pay" in Satoshi */}
pay
{/* Tagline */}
Tu agente de IA que llama por ti para cobrar.
); } // ───────────────────────────────────────────────────────────────────────────── // SCENE 2 — Problem (5.0 → 10.5s) // Pile of "IMPAGO" (unpaid) invoice cards fall onto screen, red warning accent. function InvoiceCard({ delay, x, y, rot, amount, client, status = 'IMPAGO' }) { const { localTime } = useSprite(); const t = clamp((localTime - delay) / 0.5, 0, 1); const eased = Easing.easeOutCubic(t); const opacity = t; const dy = (1 - eased) * -40; const scale = 0.9 + eased * 0.1; const isOverdue = status === 'IMPAGO'; return (
FAC-{Math.floor(1000 + Math.random() * 9000)}
{status}
{client}
€ {amount}
); } function SceneProblem() { const { localTime, duration } = useSprite(); // Title in first const titleT = clamp(localTime / 0.6, 0, 1); const titleEased = Easing.easeOutCubic(titleT); // Exit const exitStart = duration - 0.7; const exitT = clamp((localTime - exitStart) / 0.7, 0, 1); const exitOpacity = 1 - Easing.easeInCubic(exitT); const cards = [ { delay: 0.6, x: 180, y: 220, rot: -8, amount: '1.250', client: 'Clínica Dental Sonríe' }, { delay: 0.85, x: 500, y: 180, rot: 3, amount: '840', client: 'Autoescuela Velocidad' }, { delay: 1.1, x: 850, y: 240, rot: -4, amount: '2.100', client: 'Gimnasio Fuerza' }, { delay: 1.35, x: 1200, y: 200, rot: 6, amount: '560', client: 'Peluquería Bella' }, { delay: 1.6, x: 320, y: 450, rot: 5, amount: '1.780', client: 'Academia Idiomas' }, { delay: 1.85, x: 680, y: 490, rot: -6, amount: '3.400', client: 'Consultoría Nova' }, { delay: 2.1, x: 1040, y: 470, rot: 2, amount: '920', client: 'Restaurante Mar' }, ]; return (
{/* Top label */}
EL PROBLEMA
Las facturas no se pagan solas.
{cards.map((c, i) => )} {/* Counter at bottom */}
); } function SceneProblemCounter({ localTime }) { const t = clamp((localTime - 2.3) / 1.4, 0, 1); const eased = Easing.easeOutCubic(t); const value = Math.floor(eased * 10850); const formatted = value.toLocaleString('es-ES'); const appearT = clamp((localTime - 2.3) / 0.5, 0, 1); return (
IMPAGADO ESTE MES
€ {formatted}
); } Object.assign(window, { BG, ORANGE, INK, MUTED, PANEL, LINE, SATOSHI, CAVEAT, MONO, AmbientBG, SceneLogo, SceneProblem, });