// pesito — shared visual atoms (logo, icons, brand mark) const PesitoMark = ({ size = 28, color }) => ( p. ); const Wordmark = ({ color }) => (
pesito
); // Tiny iconset (1.5px hairlines, iOS feel) const I = { arrow: (p = {}) => , arrowDown: (p = {}) => , check: (p = {}) => , shield: (p = {}) => , bolt: (p = {}) => , doc: (p = {}) => , plus: (p = {}) => , minus: (p = {}) => , clock: (p = {}) => , spei: (p = {}) => , menu: (p = {}) => , close: (p = {}) => , user: (p = {}) => , bank: (p = {}) => , sparkle: (p = {}) => , ineUp: (p = {}) => , }; // Format MX currency const fmtMX = (n) => '$' + (Math.round(n)).toLocaleString('en-US') + ' MXN'; const fmtMXshort = (n) => '$' + (Math.round(n)).toLocaleString('en-US'); // Animated rolling number const Rolling = ({ value, format = (v) => v, prefix = '', suffix = '' }) => { const [display, setDisplay] = React.useState(value); const ref = React.useRef(value); React.useEffect(() => { const start = ref.current; const end = value; if (start === end) return; const t0 = performance.now(); const duration = 280; let raf; const step = (t) => { const e = Math.min(1, (t - t0) / duration); const eased = 1 - Math.pow(1 - e, 3); setDisplay(start + (end - start) * eased); if (e < 1) raf = requestAnimationFrame(step); else ref.current = end; }; raf = requestAnimationFrame(step); return () => cancelAnimationFrame(raf); }, [value]); return {prefix}{format(display)}{suffix}; }; Object.assign(window, { PesitoMark, Wordmark, I, fmtMX, fmtMXshort, Rolling, });