/* PeptideKit — shared UI bits */
const { useEffect, useRef, useState } = React;
// ---------- Logo / Wordmark ----------
function Logo({ size = 28 }) {
return (
);
}
// ---------- App Store badge (real-feel, original layout) ----------
function AppStoreBadge({ size = 'md' }) {
const big = size === 'lg';
return (
Download on the
App Store
);
}
// ---------- Floating phone ----------
function Phone({ src, alt, tilt = 0, glow = true, width = 280, className = '' }) {
return (
);
}
// ---------- Reveal-on-scroll ----------
function Reveal({ children, delay = 0, as: Tag = 'div', ...rest }) {
const ref = useRef(null);
const [shown, setShown] = useState(true);
useEffect(() => {
const el = ref.current;
if (!el) return;
setShown(false);
const obs = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) {
setTimeout(() => setShown(true), delay);
obs.unobserve(e.target);
}
});
}, { threshold: 0.05, rootMargin: '0px 0px 0px 0px' });
obs.observe(el);
return () => obs.disconnect();
}, [delay]);
return {children};
}
// ---------- Bokeh ----------
function Bokeh({ count = 14 }) {
const dots = Array.from({ length: count }).map((_, i) => {
const size = 6 + Math.random() * 22;
return {
key: i,
style: {
left: `${Math.random() * 100}%`,
top: `${Math.random() * 100}%`,
width: size, height: size,
animationDelay: `${Math.random() * 8}s`,
animationDuration: `${10 + Math.random() * 10}s`,
opacity: 0.2 + Math.random() * 0.5,
}
};
});
return (
{dots.map(d => )}
);
}
// ---------- Lucide-ish line icons (hand-drawn minimal) ----------
function Icon({ name, size = 22 }) {
const common = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none',
stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round' };
switch (name) {
case 'layers': return (
);
case 'bell': return (
);
case 'calc': return (
);
case 'scan': return (
);
case 'trend': return (
);
case 'sparkles': return (
);
case 'check': return (
);
case 'chevron': return (
);
case 'arrow-down': return (
);
case 'shield': return (
);
case 'lock': return (
);
case 'cpu': return (
);
default: return null;
}
}
Object.assign(window, { Logo, AppStoreBadge, Phone, Reveal, Bokeh, Icon });