// components.jsx — shared primitives: BlurText, FadeUp, Icons, CTAs, VideoCard, StickyCTA, Tweaks const { useState, useEffect, useRef, useCallback, useMemo } = React; // ---------- Icons (inline SVG, minimal) ---------- const Icon = { ArrowUpRight: ({ size = 16 }) => ( ), Play: ({ size = 22 }) => ( ), ChevronDown: ({ size = 18 }) => ( ), Shield: ({ size = 22 }) => ( ), Lock: ({ size = 22 }) => ( ), Bolt: ({ size = 22 }) => ( ), MapPin: ({ size = 18 }) => ( ), Star: ({ size = 16 }) => ( ), Scales: ({ size = 22 }) => ( ), X: ({ size = 14 }) => ( ), Instagram: ({ size = 14 }) => ( ), TikTok: ({ size = 14 }) => ( ), }; // ---------- BlurText ---------- function BlurText({ children, className = "", delay = 0, stagger = 90, as: As = "span" }) { const ref = useRef(null); const [inView, setInView] = useState(true); useEffect(() => { const el = ref.current; if (!el) return; const r = el.getBoundingClientRect(); if (r.top < window.innerHeight && r.bottom > 0) { setInView(true); return; } setInView(false); const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setInView(true); io.disconnect(); } }, { threshold: 0.05 }); io.observe(el); return () => io.disconnect(); }, []); let wordIdx = 0; const renderString = (s, keyPrefix) => { const tokens = s.split(/(\s+)/); return tokens.map((tok, pi) => { if (tok === "") return null; if (/^\s+$/.test(tok)) return {"\u00A0"}; const i = wordIdx++; const d = delay + i * stagger; return ( {tok} ); }); }; const arr = React.Children.toArray(children); const out = arr.map((c, ci) => { if (typeof c === "string") return {renderString(c, `c${ci}`)}; if (React.isValidElement(c) && c.type === "br") return
; if (React.isValidElement(c)) { const inner = typeof c.props.children === "string" ? renderString(c.props.children, `e${ci}`) : c.props.children; return React.cloneElement(c, { key: `e${ci}` }, inner); } return {c}; }); return {out}; } // ---------- FadeUp ---------- function FadeUp({ children, delay = 0, className = "", as: As = "div", style = {} }) { const ref = useRef(null); const [inView, setInView] = useState(false); useEffect(() => { const el = ref.current; if (!el) return; const r = el.getBoundingClientRect(); if (r.top < window.innerHeight && r.bottom > 0) { setInView(true); return; } const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setInView(true); io.disconnect(); } }, { threshold: 0.05 }); io.observe(el); return () => io.disconnect(); }, []); return ( {children} ); } // ---------- CTA ---------- function CTA({ href, children, variant = "primary", onClick, className = "" }) { const cls = variant === "primary" ? "cta cta-primary liquid-glass-strong" : variant === "red" ? "cta-red-fill" : "cta-ghost"; const Comp = href ? "a" : "button"; return ( {children} {variant === "ghost" ? : } ); } // ---------- Kicker ---------- function Kicker({ n, children }) { return
§{n} — {children}
; } // ---------- VideoBg (hydration-safe background video) ---------- function VideoBg({ src, poster, style }) { // Smoke video replaced with lightweight CSS blob background (2026-04-23). // Signature preserved so existing call sites don't need changes. return (