// 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 ;
};
// 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}
);
};