// Platform metadata — used for badges, panels, chips window.PLATFORMS = { foreplay: { label: 'Foreplay', color: '#7c3aed', bg: '#f2ebfe' }, adspy: { label: 'AdSpy', color: '#ea580c', bg: '#ffede2' }, brandsearch: { label: 'BrandSearch', color: '#0284c7', bg: '#e0f2fe' }, metaads: { label: 'MetaAds', color: '#1877f2', bg: '#e0ecfe' }, }; window.Icon = ({ name, size = 16, ...rest }) => { const className = [rest.className].filter(Boolean).join(' '); const common = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round', ...rest, className }; const paths = { search: <>, filter: , scroll: <>, film: <>, image: <>, check: , arrowRight: <>, plus: <>, trash: <>, thumbDown: <>, x: <>, play: , trend: <>, sliders: <>, chevronDown: , settings: <>, logOut: <>, bolt: , dedupe: <>, loader: <>, refresh: <>, expand: <>, copy: <>, caption: <>, target: <>, edit: <>, users: <>, shield: <>, clock: <>, }; return {paths[name]}; }; // Format an elapsed-time delta (in ms since arrival) using the dashboard's // arrival-time scale: "just now" for sub-minute, then minutes up to an hour, // hours up to a day, days up to ~30, months up to a year, and years beyond. window.formatRelativeTime = function formatRelativeTime(deltaMs) { if (!Number.isFinite(deltaMs) || deltaMs < 0) return 'just now'; const sec = Math.floor(deltaMs / 1000); if (sec < 45) return 'just now'; const min = Math.floor(sec / 60); if (min < 60) return `${min} min`; const hr = Math.floor(min / 60); if (hr < 24) return `${hr} hr`; const day = Math.floor(hr / 24); if (day < 30) return `${day} d`; const mo = Math.floor(day / 30); if (mo < 12) return `${mo} mo`; const yr = Math.floor(day / 365); return `${yr} y`; }; // Live-ticking "arrived X ago" badge — lets cards across Search, // Autoresearch, Filter, Remodel, and Auto-Remodel show how long ago an ad // landed in that section. Each instance owns its own 1-minute timer because // the dashboard never has more than a few hundred cards on screen. window.TimeAgo = function TimeAgo({ ms, className, prefix = '', suffix = ' ago', emptyLabel = '', title: titleOverride, iconSize = 11, showIcon = true, }) { const [, setNow] = React.useState(Date.now()); React.useEffect(() => { if (!ms) return undefined; const id = setInterval(() => setNow(Date.now()), 60_000); return () => clearInterval(id); }, [ms]); if (!ms) { if (!emptyLabel) return null; return {emptyLabel}; } const label = `${prefix}${window.formatRelativeTime(Date.now() - ms)}${suffix}`; let title = titleOverride; if (title === undefined) { try { title = `Arrived ${new Date(ms).toLocaleString()}`; } catch { title = label; } } return ( {showIcon && } {label} ); };