// Shared primitives: Logo, icons, arrow, badges
const { useState, useEffect, useRef, useMemo } = React;
const Logo = ({ tone = 'light', size = 28 }) => {
// White-label re-creation of the wordmark: "decisive" + "ZONE" boxed
const fg = tone === 'light' ? 'var(--ink)' : 'var(--paper)';
const box = 'var(--accent)';
const boxText = 'var(--ink)';
return (
decisive
ZONE
);
};
// Simple monoline icons (24x24)
const Icon = ({ name, size = 22, stroke = 1.6, color = 'currentColor' }) => {
const p = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round' };
switch (name) {
case 'arrow': return ;
case 'arrow-up': return ;
case 'phone': return ;
case 'mail': return ;
case 'pin': return ;
case 'whatsapp': return ;
case 'check': return ;
case 'sparkle': return ;
case 'compass': return ;
case 'building': return ;
case 'globe': return ;
case 'anchor': return ;
case 'id': return ;
case 'bank': return ;
case 'calc': return ;
case 'book': return ;
case 'office': return ;
case 'shield': return ;
case 'play': return ;
case 'star': return ;
case 'minus': return ;
case 'plus': return ;
case 'chev-r': return ;
case 'chev-d': return ;
default: return null;
}
};
const Pill = ({ children, tone = 'paper' }) => (
{children}
);
// Hook: in-view fade
const useReveal = () => {
const ref = useRef(null);
useEffect(() => {
const el = ref.current; if (!el) return;
const obs = new IntersectionObserver((entries) => {
entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('fade-up'); obs.unobserve(e.target); }});
}, { threshold: 0.12 });
obs.observe(el);
return () => obs.disconnect();
}, []);
return ref;
};
Object.assign(window, { Logo, Icon, Pill, useReveal });