// 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 */}
);
}
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 */}
);
}
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
{/* 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 */}
{/* Tagline */}
Tu agente de IA que llama por ti para cobrar.
{/* CTA */}
);
}
Object.assign(window, {
CheckBurst, Counter, RecoveryChart, SceneResult, SceneFinal,
});