Replace the vertical EPG list/panel with a single horizontal timeline ribbon
(`app-epg-timeline`) shared across all live surfaces — the M3U player, the
unified live tab, and the Xtream and Stalker layouts. It preloads a multi-day
window and supports scroll, zoom, day navigation, short-programme tiers and
per-state empty/error views; the programme-details dialog is restyled to match
and now shows the channel logo.
Timeline / UI
- Auto-focus the currently-airing programme on channel select — instant
(`behavior: 'auto'`), centred, and deduped by programme-set identity so the
30s tick / zoom / re-emits never cause flaky re-jumps.
- Wide-tier cards show a dimmed description preview under the title; title and
preview clip on whole lines (`flex-shrink: 0` + `-webkit-line-clamp`), never
mid-line.
- Dynamic bar subtitle: the now-playing / archive programme title instead of a
static "Timeline" label.
- State-aware toolbar: hide Now + zoom when there is no ribbon, and the date
stepper when the channel has no EPG on any day (hidden, not disabled).
- Empty-state fills and centres within the panel area instead of a fixed
min-height that overflowed the compact inline panel and hid the buttons.
EPG current-programme lookup (electron-backend)
- Timezone-aware "airing now" comparison via SQLite `datetime()` (was a lexical
string compare that broke for offset vs UTC `Z` timestamps).
- Unscoped fallback for resolved candidates whose programmes are tagged with an
out-of-scope source (multi-source imports sharing XMLTV ids), so the sidebar
matches the timeline.
- Match channel candidates by the raw (case-sensitive) key as well as `LOWER()`,
since SQLite `LOWER()`/`COLLATE NOCASE` fold only ASCII — fixes Cyrillic /
Greek channel names showing "No program information available".
- Overlap-based day membership (`hasProgramsForDateKey`) so a film spanning
midnight keeps the ribbon on "today" while it airs.
Refactor
- Extract the duplicated channel-list EPG enrichment (progress + side-car map)
into `channel-list-container/epg-enrichment.util.ts`, shared by the
all-channels / groups / favorites / recent views; also fixes recent's and
favorites' unguarded, NaN-prone progress maths.
Tests: ui-epg 75, components 77, electron-backend 432; lint + web build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Swap M3 primary palette from violet to azure so checkboxes, radio
buttons, raised CTAs, and active states read as the same blue used by
the rail selection token. Cascading template + SCSS updates align the
remaining hand-rolled surfaces (Add Playlist dialog, VOD play button,
radio player, multi-EPG, empty-state CTAs) with the unified system.
LIVE stays red (broadcast role), cyan stays on EPG "now" indicator,
green stays on completed-download — semantic colors keep their meaning;
only the indiscriminate accent uses get folded into the blue primary.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>