/* 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 (
);
}
/* 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
;
}
Object.assign(window, { Container, Logo, Eyebrow, Button, Section, Reveal, CountUp, ClientLogo });