/* VE GAMERZ — shared chrome, hooks, and layout primitives. Exports to window.VG. */ const { Button, Badge, Eyebrow } = window.VEGAMERZDesignSystem_63bcb5; const D = window.VG_DATA; const wrap = { maxWidth: 'var(--wrap-max)', margin: '0 auto', padding: '0 var(--wrap-pad)', position: 'relative', zIndex: 1 }; const NOTCH = 'polygon(10px 0,100% 0,100% calc(100% - 10px),calc(100% - 10px) 100%,0 100%,0 10px)'; const ROUTES = [ { id: 'home', label: 'Home' }, { id: 'about', label: 'About' }, { id: 'videos', label: 'Videos' }, { id: 'membership', label: 'Membership' }, { id: 'contact', label: 'Contact' } ]; /* ── Hooks ─────────────────────────────────────────── */ function useReducedMotion() { const [rm, setRm] = React.useState(() => typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches); React.useEffect(() => { const m = matchMedia('(prefers-reduced-motion: reduce)'); const on = () => setRm(m.matches); m.addEventListener ? m.addEventListener('change', on) : m.addListener(on); return () => { m.removeEventListener ? m.removeEventListener('change', on) : m.removeListener(on); }; }, []); return rm; } function useInView(opts) { const ref = React.useRef(null); const [seen, setSeen] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; if (typeof IntersectionObserver === 'undefined') { setSeen(true); return; } const io = new IntersectionObserver((es) => { es.forEach(e => { if (e.isIntersecting) { setSeen(true); io.disconnect(); } }); }, { threshold: (opts && opts.threshold) || 0.18, rootMargin: '0px 0px -8% 0px' }); io.observe(el); return () => io.disconnect(); }, []); return [ref, seen]; } /* Fade + rise reveal wrapper. Honors reduced motion. */ function Reveal({ children, delay = 0, y = 22, style = {}, as = 'div' }) { const rm = useReducedMotion(); const [ref, seen] = useInView(); const El = as; const on = rm || seen; return ( {children} ); } function useCountUp(target, { decimals = 0, duration = 1400, run = true } = {}) { const rm = useReducedMotion(); const [val, setVal] = React.useState(rm ? target : 0); React.useEffect(() => { if (!run) return; if (rm) { setVal(target); return; } let raf, t0; const ease = (t) => 1 - Math.pow(1 - t, 3); const step = (t) => { if (!t0) t0 = t; const p = Math.min(1, (t - t0) / duration); setVal(target * ease(p)); if (p < 1) raf = requestAnimationFrame(step); }; raf = requestAnimationFrame(step); return () => cancelAnimationFrame(raf); }, [run, target, rm]); return decimals ? val.toFixed(decimals) : Math.round(val).toString(); } /* ── Brand marks ───────────────────────────────────── */ function LogoMark({ size = 40 }) { return ( VE GAMERZ logo ); } function Wordmark({ size = 20 }) { return ( VE GAMERZ ); } /* ── Nav ───────────────────────────────────────────── */ function NavLink({ label, active, onClick }) { const [hover, setHover] = React.useState(false); return ( ); } function Hamburger({ open, onClick }) { const bar = { display: 'block', width: 22, height: 2, background: 'var(--c-primary)', transition: 'transform .25s var(--ease), opacity .2s var(--ease)' }; return ( ); } function NavBar({ route, go }) { const [open, setOpen] = React.useState(false); React.useEffect(() => { setOpen(false); }, [route]); const nav = (id) => { go(id); setOpen(false); }; return (
Live Now
setOpen(o => !o)} />
); } /* ── Section head + breadcrumbs ────────────────────── */ function SectionHead({ eyebrow, title, sub, align = 'left', style = {} }) { return (
{eyebrow ?
{eyebrow}
: null}

{title}

{sub ?

{sub}

: null}
); } function Breadcrumbs({ trail, go }) { return ( ); } /* ── Carousel (arrows + drag + snap) ───────────────── */ function Carousel({ children, ariaLabel = 'Carousel' }) { const ref = React.useRef(null); const drag = React.useRef({ down: false, x: 0, left: 0, moved: 0 }); const [atStart, setAtStart] = React.useState(true); const [atEnd, setAtEnd] = React.useState(false); const update = React.useCallback(() => { const el = ref.current; if (!el) return; setAtStart(el.scrollLeft <= 2); setAtEnd(el.scrollLeft + el.clientWidth >= el.scrollWidth - 2); }, []); React.useEffect(() => { update(); const el = ref.current; if (!el) return; el.addEventListener('scroll', update, { passive: true }); window.addEventListener('resize', update); return () => { el.removeEventListener('scroll', update); window.removeEventListener('resize', update); }; }, [update]); const step = (dir) => { const el = ref.current; if (!el) return; const card = el.querySelector('[data-slide]'); const d = (card ? card.offsetWidth + 20 : el.clientWidth * 0.8) * dir; el.scrollBy({ left: d, behavior: 'smooth' }); }; const onDown = (e) => { const el = ref.current; drag.current = { down: true, x: e.clientX, left: el.scrollLeft, moved: 0 }; el.setPointerCapture && el.setPointerCapture(e.pointerId); }; const onMove = (e) => { if (!drag.current.down) return; const dx = e.clientX - drag.current.x; drag.current.moved = Math.abs(dx); ref.current.scrollLeft = drag.current.left - dx; }; const onUp = () => { drag.current.down = false; }; const arrow = (side, disabled, onClick) => ( ); return (
{arrow('l', atStart, () => step(-1))} {arrow('r', atEnd, () => step(1))}
{ if (drag.current.moved > 6) { e.preventDefault(); e.stopPropagation(); } }} style={{ display: 'grid', gridAutoFlow: 'column', gridAutoColumns: 'minmax(300px,1fr)', gap: 20, overflowX: 'auto', scrollSnapType: 'x mandatory', scrollbarWidth: 'none', padding: '6px 2px 18px', cursor: 'grab', touchAction: 'pan-y' }} className="vg-carousel-track"> {React.Children.map(children, (ch, i) =>
{ch}
)}
); } /* ── Stat counter (count-up on view) ───────────────── */ function StatCounter({ value, suffix = '', decimals = 0, label }) { const { StatCard } = window.VEGAMERZDesignSystem_63bcb5; const [ref, seen] = useInView({ threshold: 0.4 }); const n = useCountUp(value, { decimals, run: seen }); return
{n}{suffix}} label={label} />
; } /* ── Social row ────────────────────────────────────── */ function SocialRow({ size = 'md' }) { const big = size === 'lg'; return (
{D.SOCIAL.map(s => ( { e.currentTarget.style.background = 'rgba(0,229,255,.12)'; e.currentTarget.style.boxShadow = 'var(--glow-sm)'; e.currentTarget.style.transform = 'translateY(-2px)'; }} onMouseLeave={e => { e.currentTarget.style.background = 'rgba(0,229,255,.06)'; e.currentTarget.style.boxShadow = 'none'; e.currentTarget.style.transform = 'none'; }}> {s.label} {s.handle} ))}
); } /* ── Background + footer ───────────────────────────── */ function SiteBackground() { return