// Profile-header renderer. Owns the streamerProfileHeader div above the // VOD grid: hidden when no streamer is selected, skeleton while loading, // full card once profile data is back. Smooth fade-in is in CSS. let activeProfileRequestId = 0; function formatProfileFollowers(count: number | null): string { if (count == null) return '–'; if (count >= 1_000_000) return `${(count / 1_000_000).toFixed(count >= 10_000_000 ? 0 : 1)}M`; if (count >= 1_000) return `${(count / 1_000).toFixed(count >= 10_000 ? 0 : 1)}K`; return String(count); } function formatLastStreamAgo(iso: string | null): string { if (!iso) return '–'; const ms = Date.now() - new Date(iso).getTime(); if (!Number.isFinite(ms) || ms < 0) return '–'; const minutes = Math.floor(ms / 60_000); if (minutes < 60) return UI_TEXT.profile.agoMinutes.replace('{n}', String(minutes)); const hours = Math.floor(minutes / 60); if (hours < 24) return UI_TEXT.profile.agoHours.replace('{n}', String(hours)); const days = Math.floor(hours / 24); if (days < 30) return UI_TEXT.profile.agoDays.replace('{n}', String(days)); const months = Math.floor(days / 30); if (months < 12) return UI_TEXT.profile.agoMonths.replace('{n}', String(months)); const years = Math.floor(days / 365); return UI_TEXT.profile.agoYears.replace('{n}', String(years)); } function hideStreamerProfileHeader(): void { const el = document.getElementById('streamerProfileHeader'); if (!el) return; el.style.display = 'none'; applyHtml(el, ''); } function renderStreamerProfileSkeleton(login: string): void { const el = document.getElementById('streamerProfileHeader'); if (!el) return; el.classList.remove('is-live'); el.classList.add('streamer-profile-skeleton'); el.style.display = 'flex'; applyHtml(el, `