const CLIPS_JSON_URL = '/data/clips.json'; const clipPlaySVG = ''; const clipShareSVG = ''; function escapeHTML(str) { const el = document.createElement('span'); el.textContent = str; return el.innerHTML; } async function shareClipContent(title, url, btn) { if (navigator.share) { try { await navigator.share({ title, url }); return; } catch (e) { if (e.name === 'AbortError') return; } } try { await navigator.clipboard.writeText(url); const orig = btn.innerHTML; btn.innerHTML = 'Copied!'; btn.classList.add('share-copied'); setTimeout(() => { btn.innerHTML = orig; btn.classList.remove('share-copied'); }, 2000); } catch (e) { prompt('Copy this link:', url); } } function renderClipCard(clip, featured) { const card = document.createElement('div'); card.className = 'clip-card' + (featured ? ' clip-card-featured' : ''); const youtubeId = (clip.youtube_id || '').replace(/[^a-zA-Z0-9_-]/g, ''); if (youtubeId) card.dataset.youtubeId = youtubeId; const hasVideo = !!youtubeId; const epLabel = clip.episode_number ? `Episode ${Number(clip.episode_number)}` : ''; const title = escapeHTML(clip.title || ''); const desc = escapeHTML(clip.description || ''); const thumbImg = clip.thumbnail && /^[\w\/.-]+$/.test(clip.thumbnail) ? `${title}` : ''; card.innerHTML = `
${thumbImg}
${epLabel}

${title}

${desc}

${hasVideo ? `` : ''} ${hasVideo ? `` : ''}
`; if (hasVideo) { card.querySelector('.clip-play-btn').addEventListener('click', (e) => { e.stopPropagation(); const inner = card.querySelector('.clip-card-inner'); inner.innerHTML = ``; }); const shareBtn = card.querySelector('.clip-share-btn'); if (shareBtn) { shareBtn.addEventListener('click', (e) => { e.stopPropagation(); shareClipContent(clip.title || '', `https://youtube.com/watch?v=${youtubeId}`, shareBtn); }); } } return card; } async function fetchClips() { try { const res = await fetch(CLIPS_JSON_URL); if (!res.ok) throw new Error('Failed to fetch clips'); return await res.json(); } catch (err) { console.error('Error loading clips:', err); return []; } } async function initClipsPage() { const clips = await fetchClips(); if (!clips.length) return; const featuredContainer = document.querySelector('.clips-featured'); const gridContainer = document.querySelector('.clips-grid'); if (featuredContainer) { clips.filter(c => c.featured).forEach(clip => { featuredContainer.appendChild(renderClipCard(clip, true)); }); } if (gridContainer) { clips.filter(c => !c.featured).forEach(clip => { gridContainer.appendChild(renderClipCard(clip, false)); }); } } async function renderFeaturedClipsInline(containerId) { const container = document.getElementById(containerId); if (!container) return; const clips = await fetchClips(); const featured = clips.filter(c => c.featured); featured.forEach(clip => { container.appendChild(renderClipCard(clip, true)); }); } // Auto-init if clips page containers exist if (document.querySelector('.clips-featured') || document.querySelector('.clips-grid')) { initClipsPage(); }