/* Techonymous — shared React components (Navbar, Footer, Cursor, Aurora, etc.) Babel-transpiled; components exported to window so other scripts can use them. */ const { useState, useEffect, useRef, useCallback } = React; /* ---------- Tiny inline icon set (Lucide-style strokes) ---------- */ const Icon = ({ name, size = 20, strokeWidth = 1.7, className = "" }) => { const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth, strokeLinecap: "round", strokeLinejoin: "round", className, }; switch (name) { case "arrow-right": return ; case "arrow-up-right":return ; case "check": return ; case "plus": return ; case "menu": return ; case "x": return ; case "code": return ; case "search": return ; case "trending-up": return ; case "target": return ; case "sparkles": return ; case "wand": return ; case "layers": return ; case "zap": return ; case "shield-check": return ; case "users": return ; case "bar-chart": return ; case "compass": return ; case "rocket": return ; case "globe": return ; case "play": return ; case "twitter": return ; case "linkedin": return ; case "instagram": return ; case "youtube": return ; case "star": return ; default: return null; } }; /* ---------- Custom cursor ---------- */ function Cursor() { useEffect(() => { const orb = document.createElement("div"); orb.className = "cursor-orb"; orb.innerHTML = '
'; document.body.appendChild(orb); let x = window.innerWidth/2, y = window.innerHeight/2; let tx = x, ty = y; const onMove = (e) => { tx = e.clientX; ty = e.clientY; }; window.addEventListener("mousemove", onMove); let raf; const tick = () => { x += (tx - x) * 0.22; y += (ty - y) * 0.22; orb.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`; raf = requestAnimationFrame(tick); }; tick(); const matchHover = (el) => el && (el.closest('a, button, .btn, .nav__link, .case-card, .case-filter, .faq-q, .bento__card, [data-cursor="hover"]')); const onOver = (e) => { if (matchHover(e.target)) orb.classList.add("is-hover"); }; const onOut = (e) => { if (matchHover(e.target)) orb.classList.remove("is-hover"); }; document.addEventListener("mouseover", onOver); document.addEventListener("mouseout", onOut); return () => { cancelAnimationFrame(raf); window.removeEventListener("mousemove", onMove); document.removeEventListener("mouseover", onOver); document.removeEventListener("mouseout", onOut); orb.remove(); }; }, []); return null; } /* ---------- Aurora background (animated blobs + noise + grid) ---------- */ function Aurora({ variant = "default" }) { return ( <> ); } /* ---------- Logo mark ---------- */ function Logo({ size = 45 }) { return ( Techonymous ); } /* Icon-only mark — for tight spots or favicons */ function LogoMark({ size = 32 }) { return ( ); } /* ---------- Navbar ---------- */ function Navbar({ active = "home" }) { const [scrolled, setScrolled] = useState(false); const [mobileOpen, setMobileOpen] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 12); onScroll(); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); useEffect(() => { document.body.style.overflow = mobileOpen ? "hidden" : ""; }, [mobileOpen]); const base = (typeof window !== "undefined" && window.__base) || ""; const links = [ { id: "home", label: "Home", href: base + "index.html" }, { id: "services", label: "Services", href: base + "services/index.html" }, { id: "work", label: "Work", href: base + "work/index.html" }, { id: "about", label: "About", href: base + "about/index.html" }, { id: "blog", label: "Blog", href: "#" }, { id: "contact", label: "Contact", href: base + "contact/index.html" }, ]; return ( <> {mobileOpen && (
{links.map((l, i) => ( {l.label} ))} Get a Free Audit
)} ); } /* ---------- Footer ---------- */ function Footer() { return ( ); } /* ---------- ScrollReveal helper ---------- */ function useScrollReveal(rootSelector = ".reveal") { useEffect(() => { const els = document.querySelectorAll(rootSelector); const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add("is-in"); io.unobserve(e.target); } }); }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" }); els.forEach(el => io.observe(el)); return () => io.disconnect(); }, [rootSelector]); } /* ---------- Count-up hook ---------- */ function useCountUp(target, { duration = 1800, start = false, decimals = 0 } = {}) { const [val, setVal] = useState(0); useEffect(() => { if (!start) return; const t0 = performance.now(); let raf; const tick = (t) => { const p = Math.min(1, (t - t0) / duration); const eased = 1 - Math.pow(1 - p, 3); setVal(target * eased); if (p < 1) raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, [start, target, duration]); return decimals === 0 ? Math.round(val) : val.toFixed(decimals); } /* ---------- Sparkline SVG ---------- */ function Sparkline({ data, color = "#00D4FF", className = "spark" }) { const max = Math.max(...data); const min = Math.min(...data); const w = 200, h = 36; const stepX = w / (data.length - 1); const pts = data.map((v, i) => { const x = i * stepX; const y = h - ((v - min) / (max - min || 1)) * (h - 4) - 2; return `${x},${y}`; }); const d = "M " + pts.join(" L "); const dArea = d + ` L ${w},${h} L 0,${h} Z`; return ( ); } /* ---------- Magnetic button effect ---------- */ function attachMagnetic(el, strength = 18) { if (!el || el.__magnetic) return; el.__magnetic = true; const onMove = (e) => { const r = el.getBoundingClientRect(); const x = e.clientX - (r.left + r.width / 2); const y = e.clientY - (r.top + r.height / 2); el.style.transform = `translate(${x / strength}px, ${y / strength}px)`; }; const onLeave = () => { el.style.transform = ""; }; el.addEventListener("mousemove", onMove); el.addEventListener("mouseleave", onLeave); } /* Auto-attach magnetic to all .btn-primary */ function MagneticInit() { useEffect(() => { document.querySelectorAll(".btn-primary").forEach(b => attachMagnetic(b)); }); return null; } /* ---------- Page shell ---------- */ function PageShell({ children, active }) { return ( <> {children}