/* ============================================================
   HERTZ IPTV — stylesheet
   Dark editorial / brutalist-precise. Accent: signal red.
   ============================================================ */

:root {
    /* Palette */
    --bg:           #0a0a0b;
    --bg-elev:      #131316;
    --bg-tile:      #1a1a1f;
    --bg-tile-hi:   #22222a;
    --border:       #25252c;
    --border-hi:    #3a3a44;
    --fg:           #f4f4f5;
    --fg-dim:       #9a9aa3;
    --fg-faint:     #5a5a63;
    --accent:       #ff3b30;        /* signal red */
    --accent-dim:   #ff3b3033;
    --live:         #ff3b30;
    --rec:          #fbbf24;
    --watched:      #ff3b30;
    --archive:      #60a5fa;        /* upcoming / "Greitai" */
    --soon:         #ff918a;

    /* Type */
    --font-display: 'Instrument Serif', Georgia, serif;
    --font-body:    'Manrope', system-ui, sans-serif;
    --font-mono:    'JetBrains Mono', ui-monospace, monospace;

    /* Layout */
    --topbar-h: 64px;
    --radius:   4px;
    --radius-lg: 12px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
    background: var(--bg);
    color: var(--fg);
    font-family: var(--font-body);
    font-size: 14px;
    line-height: 1.4;
    overflow-x: hidden;
    /* body (not html) is the actual scroll container by design — this plus
       height:100% above is what lets body.auth-locked / body.is-watching
       lock page scroll just by setting overflow:hidden on body. .topbar is
       position:fixed (not sticky) specifically so it doesn't care which
       element ends up being the scroll container. Since fixed removes it
       from flow entirely, compensate here so content doesn't start out
       hidden underneath it. */
    padding-top: var(--topbar-h);
    /* Subtle film grain via radial gradients */
    background-image:
        radial-gradient(ellipse at top, #16161a 0%, transparent 60%),
        radial-gradient(ellipse at bottom right, #1a1014 0%, transparent 60%);
    background-attachment: fixed;
}

button { font-family: inherit; cursor: pointer; }
input  { font-family: inherit; }
a { color: inherit; text-decoration: none; }

/* ============================================================
   TV APP MODE — applied when running inside the Android TV WebView shell
   (see isTvApp in app.js / MainActivity.kt's UA marker). D-pad remotes have
   no hover/pointer at all, so every focusable element needs a strong,
   unambiguous focus indicator here — this is what makeTvFocusable()/the
   spatial-nav keydown handler in app.js actually move focus between.
   ============================================================ */
.tv-mode :focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius);
}
/* Cards/buttons built as plain <a>/<button> already get the rule above for
   free; a few tile-shaped cards clip an outline oddly against their own
   border-radius/overflow:hidden, so those get a matching box-shadow ring
   instead of relying on outline. */
.tv-mode .upcoming-card:focus-visible,
.tv-mode .episode-card:focus-visible,
.tv-mode .channel-card:focus-visible,
.tv-mode .epg-category-card:focus-visible,
.tv-mode .rail-channel:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent);
}
/* Elements that only ever revealed themselves on hover (no equivalent on a
   remote) — show them plainly instead of gating on a pointer that will
   never come. */
.tv-mode .uc-remove-btn,
.tv-mode .home-scroll-btn {
    opacity: 1;
}

/* ============================================================
   TOPBAR
   ============================================================ */
.topbar {
    /* fixed, not sticky — sticky's "nearest scrolling ancestor" is body here
       (see body's overflow-x/height comment above), and in practice that
       made the bar drift off/disappear at some scroll offsets instead of
       reliably pinning to the viewport. Fixed always anchors to the
       viewport regardless of which element ends up scrolling. */
    position: fixed; top: 0; left: 0; right: 0; z-index: 50;
    height: var(--topbar-h);
    background: rgba(10,10,11,0.85);
    backdrop-filter: blur(20px) saturate(160%);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    border-bottom: 1px solid var(--border);
}

.topbar-inner { 
    padding: 0 32px;
    max-width: 1800px; 
    height: var(--topbar-h);
    gap: 48px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
}

.brand {
    display: flex; align-items: center; gap: 8px;
    font-family: var(--font-display);
    font-size: 22px;
    font-style: italic;
    letter-spacing: -0.01em;
    text-decoration: none;
    color: var(--fg);
    cursor: pointer;
    transition: opacity 0.15s;
}
.brand:hover { opacity: 0.85; }
.brand-mark {
    color: var(--accent);
    font-size: 24px;
    font-style: normal;
    transform: translateY(2px);
}
/* Sized relative to the mark's own font-size (set on .brand-mark/.login-mark
   above) so the logo image scales consistently wherever it's used, without
   being cropped or stretched regardless of its native aspect ratio. */
.utv-logo {
    display: block;
    width: 2em;
    height: 2em;
    object-fit: contain;
}
.login-mark .utv-logo {
    width: 4em;
    height: 4em;
    margin: 0 auto; 
}
.tv-brand {
    color: var(--accent);
}
.brand-name { font-weight: 400; }

.primary-nav {
    display: flex; gap: 4px;
    justify-self: center;
}
.nav-pill {
    background: transparent;
    border: none;
    color: var(--fg-dim);
    padding: 8px 16px;
    border-radius: 99px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.01em;
    transition: color 0.15s, background 0.15s;
}
.nav-pill:hover { color: var(--fg); background: var(--bg-tile); }
.nav-pill.active {
    color: var(--bg);
    background: var(--fg);
}

.topbar-right {
    display: flex; align-items: center; gap: 16px;
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--fg-dim);
}
.clock { font-variant-numeric: tabular-nums; letter-spacing: 0.05em; }

/* Desktop: an invisible wrapper — .primary-nav / .topbar-right stay direct
   grid children of .topbar-inner, exactly as if this div weren't here.
   Only becomes a real dropdown box under the mobile breakpoint below. */
.mobile-menu { display: contents; }
.hamburger-btn {
    display: none;
    width: 36px; height: 36px;
    align-items: center; justify-content: center;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--fg);
    justify-self: end;
}
.hamburger-btn:hover { border-color: var(--border-hi); background: var(--bg-tile); }

/* ============================================================
   VIEW HEADERS
   ============================================================ */

main { padding: 32px 32px 64px; max-width: 1800px; margin: 0 auto; }
/* Hero carousel sits flush under the topbar instead of leaving the usual
   32px gap above it — toggled by renderHome() in app.js. */
main.has-hero { padding-top: 0; }

.view-header {
    margin-bottom: 32px;
}
.view-title {
    display: flex; align-items: baseline; gap: 16px;
    margin-bottom: 20px;
}
.view-title h1 {
    font-family: var(--font-display);
    font-weight: 400;
    font-style: italic;
    font-size: 56px;
    letter-spacing: -0.02em;
    margin: 0;
    line-height: 1;
}
.channel-count {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--fg-faint);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Group filter pills — single non-wrapping, horizontally scrollable strip */
.group-filter {
    display: flex; flex-wrap: nowrap; gap: 6px;
    overflow-x: auto;
    padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.group-filter::-webkit-scrollbar { display: none; }
.group-pill {
    flex: 0 0 auto;
    background: var(--bg-tile);
    color: var(--fg-dim);
    border: 1px solid var(--border);
    padding: 6px 12px;
    border-radius: 99px;
    font-size: 12px;
    font-weight: 500;
    transition: all 0.15s;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
}
.group-pill:hover {
    color: var(--fg);
    border-color: var(--border-hi);
}
.group-pill.active {
    background: var(--fg);
    color: var(--bg);
    border-color: var(--fg);
}

/* ============================================================
   CHANNEL GRID
   ============================================================ */

.channel-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px;
}
/* TV app — the EPG-shortcut and favorite-heart buttons only ever revealed on
   .channel-card:hover, which never happens on a remote (see the tile's own
   click already opening the channel); dropping them plus shrinking the tile
   ~30% fits noticeably more channels on screen at once, which matters more
   here than on a mouse-driven grid you can just scroll. */
.tv-mode .channel-card .fav-heart-btn,
.tv-mode .channel-card .channel-epg-btn {
    display: none;
}
.tv-mode .channel-grid {
    grid-template-columns: repeat(auto-fill, minmax(154px, 1fr));
    gap: 10px;
}

.channel-card {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: transform 0.2s, border-color 0.2s;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    position: relative;
}
.channel-card:hover {
    transform: translateY(-2px);
    border-color: var(--border-hi);
}
.channel-card:hover .channel-logo-wrap {
    background: var(--bg-tile-hi);
}

.channel-logo-wrap {
    aspect-ratio: 16 / 10;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-tile);
    transition: background 0.2s;
    position: relative;
}
.channel-logo-wrap img {
    max-width: 60%;
    max-height: 60%;
    object-fit: contain;
    filter: drop-shadow(0 4px 12px rgba(0,0,0,0.3));
}
.channel-logo-wrap .logo-fallback {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 36px;
    color: var(--fg-dim);
}

.channel-number {
    position: absolute;
    top: 10px; left: 10px;
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    background: rgba(0,0,0,0.6);
    padding: 2px 6px;
    border-radius: 3px;
    letter-spacing: 0.04em;
}

/* EPG button — top right of channel card */
.channel-epg-btn {
    position: absolute;
    top: 10px; right: 10px;
    display: flex;
    align-items: center;
    gap: 5px;
    background: rgba(0,0,0,0.7);
    color: var(--fg);
    border: 1px solid rgba(255,255,255,0.12);
    padding: 4px 8px 4px 7px;
    border-radius: 3px;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    cursor: pointer;
    opacity: 0;
    transform: translateY(-2px);
    transition: opacity 0.15s, transform 0.15s, background 0.15s, border-color 0.15s;
}
.channel-card:hover .channel-epg-btn {
    opacity: 1;
    transform: translateY(0);
}
.channel-epg-btn:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}
.channel-epg-btn svg { flex-shrink: 0; }

/* Favorite heart toggle — shared base look; each context (channel-card grid
   tile vs. guide-channel grid row) positions it differently below. */
.fav-heart-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px; height: 24px;
    background: rgba(0,0,0,0.6);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 50%;
    color: var(--fg-faint);
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.fav-heart-btn:hover {
    border-color: #f87171;
    color: #f87171;
}
.fav-heart-btn.is-active {
    color: #f87171;
    border-color: rgba(248,113,113,0.5);
    background: rgba(248,113,113,0.12);
}

/* Channels grid: bottom-right of the logo tile */
.channel-logo-wrap .fav-heart-btn {
    position: absolute;
    bottom: 8px; right: 8px;
}

.channel-info {
    padding: 12px 14px 14px;
    border-top: 1px solid var(--border);
}
.channel-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--fg);
    margin-bottom: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.channel-now {
    font-size: 12px;
    color: var(--fg-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-bottom: 8px;
    min-height: 1.4em;
}
.channel-now-empty {
    color: var(--fg-faint);
    font-style: italic;
}

.progress-bar {
    height: 2px;
    background: var(--border);
    border-radius: 1px;
    overflow: hidden;
}
.progress-fill {
    height: 100%;
    background: var(--accent);
    transition: width 0.4s;
}

/* ============================================================
   GUIDE VIEW
   ============================================================ */

.date-strip {
    display: flex; gap: 4px;
    overflow-x: auto;
    padding-bottom: 4px;
    justify-content: space-between;
}
.date-pill {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--fg-dim);
    padding: 8px 14px;
    border-radius: var(--radius);
    text-align: center;
    transition: all 0.15s;
    min-width: 64px;
    display: flex; flex-direction: column; gap: 2px;
}
.date-pill:hover { color: var(--fg); border-color: var(--border-hi); }
.date-pill.active {
    background: var(--fg);
    color: var(--bg);
    border-color: var(--fg);
}
.date-pill .day {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 20px;
    line-height: 1;
}
.date-pill .dow {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.date-pill.today {
    border-color: var(--accent);
    color: var(--accent);
}
.date-pill.today.active {
    background: var(--accent);
    color: var(--bg);
}

.guide-cat-filter {
    display: flex; flex-wrap: nowrap; gap: 6px;
    margin-bottom: 12px;
    overflow-x: auto;
    padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.guide-cat-filter::-webkit-scrollbar { display: none; }
.cat-pill {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--fg-dim);
    padding: 5px 14px;
    border-radius: 999px;
    font-size: 13px;
    transition: all 0.15s;
    white-space: nowrap;
}
.cat-pill:hover { color: var(--fg); border-color: var(--border-hi); }
.cat-pill.active {
    background: var(--fg);
    color: var(--bg);
    border-color: var(--fg);
}

.guide-layout {
    display: grid;
    grid-template-columns: 280px 1fr;
    gap: 16px;
    min-height: 600px;
}
/* Guide-only (YouTube page reuses .guide-layout without a date rail at all —
   see its own comment further down) — a third, narrow column for the date
   rail ahead of the channel list. */
.guide-layout.has-dates {
    grid-template-columns: 84px 280px 1fr;
}
.guide-dates {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow-y: auto;
    max-height: calc(100vh - 280px);
    padding: 6px;
}
/* Vertical instead of .date-strip's other use (a horizontal row — see
   .side-date-strip in the player sidebar, unaffected since this only
   targets the guide page's own copy specifically). */
.guide-dates .date-strip {
    flex-direction: column;
    overflow: visible;
    padding-bottom: 0;
}
.guide-dates .date-pill {
    width: 100%;
    min-width: 0;
    flex-direction: row;
    justify-content: center;
    gap: 6px;
}
.guide-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 280px);
}
.guide-channels {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow-y: auto;
    max-height: calc(100vh - 280px);
}
.guide-channel-row {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    transition: background 0.15s;
}
.guide-channel-row:hover { background: var(--bg-tile); }
.guide-channel-row.active {
    background: var(--bg-tile-hi);
    border-left: 2px solid var(--accent);
    padding-left: 12px;
}
.guide-channel-row .mini-logo {
    width: 40px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-tile);
    border-radius: 4px;
    flex: 0 0 auto;
}
.guide-channel-row .mini-logo img { max-width: 80%; max-height: 80%; object-fit: contain; }
.guide-channel-row .mini-name {
    font-size: 13px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
}
.guide-channel-row .mini-num {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-faint);
}

/* TV app — the guide page itself must never scroll; only the channel list
   and programme list (below) scroll independently. .view-guide's height is
   pinned to exactly what's left under the topbar + main's own top/bottom
   padding (96px combined) instead of .guide-main's calc(100vh - 280px)
   guess, so .guide-layout can flex-fill it precisely and both columns reach
   the bottom of the screen (main's own 64px bottom padding already reads as
   generous breathing room, so no extra padding is added here). */
.tv-mode .view-guide {
    height: calc(100vh - var(--topbar-h) - 96px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.tv-mode .view-guide > #guideSubnav,
.tv-mode .view-guide > .guide-cat-filter {
    flex-shrink: 0;
}
.tv-mode .guide-layout {
    flex: 1;
    min-height: 0;
}
.tv-mode .guide-main,
.tv-mode .guide-channels,
.tv-mode .guide-dates {
    max-height: none;
}
.tv-mode .view-guide .fav-heart-btn {
    display: none;
}

.guide-programmes {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow-y: auto;
    /* Fills whatever's left of .guide-main's own max-height under the date
       strip (see its comment above) instead of a second, independent
       max-height guess of its own. min-height: 0 is required for a flex
       item to be allowed to shrink below its content's natural height at
       all — without it this couldn't actually get smaller than its
       (unbounded) content, and overflow-y: auto above would never kick in. */
    flex: 1;
    min-height: 0;
    padding: 8px;
}
.programme-row {
    display: grid;
    grid-template-columns: 80px 1fr auto;
    gap: 16px;
    padding: 14px 16px;
    border-radius: var(--radius);
    border: 1px solid transparent;
    transition: border-color 0.15s, background 0.15s;
    align-items: start;
    cursor: pointer;
}
.prog-info-btn {
    align-self: center;
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 5px;
    color: var(--fg-dim);
    padding: 0;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.prog-info-btn:hover {
    background: var(--bg-tile-hi);
    border-color: var(--border-hi);
    color: var(--fg);
}
.programme-row:hover {
    background: var(--bg-tile);
    border-color: var(--border);
}
.programme-row.now {
    border-color: var(--accent);
    background: linear-gradient(90deg, var(--accent-dim), transparent 60%);
}
.programme-row.past {
    opacity: 0.85;
}
.programme-row.future {
    opacity: 0.45;
}
.programme-row.is-gap {
    opacity: 0.55;
    background: repeating-linear-gradient(
        135deg,
        transparent 0,
        transparent 8px,
        rgba(255,255,255,0.025) 8px,
        rgba(255,255,255,0.025) 16px
    );
}
.programme-row.is-gap:hover { background-color: transparent; cursor: default; }
.programme-row.is-gap .prog-title { font-style: italic; color: var(--fg-faint); font-weight: 400; }
.prog-time {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--fg-dim);
    padding-top: 2px;
}
.prog-time .now-tag {
    display: block;
    color: var(--accent);
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-top: 2px;
}
.prog-img {
    width: 100px; height: 56px;
    object-fit: cover;
    border-radius: 4px;
    background: var(--bg-tile);
}
.prog-img-placeholder {
    width: 100px; height: 56px;
    border-radius: 4px;
    background: var(--bg-tile);
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-display);
    font-style: italic;
    color: var(--fg-faint);
    font-size: 20px;
}
.prog-thumb {
    position: relative;
    flex-shrink: 0;
    line-height: 0;
}
.prog-thumb .prog-duration-badge {
    position: absolute;
    right: 6px; bottom: 6px;
    background: rgba(0,0,0,0.78);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 10px;
    line-height: normal;
    font-weight: 600;
    padding: 2px 5px;
    border-radius: 3px;
    letter-spacing: 0.02em;
}
.prog-info { min-width: 0; }
.prog-title {
    font-size: 14px;
    font-weight: 600;
    margin: 0 0 4px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.prog-meta {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    display: flex; gap: 8px; flex-wrap: wrap;
    margin-bottom: 4px;
}
.prog-meta .age { color: var(--accent); }
.prog-watch-progress {
    height: 2px;
    background: var(--border);
    border-radius: 1px;
    overflow: hidden;
    margin-top: 6px;
    max-width: 220px;
}
.prog-watch-progress-fill { height: 100%; background: var(--watched); }
.prog-desc {
    font-size: 12px;
    color: var(--fg-dim);
    line-height: 1.45;
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ============================================================
   NOW PLAYING VIEW
   ============================================================ */

.now-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 12px;
}
.now-card {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.2s, transform 0.2s;
    display: flex;
}
.now-card:hover {
    border-color: var(--border-hi);
    transform: translateY(-2px);
}
.now-card-logo {
    width: 100px;
    flex: 0 0 auto;
    background: var(--bg-elev);
    display: flex; align-items: center; justify-content: center;
    border-right: 1px solid var(--border);
}
.now-card-logo img { max-width: 70%; max-height: 60%; object-fit: contain; }
.now-card-body {
    padding: 14px 16px;
    flex: 1;
    min-width: 0;
}
.now-card-channel {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-bottom: 6px;
    display: flex; justify-content: space-between;
}
.now-card-title {
    font-size: 14px;
    font-weight: 600;
    margin: 0 0 6px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.now-card-time {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-dim);
}

/* ============================================================
   SEARCH
   ============================================================ */

.search-box {
    margin-bottom: 24px;
}
.search-box input {
    width: 100%;
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 16px 20px;
    color: var(--fg);
    font-size: 16px;
    transition: border-color 0.15s;
}
.search-box input:focus {
    outline: none;
    border-color: var(--accent);
}
/* ============================================================
   PLAYER OVERLAY
   ============================================================
   Layout: narrow channel rail | stage | EPG sidebar.
   The main app topbar (.topbar) stays visible behind/above this.
   The overlay sits below the topbar (top: var(--topbar-h)).
*/

.player-overlay {
    position: fixed;
    top: var(--topbar-h, 64px);
    left: 0; right: 0; bottom: 0;
    z-index: 100;
    background: #000;
    display: grid;
    grid-template-rows: 1fr;
    grid-template-columns: 88px 1fr 360px;
    grid-template-areas: "rail stage sidebar";
}
.player-overlay[hidden] { display: none; }
.player-overlay.is-youtube-vod {
    grid-template-columns: 1fr 360px;
    grid-template-areas: "stage sidebar";
}
.player-overlay.is-vod {
    grid-template-columns: 1fr;
    grid-template-areas: "stage";
}
/* Series episode playback (openEpisodePlayer()) is-vod too (same "on-demand,
   no channel rail" behavior as a movie), but unlike a movie it also shows
   the episodes sidebar — the plain .is-vod rule above has no "sidebar" grid
   area at all, so without this the sidebar element had nowhere valid to go
   and broke the whole grid (video/controls went invisible, audio kept
   playing). Same stage+sidebar layout is-youtube-vod already uses. */
.player-overlay.is-vod.has-episode-sidebar {
    grid-template-columns: 1fr 360px;
    grid-template-areas: "stage sidebar";
}
.player-overlay.is-fullscreen {
    top: 0;   /* cover the topbar in fullscreen */
    grid-template-columns: 1fr;
    grid-template-areas: "stage";
}
.player-overlay.is-fullscreen .player-sidebar,
.player-overlay.is-fullscreen .player-channel-rail { display: none; }

/* TV app: playback is always full-bleed — no persistent rail/sidebar column
   eating into the video regardless of content type. Both become on-demand
   overlays instead (toggled via #btnTvChannels/#btnTvSidebar — see app.js),
   floating on top of the stage with a dimming backdrop behind them rather
   than sharing the grid with it. */
.tv-mode .player-overlay {
    grid-template-columns: 1fr;
    grid-template-areas: "stage";
}
.tv-mode .player-channel-rail,
.tv-mode .player-sidebar {
    display: none;
}
.player-tv-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 60;
}
.player-tv-backdrop[hidden] { display: none; }
.tv-mode .player-channel-rail.is-open,
.tv-mode .player-sidebar.is-open {
    display: block;
    position: absolute;
    top: 0; bottom: 0;
    z-index: 61;
    box-shadow: 0 0 48px rgba(0, 0, 0, 0.7);
}
.tv-mode .player-channel-rail.is-open {
    left: 0;
    width: 240px; /* wider than the desktop 88px icon rail — readable channel
                     names matter more here since it's a temporary overlay
                     the viewer is actively browsing, not an always-visible strip */
}
.tv-mode .player-sidebar.is-open {
    right: 0;
    width: 360px;
}
/* Wider rail needs the name alongside the logo, not just the channel number
   (see .rail-num) — the desktop rail is icon-only by design (see its own
   comment elsewhere in this file), that constraint doesn't apply here. */
.tv-mode .rail-channel { flex-direction: row; align-items: center; text-align: left; gap: 10px; }
.tv-mode .rail-channel .rail-name { display: block; }
.rail-name { display: none; font-size: 13px; }

/* New player controls, TV app only — #btnTvChannels is additionally
   hidden/shown per content type directly in JS (live/catchup only; a movie
   or YouTube video has no channel rail content to show). */
.ctrl-btn.tv-only { display: none; }
.tv-mode .ctrl-btn.tv-only { display: inline-flex; }

/* TV app — no on-screen volume control at all; actual output level is the
   TV/box's own hardware volume, and app.js always forces the video element
   itself to full, unmuted volume on TV (see wireCustomControls()). */
.tv-mode #btnMute,
.tv-mode #volumeSlider {
    display: none;
}

/* Body class set while watching — hides main content but keeps topbar */
body.is-watching main { display: none; }

/* ----- Left channel rail ----- */
.player-channel-rail {
    grid-area: rail;
    background: var(--bg-elev);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 12px 0;
}

.rail-channel {
    display: flex; flex-direction: column; align-items: center;
    gap: 4px;
    padding: 10px 8px;
    cursor: pointer;
    transition: background 0.1s;
    border-left: 2px solid transparent;
    position: relative;
}
.rail-channel:hover { background: var(--bg-tile); }
.rail-channel.is-active {
    background: var(--bg-tile);
    border-left-color: var(--accent);
}
.rail-channel.is-active::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 2px;
    background: var(--accent);
    box-shadow: 0 0 12px var(--accent);
}
.rail-channel .rail-logo {
    width: 48px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: 4px;
    overflow: hidden;
}
.rail-channel.is-active .rail-logo {
    /* Active state shown via the left stripe and rail-num colour;
       no red border on the logo box itself. */
}
.rail-channel .rail-logo img {
    max-width: 90%; max-height: 90%; object-fit: contain;
}
.rail-channel .rail-logo .rail-fallback {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 18px;
    color: var(--fg-faint);
}
.rail-channel .rail-num {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    color: var(--fg-dim);
    letter-spacing: 0.04em;
}
.rail-channel.is-active .rail-num { color: var(--accent); }

/* Live badge */
.live-badge {
    background: var(--live);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 3px;
    letter-spacing: 0.1em;
    animation: livePulse 2s infinite;
    white-space: nowrap;
}
@keyframes livePulse { 50% { opacity: 0.7; } }

.player-stage {
    grid-area: stage;
    position: relative;
    background: #000;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
    cursor: default;
}
.player-overlay:not(.controls-visible):not(.is-buffering) .player-stage { cursor: none; }
#videoEl {
    width: 100%;
    height: 100%;
    background: #000;
}
#lowQualityFallback {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.player-state {
    position: absolute; inset: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 16px;
    color: var(--fg-dim);
    background: rgba(0,0,0,0.6);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.04em;
    pointer-events: none;
}
.player-state[hidden] { display: none; }
.player-state.error { color: var(--accent); }
.spinner {
    width: 32px; height: 32px;
    border: 2px solid var(--border);
    border-top-color: var(--fg);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Big center play icon, shown while paused */
.player-big-play {
    position: absolute;
    top: 50%; left: 50%;
    width: 76px; height: 76px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,0.85);
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 50%;
    color: #fff;
    /* Shadow footprint ~3x the button's own size (76px → ~228px across).
       A single box-shadow layer caps out at alpha 1, so the extra intensity
       comes from stacking several near-opaque layers on top of each other. */
    box-shadow:
        0 0 140px 144px rgba(0,0,0,0.75),
        0 0 80px 60px rgba(0,0,0,0.7),
        0 16px 48px rgba(0,0,0,0.6);
    pointer-events: none;
    z-index: 3;
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.85);
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.player-big-play.show {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}
.player-big-play svg {
    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.6));
    margin-left: 4px; /* optically center the play triangle */
}
/* display:flex above beats the browser's default [hidden]{display:none} at
   equal specificity (author stylesheet wins ties over the UA stylesheet) —
   restore it explicitly, same fix as .nn-next below. */
.player-big-play[hidden] { display: none; }
/* Don't show "paused" over a stream that's actually just loading/buffering. */
.player-overlay.is-buffering .player-big-play { display: none; }

/* ----- Custom controls ----- */
.player-controls {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 16px 24px 18px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    background: linear-gradient(0deg, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.6) 60%, transparent 100%);
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.2s, transform 0.2s;
    pointer-events: none;
}
.player-overlay.controls-visible .player-controls {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.controls-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}
.ctrl-left, .ctrl-right {
    display: flex; align-items: center; gap: 10px;
    min-width: 0;
}

/* Channel info inside controls (logo + name + num) */
.ctrl-channel {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-right: 8px;
    min-width: 0;
    max-width: 240px;
}
.ctrl-channel-logo {
    width: 36px; height: 36px;
    background: rgba(0,0,0,0.5);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
}
.ctrl-channel-logo img {
    max-width: 90%; max-height: 90%; object-fit: contain;
}
.ctrl-channel-logo.is-fallback {
    font-family: var(--font-display);
    font-style: italic;
    color: var(--fg-faint);
}
.ctrl-channel-meta { min-width: 0; }
.ctrl-channel-name {
    font-size: 14px;
    font-weight: 600;
    color: #fff;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ctrl-channel-num {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* ----- Now/Next info bar ----- */
.now-next-bar {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding-bottom: 4px;
}
.nn-current, .nn-next {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    width: 100%;
}
/* `display:flex` above beats the browser's default [hidden]{display:none} at
   equal specificity, so the "up next" row stayed visible even when hidden
   was set (e.g. via resetNowNextBar() for YouTube VOD). Restore it explicitly. */
.nn-next[hidden] { display: none; }
.nn-current::before {
    content: '●';
    color: var(--accent);
    font-size: 10px;
    flex-shrink: 0;
    align-self: flex-start;
    margin-top: 12px;
    animation: livePulse 2s infinite;
}
.nn-next {
    border-left: none;
    border-top: 1px solid rgba(255,255,255,0.08);
    padding-left: 0;
    padding-top: 8px;
    max-width: none;
    opacity: 0.85;
}
.nn-next::before {
    content: '●';
    color: var(--fg-faint);
    font-size: 8px;
    flex-shrink: 0;
    align-self: center;
}
.nn-info { min-width: 0; flex: 1; }
.nn-title-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    margin-bottom: 10px;
}
.nn-title-row .nn-title { margin-bottom: 0; min-width: 0; flex: 1; }
.nn-title-row .live-badge { flex-shrink: 0; }
/* Current YouTube chapter name — same styling as .nn-next .nn-title so it
   reads as a natural "what's playing right now within this video" line. */
.nn-current-chapter {
    font-family: var(--font-body);
    font-style: normal;
    color: var(--fg-dim);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: normal;
    margin-bottom: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.nn-current-chapter[hidden] { display: none; }
.nn-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 28px;
    line-height: 1.1;
    color: #fff;
    margin-bottom: 10px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    letter-spacing: -0.01em;
}
.nn-next .nn-title {
    font-family: var(--font-body);
    font-style: normal;
    color: var(--fg-dim);
    font-size: 14px;
    font-weight: 500;
    margin-bottom: 0;
    margin-right: 12px;
    letter-spacing: normal;
    flex: 1;
}
.nn-next .nn-time {
    flex-shrink: 0;
}
/* ----- Now/next seekbar with times before & after ----- */
.nn-seek-row {
    display: flex;
    align-items: center;
    gap: 12px;
}
.nn-time-start, .nn-time-end {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-dim);
    letter-spacing: 0.04em;
    font-variant-numeric: tabular-nums;
    min-width: 44px;
    flex-shrink: 0;
}
.nn-time-end { text-align: right; }

.nn-progress {
    position: relative;
    flex: 1;
    height: 4px;
    background: rgba(255,255,255,0.15);
    border-radius: 2px;
    overflow: visible;
}
.nn-progress-fill {
    height: 100%;
    background: var(--accent);
    transition: width 1s linear;
    border-radius: 2px;
}
.nn-progress-fill.has-playhead {
    background: linear-gradient(to right,
        var(--accent)         var(--played-pct, 0%),
        rgba(255,59,48,0.32)  var(--played-pct, 0%)
    );
}
.nn-time {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-faint);
    letter-spacing: 0.04em;
    font-variant-numeric: tabular-nums;
}

/* ----- Player badges (quality + LIVE in topbar) ----- */
.player-badges { display: flex; align-items: center; gap: 8px; }
.quality-badge {
    background: rgba(255,255,255,0.1);
    color: var(--fg);
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 3px;
    letter-spacing: 0.08em;
    border: 1px solid rgba(255,255,255,0.15);
}

.ctrl-btn {
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.12);
    color: var(--fg);
    width: 40px; height: 40px;
    border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    transition: background 0.15s, border-color 0.15s;
    padding: 0;
}
.ctrl-btn:hover {
    background: rgba(255,255,255,0.15);
    border-color: rgba(255,255,255,0.25);
}

/* ----- Channel zap toast ----- */
.zap-toast {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%) scale(0.95);
    background: rgba(0,0,0,0.85);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 12px;
    padding: 24px 36px;
    text-align: center;
    z-index: 50;
    opacity: 0;
    transition: opacity 0.2s, transform 0.2s;
    pointer-events: none;
}
.zap-toast.show {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}
.zap-toast .zap-num {
    font-family: var(--font-mono);
    font-size: 14px;
    color: var(--fg-faint);
    letter-spacing: 0.1em;
    margin-bottom: 4px;
}
.zap-toast .zap-name {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 32px;
    color: #fff;
    line-height: 1;
}

#volumeSlider {
    width: 90px;
    height: 4px;
    background: rgba(255,255,255,0.2);
    border-radius: 2px;
    outline: none;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
}
#volumeSlider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 12px; height: 12px;
    background: var(--fg);
    border-radius: 50%;
    cursor: pointer;
}
#volumeSlider::-moz-range-thumb {
    width: 12px; height: 12px;
    background: var(--fg);
    border: none;
    border-radius: 50%;
    cursor: pointer;
}

/* ----- Settings overlay (quality / audio / subtitles) ----- */
.settings-overlay {
    position: absolute;   /* covers the video stage only, not the rail/sidebar */
    inset: 0;
    z-index: 40;
    background: rgba(8,8,11,0.88);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex;
    flex-direction: column;
    animation: fadeIn 0.15s ease-out;
}
.settings-overlay[hidden] { display: none; }

.settings-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
}
.settings-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 20px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
    font-family: var(--font-display);
    font-style: italic;
    font-size: 22px;
    color: #fff;
    flex-shrink: 0;
}
.settings-close-btn {
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.12);
    color: var(--fg);
    width: 32px; height: 32px;
    border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    transition: background 0.15s, border-color 0.15s;
    padding: 0;
}
.settings-close-btn:hover {
    background: rgba(255,255,255,0.15);
    border-color: rgba(255,255,255,0.25);
}

.settings-columns {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 16px;
    padding: 16px 20px;
    overflow-y: auto;
    align-content: center;
    width: 60%;
    margin: 0 auto;
}
.settings-col {
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.settings-col-title {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    color: var(--fg-faint);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: 6px 10px 8px;
}
.settings-col-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Info overlay body — reuses the .pd-* classes from the full /programme/:id
   page (see renderProgrammeDetail()), just scaled down to fit a side panel
   instead of a full-width page. */
.info-overlay-body {
    flex: 1;
    overflow-y: auto;
    padding: 20px 24px 28px;
    max-width: 640px;
    margin: 0 auto;
    width: 100%;
}
.info-overlay-body .pd-hero { aspect-ratio: 16 / 9; margin-bottom: 16px; border-radius: 10px 10px 0 0; }
.info-overlay-body .pd-hero-placeholder { font-size: 56px; }
.info-overlay-body .pd-title { font-size: 26px; margin: 4px 0 6px; }
.info-overlay-body .pd-orig-title { font-size: 14px; margin-bottom: 6px; }
.info-overlay-body .pd-meta { margin-bottom: 16px; }
.info-overlay-body .pd-actions { margin-bottom: 16px; }
.info-overlay-body .pd-desc { margin-bottom: 0; }
/* YouTube descriptions use real newlines rather than EPG's literal <br>
   tags — preserve them visually without needing to convert to markup. */
.info-overlay-body .pd-desc-pre { white-space: pre-line; }

.menu-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 16px;
    background: transparent;
    border: none;
    color: var(--fg);
    padding: 10px 12px;
    border-radius: 5px;
    text-align: left;
    cursor: pointer;
    transition: background 0.1s;
    font-size: 13px;
}
.menu-item:hover { background: rgba(255,255,255,0.08); }
.menu-item.active {
    background: var(--accent-dim);
    color: var(--fg);
}
.menu-label {
    font-weight: 600;
}
.menu-sub {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.04em;
}
.menu-empty {
    padding: 12px;
    color: var(--fg-faint);
    font-size: 12px;
    font-family: var(--font-mono);
    text-align: center;
}

.player-sidebar {
    grid-area: sidebar;
    background: var(--bg);
    border-left: 1px solid var(--border);
    padding: 0 24px 32px;
    overflow-y: auto;
}
.now-block {
    padding-bottom: 24px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 24px;
}
.now-block .now-img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 8px;
    background: var(--bg-tile);
    margin-bottom: 14px;
    display: block;
}
.now-block .now-img-placeholder {
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 8px;
    background: var(--bg-tile);
    margin-bottom: 14px;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-display);
    font-style: italic;
    font-size: 56px;
    color: var(--fg-faint);
}
.now-block .label {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--accent);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-bottom: 8px;
}
.now-block h4 {
    font-size: 18px;
    margin: 0 0 6px;
    font-weight: 700;
}
.now-block .meta {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-dim);
    margin-bottom: 12px;
    letter-spacing: 0.02em;
}
.now-block .meta .age {
    color: var(--accent);
    margin-right: 4px;
}
.now-block .desc {
    font-size: 13px;
    color: var(--fg-dim);
    line-height: 1.5;
    margin: 0;
}
.now-block .sidebar-progress {
    height: 3px;
    background: var(--border);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: 12px;
}
.now-block .sidebar-progress-fill {
    height: 100%;
    background: var(--accent);
}
.day-block {
    margin-top: 24px;
}
.day-block h3 {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    color: var(--fg-faint);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin: 0 0 12px;
}
/* Season divider inside the episodes sidebar (see renderEpisodesSidebar()) */
.sidebar-season-title {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    color: var(--fg-faint);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin: 18px 0 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
}
.sidebar-season-title:first-child { margin-top: 0; }
.side-date-strip-wrap {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 4px;
    background: var(--bg);
    margin: 0 -18px 12px;
    padding: 4px 0 8px;
}
.side-date-strip-wrap[hidden] { display: none; }
.side-date-strip {
    flex: 1;
    min-width: 0;
    margin: 0;
    scrollbar-width: none;
}
.side-date-strip::-webkit-scrollbar { display: none; }
.side-scroll-btn {
    flex: 0 0 auto;
    display: none;   /* shown from the "tablet and up" breakpoint below */
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--bg-tile);
    border: 1px solid var(--border);
    color: var(--fg-dim);
    cursor: pointer;
    padding: 0;
    transition: background 0.15s, color 0.15s, opacity 0.15s;
}
.side-scroll-btn:hover { background: var(--bg-tile-hi); color: var(--fg); }
.side-scroll-btn.is-hidden { opacity: 0; pointer-events: none; }
@media (min-width: 601px) {
    .side-scroll-btn { display: flex; }
}
.day-item {
    display: grid;
    grid-template-columns: 56px 1fr;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
    align-items: start;
}
.day-item.yt-side-item {
    grid-template-columns: 96px 1fr;
}
.day-item:last-child { border-bottom: none; }
.day-item.is-past   { opacity: 0.45; }
.day-item.is-now    { background: rgba(255, 71, 87, 0.08); margin: 0 -12px; padding: 10px 12px; border-radius: 6px; border-bottom: none; }
.day-item.is-now + .day-item { border-top: 1px solid var(--border); margin-top: 6px; }
.day-item.is-gap    { opacity: 0.35; font-style: italic; }

.day-item .t {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-dim);
    padding-top: 2px;
}
.day-item.is-now .t { color: var(--accent); font-weight: 600; }
.day-item .body { min-width: 0; }
.epg-live-badge { font-size: 9px; padding: 2px 6px; margin-bottom: 3px; display: inline-block; margin-right: 5px; }
.day-item .title {
    font-size: 13px;
    color: var(--fg);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    margin-bottom: 3px;
}
/* Keeps the live badge and title on the same line — .title is a block-level
   (-webkit-box) element, so as a plain sibling it would otherwise always
   start on its own line regardless of the badge being inline-block. */
.day-item-title-row {
    display: flex;
    align-items: flex-start;
    min-width: 0;
    margin-bottom: 3px;
}
.day-item-title-row .epg-live-badge,
.day-item-title-row .title {
    margin-bottom: 0;
}
.day-item .sub {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.04em;
}
.day-item .sub.is-watched { color: var(--watched); }

/* ============================================================
   UTILITIES
   ============================================================ */

.empty-hint {
    padding: 60px 24px;
    text-align: center;
    color: var(--fg-faint);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.04em;
}

/* ============================================================
   SCROLLBARS — one unified themed treatment for every scrollable
   container site-wide (Firefox via scrollbar-width/-color, WebKit via
   ::-webkit-scrollbar). Every horizontally-scrolling row used to
   reimplement this individually with its own slightly different width/
   color/radius (.home-scroll-row, .search-history, .subnav-row, .date-strip,
   .player-channel-rail, ...) — consolidated to just this one block instead.
   An element that wants no visible scrollbar at all (.group-filter,
   .guide-cat-filter, .side-date-strip — pill-strip rows with their own
   scroll affordance buttons) still opts out explicitly where it's defined;
   that's a deliberate design choice, not something to unify away. */
:root { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-hi); }
/* TV app — no pointer to drag a thumb with, and D-pad-driven scrollIntoView
   already keeps whatever's focused on screen, so a visible scrollbar is pure
   clutter on a TV. Overrides the themed treatment above everywhere at once
   rather than each scroll container's own opt-out. */
.tv-mode { scrollbar-width: none; }
.tv-mode ::-webkit-scrollbar { display: none; width: 0; height: 0; }

/* Fade-in for view transitions */
.view {
    animation: fadeIn 0.25s ease-out;
}
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1200px) {
    .clock { display: none; }
}
@media (max-width: 900px) {
    .clock { display: inline; }
    .brand-sub { display: none; }
    .primary-nav { justify-self: end; }
    main { padding: 24px 16px 64px; }
    .view-title h1 { font-size: 36px; }
    .guide-layout,
    .guide-layout.has-dates { grid-template-columns: 1fr; }

    /* Dates back to a horizontal strip — a narrow vertical rail only makes
       sense with the width a desktop sidebar has. */
    .guide-dates {
        max-height: none;
        overflow: visible;
        padding: 0;
        background: none;
        border: none;
    }
    .guide-dates .date-strip {
        flex-direction: row;
        overflow-x: auto;
        padding-bottom: 4px;
    }
    .guide-dates .date-pill {
        width: auto;
        flex-direction: column;
    }

    /* Channel rail — horizontal scroll bar of logos only */
    .guide-channels {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        gap: 4px;
        max-height: none;
        overflow-x: auto;
        overflow-y: hidden;
        padding: 10px 8px;
        -webkit-overflow-scrolling: touch;
    }
    .guide-channels .guide-channel-row {
        flex: 0 0 auto;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 6px;
        border-bottom: none;
        border-radius: 10px;
    }
    .guide-channels .guide-channel-row.active {
        background: var(--bg-tile-hi);
        border-left: none;
        padding-left: 6px;
        box-shadow: inset 0 0 0 2px var(--accent);
    }
    .guide-channels .mini-logo { width: 52px; height: 40px; }
    .guide-channels .gc-name,
    .guide-channels .gc-now-row,
    .guide-channels .gc-next-row,
    .guide-channels .fav-heart-btn { display: none; }

    /* Selected-channel summary card — same logo/name/now/upcoming layout as the
       channel rail rows, shown above the EPG since the rail itself is logo-only now. */
    #guideSelectedChannel:not([hidden]) {
        display: grid;
        background: var(--bg-elev);
        border: 1px solid var(--border);
        border-radius: 12px;
        margin-bottom: 12px;
        cursor: default;
    }
    #guideSelectedChannel .mini-logo { width: 52px; height: 38px; }

    .channel-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
    .now-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
    .home-featured-card { flex-basis: 200px; }

    /* Nav + clock/profile collapse into a hamburger dropdown at tablet
       widths and below. */
    .topbar-inner { padding: 0 16px; gap: 16px; grid-template-columns: auto 1fr; }
    .hamburger-btn { display: flex; }
    .mobile-menu {
        display: flex;
        flex-direction: column;
        position: absolute;
        top: 100%; left: 0; right: 0;
        gap: 4px;
        padding: 10px 12px 14px;
        background: rgba(10,10,11,0.97);
        backdrop-filter: blur(20px) saturate(160%);
        -webkit-backdrop-filter: blur(20px) saturate(160%);
        border-bottom: 1px solid var(--border);
        opacity: 0;
        visibility: hidden;
        transform: translateY(-8px);
        pointer-events: none;
        transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
    }
    .mobile-menu.open {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
        pointer-events: auto;
        transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0s;
    }
    .mobile-menu .primary-nav { flex-direction: column; gap: 2px; }
    .mobile-menu .nav-pill { text-align: left; padding: 10px 14px; font-size: 13px; }
    .mobile-menu .topbar-right {
        justify-content: space-between;
        margin-top: 6px;
        padding: 12px 0 0 14px;
        border-top: 1px solid var(--border);
        font-size: 12px;
    }

    .player-overlay {
        grid-template-columns: 1fr;
        grid-template-areas: "stage" "sidebar";
        grid-template-rows: auto 1fr;
    }
    .player-channel-rail { display: none; }   /* hidden on mobile */
    .player-stage { aspect-ratio: 16/9; }
    .player-sidebar { border-left: none; border-top: 1px solid var(--border); }
}

/* ----- Phones ----- */
@media (max-width: 600px) {
    .brand-name { display: none; }   /* keep just the mark to save space */

    main { padding: 16px 12px 48px; }
    .view-title { flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
    .view-title h1 { font-size: 28px; }
    .view-header { margin-bottom: 20px; }

    .channel-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
    .epg-category-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
    .now-grid { grid-template-columns: 1fr; }
    .home-section { margin-bottom: 32px; }
    .topbar-inner { padding: 0 12px; gap: 10px; }
    .home-section-title { font-size: 22px; }
    .home-scroll-row > * { flex-basis: 180px; }
    .home-scroll-btn { width: 40px; }
    .home-featured-card { flex-basis: 180px; }

    /* Programme rows: drop the thumbnail, tighten the time column */
    .programme-row { grid-template-columns: 52px 1fr auto; gap: 10px; padding: 10px 12px; }
    .prog-info-btn { width: 26px; height: 26px; }
    .prog-img, .prog-img-placeholder { display: none; }
    .skel-prog { grid-template-columns: 52px 1fr; }
    .skel-prog-img { display: none; }
    .prog-time { font-size: 11px; }

    /* YouTube video rows have no time column — keep a small thumbnail instead of hiding it */
    .programme-row.yt-video-row { grid-template-columns: 56px 1fr; }
    .yt-video-row .prog-img { display: block; width: 56px; height: 34px; }
    .yt-video-row .prog-img-placeholder { display: flex; width: 56px; height: 34px; }

    .date-strip { gap: 3px; }
    .date-pill { min-width: 52px; padding: 6px 10px; }

    .search-box input { padding: 12px 14px; font-size: 15px; }

    /* Programme detail view */
    .pd-hero { aspect-ratio: 16 / 9; border-radius: 10px 10px 0 0; margin-bottom: 16px; }
    .pd-hero-placeholder { font-size: 48px; }
    .pd-title { font-size: 30px; margin: 6px 0 4px; }
    .pd-orig-title { font-size: 15px; }
    .pd-desc { font-size: 14px; margin-bottom: 24px; }
    .pd-actions { margin-bottom: 20px; }
    .pd-btn { padding: 9px 14px; font-size: 12px; }

    /* Player stage + controls */
    .player-sidebar { padding: 16px 16px 24px; }
    .now-block .now-img-placeholder { font-size: 36px; }
    .player-controls { padding: 10px 12px 12px; gap: 8px; }
    .controls-row { flex-wrap: wrap; row-gap: 8px; gap: 10px; }
    .ctrl-left, .ctrl-right { gap: 6px; }
    .ctrl-btn { width: 34px; height: 34px; }
    .ctrl-btn.ctrl-skip { width: 30px; }
    .ctrl-btn.catchup-btn { width: 30px; }
    .ctrl-channel { display: none; }
    .ctrl-channel-logo { width: 30px; height: 30px; }
    .ctrl-channel-name { font-size: 12px; }
    .provider-logo { display: none; }
    .nn-title { font-size: 18px; margin-bottom: 6px; }
    .nn-title-row { margin-bottom: 6px; }
    .now-next-bar { gap: 4px; }
    .nn-next { padding-top: 6px; }

    .health-panel { width: auto; max-width: calc(100vw - 32px); left: 16px; right: 16px; top: 76px; }
    .zap-toast { padding: 18px 24px; }
    .zap-toast .zap-name { font-size: 24px; }

    /* Settings overlay — stack the 3 columns instead of cramming them side by side */
    .settings-panel-header { padding: 14px 16px; font-size: 18px; }
    .settings-columns { grid-template-columns: 1fr; gap: 14px; padding: 12px 16px; }

    /* Auth */
    .login-card { padding: 28px 20px; border-radius: 12px; }
    .login-title { font-size: 32px; }
    .login-brand { margin-bottom: 24px; }
    .modal-backdrop { padding: 16px; }
    .modal { padding: 20px; }
}

/* ============================================================
   SKELETONS
   ============================================================ */

@keyframes skelShimmer {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}

.skel {
    pointer-events: none;
}

.skel-line, .skel-logo, .skel-progress, .skel-prog-img,
.skel-now-logo {
    background: linear-gradient(90deg,
        var(--bg-tile) 0%,
        var(--bg-tile-hi) 50%,
        var(--bg-tile) 100%);
    background-size: 200% 100%;
    animation: skelShimmer 1.4s ease-in-out infinite;
    border-radius: 3px;
}

.skel-line { height: 12px; margin: 6px 0; }

.skel-channel {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex; flex-direction: column;
}
.skel-channel .skel-logo {
    aspect-ratio: 16/10;
    border-radius: 0;
    border-bottom: 1px solid var(--border);
}
.skel-channel .skel-info {
    padding: 14px;
}
.skel-line-name { width: 60%; height: 13px; }
.skel-line-now  { width: 85%; height: 11px; }
.skel-progress  {
    height: 2px;
    margin-top: 10px;
    width: 100%;
}

.skel-now {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
}
.skel-now-logo {
    width: 100px;
    flex: 0 0 auto;
    border-right: 1px solid var(--border);
    border-radius: 0;
}
.skel-now-info {
    padding: 14px 16px;
    flex: 1;
}
.skel-line-channel { width: 40%; height: 9px; }
.skel-line-title { width: 75%; height: 13px; margin-top: 8px; }
.skel-line-time { width: 50%; height: 11px; margin-top: 8px; }

.skel-prog {
    display: grid;
    grid-template-columns: 80px 100px 1fr;
    gap: 16px;
    padding: 14px 16px;
    align-items: start;
}
.skel-prog .skel-line-time { width: 80px; height: 11px; }
.skel-prog-img {
    width: 100px; height: 56px;
    border-radius: 4px;
}
.skel-prog-body { min-width: 0; }
.skel-prog-body .skel-line-title { width: 70%; height: 13px; }
.skel-prog-body .skel-line-meta { width: 50%; height: 10px; }
.skel-prog-body .skel-line-desc { width: 95%; height: 11px; }

/* ============================================================
   SEARCH HISTORY
   ============================================================ */

.search-history {
    display: flex; align-items: center; flex-wrap: nowrap;
    gap: 6px;
    margin: -14px 0 24px;
    overflow-x: auto;
    padding-bottom: 4px; /* room for the (unified, see top of file) scrollbar without clipping pill borders */
}
.search-history-pill,
.search-history-clear {
    flex-shrink: 0;
}
.search-history-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-tile);
    color: var(--fg-dim);
    border: 1px solid var(--border);
    padding: 6px 8px 6px 12px;
    border-radius: 99px;
    font-size: 12px;
    font-weight: 500;
    transition: all 0.15s;
}
.search-history-pill:hover { color: var(--fg); border-color: var(--border-hi); }
.search-history-pill-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px; height: 16px;
    border-radius: 50%;
    color: var(--fg-faint);
    line-height: 1;
}
.search-history-pill-remove:hover { color: var(--fg); background: var(--bg-hover, rgba(128,128,128,0.2)); }
.search-history-clear {
    background: transparent;
    color: var(--fg-faint);
    border: 1px solid transparent;
    padding: 6px 10px;
    border-radius: 99px;
    font-size: 12px;
    font-weight: 500;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.search-history-clear:hover { color: var(--fg-dim); }

/* ============================================================
   PROGRAMME DETAIL VIEW
   ============================================================ */

.view-programme #programmeDetail,
.view-programme #youtubeDetail,
.view-programme #vodDetail {
    max-width: 960px;
    margin: 0 auto;
}

.pd-hero {
    width: 100%;
    aspect-ratio: 16 / 7;
    border-radius: 16px 16px 0 0;
    overflow: hidden;
    margin-bottom: 24px;
    position: relative;
    background: var(--bg-tile);
}
.pd-hero img {
    width: 100%; height: 100%; object-fit: cover;
    display: block;
}
.pd-hero::after {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(0deg, var(--bg) 0%, transparent 30%, transparent 80%, rgba(0,0,0,0.4) 100%);
    pointer-events: none;
}
.pd-hero .section-back-btn {
    position: absolute;
    top: 16px; left: 16px;
    z-index: 2;
}
.pd-hero-placeholder {
    width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-display);
    font-style: italic;
    color: var(--fg-faint);
    font-size: 96px;
}

.pd-meta-row {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}
.pd-provider-logo {
    margin-left: auto;
}
.pd-badge {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 700;
    padding: 4px 10px;
    border-radius: 3px;
    letter-spacing: 0.12em;
}
.pd-badge-live    { background: var(--accent); color: #fff; animation: livePulse 2s infinite; }
.pd-badge-upcoming { background: var(--bg-tile-hi); color: var(--fg); border: 1px solid var(--border-hi); }
.pd-badge-past     { background: var(--bg-tile); color: var(--fg-faint); border: 1px solid var(--border); }

.pd-channel-link {
    color: var(--fg-dim);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: color 0.15s;
}
.pd-channel-link:hover { color: var(--fg); }
.pd-channel-name { color: var(--fg); font-weight: 600; }
.pd-channel-num { color: var(--fg-faint); }

.pd-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 56px;
    line-height: 1.05;
    letter-spacing: -0.02em;
    margin: 8px 0 6px;
    color: var(--fg);
}
.pd-orig-title {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 18px;
    color: var(--fg-dim);
    margin-bottom: 10px;
}
.pd-meta {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--fg-faint);
    letter-spacing: 0.02em;
    margin-bottom: 24px;
}

.pd-actions {
    display: flex; gap: 10px;
    margin-bottom: 28px;
    flex-wrap: wrap;
}
.pd-btn {
    background: var(--bg-tile-hi);
    color: var(--fg);
    border: 1px solid var(--border-hi);
    padding: 10px 20px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
    transition: background 0.15s, border-color 0.15s;
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.pd-btn:hover { background: var(--bg-elev); border-color: var(--fg-faint); }
.pd-btn-primary {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
}
.pd-btn-primary:hover { background: #ff5447; border-color: #ff5447; }

.pd-btn-primary-outline {
    color: #fff;
    border-color: var(--accent);
    border-width: 3px;
    background: transparent;
}
.pd-btn-primary-outline:hover { background: #ff5447; border-color: #ff5447; }

.pd-btn-ghost {
    background: transparent;
    border-color: var(--border);
}

/* Watchlist toggle — "saved" state (see watchlistToggleButton()) */
.pd-btn-active {
    background: rgba(248,113,113,0.12);
    border-color: rgba(248,113,113,0.5);
    color: #f87171;
}
.pd-btn-active:hover {
    background: rgba(248,113,113,0.2);
    border-color: #f87171;
}

.pd-desc {
    font-size: 15px;
    line-height: 1.6;
    color: var(--fg-dim);
    margin: 0 0 36px;
}

.pd-section-title {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    color: var(--fg-faint);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin: 24px 0 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border);
}

/* ----- Series detail (/series/:id) — every season's episodes, grouped
   under a .pd-section-title per season, each laid out as a horizontal
   .home-scroll-row (see wrapScrollRow() in app.js) rather than a grid.
   Clicking an episode jumps straight into playback (see episodeCard() /
   openEpisodePlayer() in app.js). ----- */
.episode-card {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: transform 0.2s, border-color 0.2s;
}
.episode-card:hover {
    transform: translateY(-2px);
    border-color: var(--border-hi);
}
.episode-card-banner {
    aspect-ratio: 16 / 9;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-tile-hi);
    position: relative;
}
.episode-card-info {
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.episode-card-num {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.episode-card-title {
    font-size: 13px;
    font-weight: 500;
    color: var(--fg);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prog-detail-skel .skel-line {
    background: linear-gradient(90deg,
        var(--bg-tile) 0%,
        var(--bg-tile-hi) 50%,
        var(--bg-tile) 100%);
    background-size: 200% 100%;
    animation: skelShimmer 1.4s ease-in-out infinite;
    border-radius: 3px;
}

/* ============================================================
   STREAM HEALTH PANEL
   ============================================================ */

.health-panel {
    position: absolute;
    top: 100px;
    right: 24px;
    width: 320px;
    background: rgba(10,10,11,0.92);
    backdrop-filter: blur(20px) saturate(160%);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    border: 1px solid var(--border-hi);
    border-radius: 10px;
    padding: 14px 16px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-dim);
    z-index: 30;
    box-shadow: 0 20px 60px rgba(0,0,0,0.6);
}
.hp-header {
    font-size: 10px;
    font-weight: 700;
    color: var(--accent);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    padding-bottom: 10px;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: baseline;
}
.hp-hint {
    color: var(--fg-faint);
    font-weight: 400;
    letter-spacing: 0.04em;
    text-transform: none;
    font-size: 9px;
}
.hp-row {
    display: flex;
    justify-content: space-between;
    padding: 4px 0;
    gap: 12px;
}
.hp-k {
    color: var(--fg-faint);
    letter-spacing: 0.04em;
}
.hp-v {
    color: var(--fg);
    text-align: right;
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 180px;
}
.hp-v.hp-warn { color: var(--rec); }
.hp-v.hp-url {
    font-size: 9px;
    color: var(--fg-dim);
}

/* ============================================================
   SUBTITLE BUTTON STATE
   ============================================================ */

.ctrl-btn.active {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

/* ============================================================
   CATCHUP CONTROLS
   ============================================================ */

.ctrl-btn.catchup-btn {
    /* icon-only, no text — same width as standard buttons */
    width: 36px;
    padding: 0;
    gap: 0;
}
.ctrl-btn.catchup-btn .live-dot {
    color: var(--accent);
    font-size: 14px;
    animation: livePulse 2s infinite;
}
.ctrl-btn.catchup-btn:hover {
    background: rgba(255,255,255,0.15);
}

/* ±30s skip buttons */
.ctrl-btn.ctrl-skip {
    position: relative;
    width: 36px;
}
.ctrl-btn.ctrl-skip .skip-label {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-size: 8px;
    font-weight: 700;
    color: var(--fg);
    padding-top: 2px;
    pointer-events: none;
    letter-spacing: 0;
}

/* Seekable progress bar */
.nn-progress.seekable {
    cursor: pointer;
    height: 6px;  /* taller hit area */
    transition: height 0.15s;
}
.nn-progress.seekable:hover {
    height: 8px;
}
.nn-progress.seekable .nn-progress-fill {
    transition: width 0.4s linear;
}

/* Playhead marker — shows current playback position when scrubbed back */
.nn-progress-marker {
    position: absolute;
    top: 50%;
    width: 12px;
    height: 12px;
    background: #fff;
    border: 2px solid var(--accent);
    border-radius: 50%;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 0 2px rgba(0,0,0,0.4);
    pointer-events: none;
    transition: left 0.4s linear;
}
.nn-progress {
    position: relative;
}
.nn-seek-tooltip {
    position: absolute;
    bottom: calc(100% + 8px);
    transform: translateX(-50%);
    background: rgba(0,0,0,0.82);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 12px;
    padding: 3px 8px;
    border-radius: 4px;
    pointer-events: none;
    white-space: nowrap;
}

/* SponsorBlock segment markers overlaid on the seek bar (YouTube VOD) */
.nn-sponsor-markers {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.nn-sponsor-marker {
    position: absolute;
    top: 0;
    bottom: 0;
    opacity: 0.85;
    border-radius: 1px;
}

/* YouTube chapter dividers (parsed from the video description) — thin
   separators between chapters, drawn on top of the sponsor markers. */
.nn-chapter-markers {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.nn-chapter-divider {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background: rgba(255,255,255,0.85);
    box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
}

/* SponsorBlock manual-skip button — floats over the stage, independent of
   controls visibility, so it stays reachable even if the mouse is idle.
   Sits just above the controls panel when it's visible, and drops closer
   to the bottom edge once the controls fade out. */
.sponsor-skip-btn {
    position: absolute;
    right: 24px;
    bottom: 32px;
    z-index: 5;
    padding: 10px 16px;
    background: rgba(20,20,20,0.92);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.25);
    border-radius: 6px;
    font-family: var(--font-display, inherit);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: bottom 0.2s, background 0.15s, transform 0.15s;
}
.sponsor-skip-btn:hover {
    background: rgba(40,40,40,0.96);
    transform: translateY(-1px);
}
.player-overlay.controls-visible .sponsor-skip-btn {
    bottom: 168px;
}

/* SponsorBlock auto-skip notice — brief, bottom-right of the stage, offset
   above the manual-skip button (same responsive bottom shift) so the two
   never overlap if both happen to be visible at once. */
.sponsor-skip-toast {
    --sponsor-color: #00d400;
    position: absolute;
    right: 24px;
    bottom: 84px;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px 9px 12px;
    background: rgba(20,20,20,0.92);
    border: 1px solid rgba(255,255,255,0.15);
    border-left: 3px solid var(--sponsor-color);
    border-radius: 6px;
    color: #fff;
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.02em;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transform: translateX(12px);
    transition: opacity 0.2s, transform 0.2s, bottom 0.2s;
}
.sponsor-skip-toast.show {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(0);
}
.player-overlay.controls-visible .sponsor-skip-toast {
    bottom: 220px;
}
.sponsor-unskip-btn {
    padding: 5px 10px;
    background: rgba(255,255,255,0.12);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.25);
    border-radius: 4px;
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 0.15s;
}
.sponsor-unskip-btn:hover {
    background: rgba(255,255,255,0.22);
}

/* ============================================================
   AUTH — login overlay, user badge, password modal
   ============================================================ */

body.auth-locked {
    overflow: hidden;
}
body.auth-locked .topbar,
body.auth-locked main {
    pointer-events: none;
    filter: blur(8px) brightness(0.4);
}

.login-overlay {
    position: fixed; inset: 0; z-index: 200;
    background: radial-gradient(ellipse at center, rgba(15,15,18,0.96), rgba(8,8,10,0.99));
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
    animation: fadeIn 0.3s ease-out;
}
.login-overlay[hidden] { display: none; }

.login-card {
    background: var(--bg-elev);
    border: 1px solid var(--border-hi);
    border-radius: 16px;
    padding: 40px 36px;
    width: 100%;
    max-width: 400px;
    box-shadow: 0 32px 80px rgba(0,0,0,0.6);
}

.login-brand {
    display: flex; align-items: baseline; gap: 8px;
    font-family: var(--font-display);
    font-size: 22px;
    font-style: italic;
    margin-bottom: 22px;
}
.login-mark { color: var(--accent); font-size: 24px; font-style: normal; width: 100%; }
.login-name { font-weight: 400; }

.login-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 40px;
    line-height: 1;
    letter-spacing: -0.02em;
    margin-top: 0;
    margin-bottom: 24px;
    text-align: center;
}
.login-sub {
    color: var(--fg-dim);
    font-size: 13px;
    margin: 0 0 28px;
}

.login-form { display: flex; flex-direction: column; gap: 16px; }
.login-field { display: flex; flex-direction: column; gap: 6px; }
.login-field span {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.login-field input {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px 14px;
    color: var(--fg);
    font-size: 15px;
    font-family: inherit;
    transition: border-color 0.15s;
}
.login-field input:focus {
    outline: none;
    border-color: var(--accent);
}
.login-field input:autofill {
    background: var(--bg-tile);
}

.login-error {
    background: var(--accent-dim);
    border: 1px solid var(--accent);
    color: var(--fg);
    padding: 10px 12px;
    border-radius: 6px;
    font-size: 13px;
}

/* TV app only — code-based login instead of the email/password form above
   (see .tv-mode rules below and showLoginScreen()/wireTvLoginForm() in
   app.js). Hidden by default; .tv-login-form only actually shows when
   .tv-mode is set, at which point the normal form hides instead. */
.tv-login-form { display: none; }
.tv-mode #loginForm { display: none; }
.tv-mode .tv-login-form { display: flex; }
.tv-login-hint {
    margin: 0 0 4px;
    font-size: 13px;
    color: var(--fg-dim);
    line-height: 1.5;
}
.login-field input.tv-login-pin-input {
    font-family: var(--font-mono);
    font-size: 28px;
    letter-spacing: 0.3em;
    text-align: center;
}

.login-submit {
    background: var(--accent);
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 14px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background 0.15s, opacity 0.15s;
    margin-top: 8px;
}
.login-submit:hover:not(:disabled) { background: #ff5447; }
.login-submit:disabled { opacity: 0.6; cursor: wait; }

.login-footnote {
    text-align: center;
    margin: 24px 0 0;
    font-size: 12px;
    color: var(--fg-faint);
    font-family: var(--font-mono);
    letter-spacing: 0.02em;
}

/* User badge in topbar */
.user-badge-btn {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0;
}
.user-badge-avatar {
    display: flex; align-items: center; justify-content: center;
    width: 32px; height: 32px;
    background: var(--accent);
    color: #fff;
    border-radius: 50%;
    font-family: var(--font-display);
    font-style: italic;
    font-size: 16px;
    font-weight: 600;
    transition: transform 0.15s;
}
.user-badge-btn:hover .user-badge-avatar { transform: scale(1.08); }

@keyframes menuPop {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.user-menu {
    position: fixed;
    z-index: 150;
    min-width: 220px;
    background: rgba(20,20,24,0.96);
    backdrop-filter: blur(20px) saturate(160%);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    border: 1px solid var(--border-hi);
    border-radius: 10px;
    padding: 6px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.6);
    animation: menuPop 0.12s ease-out;
}
.user-menu-header {
    padding: 12px 12px 14px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 6px;
}
.user-menu-email {
    font-size: 13px;
    font-weight: 600;
    color: var(--fg);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.user-menu-role {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-top: 2px;
}
.tv-pin-box {
    padding: 10px 12px 14px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 6px;
}
.tv-pin-label {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 6px;
}
.tv-pin-code {
    font-family: var(--font-mono);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--fg);
}
.tv-pin-expiry {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-dim);
    margin-top: 4px;
}
.user-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    color: var(--fg);
    padding: 10px 12px;
    border-radius: 5px;
    font-size: 13px;
    cursor: pointer;
    transition: background 0.1s;
    font-family: inherit;
    text-decoration: none;
}
.user-menu-item:hover { background: rgba(255,255,255,0.08); }
.user-menu-item.user-menu-danger { color: var(--accent); }

/* Password change modal */
.modal-backdrop {
    position: fixed; inset: 0; z-index: 250;
    background: rgba(0,0,0,0.75);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
    animation: fadeIn 0.2s;
}
.modal {
    background: var(--bg-elev);
    border: 1px solid var(--border-hi);
    border-radius: 12px;
    padding: 28px;
    max-width: 380px;
    width: 100%;
}
.modal h3 {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 28px;
    margin: 0 0 20px;
    line-height: 1;
}
.pw-modal label {
    display: flex; flex-direction: column; gap: 6px;
    margin-bottom: 14px;
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.pw-modal label input {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 10px 12px;
    color: var(--fg);
    font-size: 14px;
    font-family: var(--font-body);
    text-transform: none;
    letter-spacing: normal;
}
.pw-modal label input:focus {
    outline: none;
    border-color: var(--accent);
}
.pw-error {
    color: var(--accent);
    font-size: 12px;
    margin-bottom: 8px;
    min-height: 16px;
}
.modal-actions {
    display: flex; gap: 8px; justify-content: flex-end;
    margin-top: 16px;
}

/* ---------- Settings dialog: audio/subtitle language priority ---------- */
.settings-modal {
    max-width: 460px;
    max-height: 85vh;
    overflow-y: auto;
}
.settings-section-title {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--fg-faint);
    margin: 20px 0 6px;
}
.settings-section-title:first-of-type { margin-top: 0; }
.settings-hint {
    font-size: 12px;
    color: var(--fg-faint);
    margin-bottom: 10px;
    line-height: 1.4;
}
.lang-priority-section { margin-bottom: 4px; }
.lang-priority-list {
    display: flex; flex-direction: column; gap: 6px;
    margin-bottom: 10px;
}
.lang-priority-empty {
    font-size: 12px;
    color: var(--fg-faint);
    font-style: italic;
    padding: 8px 0;
}
.lang-priority-row {
    display: flex; align-items: center; gap: 10px;
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 10px;
}
.lang-priority-rank {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-faint);
    width: 16px;
}
.lang-priority-name { flex: 1; font-size: 14px; }
.lang-priority-actions { display: flex; gap: 4px; }
.lang-priority-btn {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--fg);
    width: 26px; height: 26px;
    font-size: 11px;
    cursor: pointer;
}
.lang-priority-btn:hover { background: var(--bg-elev); border-color: var(--fg-faint); }
.lang-priority-btn:disabled { opacity: 0.3; cursor: default; }
.lang-priority-btn:disabled:hover { background: transparent; border-color: var(--border); }
.lang-priority-remove:hover { color: var(--accent); border-color: var(--accent); }
.lang-priority-add-row {
    display: flex; gap: 8px;
}
.lang-add-select {
    flex: 1;
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0 10px;
    color: var(--fg);
    font-size: 13px;
}
.lang-priority-add-btn { white-space: nowrap; }

/* ============================================================
   PROVIDER LOGO (now lives inside controls overlay)
   ============================================================ */
.provider-logo {
    height: 22px;
    max-width: 120px;
    opacity: 0.7;
    margin-right: 6px;
    filter: brightness(1.1);
    transition: opacity 0.2s;
    flex-shrink: 0;
}
.provider-logo:hover { opacity: 1; }

/* ============================================================
   HOME VIEW
   ============================================================ */
.view-home {
    padding: 0 0 80px;
}

/* ============================================================
   HERO CAROUSEL — breaks out of <main>'s centered max-width via the
   left:50%/margin-left:-50vw full-bleed trick, ~50% viewport height.
   ============================================================ */
.hero-carousel {
    position: relative;
    left: 50%;
    width: 100vw;
    margin-left: -50vw;
    margin-top: -64px;
    height: 85vh;
    min-height: 340px;
    overflow: hidden;
    margin-bottom: 40px;
    background: var(--bg-tile);
}
.hero-track {
    display: flex;
    height: 100%;
    transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    /* Let the browser keep handling vertical page scroll; horizontal drags
       are claimed by the pointer-event handlers in renderHeroCarousel(). */
    touch-action: pan-y;
    user-select: none;
    cursor: grab;
}
.hero-track.is-dragging { cursor: grabbing; }
.hero-slide {
    position: relative;
    height: 100%;
    background-size: auto 100%;
    background-position: right center;
    background-repeat: no-repeat;
    background-color: #000;
}
/* Thumbnails are right-aligned at their native aspect ratio (not stretched
   to cover), so anything narrower than the slide leaves black background
   showing on the left — this fades that gap into the image instead of a
   hard edge. --hero-fade-w (set per-slide by measureHeroFade() in app.js,
   once the image's natural size is known) is the actual pixel gap width
   plus a 100px overlap onto the image itself, so the box stays fully
   solid — matching the flat background-color exactly, no visible internal
   transition — for the whole gap, and only starts fading to transparent
   inside that last 100px overlap. That guarantees the fade is still
   fully opaque at the exact spot the image starts, so the seam is never
   visible; it only clears up gradually further into the image. Falls back
   to a fixed percentage before JS has measured anything (image not loaded
   yet, or unsupported/no-JS). */
.hero-slide::before {
    content: '';
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: var(--hero-fade-w, 45%);
    background: linear-gradient(90deg,
        #000 0%,
        #000 calc(100% - 100px),
        rgba(0,0,0,0.98) calc(100% - 85px),
        rgba(0,0,0,0.9) calc(100% - 65px),
        rgba(0,0,0,0.72) calc(100% - 48px),
        rgba(0,0,0,0.48) calc(100% - 32px),
        rgba(0,0,0,0.2) calc(100% - 15px),
        transparent 100%);
    pointer-events: none;
}
/* Bottom fade — its own pseudo-element (rather than living on
   .hero-slide-overlay, the text container) so moving the text to vertical
   middle on desktop (below) doesn't drag the fade away from the bottom
   edge with it; this always stays bottom-anchored regardless of where the
   text sits. */
.hero-slide::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 55%;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(8,8,11,0.35) 40%,
        rgba(8,8,11,0.75) 65%,
        rgba(8,8,11,0.97) 100%);
    pointer-events: none;
}
/* Desktop (900px+ — see the max-width:900px override below for
   tablet/phone): vertically centered and inset from the sides so it never
   sits under the hero-nav arrows (24px + 48px wide = 72px, +28px breathing
   room). Tablet/phone have no room to spare for that and hide/shrink the
   arrows anyway, so they keep the old bottom-pinned layout. z-index keeps
   the text above the ::before/::after fades above, since a plain DOM child
   would otherwise stack below a later ::after in paint order. */
.hero-slide-overlay {
    position: absolute;
    top: 50%; left: 100px; right: 100px;
    transform: translateY(-50%);
    z-index: 1;
    display: flex;
    flex-direction: column;
    padding: 24px 0;
}
.hero-slide-badges { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
/* providerLogoImg() hardcodes .pd-provider-logo too (margin-left: auto —
   meant to push it to the far right of a .pd-meta-row), which otherwise
   shoves it to the opposite end of this row instead of sitting next to the
   badge; this outweighs it via specificity (two classes vs. one). Full
   opacity/no brightness filter here too — .provider-logo's dimmed-until-
   hover treatment fits the controls-overlay/meta-row contexts it was built
   for, not a full-bleed HERO backdrop. */
.hero-slide-badges .provider-logo { margin-left: 0; opacity: 1; filter: none; }
.hero-badge {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 4px 10px;
    border-radius: 3px;
    color: #fff;
}
.hero-badge.is-live    { background: var(--live); }
.hero-badge.is-soon    { background: var(--soon); }
.hero-badge.is-archive { background: var(--archive); }
.hero-slide-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(26px, 4vw, 48px);
    line-height: 1.1;
    margin: 0 0 12px;
    max-width: 620px;
    color: #fff;
    text-shadow: 0 2px 16px rgba(0,0,0,0.4);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.hero-slide-meta {
    font-family: var(--font-mono);
    font-size: 13px;
    color: rgba(255,255,255,0.82);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.hero-slide-logo {
    width: 55px !important; height: 55px !important;
    margin-top: 0;
    background: rgba(255,255,255,0.08);
    border-color: rgba(255,255,255,0.25);
    transition: border-color 0.15s, background 0.15s;
}
.hero-slide-logo-link { display: flex; cursor: pointer; }
.hero-slide-logo-link:hover .hero-slide-logo {
    background: rgba(255,255,255,0.16);
    border-color: rgba(255,255,255,0.45);
}
.hero-slide-actions { display: flex; gap: 14px; margin-top: 14px; }
.hero-btn {
    display: flex; align-items: center; gap: 8px;
    padding: 14px 28px;
    border-radius: 8px;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s, transform 0.1s;
    box-sizing: border-box;
}
.hero-btn:active { transform: scale(0.97); }
.hero-btn-watch { background: var(--accent); color: #fff; border: 3px var(--accent) solid; } 
.hero-btn-watch:hover { background: transparent;}
.hero-btn-info {
    background: rgba(120,120,130,0.35);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.25);
}
.hero-btn-info:hover { background: rgba(120,120,130,0.5); }
.hero-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 48px; height: 48px;
    border-radius: 50%;
    background: rgba(10,10,11,0.55);
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    z-index: 2;
    transition: background 0.15s;
}
.hero-nav:hover { background: rgba(10,10,11,0.85); }
.hero-nav-prev { left: 24px; }
.hero-nav-next { right: 24px; }
.hero-dots {
    position: absolute;
    bottom: 22px; left: 50%;
    transform: translateX(-50%);
    display: flex; gap: 8px;
    z-index: 2;
}
.hero-dot {
    position: relative;
    width: 40px; height: 4px;
    box-sizing: content-box;
    /* Extends the clickable/tappable area ~5px above and below the visible
       dash without changing how thick it looks — the dash itself lives on
       ::before/::after, positioned to the un-padded content box. */
    padding: 5px 0;
    background: none;
    border: none;
    cursor: pointer;
}
.hero-dot::before {
    content: '';
    position: absolute;
    top: 5px; left: 0; right: 0; bottom: 5px;
    border-radius: 2px;
    background: rgba(255,255,255,0.35);
}
.hero-dot::after {
    content: '';
    position: absolute;
    top: 5px; left: 0; bottom: 5px;
    width: 0%;
    border-radius: 2px;
    background: #fff;
}
/* Fill sweeps 0% -> 100% in step with the 6s autoplay interval (see
   restartAutoplay() in app.js) so the dash finishes right as the next
   slide shows; .paused (hover) freezes it in place instead of letting it
   drift out of sync with the cleared JS timer. */
.hero-dot.active::after { animation: hero-dot-fill 6s linear forwards; }
.hero-dots.paused .hero-dot.active::after { animation-play-state: paused; }
.hero-dot.done::after { width: 100%; animation: none; }
@keyframes hero-dot-fill {
    from { width: 0%; }
    to { width: 100%; }
}
/* TV app — no pointer to hover the prev/next chevrons or click through
   dot-pagination with, and the Informacija link duplicates what pressing OK
   on the slide itself already does. Hiding all three (rather than just
   leaving them unreachable) also drops them out of getTvFocusable()'s
   candidate set for free, since it filters on actual rendered rects. */
.tv-mode .hero-nav,
.tv-mode .hero-dots,
.tv-mode .hero-btn-info {
    display: none;
}

@media (max-width: 900px) {
    .hero-carousel { height: 42vh; min-height: 280px; margin-bottom: 28px; margin-top: 0; }
    .hero-slide-overlay {
        top: auto; left: 0; right: 0; bottom: 0;
        transform: none;
        height: 65%;
        justify-content: flex-end;
        padding: 28px 24px 24px;
    }
    .hero-dots { bottom: 14px; }
    .hero-dot { width: 32px; height: 3px; }
    .hero-nav { width: 38px; height: 38px; }
    .hero-nav-prev { left: 10px; }
    .hero-nav-next { right: 10px; }
    .hero-slide-actions { margin-top: 16px; gap: 10px; }
    .hero-btn { padding: 10px 18px; font-size: 13px; }
}
@media (max-width: 600px) {
    .hero-carousel { height: auto; aspect-ratio: 16 / 9; min-height: 0; }
    .hero-slide-title { font-size: clamp(20px, 6vw, 30px); -webkit-line-clamp: 3; }
    .hero-nav { display: none; }
    /* The left-fade is tuned for the wide desktop slide; at 16:9 the image
       already fills most of the frame, so the fade just muddies it. */
    .hero-slide::before { display: none; }
}

.home-section {
    margin-bottom: 48px;
}
.home-section-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 18px;
}
.home-section-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 28px;
    margin: 0;
    letter-spacing: -0.01em;
}
/* "Rodyti viską" — expands a home/search row into its own full page */
.group-pill svg { display: none; }

/* ----- Expanded section page (#/home/:key, #/search/:query/:category) -----
   Horizontal inset comes from <main>'s own padding — no extra padding here. */
.view-section-page {
    padding-bottom: 48px;
}
.section-page-header {
    display: flex;
    align-items: center;
    gap: 16px;
    margin: 24px 0 28px;
}
.yt-rss-add-btn {
    margin-left: auto;
    flex-shrink: 0;
    background: var(--accent);
    color: #fff;
    border: none;
    border-radius: 99px;
    padding: 9px 16px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s, opacity 0.15s;
}
.category-sort-select {
    margin-left: auto;
    flex-shrink: 0;
    background: var(--bg-tile);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 9px 14px;
    font-family: var(--font-body);
    font-size: 13px;
    cursor: pointer;
}
.category-sort-select:hover,
.category-sort-select:focus {
    border-color: var(--border-hi);
    outline: none;
}
.yt-rss-add-btn:hover:not(:disabled) { background: #ff5447; }
.yt-rss-add-btn:disabled { opacity: 0.6; cursor: default; }
.yt-rss-add-btn.is-added {
    background: var(--bg-tile);
    color: var(--fg-dim);
    border: 1px solid var(--border);
}
.section-back-btn {
    flex-shrink: 0;
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: 50%;
    color: var(--fg);
    transition: border-color 0.15s, background 0.15s;
}
.section-back-btn:hover { border-color: var(--accent); background: var(--bg-tile-hi); }
.section-page-titles {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.section-page-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 32px;
    letter-spacing: -0.01em;
    margin: 0;
}
.section-page-sub {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-faint);
    letter-spacing: 0.05em;
}
.section-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 16px;
}

/* ----- Categories (/categories) — epg_categories rows, both Go3's
   sport/competition categories (Formula 1, Krepšinis, WNBA) and its VOD
   genre categories (Dramos, Veiksmo, ...), laid out as a full-page grid
   rather than a scrollable row — see loadEpgCategoriesPage() in app.js.
   Banner shows the category's own 1x1 cover image where Go3 provides one
   (mostly sport/competition categories today), falling back to a plain
   initial like any other logo-less card otherwise. ----- */
.epg-category-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
}
.epg-category-card {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: transform 0.2s, border-color 0.2s;
}
.epg-category-card:hover {
    transform: translateY(-2px);
    border-color: var(--border-hi);
}
.epg-category-card-banner {
    aspect-ratio: 1 / 1;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-tile-hi);
}
.epg-category-card-banner img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.epg-category-card-banner .logo-fallback {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 36px;
    color: var(--fg-dim);
}
.epg-category-card-info {
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.epg-category-card-name {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 18px;
    letter-spacing: -0.01em;
}
.epg-category-card-meta {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Featured channels — cards inside the shared .home-scroll-row */
.home-featured-card {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.15s;
    display: flex; flex-direction: column;
    flex: 0 0 240px;
    scroll-snap-align: start;
}
.home-featured-card:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
}
.home-featured-card .ff-banner {
    aspect-ratio: 16/9;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-tile-hi);
    position: relative;
}
.home-featured-card .ff-info {
    padding: 12px 14px;
    display: flex;
    align-items: flex-start;
    gap: 10px;
}
.home-featured-card .ff-info-text { min-width: 0; flex: 1; }
.home-featured-card .ff-name {
    font-size: 14px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.home-featured-card .ff-now {
    font-size: 12px;
    color: var(--fg-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 4px;
}

/* Horizontal scroll row wrapper with gradient scroll buttons */
.home-scroll-wrap {
    position: relative;
}

.home-scroll-row {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 12px;
    padding-top: 3px;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    cursor: grab;
}
/* Click-and-drag scrolling (see enableDragScroll() in app.js) — snap is
   suspended mid-drag so it doesn't fight the cursor's exact position. */
.home-scroll-row.is-dragging {
    cursor: grabbing;
    scroll-snap-type: none;
    user-select: none;
}
.home-scroll-row > * {
    flex: 0 0 240px;
    scroll-snap-align: start;
}

/* Phones: snap to the middle of the row instead of the left edge. Must come
   after the unconditional .home-scroll-row > * / .home-featured-card rules
   above — same specificity, so an earlier (e.g. top-of-file) media query
   would otherwise lose the cascade to these on every screen size, not just
   phones. */
@media (max-width: 600px) {
    .home-scroll-row > *, .home-featured-card {
        scroll-snap-align: center;
    }
}

/* "Rodyti viską" tile — last item in a home/search scroll row or the
   channel-grid search result, in place of the old header button. It's a
   plain .upcoming-card (see seeAllCard() in app.js) reusing .uc-banner/
   .uc-info/.uc-title as-is, so it matches real cards exactly; only the
   icon centering inside the banner is specific to this tile. */
.see-all-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--fg-dim);
    transition: color 0.15s;
}
.see-all-card:hover .see-all-icon {
    color: var(--fg);
}

/* Gradient scroll buttons that overlay the row */
.home-scroll-btn {
    position: absolute;
    top: 0;
    bottom: 12px;   /* leave room for scrollbar */
    width: 56px;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    z-index: 2;
    transition: opacity 0.15s;
    opacity: 0.95;
}
.home-scroll-btn:hover { opacity: 1; }
.home-scroll-btn.is-hidden {
    opacity: 0;
    pointer-events: none;
}
.home-scroll-btn-left {
    left: 0;
    background: linear-gradient(90deg, rgba(8,8,11,0.92) 30%, transparent);
    justify-content: flex-start;
    padding-left: 12px;
}
.home-scroll-btn-right {
    right: 0;
    background: linear-gradient(270deg, rgba(8,8,11,0.92) 30%, transparent);
    justify-content: flex-end;
    padding-right: 12px;
}
.home-scroll-btn svg {
    background: rgba(20,20,24,0.85);
    border-radius: 50%;
    padding: 7px;
    box-sizing: content-box;
    border: 1px solid rgba(255,255,255,0.12);
}
.home-scroll-btn:hover svg {
    background: rgba(255,71,87,0.85);
    border-color: var(--accent);
}

.upcoming-card {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.15s;
    display: flex; flex-direction: column;
}
.upcoming-card:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
}
.upcoming-card .uc-banner {
    aspect-ratio: 16/9;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-tile-hi);
    position: relative;
}
.upcoming-card .uc-status-overlay {
    position: absolute;
    top: 8px; right: 0px;
    color: #fff;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 3px 0 0 3px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.upcoming-card .uc-status-overlay.is-live    { background: var(--live); }
.upcoming-card .uc-status-overlay.is-soon    { background: var(--soon); }
.upcoming-card .uc-status-overlay.is-archive { background: var(--archive); }
.upcoming-card .uc-progress-overlay,
.episode-card-banner .uc-progress-overlay {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 3px;
    background: rgba(255,255,255,0.25);
}
.upcoming-card .uc-progress-overlay-fill,
.episode-card-banner .uc-progress-overlay-fill {
    height: 100%;
    background: var(--watched);
}
/* Remove-from-watchlist button (see watchlistCard() in app.js) */
.upcoming-card .uc-remove-btn {
    position: absolute;
    top: 6px; left: 6px;
    width: 24px; height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,0.7);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 50%;
    color: var(--fg-dim);
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s, border-color 0.15s;
}
.upcoming-card:hover .uc-remove-btn { opacity: 1; }
.upcoming-card .uc-remove-btn:hover { color: #f87171; border-color: #f87171; }
/* Duration badge for YouTube search-result cards (ytSearchVideoCard) and
   series episode cards (episodeCard() on /series/:id) — same class, two
   card types, since the badge look is identical either way. */
.upcoming-card .uc-duration-badge,
.episode-card-banner .uc-duration-badge {
    position: absolute;
    right: 6px; bottom: 6px;
    background: rgba(0,0,0,0.78);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    padding: 2px 5px;
    border-radius: 3px;
    letter-spacing: 0.02em;
}
.upcoming-card .uc-info {
    padding: 12px 14px;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.upcoming-card .uc-info-top {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

/* Shared logo thumbnail used in the info section of every homepage card type */
.card-logo {
    flex: 0 0 auto;
    width: 36px; height: 36px;
    border-radius: 6px;
    background: var(--bg-tile-hi);
    border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.card-logo img { width: 100%; height: 100%; object-fit: contain; }
.card-logo img[src$=".svg"] { width: 65%; height: 65%; }
.card-logo .logo-fallback {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 15px;
    color: var(--fg-dim);
}

/* Per-page "subnav" — curated shortcut row rendered right after HERO (see
   renderSubnav()/subnavCard() in app.js). Round logo + label underneath,
   deliberately smaller/plainer than a real content card since these are
   just navigation shortcuts. */
.subnav-row {
    display: flex;
    gap: 20px;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 4px;
    padding-top: 3px;
    margin-bottom: 40px;
    justify-content: space-between;
}
/* The channels/guide views' subnav container starts with a plain `hidden`
   attribute in index.html (see loadNativeSubnav()) — an author stylesheet's
   `display` beats the UA stylesheet's `[hidden] { display: none }` on
   origin alone, specificity aside, so without this the row would render as
   an empty flex box instead of actually disappearing. */
.subnav-row[hidden] {
    display: none;
}
.subnav-card {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    width: 90px;
    text-align: center;
    cursor: pointer;
}
.subnav-card-logo {
    width: 86px; height: 86px;
    border-radius: 50%;
    transition: border-color 0.15s, transform 0.15s;
}
.subnav-card:hover .subnav-card-logo {
    border-color: var(--accent);
    transform: translateY(-2px);
}
.subnav-card-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--fg-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}
.subnav-card:hover .subnav-card-label { color: var(--fg); }
.upcoming-card .uc-title {
    min-width: 0;
    flex: 1;
    font-size: 13px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.upcoming-card .uc-meta {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.04em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* YouTube channel search-result card (ytSearchChannelCard) — profile-style,
   sits alongside video cards inside a shared .home-scroll-row/.section-grid. */
.yt-channel-card {
    background: var(--bg-tile);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 18px 14px;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.15s;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 10px;
}
.yt-channel-card:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
}
.yt-channel-card-avatar {
    width: 72px; height: 72px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-tile-hi);
    border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    flex: 0 0 auto;
}
.yt-channel-card-avatar img { width: 100%; height: 100%; object-fit: cover; }
.yt-channel-card-avatar .logo-fallback {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 26px;
    color: var(--fg-dim);
}
.yt-channel-card-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    width: 100%;
}
.yt-channel-card-name {
    font-size: 14px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.yt-channel-card-meta {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.04em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.yt-channel-card-desc {
    font-size: 11px;
    color: var(--fg-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

/* External YouTube channel RSS page (#/youtube/rss/:channelId) — vertical
   list of .programme-row.yt-video-row entries, same idea as .guide-programmes
   but for a full page (no max-height cap). */
.yt-rss-list {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 8px;
}



/* YouTube sidebar (inside player) */
.yt-side-item { gap: 10px; align-items: flex-start; }
.yt-side-thumb {
    flex-shrink: 0;
    width: 96px;
    aspect-ratio: 16/9;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-tile-hi);
    border-radius: 4px;
}

/* ============================================================
   YOUTUBE PAGE — reuses the EPG (.guide-layout) structure; the
   channel rail shows logo+name only, and video rows use the
   programme-row layout without the time column.
   ============================================================ */
.view-youtube { padding: 0 0 80px; }

.programme-row.yt-video-row { grid-template-columns: 100px 1fr; }

.yt-date {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--fg-faint);
    letter-spacing: 0.04em;
}

/* ============================================================
   GUIDE — channel list with NOW/UPCOMING
   ============================================================ */
.guide-channel.is-rich {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    grid-template-rows: auto auto auto;
    gap: 4px 10px;
    align-items: start;
    padding: 12px;
}
.guide-channel.is-rich .gc-logo {
    grid-row: 1 / span 3;
    grid-column: 1;
    align-self: center;
}
.guide-channel.is-rich .fav-heart-btn {
    grid-row: 1 / span 3;
    grid-column: 3;
    align-self: center;
}
.guide-channel.is-rich .gc-name {
    grid-column: 2;
    grid-row: 1;
    font-size: 14px;
    font-weight: 600;
    color: var(--fg);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.guide-channel.is-rich .gc-now-row,
.guide-channel.is-rich .gc-next-row {
    grid-column: 2;
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.3;
}
.guide-channel.is-rich .gc-now-row {
    color: var(--fg-dim);
}
.guide-channel.is-rich .gc-now-row::before {
    content: '●';
    color: var(--accent);
    font-size: 8px;
    margin-right: 6px;
    vertical-align: middle;
}
.guide-channel.is-rich .gc-next-row {
    color: var(--fg-faint);
}
.guide-channel.is-rich .gc-next-row::before {
    content: '●';
    color: var(--fg-faint);
    font-size: 7px;
    margin-right: 6px;
    vertical-align: middle;
}

/* Selected-channel summary card above the EPG — desktop already shows this info
   per-row in the channel rail, so the card only appears on mobile/tablet (see RESPONSIVE). */
#guideSelectedChannel { display: none; }

/* ============================================================
   UNMUTE OVERLAY
   ============================================================
   Shown when video starts muted due to autoplay policy. Click to unmute. */
.unmute-overlay {
    position: absolute;
    inset: 0;
    z-index: 8;
    display: flex;
    align-items: center;
    justify-content: center;
    background: radial-gradient(ellipse at center, rgba(0,0,0,0.55), rgba(0,0,0,0.85));
    cursor: pointer;
    animation: fadeIn 0.2s ease-out;
}
.unmute-overlay[hidden] { display: none; }
.unmute-card {
    background: rgba(20,20,24,0.92);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 16px;
    padding: 32px 40px;
    text-align: center;
    color: #fff;
    box-shadow: 0 24px 64px rgba(0,0,0,0.7);
    transition: transform 0.15s;
}
.unmute-overlay:hover .unmute-card { transform: scale(1.02); }
.unmute-card svg { color: var(--accent); margin-bottom: 12px; }
.unmute-card p {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 26px;
    margin: 0 0 6px;
    line-height: 1;
}
.unmute-card .unmute-hint {
    display: block;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-faint);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* ============================================================
   SUBTITLE LIFT WHEN CONTROLS VISIBLE
   ============================================================
   Native HTMLMediaElement cues respect padding-bottom via ::cue + 
   the `track` element renders cues at bottom. We push them up using
   `padding-bottom` on the video container when controls are shown,
   or by adjusting `::cue` if Shaka's UI text renderer is in use.
*/
.player-overlay video::-webkit-media-text-track-container {
    /* Baseline gap from the bottom edge even with controls hidden — subtitles
       otherwise render flush against the screen edge. */
    transform: translateY(-24px);
}
.player-overlay.controls-visible video::-webkit-media-text-track-container {
    transform: translateY(-160px);
    transition: transform 0.2s;
}
.player-overlay video::cue {
    /* fallback for other browsers */
    background: rgba(0,0,0,0.5);
}

/* ============================================================
   When player is open, hide app main; topbar stays
   ============================================================ */
body.is-watching { overflow: hidden; }
body.is-watching .topbar {
    background: rgba(8,8,11,0.92);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(255,255,255,0.1);
}
body.is-watching .topbar-inner { max-width: none; }

/* TV app — the topbar served desktop users as a persistent "still signed in
   as X" bar while watching; on TV the player should be 100% of the screen
   with nothing else drawn over it. It only reappears — as an overlay above
   the dimmed backdrop, exactly like the rail/sidebar panels it now shares
   z-index-space with (60/61) — while one of those panels is actually open,
   via :has() rather than a new JS-toggled class since nothing else here
   needs to know the panel state. */
.tv-mode body.is-watching .topbar {
    display: none;
}
.tv-mode body.is-watching:has(.player-channel-rail.is-open) .topbar,
.tv-mode body.is-watching:has(.player-sidebar.is-open) .topbar {
    display: block;
    z-index: 62;
}

/* ============================================================
   EPG NOW BLOCK INSIDE DAY LIST (current programme highlight)
   ============================================================
   The "now block" rich card is now rendered IN-FLOW inside the day list,
   replacing the current programme entry. */
.day-item.is-now-rich {
    display: block;
    margin: 6px -16px;
    padding: 16px;
    background: linear-gradient(180deg, rgba(255, 71, 87, 0.12), transparent 70%);
    border: 1px solid var(--accent);
    border-radius: 10px;
}
.day-item.is-now-rich .now-rich-img {
    width: 100%;
    aspect-ratio: 16/9;
    object-fit: cover;
    border-radius: 6px;
    background: var(--bg-tile);
    margin-bottom: 10px;
    display: block;
}
.day-item.is-now-rich .now-rich-label {
    font-family: var(--font-mono);
    font-size: 9px;
    color: var(--accent);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    margin-bottom: 6px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.day-item.is-now-rich .now-rich-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 6px;
}
.day-item.is-now-rich .now-rich-title-row .now-rich-title { margin: 0; }
.day-item.is-now-rich .now-rich-title {
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 20px;
    line-height: 1.15;
    color: #fff;
    margin: 0 0 6px;
}
.day-item.is-now-rich .now-rich-time {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-dim);
    margin-bottom: 8px;
}
.day-item.is-now-rich .now-rich-progress {
    height: 3px;
    background: rgba(255,255,255,0.1);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: 10px;
}
.day-item.is-now-rich .now-rich-progress-fill {
    height: 100%;
    background: var(--accent);
}
.day-item.is-now-rich .now-rich-desc {
    font-size: 12px;
    color: var(--fg-dim);
    line-height: 1.5;
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
