/* CARDS — renders poster cards, rows (carousels) and grids. Items can come straight from the API ({tmdb_id, type, name, year, poster}) or from storage records; normalizeItem() handles both. */ (function () { 'use strict'; const { escapeHtml: esc, tmdbResize, formatSeconds } = SR.util; function normalizeItem(r) { return { tmdbId: r.tmdb_id != null ? r.tmdb_id : r.tmdbId, type: r.type, season: r.season, episode: r.episode, name: r.name || r.title || '', year: r.year || '', poster: r.poster || r.poster_url || '', overview: r.overview || '', }; } function watchHref(item) { const p = new URLSearchParams(); p.set('id', item.tmdbId); p.set('type', item.type); if (item.type === 'tv') { if (item.season != null) p.set('s', item.season); if (item.episode != null) p.set('e', item.episode); } return `watch.html?${p.toString()}`; } function card(item, opts = {}) { const el = document.createElement('a'); el.className = 'card'; el.href = opts.href || watchHref(item); const poster = tmdbResize(item.poster, 'w342'); const progress = opts.progress != null ? `` : ''; const meta = item.meta || (item.year ? `${item.year} · ${item.type === 'tv' ? 'TV' : 'Movie'}` : item.type === 'tv' ? 'TV' : 'Movie'); el.innerHTML = ` ${poster ? `` : '?'} ${progress} ${esc(item.name)} ${esc(meta)}`; return el; } function row(title, items) { const section = document.createElement('section'); section.className = 'row'; section.innerHTML = `

${esc(title)}

`; const scroll = document.createElement('div'); scroll.className = 'row__scroll'; for (const item of items) scroll.appendChild(card(item)); section.appendChild(scroll); return section; } function grid(items) { const el = document.createElement('div'); el.className = 'grid'; for (const item of items) el.appendChild(card(item)); return el; } function emptyState(title, hint) { const el = document.createElement('div'); el.className = 'empty'; el.innerHTML = `

${esc(title)}

${hint ? `

${esc(hint)}

` : ''}`; return el; } // "Continue watching" row: latest record per show, with progress bar function continueRow() { const recs = SR.storage.latestPerShow(); if (!recs.length) return null; const items = recs.map((r) => ({ tmdbId: r.tmdbId, type: r.type, season: r.season, episode: r.episode, name: r.show || r.title || '', poster: r.poster || '', meta: r.type === 'tv' ? `S${r.season}E${r.episode}${r.title ? ` · ${r.title}` : ''} · ${formatSeconds(Math.max(0, r.d - r.t))} left` : `Movie · ${formatSeconds(Math.max(0, r.d - r.t))} left`, progress: r.d ? r.t / r.d : 0, })); return row('Continue watching', items); } window.SR = window.SR || {}; SR.cards = { normalizeItem, card, row, grid, emptyState, continueRow }; })();