/* Primitives — Logo, Button, Eyebrow, Section, Container, Reveal, hooks. */ const { useState, useEffect, useRef } = React; function Container({ children, style }) { return
{children}
; } /* Wordmark: orbital mark + "Brand New Edge" */ function Logo({ size = 30, variant, href = 'index.html' }) { return ( Brand New Edge ); } function Eyebrow({ children, style }) { return
{children}
; } function Button({ children, variant = 'solid', href = '#contact', onClick, style }) { const [h, setH] = useState(false); const base = { display:'inline-flex', alignItems:'center', gap:8, cursor:'pointer', fontFamily:'var(--font-body)', fontWeight:600, fontSize:15.5, lineHeight:1, padding:'14px 22px', borderRadius:'var(--r-btn)', textDecoration:'none', transition:'all var(--dur) var(--ease-out)', border:'1px solid transparent', whiteSpace:'nowrap', }; const variants = { solid: { background:'linear-gradient(100deg, #9B55D6 0%, #7B2FBE 38%, #5B3FD6 70%, #3D4FC9 100%)', color:'#fff', boxShadow: h ? 'var(--glow)' : 'var(--shadow-sm)', transform: h ? 'translateY(-1px)' : 'none' }, accent:{ background:'linear-gradient(100deg, #9B55D6 0%, #7B2FBE 38%, #5B3FD6 70%, #3D4FC9 100%)', color:'#fff', boxShadow: h ? 'var(--glow)' : 'none', transform: h ? 'translateY(-1px)' : 'none' }, ghost: { background: h ? 'rgba(155,85,214,.10)' : 'transparent', color:'var(--text-1)', borderColor:'var(--border-2)' }, }; return ( setH(true)} onMouseLeave={()=>setH(false)} style={{ ...base, ...variants[variant], ...style }}>{children} ); } /* Section wrapper. bg: app | alt | deep (theme-aware light/dark) | navy (always dark feature) */ function Section({ id, bg = 'app', children, style, label }) { const bgMap = { app:'var(--app-bg)', alt:'var(--section-alt)', deep:'var(--section-deep)', navy:'var(--navy-feature)' }; // deep = theme-aware surface (light-gray in bright mode, navy in dark); navy = always-dark feature band const deepForce = { '--text-1':'var(--on-deep-1)', '--text-2':'var(--on-deep-2)', '--text-3':'var(--on-deep-3)', '--border-1':'var(--deep-border)', '--border-2':'var(--deep-border)', '--eyebrow':'var(--deep-eyebrow)', '--card-bg':'var(--deep-card)', '--client-filter':'var(--deep-client-filter)' }; const navyForce = { '--text-1':'#fff', '--text-2':'rgba(255,255,255,.74)', '--text-3':'rgba(255,255,255,.54)', '--border-1':'rgba(255,255,255,.12)', '--border-2':'rgba(255,255,255,.22)', '--eyebrow':'#A98BD6', '--accent':'#9B55D6', '--accent-strong':'#7B2FBE', '--card-bg':'rgba(255,255,255,.05)', '--client-filter':'none', '--on-deep-1':'#fff', '--on-deep-2':'rgba(255,255,255,.74)', '--on-deep-3':'rgba(255,255,255,.54)', '--deep-card':'rgba(255,255,255,.05)', '--deep-border':'rgba(255,255,255,.12)', '--deep-chip':'rgba(255,255,255,.08)', '--deep-input':'rgba(255,255,255,.06)' }; const force = bg === 'deep' ? deepForce : bg === 'navy' ? navyForce : {}; return (
{children}
); } /* Reveal — visible-by-default safe entrance via CSS transition + forced fallback. */ function Reveal({ children, delay = 0, as = 'div', style, ...rest }) { const ref = useRef(null); const [shown, setShown] = useState(false); useEffect(() => { const el = ref.current; if (!el) return; const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (reduce || !('IntersectionObserver' in window)) { setShown(true); return; } const io = new IntersectionObserver((es) => { es.forEach(e => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }); }, { threshold:.12, rootMargin:'0px 0px -8% 0px' }); io.observe(el); const t = setTimeout(() => setShown(true), 1400); // safety: never stay hidden return () => { io.disconnect(); clearTimeout(t); }; }, []); const Tag = as; // Opacity stays 1 (never strands invisible in captures); only transform animates. return ( {children} ); } /* Count-up on view. Pass numeric string; non-numeric (EST) renders as-is. */ function CountUp({ value, suffix = '', dur = 1400, style }) { const ref = useRef(null); const numeric = /^\d/.test(value); const target = numeric ? parseInt(value, 10) : null; const [n, setN] = useState(numeric ? 0 : value); useEffect(() => { if (!numeric) return; const el = ref.current; if (!el) return; let raf, started = false; const run = () => { const t0 = performance.now(); const tick = (t) => { const p = Math.min(1, (t - t0) / dur); const e = 1 - Math.pow(1 - p, 3); setN(Math.round(e * target)); if (p < 1) raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); }; const io = new IntersectionObserver((es) => { es.forEach(e => { if (e.isIntersecting && !started) { started = true; run(); io.disconnect(); } }); }, { threshold:.4 }); io.observe(el); const safety = setTimeout(() => { if (!started) { started = true; setN(target); } }, 1600); return () => { io.disconnect(); cancelAnimationFrame(raf); clearTimeout(safety); }; }, []); const display = numeric ? `${n}${suffix}` : `${value}${suffix}`; return {display}; } function ClientLogo({ name, h = 22 }) { const src = (window.__resources && window.__resources['client-' + name]) || `assets/clients/${name}.svg`; return {name}; } Object.assign(window, { Container, Logo, Eyebrow, Button, Section, Reveal, CountUp, ClientLogo });