export function timeAgo(d: Date): string { const s = Math.floor((Date.now() - d.getTime()) / 1000); if (s < 60) return "just now"; if (s < 3600) return `${Math.floor(s / 60)}m ago`; if (s < 86400) return `${Math.floor(s / 3600)}h ago`; return `${Math.floor(s / 86400)}d ago`; } export function yesPct(poolYes: string, poolNo: string): number { const yes = parseFloat(poolYes); const no = parseFloat(poolNo); return Math.round((no / (yes + no)) * 100); } export function daysLeft(d: Date | null): number | null { if (!d) return null; return Math.max(0, Math.ceil((d.getTime() - Date.now()) / 86400000)); } export function formatVol(v: string | number): string { const n = typeof v === "string" ? parseFloat(v) : v; if (n >= 1_000_000) return `$${(n / 1_000_000).toFixed(1)}M`; if (n >= 1000) return `$${(n / 1000).toFixed(1)}K`; return `$${Math.round(n)}`; } export function isPast(d: Date | null): boolean { if (!d) return false; return d.getTime() < Date.now(); } export function formatDate(d: Date): string { return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }); } export function formatPnl(v: string): string { const n = parseFloat(v); if (n >= 0) return `+$${n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; return `-$${Math.abs(n).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } export function formatCurrency(n: number, decimals = 2): string { return n.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); } export function pnlClass(v: string): string { return parseFloat(v) >= 0 ? "pnl-positive" : "pnl-negative"; } export function eventVolume(markets: { volume: string }[]): number { return markets.reduce((sum, m) => sum + parseFloat(m.volume), 0); } export const SELECTED_TAGS = ["sports", "finance", "pop-culture", "geopolitics", "stock-market", "tech", "politics"] as const; export const TAG_LABELS: Record = { politics: "Politics", elections: "Elections", sports: "Sports", finance: "Finance", economy: "Economy", tech: "Tech", earnings: "Earnings", "pop-culture": "Pop Culture", culture: "Culture", geopolitics: "Geopolitics", "stock-market": "Stock Market", "climate-science": "Climate & Science", world: "World", mentions: "Mentions", };