// KarlaPay — Scenes part 3: Result + final lockup // ───────────────────────────────────────────────────────────────────────────── // SCENE 4 — Result (19.0 → 25.0s) // "PAGADO" check ripples out, euro counter tickers up, line chart draws in. function CheckBurst({ localTime }) { const popT = clamp(localTime / 0.5, 0, 1); const popEased = Easing.easeOutBack(popT); const scale = popEased; const rippleT = clamp((localTime - 0.3) / 1.4, 0, 1); const rippleSize = 120 + rippleT * 520; const rippleOpacity = (1 - rippleT) * 0.6; return (
{/* Ripple */}
{/* Circle */}
{/* Check draw */}
); } function Counter({ localTime, delay, duration, from, to, prefix = '', suffix = '', size = 120, weight = 600 }) { const t = clamp((localTime - delay) / duration, 0, 1); const eased = Easing.easeOutCubic(t); const value = from + (to - from) * eased; const formatted = Math.floor(value).toLocaleString('es-ES'); return (
{prefix}{formatted}{suffix}
); } function RecoveryChart({ localTime }) { // Draw a line chart that climbs const drawT = clamp((localTime - 1.2) / 2.2, 0, 1); const drawEased = Easing.easeInOutCubic(drawT); // Points (normalized) const pts = [ [0, 0.85], [0.12, 0.78], [0.22, 0.82], [0.35, 0.68], [0.45, 0.62], [0.55, 0.50], [0.65, 0.42], [0.75, 0.28], [0.85, 0.22], [1.0, 0.08], ]; const W = 460, H = 180; const path = pts.map(([x, y], i) => { const cmd = i === 0 ? 'M' : 'L'; return `${cmd} ${x * W} ${y * H}`; }).join(' '); const totalLen = 600; // approx return (
{/* Y labels */}
€ 12K € 6K € 0
{/* Grid */} {[0, 0.25, 0.5, 0.75, 1].map((p, i) => ( ))} {/* Line */} {/* End dot */} {drawT > 0.95 && ( )}
); } function SceneResult() { const { localTime, duration } = useSprite(); // Label in const labelT = clamp(localTime / 0.5, 0, 1); const labelEased = Easing.easeOutCubic(labelT); // Check const checkStart = 0.2; // Counter const counterStart = 0.6; // Chart const chartStart = 1.0; const exitStart = duration - 0.7; const exitT = clamp((localTime - exitStart) / 0.7, 0, 1); const exitOpacity = 1 - Easing.easeInCubic(exitT); return (
{/* Label */}
EL RESULTADO
Más cobros. Menos esfuerzo.
{/* Left: Big counter + check */}
{localTime >= checkStart && ( )}
Recuperado este mes
por Carla
+18,6% vs. mes anterior
{/* Right: Chart card */}
IMPAGO RESTANTE
De € 12K a casi cero
{localTime >= chartStart && ( )}
); } // ───────────────────────────────────────────────────────────────────────────── // SCENE 5 — Final lockup (25.0 → 30.0s) function SceneFinal() { const { localTime, duration } = useSprite(); // Logo reassembles const t1 = clamp(localTime / 0.8, 0, 1); const e1 = Easing.easeOutCubic(t1); const t2 = clamp((localTime - 0.6) / 0.6, 0, 1); const e2 = Easing.easeOutCubic(t2); const t3 = clamp((localTime - 1.1) / 0.6, 0, 1); const e3 = Easing.easeOutCubic(t3); const t4 = clamp((localTime - 1.8) / 0.5, 0, 1); const e4 = Easing.easeOutBack(t4); return (
{/* Wordmark */}
Karla
pay
{/* Tagline */}
Tu agente de IA que llama por ti para cobrar.
{/* CTA */}
Solicita una demo
karlapay.com
); } Object.assign(window, { CheckBurst, Counter, RecoveryChart, SceneResult, SceneFinal, });