/* ==========================================================================
   PREVIOUSLY · MINI-POPUP — universal quick-view component · v20261003b
   --------------------------------------------------------------------------
   SITE-WIDE PATTERN (James, 2026-10-03 — PERMANENT):
   Every clickable entity gets a MINI quick-view popup BEFORE the full page:
   click -> mini card pops up (photo, key info, play/listen) -> tap through
   to the full page. Same look, same behavior, everywhere. Never reinvented
   per section.

   ADOPTION (any section — music, browse, sports, podcasts):
     1. Load this CSS + /js/mini-popup.js on the page.
     2. Build your content HTML (any markup, your section's classes).
     3. MiniPopup.open(html,{ ariaLabel: "..." })  -> shows it.
        MiniPopup.setContent(html)                 -> swap body (loading -> data).
        MiniPopup.close()                           -> dismiss.
     4. Close is automatic: X button, backdrop click, Escape.
   The shell is content-agnostic. Section-specific styles live in the
   section's own CSS (e.g. .apop-* for music artists).
   ========================================================================== */
.mpop-overlay{position:fixed;inset:0;z-index:2000;background:rgba(var(--desert-ink-rgb), .55);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  display:flex;align-items:center;justify-content:center;padding:24px;
  opacity:0;pointer-events:none;transition:opacity .3s cubic-bezier(.22,.8,.28,1)}.mpop-overlay.open{opacity:1;pointer-events:auto}.mpop-card{position:relative;background:var(--surface-cream);border:1px solid var(--desert-ink-faint);
  border-radius:16px;max-width:520px;width:100%;max-height:88vh;max-height:88dvh;overflow-y:auto;
  box-shadow:0 40px 90px -30px rgba(var(--desert-ink-rgb), .6);color:var(--desert-ink);
  font-family:var(--font-sans);font-size:16px;line-height:1.55;
  transform:translateY(16px) scale(.98);transition:transform .3s cubic-bezier(.22,.8,.28,1)}.mpop-overlay.open .mpop-card{transform:none}.mpop-close{position:absolute;top:14px;right:14px;width:38px;height:38px;border-radius:50%;
  border:1px solid var(--desert-ink-faint);background:var(--desert-pressed);color:var(--desert-ink);cursor:pointer;
  display:flex;align-items:center;justify-content:center;z-index:2;
  transition:background .25s,transform .25s,color .25s}.mpop-close:hover{background:var(--brand-red-deep);color:var(--desert-ink);transform:rotate(90deg)}.mpop-close svg{width:16px;height:16px}.mpop-body{padding:32px}.mpop-body *{box-sizing:border-box}/* WCAG AA (2026-10-03): section --muted values tuned for darker hub
   backgrounds can fall below 4.5:1 on this light card (music's #8C7F68
   was 3.86:1). Darken muted text inside popups only — hubs keep theirs. */
.mpop-body{--muted:var(--desert-ink-dim)}@media(max-width:560px){.mpop-overlay{padding:16px}.mpop-body{padding:24px 20px}.mpop-card{border-radius:14px}
}@media(prefers-reduced-motion:reduce){.mpop-overlay,.mpop-card,.mpop-close{transition:none}
}/* ---- Person quick-view (James 2026-10-03: cast is always clickable) ----
   Rendered by /browse/js/tmdb-person-popup.js inside MiniPopup. */
.pv-pperson__top{display:flex;gap:18px;align-items:flex-start;margin-bottom:14px}.pv-pperson__ph{width:96px;height:144px;object-fit:cover;border-radius:10px;background:var(--desert-pressed);flex:none;
  box-shadow:0 10px 24px -12px rgba(var(--desert-ink-rgb), .45)}.pv-pperson__ph--init{display:flex;align-items:center;justify-content:center;font-size:40px;font-weight:700;color:var(--desert-ink-dim)}.pv-pperson__ph.is-sk{animation:pvPsk 1.2s ease-in-out infinite}.pv-pperson__head{min-width:0}.pv-pperson__kicker{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--text-on-light-muted);margin:0 0 6px}.pv-pperson__name{font-family:var(--font-serif);font-size:26px;line-height:1.15;margin:0 0 6px;color:var(--desert-ink)}.pv-pperson__char{font-size:14px;color:var(--text-on-light-muted);margin:0}.pv-pperson__char em{color:var(--desert-ink)}.pv-pperson__known{font-size:14px;color:var(--text-on-light-muted);margin:0 0 10px}.pv-pperson__known strong{color:var(--desert-ink)}.pv-pperson__bio{font-size:15px;line-height:1.65;color:var(--desert-ink);margin:0 0 6px}.pv-pperson__bio.is-empty{color:var(--desert-ink-dim);font-style:italic}.pv-pperson__loading{font-size:13px;color:var(--desert-ink-dim);margin:12px 0 0}.pv-pperson__skline{height:12px;border-radius:6px;background:var(--desert-pressed);margin:8px 0;animation:pvPsk 1.2s ease-in-out infinite}.pv-pperson__actions{margin-top:16px}.pv-pperson__cta{display:inline-block;font-weight:700;color:var(--desert-card);background:var(--brand-red-deep);
  border-radius:8px;padding:11px 22px;text-decoration:none;font-size:15px}.pv-pperson__cta:hover{background:var(--brand-red-deep)}.pv-pperson__retry{font-size:13px;color:var(--desert-ink-dim);margin:12px 0 0}.pv-pperson__retry button{font:inherit;color:var(--brand-red-deep);background:none;border:0;padding:0;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px}@keyframes pvPsk{0%,100%{opacity:.55}50%{opacity:1}}
/* ---- Universal thumbnail popup content (James 2026-10-08 — PERMANENT:
   every thumbnail site-wide opens a pop-up; .tpop-* is the one shared
   content style, rendered by /js/thumbnail-popups.js) ----

   QUICK-PEEK REBUILD (James 2026-10-13): the pop-up is a light peek in the
   current Bible / title-page language — capped art or a trailer facade,
   title + key facts line, the viewer's own Favorite / Watched / Want row
   (titles), top-cast circles (titles), a SHORT overview snippet, and View
   full page. The full overview, facts grid, season/episode detail,
   more-like-this and supporting stills live on the full page only.
   FIT RULE (James 2026-10-13): NO scrolling inside the pop-up — not on
   phone, not on laptop. A card holding .tpop content is a flex column;
   every text block is flex:none at natural height and only the art
   yields (flex-shrink + a calc(88dvh - 290px) height cap — the card's
   own 88dvh ceiling minus the reserved text stack; a percentage cap
   cannot resolve inside this flex column, which is how the old
   min(34dvh,100%) cap silently collapsed and the art painted over
   the text at short/wide viewports. The art slot also clips, so an
   over-long text stack trims the art instead of covering the words;
   aspect preserved, never stretched). Scoped via :has(.tpop) so the
   person and music popups keep the classic scrolling card. */
.mpop-card:has(.tpop){display:flex;flex-direction:column;overflow:hidden}
.mpop-card:has(.tpop) .mpop-body{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:20px 24px}
.tpop{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}
.tpop-facts[hidden],.tpop-dek[hidden],.tpop-cast[hidden]{display:none}
.tpop-art{flex:0 1 auto;min-height:0;display:flex;align-items:flex-start;justify-content:center;margin-bottom:12px;max-height:calc(88dvh - 290px);overflow:hidden}
.tpop-art img{max-width:100%;max-height:34vh;max-height:calc(88dvh - 290px);width:auto;height:auto;display:block;border-radius:10px;background:var(--desert-pressed)}
.tpop-video{position:relative;width:100%;aspect-ratio:16/9;max-height:100%;border-radius:10px;overflow:hidden;background:#000}
.tpop-video iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.tpop-facade{position:relative;display:block;width:100%;aspect-ratio:16/9;max-height:100%;border:0;padding:0;margin:0;border-radius:10px;overflow:hidden;background:#000;cursor:pointer}
.tpop-facade img{position:absolute;inset:0;width:100%;height:100%;max-height:none;object-fit:cover;border-radius:0;background:#000}
.tpop-facade .tpop-playring{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:54px;height:54px;pointer-events:none}
.tpop-facade .tpop-trailerlabel{position:absolute;left:10px;bottom:10px;background:rgba(10,10,10,.62);color:#faf6ee;font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;border-radius:4px;padding:4px 9px;pointer-events:none}
.tpop-kicker{flex:none;font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--text-on-light-muted);margin:0 0 5px}
.tpop-title{flex:none;font-family:var(--font-serif);font-size:23px;line-height:1.16;margin:0 0 6px;color:var(--desert-ink)}
.tpop-facts{flex:none;display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin:0 0 4px;font-size:13.5px;color:var(--text-on-light-muted)}
.tpop-score{display:inline-flex;align-items:center;background:var(--desert-ink);color:var(--surface-cream);font-weight:700;font-size:12.5px;line-height:1;border-radius:4px;padding:4px 10px;letter-spacing:.02em}
.tpop-info{font-weight:600}
.tpop-byline{flex:none;font-size:13px;color:var(--text-on-light-muted);margin:0 0 4px}
.tpop-dek{flex:none;font-size:14.5px;line-height:1.6;color:var(--desert-ink);margin:2px 0 0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tpop-tags{flex:none;display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
.tpop-tag{font-size:11px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;border:1px solid var(--desert-ink-faint);border-radius:4px;padding:3px 10px;color:var(--desert-ink-dim)}
.tpop-actions{flex:none;display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.tpop-cta{display:inline-block;font-weight:700;color:var(--desert-card);background:var(--brand-red-deep);border:0;border-radius:6px;padding:10px 20px;text-decoration:none;font-size:14.5px;cursor:pointer;font-family:inherit}
.tpop-cta:hover{background:var(--brand-red-deep)}
.tpop-go{background:transparent;color:var(--desert-ink);border:1.5px solid var(--desert-ink);padding:9px 18px}
.tpop-go:hover{background:var(--desert-ink);color:var(--surface-cream)}
/* Viewer's own row (titles only): pv-marks.js builds the labeled Watched /
   Want to Watch buttons inside this host and pv-account's Favorite heart is
   adopted into the row — the exact title-page mechanism, reused verbatim
   (the host carries .td-hero + data-like-*). The .td-hero neutralization
   below keeps the title shell's hero-grid styles out of the card, and the
   heart rules mirror pv-marks.css's #td-root row-heart design so the row
   looks identical inside the pop-up. On pages without pv-marks/pv-account
   the host simply stays empty (zero height, invisible). */
.tpop-marks{flex:none}
.mpop-card .td-hero{display:block;margin:0;padding:0;background:none;border:0;min-height:0}
.mpop-card .pv-marks-row{margin:8px 0 2px}
.mpop-card .pv-marks-row .pv-heart--row{position:static;width:40px;height:40px;flex:none;border:1.5px solid var(--desert-ink,#2b2118);border-radius:999px;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
.mpop-card .pv-marks-row .pv-heart--row svg{width:19px;height:19px;fill:none;stroke:var(--desert-ink,#2b2118)}
.mpop-card .pv-marks-row .pv-heart--row[aria-pressed="true"]{border-color:#e0245e}
.mpop-card .pv-marks-row .pv-heart--row[aria-pressed="true"] svg{fill:#e0245e;stroke:#e0245e}
.mpop-card .pv-marks-row .pv-heart--row:focus-visible{outline:2px solid var(--brand-red,#c0391b);outline-offset:2px}
.mpop-card .tpop-marks>.pv-heart{position:static;width:40px;height:40px;border:1.5px solid var(--desert-ink,#2b2118);border-radius:999px;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;margin:8px 0 2px}
.mpop-card .tpop-marks>.pv-heart svg{width:19px;height:19px;fill:none;stroke:var(--desert-ink,#2b2118)}
.mpop-card .tpop-marks>.pv-heart[aria-pressed="true"]{border-color:#e0245e}
.mpop-card .tpop-marks>.pv-heart[aria-pressed="true"] svg{fill:#e0245e;stroke:#e0245e}
/* Top cast (titles): small circles row — deliberately lighter than the
   full page's cast grid. Populated from the title record by
   thumbnail-popups.js; absent when the record has no cast photos. */
.tpop-cast{flex:none;display:flex;gap:12px;margin-top:10px;overflow:hidden}
.tpop-castm{flex:none;width:54px;text-align:center}
.tpop-castm img{width:42px;height:42px;border-radius:50%;object-fit:cover;background:var(--desert-pressed);display:block;margin:0 auto}
.tpop-castm__init{width:42px;height:42px;border-radius:50%;background:var(--desert-pressed);color:var(--desert-ink-dim);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px;margin:0 auto}
.tpop-castm span{display:block;font-size:10px;line-height:1.25;color:var(--text-on-light-muted);margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:560px){
  .mpop-card:has(.tpop) .mpop-body{padding:18px}
  .tpop-title{font-size:21px}
  .tpop-facade .tpop-playring{width:46px;height:46px}
}
/* ---- SCROLL SAFETY NET · 2026-10-14 (appended) — same trap as pv-qv:
   the .tpop card is overflow:hidden with every text block flex:none at
   natural height, so a stack taller than the card (long title + marks
   row + cast on a short phone) clipped its last rows (the actions)
   with no way to scroll. The art still yields first (the caps above
   stand — peeks that fit are pixel-identical); underneath, .mpop-body
   becomes the scroller so any overflow is reachable, never amputated.
   The x is a card-level sibling of the body, so it stays pinned. ---- */
.mpop-card:has(.tpop) .mpop-body{overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.mpop-card:has(.tpop) .tpop{flex:none}
