// Blueprint visual primitives: hooks, ticks, labels, animated underline, etc. const useReveal = (options = {}) => { const ref = React.useRef(null); const [inView, setInView] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; const obs = new IntersectionObserver( ([e]) => { if (e.isIntersecting) { setInView(true); obs.disconnect(); } }, { threshold: options.threshold ?? 0.15, rootMargin: options.rootMargin ?? '0px 0px -10% 0px' } ); obs.observe(el); return () => obs.disconnect(); }, []); return [ref, inView]; }; const useScrollProgress = (ref) => { const [p, setP] = React.useState(0); React.useEffect(() => { const onScroll = () => { const el = ref.current; if (!el) return; const rect = el.getBoundingClientRect(); const vh = window.innerHeight; const total = rect.height + vh; const passed = vh - rect.top; const pr = Math.max(0, Math.min(1, passed / total)); setP(pr); }; onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); return p; }; // Animated number that counts up when in view const Counter = ({ to, duration = 2000, decimals = 0, prefix = '', suffix = '', className = '' }) => { const [ref, inView] = useReveal({ threshold: 0.4 }); const [val, setVal] = React.useState(0); React.useEffect(() => { if (!inView) return; let start; const step = (ts) => { if (!start) start = ts; const t = Math.min(1, (ts - start) / duration); const eased = 1 - Math.pow(1 - t, 3); setVal(eased * to); if (t < 1) requestAnimationFrame(step); }; requestAnimationFrame(step); }, [inView, to]); const formatted = val.toLocaleString('pt-BR', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); return {prefix}{formatted}{suffix}; }; // Section header with technical labels const SectionHeader = ({ index, label, title, kicker, className = '' }) => { const [ref, inView] = useReveal(); return (
§ {index} {label}

{title}

{kicker && (

{kicker}

)}
); }; // Technical dimension label (like in CAD drawings) const DimLabel = ({ children, className = '' }) => ( {children} ); // Tiny crosshair/marker const Crosshair = ({ size = 10, className = '' }) => ( ); Object.assign(window, { useReveal, useScrollProgress, Counter, SectionHeader, DimLabel, Crosshair });