@font-face {
  font-family: "Brada Sans";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('./fonts/BradaSans-Light.otf') format('opentype');
}
@font-face {
  font-family: "Brada Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('./fonts/BradaSans-Regular.otf') format('opentype');
}
@font-face {
  font-family: "Brada Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('./fonts/BradaSans-SemiBold.otf') format('opentype');
}
@font-face {
  font-family: "Brada Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('./fonts/BradaSans-Bold.otf') format('opentype');
}

/* ============================================================
     CUSTOM FONT: Brada Sans (embedded base64 OTF)
     Eight weights/styles — Light(300)/Regular(400)/Semibold(600)/Bold(700)
     in normal & italic. Embedded inline so the file is self-contained
     in any Squarespace codeblock or static host.
     ============================================================ */
  /* ============================================================
     DESIGN TOKENS
     ============================================================ */
  :root {
    /* Surfaces */
    --bg-base: #070a14;
    --bg-elevated: #0f1424;
    --bg-overlay: rgba(7, 10, 20, 0.94);
    --surface-1: rgba(255, 255, 255, 0.035);
    --surface-2: rgba(255, 255, 255, 0.07);
    --surface-3: rgba(255, 255, 255, 0.11);
    --border: rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.16);

    /* Type */
    --text-primary: #f5f7fb;
    --text-secondary: rgba(245, 247, 251, 0.74);
    --text-muted: rgba(245, 247, 251, 0.5);
    --text-faint: rgba(245, 247, 251, 0.32);

    /* Brand */
    --accent: #5eead4;
    --accent-bright: #7ff5dd;
    --accent-deep: #0d9488;
    --accent-glow: rgba(94, 234, 212, 0.45);
    --accent-soft: rgba(94, 234, 212, 0.12);
    --accent-faint: rgba(94, 234, 212, 0.04);

    /* Shadows */
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
    --shadow-md: 0 4px 12px rgba(0,0,0,0.45), 0 1px 3px rgba(0,0,0,0.3);
    --shadow-lg: 0 12px 32px rgba(0,0,0,0.55), 0 4px 10px rgba(0,0,0,0.35);
    --shadow-card-hover: 0 22px 48px rgba(0,0,0,0.7), 0 0 0 1px rgba(94, 234, 212, 0.25), 0 0 40px rgba(94, 234, 212, 0.12);

    /* Motion */
    --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
    --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
    --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);

    /* Type stack */
    /* Typography — Brada Sans is the family for everything. There's no
       monospace variant in Brada, so the "mono" slot maps to the same family;
       elements that previously used --font-mono pick up letter-spacing and
       uppercase tracking in their own rules to keep the labeled-tag feel. */
    --font-display: 'Brada Sans', system-ui, -apple-system, sans-serif;
    --font-body: 'Brada Sans', system-ui, -apple-system, sans-serif;
    --font-mono: 'Brada Sans', system-ui, -apple-system, sans-serif;

    /* Plyr override */
    --plyr-color-main: #5eead4;
    --plyr-video-control-color: #f5f7fb;
    --plyr-video-control-color-hover: #070a14;
    --plyr-video-control-background-hover: #5eead4;
  }

  /* ============================================================
     RESET & BASE
     ============================================================ */
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
  html, body {
    width: 100%;
    background: #070a14;
    color: var(--text-primary);
    font-family: var(--font-body);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    -webkit-tap-highlight-color: transparent;
    margin: 0 !important;
    padding: 0 !important;
  }
  body {
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
  }

  /* ============================================================
     APP WRAPPER — full-screen overlay, makes the app behave the
     same way whether you load the page directly or embed it inside
     a Squarespace code block. Covers any host-site chrome and
     creates an isolated scroll context.
     ============================================================ */
  #tpp-app {
    position: fixed;
    inset: 0;
    z-index: 2147483647;
    background: var(--bg-base);
    color: var(--text-primary);
    font-family: var(--font-body);
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  /* Lock app scroll when a modal is open */
  #tpp-app.scroll-locked { overflow: hidden; }

  img { -webkit-user-drag: none; user-drag: none; }
  button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; touch-action: manipulation; }
  a { touch-action: manipulation; }
  .card, .episode, .mtab, .chip, .nav__link, .nav__icon-btn { touch-action: manipulation; }
  ::selection { background: var(--accent); color: var(--bg-base); }

  /* Atmospheric base background — subtle gradient mesh */
  #tpp-app::before {
    content: '';
    position: fixed;
    inset: 0;
    background:
      radial-gradient(ellipse 80% 50% at 20% 0%, rgba(94, 234, 212, 0.08), transparent 60%),
      radial-gradient(ellipse 60% 40% at 100% 30%, rgba(64, 129, 133, 0.12), transparent 70%),
      radial-gradient(ellipse 100% 60% at 50% 100%, rgba(15, 20, 36, 0.6), transparent 70%);
    pointer-events: none;
    z-index: 0;
  }

  /* Film grain overlay — subtle texture, very low opacity */
  #tpp-app::after {
    content: '';
    position: fixed;
    inset: 0;
    background-image: url("data:image/svg+xml;utf8,<svg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='0.5'/></svg>");
    opacity: 0.025;
    mix-blend-mode: overlay;
    pointer-events: none;
    z-index: 1;
  }

  /* ============================================================
     PAGE LOAD INTRO
     ============================================================ */
  #intro {
    position: fixed;
    inset: 0;
    z-index: 9999998;
    background: var(--bg-base);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    transition: opacity 0.9s var(--ease-out-expo);
  }
  #intro .intro-mark {
    /* Sized via width so the original glyph proportions are preserved.
       The clamp here roughly matches the visual weight of the previous
       wordmark (≈ 2.5rem-tall text scaled up to ~5rem on large screens). */
    width: clamp(220px, 32vw, 420px);
    height: auto;
    display: block;
    opacity: 0;
    transform: translateY(20px);
    animation: introMark 1.2s var(--ease-out-expo) forwards;
    /* Crisp scaling on retina; keep transparent PNG edges clean */
    image-rendering: -webkit-optimize-contrast;
  }
  #intro.done { opacity: 0; }
  @keyframes introMark {
    to { opacity: 1; transform: translateY(0); }
  }

  /* ============================================================
     NAVIGATION
     ============================================================ */
  .nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 4vw;
    padding-top: calc(18px + env(safe-area-inset-top));
    transition: background 0.4s var(--ease-smooth), backdrop-filter 0.4s var(--ease-smooth);
    background: linear-gradient(to bottom, rgba(7,10,20,0.85) 0%, rgba(7,10,20,0.4) 60%, rgba(7,10,20,0) 100%);
  }
  /* Bottom separator line — fades cleanly with the scrolled state */
  .nav::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 1px;
    background: var(--border);
    opacity: 0;
    transition: opacity 0.4s var(--ease-smooth);
    pointer-events: none;
  }
  .nav.scrolled {
    background: rgba(7, 10, 20, 0.78);
    backdrop-filter: saturate(180%) blur(22px);
    -webkit-backdrop-filter: saturate(180%) blur(22px);
  }
  .nav.scrolled::after { opacity: 1; }
  .nav__left { display: flex; align-items: center; gap: 32px; }
  .nav__logo {
    height: 30px;
    display: block;
    transition: opacity 0.2s, transform 0.25s var(--ease-out-quart);
    cursor: pointer;
  }
  .nav__logo:hover { opacity: 0.85; transform: scale(1.03); }
  .nav__logo:active { transform: scale(0.97); }

  .nav__links {
    display: flex;
    gap: 26px;
    list-style: none;
    /* Anchor for the absolutely-positioned sliding underline */
    position: relative;
  }
  .nav__link {
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-secondary);
    letter-spacing: -0.01em;
    background: none;
    padding: 0;
    transition: color 0.3s var(--ease-out-quart);
    position: relative;
  }
  .nav__link:hover, .nav__link.active { color: var(--text-primary); }
  /* The sliding active-indicator. Its `left` and `width` are written by
     updateNavUnderline() in JS; the transition turns those writes into a
     smooth glide between adjacent links instead of a snap. */
  .nav__underline {
    position: absolute;
    bottom: -6px;
    left: 0;
    width: 0;
    height: 2px;
    background: var(--accent);
    border-radius: 2px;
    box-shadow: 0 0 12px var(--accent-glow);
    transition:
      left 0.42s cubic-bezier(0.5, 0, 0.2, 1),
      width 0.42s cubic-bezier(0.5, 0, 0.2, 1),
      opacity 0.2s ease;
    pointer-events: none;
    opacity: 0;
  }
  .nav__underline.ready { opacity: 1; }

  .nav__right { display: flex; align-items: center; gap: 14px; }
  .nav__icon-btn {
    width: 36px; height: 36px;
    display: grid; place-items: center;
    color: var(--text-secondary);
    border-radius: 8px;
    transition: background 0.2s, color 0.2s, transform 0.2s var(--ease-spring);
  }
  .nav__icon-btn:hover {
    background: var(--surface-2);
    color: var(--text-primary);
    transform: scale(1.06);
  }
  .nav__icon-btn svg { width: 18px; height: 18px; }

  /* Mobile nav adjustments */
  @media (max-width: 820px) {
    .nav { padding: 14px 16px; padding-top: calc(14px + env(safe-area-inset-top)); }
    .nav__links { display: none; }
    .nav__left { gap: 16px; }
    .nav__logo { height: 26px; }
    /* Slightly bigger tap targets on mobile */
    .nav__icon-btn { width: 40px; height: 40px; }
    .nav__icon-btn svg { width: 20px; height: 20px; }
  }

  /* ============================================================
     MOBILE BOTTOM TAB BAR — primary nav on touch devices
     ============================================================ */
  .mobile-tabs {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    z-index: 9998;
    display: none;
    justify-content: space-around;
    align-items: stretch;
    padding: 6px 8px;
    padding-bottom: calc(6px + env(safe-area-inset-bottom));
    background: rgba(7, 10, 20, 0.92);
    backdrop-filter: saturate(180%) blur(24px);
    -webkit-backdrop-filter: saturate(180%) blur(24px);
    border-top: 1px solid var(--border);
    transition: transform 0.3s var(--ease-smooth);
  }
  .mobile-tabs.hidden { transform: translateY(100%); }
  @media (max-width: 820px) { .mobile-tabs { display: flex; } }
  .mtab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 8px 4px 6px;
    color: var(--text-muted);
    background: none;
    border-radius: 10px;
    transition: color 0.2s, background 0.2s;
    position: relative;
    min-height: 52px;
  }
  .mtab:active { background: var(--surface-1); transform: scale(0.96); }
  .mtab svg { width: 22px; height: 22px; transition: transform 0.2s var(--ease-spring); }
  .mtab span {
    font-family: var(--font-body);
    font-size: 0.66rem;
    font-weight: 500;
    letter-spacing: 0.01em;
  }
  .mtab.active { color: var(--accent); }
  .mtab.active svg { transform: translateY(-1px); }
  .mtab.active::before {
    content: '';
    position: absolute;
    top: 0; left: 50%;
    transform: translateX(-50%);
    width: 24px;
    height: 2.5px;
    background: var(--accent);
    border-radius: 0 0 4px 4px;
    box-shadow: 0 0 8px var(--accent-glow);
  }
  /* Push content above bottom tabs on mobile */
  @media (max-width: 820px) {
    .shelves { padding-bottom: calc(120px + env(safe-area-inset-bottom)) !important; }
    .toast { bottom: calc(80px + env(safe-area-inset-bottom)); }
  }

  /* ============================================================
     HERO CAROUSEL
     ============================================================ */
  .hero {
    position: relative;
    width: 100%;
    height: 92vh;
    min-height: 580px;
    overflow: hidden;
    z-index: 2;
  }
  @media (max-width: 820px) {
    .hero { height: 78vh; min-height: 480px; }
  }
  .hero__slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 1.2s var(--ease-out-expo);
    pointer-events: none;
  }
  .hero__slide.active { opacity: 1; pointer-events: auto; }
  .hero__bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    animation: heroKenBurns 22s ease-in-out infinite alternate;
  }
  @keyframes heroKenBurns {
    0% { transform: scale(1) translateX(0); }
    100% { transform: scale(1.08) translateX(-1%); }
  }
  .hero__overlay {
    position: absolute;
    inset: 0;
    background:
      linear-gradient(to right, rgba(7,10,20,0.92) 0%, rgba(7,10,20,0.5) 35%, rgba(7,10,20,0.1) 60%, transparent 80%),
      linear-gradient(to top, var(--bg-base) 0%, transparent 35%, transparent 65%, rgba(7,10,20,0.45) 100%);
  }
  .hero__content {
    position: absolute;
    bottom: 12%;
    left: 5%;
    max-width: 560px;
    z-index: 2;
  }
  @media (max-width: 820px) {
    .hero__content { left: 16px; right: 16px; max-width: none; bottom: 10%; }
  }
  .hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--accent);
    margin-bottom: 18px;
    padding: 6px 12px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-soft);
    border-radius: 100px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
  }
  .hero__eyebrow::before {
    content: '';
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 8px var(--accent-glow);
    animation: pulse 2s ease-in-out infinite;
  }
  @keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.6; transform: scale(0.85); }
  }
  .hero__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(2.4rem, 5.5vw, 4.5rem);
    line-height: 0.95;
    letter-spacing: -0.045em;
    margin-bottom: 18px;
    color: var(--text-primary);
    text-wrap: balance;
  }
  .hero__title-img {
    display: block;
    width: clamp(220px, 36vw, 420px);
    height: auto;
    margin-bottom: 18px;
    filter: drop-shadow(0 4px 20px rgba(0,0,0,0.5));
  }
  .hero__meta {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 16px;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--text-secondary);
    letter-spacing: 0.02em;
  }
  .hero__meta-dot { width: 3px; height: 3px; border-radius: 50%; background: var(--text-muted); }
  .hero__desc {
    font-size: 1.05rem;
    line-height: 1.55;
    color: var(--text-secondary);
    margin-bottom: 28px;
    max-width: 480px;
    text-wrap: pretty;
  }
  @media (max-width: 820px) {
    .hero__desc { font-size: 0.95rem; margin-bottom: 22px; }
  }
  .hero__actions {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
  }
  @media (max-width: 480px) {
    .hero__actions { gap: 8px; }
    .hero__actions .btn { padding: 11px 18px; font-size: 0.88rem; flex: 1; min-width: 0; justify-content: center; }
  }
  .btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 13px 24px;
    font-family: var(--font-body);
    font-size: 0.94rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    border-radius: 100px;
    transition: all 0.25s var(--ease-out-quart);
    white-space: nowrap;
  }
  .btn svg { width: 16px; height: 16px; }
  .btn--primary {
    background: var(--text-primary);
    color: var(--bg-base);
  }
  .btn--primary:hover {
    background: var(--accent-bright);
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(94, 234, 212, 0.3);
  }
  .btn--ghost {
    background: var(--surface-2);
    color: var(--text-primary);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--border);
  }
  .btn--ghost:hover {
    background: var(--surface-3);
    border-color: var(--border-strong);
    transform: translateY(-1px);
  }
  .btn--icon {
    width: 44px;
    height: 44px;
    padding: 0;
    justify-content: center;
    border-radius: 50%;
  }
  .btn--icon svg { width: 18px; height: 18px; }

  /* Hero carousel dots */
  .hero__dots {
    position: absolute;
    bottom: 24px;
    right: 5%;
    display: flex;
    gap: 8px;
    z-index: 3;
  }
  @media (max-width: 820px) {
    .hero__dots { right: 16px; bottom: 16px; }
  }
  .hero__dot {
    width: 28px;
    height: 3px;
    background: rgba(255,255,255,0.2);
    border-radius: 100px;
    cursor: pointer;
    transition: background 0.3s, width 0.4s var(--ease-out-quart);
    position: relative;
    overflow: hidden;
  }
  .hero__dot.active {
    width: 44px;
    background: rgba(255,255,255,0.25);
  }
  .hero__dot.active::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--accent);
    transform-origin: left;
    animation: dotProgress 8s linear forwards;
  }
  @keyframes dotProgress {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
  }

  /* ============================================================
     ROWS / SHELVES
     ============================================================ */
  .shelves {
    position: relative;
    z-index: 3;
    margin-top: -8vh;
    padding-bottom: 120px;
    /* Smoothly fade in when navigate() swaps in new route content. The JS
       toggles .shelves--switching off after a frame so the transition runs. */
    transition: opacity 0.32s cubic-bezier(0.4, 0, 0.2, 1), transform 0.4s cubic-bezier(0.2, 0.85, 0.25, 1);
  }
  .shelves--switching {
    opacity: 0;
    transform: translateY(8px);
  }
  /* When no hero is shown (Series / Shorts / My List), restore top spacing */
  .shelves.shelves--no-hero {
    margin-top: 0;
    padding-top: calc(96px + env(safe-area-inset-top));
  }
  @media (max-width: 820px) {
    .shelves { margin-top: -4vh; padding-bottom: calc(100px + env(safe-area-inset-bottom)); }
    .shelves.shelves--no-hero { padding-top: calc(78px + env(safe-area-inset-top)); padding-bottom: calc(120px + env(safe-area-inset-bottom)); }
  }

  .row {
    position: relative;
    padding: 14px 0 6px;
  }
  .row__head {
    display: flex;
    align-items: baseline;
    justify-content: center;
    padding: 0 5vw 12px;
    gap: 16px;
    text-align: center;
  }
  @media (max-width: 820px) { .row__head { padding: 0 16px 10px; } }
  .row__title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: clamp(1.05rem, 1.8vw, 1.4rem);
    letter-spacing: -0.025em;
    color: var(--text-primary);
    text-align: center;
  }
  .row__see-all {
    font-family: var(--font-body);
    font-size: 0.82rem;
    color: var(--text-muted);
    letter-spacing: -0.005em;
    transition: color 0.2s;
  }
  .row__see-all:hover { color: var(--accent); }

  .row__viewport {
    position: relative;
  }
  .row__track {
    display: flex;
    gap: 12px;
    padding: 8px 5vw 18px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    scroll-snap-type: x proximity;
    scroll-behavior: smooth;
  }
  @media (max-width: 820px) {
    .row__track { padding: 8px 16px 18px; gap: 8px; }
  }
  .row__track::-webkit-scrollbar { display: none; }
  .row__track--large { padding-top: 12px; padding-bottom: 22px; }
  /* Center cards when there are too few to overflow the row — used by
     featured rows like Live Shows (only 3 series). Falls back to normal
     start-alignment if the cards do overflow, since flex justify-content
     centers within available space. */
  .row__track--center { justify-content: center; }
  @media (max-width: 820px) {
    /* On narrow viewports the row almost always overflows, so the centering
       becomes a no-op anyway — but explicit start-alignment guarantees the
       leftmost card is reachable when the track is wider than the viewport. */
    .row__track--center { justify-content: flex-start; }
  }

  /* Scroll arrows (desktop only) */
  .row__arrow {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 5vw;
    min-width: 60px;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(to right, var(--bg-base) 0%, rgba(7,10,20,0.85) 60%, transparent 100%);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s;
    color: var(--text-primary);
  }
  .row__arrow--right {
    right: 0;
    background: linear-gradient(to left, var(--bg-base) 0%, rgba(7,10,20,0.85) 60%, transparent 100%);
  }
  .row__arrow--left { left: 0; }
  .row__viewport:hover .row__arrow.visible { opacity: 1; pointer-events: auto; }
  .row__arrow-btn {
    width: 44px; height: 44px;
    border-radius: 50%;
    background: rgba(7, 10, 20, 0.85);
    border: 1px solid var(--border);
    backdrop-filter: blur(10px);
    display: grid;
    place-items: center;
    transition: transform 0.25s var(--ease-spring), background 0.2s;
  }
  .row__arrow-btn:hover { background: var(--bg-elevated); transform: scale(1.1); }
  .row__arrow-btn svg { width: 18px; height: 18px; }
  @media (max-width: 820px) { .row__arrow { display: none; } }

  /* ============================================================
     CARDS
     ============================================================ */
  .card {
    position: relative;
    flex-shrink: 0;
    height: 156px;
    aspect-ratio: 16/9;
    border-radius: 12px;
    overflow: hidden;
    cursor: pointer;
    background: var(--surface-1);
    transition: transform 0.4s var(--ease-out-quart), box-shadow 0.4s var(--ease-out-quart);
    scroll-snap-align: start;
    box-shadow: var(--shadow-md);
    will-change: transform;
  }
  .card--large {
    height: 230px;
  }
  /* Poster variant: portrait 2/3 — for film & series art that's poster-shaped */
  .card--poster {
    aspect-ratio: 2/3;
    height: 280px;
  }
  .card--poster.card--large {
    height: 320px;
  }
  @media (max-width: 820px) {
    .card { height: 122px; border-radius: 10px; }
    .card--large { height: 170px; }
    .card--poster { height: 220px; }
    .card--poster.card--large { height: 240px; }
  }
  @media (max-width: 480px) {
    .card--poster { height: 200px; }
    .card--poster.card--large { height: 220px; }
  }
  /* Touch-friendly: no scale hover lift, always-visible meta */
  @media (hover: none) {
    .card:hover, .card:active { transform: none; box-shadow: var(--shadow-md); }
    .card:active { transform: scale(0.97); transition-duration: 0.15s; }
    .card:hover .card__img, .card:active .card__img { transform: none; }
    .card__overlay {
      opacity: 1;
      transform: none;
      background: linear-gradient(to top, rgba(7,10,20,0.92) 0%, rgba(7,10,20,0.55) 50%, transparent 100%);
      padding: 24px 12px 10px;
    }
    .card__title { font-size: 0.82rem; }
    .card__meta { font-size: 0.62rem; }
  }
  .card__img {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    transition: transform 0.6s var(--ease-out-quart);
  }
  .card:hover {
    transform: translateY(-4px) scale(1.04);
    box-shadow: var(--shadow-card-hover);
    z-index: 10;
  }
  .card:hover .card__img { transform: scale(1.06); }

  /* ============================================================
     COMING SOON ROW — placeholder cards for unreleased content.
     Each card is a non-clickable shimmer-animated tile. The whole
     row is intentionally distinct from the normal shelves so users
     immediately understand "this is upcoming, not playable yet."
     ============================================================ */
  .card--placeholder {
    cursor: pointer;
    background: linear-gradient(135deg, rgba(94, 234, 212, 0.06) 0%, rgba(120, 80, 180, 0.03) 100%);
    border: 1.5px dashed rgba(94, 234, 212, 0.22);
    box-shadow: none;
  }
  .card--placeholder:hover {
    transform: none;
    border-color: rgba(94, 234, 212, 0.45);
    box-shadow: 0 0 0 1px rgba(94, 234, 212, 0.12), 0 8px 24px -8px rgba(94, 234, 212, 0.2);
  }
  /* Smooth, slow diagonal shimmer. Default duration bumped from 2.8s to 3.6s
     and easing changed to linear so the wave moves at constant pace (no
     accel/decel "ease-in-out" bump). Each card gets its own duration AND
     delay via inline CSS variables so the row never falls into lockstep. */
  .placeholder-shimmer {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      105deg,
      transparent 25%,
      rgba(94, 234, 212, 0.10) 50%,
      transparent 75%
    );
    background-size: 250% 100%;
    animation: shimmer-sweep var(--shimmer-duration, 3.6s) linear var(--shimmer-delay, 0s) infinite;
    pointer-events: none;
  }
  @keyframes shimmer-sweep {
    0%   { background-position: 250% 0; }
    100% { background-position: -150% 0; }
  }
  /* Decorative "frame markers" — softened from 1.5px solid to 1px and
     dimmed to feel more like genuine wireframe than a loud accent. */
  .placeholder-shimmer::before,
  .placeholder-shimmer::after {
    content: '';
    position: absolute;
    width: 18px;
    height: 18px;
    border: 1px solid rgba(94, 234, 212, 0.3);
  }
  .placeholder-shimmer::before {
    top: 10px;
    left: 10px;
    border-right: none;
    border-bottom: none;
    border-top-left-radius: 4px;
  }
  .placeholder-shimmer::after {
    bottom: 10px;
    right: 10px;
    border-left: none;
    border-top: none;
    border-bottom-right-radius: 4px;
  }
  @media (max-width: 820px) {
    .placeholder-shimmer::before,
    .placeholder-shimmer::after { width: 14px; height: 14px; }
  }
  /* "Coming Soon" pulsing dot next to the row title. */
  .coming-soon-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    background: var(--accent);
    border-radius: 50%;
    margin-right: 7px;
    vertical-align: middle;
    animation: coming-soon-dot-pulse 1.8s ease-in-out infinite;
  }
  @keyframes coming-soon-dot-pulse {
    0%, 100% {
      opacity: 1;
      transform: scale(1);
      box-shadow: 0 0 0 0 rgba(94, 234, 212, 0.55);
    }
    70% {
      box-shadow: 0 0 0 10px rgba(94, 234, 212, 0);
    }
    100% {
      opacity: 1;
      transform: scale(1);
      box-shadow: 0 0 0 0 rgba(94, 234, 212, 0);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .placeholder-shimmer,
    .coming-soon-dot { animation: none !important; }
  }

  /* Card hover overlay with metadata */
  .card__overlay {
    position: absolute;
    inset: auto 0 0 0;
    padding: 12px 14px 12px;
    background: linear-gradient(to top, rgba(7,10,20,0.95) 20%, rgba(7,10,20,0.6) 70%, transparent 100%);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 0.3s, transform 0.3s var(--ease-out-quart);
    pointer-events: none;
  }
  .card:hover .card__overlay {
    opacity: 1;
    transform: translateY(0);
  }
  .card__title {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-primary);
    letter-spacing: -0.015em;
    line-height: 1.2;
    margin-bottom: 4px;
    text-shadow: 0 1px 3px rgba(0,0,0,0.6);
  }
  .card__meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--text-secondary);
    letter-spacing: 0.02em;
  }
  .card__meta-dot { width: 2px; height: 2px; border-radius: 50%; background: var(--text-muted); }

  /* Series badge */
  .card__badge {
    position: absolute;
    top: 10px; left: 10px;
    padding: 4px 9px;
    background: rgba(7,10,20,0.7);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 100px;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent);
    z-index: 2;
  }

  /* Save button (top-right of card) */
  .card__save {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 32px; height: 32px;
    border-radius: 50%;
    background: rgba(7, 10, 20, 0.55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255,255,255,0.12);
    color: var(--text-primary);
    display: grid;
    place-items: center;
    opacity: 0;
    transform: translateY(-4px) scale(0.9);
    transition: opacity 0.22s, transform 0.25s var(--ease-spring), background 0.2s, color 0.2s;
    z-index: 3;
    cursor: pointer;
  }
  .card__save svg { width: 14px; height: 14px; }
  .card:hover .card__save { opacity: 1; transform: translateY(0) scale(1); }
  .card__save:hover { background: rgba(7, 10, 20, 0.85); }
  .card__save.active {
    color: var(--accent);
    background: rgba(94, 234, 212, 0.18);
    border-color: rgba(94, 234, 212, 0.4);
    opacity: 1; /* always visible when saved */
    transform: translateY(0) scale(1);
  }
  .card.is-saved .card__save { opacity: 1; transform: translateY(0) scale(1); }
  /* On touch: always visible, slightly larger */
  @media (hover: none) {
    .card__save {
      opacity: 1;
      transform: none;
      width: 34px; height: 34px;
      top: 6px; right: 6px;
    }
    .card__save svg { width: 15px; height: 15px; }
  }

  /* Continue Watching progress bar */
  .card__progress {
    position: absolute;
    bottom: 0; left: 0; right: 0;
    height: 3px;
    background: rgba(255,255,255,0.18);
    z-index: 3;
  }
  .card__progress-fill {
    height: 100%;
    background: var(--accent);
    box-shadow: 0 0 8px var(--accent-glow);
    transition: width 0.4s;
  }

  /* Preview video on hover — crossfades smoothly with no pop */
  .card__preview {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    overflow: hidden;
    opacity: 0;
    transition: opacity 0.22s ease-out;
    pointer-events: none;
    background: #000;
  }
  .card__preview video {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
  }
  .card__preview.active { opacity: 1; }
  /* No previews on touch devices — saves bandwidth, avoids accidental triggers */
  @media (hover: none) { .card__preview { display: none !important; } }

  /* ============================================================
     SEARCH OVERLAY
     ============================================================ */
  .search-overlay {
    position: fixed;
    inset: 0;
    z-index: 100000;
    background: rgba(7, 10, 20, 0.85);
    backdrop-filter: blur(30px) saturate(180%);
    -webkit-backdrop-filter: blur(30px) saturate(180%);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s var(--ease-smooth);
    display: flex;
    flex-direction: column;
    padding-top: calc(60px + env(safe-area-inset-top));
  }
  .search-overlay.open { opacity: 1; pointer-events: auto; }
  .search-overlay__container {
    width: min(720px, 90%);
    margin: 0 auto;
    padding: 0 20px;
    transform: translateY(-20px);
    transition: transform 0.4s var(--ease-out-expo);
    flex: 1;
    overflow-y: auto;
    padding-bottom: 60px;
  }
  .search-overlay.open .search-overlay__container { transform: translateY(0); }
  .search-overlay__container::-webkit-scrollbar { display: none; }

  .search-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px 22px;
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: 16px;
    margin-bottom: 28px;
    transition: border-color 0.25s, background 0.25s;
  }
  .search-input-wrap:focus-within {
    border-color: var(--accent);
    background: var(--surface-2);
    box-shadow: 0 0 0 4px var(--accent-soft);
  }
  .search-input-wrap svg { width: 20px; height: 20px; color: var(--text-muted); flex-shrink: 0; }
  .search-clear {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--surface-2);
    color: var(--text-muted);
    display: none;
    place-items: center;
    flex-shrink: 0;
    transition: background 0.18s, color 0.18s;
    cursor: pointer;
  }
  .search-clear svg { width: 12px !important; height: 12px !important; color: inherit; }
  .search-clear:hover { background: var(--surface-3); color: var(--text-primary); }
  .search-clear.visible { display: grid; }
  .search-input {
    flex: 1;
    background: none;
    border: none;
    outline: none;
    color: var(--text-primary);
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 500;
    letter-spacing: -0.02em;
    width: 100%;
    min-width: 0;
  }
  .search-input::placeholder { color: var(--text-faint); }
  .search-kbd {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--text-muted);
    padding: 4px 8px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface-1);
    white-space: nowrap;
  }
  @media (max-width: 600px) {
    .search-kbd { display: none; }
    .search-overlay { padding-top: calc(20px + env(safe-area-inset-top)); }
    .search-overlay__container { padding: 0 14px; padding-bottom: calc(80px + env(safe-area-inset-bottom)); }
    .search-input-wrap { padding: 14px 16px; margin-bottom: 18px; border-radius: 14px; }
    .search-input { font-size: 1.15rem; }
    .search-section { margin-bottom: 22px; }
    .search-result { padding: 12px 10px; }
    .search-result__thumb { width: 84px; height: 50px; }
    .search-result__title { font-size: 0.95rem; white-space: normal; }
    .search-result__meta { font-size: 0.72rem; margin-top: 4px; }
  }

  .search-section { margin-bottom: 32px; }
  .search-section__title {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.15em;
    color: var(--text-muted);
    margin-bottom: 12px;
    padding: 0 4px;
  }
  .search-results { display: flex; flex-direction: column; gap: 4px; }
  .search-result {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 12px;
    border-radius: 10px;
    cursor: pointer;
    transition: background 0.18s;
  }
  .search-result:hover, .search-result.focused {
    background: var(--surface-2);
  }
  .search-result.focused {
    box-shadow: inset 0 0 0 1px var(--accent-soft);
  }
  .search-result__thumb {
    width: 72px; height: 42px;
    border-radius: 6px;
    object-fit: cover;
    flex-shrink: 0;
    background: var(--surface-2);
  }
  .search-result__info { flex: 1; min-width: 0; }
  .search-result__title {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .search-result__meta {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--text-muted);
    letter-spacing: 0.02em;
    margin-top: 2px;
  }
  .search-result__meta mark {
    background: var(--accent-soft);
    color: var(--accent-bright);
    padding: 1px 4px;
    border-radius: 3px;
  }
  .search-result__title mark {
    background: var(--accent-soft);
    color: var(--accent-bright);
    padding: 0 2px;
    border-radius: 3px;
  }
  .search-empty {
    text-align: center;
    padding: 60px 20px;
    color: var(--text-muted);
    font-size: 0.95rem;
  }
  .search-empty strong { color: var(--text-primary); font-weight: 500; }

  /* Category chips inside search */
  .category-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 4px;
  }
  .chip {
    padding: 8px 14px;
    font-family: var(--font-body);
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--text-secondary);
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: 100px;
    transition: all 0.2s;
    cursor: pointer;
  }
  .chip:hover {
    background: var(--surface-2);
    color: var(--text-primary);
    border-color: var(--border-strong);
  }
  .chip.active {
    background: var(--accent);
    color: var(--bg-base);
    border-color: var(--accent);
  }

  /* ============================================================
     FILTERED VIEW (Series / Shorts / My List)
     ============================================================ */
  .filtered-head {
    padding: 8px 5vw 4px;
    text-align: center;
  }
  @media (max-width: 820px) { .filtered-head { padding: 4px 16px 2px; } }
  .filtered-head__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(1.8rem, 4vw, 2.6rem);
    letter-spacing: -0.035em;
    color: var(--text-primary);
    line-height: 1;
    margin: 0;
  }
  /* Count tagline intentionally hidden — kept in markup so we don't have to
     change every render call, but hidden so the page heading stays clean. */
  .filtered-head__count { display: none; }
  .sub-filter-bar {
    display: flex;
    gap: 8px;
    padding: 18px 5vw 12px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    justify-content: center;
    flex-wrap: wrap;
  }
  .sub-filter-bar::-webkit-scrollbar { display: none; }
  @media (max-width: 820px) { .sub-filter-bar { padding: 14px 16px 10px; } }
  .sub-filter-bar .chip { flex-shrink: 0; }
  .filtered-grid {
    display: grid;
    gap: 14px;
    padding: 14px 5vw 60px;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  }
  .filtered-grid--posters {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  }
  /* In a grid the card must fill its cell — otherwise the cards keep their
     row-row fixed height (156/230/etc.) and derive width from aspect-ratio,
     which overflows the column. Switching to width:100% + height:auto lets
     aspect-ratio drive the height, so cards align to their grid cells. */
  .filtered-grid .card {
    width: 100%;
    height: auto;
  }
  @media (max-width: 820px) {
    .filtered-grid {
      padding: 10px 16px 60px;
      gap: 10px;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }
    .filtered-grid--posters {
      grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    }
  }
  @media (max-width: 380px) {
    .filtered-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
    .filtered-grid--posters { grid-template-columns: repeat(2, 1fr); }
  }

  /* ============================================================
     EPISODE PICKER
     A multi-layer cinematic open animation:
       1. Backdrop fades + blurs in (200ms)
       2. Container scales/lifts/un-blurs in with a slight rotateX (500ms)
       3. Banner background fades and ken-burns subtly (700ms)
       4. Banner logo + close button drop in (350ms after container settles)
       5. Episode rows stagger-fade in from below (~60ms apart)
     The cumulative effect: open feels like a theater curtain rather than
     a generic dialog. Reversed on close.
     ============================================================ */
  .episode-picker {
    position: fixed;
    inset: 0;
    z-index: 100000;
    /* Two layered backdrops: the dim color first, with the blur on the
       pseudo-element below so we can animate them separately. */
    background: rgba(7, 10, 20, 0); /* fades in */
    backdrop-filter: blur(0);
    -webkit-backdrop-filter: blur(0);
    display: none;
    align-items: flex-start;
    justify-content: center;
    opacity: 1;
    transition:
      background 0.4s cubic-bezier(0.5, 0, 0.2, 1),
      backdrop-filter 0.4s cubic-bezier(0.5, 0, 0.2, 1),
      -webkit-backdrop-filter 0.4s cubic-bezier(0.5, 0, 0.2, 1);
    padding: 60px 20px;
    overflow-y: auto;
    /* 3D space for the container's rotateX entrance */
    perspective: 1500px;
  }
  .episode-picker.visible {
    display: flex;
    background: rgba(7, 10, 20, 0.7);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
  }
  @media (max-width: 820px) {
    .episode-picker { padding: 0; align-items: stretch; perspective: none; }
  }
  .episode-picker__container {
    background: var(--bg-elevated);
    border-radius: 18px;
    width: 100%;
    max-width: 880px;
    overflow: hidden;
    border: 1px solid var(--border);
    box-shadow: 0 40px 100px rgba(0,0,0,0.75), 0 0 0 1px rgba(94, 234, 212, 0);
    /* Initial state: pushed down, scaled down, tilted away, blurred. */
    transform: translateY(60px) scale(0.88) rotateX(-8deg);
    transform-origin: center top;
    opacity: 0;
    filter: blur(8px);
    transition:
      transform 0.7s cubic-bezier(0.16, 1, 0.3, 1) 80ms,
      opacity 0.5s cubic-bezier(0.5, 0, 0.2, 1) 80ms,
      filter 0.5s cubic-bezier(0.5, 0, 0.2, 1) 80ms,
      box-shadow 0.7s cubic-bezier(0.16, 1, 0.3, 1) 80ms;
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 120px);
    will-change: transform, opacity, filter;
  }
  .episode-picker.visible .episode-picker__container {
    transform: translateY(0) scale(1) rotateX(0);
    opacity: 1;
    filter: blur(0);
    /* Subtle teal glow at the end of the entrance to emphasize arrival */
    box-shadow: 0 40px 100px rgba(0,0,0,0.75), 0 0 0 1px rgba(94, 234, 212, 0.08);
  }
  @media (max-width: 820px) {
    .episode-picker__container {
      border-radius: 0;
      max-height: 100vh;
      height: 100vh;
      max-width: none;
      /* Slide-up rather than rotate-zoom on mobile (full-screen sheet feel) */
      transform: translateY(100%);
      filter: none;
    }
    .episode-picker.visible .episode-picker__container {
      transform: translateY(0);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .episode-picker, .episode-picker__container {
      transition-duration: 0.15s !important;
      transition-delay: 0s !important;
    }
    .episode-picker__container {
      transform: none !important;
      filter: none !important;
    }
  }
  .episode-picker__banner {
    position: relative;
    width: 100%;
    height: 280px;
    flex-shrink: 0;
    overflow: hidden;
  }
  @media (max-width: 820px) {
    .episode-picker__banner { height: 220px; }
  }
  .episode-picker__banner-img {
    width: 100%; height: 100%;
    object-fit: cover;
    filter: brightness(0.55);
    /* Subtle "ken burns" — starts slightly larger and zoomed in, settles to
       its natural size as the picker finishes opening. Combined with the
       container's blur-to-clear, this gives the banner a cinematic quality. */
    transform: scale(1.12);
    transition: transform 1.6s cubic-bezier(0.16, 1, 0.3, 1) 200ms;
  }
  .episode-picker.visible .episode-picker__banner-img {
    transform: scale(1.02);
  }
  .episode-picker__banner-fade {
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, rgba(7,10,20,0.4) 0%, transparent 40%, var(--bg-elevated) 100%);
  }
  .episode-picker__banner-logo {
    position: absolute;
    bottom: 24px;
    left: 28px;
    width: clamp(180px, 30vw, 340px);
    height: auto;
    filter: drop-shadow(0 4px 16px rgba(0,0,0,0.6));
    /* Logo drops in shortly after the container settles, building the layered
       feeling of the reveal. */
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity 0.5s cubic-bezier(0.5, 0, 0.2, 1) 320ms,
      transform 0.5s cubic-bezier(0.2, 0.85, 0.25, 1) 320ms;
  }
  .episode-picker.visible .episode-picker__banner-logo {
    opacity: 1;
    transform: translateY(0);
  }
  .episode-picker__back {
    position: absolute;
    top: 20px; left: 20px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px;
    background: rgba(7,10,20,0.6);
    border: 1px solid var(--border);
    border-radius: 100px;
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.82rem;
    font-weight: 500;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: background 0.2s, transform 0.2s var(--ease-spring);
  }
  .episode-picker__back:hover { background: rgba(7,10,20,0.85); transform: translateX(-2px); }
  .episode-picker__back svg { width: 14px; height: 14px; }

  .episode-picker__list {
    flex: 1;
    overflow-y: auto;
    padding: 12px 24px 32px;
    scrollbar-width: thin;
    scrollbar-color: var(--surface-3) transparent;
  }
  .episode-picker__list::-webkit-scrollbar { width: 6px; }
  .episode-picker__list::-webkit-scrollbar-track { background: transparent; }
  .episode-picker__list::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 3px; }
  @media (max-width: 820px) {
    .episode-picker__list { padding: 12px 16px 32px; }
  }

  .episode {
    display: flex;
    gap: 16px;
    padding: 16px 0;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    border-radius: 10px;
    padding-left: 12px;
    padding-right: 12px;
    margin-left: -12px;
    margin-right: -12px;
    /* Initial state for the picker-open stagger reveal. Each row is offset
       and faded out; the picker's .visible class triggers them in sequence
       via the per-child transition-delay rules below. The shared transition
       includes background for hover, transform for stagger + active state. */
    opacity: 0;
    transform: translateY(22px);
    transition:
      background 0.15s,
      opacity 0.5s cubic-bezier(0.2, 0.85, 0.25, 1),
      transform 0.5s cubic-bezier(0.2, 0.85, 0.25, 1);
  }
  .episode-picker.visible .episode {
    opacity: 1;
    transform: translateY(0);
  }
  /* Stagger — each episode row appears ~70ms after the previous, creating a
     waterfall effect that draws the eye downward through the list. */
  .episode-picker.visible .episode:nth-child(1) { transition-delay: 0.38s, 0.38s, 0.38s; }
  .episode-picker.visible .episode:nth-child(2) { transition-delay: 0.45s, 0.45s, 0.45s; }
  .episode-picker.visible .episode:nth-child(3) { transition-delay: 0.52s, 0.52s, 0.52s; }
  .episode-picker.visible .episode:nth-child(4) { transition-delay: 0.59s, 0.59s, 0.59s; }
  .episode-picker.visible .episode:nth-child(5) { transition-delay: 0.66s, 0.66s, 0.66s; }
  .episode-picker.visible .episode:nth-child(6) { transition-delay: 0.73s, 0.73s, 0.73s; }
  .episode-picker.visible .episode:nth-child(7) { transition-delay: 0.80s, 0.80s, 0.80s; }
  .episode-picker.visible .episode:nth-child(n+8) { transition-delay: 0.86s, 0.86s, 0.86s; }
  @media (prefers-reduced-motion: reduce) {
    .episode, .episode-picker.visible .episode {
      transition-delay: 0s !important;
      transform: none !important;
    }
  }
  .episode:hover { background: var(--surface-1); }
  .episode:active { background: var(--surface-2); }
  .episode:last-child { border-bottom: none; }
  @media (max-width: 600px) {
    .episode { gap: 12px; padding: 14px 10px; margin: 0 -10px; }
  }
  .episode__num {
    font-family: var(--font-mono);
    font-size: 1.4rem;
    font-weight: 400;
    color: var(--text-faint);
    min-width: 28px;
    line-height: 1;
    margin-top: 6px;
    letter-spacing: -0.02em;
  }
  .episode__thumb-wrap {
    position: relative;
    flex-shrink: 0;
    width: 168px;
    aspect-ratio: 16/9;
    border-radius: 8px;
    overflow: hidden;
  }
  @media (max-width: 600px) {
    .episode__thumb-wrap { width: 120px; }
    .episode__num { display: none; }
  }
  .episode__thumb {
    width: 100%; height: 100%;
    object-fit: cover;
    transition: transform 0.4s var(--ease-out-quart);
  }
  .episode__thumb-wrap:hover .episode__thumb { transform: scale(1.05); }
  .episode__play-icon {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    background: rgba(7,10,20,0.4);
    opacity: 0;
    transition: opacity 0.25s;
  }
  .episode__thumb-wrap:hover .episode__play-icon { opacity: 1; }
  .episode__play-icon svg { width: 36px; height: 36px; color: var(--text-primary); filter: drop-shadow(0 2px 8px rgba(0,0,0,0.6)); }
  .episode__progress {
    position: absolute;
    bottom: 0; left: 0; right: 0;
    height: 3px;
    background: rgba(255,255,255,0.18);
  }
  .episode__progress-fill {
    height: 100%;
    background: var(--accent);
  }
  .episode__details { flex: 1; min-width: 0; }
  .episode__title-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 6px;
  }
  .episode__title {
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -0.015em;
    color: var(--text-primary);
    line-height: 1.25;
  }
  .episode__runtime {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--text-muted);
    white-space: nowrap;
    letter-spacing: 0.02em;
  }
  .episode__desc {
    font-size: 0.88rem;
    line-height: 1.5;
    color: var(--text-secondary);
    text-wrap: pretty;
  }

  /* ============================================================
     LIGHTBOX / PLAYER
     ============================================================ */
  /* ============================================================
     LIGHTBOX / PLAYER
     The container scales up from 0.93 and the backdrop fades in. The two
     transitions are timed so the backdrop arrives slightly ahead of the
     content, giving the impression that the video is rising into a darkened
     room rather than just appearing. Closing reverses cleanly.
     ============================================================ */
  .lightbox {
    display: none;
    opacity: 0;
    position: fixed;
    inset: 0;
    z-index: 999990;
    background: #000;
    justify-content: center;
    align-items: center;
    transition: opacity 0.42s cubic-bezier(0.5, 0, 0.2, 1);
  }
  .lightbox.visible { display: flex; opacity: 1; }
  .lightbox__content {
    position: relative;
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
    background: #000;
    /* Default (closed) state: noticeably small, lifted, and heavily blurred so
       the open animation is unmistakably visible. The 80ms delay holds the
       content offscreen for a beat while the backdrop catches up. Previous
       values (scale 0.93, translateY 28px, blur 6px) were too subtle to read
       as an intentional animation — bumped to scale 0.82, translateY 60px,
       blur 14px for clearer perceived motion, especially on the episode→
       lightbox transition where the picker just disappeared. */
    transform: scale(0.82) translateY(60px);
    opacity: 0;
    transition:
      transform 0.62s cubic-bezier(0.16, 1, 0.3, 1) 80ms,
      opacity 0.5s cubic-bezier(0.5, 0, 0.2, 1) 80ms,
      filter 0.62s cubic-bezier(0.16, 1, 0.3, 1) 80ms;
    filter: blur(14px);
    will-change: transform, opacity, filter;
  }
  .lightbox.visible .lightbox__content {
    transform: scale(1) translateY(0);
    opacity: 1;
    filter: blur(0);
  }
  @media (prefers-reduced-motion: reduce) {
    .lightbox, .lightbox__content {
      transition-duration: 0.15s !important;
      transition-delay: 0s !important;
    }
    .lightbox__content {
      transform: none !important;
      filter: none !important;
    }
  }
  .video-container {
    position: relative;
    width: 100%;
    height: 100vh;
    max-width: calc(100vh * 16/9);
    max-height: calc(100vw * 9/16);
    background: #000;
    margin: 0 auto;
  }
  /* On mobile portrait, remove the 16:9 aspect constraint on the video
     container so it fills the entire viewport. The video element inside
     uses `object-fit: contain` so it stays at its native aspect with black
     bars above/below — but now the Plyr controls bar sits at the bottom of
     the *screen* instead of the bottom of the (vertically centered, short)
     video element. This is what users expect from full-screen video players
     on phones: controls at the bottom of the device, not floating in the
     middle of black space. */
  @media (max-width: 820px) {
    .video-container {
      max-width: none !important;
      max-height: none !important;
      width: 100vw !important;
      height: 100vh !important;
    }
  }
  #lightboxVideo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    transition: opacity 0.5s var(--ease-smooth);
    z-index: 1;
  }
  #videoLoadingOverlay {
    position: absolute;
    inset: 0;
    background: #000;
    opacity: 1;
    transition: opacity 0.5s var(--ease-smooth);
    z-index: 5;
    pointer-events: none;
    display: grid;
    place-items: center;
  }
  /* Error state: clickable, sits ABOVE the player-top (z-index 10) so the
     Retry/Close buttons can't be intercepted by the player-top bar on small
     mobile viewports where the centered error UI may overlap the top region. */
  #videoLoadingOverlay.error {
    pointer-events: auto !important;
    z-index: 12;
    background: rgba(7, 10, 20, 0.96);
  }
  .player-loader {
    width: 48px; height: 48px;
    border-radius: 50%;
    border: 2px solid rgba(94, 234, 212, 0.2);
    border-top-color: var(--accent);
    animation: spin 0.9s linear infinite;
  }
  @keyframes spin { to { transform: rotate(360deg); } }
  /* Player error state */
  .player-error {
    max-width: 400px;
    text-align: center;
    padding: 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
  }
  .player-error svg {
    width: 48px;
    height: 48px;
    color: var(--text-faint);
  }
  .player-error__title {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text-primary);
    letter-spacing: -0.02em;
  }
  .player-error__msg {
    font-size: 0.92rem;
    color: var(--text-secondary);
    line-height: 1.5;
  }
  .player-error__actions {
    display: flex;
    gap: 10px;
    margin-top: 6px;
    flex-wrap: wrap;
    justify-content: center;
  }

  /* ============================================================
     PLAYER TOP BAR — completely rebuilt (close-button reliability).
     ============================================================
     Now lives as a direct child of .lightbox (not inside .lightbox__content),
     so transform/blur on .lightbox__content during open animations can't
     affect its hit-testing or positioning. position: absolute relative to
     .lightbox (which is position: fixed at viewport), z-index 100 to sit
     above EVERYTHING else inside the lightbox. No auto-hide, no dimming,
     no pointer-events games — the back button is permanently fully visible
     and fully clickable from the moment the lightbox opens. */
  .player-top {
    position: absolute;
    top: 0; left: 0; right: 0;
    padding: 24px 32px;
    padding-top: calc(24px + env(safe-area-inset-top));
    background: linear-gradient(to bottom, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.5) 50%, transparent 100%);
    z-index: 100;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    /* Fade in alongside the lightbox so it doesn't pop in instantly while
       the rest of the player animates. */
    opacity: 0;
    transition: opacity 0.42s cubic-bezier(0.5, 0, 0.2, 1) 200ms;
    pointer-events: auto;
  }
  .lightbox.visible .player-top {
    opacity: 1;
  }
  .player-top__left { display: flex; align-items: center; gap: 20px; min-width: 0; flex: 1; }
  .player-back {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    background: rgba(0,0,0,0.4);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 100px;
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.88rem;
    font-weight: 500;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: background 0.2s, transform 0.2s var(--ease-spring);
  }
  .player-back:hover { background: rgba(0,0,0,0.7); transform: translateX(-2px); }
  .player-back svg { width: 14px; height: 14px; }
  .player-title-wrap { display: flex; flex-direction: column; gap: 4px; }
  .player-title {
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 600;
    letter-spacing: -0.025em;
    color: var(--text-primary);
    line-height: 1.1;
  }
  @media (max-width: 820px) {
    /* On mobile the top bar is tighter — the back button shrinks, the title
       gets smaller, and crucially we vertically center the row (instead of
       align-items: flex-start at desktop) so the back button is visually
       centered against the title text rather than aligned to the top of it.
       The title-wrap also gets min-width:0 + flex:1 so a long title can
       shrink and ellipsis-truncate instead of pushing the layout. */
    .player-top {
      padding: 16px 18px;
      padding-top: calc(16px + env(safe-area-inset-top));
      align-items: center;
    }
    .player-top__left {
      min-width: 0;       /* allows children to shrink */
      flex: 1;            /* take available width */
      align-items: center; /* keep back-button centered with title */
      gap: 14px;
    }
    .player-title { font-size: 1.05rem; }
    .player-back {
      padding: 8px 12px;
      font-size: 0.78rem;
      flex-shrink: 0;     /* never let the back button itself collapse */
    }
    .player-title-wrap {
      min-width: 0;
      flex: 1;
      gap: 2px;           /* tighter than desktop */
    }
    .player-title {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .player-subtitle {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 0.68rem; /* slightly smaller on mobile */
    }
  }
  .player-subtitle {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-secondary);
    letter-spacing: 0.05em;
  }
  /* When a video has no subtitle (commercials, plays from hero), the subtitle
     element is given empty text content. Collapse it entirely so it doesn't
     reserve vertical space and shift the title's baseline. */
  .player-subtitle:empty { display: none; }
  .player-top__right {
    display: flex;
    gap: 8px;
  }
  .player-tool-btn {
    width: 40px; height: 40px;
    border-radius: 50%;
    background: rgba(0,0,0,0.4);
    border: 1px solid rgba(255,255,255,0.12);
    color: var(--text-primary);
    display: grid;
    place-items: center;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: all 0.2s;
  }
  .player-tool-btn:hover { background: rgba(0,0,0,0.7); border-color: var(--accent); color: var(--accent); }
  .player-tool-btn.active { background: var(--accent); color: var(--bg-base); border-color: var(--accent); }
  .player-tool-btn svg { width: 16px; height: 16px; }
  @media (max-width: 600px) {
    .player-tool-btn { width: 36px; height: 36px; }
  }

  /* Next Episode card */
  #nextEpisodeOverlay {
    position: fixed;
    bottom: 110px;
    right: 32px;
    z-index: 100;
    display: none;
    transform: translateY(30px);
    opacity: 0;
    transition: transform 0.5s var(--ease-out-expo), opacity 0.5s;
  }
  #nextEpisodeOverlay.active { display: block; transform: translateY(0); opacity: 1; }
  @media (max-width: 820px) {
    #nextEpisodeOverlay { bottom: 120px; right: 16px; left: 16px; }
  }
  .next-episode-card {
    background: rgba(15, 20, 36, 0.92);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid var(--border-strong);
    border-radius: 14px;
    padding: 14px;
    display: flex;
    gap: 12px;
    align-items: center;
    width: 320px;
    box-shadow: 0 12px 40px rgba(0,0,0,0.5);
  }
  @media (max-width: 820px) { .next-episode-card { width: 100%; } }
  .next-episode-card__label {
    font-family: var(--font-mono);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.15em;
    color: var(--accent);
    margin-bottom: 3px;
  }
  .next-episode-card__title {
    font-family: var(--font-display);
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--text-primary);
    letter-spacing: -0.01em;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .next-episode-card__btn {
    margin-left: auto;
    padding: 9px 14px;
    background: var(--accent);
    color: var(--bg-base);
    font-family: var(--font-body);
    font-size: 0.82rem;
    font-weight: 600;
    border-radius: 100px;
    transition: transform 0.2s var(--ease-spring), background 0.2s;
  }
  .next-episode-card__btn:hover { background: var(--accent-bright); transform: scale(1.04); }

  /* Captions toggle indicator (badge near title when on) */
  .captions-badge {
    display: inline-block;
    padding: 2px 7px;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.1em;
    border-radius: 4px;
    background: var(--accent-soft);
    color: var(--accent);
    margin-left: 8px;
    vertical-align: middle;
  }

  /* ============================================================
     TRANSCRIPT PANEL
     ============================================================ */
  .transcript-panel {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: 420px;
    max-width: 92vw;
    background: rgba(7, 10, 20, 0.95);
    backdrop-filter: blur(22px) saturate(180%);
    -webkit-backdrop-filter: blur(22px) saturate(180%);
    border-left: 1px solid var(--border);
    z-index: 999999;
    transform: translateX(100%);
    transition: transform 0.5s var(--ease-out-expo);
    display: flex;
    flex-direction: column;
    box-shadow: -20px 0 60px rgba(0,0,0,0.5);
  }
  .transcript-panel.open { transform: translateX(0); }
  /* Mobile: bottom sheet instead of side panel */
  @media (max-width: 600px) {
    .transcript-panel {
      top: auto;
      right: 0;
      left: 0;
      bottom: 0;
      width: 100%;
      max-width: none;
      height: 75vh;
      border-left: none;
      border-top: 1px solid var(--border);
      border-radius: 18px 18px 0 0;
      transform: translateY(100%);
      box-shadow: 0 -20px 60px rgba(0,0,0,0.5);
    }
    .transcript-panel.open { transform: translateY(0); }
    /* Drag handle */
    .transcript-panel::before {
      content: '';
      position: absolute;
      top: 8px;
      left: 50%;
      transform: translateX(-50%);
      width: 36px;
      height: 4px;
      border-radius: 2px;
      background: var(--surface-3);
    }
    .transcript-panel__head { padding-top: 22px; }
  }
  .transcript-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 22px 24px 16px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
  }
  .transcript-panel__title {
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 600;
    letter-spacing: -0.02em;
  }
  .transcript-panel__close {
    width: 32px; height: 32px;
    border-radius: 50%;
    color: var(--text-muted);
    display: grid;
    place-items: center;
    transition: background 0.2s, color 0.2s;
  }
  .transcript-panel__close:hover { background: var(--surface-2); color: var(--text-primary); }
  .transcript-panel__close svg { width: 16px; height: 16px; }
  .transcript-panel__search {
    padding: 12px 24px 16px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
  }
  .transcript-panel__search input {
    width: 100%;
    padding: 10px 14px;
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.88rem;
    outline: none;
    transition: border-color 0.2s, background 0.2s;
  }
  .transcript-panel__search input:focus { border-color: var(--accent); background: var(--surface-2); }
  .transcript-panel__search input::placeholder { color: var(--text-faint); }
  .transcript-panel__body {
    flex: 1;
    overflow-y: auto;
    padding: 16px 8px 32px;
    scrollbar-width: thin;
    scrollbar-color: var(--surface-3) transparent;
  }
  .transcript-panel__body::-webkit-scrollbar { width: 4px; }
  .transcript-panel__body::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 2px; }
  .transcript-line {
    display: flex;
    gap: 14px;
    padding: 10px 16px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.18s;
  }
  .transcript-line:hover { background: var(--surface-1); }
  .transcript-line.active {
    background: var(--accent-soft);
  }
  .transcript-line.active .transcript-line__time { color: var(--accent); }
  .transcript-line.active .transcript-line__text { color: var(--text-primary); }
  .transcript-line__time {
    font-family: var(--font-mono);
    font-size: 0.74rem;
    color: var(--text-faint);
    flex-shrink: 0;
    width: 44px;
    line-height: 1.55;
    letter-spacing: 0.02em;
    padding-top: 1px;
  }
  .transcript-line__text {
    font-size: 0.92rem;
    line-height: 1.55;
    color: var(--text-secondary);
    flex: 1;
  }
  .transcript-line__text mark {
    background: var(--accent-soft);
    color: var(--accent-bright);
    padding: 1px 3px;
    border-radius: 3px;
  }
  .transcript-empty {
    padding: 40px 28px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.9rem;
    line-height: 1.6;
  }
  .transcript-empty svg { width: 36px; height: 36px; color: var(--text-faint); margin-bottom: 14px; }

  /* ============================================================
     TOAST
     ============================================================ */
  .toast {
    position: fixed;
    bottom: 28px;
    left: 50%;
    transform: translateX(-50%) translateY(80px);
    padding: 12px 20px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    border-radius: 100px;
    font-size: 0.88rem;
    color: var(--text-primary);
    z-index: 1000000;
    opacity: 0;
    transition: opacity 0.3s, transform 0.45s var(--ease-out-expo);
    box-shadow: 0 12px 30px rgba(0,0,0,0.4);
    display: flex;
    align-items: center;
    gap: 10px;
    pointer-events: none;
  }
  .toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
  .toast svg { width: 16px; height: 16px; color: var(--accent); }

  /* Scroll-to-top button */
  .scroll-to-top {
    position: fixed;
    bottom: 28px;
    right: 28px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(7, 10, 20, 0.85);
    border: 1px solid var(--border-strong);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    color: var(--text-primary);
    display: grid;
    place-items: center;
    z-index: 999;
    opacity: 0;
    transform: translateY(20px);
    pointer-events: none;
    transition: opacity 0.3s, transform 0.3s var(--ease-out-quart), background 0.2s, border-color 0.2s;
    box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  }
  .scroll-to-top.visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  .scroll-to-top:hover {
    background: var(--bg-elevated);
    border-color: var(--accent);
    color: var(--accent);
  }
  .scroll-to-top svg { width: 18px; height: 18px; }
  @media (max-width: 820px) {
    .scroll-to-top {
      bottom: calc(80px + env(safe-area-inset-bottom));
      right: 16px;
      width: 42px;
      height: 42px;
    }
  }

  /* ============================================================
     PLYR CUSTOMIZATIONS
     ============================================================ */
  .plyr {
    --plyr-font-family: var(--font-body);
    /* Force the Plyr wrapper to fill its parent (.video-container) regardless
       of whether the video has finished loading. Without an explicit size,
       Plyr sizes its wrapper to the video element, which is 0x0 before
       metadata loads — meaning the controls bar appears floating wherever
       the wrapper happens to be.
       NOTE: explicitly NOT setting position here. Plyr's default position:
       relative is critical for its internal absolute-positioned children
       (controls bar, big-play button, scrubber). Overriding to absolute
       breaks Plyr's scrubber math and click-to-play hit-testing. */
    width: 100% !important;
    height: 100% !important;
  }
  .plyr__controls {
    background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.5) 60%, transparent 100%) !important;
    padding: 30px 24px 22px !important;
    padding-bottom: calc(22px + env(safe-area-inset-bottom)) !important;
    /* Sit above .video-click-overlay (z-index 4) so the progress bar, time,
       volume, fullscreen, etc. all receive pointer events. Without this the
       click overlay swallows scrubber drags and turns them into play/pause toggles. */
    position: relative;
    z-index: 5;
    /* Explicit fade transition for the auto-hide. Plyr toggles the
       .plyr--hide-controls class on the parent .plyr; the rule below uses
       opacity + translateY to fade the bar down. Forcing the transition here
       so my other !important overrides on this element can't accidentally
       inherit a duration of 0s and skip the animation. */
    transition: opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1), transform 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important;
  }
  /* Auto-hide state: applied by Plyr when there's no mouse/focus movement
     for ~2s during playback. We re-declare these properties (Plyr provides
     them too) to make sure my custom .plyr__controls rules above don't
     compete with them on specificity. */
  .plyr--hide-controls .plyr__controls {
    opacity: 0 !important;
    transform: translateY(100%) !important;
    pointer-events: none !important;
  }
  /* Hover always wins: any time the cursor is over the player area, force
     the controls visible regardless of Plyr's auto-hide state. Originally
     used `.plyr:hover` but that fails: .video-click-overlay (z-index 4)
     sits ON TOP of .plyr (z-index auto), so the user's cursor is hovering
     the click-overlay, not .plyr — `.plyr:hover` never fires. Using
     `.video-container:hover` instead, since .video-container is the
     ancestor of EVERYTHING inside the player and gets :hover when any of
     its descendants is hovered. */
  .video-container:hover .plyr__controls,
  .video-container:focus-within .plyr__controls {
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto !important;
  }
  /* z-index lift on the big center play button so it remains tappable
     above the .video-click-overlay. NOTE: do NOT set position:relative here.
     Plyr's own CSS uses position:absolute with top:50%/left:50% + transform
     to center the overlaid play button; overriding to position:relative drops
     it back into normal document flow, where it ends up in the bottom-right
     of the .plyr container (very visible bug on mobile). z-index works on
     positioned elements, and Plyr already provides the positioning. */
  .plyr__control--overlaid { z-index: 5; }
  .plyr__progress__buffer { color: rgba(255,255,255,0.25); }
  .plyr__progress input[type=range] { color: var(--accent); }
  .plyr__time {
    font-family: var(--font-mono);
    font-size: 0.85rem;
    letter-spacing: 0.02em;
    /* Brada Sans is proportional. Tabular numerals fix the changing-digit
       width problem so the timer doesn't jitter as it counts up. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
  }
  .plyr--video .plyr__control:hover { background: var(--accent); }
  .plyr__control--overlaid {
    background: rgba(94, 234, 212, 0.85);
    padding: 22px;
  }
  .plyr__control--overlaid:hover { background: var(--accent-bright); }

  @media (min-width: 821px) {
    .plyr__control { padding: 11px !important; }
    .plyr__control svg { width: 18px !important; height: 18px !important; }
  }
  @media (max-width: 820px) {
    .plyr__controls { padding: 14px 14px !important; padding-bottom: max(18px, env(safe-area-inset-bottom)) !important; gap: 4px !important; align-items: center !important; }
    .plyr__volume { display: none !important; }
    .plyr__time { font-size: 0.72rem !important; padding: 0 2px !important; }
    .plyr__time--duration { display: none !important; } /* keep current time, save space */
    .plyr__progress__container { flex: 1 1 auto !important; min-width: 0 !important; }
    .plyr__control { padding: 10px !important; }
    .plyr__control svg { width: 20px !important; height: 20px !important; }
    .plyr__control[data-plyr="pip"], .plyr__control[data-plyr="airplay"] { display: none !important; }
  }

  /* ============================================================
     UTILITIES
     ============================================================ */
  body.scroll-lock {
    overflow: hidden;
    /* iOS Safari needs more to prevent rubber-band scroll behind modals */
    position: fixed;
    top: var(--scroll-y, 0);
    left: 0;
    right: 0;
    width: 100%;
  }

  /* Respect prefers-reduced-motion — disable Ken Burns, intro fade, hero rotation animations */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.001s !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.05s !important;
      scroll-behavior: auto !important;
    }
    .hero__bg { animation: none !important; transform: none !important; }
    .hero__dot.active::after { animation: none !important; transform: scaleX(1) !important; background: var(--accent); }
    .hero__slide { transition: opacity 0.1s linear !important; }
  }

  /* Image fade-in on load — only .card__img (which has load listeners wired in el()) */
  .card__img {
    opacity: 0;
    transition: opacity 0.4s var(--ease-out-quart), transform 0.6s var(--ease-out-quart);
  }
  .card__img.loaded { opacity: 1; }
  .card__img.errored { opacity: 0.35; filter: grayscale(0.6); }

  /* Visible scrollbar on shelves track (subtle) on desktop only */
  @media (hover: hover) {
    .row__track { scrollbar-width: thin; scrollbar-color: transparent transparent; }
    .row__track:hover { scrollbar-color: var(--surface-3) transparent; }
  }
  .reveal {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.6s var(--ease-out-quart), transform 0.6s var(--ease-out-quart);
  }
  .reveal.in { opacity: 1; transform: translateY(0); }

  /* Click overlay for video — sits over the video to capture taps for play/pause.
     CRITICAL: must be a lower stacking-order than Plyr's controls bar
     (.plyr__controls is bumped to z-index:5 below) so that the progress bar,
     time display, and other controls still receive their own pointer events
     and the user can actually drag the scrubber. */
  .video-click-overlay {
    position: absolute;
    inset: 0;
    z-index: 4;
    cursor: pointer;
  }

  /* Play/pause feedback pulse */
  .play-pulse {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%) scale(0.6);
    width: 80px; height: 80px;
    border-radius: 50%;
    background: rgba(7, 10, 20, 0.65);
    color: var(--text-primary);
    display: grid;
    place-items: center;
    opacity: 0;
    pointer-events: none;
    z-index: 7;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .play-pulse svg { width: 36px; height: 36px; filter: drop-shadow(0 2px 6px rgba(0,0,0,0.5)); }
  .play-pulse.show {
    animation: playPulse 0.5s var(--ease-out-quart) forwards;
  }
  @keyframes playPulse {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.6); }
    30% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.4); }
  }

  /* Empty state for My List */
  .empty-list {
    padding: 40px 24px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.92rem;
    background: var(--surface-1);
    border: 1px dashed var(--border);
    border-radius: 14px;
    margin: 0 5vw;
  }