<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; object-src 'none'; base-uri 'self'; worker-src 'none'; upgrade-insecure-requests; script-src 'self' https://www.youtube.com https://static.cloudflareinsights.com 'sha256-xRnvLn+60NUvJ3gzd8R4EnK9X4H+1TSihEI3nuu/KpA=' 'sha256-kbcklK4WcFOn7F34czNX8Wfpy+goGFOkx0UYpaatrsk='; style-src 'self' 'sha256-E31WBZf3aQC4AsOAmgscARE20O3rhSeZuvQqWh/kPPg=' 'sha256-vKD3N04u9ixfzsEkyeU3hes/2cow/fWA5Kf6FMq3soM=' 'sha256-mEh0Z8cjrwAr5ptmi4cdKqiVHU6k9KYl3f2w20HNi4M='; img-src 'self' data: https://image.tmdb.org https://i.ytimg.com https://yt3.ggpht.com; font-src 'self'; connect-src 'self' https://previously-live-now.james-moore2013.workers.dev https://beta.watchpreviously.com https://previously-freshness.james-moore2013.workers.dev; frame-src https://www.youtube-nocookie.com; form-action 'self' https://beta.watchpreviously.com">
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
  <meta name="theme-color" content="#161114">
  <meta name="color-scheme" content="dark">
  <meta name="description" content="Previously — tonight's TV schedule, movies, and shows in one place. What to watch, and when.">
  <meta property="og:title" content="Previously — What to watch, and when">
  <meta property="og:description" content="Previously — tonight's TV schedule, movies, and shows in one place. What to watch, and when.">
  <meta property="og:type" content="website">
  <meta property="og:url" content="https://watchpreviously.com/">
  <meta property="og:image" content="https://watchpreviously.com/assets/og-card.jpg">
  <meta property="og:image:width" content="1200">
  <meta property="og:image:height" content="630">
  <meta property="og:image:alt" content="Previously — what to watch, and when">
  <meta property="og:site_name" content="Previously">
  <meta property="og:locale" content="en_US">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:title" content="Previously — What to watch, and when">
  <meta name="twitter:description" content="Previously — tonight's TV schedule, movies, and shows in one place. What to watch, and when.">
  <meta name="twitter:image" content="https://watchpreviously.com/assets/og-card.jpg">
  <meta name="twitter:image:alt" content="Previously — what to watch, and when">
  <link rel="canonical" href="https://www.watchpreviously.com/">
  <script type="application/ld+json">
  {"@context":"https://schema.org","@type":"WebSite","name":"Previously","url":"https://www.watchpreviously.com/","description":"Tonight's TV schedule, movies, and shows in one place. What to watch, and when.","inLanguage":"en-US","potentialAction":{"@type":"SearchAction","target":"https://www.watchpreviously.com/#browse?q={search_term_string}","query-input":"required name=search_term_string"},"publisher":{"@type":"Organization","name":"Previously","url":"https://www.watchpreviously.com/"}}
  </script>
  <link rel="preconnect" href="https://www.youtube-nocookie.com">
  <link rel="preconnect" href="https://i.ytimg.com">
  <link rel="dns-prefetch" href="https://www.youtube.com">
  <link rel="icon" type="image/svg+xml" href="assets/favicon.svg">
  <link rel="icon" type="image/png" sizes="16x16" href="assets/favicon-16.png">
  <link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32.png">
  <link rel="icon" type="image/png" sizes="192x192" href="assets/favicon-192.png">
  <link rel="icon" type="image/png" sizes="512x512" href="assets/favicon-512.png">
  <link rel="apple-touch-icon" sizes="180x180" href="assets/favicon-180.png">
  <title>Previously — What to watch, and when</title>
  <script>
  /* Apply the saved/OS theme BEFORE first paint — no flash of the wrong theme.
     Website-only; the Previously app is unaffected. */
  (function(){
    var t="dark";
    try{
      t=localStorage.getItem("prev-theme");
      if(!t){t=window.matchMedia("(prefers-color-scheme: light)").matches?"light":"dark";}
    }catch(e){t="dark";}
    document.documentElement.setAttribute("data-theme",t);
    var metas=document.getElementsByTagName("meta"),i,mc=null,cs=null;
    for(i=0;i<metas.length;i++){
      if(metas[i].getAttribute("name")==="theme-color")mc=metas[i];
      if(metas[i].getAttribute("name")==="color-scheme")cs=metas[i];
    }
    if(mc)mc.setAttribute("content",t==="light"?"#ffffff":"#161114");
    if(cs)cs.setAttribute("content",t);
  })();
  </script>
  <style>
    @font-face{font-family:"Previously Display";src:url("assets/previously-wordmark.ttf") format("truetype");font-display:swap}
    @font-face{font-family:"Cinzel";src:url("assets/cinzel-var.woff2") format("woff2");font-weight:400 900;font-display:swap}
    @font-face{font-family:"Inter";src:url("assets/inter-var.woff2") format("woff2");font-weight:100 900;font-display:swap}
    :root,[data-theme="dark"]{color-scheme:dark;--page:#161114;--page-rgb:22,17,20;--surface:#1e1a18;--surface-2:#26211e;--surface-3:#2e2826;--ink:#ede6d6;--ink-rgb:237,230,214;--copy:#b7ac9c;--copy-hi:#d8cdbd;--muted:#a79e8e;--faint:#8d8478;--line:rgba(237,230,214,.12);--line-strong:rgba(237,230,214,.25);--emerald:#2b2b30;--emerald-deep:#222226;--emerald-hi:#f4f1ea;--emerald-hover:#34343b;--crimson:#e8321e;--shadow:0 28px 90px rgba(0,0,0,.44);--nav-bg:rgba(13,11,10,.82);--radius-lg:28px;--radius-md:18px;--focus:#f4f1ea;--pearl:#f4f1ea;--red:#e8321e;/* legacy token names kept: --emerald* = graphite CTA scale, --emerald-hi = Rewind Red status accent */}
    *{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth;background:var(--page)}body{min-width:320px;background:var(--page);color:var(--ink);font-family:"Inter",sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}button,input,select{font:inherit}button,a{touch-action:manipulation;-webkit-tap-highlight-color:transparent}button{color:inherit}a{color:inherit}img{max-width:100%}::selection{background:rgba(43,43,48,.55)}
    button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible{outline:2px solid var(--focus);outline-offset:3px}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}    /* ---- Catch-Up / Binge Calculator (Gate 2 approved 2026-09-24) ---- */
    #bingeModal{z-index:120}
    .modal-engage{flex-wrap:wrap}
    .bc-entry{flex:1 1 100%;display:flex;align-items:center;justify-content:center;gap:10px;min-height:48px;padding:12px 18px;border-radius:999px;border:1px solid transparent;background:var(--emerald);color:#fff;font:700 15px/1.2 "Inter",sans-serif;cursor:pointer;margin-bottom:12px;box-shadow:0 10px 26px rgba(43,43,48,.35)}
    .bc-entry:hover{background:var(--emerald-hover)}
    .bc-entry:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
    .bc-entry svg{width:20px;height:20px;flex:none}
    .bc-panel{position:relative;width:min(480px,calc(100vw - 32px));max-height:92dvh;overflow-y:auto;background:var(--surface);border:1px solid var(--line-strong);border-radius:var(--radius-md);padding:26px 22px calc(22px + env(safe-area-inset-bottom));box-shadow:var(--shadow)}
    .bc-handle{display:none;width:44px;height:5px;border-radius:999px;background:var(--line-strong);margin:0 auto 14px}
    .bc-eyebrow{font:700 11px/1 "Inter",sans-serif;letter-spacing:.14em;text-transform:uppercase;color:var(--emerald-hi);margin:0 34px 10px 0}
    .bc-headline{font:800 clamp(22px,4.6vw,28px)/1.25 "Inter",sans-serif;letter-spacing:-.01em;margin:0 30px 8px 0}
    .bc-headline.is-bad{color:#f2614d}
    .bc-sub{color:var(--copy);font-size:14.5px;line-height:1.55;margin:0 0 18px}
    .bc-chips{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:14px}
    .bc-chip{border:1px solid var(--line-strong);background:var(--surface-2);color:var(--ink);border-radius:14px;padding:13px 6px;font:800 20px/1.1 "Inter",sans-serif;cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:3px;min-height:64px;justify-content:center}
    .bc-chip small{font:600 11px/1 "Inter",sans-serif;color:var(--muted)}
    .bc-chip.is-on{background:var(--emerald);border-color:var(--emerald);color:#fff;box-shadow:0 8px 22px rgba(43,43,48,.4)}
    .bc-chip.is-on small{color:rgba(255,255,255,.85)}
    .bc-chip:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
    .bc-toggle{display:flex;align-items:center;gap:12px;width:100%;background:none;border:0;color:var(--copy-hi);font:600 14.5px/1.4 "Inter",sans-serif;cursor:pointer;padding:12px 2px;margin-bottom:4px;text-align:left}
    .bc-toggle .bc-dot{width:44px;height:26px;flex:none;border-radius:999px;background:var(--surface-3);border:1px solid var(--line-strong);position:relative;transition:background .18s}
    .bc-toggle .bc-dot::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--muted);transition:transform .18s,background .18s}
    .bc-toggle[aria-pressed="true"] .bc-dot{background:var(--emerald)}
    .bc-toggle[aria-pressed="true"] .bc-dot::after{transform:translateX(18px);background:#fff}
    .bc-expander{display:flex;align-items:center;justify-content:space-between;width:100%;background:none;border:0;border-top:1px solid var(--line);color:var(--ink);font:700 14.5px/1 "Inter",sans-serif;cursor:pointer;padding:14px 2px;margin-top:6px}
    .bc-expander .bc-caret{transition:transform .2s;color:var(--muted)}
    .bc-expander[aria-expanded="true"] .bc-caret{transform:rotate(180deg)}
    .bc-adjust{padding:2px 2px 6px}
    .bc-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 0;border-top:1px dashed var(--line)}
    .bc-row>span{font:600 13.5px/1.4 "Inter",sans-serif;color:var(--copy)}
    .bc-seg{display:flex;background:var(--surface-2);border:1px solid var(--line);border-radius:999px;padding:3px;gap:2px}
    .bc-seg button{border:0;background:none;color:var(--muted);font:700 13px/1 "Inter",sans-serif;padding:9px 13px;border-radius:999px;cursor:pointer;white-space:nowrap}
    .bc-seg button.is-on{background:var(--emerald);color:#fff}
    .bc-stepper{display:flex;align-items:center;gap:12px}
    .bc-stepper button{width:38px;height:38px;border-radius:50%;border:1px solid var(--line-strong);background:var(--surface-2);color:var(--ink);font:800 18px/1 "Inter",sans-serif;cursor:pointer}
    .bc-stepper button:hover{background:var(--emerald);border-color:var(--emerald);color:#fff}
    .bc-stepper span{font:800 17px/1 "Inter",sans-serif;min-width:64px;text-align:center}
    .bc-eps-head{display:flex;align-items:center;justify-content:space-between;margin:16px 0 8px}
    .bc-eps-head span{font:700 14px/1 "Inter",sans-serif}
    .bc-link{background:none;border:0;color:var(--emerald-hi);font:700 13px/1 "Inter",sans-serif;cursor:pointer;padding:8px 4px}
    .bc-eps{display:flex;flex-direction:column;gap:8px;max-height:300px;overflow-y:auto;padding-right:2px}
    .bc-ep{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:var(--surface-2);border:1px solid var(--line);border-radius:14px;padding:12px;cursor:pointer;color:var(--ink)}
    .bc-ep:hover{border-color:var(--line-strong)}
    .bc-ep .bc-check{width:30px;height:30px;flex:none;border-radius:50%;border:2px solid var(--muted);display:flex;align-items:center;justify-content:center;font:800 15px/1 "Inter",sans-serif;color:transparent;transition:all .15s}
    .bc-ep.is-watched .bc-check{background:var(--emerald);border-color:var(--emerald);color:#fff}
    .bc-ep .bc-ep-main{flex:1;min-width:0}
    .bc-ep .bc-ep-name{display:block;font:600 14px/1.35 "Inter",sans-serif;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .bc-ep.is-watched .bc-ep-name{color:var(--muted);text-decoration:line-through;text-decoration-thickness:1px}
    .bc-ep .bc-ep-rt{flex:none;font:600 12.5px/1 "Inter",sans-serif;color:var(--muted)}
    .bc-ep.is-watched .bc-ep-rt{color:var(--faint)}
    .bc-note{color:var(--muted);font-size:13px;line-height:1.55;margin:14px 0 0}
    .bc-note .bc-est{color:var(--emerald-hi);font-weight:700}
    .bc-season-label{font:700 12px/1 "Inter",sans-serif;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin:10px 0 2px}
    .bc-retry{display:inline-flex;margin-top:12px}
    @media (max-width:640px){
      #bingeModal{align-items:flex-end;padding:0}
      .bc-panel{width:100%;max-width:100%;border-radius:20px 20px 0 0;border-left:0;border-right:0;border-bottom:0;animation:bcUp .28s cubic-bezier(.32,.72,.28,1)}
      .bc-handle{display:block}
    }
    @keyframes bcUp{from{transform:translateY(48px);opacity:.6}to{transform:none;opacity:1}}
    @media (prefers-reduced-motion:reduce){.bc-panel{animation:none}}
    .no-scroll{overflow:hidden}.view{display:none}.view.active{display:block}.page{padding-top:68px}
    .topbar{position:fixed;z-index:50;inset:0 0 auto;display:flex;align-items:center;justify-content:space-between;height:68px;padding:0 max(28px,calc((100vw - 1460px)/2));border-bottom:1px solid color-mix(in srgb,var(--ink) 9%,transparent);background:var(--nav-bg);backdrop-filter:saturate(150%) blur(22px);-webkit-backdrop-filter:saturate(150%) blur(22px)}.top-left{display:flex;align-items:center;gap:2px;min-width:0}.wm-glyph{flex:none;display:block}.wordmark{display:inline-flex;align-items:center;gap:10px;border:0;background:transparent;cursor:pointer;font-family:"Previously Display",serif;font-size:23px;letter-spacing:.01em;color:var(--ink);padding:8px 12px 8px 0;margin-right:10px;transition:color .18s ease,transform .12s ease}.wordmark:hover{color:var(--emerald-hi)}.wordmark:active{transform:scale(.96)}.primary-nav{display:flex;align-items:center;gap:3px}.nav-btn{position:relative;min-height:44px;min-width:44px;border:0;background:transparent;color:var(--muted);padding:0 15px;border-radius:999px;cursor:pointer;font-size:13px;font-weight:680;transition:color .18s ease,background .18s ease,transform .12s ease}.nav-btn:hover{color:var(--ink);background:rgba(var(--ink-rgb),.075)}.nav-btn:active{transform:scale(.96);background:rgba(var(--ink-rgb),.12)}.nav-btn.active{color:var(--ink);background:rgba(var(--ink-rgb),.09)}.nav-btn.active::after{content:"";position:absolute;left:18px;right:18px;bottom:5px;height:2px;border-radius:4px;background:var(--emerald-hi);transform-origin:center;animation:navLine .24s ease both}.top-actions{display:flex;align-items:center;gap:8px}.icon-btn{display:grid;place-items:center;width:44px;height:44px;border:0;border-radius:50%;background:transparent;color:var(--muted);cursor:pointer;transition:color .18s,background .18s,transform .12s}.icon-btn:hover{color:var(--ink);background:rgba(var(--ink-rgb),.075)}.icon-btn:active{transform:scale(.92)}
    .cta{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:46px;border:1px solid transparent;border-radius:999px;background:var(--emerald);color:#fff;padding:0 22px;cursor:pointer;text-decoration:none;font-size:13px;font-weight:760;letter-spacing:.01em;box-shadow:0 10px 30px rgba(43,43,48,.26);transition:transform .18s cubic-bezier(.2,.8,.2,1),background .18s ease,box-shadow .18s ease,border-color .18s ease}.cta:hover{background:var(--emerald-hover);transform:translateY(-1px);box-shadow:0 15px 36px rgba(43,43,48,.34)}.cta:active{transform:translateY(0) scale(.975);box-shadow:0 6px 18px rgba(43,43,48,.24)}.cta:disabled{cursor:wait;opacity:.58;transform:none;box-shadow:none}.cta.secondary{border-color:var(--line-strong);background:rgba(var(--ink-rgb),.045);box-shadow:none;color:var(--ink)}.cta.secondary:hover{border-color:rgba(237,230,214,.4);background:rgba(var(--ink-rgb),.095)}.cta.compact{min-height:44px;padding:0 18px}.cta.textual{min-height:38px;padding:0 2px;border:0;border-radius:0;background:transparent;box-shadow:none;color:var(--ink)}.cta.textual:hover{color:var(--emerald-hi);transform:none}.cta .short{display:none}
    .hero{--hero-ink:#ede6d6;position:relative;min-height:min(900px,calc(100svh - 68px));overflow:hidden;display:flex;align-items:flex-end;background:#0d0b0a;color:var(--hero-ink)}.hero-slide{position:absolute;inset:0;opacity:0;transform:scale(1.025);visibility:hidden;transition:opacity .9s cubic-bezier(.2,.65,.2,1),visibility .9s}.hero-slide.active{opacity:1;visibility:visible}.hero-slide picture{display:block;width:100%;height:100%}.hero-slide img,.hero-slide picture img{width:100%;height:100%;object-fit:cover;object-position:center 23%;filter:saturate(.8) contrast(1.06);animation:heroDrift 17s ease-in-out infinite alternate}.hero-slide::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(13,11,10,.88) 0%,rgba(13,11,10,.58) 35%,rgba(13,11,10,.10) 72%),linear-gradient(0deg,var(--page) 0%,rgba(13,11,10,.55) 26%,rgba(13,11,10,.12) 100%)}.hero-copy{position:relative;z-index:3;width:min(840px,75vw);padding:120px 0 94px max(42px,calc((100vw - 1360px)/2))}.eyebrow{display:flex;align-items:center;gap:10px;margin-bottom:17px;color:var(--emerald-hi);font-size:11px;font-weight:800;letter-spacing:.18em;text-transform:uppercase}.eyebrow::before{content:"";width:28px;height:1px;background:currentColor}.hero h1{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:clamp(56px,7.5vw,116px);font-weight:590;line-height:.88;letter-spacing:-.052em;text-wrap:balance}.hero h1 em{display:block;color:var(--emerald-hi);font-style:normal}.hero p{max-width:625px;margin:27px 0 31px;color:var(--copy-hi);font-size:18px;line-height:1.64}.hero-actions{display:flex;gap:11px;flex-wrap:wrap}.hero .cta.secondary{border-color:rgba(237,230,214,.28);background:rgba(13,11,10,.38);color:#ede6d6}.hero .cta.secondary:hover{background:rgba(237,230,214,.13)}.hero-controls{position:absolute;z-index:4;right:max(42px,calc((100vw - 1360px)/2));bottom:94px;display:flex;align-items:center;gap:14px}.hero-pager{display:flex;gap:7px}.hero-dot{position:relative;display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;background:transparent;cursor:pointer;transition:transform .12s}.hero-dot::after{content:"";display:block;width:30px;height:4px;border-radius:99px;background:rgba(237,230,214,.3);transition:transform .25s,background .25s;transform-origin:left}.hero-dot:hover::after{background:rgba(237,230,214,.7)}.hero-dot:active{transform:scaleX(.9)}.hero-dot.active::after{transform:scaleX(1.6);background:var(--ink)}.round-btn{display:grid;place-items:center;width:44px;height:44px;border:1px solid rgba(237,230,214,.28);border-radius:50%;background:rgba(13,11,10,.48);color:#ede6d6;cursor:pointer;font-size:19px;transition:background .18s,border-color .18s,transform .12s}.round-btn:hover{border-color:var(--emerald-hi);background:var(--emerald)}.round-btn:active{transform:scale(.92)}
    /* ---------- Trailer hero (Amendment A): muted autoplay, Netflix parity ---------- */
    .hero-slide{overflow:hidden}
    /* ---------- Hero single-commit skeleton (James 2026-09-26) ----------
       First paint is a branded shimmer skeleton, never a hardcoded title.
       .hero-loading is removed by paintHeroItems() on the single commit. */
    .hero-skel picture{display:block;width:100%;height:100%;background:#141110}
    .hero-skel-shimmer{position:absolute;inset:0;background:linear-gradient(100deg,transparent 25%,rgba(237,230,214,.07) 50%,transparent 75%);background-size:200% 100%;animation:heroSkelShimmer 1.6s linear infinite}
    @keyframes heroSkelShimmer{to{background-position:-200% 0}}
    .hero-loading .hero-slide{opacity:1;visibility:visible}
    .hero-loading .hero-pager{visibility:hidden}
    .skel-bar{display:block;height:.68em;border-radius:8px;background:rgba(237,230,214,.10);margin:.22em 0;position:relative;overflow:hidden}
    .skel-bar::after{content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent 30%,rgba(237,230,214,.16) 50%,transparent 70%);background-size:200% 100%;animation:heroSkelShimmer 1.5s linear infinite}
    .hero-trailer{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:max(100%,177.78vh);aspect-ratio:16/9;border:0;pointer-events:none;background:transparent}
    .hero-facade{position:absolute;inset:0;z-index:2;display:grid;place-items:center;background:transparent;border:0;cursor:pointer;padding:0}
    .hero-facade .trailer-play{position:absolute;left:50%;top:44%}
    .hero-copy{pointer-events:none}
    .hero-copy button,.hero-copy a{pointer-events:auto}
    .hero-controls .round-btn.trailer-btn svg{display:block}
    .hero-controls .round-btn.trailer-btn .ic-muted{display:none}
    .hero-controls .round-btn.trailer-btn.is-muted .ic-muted{display:block}
    .hero-controls .round-btn.trailer-btn.is-muted .ic-unmuted{display:none}
    @media(max-width:600px){.hero-controls .round-btn.trailer-btn{display:grid}}
    .trailer-ctl{position:absolute;z-index:4;right:10px;bottom:10px;display:flex;gap:8px}
    .trailer-ctl .round-btn{width:38px;height:38px;font-size:16px}
    .trailer-ctl .round-btn svg{display:block}
    .trailer-ctl .round-btn .ic-muted{display:none}
    .trailer-ctl .round-btn.is-muted .ic-muted{display:block}
    .trailer-ctl .round-btn.is-muted .ic-unmuted{display:none}
    .shell{max-width:1440px;margin:auto;padding:108px 40px 126px}.section{margin-top:118px}.section:first-child{margin-top:0}.section-head{display:flex;align-items:end;justify-content:space-between;gap:30px;margin-bottom:30px}.section-head h2,.browse-head h2,.library-hero h2{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:clamp(34px,4.4vw,64px);font-weight:570;line-height:1.04;letter-spacing:-.042em}.section-head p,.browse-head p{max-width:610px;margin-top:12px;color:var(--muted);font-size:15px;line-height:1.7}.section-actions{display:flex;align-items:center;gap:6px}.text-link{position:relative;display:inline-flex;align-items:center;min-height:44px;border:0;background:transparent;color:var(--ink);cursor:pointer;padding:10px 3px;font-size:13px;font-weight:760}.text-link::after{content:"";position:absolute;left:3px;right:3px;bottom:7px;height:1px;background:var(--emerald-hi);transform:scaleX(0);transform-origin:left;transition:transform .2s ease}.text-link:hover::after{transform:scaleX(1)}.text-link:active{color:var(--emerald-hi)}
    .timeline{position:relative;display:block;margin-top:52px}.tl-hours{position:relative}.tl-hrow{display:grid;grid-template-columns:150px minmax(0,1fr);min-height:96px;border-top:1px solid var(--line)}.tl-hrow:first-child{border-top:0}.tl-tick{position:relative;padding:14px 16px 14px 0}.tl-tick .tick{height:auto;min-height:68px}.tl-hcards{display:flex;flex-direction:column;gap:18px;padding:14px 0;min-width:0}.tl-hcards .tl-btn{margin:0}@media(max-width:700px){.tl-hrow{grid-template-columns:64px minmax(0,1fr)}}.timeline[hidden]{display:none}.tl-rail{position:relative;min-height:100%}.tl-rail::before{content:"";position:absolute;top:6px;bottom:6px;left:118px;width:2px;background:linear-gradient(var(--line-strong),var(--line) 60%,transparent)}.tick{position:relative;height:118px}.tick .t{position:absolute;left:0;top:-9px;width:104px;text-align:right;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:15px;color:var(--muted);letter-spacing:.02em}.tick .t small{display:block;font-family:Inter,sans-serif;font-size:9px;letter-spacing:.2em;color:var(--faint);margin-top:2px}.tick::after{content:"";position:absolute;left:112px;top:-7px;width:14px;height:14px;border-radius:50%;background:var(--page);border:2px solid var(--faint)}.tick.major::after{border-color:var(--red);box-shadow:0 0 0 5px rgba(232,50,30,.12)}.tick.major .t{color:var(--ink)}.daypart{position:absolute;left:0;top:-34px;display:flex;align-items:center;gap:10px;color:var(--emerald-hi);font-size:10px;font-weight:800;letter-spacing:.24em;text-transform:uppercase;white-space:nowrap}.daypart::after{content:"";width:52px;height:1px;background:var(--emerald-hi);opacity:.5}.now-marker{position:absolute;left:96px;right:0;top:0;z-index:5;display:flex;align-items:center;gap:10px;pointer-events:none}.now-marker .dot{width:12px;height:12px;flex:none;border-radius:50%;background:var(--red);box-shadow:0 0 0 6px rgba(232,50,30,.18),0 0 16px var(--emerald-hi);animation:nowpulse 2s ease-in-out infinite}.now-marker .line{flex:1;height:2px;background:linear-gradient(90deg,var(--red),rgba(232,50,30,.15));box-shadow:0 0 18px rgba(232,50,30,.55)}.now-marker .pill{flex:none;background:var(--red);border:1px solid var(--red);color:#fff;font-size:10px;font-weight:800;letter-spacing:.14em;padding:7px 12px;border-radius:999px;box-shadow:0 8px 26px rgba(43,43,48,.5);white-space:nowrap}@keyframes nowpulse{50%{box-shadow:0 0 0 9px rgba(232,50,30,.08),0 0 16px var(--red)}}.events{position:relative;display:block;padding-left:44px;min-width:0}button.tl-btn{all:unset;display:block;width:100%;margin:0 0 22px;cursor:pointer;text-align:left;box-sizing:border-box}button.tl-btn:focus-visible .event{outline:2px solid var(--focus);outline-offset:3px}.event{position:relative;display:grid;grid-template-columns:300px minmax(0,1fr);border:1px solid var(--line);border-radius:20px;overflow:hidden;background:var(--surface);transition:transform .3s cubic-bezier(.2,.7,.25,1),border-color .25s,box-shadow .3s}.event:hover{transform:translateY(-4px);border-color:var(--line-strong);box-shadow:0 24px 60px rgba(0,0,0,.5)}.event .art{position:relative;min-height:172px;background:var(--surface-2)}.event .art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.event .art::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,transparent 55%,rgba(13,11,10,.55));pointer-events:none}.event .mono{position:absolute;inset:0;display:grid;place-items:center;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:64px;color:var(--ink);background:linear-gradient(135deg,#1e1a18,#2b2b30 130%)}.event .air{position:absolute;left:14px;bottom:12px;z-index:2;background:rgba(13,11,10,.78);backdrop-filter:blur(8px);border:1px solid var(--line-strong);border-radius:10px;padding:8px 12px;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:15px;letter-spacing:.02em;color:var(--ink);white-space:nowrap}.event .air small{display:block;font-family:Inter,sans-serif;font-size:9px;letter-spacing:.18em;color:var(--emerald-hi);font-weight:800;margin-bottom:2px}.event .body{padding:22px 26px;display:flex;flex-direction:column;justify-content:center;gap:8px;min-width:0}.event h3{margin:0;font-size:21px;font-weight:780;letter-spacing:-.01em;color:var(--ink);display:flex;align-items:center;gap:10px;flex-wrap:wrap}.live-pill{display:inline-flex;align-items:center;gap:6px;min-height:24px;padding:0 10px;border-radius:999px;background:var(--emerald);color:#fff;font-size:10px;font-weight:800;letter-spacing:.12em}.live-pill::before{content:"";width:7px;height:7px;border-radius:50%;background:#fff;animation:nowpulse 1.6s ease-in-out infinite}.event .meta{margin:0;color:var(--muted);font-size:13px;line-height:1.55}.event .foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:2px}.net{display:inline-flex;align-items:center;min-height:30px;padding:0 13px;border-radius:999px;background:rgba(237,230,214,.07);border:1px solid var(--line);font-size:11.5px;font-weight:700;letter-spacing:.04em;color:var(--copy);white-space:nowrap}.go{color:var(--emerald-hi);font-size:12.5px;font-weight:780;white-space:nowrap}.event::before{content:"";position:absolute;left:-44px;top:50%;width:44px;height:2px;background:var(--line-strong);pointer-events:none}.event::after{content:"";position:absolute;left:-50px;top:calc(50% - 5px);width:10px;height:10px;border-radius:50%;background:var(--ink);box-shadow:0 0 12px rgba(237,230,214,.25);pointer-events:none}.timeline-foot{display:flex;justify-content:center;margin-top:4px}.schedule-toggle{display:none;margin:14px auto 0}.schedule-toggle.visible{display:inline-flex}.timeline-empty{display:grid;place-items:center;min-height:250px;padding:40px;border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface);color:var(--copy);text-align:center;line-height:1.6;margin-top:52px}.timeline-empty[hidden]{display:none}.earlier{margin-top:56px;border-top:1px solid var(--line);padding-top:30px}.earlier[hidden]{display:none}.earlier h4{margin:0 0 18px;font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--muted);font-weight:800}.earlier-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}button.mini{all:unset;display:flex;align-items:center;gap:14px;padding:14px 16px;border:1px solid var(--line);border-radius:14px;background:var(--surface);transition:border-color .2s,transform .2s;cursor:pointer;color:var(--ink);box-sizing:border-box;min-width:0}button.mini:hover{border-color:var(--line-strong);transform:translateY(-2px)}button.mini:focus-visible{outline:2px solid var(--focus);outline-offset:3px}.mini .mt{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;color:var(--emerald-hi);white-space:nowrap;flex:none}.mini .mini-copy{display:flex;flex-direction:column;min-width:0}.mini .ms{font-size:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mini .mn{font-size:11px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.timeline-note{margin-top:40px;color:var(--faint);font-size:12px;line-height:1.6}@media(prefers-reduced-motion:reduce){.now-marker .dot,.live-pill::before{animation:none}.event,.event:hover{transform:none;transition:none}button.mini,button.mini:hover{transform:none}}
    .poster-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:17px}.poster-card{position:relative;overflow:hidden;border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface);cursor:pointer;text-align:left;box-shadow:0 18px 48px rgba(0,0,0,.14);transition:transform .26s cubic-bezier(.2,.75,.2,1),border-color .22s,box-shadow .22s}.poster-card:hover{transform:translateY(-6px);border-color:var(--line-strong);box-shadow:0 26px 58px rgba(0,0,0,.23)}.poster-card:active{transform:translateY(-2px) scale(.987)}.poster-art{position:relative;display:block;overflow:hidden;aspect-ratio:2/3;background:var(--surface-2)}.poster-art img{display:block;width:100%;height:100%;object-fit:cover;transition:transform .55s cubic-bezier(.2,.7,.2,1),filter .3s}.poster-card:hover .poster-art img{transform:scale(1.035);filter:saturate(1.07)}.poster-art::after{content:"";position:absolute;inset:auto 0 0;height:34%;background:linear-gradient(transparent,rgba(0,0,0,.7))}.poster-badge{position:absolute;z-index:2;left:12px;bottom:11px;padding:5px 8px;border-radius:7px;background:rgba(13,11,10,.72);color:#ede6d6;font-size:9px;font-weight:760;letter-spacing:.1em;text-transform:uppercase;backdrop-filter:blur(10px)}.poster-copy{display:block;padding:17px 16px 18px}.poster-copy h3{display:-webkit-box;min-height:2.4em;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:16px;line-height:1.2}.genre{display:block;margin-top:7px;color:var(--muted);font-size:11px}
    .wide-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:17px}.wide-card{position:relative;overflow:hidden;min-height:360px;border:1px solid var(--line);border-radius:var(--radius-lg);background:#0d0b0a;cursor:pointer;text-align:left;color:#ede6d6;box-shadow:var(--shadow);transition:transform .25s,border-color .22s}.wide-card:hover{transform:translateY(-5px);border-color:var(--line-strong)}.wide-card:active{transform:translateY(-1px) scale(.99)}.wide-card img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .65s cubic-bezier(.2,.7,.2,1)}.wide-card:hover img{transform:scale(1.04)}.wide-card::after{content:"";position:absolute;inset:0;background:linear-gradient(0deg,rgba(13,11,10,.94),rgba(13,11,10,.02) 70%)}.wide-copy{position:absolute;z-index:2;inset:auto 26px 25px}.wide-copy h3{margin-top:7px;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:24px;line-height:1.08}.wide-copy span{color:var(--copy-hi);font-size:12px}
    .ad-slot{position:relative;display:flex;justify-content:center;align-items:center}.ad-label{position:absolute;top:10px;right:14px;color:var(--muted);font-size:9px;letter-spacing:.15em;text-transform:uppercase}.ad-unit{border:1px solid var(--line);border-radius:16px;background:var(--surface)}.ad-copy strong{display:block;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:19px;font-weight:600;line-height:1.2}.ad-copy span{display:block;margin-top:6px;color:var(--muted);font-size:12.5px;line-height:1.55}
    .ad-leaderboard{margin:0 auto;padding:36px 20px;min-height:162px;border-bottom:1px solid var(--line);background:rgba(var(--ink-rgb),.02)}.ad-leaderboard .ad-unit{display:flex;align-items:center;gap:26px;width:728px;max-width:100%;min-height:90px;padding:18px 28px}.ad-leaderboard .ad-copy{flex:1;min-width:0}
    .more-layout{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:17px;align-items:start}.ad-rail .ad-unit{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:16px;width:300px;max-width:100%;min-height:600px;margin-left:auto;padding:30px 24px;border-radius:var(--radius-lg);text-align:center}.ad-rail .ad-copy strong{font-size:21px}
    @media(max-width:1199px){.more-layout{grid-template-columns:1fr}.ad-rail .ad-unit{width:300px;min-height:250px;margin:4px auto 0}}
    @media(max-width:820px){.ad-leaderboard{min-height:310px;padding:28px 16px}.ad-leaderboard .ad-unit{flex-direction:column;justify-content:center;gap:14px;width:300px;min-height:250px;padding:24px 20px;text-align:center}.ad-leaderboard .ad-copy strong{font-size:18px}}
    .spotlight{position:relative;overflow:hidden;min-height:690px;border-radius:var(--radius-lg);background:#0d0b0a;color:#ede6d6;box-shadow:var(--shadow)}.spotlight img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;filter:saturate(.8)}.spotlight::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(13,11,10,.94),rgba(13,11,10,.58) 45%,rgba(13,11,10,.12)),linear-gradient(0deg,rgba(13,11,10,.88),transparent 58%)}.spotlight-copy{position:relative;z-index:2;display:flex;min-height:690px;max-width:650px;padding:70px 62px;flex-direction:column;justify-content:flex-end}.spotlight-copy h2{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:clamp(44px,5.8vw,80px);line-height:.92;letter-spacing:-.047em}.spotlight-copy h2 em{display:block;color:var(--emerald-hi);font-style:normal}.spotlight-copy p{margin:23px 0 27px;color:var(--copy-hi);font-size:16px;line-height:1.72}.snapshot-note{margin-top:26px;color:var(--faint);font-size:11px;line-height:1.55}
    .browse{min-height:100vh}.browse .shell{padding-top:104px}.browse-head{display:flex;align-items:end;justify-content:space-between;gap:40px;margin-bottom:34px}.search-wrap{display:flex;align-items:center;gap:10px;width:min(470px,100%);border:1px solid var(--line);border-radius:999px;background:var(--surface);padding:0 18px;transition:border-color .2s,box-shadow .2s,background .2s}.search-wrap:hover{border-color:var(--line-strong)}.search-wrap:focus-within{border-color:var(--emerald-hi);box-shadow:0 0 0 4px rgba(43,43,48,.15);background:var(--surface-2)}.search-wrap svg{flex:none;color:var(--muted)}.search-wrap input{width:100%;border:0;outline:0;background:transparent;color:var(--ink);padding:15px 0}.search-wrap input::placeholder{color:var(--muted)}.filter-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:31px}
/* ============ REWIND BROWSE TABS: TV · Movies · Music style contract ============
   The music lane mounts the Music panel inside Browse; this one component styles
   the tab switcher for all three tabs. Selected state via [aria-selected="true"]
   (preferred) or .active. TV is the default tab. No tab-specific overrides. */
.browse-tabs{display:inline-flex;gap:4px;padding:4px;border:1px solid var(--line);border-radius:999px;background:rgba(13,11,10,.55);margin-bottom:31px;max-width:100%}
.browse-tab{flex:1 1 0;border:0;background:transparent;color:var(--muted);font:700 13px/1 "Inter","Helvetica Neue",Helvetica,Arial,sans-serif;letter-spacing:.02em;padding:12px 22px;border-radius:999px;cursor:pointer;white-space:nowrap;transition:color .18s ease,background .18s ease,transform .12s ease}
.browse-tab:hover{color:var(--ink);background:rgba(237,230,214,.07)}
.browse-tab:active{transform:scale(.97)}
.browse-tab[aria-selected="true"],.browse-tab.active{background:var(--pearl);color:#161114}
.browse-tab:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
[data-theme="light"] .browse-tab[aria-selected="true"],[data-theme="light"] .browse-tab.active{background:#2b2b30;color:#f4f1ea}
@media(max-width:560px){.browse-tabs{display:flex;width:100%}.browse-tab{padding:12px 8px;font-size:12.5px}}
@media(prefers-reduced-motion:reduce){.browse-tab{transition:none}}.chip{min-height:44px;border:1px solid var(--line);border-radius:999px;background:transparent;color:var(--muted);padding:0 17px;cursor:pointer;font-size:12px;font-weight:650;transition:color .17s,background .17s,border-color .17s,transform .12s}.chip:hover{color:var(--ink);border-color:var(--line-strong);background:rgba(var(--ink-rgb),.055)}.chip:active{transform:scale(.96)}.chip.active{border-color:var(--emerald);background:var(--emerald);color:var(--ink)}.catalog{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:17px}.empty{display:none;padding:74px 20px;border:1px dashed var(--line);border-radius:var(--radius-md);color:var(--muted);text-align:center}.empty.visible{display:block}#emptyState .cta{margin-top:20px}
    .library{min-height:100vh}.library-hero{padding:120px 40px 75px;text-align:center}.library-hero .eyebrow{justify-content:center}.library-hero p{max-width:650px;margin:23px auto;color:var(--copy);font-size:16px;line-height:1.7}.library-hero h2 span{color:var(--emerald-hi)}.library-native{max-width:1160px;margin:0 auto 140px;padding:0 40px}.library-surface{overflow:hidden;border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--surface);box-shadow:var(--shadow)}.library-top{display:flex;align-items:center;justify-content:space-between;padding:23px 28px;border-bottom:1px solid var(--line)}.library-top h2{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:23px}.meta{color:var(--emerald-hi);font-size:10px;font-weight:800;letter-spacing:.11em;text-transform:uppercase}.library-grid{display:grid;grid-template-columns:1fr 1fr;min-height:430px}.library-empty{display:grid;place-items:center;padding:50px;text-align:center}.empty-mark{display:grid;place-items:center;width:60px;height:60px;margin:0 auto 19px;border:1px solid var(--line);border-radius:50%;color:var(--emerald-hi)}.library-empty h3{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:25px}.library-empty p{max-width:410px;margin:12px auto 24px;color:var(--muted);line-height:1.65}.library-art{position:relative;overflow:hidden;min-height:430px}.library-art img{width:100%;height:100%;object-fit:cover;filter:saturate(.82) brightness(.72)}.library-art::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,var(--surface),transparent 34%),linear-gradient(0deg,var(--surface),transparent 35%)}
    .modal{position:fixed;z-index:100;inset:0;display:grid;place-items:center;padding:24px;background:rgba(0,0,0,.78);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .24s ease,visibility .24s}.modal.open{opacity:1;visibility:visible;pointer-events:auto}.modal-card{position:relative;width:min(850px,100%);max-height:min(900px,92svh);overflow:auto;overscroll-behavior:contain;border:1px solid var(--line-strong);border-radius:24px;background:var(--surface);box-shadow:var(--shadow);transform:translateY(16px) scale(.985);opacity:.3;transition:transform .32s cubic-bezier(.2,.8,.2,1),opacity .25s}.modal.open .modal-card{transform:none;opacity:1}#showModal .modal-card{width:min(1200px,100%)}.modal-card>img{display:block;width:100%;max-height:400px;object-fit:cover}.modal-body{padding:30px}.modal-body h2{margin:9px 0 11px;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:clamp(28px,4vw,42px);line-height:1.03}.modal-body>p{color:var(--muted);line-height:1.67}.modal-cast{display:none;margin-top:14px;color:var(--copy);font-size:13px;line-height:1.6}.modal-cast strong{color:var(--ink);font-weight:700}.modal-close{position:absolute;z-index:3;top:15px;right:15px;display:grid;place-items:center;width:44px;height:44px;border:1px solid rgba(237,230,214,.28);border-radius:50%;background:rgba(13,11,10,.78);color:#fff;cursor:pointer;font-size:23px;line-height:1;backdrop-filter:blur(10px);transition:background .18s,border-color .18s,transform .14s}.modal-close:hover{background:var(--emerald);border-color:var(--emerald-hi)}.modal-close:active{transform:scale(.9)}.modal-actions{display:flex;gap:10px;margin-top:24px}.beta-card{width:min(660px,100%)}.beta-card .modal-body{padding:42px}.beta-card h2{font-size:clamp(32px,5vw,48px);line-height:1}.beta-form{display:grid;gap:15px;margin-top:27px}.field{display:grid;gap:8px;text-align:left}.field label{font-size:12px;font-weight:750;color:var(--copy)}.field input,.field select{width:100%;min-height:50px;border:1px solid var(--line);border-radius:12px;background:var(--surface-2);color:var(--ink);padding:13px 14px;transition:border-color .18s,background .18s,box-shadow .18s}.field input::placeholder{color:var(--muted)}.field input:hover,.field select:hover{border-color:var(--line-strong)}.field input:focus,.field select:focus{outline:0;border-color:var(--emerald-hi);background:var(--surface);box-shadow:0 0 0 4px rgba(43,43,48,.15)}.field select{cursor:pointer}.form-row{display:grid;grid-template-columns:1fr 1fr;gap:13px}.form-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:4px}.form-note{color:var(--muted);font-size:12px;line-height:1.55}.form-status{display:none;min-height:44px;padding:12px 14px;border-radius:10px;background:rgba(43,43,48,.12);color:var(--emerald-hi);font-size:13px;line-height:1.45;text-align:left}.form-status.visible{display:block}.form-status.error{background:color-mix(in srgb,var(--crimson) 13%,transparent);color:var(--ink)}.manual-fallback{display:grid;grid-template-columns:1fr auto;align-items:center;gap:12px;padding:15px;border:1px solid var(--line);border-radius:13px;background:var(--surface-2);transition:border-color .2s,background .2s,box-shadow .2s}.manual-fallback.prominent{border-color:rgba(237,230,214,.45);background:rgba(43,43,48,.11);box-shadow:0 0 0 4px rgba(43,43,48,.1)}.manual-copy{min-width:0;text-align:left}.manual-copy strong{display:block;font-size:12px}.manual-copy a{display:block;overflow:hidden;margin-top:4px;padding:6px 0;color:var(--emerald-hi);font-size:12px;text-overflow:ellipsis;white-space:nowrap;text-underline-offset:3px}.manual-actions{display:flex;gap:7px}.mini-btn{display:inline-flex;align-items:center;justify-content:center;min-height:44px;border:1px solid var(--line-strong);border-radius:999px;background:transparent;color:var(--ink);padding:0 13px;cursor:pointer;text-decoration:none;font-size:11px;font-weight:740;white-space:nowrap;transition:background .18s,border-color .18s,transform .12s}.mini-btn:hover{border-color:var(--emerald-hi);background:rgba(var(--ink-rgb),.07)}.mini-btn:active{transform:scale(.95)}.copy-buffer{position:fixed;left:-9999px;top:0;width:1px;height:1px;opacity:.01}
    footer{border-top:1px solid var(--line);padding:38px 40px;color:var(--muted);font-size:12px}.footer-inner{max-width:1360px;margin:auto;display:flex;justify-content:space-between;gap:20px;align-items:center}.footer-links{display:flex;gap:6px;flex-wrap:wrap}.footer-links button{min-height:44px;border:0;border-radius:999px;background:none;color:var(--muted);cursor:pointer;padding:0 11px;font-size:12px;transition:color .17s,background .17s}.footer-links button:hover{color:var(--ink);background:rgba(var(--ink-rgb),.06)}.footer-links button:active{transform:scale(.96)}.reveal{opacity:1;transform:none}.reveal.in{animation:revealIn .72s cubic-bezier(.2,.72,.2,1) both}
    @keyframes navLine{from{transform:scaleX(0)}to{transform:scaleX(1)}}@keyframes revealIn{from{opacity:.01;transform:translateY(20px)}to{opacity:1;transform:none}}@keyframes heroDrift{to{transform:scale(1.075) translate3d(-.7%,.4%,0)}}
    @media(max-width:1100px){.poster-grid,.catalog{grid-template-columns:repeat(4,minmax(0,1fr))}.wide-card{min-height:320px}}
    @media(max-width:820px){.topbar{padding:0 18px}.hero-copy{width:84vw;padding-left:28px}.hero-controls{right:28px}.shell{padding-inline:24px}.poster-grid,.catalog{grid-template-columns:repeat(3,minmax(0,1fr))}.wide-grid{grid-template-columns:1fr 1fr}.wide-card:last-child{grid-column:1/-1}.browse-head{align-items:start;flex-direction:column}.search-wrap{width:100%}.spotlight-copy{padding:58px 42px}}
    @media(max-width:600px){.topbar{height:auto;min-height:62px;padding:9px 10px 0;flex-wrap:wrap;row-gap:0}.top-left{display:contents}.wordmark{order:1;margin-right:4px;font-size:21px;min-height:44px;display:inline-flex;align-items:center}.top-actions{order:2;margin-left:auto;gap:2px}.primary-nav{order:3;flex:1 1 100%;gap:0;overflow-x:auto;padding:2px 2px 8px;scrollbar-width:none}.primary-nav::-webkit-scrollbar{display:none}.nav-btn{flex:none;min-height:44px;padding:0 12px;font-size:11px}.nav-btn.active::after{left:12px;right:12px}#inboxBtn{flex:none}.icon-btn[data-go="browse"]{display:none}.cta.nav-cta{min-height:44px;padding:0 13px}.cta .long{display:none}.cta .short{display:inline}.page{padding-top:118px}.hero{min-height:calc(100svh - 118px)}.hero-slide:nth-of-type(1) img{object-position:50% center}.hero-slide:nth-of-type(2) img{object-position:46% center}.hero-slide:nth-of-type(3) img{object-position:50% center}.hero-slide::after{background:linear-gradient(0deg,var(--page) 0%,rgba(13,11,10,.78) 48%,rgba(13,11,10,.14) 100%)}.hero-copy{width:100%;padding:280px 18px 92px}.hero h1{font-size:clamp(44px,14.7vw,66px)}.hero p{font-size:15px;margin-block:20px 25px}.hero-controls{left:18px;right:auto;bottom:35px}.hero-controls .round-btn{display:none}.hero-dot::after{width:23px}.hero-dot.active::after{transform:scaleX(1.65)}.shell{padding:78px 16px 90px}.section{margin-top:84px}.section-head{align-items:start;flex-direction:column;margin-bottom:23px}.section-head h2{font-size:clamp(33px,10vw,48px)}.timeline{grid-template-columns:64px minmax(0,1fr);margin-top:36px}.tl-rail::before{left:50px}.tick{height:96px}.tick .t{width:44px;font-size:11px}.tick .t small{font-size:8px}.tick::after{left:44px;top:-5px;width:10px;height:10px}.daypart{font-size:8.5px;top:-28px;letter-spacing:.12em}.now-marker{left:40px}.now-marker .pill{font-size:9px;padding:5px 9px}.events{padding-left:20px}button.tl-btn{margin-bottom:16px}.event{grid-template-columns:1fr}.event .art{min-height:150px}.event .art::after{background:linear-gradient(0deg,rgba(13,11,10,.5),transparent 60%)}.event::before{left:-20px;width:20px}.event::after{left:-24px}.event .body{padding:16px 18px}.event h3{font-size:17px}.earlier-grid{grid-template-columns:1fr 1fr}.timeline-empty{margin-top:36px}.poster-grid,.catalog{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.poster-copy{padding:13px 12px 14px}.poster-copy h3{font-size:13px}.poster-badge{left:8px;bottom:8px}.wide-grid{grid-template-columns:1fr}.wide-card,.wide-card:last-child{grid-column:auto;min-height:340px}.spotlight{min-height:650px;border-radius:20px}.spotlight img{object-position:64% center}.spotlight-copy{min-height:650px;padding:45px 23px}.spotlight-copy h2{font-size:clamp(40px,13vw,61px)}.browse .shell{padding-top:80px}.library-hero{padding:86px 19px 55px}.library-native{padding:0 14px;margin-bottom:90px}.library-grid{grid-template-columns:1fr}.library-art{order:-1;min-height:250px}.library-empty{padding:36px 22px 42px}.library-top{padding:20px}.library-top .meta{display:none}.modal{padding:8px}.wtw{padding:20px 18px;margin-top:18px}.wtw h3{font-size:19px}.wtw-svc{min-width:0;flex:1 1 calc(50% - 5px);padding:12px 14px;min-height:60px}.wtw-logo{width:34px;height:34px}.wtw-txt b{font-size:14px}.modal-card{border-radius:18px;max-height:95svh}#showModal #trailerStageTop{border-radius:18px 18px 0 0;height:auto;aspect-ratio:16/9;max-height:260px}#showModal #trailerStageTop .play-btn{width:76px;height:76px;border-width:2.5px}#showModal #trailerStageTop .play-btn svg{width:28px;height:28px;margin-left:4px}#showModal #trailerStageTop .play-wrap{gap:10px}#showModal #trailerStageTop .watch-label{min-height:36px;font-size:11.5px}#showModal .no-trailer-note{padding:12px 19px 0}.modal-card>img{max-height:260px}.modal-body,.beta-card .modal-body{padding:24px 19px}.modal-actions,.form-actions{align-items:stretch;flex-direction:column}.form-row{grid-template-columns:1fr}.manual-fallback{grid-template-columns:1fr}.manual-actions{width:100%}.mini-btn{flex:1}.footer-inner{align-items:center;flex-direction:column;text-align:center}.footer-links{justify-content:center}}
    @media(max-width:600px){.wordmark{font-size:17px;margin-right:4px;padding-right:6px}}
    @media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.hero-slide img{animation:none}.reveal,.reveal.in{opacity:1;transform:none;animation:none}*,*::before,*::after{transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}

    /* Priority-one polish: live lineup, editorial spotlight, embedded trailers, and real footer. */
    .skip-link{position:fixed;z-index:200;left:16px;top:10px;transform:translateY(-150%);padding:10px 14px;border-radius:10px;background:var(--ink);color:var(--page);font-size:12px;font-weight:800;text-decoration:none;transition:transform .18s ease}.skip-link:focus{transform:none}
    .eyebrow,.meta,.poster-badge,.genre,.wide-copy>span,.card-action,.ad-label{font-family:"Inter",sans-serif;font-weight:760;letter-spacing:-.01em}.eyebrow{font-size:10.5px;font-weight:750;letter-spacing:.16em;text-transform:uppercase}.poster-badge,.ad-label{text-transform:uppercase;letter-spacing:.12em}
    
    .brand-band{display:grid;grid-template-columns:minmax(240px,.85fr) minmax(0,1.65fr) auto;align-items:center;gap:34px;margin-top:64px;padding:38px 40px;border-block:1px solid var(--line);background:linear-gradient(90deg,rgba(43,43,48,.16),rgba(43,43,48,.03))}.brand-band h2{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:clamp(29px,3vw,46px);font-weight:570;line-height:1;letter-spacing:-.042em}.brand-props{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.brand-prop{color:var(--copy);font-size:13px;font-weight:720;line-height:1.45}.brand-prop::before{content:"";display:block;width:24px;height:2px;margin-bottom:10px;background:var(--emerald-hi)}
    .poster-copy h3{display:-webkit-box;min-height:2.4em;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2;white-space:normal;font-family:"Inter",sans-serif;font-size:15px;font-weight:780;letter-spacing:-.01em}.card-action{display:block;margin-top:12px;color:var(--emerald-hi);font-size:11px}.wide-copy h3{font-family:"Inter",sans-serif;font-size:22px;font-weight:780;letter-spacing:-.01em;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.wide-copy .card-action{margin-top:10px}.poster-grid.movies{grid-template-columns:repeat(3,minmax(0,1fr));max-width:900px}
    .spotlight{display:grid;grid-template-columns:55fr 45fr;min-height:520px;border:1px solid var(--line);background:var(--surface)}.spotlight::after{display:none}.spotlight-media{position:relative;overflow:hidden;min-height:520px}.spotlight-media::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,var(--surface),transparent 22%)}.spotlight img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;filter:saturate(.82)}.spotlight-copy{order:-1;min-height:520px;max-width:none;padding:58px 56px;justify-content:center}.spotlight-copy h2{font-size:clamp(42px,5vw,72px)}
    .trailer-stage{position:relative;overflow:hidden;aspect-ratio:16/9;margin-top:24px;border:1px solid var(--line);border-radius:16px;background:#0d0b0a}
    /* Generic facade/player treatment (the Watch Free stage reuses it): the
       trailer-at-top rules below override these for #trailerStageTop only. */
    .trailer-stage iframe,.trailer-facade,.trailer-facade img{display:block;width:100%;height:100%;border:0}
    .trailer-facade{position:relative;width:100%;padding:0;border:0;background:#0d0b0a;cursor:pointer}
    .trailer-facade img{object-fit:cover}
    .trailer-facade::after{content:"";position:absolute;inset:0;background:linear-gradient(0deg,rgba(0,0,0,.34),rgba(0,0,0,.04));pointer-events:none}
    .trailer-loading{position:absolute;z-index:3;left:14px;bottom:14px;display:none;padding:8px 11px;border-radius:999px;background:rgba(13,11,10,.84);color:#fff;font-size:11px;font-weight:760}
    .trailer-loading.visible{display:block}
/* ---- Trailer stage at the TOP of the title-detail popup (Gate 2 Rev 2) ----
   Full-bleed across the card: height min(470px,52vw) at full card width, art
   cropped cinematically via object-fit:cover. Zero dead space on the right.
   Scoped to #trailerStageTop: the Watch Free section reuses .trailer-stage
   with its own 16:9 box styles and must NOT inherit this treatment. */
#trailerStageTop{position:relative;overflow:hidden;height:min(470px,52vw);aspect-ratio:auto;margin-top:0;border:0;background:#0d0b0a;border-radius:24px 24px 0 0}
#trailerStageTop .stage-art{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
#trailerStageTop iframe,#trailerStageTop .trailer-facade,#trailerStageTop .trailer-facade img{display:block;width:100%;height:100%;border:0}
#trailerStageTop .trailer-facade img{object-fit:cover}
#trailerStageTop .trailer-facade{position:absolute;inset:0;width:100%;height:100%;padding:0;border:0;background:transparent;cursor:pointer}
#trailerStageTop .trailer-facade::after{content:"";position:absolute;inset:0;background:linear-gradient(0deg,rgba(0,0,0,.42),rgba(0,0,0,.05) 55%,rgba(0,0,0,.18))}
#trailerStageTop .play-wrap{position:absolute;z-index:2;left:50%;top:50%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:14px}
#trailerStageTop .play-btn{display:grid;place-items:center;width:104px;height:104px;border-radius:50%;border:3px solid rgba(255,255,255,.9);background:var(--emerald);color:#fff;box-shadow:0 18px 55px rgba(0,0,0,.55),0 0 0 10px rgba(43,43,48,.28);transition:transform .18s ease}
#trailerStageTop .trailer-facade:hover .play-btn{transform:scale(1.06)}
#trailerStageTop .play-btn svg{width:38px;height:38px;margin-left:5px}
#trailerStageTop .watch-label{display:inline-flex;align-items:center;min-height:40px;padding:0 20px;border-radius:999px;background:rgba(13,11,10,.8);border:1px solid rgba(237,230,214,.25);color:#fff;font-size:12.5px;font-weight:760;letter-spacing:.06em;backdrop-filter:blur(8px)}
#trailerStageTop .trailer-loading{position:absolute;z-index:3;left:50%;bottom:18px;transform:translateX(-50%);display:none;padding:9px 16px;border-radius:999px;background:rgba(13,11,10,.88);color:#fff;font-size:12px;font-weight:760;letter-spacing:.03em}
#trailerStageTop .trailer-loading.visible{display:block}
/* Player expanded in place at the top */
#trailerStageTop .player{position:absolute;inset:0;background:#000}
#trailerStageTop .player iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
#trailerStageTop .stage-ctrls{position:absolute;z-index:3;top:14px;left:14px;display:flex;gap:10px}
#trailerStageTop .stage-btn{display:grid;place-items:center;width:44px;height:44px;border:1px solid rgba(237,230,214,.28);border-radius:50%;background:rgba(13,11,10,.78);color:#fff;cursor:pointer;backdrop-filter:blur(10px);transition:background .18s,border-color .18s}
#trailerStageTop .stage-btn:hover{background:var(--emerald);border-color:var(--emerald-hi)}
#trailerStageTop .stage-btn svg{width:20px;height:20px}
#trailerStageTop .stage-btn .is-off{display:none}
#trailerStageTop .trailer-facade:focus-visible,#trailerStageTop .stage-btn:focus-visible{outline:2px solid var(--focus);outline-offset:3px}
/* Honest no-trailer caption: muted line beneath the stage, centered */
.no-trailer-note{display:block;max-width:840px;margin-inline:auto;padding:14px 30px 0;color:var(--muted);font-size:13px;text-align:center;letter-spacing:.01em}
.no-trailer-note[hidden]{display:none}
.no-trailer-note .dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--faint);margin-right:8px;vertical-align:1px}
#showModal .modal-body{max-width:840px;margin-inline:auto}.trailer-play{position:absolute;z-index:2;left:50%;top:50%;display:grid;place-items:center;width:68px;height:68px;border:2px solid rgba(255,255,255,.82);border-radius:50%;background:var(--emerald);color:#fff;transform:translate(-50%,-50%);font-size:25px;box-shadow:0 16px 45px rgba(0,0,0,.45)}
.wtw{margin-top:22px;border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface-2);padding:24px 26px;position:relative;overflow:hidden}
.wtw::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--emerald),var(--emerald-hi),var(--emerald))}
.wtw h3{font-size:21px;font-weight:750;letter-spacing:.01em;margin:0 0 8px}
.wtw-disclosure{font-size:13px;color:var(--muted);line-height:1.55;margin:0 0 18px;max-width:60ch}
.wtw-group{margin:0 0 18px}
.wtw-group:last-of-type{margin-bottom:12px}
.wtw-label{font-size:11px;font-weight:750;letter-spacing:.3em;text-transform:uppercase;color:var(--muted);margin-bottom:10px;display:flex;align-items:center;gap:12px}
.wtw-label::after{content:"";flex:1;height:1px;background:var(--line)}
.wtw-btns{display:flex;flex-wrap:wrap;gap:10px}
.wtw-svc{display:flex;align-items:center;gap:12px;text-decoration:none;color:var(--ink);border:1px solid var(--line-strong);border-radius:14px;padding:12px 16px;min-height:60px;min-width:200px;background:rgba(237,230,214,.03);transition:transform .15s ease,border-color .15s ease,background .15s ease}
.wtw-svc:hover{transform:translateY(-2px);border-color:rgba(237,230,214,.55);background:rgba(237,230,214,.06)}
.wtw-svc:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.wtw-logo{width:40px;height:40px;border-radius:10px;flex:none;object-fit:cover;background:#0d0b0a}
.wtw-txt{min-width:0}
.wtw-txt b{display:block;font-size:15px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wtw-txt span{font-size:12.5px;color:var(--muted)}
.wtw-svc.wtw-primary{background:var(--emerald);border-color:var(--emerald);color:#fff}
.wtw-svc.wtw-primary:hover{background:var(--emerald-hover);border-color:var(--emerald-hover)}
.wtw-svc.wtw-primary .wtw-txt span{color:rgba(255,255,255,.84)}
.wtw-tag{font-size:10px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;background:rgba(255,255,255,.18);color:#fff;padding:4px 10px;border-radius:999px;margin-left:auto;flex:none}
.wtw-fresh{font-size:12px;color:var(--faint);line-height:1.55;margin:2px 0 0}
.wtw-empty{font-size:14px;color:var(--muted);line-height:1.6;padding:6px 0 2px}
.modal-actions{align-items:center}.modal-actions .cta.textual{min-height:44px;margin-left:auto;padding:0 12px}
/* Watch Free (Gate 3, 2026-09-24): second native .wtw section in the title popup.
   Sits below trailer/synopsis, above paid "Where to watch". Rendered only when
   real free data exists — the node is absent from the DOM otherwise. */
.wtw-free .wtw-label.free-ads{color:var(--emerald-hi)}
.plays-badge{display:inline-flex;align-items:center;gap:8px;background:var(--emerald);color:#fff;font-size:11px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;padding:7px 14px;border-radius:999px}
.free-plays-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 12px}
.free-src{font-size:11px;font-weight:750;letter-spacing:.22em;text-transform:uppercase;color:var(--muted)}
.free-stage{margin:0}
.trailer-facade .free-plays-badge{position:absolute;top:12px;left:12px;z-index:3}
.free-disc{font-size:13px;color:var(--muted);line-height:1.55;margin:12px 0 14px;max-width:60ch}
.free-out{display:inline-flex;align-items:center;gap:10px;min-height:44px;margin:0 0 10px}
.free-verified{font-size:12px;color:var(--faint);line-height:1.55;margin:0 0 18px;max-width:62ch}
.free-fallback{border:1px dashed var(--line-strong);border-radius:14px;padding:18px;margin:0 0 18px;background:rgba(237,230,214,.02)}
.free-fallback .free-retry{width:100%;margin-bottom:10px}
.free-fallback p{font-size:14px;color:var(--muted);line-height:1.6;margin:0 0 12px}
.wtw-search-tag{color:var(--faint)}.wtw-honesty{font-size:13px;font-style:italic;color:var(--muted);line-height:1.6;margin:0 0 12px;max-width:60ch}
@media(max-width:600px){.free-out{width:100%;justify-content:center}}
    .beta-benefits{display:grid;gap:10px;margin:23px 0 20px;list-style:none}.beta-benefits li{display:grid;grid-template-columns:18px 1fr;gap:10px;color:var(--copy);font-size:14px;line-height:1.5}.beta-benefits li::before{content:"✓";color:var(--ink);font-weight:800}.next-step{color:var(--ink)!important;font-weight:670}.privacy-note{margin-top:2px;color:var(--muted);font-size:11px;line-height:1.45}
    .footer-shell{max-width:1360px;margin:auto}.footer-main{display:grid;grid-template-columns:1.3fr repeat(3,minmax(130px,.7fr));gap:46px;padding:32px 0 42px}.footer-brand{max-width:390px;color:var(--copy);font-size:14px;line-height:1.7}.footer-brand strong{display:block;margin-bottom:12px;font-family:"Previously Display",serif;color:var(--ink);font-size:26px;font-weight:400}.footer-group h2{margin-bottom:13px;color:var(--ink);font-size:12px}.footer-group a,.footer-group button,.social-placeholder{display:block;width:max-content;max-width:100%;min-height:44px;border:0;background:none;color:var(--muted);padding:7px 0;text-decoration:none;font-size:12px;cursor:pointer}.footer-group a:hover,.footer-group button:hover{color:var(--emerald-hi)}.social-placeholder{cursor:default}.footer-base{display:flex;justify-content:space-between;gap:24px;padding:25px 0 5px;border-top:1px solid var(--line);color:var(--muted);line-height:1.55}.footer-base p{max-width:720px}.sr-anchor{scroll-margin-top:90px}
    @media(min-width:601px){.spotlight-copy .cta{align-self:flex-start;width:auto}}
    @media(min-width:1200px){.more-layout{align-items:stretch}}
    @media(min-width:1440px){.poster-grid.movies{max-width:none}}
    @media(max-width:900px){.brand-band{grid-template-columns:1fr;gap:24px}.brand-band .cta{align-self:flex-start}.brand-props{grid-template-columns:repeat(3,1fr)}.footer-main{grid-template-columns:1fr 1fr}.spotlight{grid-template-columns:1fr 1fr}.spotlight-copy{padding:44px 34px}}
    @media(max-width:600px){.nav-cta{display:inline-flex;min-height:44px;padding:0 13px;font-size:12px}.hero-copy{display:flex;flex-direction:column;justify-content:flex-end;min-height:calc(100svh - 62px);padding:96px 18px 90px}.brand-band{margin-top:46px;padding:30px 18px}.brand-props{grid-template-columns:1fr;gap:13px}.brand-prop::before{display:inline-block;margin:0 10px 3px 0}.poster-grid.movies{grid-template-columns:repeat(2,minmax(0,1fr));max-width:none}.poster-grid.movies .poster-card:last-child{grid-column:1/-1;max-width:calc(50% - 5px);width:100%;justify-self:center}.spotlight{grid-template-columns:1fr}.spotlight-copy{min-height:auto;padding:40px 24px}.spotlight-media{min-height:310px}.spotlight-media::after{background:linear-gradient(0deg,var(--surface),transparent 24%)}.footer-main{grid-template-columns:1fr 1fr;gap:30px}.footer-brand{grid-column:1/-1}.footer-base{flex-direction:column}.trailer-play{width:58px;height:58px}}
    @media(max-width:1100px){}
  
/*PV2-CSS-APPENDED*/
/* ============================================================
   Previously — round 2 additions: retention, motion, HD artwork
   (appended 2026-09-23; extends the base Midnight Noir styles)
   ============================================================ */

/* ---------- Page transitions ---------- */
.view{animation:none}
.view.active{animation:viewIn .45s cubic-bezier(.2,.72,.2,1) both}
@keyframes viewIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

/* ---------- Cards: hover lift + glow + zoom (fine pointers only) ---------- */
.poster-card,.wide-card{position:relative;transition:transform .35s cubic-bezier(.2,.7,.25,1),box-shadow .35s ease,border-color .3s ease}
.poster-card .poster-art,.wide-card .poster-art{overflow:hidden}
.poster-card .poster-art img,.wide-card img{transition:transform .55s cubic-bezier(.2,.7,.25,1),filter .3s ease}
@media (hover:hover) and (pointer:fine){
  .poster-card:hover,.poster-card:focus-within{transform:translateY(-6px);box-shadow:0 26px 60px rgba(0,0,0,.55),0 0 0 1px rgba(237,230,214,.14);z-index:2}
  .wide-card:hover,.wide-card:focus-within{transform:translateY(-4px);box-shadow:0 22px 54px rgba(0,0,0,.5),0 0 0 1px rgba(237,230,214,.12);z-index:2}
  .poster-card:hover .poster-art img,.poster-card:focus-within .poster-art img{transform:scale(1.07)}
  .wide-card:hover img,.wide-card:focus-within img{transform:scale(1.05)}
  .card-hover{opacity:0;transition:opacity .28s ease}
  .poster-card:hover .card-hover,.poster-card:focus-within .card-hover,
  .wide-card:hover .card-hover,.wide-card:focus-within .card-hover{opacity:1}
  .star-btn{opacity:0;transform:translateY(-4px);transition:opacity .25s ease,transform .25s ease,background .18s,border-color .18s}
  .poster-card:hover .star-btn,.poster-card:focus-within .star-btn,
  .wide-card:hover .star-btn,.wide-card:focus-within .star-btn{opacity:1;transform:none}
  .star-btn[aria-pressed="true"]{opacity:1;transform:none}
}
@media (hover:none),(pointer:coarse){
  .card-hover{display:none}
  .poster-card:active,.wide-card:active{transform:scale(.985)}
}

/* Hover overlay: quick actions (desktop/keyboard only; touch uses the modal) */
.card-hover{position:absolute;inset:0;display:flex;align-items:flex-end;justify-content:space-between;padding:12px;background:linear-gradient(0deg,rgba(13,11,10,.82) 0%,rgba(13,11,10,.25) 45%,transparent 70%);pointer-events:none}
.card-hover .hover-actions{pointer-events:auto;display:flex;gap:8px}
.hover-chip{display:inline-flex;align-items:center;gap:6px;padding:8px 12px;border-radius:999px;border:1px solid rgba(237,230,214,.3);background:rgba(13,11,10,.72);color:var(--ink);font-size:12px;font-weight:600;cursor:pointer;backdrop-filter:blur(8px);transition:background .18s,border-color .18s,transform .14s}
.hover-chip:hover{background:var(--emerald);border-color:var(--emerald-hi)}
.hover-chip:active{transform:scale(.93)}

/* Star toggle (cards) */
.star-btn{position:absolute;top:10px;right:10px;z-index:3;display:grid;place-items:center;width:44px;height:44px;border-radius:50%;border:1px solid rgba(237,230,214,.32);background:rgba(13,11,10,.72);color:#ede6d6;cursor:pointer;backdrop-filter:blur(8px);transition:background .18s,border-color .18s,transform .14s,color .18s}
.star-btn svg{width:18px;height:18px}
.star-btn:hover{border-color:var(--emerald-hi)}
.star-btn:active{transform:scale(.88)}
.star-btn[aria-pressed="true"]{background:var(--emerald);border-color:var(--emerald-hi);color:#fff}
.star-btn[aria-pressed="true"] svg{fill:currentColor}
.star-btn.pop{animation:starPop .38s cubic-bezier(.2,.9,.3,1.4)}
@keyframes starPop{0%{transform:scale(.6)}55%{transform:scale(1.25)}100%{transform:scale(1)}}

/* ---------- Star + labels: one-time hint, hover tooltips ---------- */
/* One-time coach-mark hint (touch/coarse pointers only; shown once via JS) */
.star-hint{position:fixed;z-index:190;max-width:232px;background:var(--emerald-deep);color:#ede6d6;border-radius:14px;padding:13px 15px;font-size:14px;line-height:1.45;box-shadow:0 14px 34px rgba(0,0,0,.42);text-align:left}
.star-hint[hidden]{display:none}
.star-hint::before{content:"";position:absolute;top:-7px;right:30px;border:7px solid transparent;border-bottom-color:var(--emerald-deep);border-top:0}
.star-hint p{margin:0 0 10px}
.star-hint button{display:inline-block;min-height:44px;min-width:44px;background:#ede6d6;color:var(--emerald-deep);border:0;border-radius:999px;font-weight:700;font-size:13.5px;padding:8px 18px;cursor:pointer}
/* Netflix-style hover tooltips: fine pointers with hover ONLY — never on touch */
@media (hover:hover) and (pointer:fine){
  .hover-chip[data-tip]{position:relative} /* star-btn is already position:absolute */
  [data-tip]::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 9px);left:50%;transform:translateX(-50%) translateY(4px);background:#1e1a18;color:#ede6d6;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap;padding:8px 12px;border-radius:8px;z-index:60;pointer-events:none;opacity:0;transition:opacity .18s ease,transform .18s ease;box-shadow:0 8px 20px rgba(0,0,0,.35)}
  [data-tip]::before{content:"";position:absolute;bottom:calc(100% + 4px);left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#1e1a18;border-bottom:0;z-index:60;pointer-events:none;opacity:0;transition:opacity .18s ease}
  [data-tip]:hover::after,[data-tip]:focus-visible::after{opacity:1;transform:translateX(-50%) translateY(0)}
  [data-tip]:hover::before,[data-tip]:focus-visible::before{opacity:1}
}
/* FIX 2026-09-24: badge overlapped trailer chip; hover overlay above badge */
.poster-card:hover .card-hover,.poster-card:focus-within .card-hover,
.wide-card:hover .card-hover,.wide-card:focus-within .card-hover{z-index:3}
/* FIX 2026-09-24: .poster-card/.wide-card use overflow:hidden, so an
   above-the-button tooltip on .star-btn (top:10px) is clipped away.
   Star tooltips drop BELOW the button, right-anchored — fully visible. */
.star-btn[data-tip]::after{bottom:auto;top:calc(100% + 9px);left:auto;right:-4px;transform:translateY(-4px)}
.star-btn[data-tip]:hover::after,.star-btn[data-tip]:focus-visible::after{transform:translateY(0)}
.star-btn[data-tip]::before{bottom:auto;top:calc(100% + 4px);left:auto;right:15px;transform:none;border-top:0;border-bottom:5px solid #1e1a18}
/* NEW-episode badge */
.new-badge{position:absolute;top:10px;left:10px;z-index:3;padding:5px 10px;border-radius:999px;background:var(--emerald);color:#fff;font-size:10.5px;font-weight:800;letter-spacing:.08em;box-shadow:0 6px 18px rgba(43,43,48,.5);animation:badgeIn .4s cubic-bezier(.2,.9,.3,1.2) both}
@keyframes badgeIn{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}
.new-pill{display:inline-block;margin-left:8px;padding:3px 8px;border-radius:999px;background:var(--emerald);color:#fff;font-size:10px;font-weight:800;letter-spacing:.07em;vertical-align:middle}

/* ---------- Inbox bell ---------- */
#inboxBtn{position:relative}
.inbox-badge{position:absolute;top:2px;right:2px;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--emerald);color:#fff;font-size:10.5px;font-weight:800;line-height:18px;text-align:center;box-shadow:0 4px 12px rgba(43,43,48,.55);animation:badgeIn .35s cubic-bezier(.2,.9,.3,1.3) both}
.inbox-list{display:flex;flex-direction:column;gap:10px;margin-top:18px;max-height:46svh;overflow:auto}
.inbox-item{display:flex;gap:12px;align-items:center;width:100%;text-align:left;padding:10px;border:1px solid var(--line);border-radius:16px;background:var(--surface-2);cursor:pointer;transition:border-color .2s,transform .18s,background .2s}
.inbox-item:hover{border-color:var(--emerald-hi);transform:translateX(3px)}
.inbox-item img{width:52px;height:76px;object-fit:cover;border-radius:10px;flex:none}
.inbox-item .inbox-copy{min-width:0}
.inbox-item h3{font-size:15px;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.inbox-item p{font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.inbox-empty{padding:26px 10px;color:var(--muted);text-align:center;line-height:1.6}
.inbox-sub{color:var(--muted);font-size:14px;margin-top:6px}

/* ---------- Rails (horizontal scroll) ---------- */
.rail{display:grid;grid-auto-flow:column;grid-auto-columns:clamp(150px,17vw,210px);gap:14px;overflow-x:auto;overscroll-behavior-x:contain;padding:6px 2px 18px;scroll-snap-type:x proximity;scrollbar-width:thin}
.rail .poster-card{scroll-snap-align:start}
.section-foot{margin-top:6px}

/* ---------- Top 10 charts (Gate 3 build) ----------
   Rank numerals are real text; #1 alone gets the Emerald accent. */
.top10-rail{padding:8px 18px 22px 34px;scroll-padding-left:34px;scrollbar-width:none}
/* Lock chart card width against the later 1100px+ .rail widening (approved mockup size) */
.rail.top10-rail{grid-auto-columns:clamp(150px,17vw,210px);gap:14px}
@media(max-width:640px){.rail.top10-rail{grid-auto-columns:clamp(132px,38vw,168px);gap:10px}}
/* Empty state spans the rail full-width instead of one card column */
.rail.top10-rail.is-empty{display:block;padding:8px 0 4px}
.rail.top10-rail.is-empty .top10-empty{max-width:560px;margin:0 auto}
.top10-rail::-webkit-scrollbar{display:none}
@media(min-width:641px){.top10-rail{padding:10px 40px 26px 52px;scroll-padding-left:52px}}
.tcard{position:relative;background:none;border:0;padding:0;cursor:pointer;text-align:left;font:inherit;color:inherit;scroll-snap-align:start;border-radius:var(--radius-md)}
.tcard:focus-visible{outline:2px solid var(--focus);outline-offset:4px}
.tcard .artwrap{position:relative;display:block}
.tcard .art{position:relative;display:block;aspect-ratio:2/3;border-radius:var(--radius-md);overflow:hidden;border:1px solid var(--line);box-shadow:0 18px 48px rgba(0,0,0,.35);background:var(--surface-2);transition:transform .26s cubic-bezier(.2,.75,.2,1),border-color .22s,box-shadow .22s}
.tcard:hover .art{transform:translateY(-4px);border-color:var(--line-strong);box-shadow:0 26px 60px rgba(0,0,0,.5)}
.tcard .art picture{position:absolute;inset:0;display:block}
.tcard .art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.tcard .art::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 46%,rgba(5,4,3,.72) 100%)}
/* Art-overlay chips use fixed pearl ink (the hero's --hero-ink pattern): the
   artwork is always dark, in both themes. */
.tcard .ptype{position:absolute;z-index:2;left:10px;top:10px;font-size:9.5px;font-weight:800;letter-spacing:.14em;padding:5px 9px;border-radius:999px;background:rgba(13,11,10,.72);border:1px solid var(--line-strong);color:#ede6d6;backdrop-filter:blur(6px)}
.tcard .pgenre{position:absolute;z-index:2;left:12px;top:38px;font-size:9px;font-weight:800;letter-spacing:.22em;text-transform:uppercase;color:rgba(237,230,214,.78)}
.tcard .ptitle{position:absolute;z-index:2;left:12px;right:12px;bottom:12px;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:700;font-size:17px;line-height:1.12;letter-spacing:-.01em;color:#ede6d6;text-shadow:0 2px 12px rgba(0,0,0,.8)}
@media(min-width:641px){.tcard .ptitle{left:14px;right:14px;bottom:14px;font-size:19px}.tcard .ptype{left:12px;top:12px}.tcard .pgenre{left:14px}}
.tcard .rank{position:absolute;z-index:3;left:-.34em;bottom:-8px;font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:800;font-size:58px;line-height:.8;letter-spacing:-.04em;color:var(--ink);text-shadow:0 3px 16px rgba(0,0,0,.85),0 1px 2px rgba(0,0,0,.9);pointer-events:none}
.tcard .rank.r1{color:#2b2b30;-webkit-text-stroke:1.5px var(--ink);paint-order:stroke fill;text-shadow:0 4px 22px rgba(0,0,0,.9)}
@media(min-width:641px){.tcard .rank{font-size:78px;bottom:-10px;left:-.32em}}
.tcard .meta{display:block;padding:12px 4px 0}
.tcard .meta .t{display:block;color:var(--ink);font-size:14.5px;font-weight:700;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tcard .meta .g{display:block;margin-top:5px;font-size:12px;color:var(--muted)}
.tcard .meta .trate{color:var(--emerald-hi);font-weight:700}
.top10-fresh{display:flex;align-items:center;gap:8px;margin-top:12px;color:var(--faint);font-size:12.5px;font-weight:600}
.top10-fresh .dot{width:7px;height:7px;border-radius:50%;background:var(--red);box-shadow:0 0 12px rgba(232,50,30,.8);flex:none}
.top10-fresh.stale{color:var(--muted)}
.top10-fresh.stale .dot{background:var(--muted);box-shadow:none}
.top10-empty{border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface);padding:38px 26px;text-align:center}
.top10-empty h3{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:23px;font-weight:570;letter-spacing:-.02em;line-height:1.2}
.top10-empty p{margin-top:10px;color:var(--muted);font-size:13.5px;line-height:1.65}
.top10-empty .cta{margin-top:20px}
/* ---------- "One film." signature band (slim, between the charts) ---------- */
.onefilm{margin:64px -40px 8px;padding:44px 40px;text-align:center;border-block:1px solid var(--line);background:linear-gradient(180deg,rgba(43,43,48,.10),rgba(43,43,48,.02))}
.onefilm .eyebrow{justify-content:center}
.onefilm .eyebrow::after{content:"";width:28px;height:1px;background:currentColor}
.onefilm h2{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:44px;font-weight:570;letter-spacing:-.038em;line-height:1.05}
.onefilm p{margin-top:12px;color:var(--muted);font-size:15px}
@media(max-width:640px){.onefilm{margin:44px -16px 6px;padding:34px 18px}.onefilm h2{font-size:30px}.onefilm p{font-size:13.5px}}
@media(prefers-reduced-motion:reduce){.tcard:hover .art{transform:none}}

/* ---------- Schedule rows with artwork ---------- */

@keyframes rowIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.schedule-art{width:52px;height:76px;border-radius:10px;object-fit:cover;background:var(--surface-3)}

.freshness{font-size:12px;color:var(--muted);font-weight:400}




/* ---------- Modal engage row (star + alerts) ---------- */
.modal-engage{display:flex;gap:10px;margin:14px 0 4px}
.engage-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:12px 18px;border-radius:999px;border:1px solid var(--line-strong);background:transparent;color:var(--ink);font-size:13.5px;font-weight:700;cursor:pointer;transition:background .2s,border-color .2s,transform .14s,color .2s}
.engage-btn:hover{border-color:var(--emerald-hi)}
.engage-btn:active{transform:scale(.94)}
.engage-btn[aria-pressed="true"]{background:var(--emerald);border-color:var(--emerald-hi);color:#fff}
.engage-btn[aria-pressed="true"] svg{fill:currentColor}
.engage-btn.ring svg{animation:bellRing .5s ease;transform-origin:top center}
@keyframes bellRing{0%,100%{transform:rotate(0)}25%{transform:rotate(14deg)}55%{transform:rotate(-11deg)}80%{transform:rotate(6deg)}}
.modal-rating{margin-top:10px;color:var(--copy);font-size:13px}
.modal-rating strong{color:var(--emerald-hi);font-size:15px}

/* ---------- Library alerts ---------- */
.library-alerts{margin:6px 0 26px;padding:20px;border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface)}
.library-alerts h2{font-size:19px;margin-bottom:4px}
.library-alerts-sub{color:var(--muted);font-size:13px;margin-bottom:14px}
.alert-row{display:flex;align-items:center;gap:12px;padding:10px 4px;border-top:1px solid var(--line)}
.alert-row:first-of-type{border-top:none}
.alert-row img{width:40px;height:58px;object-fit:cover;border-radius:8px}
.alert-row .alert-copy{flex:1;min-width:0}
.alert-row h3{font-size:14.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.alert-row p{font-size:12px;color:var(--muted)}
.alert-toggle{position:relative;flex:none;width:52px;height:30px;border-radius:999px;border:1px solid var(--line-strong);background:var(--surface-3);cursor:pointer;transition:background .22s,border-color .22s}
.alert-toggle::after{content:"";position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:50%;background:#8d8478;transition:transform .22s cubic-bezier(.2,.8,.3,1.2),background .22s}
.alert-toggle[aria-pressed="true"]{background:var(--emerald);border-color:var(--emerald-hi)}
.alert-toggle[aria-pressed="true"]::after{transform:translateX(22px);background:#fff}

/* ---------- Browse show-more ---------- */
.browse-more{display:flex;justify-content:center;margin:26px 0 8px}

/* ---------- Footer wordmark ---------- */
.footer-wordmark{font-size:21px;display:inline-flex;align-items:center;gap:10px}.footer-wordmark .wm-glyph{flex:none}

/* ---------- Legal status note ---------- */
.legal-status{background:var(--surface-2);border:1px solid var(--line);border-radius:14px;padding:14px 16px;margin-bottom:18px;font-size:14px;line-height:1.6}

/* ---------- Trailer facade polish ---------- */
.trailer-facade img{transition:transform .5s cubic-bezier(.2,.7,.25,1)}
.trailer-facade:hover img{transform:scale(1.04)}

/* ---------- Micro-interactions ---------- */
.chip,.nav-btn,.round-btn,.text-link,.icon-btn{transition:color .18s,background .18s,border-color .18s,transform .14s}
.chip:active,.nav-btn:active,.round-btn:active,.icon-btn:active{transform:scale(.93)}
.cta{transition:background .2s,border-color .2s,transform .14s,box-shadow .25s}
.cta:active{transform:scale(.96)}
.cta:not(.secondary):hover{box-shadow:0 10px 30px rgba(43,43,48,.4)}

/* ---------- Responsive: rails & schedule ---------- */
@media (max-width:640px){
  .rail{grid-auto-columns:clamp(132px,38vw,168px);gap:10px}
  .modal-engage{flex-wrap:wrap}
}
@media (min-width:1100px){
  .rail{grid-auto-columns:clamp(170px,13vw,220px)}
}

/* ---------- Reduced motion: everything calms down ---------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001s!important;animation-iteration-count:1!important;transition-duration:.001s!important}
  .hero-slide img{animation:none!important}
  .view.active{animation:none}
  html{scroll-behavior:auto}
}

/* ---------- Card open button (wraps art + copy) ---------- */
.card-open{all:unset;display:block;width:100%;cursor:pointer;color:inherit;font:inherit;text-align:left;box-sizing:border-box}
.card-open:focus-visible{outline:2px solid var(--focus);outline-offset:3px;border-radius:18px}
.card-rating{display:block;margin-top:6px;font-size:12.5px;color:var(--emerald-hi);font-weight:700}
.sr-anchor{scroll-margin-top:90px}
/* Wide-card hover overlay alignment */
.wide-card .card-hover{border-radius:inherit}

/* ---------- Neutral Guide (bet #1) ---------- */
.neutral-line{font-size:12.5px;color:var(--muted)}
.neutral-line .text-link{font-size:12.5px}
.rank-note{color:var(--muted);font-size:13px}


    /* ============ REWIND DRAG-DROP THEME HOOKS (shared module: previously-site/batch3-2026-09-26/shared/drag-drop/) ============
    :root{--pv-drop:var(--dnd-red);--pv-handle:var(--dnd-bone);--pv-gap:rgba(232,50,30,.16);--pv-ghost:var(--dnd-charcoal);--pv-spring:cubic-bezier(.2,.9,.25,1.2)}/* --pv-* aliases the shared PreviouslyDnD tokens (--dnd-*) so the drag visual language has one source of truth */
  
/* ---------- genre pill slider (tucked into Browse) ---------- */
.filter-row.genre-slider{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--line) transparent;scroll-snap-type:x proximity;padding-bottom:8px;margin-bottom:23px}
.filter-row.genre-slider::-webkit-scrollbar{height:6px}
.filter-row.genre-slider::-webkit-scrollbar-thumb{background:var(--line);border-radius:3px}
.filter-row.genre-slider .chip{flex:0 0 auto;scroll-snap-align:start}
#genrePills{display:contents}
.chip .gct{opacity:.6;font-weight:600;font-size:11px;margin-left:7px;font-variant-numeric:tabular-nums}
</style>
  <style>
    /* Legal pages: Terms of Service + Privacy Policy */
    .legal{max-width:800px;margin:0 auto;padding:72px 40px 120px}
    .legal h2{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:clamp(36px,4.6vw,58px);font-weight:570;line-height:1.02;letter-spacing:-.04em;margin:0 0 14px;color:var(--ink)}
    .legal-meta{color:var(--muted);font-size:13px;line-height:1.7;margin-bottom:8px}
    .legal-meta a{color:var(--emerald-hi);text-decoration:none}
    .legal-meta a:hover{text-decoration:underline}
    .legal-body{margin-top:44px}
    .legal-body h2{font-family:"Inter","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:clamp(20px,2.6vw,26px);font-weight:570;letter-spacing:-.02em;margin:46px 0 14px;color:var(--ink)}
    .legal-body h2:first-child{margin-top:0}
    .legal-body h3{font-size:15px;font-weight:760;margin:26px 0 10px;color:var(--ink)}
    .legal-body p,.legal-body li{color:var(--copy);font-size:15px;line-height:1.78}
    .legal-body p{margin:0 0 14px}
    .legal-body ul{margin:0 0 16px;padding-left:22px;display:grid;gap:9px}
    .legal-body strong{color:var(--ink);font-weight:700}
    .legal-body a{color:var(--emerald-hi);text-decoration:none}
    .legal-body a:hover{text-decoration:underline}
    .legal-back{margin-bottom:38px}
    .wordmark-inline{font-family:"Previously Display",serif}
    @media(max-width:600px){.legal{padding:56px 20px 90px}}

    /* inbox: coming-soon reminders group (inbox-first delivery; email comes later) */
    .inbox-div{margin:18px 2px 2px;font-size:11px;font-weight:800;letter-spacing:.22em;text-transform:uppercase;color:var(--emerald-hi)}
    .inbox-rem{align-items:center}
    .inbox-remove{margin-left:auto;flex:none;color:var(--muted)}
    .inbox-remove:hover{color:var(--ink)}

    /* ============ LIGHT THEME — designed from scratch, clean white like Google.
       Dark Midnight Noir stays the brand default. The toggle is website-only;
       the Previously app is unaffected. ============ */
    html[data-theme="light"]{background:#f4f1ea}
    [data-theme="light"]{
      color-scheme:light;
      --page:#f4f1ea; --page-rgb:244,241,234;
      --surface:#ede6d6; --surface-2:#e7dfcc; --surface-3:#dcd2bd;
      --ink:#161114; --ink-rgb:22,17,20; --copy:#4a4238;
      --muted:#6f665d; --faint:#8d8478;
      --line:#d9cfbb; --line-strong:#c6b99f;
      --emerald:#2b2b30; --emerald-deep:#222226; --emerald-hi:#2b2b30; --emerald-hover:#34343b;
      --crimson:#e8321e;
      --shadow:0 1px 2px rgba(22,17,20,.16),0 16px 42px rgba(22,17,20,.14);
      --nav-bg:rgba(244,241,234,.9);
      --focus:#2b2b30;
    }
    /* theme switch: instant but smooth (killed under reduced motion below) */
    [data-theme] body,[data-theme] .topbar{transition:background-color .28s ease,color .28s ease,border-color .28s ease}
    /* dark imagery surfaces keep their pearl ink and bright emerald accents */
    [data-theme="light"] .event .air{color:#ede6d6}
    [data-theme="light"] .event .air small{color:var(--ink)}
    [data-theme="light"] .event .mono{color:#ede6d6}
    [data-theme="light"] .hover-chip{color:#ede6d6}
    [data-theme="light"] .hero-copy,[data-theme="light"] .hero-copy p,[data-theme="light"] .spotlight-copy p{color:#d8cdbd}
    /* light-surface restyle of hardcoded dark tints */
    [data-theme="light"] .net{background:rgba(22,17,20,.05)}
    [data-theme="light"] .wtw-svc{background:rgba(22,17,20,.035)}
    [data-theme="light"] .wtw-svc:hover{border-color:rgba(43,43,48,.45);background:rgba(22,17,20,.06)}
    [data-theme="light"] .event:hover{border-color:rgba(43,43,48,.4);box-shadow:0 2px 4px rgba(22,17,20,.16),0 16px 34px rgba(22,17,20,.16)}
    [data-theme="light"] button.mini:hover{border-color:rgba(43,43,48,.4)}
    [data-theme="light"] .tick.major::after{box-shadow:0 0 0 5px rgba(43,43,48,.15)}
    [data-theme="light"] .alert-toggle::after{background:#8d8478}
    [data-theme="light"] .modal{background:rgba(22,17,20,.55)}
    /* theme toggle control — 46px circular sun/moon, in the topbar everywhere */
    .theme-toggle{width:46px;height:46px;flex:none;border-radius:50%;border:1px solid var(--line-strong);
      display:grid;place-items:center;color:var(--muted);cursor:pointer;
      transition:color .2s,border-color .2s,background-color .28s ease,transform .2s}
    .theme-toggle:hover{color:var(--emerald-hi);border-color:var(--emerald-hi);transform:scale(1.06)}
    .theme-toggle svg{width:21px;height:21px}
    .theme-toggle .ic-moon{display:none}
    [data-theme="light"] .theme-toggle .ic-moon{display:block}
    [data-theme="light"] .theme-toggle .ic-sun{display:none}
    /* nav page-link styled exactly like the SPA nav buttons */
    a.nav-btn{text-decoration:none;display:inline-flex;align-items:center}
    @media (prefers-reduced-motion:reduce){
      [data-theme] body,[data-theme] .topbar{transition:none}
    }
  h2.free-h1{display:block;font-size:2em;font-weight:700;margin:.67em 0}
.spa-live-dot{width:8px;height:8px;border-radius:50%;background:#E8321E;flex:none;margin-right:7px;box-shadow:0 0 0 0 rgba(232,50,30,.55);animation:spa-live-pulse 1.8s infinite}
.spa-live-dot[hidden]{display:none}
@keyframes spa-live-pulse{0%{box-shadow:0 0 0 0 rgba(232,50,30,.55)}70%{box-shadow:0 0 0 9px rgba(232,50,30,0)}100%{box-shadow:0 0 0 0 rgba(232,50,30,0)}}
@media (prefers-reduced-motion:reduce){.spa-live-dot{animation:none}}
</style>
  <link rel="preload" href="data/catalog.c3540a80.js" as="script">
  <style>
/* ================= DRAG-TO-FAVORITES (2026-09-24) =================
   Sitewide long-press drag. Floating folder + coaching bubble + toast +
   Favorites popup (HD thumbnails) + drag-out-to-remove zone. */
[data-dragid]{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}
body.pv-dragging,body.pv-dragging *{touch-action:none!important;-webkit-user-select:none!important;user-select:none!important}
.poster-card.pv-lifting,.wide-card.pv-lifting,.tl-btn.pv-lifting,.mini.pv-lifting,.fav-row.pv-lifting{opacity:.35}
#pvFolder{position:fixed;z-index:210;right:20px;bottom:calc(20px + env(safe-area-inset-bottom));width:68px;height:68px;border-radius:50%;border:1px solid rgba(237,230,214,.25);background:linear-gradient(150deg,#34343b,#2b2b30 60%,#222226);color:#fff;font-size:28px;line-height:1;cursor:grab;display:flex;align-items:center;justify-content:center;box-shadow:0 10px 30px rgba(0,0,0,.5);animation:pvFloat 3.2s ease-in-out infinite;transition:transform .18s ease,box-shadow .18s ease;touch-action:none;-webkit-user-select:none;user-select:none}
@keyframes pvFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}
#pvFolder.pv-hot{transform:scale(1.22);box-shadow:0 0 0 10px rgba(232,50,30,.28),0 14px 34px rgba(0,0,0,.55);animation:none}
#pvFolder.pv-pop{animation:pvPop .45s ease}
@keyframes pvPop{0%{transform:scale(1)}35%{transform:scale(1.3)}70%{transform:scale(.94)}100%{transform:scale(1)}}
#pvFavCount{position:absolute;top:-4px;right:-4px;min-width:26px;height:26px;border-radius:999px;background:#2b2b30;color:#ede6d6;font-size:13px;font-weight:700;display:flex;align-items:center;justify-content:center;padding:0 7px;border:2px solid #161114}
#pvFavCount.pv-bump{animation:pvBump .4s ease}
@keyframes pvBump{0%{transform:scale(1)}40%{transform:scale(1.45)}100%{transform:scale(1)}}
#pvCoach{position:fixed;z-index:205;right:100px;bottom:calc(40px + env(safe-area-inset-bottom));max-width:230px;background:#26211e;border:1px solid #34343b;color:#ede6d6;border-radius:12px;padding:12px 14px;font-size:13.5px;line-height:1.5;box-shadow:0 12px 30px rgba(0,0,0,.5);cursor:pointer}
#pvCoach::after{content:"";position:absolute;right:-7px;bottom:22px;width:12px;height:12px;background:#26211e;border-right:1px solid #34343b;border-top:1px solid #34343b;transform:rotate(45deg)}
#pvCoach.pv-hide{display:none}
#pvToast{position:fixed;z-index:300;left:50%;bottom:calc(104px + env(safe-area-inset-bottom));transform:translateX(-50%) translateY(16px);background:#1e1a18;border:1px solid rgba(237,230,214,.14);color:#ede6d6;border-radius:999px;padding:12px 20px;font-size:14px;opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;white-space:nowrap;box-shadow:0 10px 28px rgba(0,0,0,.5);display:flex;align-items:center;gap:12px;max-width:92vw}
#pvToast.pv-show{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
#pvToast button{background:none;border:none;color:#f4f1ea;font-weight:700;font-size:14px;cursor:pointer;padding:6px 2px;min-height:32px}
#pvToast.pv-error{border-color:rgba(232,50,30,.6);background:#1e0f0d}
#pvToast.pv-error .pv-glyph{flex:none;display:grid;place-items:center;width:26px;height:26px;border-radius:50%;background:rgba(43,43,48,.55);border:1px solid var(--line-strong)}
#pvToast.pv-error .pv-glyph svg{display:block}
/* ---------- loading skeletons ---------- */
.skel{position:relative;overflow:hidden;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius-md);pointer-events:none}
.skel::after{content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent 20%,rgba(237,230,214,.08) 50%,transparent 80%);animation:skelShimmer 1.4s ease-in-out infinite}
@keyframes skelShimmer{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
.skel-card{aspect-ratio:2/3}
.skel-row{min-height:172px;border-radius:20px}
.skel-line{height:12px;border-radius:6px;background:rgba(237,230,214,.06);margin:12px 14px}
.skel-line.skel-w62{width:62%}.skel-line.skel-w38{width:38%}
@media(prefers-reduced-motion:reduce){.skel::after{animation:none}}
/* ---------- long-grid render perf ---------- */
.catalog,.poster-grid{content-visibility:auto;contain-intrinsic-size:auto 900px}
.events{content-visibility:auto;contain-intrinsic-size:auto 1200px}
.pv-ghost{position:fixed;z-index:400;left:0;top:0;pointer-events:none;border-radius:12px;overflow:hidden;box-shadow:0 24px 60px rgba(0,0,0,.65);will-change:transform,opacity;background:#1e1a18}
#pvRemoveZone{position:fixed;z-index:390;left:50%;top:calc(84px + env(safe-area-inset-top));transform:translateX(-50%) translateY(-8px);display:flex;align-items:center;gap:10px;padding:13px 22px;border-radius:999px;border:1.5px dashed rgba(237,230,214,.5);background:rgba(13,11,10,.88);color:#ede6d6;font-size:14px;font-weight:700;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s,border-color .2s,background .2s;backdrop-filter:blur(10px);white-space:nowrap}
#pvRemoveZone.pv-show{opacity:1;transform:translateX(-50%) translateY(0)}
#pvRemoveZone.pv-hot{border-color:#e8321e;background:rgba(232,50,30,.4);transform:translateX(-50%) scale(1.06)}
#pvFolder.pv-placed{right:auto;bottom:auto}
#pvFolder.pv-moving{animation:none;cursor:grabbing;z-index:395}
#pvFolder.pv-hidden{display:none}
#pvMenu{position:fixed;z-index:396;min-width:172px;background:#26211e;border:1px solid #34343b;border-radius:12px;box-shadow:0 12px 30px rgba(0,0,0,.5);padding:6px;display:flex;flex-direction:column;gap:2px}
#pvMenu.pv-hide{display:none}
#pvMenu button{background:none;border:0;color:#ede6d6;text-align:left;font-size:14px;font-weight:600;padding:12px;border-radius:8px;cursor:pointer;min-height:44px}
#pvMenu button:active{background:rgba(237,230,214,.12)}
#pvMenu .pv-menu-hint{font-size:11.5px;color:#8d8478;padding:6px 12px 8px;line-height:1.4}
#favModal{padding:24px}
#favModal .modal-card.fav-panel{margin:0;width:min(400px,100%);max-height:min(72svh,660px);display:flex;flex-direction:column;overflow:hidden}
#favModal .fav-body{padding:26px 22px 14px;display:flex;flex-direction:column;min-height:0;flex:1}
#favModal .fav-body h2{margin:8px 0 4px;font-size:30px}
.fav-sub{color:#a79e8e;font-size:13px;margin-bottom:6px;min-height:18px}
.fav-list{list-style:none;overflow-y:auto;margin:6px -6px 0;padding:2px 6px 18px;min-height:0}
.fav-row{display:flex;align-items:center;gap:12px;padding:10px 6px;border-top:1px solid rgba(237,230,214,.14)}
.fav-go{flex:1;min-width:0;display:flex;align-items:center;gap:12px;border:0;background:none;cursor:pointer;text-align:left;padding:4px;color:inherit;border-radius:10px}
.fav-thumb{width:60px;height:88px;border-radius:8px;flex:0 0 auto;overflow:hidden;background:#2e2826;position:relative}
.fav-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.fav-meta{min-width:0}
.fav-meta strong{display:block;font-size:14.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fav-meta span{display:block;font-size:12px;color:#a79e8e;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fav-rm{width:36px;height:36px;flex:0 0 auto;border-radius:50%;border:1px solid rgba(237,230,214,.14);background:transparent;color:#a79e8e;font-size:16px;cursor:pointer}
.fav-rm:hover{color:#ede6d6;border-color:#a79e8e}
.fav-empty{padding:34px 16px 40px;text-align:center;color:#a79e8e;font-size:14.5px;line-height:1.6}
.fav-empty .big{font-size:34px;display:block;margin-bottom:10px;color:#8d8478}
@media(min-width:641px){#favModal{place-items:end end}}
@media(max-width:640px){
  #favModal{place-items:end center;padding:8px}
  #favModal .modal-card.fav-panel{width:100%;max-height:74svh;border-radius:20px 20px 0 0}
  #pvCoach{right:96px;max-width:200px}
  #pvFolder{right:16px}
}
  </style>
  <link rel="stylesheet" href="account.5218d73e.css">
  <link rel="stylesheet" href="hero-bleed.7071cd6f.css">
  <link rel="stylesheet" href="shared/drag-drop/drag-drop.css">
  <link rel="stylesheet" href="section-reorder.css">
  <link rel="stylesheet" href="shared/nudges/nudges.css">
<link rel="stylesheet" href="free.a9d65ea2.css">
<link rel="stylesheet" href="batch.5215ea05.css">
<link rel="stylesheet" href="pod-episode.4924aeb4.css">
<link rel="stylesheet" href="podcast-player.css">
<link rel="stylesheet" href="tour.0fce7b69.css">
<link rel="stylesheet" href="shared/drag-drop/drag-drop.css">
<link rel="stylesheet" href="sb-banner.css">
<link rel="stylesheet" href="spotlight.css">
</head>
<body class="bleed-home">
  <a class="skip-link" href="#mainContent">Skip to content</a>
  <header class="topbar">
    <div class="top-left"><button class="wordmark" data-go="home" aria-label="Previously — home"><svg class="wm-glyph" width="26" height="18" viewBox="0 0 48 32" fill="none" aria-hidden="true"><path d="M21 5 L8 16 L21 27" stroke="#E8321E" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/><path d="M39 5 L26 16 L39 27" stroke="#E8321E" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/></svg><span>Previously</span></button>
    <nav class="primary-nav" aria-label="Primary navigation"><button class="nav-btn active" data-view="home" aria-current="page">Home</button><button class="nav-btn" data-view="browse">Browse</button><a class="nav-btn" href="/culture/">Culture</a><a class="nav-btn" href="/coming-soon">Coming Soon</a><button class="nav-btn" data-view="library">Library</button><button class="nav-btn" data-view="podcasts">Podcasts</button><a class="nav-btn" href="/sports/">Sports</a><button class="nav-btn" data-view="free">Free</button><a class="nav-btn" href="/live/"><span class="spa-live-dot" hidden></span>Live</a></nav></div>
    <div class="top-actions"><button class="theme-toggle" id="themeToggle" aria-label="Switch to light theme" aria-pressed="false" title="Toggle light / dark theme"><svg class="ic-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg><svg class="ic-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg></button><button class="icon-btn" id="inboxBtn" aria-label="Tonight's inbox — shows you follow that air tonight"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.7 21a2 2 0 0 1-3.4 0"/></svg><span class="inbox-badge" id="inboxBadge" hidden></span></button><button class="icon-btn" data-go="browse" aria-label="Search the catalog"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-4-4"/></svg></button><button class="ghost-btn" id="signinBtn" type="button">Sign in</button><button class="avatar-btn" id="avatarBtn" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="Account menu — sign in"><span class="avatar-circle" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 3.6-6.5 8-6.5s8 2.5 8 6.5"/></svg></span></button><div class="acct-menu" id="acctMenu" role="menu" aria-label="Account" hidden></div></div>
  </header>

  <main id="mainContent">
    <section class="view active page" id="view-home" aria-label="Home">
      <section class="hero hero-loading" aria-labelledby="heroTitle">
        <figure class="hero-slide hero-skel"><picture></picture><div class="hero-skel-shimmer" aria-hidden="true"></div></figure>
        <figure class="hero-slide hero-skel"><picture></picture><div class="hero-skel-shimmer" aria-hidden="true"></div></figure>
        <figure class="hero-slide hero-skel"><picture></picture><div class="hero-skel-shimmer" aria-hidden="true"></div></figure>
        <div class="hero-copy">
          <div class="eyebrow" id="heroEyebrow">Tonight's lineup</div>
          <h1 id="heroTitle"><span class="sr-only">Loading tonight's featured titles.</span><span class="skel-bar" style="width:min(520px,72%)" aria-hidden="true"></span><span class="skel-bar" style="width:min(340px,48%)" aria-hidden="true"></span></h1>
          <p id="heroText"><span class="skel-bar" style="width:min(560px,94%)" aria-hidden="true"></span><span class="skel-bar" style="width:min(400px,66%)" aria-hidden="true"></span></p>
          <div class="hero-actions"><button class="cta" id="heroDetails">View details</button><button class="cta secondary" data-go="browse">Browse everything</button></div>
        </div>
        <div class="hero-controls" aria-label="Featured title controls"><div class="hero-pager"><button class="hero-dot active" data-hero="0" aria-label="Show feature 1" aria-pressed="true"></button><button class="hero-dot" data-hero="1" aria-label="Show feature 2" aria-pressed="false"></button><button class="hero-dot" data-hero="2" aria-label="Show feature 3" aria-pressed="false"></button></div><button class="round-btn trailer-btn is-muted" id="heroMute" aria-label="Unmute trailer" hidden><svg class="ic-unmuted" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11 5 6 9H3v6h3l5 4z"/><path d="M15.5 8.5a5 5 0 0 1 0 7"/><path d="M18.4 5.6a9 9 0 0 1 0 12.8"/></svg><svg class="ic-muted" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11 5 6 9H3v6h3l5 4z"/><line x1="16" y1="9" x2="22" y2="15"/><line x1="22" y1="9" x2="16" y2="15"/></svg></button><button class="round-btn trailer-btn" id="heroFull" aria-label="Watch trailer fullscreen" hidden><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"/></svg></button></div>
      </section>

      <div class="shell">
        <section class="section reveal" aria-labelledby="top10-tv-title"><div class="section-head"><div><div class="eyebrow" id="top10-tv-eyebrow">Top 10 · TV</div><h2 id="top10-tv-title">Top 10 TV Shows.</h2><p>The series everyone's watching right now.</p><p class="top10-fresh" id="top10TvFresh" aria-live="polite"></p></div><button class="text-link" data-go="browse" data-filter="series">See all series →</button></div><div class="top10-rail rail" id="top10TvRail" role="list" aria-label="Top 10 TV Shows" tabindex="0"></div></section>
        <section class="section reveal" aria-labelledby="top10-movie-title"><div class="section-head"><div><div class="eyebrow" id="top10-movie-eyebrow">Top 10 · Movies</div><h2 id="top10-movie-title">Top 10 Movies.</h2><p>The films everyone's watching right now.</p><p class="top10-fresh" id="top10MovieFresh" aria-live="polite"></p></div><button class="text-link" data-go="browse" data-filter="movie">See all movies →</button></div><div class="top10-rail rail" id="top10MovieRail" role="list" aria-label="Top 10 Movies" tabindex="0"></div></section>
        <section class="section reveal" aria-labelledby="lineup-title"><div class="section-head"><div><div class="eyebrow" id="scheduleEyebrow">Tonight's Pacific schedule</div><h2 id="lineup-title">Tonight, in order.</h2><p>Every episode, its airtime, and what's on next — in one place. <span class="freshness" id="scheduleFresh"></span></p></div><button class="text-link" data-go="browse">Browse the full catalog →</button></div><div class="timeline-empty" id="timelineEmpty" hidden></div><div class="timeline" id="timeline"><div class="now-marker" id="nowMarker" aria-hidden="true"><span class="dot"></span><span class="line"></span><span class="pill" id="nowPill">NOW</span></div><div class="tl-hours" id="timelineHours" aria-live="polite"></div></div><div class="timeline-foot"><button class="cta secondary schedule-toggle" id="scheduleToggle" type="button"></button></div><div class="earlier" id="streamStrip" hidden><h4>Also streaming tonight</h4><div class="earlier-grid" id="streamGrid"></div></div><div class="earlier" id="earlierStrip" hidden><h4>Earlier today</h4><div class="earlier-grid" id="earlierGrid"></div></div><p class="timeline-note">Times shown in Pacific. Schedules change — check the network for the final word.</p></section>

        <section class="section reveal" id="tonightForYouSection" aria-labelledby="tfy-title" hidden><div class="section-head"><div><div class="eyebrow">Picked for you</div><h2 id="tfy-title">Tonight for you.</h2><p>From the shows you've starred.</p></div><button class="text-link" data-go="library">Manage your library →</button></div><div class="rail" id="tonightForYou"></div></section>

        <aside class="ad-slot ad-leaderboard reveal" aria-label="Advertisement"><span class="ad-label">Ad</span><div class="ad-unit"><div class="ad-copy"><strong>Track your shows anywhere.</strong><span>Follow your shows and keep your watchlist synced.</span></div><button class="cta compact" data-beta-open type="button">Join the open beta</button></div></aside>

        <section class="brand-band reveal" aria-labelledby="brand-band-title"><h2 id="brand-band-title">Never miss the story.</h2><div class="brand-props"><p class="brand-prop">Tonight's lineup, in order.</p><p class="brand-prop">Every title, one search.</p><p class="brand-prop">Your library follows you anywhere.</p></div><button class="cta" data-beta-open type="button">Join the open beta</button></section>

        <section class="section reveal" id="recentSection" aria-labelledby="recent-title" hidden><div class="section-head"><div><div class="eyebrow">Keep watching</div><h2 id="recent-title">Recently viewed.</h2><p>Pick up where you left off.</p></div><button class="text-link" id="clearRecent">Clear</button></div><div class="rail" id="recentRail"></div></section>

        <section class="section reveal" aria-labelledby="spot-title"><article class="spotlight"><div class="spotlight-copy"><div class="eyebrow">New season</div><h2 id="spot-title">MobLand<em>returns.</em></h2><p>Family power and shifting loyalties in a new season of the crime drama — new episodes Fridays on Paramount+.</p><button class="cta" data-show="mobland">View details</button></div><div class="spotlight-media"><picture><source type="image/webp" srcset="assets/artwork/mobland-800.webp 800w, assets/artwork/mobland.webp 1104w" sizes="(max-width:600px) 100vw, 45vw"><img src="assets/artwork/mobland.jpg" alt="MobLand key art" loading="lazy" decoding="async"></picture></div></article></section>

        <section class="section reveal" aria-labelledby="more-title"><div class="section-head"><div><div class="eyebrow">More titles</div><h2 id="more-title">What to watch next.</h2><p>More series for tonight and beyond.</p></div></div><div class="more-layout"><div class="wide-grid" id="wideGrid"></div><aside class="ad-slot ad-rail" aria-label="Advertisement"><span class="ad-label">Ad</span><div class="ad-unit"><div class="ad-copy"><strong>Never miss a premiere.</strong><span>The Previously app tracks air dates for every show you follow.</span></div><button class="cta compact" data-beta-open type="button">Join the open beta</button></div></aside></div></section>
      </div>
    </section>

    <section class="view page browse" id="view-browse" aria-label="Browse">
      <div class="shell"><div class="browse-head"><div><div class="eyebrow">Explore titles</div><h2>Find something to watch.</h2><p>Search every show and movie on Previously. <span class="rank-note">Ranked for viewers, never for advertisers — <button class="text-link" data-go="how-we-rank">how we rank</button>.</span></p></div><label class="search-wrap"><span class="sr-only">Search titles</span><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-4-4"/></svg><input id="catalogSearch" type="search" placeholder="Search by title or genre" autocomplete="off"></label></div><div class="filter-row genre-slider" id="browseFilterRow" aria-label="Filter catalog"><button class="chip active" data-genre="all" aria-pressed="true">All</button><button class="chip" data-genre="favorites" aria-pressed="false">★ Favorites</button><button class="chip" data-genre="series" aria-pressed="false">TV series</button><button class="chip" data-genre="movie" aria-pressed="false">Movies</button><span class="genre-pills" id="genrePills"></span></div><div class="catalog" id="catalog"></div><div class="browse-more"><button class="cta secondary" id="showMore" type="button" hidden>Show more</button></div><div class="empty" id="emptyState"><strong>No titles found.</strong><br>Try another name or clear the active filter.<br><button class="cta secondary compact" id="emptyClear" type="button">Clear search</button></div></div>
    </section>

    
    <section class="view page" id="view-free" aria-label="Free on YouTube">
      <div class="shell">
        <div class="free-head">
          <h2 class="free-h1">Free on YouTube <span class="free-count" id="freeCount" aria-live="polite">67 titles</span></h2>
          <p class="free-sub">Tap any title — it plays right here.</p>
        </div>
        <div class="free-toolbar">
          <div class="filter-row" id="freeFilterRow" role="group" aria-label="Filter free titles">
            <button class="chip active" type="button" data-ffilter="all" aria-pressed="true">All</button>
            <button class="chip" type="button" data-ffilter="movies" aria-pressed="false">Movies</button>
            <button class="chip" type="button" data-ffilter="series" aria-pressed="false">Series</button>
            <button class="chip" type="button" data-ffilter="sports" aria-pressed="false" aria-label="Sports — 24 titles">Sports <span class="chip-count">24</span></button>
          </div>
          <div class="free-tools">
            <label class="free-search-wrap"><span class="sr-only">Search free titles</span><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-4-4"/></svg><input id="freeSearch" type="search" placeholder="Search free titles" autocomplete="off"></label>
            <label class="free-sort-wrap"><span class="sr-only">Sort free titles</span><select id="freeSort" class="free-sort" aria-label="Sort free titles"><option value="featured" selected>Featured order</option><option value="az">Title: A to Z</option><option value="za">Title: Z to A</option><option value="recent">Recently verified</option></select></label>
          </div>
        </div>
        <div class="free-grid" id="freeGrid" role="list" aria-label="Free movies on YouTube">
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="EC6fDAq3cBk" aria-label="Summoned — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/EC6fDAq3cBk/maxresdefault.jpg" data-yt="EC6fDAq3cBk" alt="Summoned artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="EC6fDAq3cBk" aria-label="Details for Summoned"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="EC6fDAq3cBk">Summoned</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="AInJiXswLm4" aria-label="Twin Betrayal — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/AInJiXswLm4/maxresdefault.jpg" data-yt="AInJiXswLm4" alt="Twin Betrayal artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="AInJiXswLm4" aria-label="Details for Twin Betrayal"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="AInJiXswLm4">Twin Betrayal</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="DiVWMrFv-r0" aria-label="Free, Dead or Alive — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/DiVWMrFv-r0/maxresdefault.jpg" data-yt="DiVWMrFv-r0" alt="Free, Dead or Alive artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="DiVWMrFv-r0" aria-label="Details for Free, Dead or Alive"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="DiVWMrFv-r0">Free, Dead or Alive</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="jIWd_5INdDA" aria-label="Below Zero — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/jIWd_5INdDA/maxresdefault.jpg" data-yt="jIWd_5INdDA" alt="Below Zero artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="jIWd_5INdDA" aria-label="Details for Below Zero"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="jIWd_5INdDA">Below Zero</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="WWe6c6HFY8E" aria-label="3.3 Miles — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/WWe6c6HFY8E/maxresdefault.jpg" data-yt="WWe6c6HFY8E" alt="3.3 Miles artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="WWe6c6HFY8E" aria-label="Details for 3.3 Miles"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="WWe6c6HFY8E">3.3 Miles</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="JOUyUh--A7c" aria-label="The Attic Door — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/JOUyUh--A7c/maxresdefault.jpg" data-yt="JOUyUh--A7c" alt="The Attic Door artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="JOUyUh--A7c" aria-label="Details for The Attic Door"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="JOUyUh--A7c">The Attic Door</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="gsoBBiUv2Yo" aria-label="The Elite — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/gsoBBiUv2Yo/maxresdefault.jpg" data-yt="gsoBBiUv2Yo" alt="The Elite artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="gsoBBiUv2Yo" aria-label="Details for The Elite"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="gsoBBiUv2Yo">The Elite</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="NMZP2URG1oU" aria-label="The Infernal Idol — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/NMZP2URG1oU/maxresdefault.jpg" data-yt="NMZP2URG1oU" alt="The Infernal Idol artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="NMZP2URG1oU" aria-label="Details for The Infernal Idol"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="NMZP2URG1oU">The Infernal Idol</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="GJytAtSuEew" aria-label="The Santa Trap — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/GJytAtSuEew/maxresdefault.jpg" data-yt="GJytAtSuEew" alt="The Santa Trap artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="GJytAtSuEew" aria-label="Details for The Santa Trap"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="GJytAtSuEew">The Santa Trap</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="XtiAyWDoY3E" aria-label="All We Had — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/XtiAyWDoY3E/maxresdefault.jpg" data-yt="XtiAyWDoY3E" alt="All We Had artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="XtiAyWDoY3E" aria-label="Details for All We Had"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="XtiAyWDoY3E">All We Had</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="wiCI67BGjlk" aria-label="Trace — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/wiCI67BGjlk/maxresdefault.jpg" data-yt="wiCI67BGjlk" alt="Trace artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="wiCI67BGjlk" aria-label="Details for Trace"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="wiCI67BGjlk">Trace</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="K7sw5CR4nSI" aria-label="Jabberjaw — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/K7sw5CR4nSI/maxresdefault.jpg" data-yt="K7sw5CR4nSI" alt="Jabberjaw artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="K7sw5CR4nSI" aria-label="Details for Jabberjaw"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="K7sw5CR4nSI">Jabberjaw</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="VnjDjpyyfBc" aria-label="Delivered — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/VnjDjpyyfBc/maxresdefault.jpg" data-yt="VnjDjpyyfBc" alt="Delivered artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="VnjDjpyyfBc" aria-label="Details for Delivered"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="VnjDjpyyfBc">Delivered</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="0y2mF957R2w" aria-label="Class Dismissed — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/0y2mF957R2w/maxresdefault.jpg" data-yt="0y2mF957R2w" alt="Class Dismissed artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="0y2mF957R2w" aria-label="Details for Class Dismissed"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="0y2mF957R2w">Class Dismissed</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="-9se9dkUD24" aria-label="Never Too Far Away — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/-9se9dkUD24/maxresdefault.jpg" data-yt="-9se9dkUD24" alt="Never Too Far Away artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="-9se9dkUD24" aria-label="Details for Never Too Far Away"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="-9se9dkUD24">Never Too Far Away</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="znq6DGDOTb4" aria-label="Robbin&#x27; In Da Hood — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/znq6DGDOTb4/maxresdefault.jpg" data-yt="znq6DGDOTb4" alt="Robbin&#x27; In Da Hood artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="znq6DGDOTb4" aria-label="Details for Robbin&#x27; In Da Hood"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="znq6DGDOTb4">Robbin&#x27; In Da Hood</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="-zsGAV9Lx7I" aria-label="Sustenance — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/-zsGAV9Lx7I/maxresdefault.jpg" data-yt="-zsGAV9Lx7I" alt="Sustenance artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="-zsGAV9Lx7I" aria-label="Details for Sustenance"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="-zsGAV9Lx7I">Sustenance</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="jXPzwt9auSs" aria-label="Among Thieves — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/jXPzwt9auSs/maxresdefault.jpg" data-yt="jXPzwt9auSs" alt="Among Thieves artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="jXPzwt9auSs" aria-label="Details for Among Thieves"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="jXPzwt9auSs">Among Thieves</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="vygV_Gb5NDM" aria-label="A Deadly Legend — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/vygV_Gb5NDM/maxresdefault.jpg" data-yt="vygV_Gb5NDM" alt="A Deadly Legend artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="vygV_Gb5NDM" aria-label="Details for A Deadly Legend"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="vygV_Gb5NDM">A Deadly Legend</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="xcerEavrZhs" aria-label="Black Web — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/xcerEavrZhs/maxresdefault.jpg" data-yt="xcerEavrZhs" alt="Black Web artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="xcerEavrZhs" aria-label="Details for Black Web"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="xcerEavrZhs">Black Web</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="XkosfmWQF5Y" aria-label="Beliath — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/XkosfmWQF5Y/maxresdefault.jpg" data-yt="XkosfmWQF5Y" alt="Beliath artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="XkosfmWQF5Y" aria-label="Details for Beliath"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="XkosfmWQF5Y">Beliath</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="dvWzw49MCw4" aria-label="The Death of April — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/dvWzw49MCw4/maxresdefault.jpg" data-yt="dvWzw49MCw4" alt="The Death of April artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="dvWzw49MCw4" aria-label="Details for The Death of April"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="dvWzw49MCw4">The Death of April</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="Ut86prMsjgU" aria-label="Last Radio Call — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/Ut86prMsjgU/maxresdefault.jpg" data-yt="Ut86prMsjgU" alt="Last Radio Call artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="Ut86prMsjgU" aria-label="Details for Last Radio Call"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="Ut86prMsjgU">Last Radio Call</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="HEJXIYC1520" aria-label="The Woods — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/HEJXIYC1520/maxresdefault.jpg" data-yt="HEJXIYC1520" alt="The Woods artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="HEJXIYC1520" aria-label="Details for The Woods"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="HEJXIYC1520">The Woods</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="goZIHfvzaN0" aria-label="Night Terror — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/goZIHfvzaN0/maxresdefault.jpg" data-yt="goZIHfvzaN0" alt="Night Terror artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="goZIHfvzaN0" aria-label="Details for Night Terror"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="goZIHfvzaN0">Night Terror</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="yxDPnbnlX1E" aria-label="Patient Seven — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/yxDPnbnlX1E/maxresdefault.jpg" data-yt="yxDPnbnlX1E" alt="Patient Seven artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="yxDPnbnlX1E" aria-label="Details for Patient Seven"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="yxDPnbnlX1E">Patient Seven</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="cNV2ipgsv2s" aria-label="The Devil&#x27;s Work — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/cNV2ipgsv2s/maxresdefault.jpg" data-yt="cNV2ipgsv2s" alt="The Devil&#x27;s Work artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="cNV2ipgsv2s" aria-label="Details for The Devil&#x27;s Work"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="cNV2ipgsv2s">The Devil&#x27;s Work</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="89aYPBmzZOM" aria-label="Intrusive — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/89aYPBmzZOM/maxresdefault.jpg" data-yt="89aYPBmzZOM" alt="Intrusive artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="89aYPBmzZOM" aria-label="Details for Intrusive"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="89aYPBmzZOM">Intrusive</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="7h_ffrT8q40" aria-label="The Bleeding Game — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/7h_ffrT8q40/maxresdefault.jpg" data-yt="7h_ffrT8q40" alt="The Bleeding Game artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="7h_ffrT8q40" aria-label="Details for The Bleeding Game"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="7h_ffrT8q40">The Bleeding Game</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="sS6wJEDkjIY" aria-label="House Sitter — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/sS6wJEDkjIY/maxresdefault.jpg" data-yt="sS6wJEDkjIY" alt="House Sitter artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="sS6wJEDkjIY" aria-label="Details for House Sitter"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="sS6wJEDkjIY">House Sitter</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="Nx5NEb9QJ7g" aria-label="Tape Me — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/Nx5NEb9QJ7g/maxresdefault.jpg" data-yt="Nx5NEb9QJ7g" alt="Tape Me artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="Nx5NEb9QJ7g" aria-label="Details for Tape Me"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="Nx5NEb9QJ7g">Tape Me</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="6atSeI_1K9Q" aria-label="Split Screen — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/6atSeI_1K9Q/maxresdefault.jpg" data-yt="6atSeI_1K9Q" alt="Split Screen artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="6atSeI_1K9Q" aria-label="Details for Split Screen"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="6atSeI_1K9Q">Split Screen</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="HrtfmwW8EZo" aria-label="Cold Moon — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/HrtfmwW8EZo/maxresdefault.jpg" data-yt="HrtfmwW8EZo" alt="Cold Moon artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="HrtfmwW8EZo" aria-label="Details for Cold Moon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="HrtfmwW8EZo">Cold Moon</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="-fyASTDtFyI" aria-label="The Lifeguard — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/-fyASTDtFyI/maxresdefault.jpg" data-yt="-fyASTDtFyI" alt="The Lifeguard artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="-fyASTDtFyI" aria-label="Details for The Lifeguard"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="-fyASTDtFyI">The Lifeguard</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="iiBk6wleCjI" aria-label="Personal Effects — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/iiBk6wleCjI/maxresdefault.jpg" data-yt="iiBk6wleCjI" alt="Personal Effects artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="iiBk6wleCjI" aria-label="Details for Personal Effects"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="iiBk6wleCjI">Personal Effects</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="Z6y-61JKLZk" aria-label="A Wing and a Prayer — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/Z6y-61JKLZk/maxresdefault.jpg" data-yt="Z6y-61JKLZk" alt="A Wing and a Prayer artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="Z6y-61JKLZk" aria-label="Details for A Wing and a Prayer"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="Z6y-61JKLZk">A Wing and a Prayer</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="nhX-JhXTzL8" aria-label="A Stand Up Guy — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/nhX-JhXTzL8/maxresdefault.jpg" data-yt="nhX-JhXTzL8" alt="A Stand Up Guy artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="nhX-JhXTzL8" aria-label="Details for A Stand Up Guy"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="nhX-JhXTzL8">A Stand Up Guy</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="ImNmTjLAsG8" aria-label="Party Girl — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/ImNmTjLAsG8/maxresdefault.jpg" data-yt="ImNmTjLAsG8" alt="Party Girl artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="ImNmTjLAsG8" aria-label="Details for Party Girl"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="ImNmTjLAsG8">Party Girl</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="fod42CfDmhY" aria-label="Adventures in Dinotopia — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/fod42CfDmhY/maxresdefault.jpg" data-yt="fod42CfDmhY" alt="Adventures in Dinotopia artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="fod42CfDmhY" aria-label="Details for Adventures in Dinotopia"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="fod42CfDmhY">Adventures in Dinotopia</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="_zQ6nb50x-U" aria-label="Submergence — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/_zQ6nb50x-U/maxresdefault.jpg" data-yt="_zQ6nb50x-U" alt="Submergence artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="_zQ6nb50x-U" aria-label="Details for Submergence"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="_zQ6nb50x-U">Submergence</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="CAkDSrMUk-8" aria-label="Glisten And The Merry Mission — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/CAkDSrMUk-8/maxresdefault.jpg" data-yt="CAkDSrMUk-8" alt="Glisten And The Merry Mission artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="CAkDSrMUk-8" aria-label="Details for Glisten And The Merry Mission"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="CAkDSrMUk-8">Glisten And The Merry Mission</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="MycT5SH3iBE" aria-label="Our Nixon — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/MycT5SH3iBE/maxresdefault.jpg" data-yt="MycT5SH3iBE" alt="Our Nixon artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="MycT5SH3iBE" aria-label="Details for Our Nixon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="MycT5SH3iBE">Our Nixon</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="2mcwvyAausg" aria-label="The Identical — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/2mcwvyAausg/maxresdefault.jpg" data-yt="2mcwvyAausg" alt="The Identical artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="2mcwvyAausg" aria-label="Details for The Identical"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="2mcwvyAausg">The Identical</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="2PLeS7Oglho" aria-label="Biker Fox — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/2PLeS7Oglho/maxresdefault.jpg" data-yt="2PLeS7Oglho" alt="Biker Fox artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="2PLeS7Oglho" aria-label="Details for Biker Fox"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="2PLeS7Oglho">Biker Fox</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="iK2bm--GFOE" aria-label="Chop Kick Panda — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/iK2bm--GFOE/maxresdefault.jpg" data-yt="iK2bm--GFOE" alt="Chop Kick Panda artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="iK2bm--GFOE" aria-label="Details for Chop Kick Panda"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="iK2bm--GFOE">Chop Kick Panda</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="9bsYHvQAGno" aria-label="The Forest — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/9bsYHvQAGno/maxresdefault.jpg" data-yt="9bsYHvQAGno" alt="The Forest artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="9bsYHvQAGno" aria-label="Details for The Forest"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="9bsYHvQAGno">The Forest</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="R-b679J9Uo8" aria-label="The Trump Prophecy — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/R-b679J9Uo8/maxresdefault.jpg" data-yt="R-b679J9Uo8" alt="The Trump Prophecy artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="R-b679J9Uo8" aria-label="Details for The Trump Prophecy"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="R-b679J9Uo8">The Trump Prophecy</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="w4U03PYsZag" aria-label="The Depths — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/w4U03PYsZag/maxresdefault.jpg" data-yt="w4U03PYsZag" alt="The Depths artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="w4U03PYsZag" aria-label="Details for The Depths"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="w4U03PYsZag">The Depths</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="xKQbBya-5oY" aria-label="Assimilate — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/xKQbBya-5oY/maxresdefault.jpg" data-yt="xKQbBya-5oY" alt="Assimilate artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="xKQbBya-5oY" aria-label="Details for Assimilate"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="xKQbBya-5oY">Assimilate</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="ELs7RnlwoT4" aria-label="Operation Seawolf — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/ELs7RnlwoT4/maxresdefault.jpg" data-yt="ELs7RnlwoT4" alt="Operation Seawolf artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="ELs7RnlwoT4" aria-label="Details for Operation Seawolf"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="ELs7RnlwoT4">Operation Seawolf</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="AOrjMrkl9DU" aria-label="Assault On Precinct 13 — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/AOrjMrkl9DU/maxresdefault.jpg" data-yt="AOrjMrkl9DU" alt="Assault On Precinct 13 artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="AOrjMrkl9DU" aria-label="Details for Assault On Precinct 13"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="AOrjMrkl9DU">Assault On Precinct 13</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="6dEkg99F9oY" aria-label="MosquitoMan — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/6dEkg99F9oY/maxresdefault.jpg" data-yt="6dEkg99F9oY" alt="MosquitoMan artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="6dEkg99F9oY" aria-label="Details for MosquitoMan"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="6dEkg99F9oY">MosquitoMan</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="SgMiwsuc688" aria-label="Butterfly Kisses — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/SgMiwsuc688/maxresdefault.jpg" data-yt="SgMiwsuc688" alt="Butterfly Kisses artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="SgMiwsuc688" aria-label="Details for Butterfly Kisses"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="SgMiwsuc688">Butterfly Kisses</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="2P1SmArs71o" aria-label="The Slaughterhouse Killer — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/2P1SmArs71o/maxresdefault.jpg" data-yt="2P1SmArs71o" alt="The Slaughterhouse Killer artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="2P1SmArs71o" aria-label="Details for The Slaughterhouse Killer"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="2P1SmArs71o">The Slaughterhouse Killer</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="E9PJYY_Arn8" aria-label="Steel — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/E9PJYY_Arn8/maxresdefault.jpg" data-yt="E9PJYY_Arn8" alt="Steel artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="E9PJYY_Arn8" aria-label="Details for Steel"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="E9PJYY_Arn8">Steel</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="yzz9rG27A7o" aria-label="Tooth Fairy: The Root of Evil — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/yzz9rG27A7o/maxresdefault.jpg" data-yt="yzz9rG27A7o" alt="Tooth Fairy: The Root of Evil artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="yzz9rG27A7o" aria-label="Details for Tooth Fairy: The Root of Evil"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="yzz9rG27A7o">Tooth Fairy: The Root of Evil</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="l-YD3bLss40" aria-label="White Rush — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/l-YD3bLss40/maxresdefault.jpg" data-yt="l-YD3bLss40" alt="White Rush artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="l-YD3bLss40" aria-label="Details for White Rush"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="l-YD3bLss40">White Rush</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="agWEShQi1rk" aria-label="Midnight in Phoenix — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/agWEShQi1rk/maxresdefault.jpg" data-yt="agWEShQi1rk" alt="Midnight in Phoenix artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="agWEShQi1rk" aria-label="Details for Midnight in Phoenix"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="agWEShQi1rk">Midnight in Phoenix</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="BsMBUqMtiew" aria-label="The House on Hill Street — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/BsMBUqMtiew/maxresdefault.jpg" data-yt="BsMBUqMtiew" alt="The House on Hill Street artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="BsMBUqMtiew" aria-label="Details for The House on Hill Street"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="BsMBUqMtiew">The House on Hill Street</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="bMXEcbmkr9w" aria-label="Amy&#x27;s F It List — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/bMXEcbmkr9w/maxresdefault.jpg" data-yt="bMXEcbmkr9w" alt="Amy&#x27;s F It List artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="bMXEcbmkr9w" aria-label="Details for Amy&#x27;s F It List"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="bMXEcbmkr9w">Amy&#x27;s F It List</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="k9KOkbWgAQs" aria-label="15 Days — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/k9KOkbWgAQs/maxresdefault.jpg" data-yt="k9KOkbWgAQs" alt="15 Days artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="k9KOkbWgAQs" aria-label="Details for 15 Days"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="k9KOkbWgAQs">15 Days</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="OM-JtDzrav4" aria-label="The Best of The Best Jazz From Detroit — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/OM-JtDzrav4/maxresdefault.jpg" data-yt="OM-JtDzrav4" alt="The Best of The Best Jazz From Detroit artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="OM-JtDzrav4" aria-label="Details for The Best of The Best Jazz From Detroit"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="OM-JtDzrav4">The Best of The Best Jazz From Detroit</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="E9kLZYyIJfQ" aria-label="All Things Must Pass — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/E9kLZYyIJfQ/maxresdefault.jpg" data-yt="E9kLZYyIJfQ" alt="All Things Must Pass artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="E9kLZYyIJfQ" aria-label="Details for All Things Must Pass"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="E9kLZYyIJfQ">All Things Must Pass</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="S_6fFIlJ9fk" aria-label="1 Mile To You — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/S_6fFIlJ9fk/maxresdefault.jpg" data-yt="S_6fFIlJ9fk" alt="1 Mile To You artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="S_6fFIlJ9fk" aria-label="Details for 1 Mile To You"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="S_6fFIlJ9fk">1 Mile To You</button></div>
<div class="free-card" role="listitem"><button class="free-tap" type="button" data-yt="NN5qR4DACEk" aria-label="The Sensitives — play free"><span class="free-art"><img src="https://i.ytimg.com/vi/NN5qR4DACEk/maxresdefault.jpg" data-yt="NN5qR4DACEk" alt="The Sensitives artwork" loading="lazy" decoding="async"><span class="free-ring" aria-hidden="true"><span class="free-dot"><span class="free-tri"></span></span></span></span></button><button class="free-info" type="button" data-yt="NN5qR4DACEk" aria-label="Details for The Sensitives"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5" stroke-linecap="round"/><circle cx="12" cy="7.6" r="1.2" fill="currentColor" stroke="none"/></svg></button><button class="free-title" type="button" data-yt="NN5qR4DACEk">The Sensitives</button></div>











































































































































































































        </div>
<div class="free-empty" id="freeEmpty" hidden>
          <strong>No titles found.</strong><br><span id="freeEmptyHint">Try another name or clear the active filter.</span><br>
          <button class="cta secondary compact" id="freeEmptyClear" type="button">Clear search &amp; filters</button>
        </div>
        <section class="hood-block" id="hoodBlock" aria-label="Hood films and series" hidden>
          <div class="section-head"><div><div class="eyebrow">The culture</div><h2>Hood classics &amp; street cinema</h2></div><button class="cta textual" id="hoodSeeAll" type="button">See all &rarr;</button></div>
          <div class="hood-rail" id="hoodRail" role="list"></div>
        </section>
        <section class="series-block" id="seriesBlock" aria-label="Free series">
          <div class="section-head"><div><div class="eyebrow">Full seasons, free</div><h2>Series on YouTube</h2></div></div>
          <div class="series-rail" id="seriesRail" role="list"></div>
        </section>
</div>
    </section>
<section class="view page" id="view-podcasts" aria-label="Podcasts">
      <div class="shell">
        <div class="pod-head">
          <div><div class="eyebrow">Video-first, official channels</div>
          <h2 class="pod-h1">Podcasts <span class="free-count" id="podCount" aria-live="polite">144 shows</span></h2>
          <p class="free-sub">The culture’s loudest mics — every show streams from its official YouTube channel.</p></div>
          <label class="free-search-wrap pod-search"><span class="sr-only">Search podcasts</span><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-4-4"/></svg><input id="podSearch" type="search" placeholder="Search shows, hosts, lanes" autocomplete="off"></label>
        </div>
                                    <!-- ============ STORY BOARD FEATURE BANNER ============ -->
    <section class="sb-banner" aria-label="Story Board — true crime story tracker">
      <div class="sb-art">
        <span class="sb-flag"><i></i>STORY TRACKER</span>
        <div class="sb-art-fallback" aria-hidden="true"><span class="glyph">&laquo;</span><span>Story Board</span></div>
        <div class="sb-blur" data-sb-blur></div>
        <img class="sb-main" src="https://i.ytimg.com/vi/oWufpDAlTEw/hqdefault.jpg" alt="The Twisted Murder of Rebecca Park — featured true-crime episode artwork" loading="lazy">
      </div>
      <div class="sb-copy">
        <div class="sb-kicker"><span class="glyph">&laquo;</span> Story Board</div>
        <h2>True crime, minus the confusion.</h2>
        <p>Story Board turns true-crime episodes into a <b>visual map</b> &mdash; who&rsquo;s who, every story beat in true order, and a live <b>YOU ARE HERE</b> marker that follows along as the episode plays.</p>
        <div class="sb-timeline" aria-hidden="true">
          <span class="t-dot done"></span><span class="t-line"></span><span class="t-dot done"></span><span class="t-line"></span><span class="t-here">YOU ARE HERE</span><span class="t-line"></span><span class="t-dot"></span><span class="t-line"></span><span class="t-dot"></span>
        </div>
        <div class="sb-meta"><span>4 episodes mapped</span><span aria-hidden="true">&middot;</span><span>People Are the Worst</span></div>
        <div class="sb-cta-row">
          <a class="sb-cta" href="/culture/story-board/">Open the Story Board</a>
        </div>
        <div class="sb-next">
          <h3>Also mapped</h3>
          <div class="sb-next-row"></div>
        </div>
      </div>
    </section>
    <!-- ============ /STORY BOARD ============ -->
<!-- ============ STORY OF THE DAY SPOTLIGHT ============
     Paste directly AFTER the /STORY BOARD banner close comment in #view-podcasts.
     Requires: spotlight.css (in <head>), spotlight.js (deferred, before </body>),
     and /spotlight.json at the site root. JS fills this section; the static
     child below is the no-JS / pre-hydration state — never blank. -->
<section class="sotd" data-spotlight aria-label="Story of the day">
  <div class="sotd-copy">
    <div class="sotd-kicker"><span class="bolt" aria-hidden="true">&#9889;</span><span class="k-label">Story of the day</span></div>
    <h2>Today's pick is loading.</h2>
    <p class="sotd-why">One story a day, picked by a human. The craziest true-crime story making the rounds.</p>
    <div class="sotd-cta-row"><a class="sotd-cta" href="/culture/story-board/">Open the Story Board</a></div>
  </div>
</section>
<!-- ============ /STORY OF THE DAY ============ -->
<section class="pod-feat" id="podFeatured" hidden aria-label="Featured podcasts">
          <div class="pod-feat-head"><h3>Featured today</h3><p class="pod-feat-sub">Fresh picks from the library</p></div>
          <div class="pod-feat-grid"></div>
        </section>
        <div class="filter-row pod-lanes" id="podLaneRow" role="group" aria-label="Podcast lanes"></div>
        <div class="pod-grid" id="podGrid" role="list" aria-label="Podcast shows"></div>
        <div class="pod-more"><button class="cta secondary" id="podShowMore" type="button" hidden>Show more</button></div>
        <div class="free-empty" id="podEmpty" hidden><strong>No shows found.</strong><br>Try another name or pick a different lane.<br><button class="cta secondary compact" id="podEmptyClear" type="button">Clear search</button></div>
      </div>
    </section>
<section class="view page library" id="view-library" aria-label="Library">
      <div class="shell"><div class="browse-head"><div><div class="eyebrow">Your library</div><h2>My stuff.</h2><p id="librarySub">Star any title and it lives here — saved on this device.</p></div><button class="cta compact" data-go="browse">Find shows to star</button><button class="cta compact secondary" id="libraryStarToggle" type="button">Hide floating ★</button></div>
      <div class="lib-unified rw" id="libUnified">
        <div class="lib-sec" id="libFavSec" aria-labelledby="libFavH">
          <div class="lib-sec-head"><div><div class="eyebrow">Your collection</div><h2 id="libFavH">Favorites.</h2><p class="lib-sec-sub" id="favSub">The shows and movies you've starred.</p></div><div class="fav-stats" id="favStats" aria-live="polite"></div></div>
          <div class="poster-grid fav-grid" id="favGrid" aria-label="Your favorites"></div>
          <div class="fav-list" id="favList" aria-label="Your favorites"></div>
          <div class="fav-empty" id="favEmpty" hidden></div>
          <p class="drag-hint" id="favDragHint" hidden><span class="dh-grip" aria-hidden="true">⠿</span><span id="favDragHintTxt">Drag cards to set your order — it saves automatically.</span></p>
        </div>
        <div class="lib-sec" id="libMusicSec" aria-labelledby="libMusicH">
          <div class="lib-sec-head"><div><div class="eyebrow">Your music</div><h2 id="libMusicH">Music.</h2><p class="lib-sec-sub" id="musicSub">Playlists, artists you follow, and what you've been playing.</p></div><div id="musicOpenWrap"></div></div>
          <div id="musicBody"></div>
        </div>
        <p class="lib-footnote">Continue watching and watchlist are on pause — everything you saved is safe and will return.</p>
      </div
      </div>
    </section>


    <section class="view page" id="view-account" aria-label="Account settings">
      <div class="shell"><div class="acct-wrap">
        <div class="browse-head acct-head"><div><div class="eyebrow">Account</div><h2>Settings.</h2><p>Your profile, your services, and how Previously treats you. Everything here saves to your account — nothing is guessed.</p></div></div>

        <div class="acct-sec" aria-labelledby="acctProfileH">
          <h2 id="acctProfileH">Profile</h2>
          <p class="acct-sec-sub">This is how you appear in your account. Your email never changes here — it's your sign-in.</p>
          <div class="profile-grid">
            <div>
              <div class="avatar-honor-wrap"><button class="avatar-edit" id="avatarEditBtn" type="button" aria-label="Change your avatar"><span id="avatarPreviewBox"></span></button></div>
              <input type="file" id="avatarFile" accept="image/*" hidden>
              <div class="avatar-actions"><button class="text-link" id="avatarRemove" type="button">Remove</button></div>
            </div>
            <div>
              <div class="field"><label for="acctDisplayName">Display name</label><input id="acctDisplayName" type="text" maxlength="60" autocomplete="nickname" placeholder="What should we call you?"></div>
              <div class="form-row acct-mt13">
                <div class="field"><label for="acctEmail">Email (sign-in)</label><input id="acctEmail" type="email" readonly tabindex="-1" aria-readonly="true"></div>
                <div class="field"><label for="acctTimezone">Timezone</label><select id="acctTimezone"></select></div>
              </div>
              <div class="form-actions acct-mt16"><button class="cta compact" id="acctSaveProfile" type="button">Save profile</button><span class="form-status" id="acctSaveStatus" role="status"></span></div>
            </div>
          </div>
          <p class="explicit-note">Avatars are only ever shown to you, on your own account. Keep it tasteful — no explicit, hateful, or harassing imagery. Images over 2&nbsp;MB are rejected.</p>
        </div>

        <div class="acct-sec acct-honors rw" id="acctHonors" aria-labelledby="acctHonorsH" hidden>
          <h2 id="acctHonorsH">Founder honors</h2>
          <p class="acct-sec-sub" id="acctHonorsSub">Yours alone &mdash; never earnable.</p>
          <div class="honor-row" id="honorRow"></div>
          <p class="honor-lock" id="acctHonorsLock">Locked to this account &mdash; permanently and exclusively yours. Never earnable by anyone else, never transferable.</p>
        </div>

        <div class="acct-sec" aria-labelledby="acctSvcH">
          <h2 id="acctSvcH">Streaming services</h2>
          <p class="acct-sec-sub">Tell us what you pay for. Where-to-watch results can stick to just these — anonymous visitors always see the full, unbiased list.</p>
          <div class="acct-row"><div class="grow"><b>Only show me what's on my services</b><p><span class="svc-note">When on, Where-to-watch hides everything you don't subscribe to. Applies only to your signed-in account.</span></p></div><label class="switch"><input type="checkbox" id="svcMaster"><span class="track" aria-hidden="true"></span><span class="sr-only">Only show me what's on my services</span></label></div>
          <div id="svcList">
            <div class="acct-row"><div class="grow"><b>Netflix</b></div><label class="switch"><input type="checkbox" id="svc-netflix"><span class="track" aria-hidden="true"></span><span class="sr-only">Netflix</span></label></div>
            <div class="acct-row"><div class="grow"><b>Max</b></div><label class="switch"><input type="checkbox" id="svc-max"><span class="track" aria-hidden="true"></span><span class="sr-only">Max</span></label></div>
            <div class="acct-row"><div class="grow"><b>Hulu</b></div><label class="switch"><input type="checkbox" id="svc-hulu"><span class="track" aria-hidden="true"></span><span class="sr-only">Hulu</span></label></div>
            <div class="acct-row"><div class="grow"><b>Disney+</b></div><label class="switch"><input type="checkbox" id="svc-disney"><span class="track" aria-hidden="true"></span><span class="sr-only">Disney plus</span></label></div>
            <div class="acct-row"><div class="grow"><b>Prime Video</b></div><label class="switch"><input type="checkbox" id="svc-prime"><span class="track" aria-hidden="true"></span><span class="sr-only">Prime Video</span></label></div>
            <div class="acct-row"><div class="grow"><b>Apple TV+</b></div><label class="switch"><input type="checkbox" id="svc-apple"><span class="track" aria-hidden="true"></span><span class="sr-only">Apple TV plus</span></label></div>
            <div class="acct-row"><div class="grow"><b>Paramount+</b></div><label class="switch"><input type="checkbox" id="svc-paramount"><span class="track" aria-hidden="true"></span><span class="sr-only">Paramount plus</span></label></div>
            <div class="acct-row"><div class="grow"><b>Peacock</b></div><label class="switch"><input type="checkbox" id="svc-peacock"><span class="track" aria-hidden="true"></span><span class="sr-only">Peacock</span></label></div>
          </div>
        </div>

        <div class="acct-sec" aria-labelledby="acctAppH">
          <h2 id="acctAppH">Appearance</h2>
          <p class="acct-sec-sub">Midnight noir is home. Pick your light.</p>
          <div class="segmented" id="acctAppearance" role="group" aria-label="Appearance">
            <button type="button" data-ap="dark" aria-pressed="true">Dark</button>
            <button type="button" data-ap="light" aria-pressed="false">Light</button>
            <button type="button" data-ap="device" aria-pressed="false">Device</button>
          </div>
        </div>

        <div class="acct-sec" aria-labelledby="acctNtfH">
          <h2 id="acctNtfH">Notifications</h2>
          <p class="acct-sec-sub">What Previously is allowed to nudge you about. Nothing here is on until you say so.</p>
          <div class="acct-row"><div class="grow"><b>New-episode alerts</b><p><span class="svc-note">Flag episodes from your starred shows in your inbox the day they air.</span></p></div><label class="switch"><input type="checkbox" id="ntfEpisodes"><span class="track" aria-hidden="true"></span><span class="sr-only">New-episode alerts</span></label></div>
          <div class="acct-row"><div class="grow"><b>Continue-watching nudges</b><p><span class="svc-note">A gentle reminder here in your library when a show you started has been sitting unwatched for over a week.</span></p></div><label class="switch"><input type="checkbox" id="ntfNudges"><span class="track" aria-hidden="true"></span><span class="sr-only">Continue-watching nudges</span></label></div>
        </div>

        <div class="acct-sec" id="acctWatchHist" aria-labelledby="acctWhH">
          <h2 id="acctWhH">Watch history</h2>
          <p class="acct-sec-sub">Your watched movies and shows — tracked here, or imported from Trakt in one tap. Read-only: Previously never changes anything on Trakt.</p>
          <div id="traktBox"><p class="trakt-muted">Loading…</p></div>
        </div>

        <div class="acct-sec" aria-labelledby="acctHelpH">
          <h2 id="acctHelpH">Help &amp; contact</h2>
          <p class="acct-sec-sub">Something broken, or just want to talk? A human reads every message.</p>
          <div class="acct-row"><div class="grow"><b>Email us</b><p><span class="svc-note"><a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="543631203514233520373c242631223d3b2127382d7a373b39">[email&#160;protected]</a> — we answer within a day or two.</span></p></div><a class="ghost-btn" href="/cdn-cgi/l/email-protection#91f3f4e5f0d1e6f0e5f2f9e1e3f4e7f8fee4e2fde8bff2fefcaee2e4f3fbf4f2e5acc1e3f4e7f8fee4e2fde8b4a3a1f0f2f2fee4ffe5b4a3a1f9f4fde1">Email us</a></div>
          <div class="acct-row"><div class="grow"><b>Sign out</b><p><span class="svc-note">Sign out on this device. Your library stays safe in your account.</span></p></div><button class="ghost-btn" id="acctSignOut" type="button">Sign out</button></div>
          <div class="acct-row"><div class="grow"><b>Replay quick tour</b><p><span class="svc-note">Take the 10-second tour again — welcome, drag-and-drop, done.</span></p></div><button class="ghost-btn" id="tourReplayBtn" type="button">Replay tour</button></div>
        </div>

        <div class="acct-sec danger-zone" aria-labelledby="acctDangerH">
          <h2 id="acctDangerH">Danger zone</h2>
          <p class="acct-sec-sub">No dark patterns here. Leaving deletes your profile, library, watch history, and preferences — permanently.</p>
          <button class="text-danger" id="deleteAccountLink" type="button">Delete my account</button>
          <div class="delete-confirm" id="deleteConfirm" hidden>
            <p><b>Delete your account for good?</b><br>This permanently removes your profile, library, watch history, and preferences from Previously. Your starred shows stay on this device only. This can't be undone.</p>
            <div class="del-actions">
              <button class="ghost-btn" id="deleteAccountYes" type="button">Yes, delete my account</button>
              <button class="text-link" id="deleteAccountNo" type="button">Keep my account</button>
            </div>
          </div>
        </div>

      </div></div>
    </section>

<section class="view page" id="view-terms" aria-label="Terms of Service">
      <div class="legal">
        <div class="legal-back"><button class="text-link" data-go="home">← Back to <span class="wordmark-inline">Previously</span></button></div>
        <div class="eyebrow">Legal</div>
        <h2>Terms of Service</h2>
        <p class="legal-meta">Effective September 23, 2026 · Previously · Las Vegas, Nevada<br>Questions about these terms: <a href="/cdn-cgi/l/email-protection#c5a7a0b1a485b2a4b1a6adb5b7a0b3acaab0b6a9bceba6aaa8"><span class="__cf_email__" data-cfemail="ea888f9e8baa9d8b9e89829a988f9c83859f998693c4898587">[email&#160;protected]</span></a></p>
        <div class="legal-body">
          <p>These terms cover your use of the Previously website at watchpreviously.com (the "Site"). If you don't agree with them, please don't use the Site.</p>
          <h2>1. What Previously is</h2>
          <p><strong>Previously is a discovery guide</strong> for TV shows and movies. We help you find what to watch and when it airs. That's it.</p>
          <ul>
            <li>We <strong>do not stream, host, or sell</strong> any shows or movies. When we point you to where something is available, that service's own terms and prices apply.</li>
            <li>Show and movie information — titles, artwork, air dates, release dates — comes from third-party data providers, mainly TMDB. It's the best data we have, but it can be wrong or out of date. <strong>Always double-check air times and availability with the actual network or streaming service before you plan your night around them.</strong></li>
            <li>Trailers play inside the Site through embedded YouTube players. Using them is also subject to YouTube's terms.</li>
          </ul>
          <h2>2. Who can use the Site</h2>
          <p>The Site is for people <strong>13 and older</strong>. It's a general-audience site — it's not made for children, and we don't knowingly collect information from anyone under 13. If you're under 13, please don't sign up for anything here.</p>
          <h2>3. The open beta</h2>
          <p>The Site is currently in <strong>open beta</strong> — it's live and improving, and some things may change or break while we polish them.</p>
          <ul>
            <li>Joining the beta means giving us your email address so we can tell you about the beta. The signup form says it plainly: <strong>"We'll only email you about the beta. Unsubscribe anytime."</strong> We mean that.</li>
            <li>The beta is free. Being in the beta doesn't give you any ownership in Previously or any promise about future features.</li>
          </ul>
          <h2>4. Email alerts and the newsletter (coming after launch)</h2>
          <p>After launch we plan to offer <strong>episode alerts</strong> ("your show airs tonight"), <strong>movie release alerts</strong>, and a weekly <strong>newsletter</strong>. These will be strictly opt-in: you choose which shows or topics to follow, every email has a one-click unsubscribe, and unsubscribing stops the emails immediately. The founder personally approves every newsletter before it goes out.</p>
          <h2>5. Acceptable use — the short version</h2>
          <p>Use the Site like a normal person. Don't:</p>
          <ul>
            <li>Scrape, bulk-copy, or re-publish our catalog pages or artwork as your own product.</li>
            <li>Try to break the Site, overload it, or get around any of its limits.</li>
            <li>Use the Site for anything illegal, or to harass anyone.</li>
            <li>Pretend to be us — don't copy our name, logo, or design to mislead people.</li>
          </ul>
          <p>If someone abuses the Site, we may block their access. We'll be reasonable about it.</p>
          <h2>6. Intellectual property</h2>
          <ul>
            <li>The Previously name, logo, wordmark, and the Site's design are ours. Don't use them without asking.</li>
            <li>Show and movie titles, posters, stills, and descriptions belong to their respective owners (studios, networks, distributors) and to our data providers. We display artwork under TMDB's terms, hotlinked from their image servers — we don't claim to own any of it.</li>
            <li>Nothing on the Site gives you ownership of anyone else's content. Browsing the catalog is fine; lifting the whole catalog to build a competing database is not.</li>
          </ul>
          <h2>7. Ads and recommendations</h2>
          <ul>
            <li>The Site shows ads, clearly labeled <strong>"Ad."</strong> Ads keep the lights on; they don't change what the catalog recommends.</li>
            <li>Later we may add affiliate links (links where we earn a small commission if you sign up for something) and clearly labeled sponsored features. When that happens, we'll say so right where the link appears. We never let advertisers buy a show's placement in the catalog or pretend an ad is an editorial pick.</li>
          </ul>
          <h2>8. Third-party services</h2>
          <p>Parts of the Site run on third-party services: TMDB (catalog data and artwork), YouTube (trailer playback), and later Resend (alert and newsletter email). The beta signup form posts to <strong>our own endpoint</strong> (a Cloudflare Worker writing to a database we control) — no third party processes your signup. Those services have their own terms and privacy policies, which apply to their part of the experience. We're responsible for our Site; they're responsible for theirs.</p>
          <h2>9. No warranties — the honest version</h2>
          <p>The Site is provided <strong>"as is."</strong> We work hard to keep the catalog accurate and the Site running, but we can't promise it's always complete, correct, or uninterrupted. Schedules change, data providers have outages, and we're a small team. To the extent the law allows, we disclaim warranties of merchantability, fitness for a particular purpose, and non-infringement.</p>
          <h2>10. Limitation of liability</h2>
          <p>To the fullest extent the law allows: if something about the Site causes you harm, our total liability is limited to <strong>the amount you paid us to use the Site — which is $0.</strong> We're not liable for indirect, incidental, or consequential damages (like missing a season premiere because an air date was wrong — check with the network). Nothing here limits liability where the law doesn't allow it to be limited.</p>
          <h2>11. Changes to these terms</h2>
          <p>We'll post updated terms here with a new effective date. If we make a material change, we'll note it on the Site, and if you're an email subscriber we'll tell you by email. Continuing to use the Site after the change means you accept the new terms.</p>
          <h2>12. Governing law</h2>
          <p>These terms are governed by the laws of the <strong>State of Nevada</strong>, without regard to conflict-of-law rules. Any dispute will be handled in the state or federal courts located in Clark County, Nevada. If any part of these terms is found unenforceable, the rest still stands.</p>
          <h2>13. Contact</h2>
          <p>Questions about these terms: <a href="/cdn-cgi/l/email-protection#c5a7a0b1a485b2a4b1a6adb5b7a0b3acaab0b6a9bceba6aaa8"><span class="__cf_email__" data-cfemail="b4d6d1c0d5f4c3d5c0d7dcc4c6d1c2dddbc1c7d8cd9ad7dbd9">[email&#160;protected]</span></a>.</p>
        </div>
      </div>
    </section>

    <section class="view page" id="view-privacy" aria-label="Privacy Policy">
      <div class="legal">
        <div class="legal-back"><button class="text-link" data-go="home">← Back to <span class="wordmark-inline">Previously</span></button></div>
        <div class="eyebrow">Legal</div>
        <h2>Privacy Policy</h2>
        <p class="legal-meta">Effective September 25, 2026 · Previously · Las Vegas, Nevada<br>Privacy questions or requests: <a href="/cdn-cgi/l/email-protection#d0b2b5a4b190a7b1a4b3b8a0a2b5a6b9bfa5a3bca9feb3bfbd"><span class="__cf_email__" data-cfemail="e98b8c9d88a99e889d8a81999b8c9f80869c9a8590c78a8684">[email&#160;protected]</span></a></p>
        <div class="legal-body">
          <p>This policy explains what information the Previously website at watchpreviously.com collects, what we do with it, and what choices you have. Short version: <strong>we collect as little as possible, we don't sell anything, and you can leave whenever you want.</strong></p>
          <h2>1. What we collect</h2>
          <h3>a) Account information — only if you create an account.</h3>
          <p>Signing in is optional. If you create an account, we store:</p>
          <ul>
            <li>Your <strong>email address</strong> (used for sign-in — a magic link we email you, or a password you choose).</li>
            <li>A <strong>password scramble</strong>, only if you add a password. We never store your actual password — only a one-way scrambled version (bcrypt) that can't be turned back into the password, and we can never read it.</li>
            <li>A <strong>display name</strong>, only if you type one in. We never guess it from your email.</li>
            <li>An optional <strong>profile photo</strong> you upload, and your <strong>timezone</strong> if you set one.</li>
            <li>Your <strong>preferences</strong>: streaming services you use, appearance choice, and notification toggles.</li>
            <li>Your <strong>library</strong>: watchlist entries, favorites, continue-watching progress, and the episodes you've marked watched (with the dates you marked them).</li>
          </ul>
          <p>Account data is stored in a database we control (Cloudflare D1) and synced to every device you sign in on. Deleting your account (Settings → Delete account) permanently removes all of it — profile, preferences, and library — and signs you out everywhere.</p>
          <h3>b) Email signups.</h3>
          <p>Separately, the <strong>open-beta signup form</strong> collects your email and device type so we can invite you to the beta ("We'll only email you about the beta. Unsubscribe anytime.").</p>
          <h3>c) What we don't collect.</h3>
          <p>No payment info, no analytics trackers, no advertising cookies. Passwords are optional — if you never set one, we hold nothing password-related at all; if you do, we hold only the scramble, never the password itself. <strong>Without an account</strong>, your starred favorites, episode-alert choices, recently viewed titles, and last-visit time stay in your browser's local storage — on your device only. We never see or receive any of it until you sign in and choose to sync it. Searching and browsing the catalog happens entirely in your browser — we don't see or store your searches.</p>
          <h2>2. How your email is handled</h2>
          <p>Your email is used for <strong>sign-in</strong> (a magic link we email you, or your password if you set one — resets go by email link too) and, if you joined it, the <strong>beta list</strong>. We <strong>never sell</strong> your email address or any personal information, and we don't share it with advertisers. The beta form sends your address <strong>directly to our own signup endpoint</strong> — a Cloudflare Worker that stores it in a database we control. No third-party service processes your signup.</p>
          <p><strong>Sending mail:</strong> delivery currently goes through our own backend; we're moving to <strong>Resend</strong> as the delivery provider, with double opt-in for marketing mail and one-click unsubscribe in every message. When that ships, this policy will be updated to describe it precisely — the promises stay the same, only the plumbing changes.</p>
          <h2>2a. How long we keep account data</h2>
          <ul>
            <li><strong>Active accounts:</strong> as long as your account exists.</li>
            <li><strong>Deleted accounts:</strong> everything — profile, preferences, watchlist, favorites, history — is deleted <strong>immediately</strong> when you delete your account. There is no grace period and no backup copy kept.</li>
            <li><strong>Sessions:</strong> sign-in sessions expire automatically; signing out ends them at once.</li>
          </ul>
          <h2>3. Trailers and third parties</h2>
          <p>Trailers play through embedded <strong>YouTube</strong> players, which load only after you tap play. YouTube/Google may set cookies or collect viewing data when the player loads — that's governed by Google's privacy policy, not ours. We don't receive your YouTube viewing data.</p>
          <p>Catalog data and artwork come from <strong>TMDB</strong>; we fetch that data server-side, so TMDB doesn't receive information about you from your visits.</p>
          <h2>4. How long we keep your email</h2>
          <ul>
            <li><strong>Active subscribers:</strong> as long as you're subscribed.</li>
            <li><strong>Unsubscribed:</strong> your address is deleted from the mailing list <strong>within 30 days</strong> of unsubscribing. We keep only an anonymous marker so we don't accidentally re-add you later — it can't be turned back into your address.</li>
            <li><strong>Never-confirmed signups:</strong> if you sign up but never click the confirmation link, the pending signup is purged after <strong>30 days</strong>.</li>
            <li><strong>Inactive subscribers:</strong> if you stop opening our emails for 12 months, we suppress the address and ask if you still want to hear from us before emailing again.</li>
          </ul>
          <h2>5. Your rights</h2>
          <p>Whatever the law where you live calls them, we honor these for everyone:</p>
          <ul>
            <li><strong>See</strong> what personal information we hold about you (your account profile, preferences, and library — everything listed in §1a).</li>
            <li><strong>Delete</strong> it — delete your account in Settings for immediate, complete removal, or email <a href="/cdn-cgi/l/email-protection#0b696e7f6a4b7c6a7f68637b796e7d62647e78677225686466"><span class="__cf_email__" data-cfemail="1f7d7a6b7e5f687e6b7c776f6d7a6976706a6c7366317c7072">[email&#160;protected]</span></a> with "Delete my data" and we'll confirm within 72 hours.</li>
            <li><strong>Unsubscribe</strong> — one click, in every email, no login required, effective immediately.</li>
            <li><strong>California residents:</strong> we honor access, deletion, and portability requests, and we do not sell personal information, so there's nothing to opt out of selling. You won't be treated differently for exercising your rights.</li>
            <li><strong>EU/UK visitors:</strong> same rights, plus you can object to or restrict processing and lodge a complaint with your data-protection authority.</li>
          </ul>
          <p>To make any request: <a href="/cdn-cgi/l/email-protection#610304150021160015020911130417080e14120d184f020e0c"><span class="__cf_email__" data-cfemail="c1a3a4b5a081b6a0b5a2a9b1b3a4b7a8aeb4b2adb8efa2aeac">[email&#160;protected]</span></a> — put "Privacy request" in the subject.</p>
          <h2>6. Security</h2>
          <p>The beta form posts to an endpoint we operate ourselves (see §2): subscriber data is encrypted at rest and signups are rate-limited. No system is perfect; if we ever discover a breach affecting your data, we'll tell you promptly.</p>
          <h2>7. Children</h2>
          <p>The Site is not directed at children under 13, and we don't knowingly collect their information. If you believe a child under 13 gave us an email address, contact us and we'll delete it.</p>
          <h2>8. Changes to this policy</h2>
          <p>We'll post updates here with a new effective date. Material changes get a notice on the Site and, if you're subscribed, an email. The v1.1 email-backend migration described in §2 will be reflected here when it ships.</p>
          <h2>9. Contact</h2>
          <p>Privacy questions or requests: <a href="/cdn-cgi/l/email-protection#82e0e7f6e3c2f5e3f6e1eaf2f0e7f4ebedf7f1eefbace1edef"><span class="__cf_email__" data-cfemail="bddfd8c9dcfdcadcc9ded5cdcfd8cbd4d2c8ced1c493ded2d0">[email&#160;protected]</span></a>.</p>
        </div>
      </div>
    </section>
      <section class="view page" id="view-cookies" aria-label="Cookie Notice">
      <div class="legal">
        <div class="legal-back"><button class="text-link" data-go="home">← Back to <span class="wordmark-inline">Previously</span></button></div>
        <div class="eyebrow">Legal</div>
        <h2>Cookie Notice</h2>
        <p class="legal-meta">Effective September 24, 2026 · Previously · Las Vegas, Nevada</p>
        <div class="legal-body">
          <p><strong>Short version: one cookie, and only if you sign in.</strong> No cookie banner for browsing — anonymous visitors get zero cookies from us.</p>
          <h2>What we set</h2>
          <ul>
            <li><strong>Session cookie</strong> (<code>wp_session</code>): set only when you sign in, so the site remembers you're you as you move between pages. It's HttpOnly (JavaScript can't read it), scoped to our domain, and deleted when you sign out or delete your account. No session cookie is set for signed-out visitors.</li>
            <li>No analytics cookies, no advertising cookies. Ever.</li>
          </ul>
          <h2>What we store — on your device, or in your account</h2>
          <p><strong>Signed out:</strong> your starred favorites, episode-alert choices, recently viewed titles, and last-visit time live in your browser's <strong>local storage</strong> — on your device, not our servers. We never see or receive any of it. Clear your browser's site data and it's gone. <strong>Signed in:</strong> your library syncs to your account on our servers (§1a) so it follows you across devices; signing out leaves the local copy but stops syncing.</p>
          <h2>Third parties</h2>
          <ul>
            <li><strong>Trailers</strong> play through YouTube's privacy-enhanced player, which only loads after you tap play. Tapping play is your consent — YouTube and Google's policies apply from that moment.</li>
            <li><strong>Beta signup</strong> posts directly to our own endpoint on infrastructure we control — it sets no cookies, on any domain.</li>
          </ul>
          <h2>When this changes</h2>
          <p>If we ever add anything that tracks you — analytics, ad networks, social pixels — this notice gets rewritten first, and a consent choice appears before anything loads. That's the deal.</p>
        </div>
      </div>
    </section>

    <section class="view page" id="view-dmca" aria-label="Copyright and DMCA">
      <div class="legal">
        <div class="legal-back"><button class="text-link" data-go="home">← Back to <span class="wordmark-inline">Previously</span></button></div>
        <div class="eyebrow">Legal</div>
        <h2>Copyright &amp; DMCA</h2>
        <p class="legal-meta">Effective September 23, 2026 · Contact: <a href="/cdn-cgi/l/email-protection#0d6f68796c4d7a6c796e657d7f687b6462787e6174236e6260327e786f67686e793049404e4c283f3d796c666869627a63"><span class="__cf_email__" data-cfemail="650700110425120411060d151700130c0a1016091c4b060a08">[email&#160;protected]</span></a></p>
        <div class="legal-body">
          <p>Previously respects copyright. Show and movie artwork on the Site is displayed under TMDB's API terms, hotlinked from TMDB's image servers — we don't re-host it and we don't claim to own it. Trailers are embedded YouTube players, which is how YouTube intends its videos to be shared.</p>
          <p>Because the catalog is large, mistakes can happen. If you're a rights holder (or their authorized agent) and you believe something on the Site infringes your copyright, tell us and we'll act promptly.</p>
          <h2>Filing a takedown notice</h2>
          <p>Email <a href="/cdn-cgi/l/email-protection#7f1d1a0b1e3f081e0b1c170f0d1a0916100a0c1306511c1012400c0a1d151a1c0b423b323c3e5a4d4f0b1e141a1b100811"><span class="__cf_email__" data-cfemail="cba9aebfaa8bbcaabfa8a3bbb9aebda2a4beb8a7b2e5a8a4a6">[email&#160;protected]</span></a> with the subject <strong>"DMCA takedown"</strong> and include:</p>
          <ol>
            <li>Your full name and contact information (email and phone), and your relationship to the copyrighted work.</li>
            <li>Identification of the copyrighted work you claim is infringed (title, and registration number if you have one).</li>
            <li>The exact URL(s) on watchpreviously.com where the material appears.</li>
            <li>This statement: <em>"I have a good faith belief that the use of the material is not authorized by the copyright owner, its agent, or the law."</em></li>
            <li>This statement: <em>"The information in this notice is accurate, and under penalty of perjury, I am authorized to act on behalf of the owner of the exclusive right that is allegedly infringed."</em></li>
            <li>Your physical or electronic signature.</li>
          </ol>
          <p>We review every notice. Valid notices result in removal or disabling of the material.</p>
          <h2>Counter-notices</h2>
          <p>If your material was removed because of a notice you believe was wrong, you may email a counter-notice with: your contact info, the removed material's URL, a statement under penalty of perjury that the removal was a mistake or misidentification, your consent to the jurisdiction of your local federal court, and your signature.</p>
        </div>
      </div>
    </section>

    <section class="view page" id="view-affiliates" aria-label="Affiliate Disclosure">
      <div class="legal">
        <div class="legal-back"><button class="text-link" data-go="home">← Back to <span class="wordmark-inline">Previously</span></button></div>
        <div class="eyebrow">Legal</div>
        <h2>Affiliate Disclosure</h2>
        <p class="legal-meta">Effective September 23, 2026 · Previously · Las Vegas, Nevada</p>
        <div class="legal-body">
          <p class="legal-status"><strong>Status today:</strong> the Site carries only house ads for our own app — <strong>no affiliate links, no sponsored placements.</strong> Below is our standing policy, published now so the rules are on the record before any money changes hands.</p>
          <h2>How Previously makes money</h2>
          <p>Some links on this Site — for example, links to streaming services or free trials — <strong>may in the future be affiliate links</strong>. If you sign up through one, we may earn a commission at no extra cost to you. Occasionally we may feature sponsored premieres; those are always labeled <strong>"Sponsored."</strong> Advertising and affiliate relationships never decide what appears in the catalog or how titles are ranked — our picks are editorial, full stop.</p>
          <h2>Where you'll see the labels</h2>
          <ul>
            <li><strong>Affiliate links</strong> carry a small "Affiliate link" tag right next to the link or button itself — not buried in the footer.</li>
            <li><strong>Sponsored premieres</strong> carry a prominent "Sponsored" label at the top of the feature.</li>
            <li><strong>Display ads</strong> are always labeled "Ad."</li>
          </ul>
          <h2>Rules that don't bend</h2>
          <ul>
            <li>No bought rankings — an affiliate or sponsor can never pay for a show's position in browse, search, rails, or the schedule.</li>
            <li>Plain language only: "Affiliate link" and "Sponsored" — never "partner content" or fine print.</li>
            <li>If we ever recommend a service we have an affiliate relationship with, it's a recommendation we'd make without the commission.</li>
          </ul>
        </div>
      </div>
    </section>

    <section class="view page" id="view-how-we-rank" aria-label="How we rank">
      <div class="legal">
        <div class="legal-back"><button class="text-link" data-go="home">← Back to <span class="wordmark-inline">Previously</span></button></div>
        <div class="eyebrow">Our promise</div>
        <h2>How we rank.</h2>
        <p class="legal-meta">The whole thing, in plain English.</p>
        <div class="legal-body">
          <p><strong>No one pays for placement on Previously. Ever.</strong> No studio, streamer, or sponsor can buy a show's position in search, browse, rails, or the schedule. That rule doesn't bend.</p>
          <h2>How each part of the site is ordered</h2>
          <ul>
            <li><strong>Tonight's schedule</strong> — chronological. Air times decide, nothing else.</li>
            <li><strong>Series &amp; movie rails</strong> — our editors' picks first, then the titles the most TMDB viewers bothered to rate.</li>
            <li><strong>Browse &amp; search</strong> — matches your words. No boosting, no burying.</li>
            <li><strong>Tonight for you</strong> — built only from the shows <em>you</em> starred. Your taste, not a sponsor's.</li>
          </ul>
          <h2>How we make money</h2>
          <p>Right now: house ads for our own app, always labeled <strong>"Ad."</strong> If we ever add affiliate links or sponsored premieres, they're labeled at the link — see our <button class="text-link" data-go="affiliates">affiliate disclosure</button> — and they never touch rankings.</p>
          <h2>Why independence matters</h2>
          <p>We're not a streaming service. We don't sell subscriptions or rentals, so we have nothing to push and no reason to steer you. When we say a show is worth your night, the only thing in it for us is your trust.</p>
        </div>
      </div>
    </section>

  </main>

  <div class="modal" id="bingeModal" role="dialog" aria-modal="true" aria-labelledby="bcTitle" aria-hidden="true"><div class="bc-panel"><div class="bc-handle" aria-hidden="true"></div><button class="modal-close" data-modal-close="bingeModal" aria-label="Close calculator">×</button><div class="bc-body"><p class="bc-eyebrow" id="bcEyebrow">Binge calculator</p><h2 class="bc-headline" id="bcTitle">Loading your plan…</h2><p class="bc-sub" id="bcSub"></p><div class="bc-chips" id="bcChips" role="group" aria-label="Hours per day"><button class="bc-chip" type="button" data-h="1">1<small>hr / day</small></button><button class="bc-chip is-on" type="button" data-h="2">2<small>hrs / day</small></button><button class="bc-chip" type="button" data-h="3">3<small>hrs / day</small></button></div><button class="bc-toggle" id="bcEarlier" type="button" aria-pressed="false"><span class="bc-dot" aria-hidden="true"></span><span id="bcEarlierLabel">Include earlier seasons</span></button><button class="bc-expander" id="bcAdjustBtn" type="button" aria-expanded="false" aria-controls="bcAdjust">Adjust plan<span class="bc-caret" aria-hidden="true">▾</span></button><div class="bc-adjust" id="bcAdjust" hidden><div class="bc-row" id="bcBufferRow"><span>Buffer before the premiere</span><div class="bc-seg" id="bcBuffer" role="group" aria-label="Buffer before the premiere"><button type="button" data-b="0">0</button><button type="button" data-b="15">15</button><button type="button" data-b="30" class="is-on">30</button><button type="button" data-b="60">60</button></div></div><div class="bc-row"><span>Pacing</span><div class="bc-seg" id="bcPacing" role="group" aria-label="Pacing"><button type="button" data-p="even" class="is-on">Even</button><button type="button" data-p="front">Front-loaded</button></div></div><div class="bc-row"><span>Daily hours, fine-tuned</span><div class="bc-stepper"><button type="button" id="bcMinus" aria-label="Half an hour less per day">−</button><span id="bcHoursVal">2.0</span><button type="button" id="bcPlus" aria-label="Half an hour more per day">+</button></div></div></div><div class="bc-eps-head"><span id="bcEpsTitle">Episodes to watch</span><button class="bc-link" id="bcReset" type="button">Reset</button></div><div class="bc-eps" id="bcEpisodes"></div><p class="bc-note" id="bcNote"></p></div></div></div>
  <div class="modal" id="showModal" role="dialog" aria-modal="true" aria-labelledby="modalTitle" aria-hidden="true"><article class="modal-card"><button class="modal-close" data-modal-close="showModal" aria-label="Close details">×</button><div class="trailer-stage" id="trailerStageTop" aria-label="Trailer"></div><p class="no-trailer-note" id="noTrailerNote" hidden><span class="dot"></span>No trailer available for this title yet.</p><div class="modal-body"><div class="meta" id="modalMeta"></div><div class="modal-engage"><button class="bc-entry" id="modalBinge" type="button" hidden><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="13" r="8"/><path d="M12 9v4l2.5 2.5"/><path d="M9 2h6"/></svg><span>Can I catch up in time?</span></button><button class="engage-btn" id="modalStar" aria-pressed="false" aria-label="Save this title to your Library"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="m12 2.5 2.9 6 6.6.9-4.8 4.6 1.2 6.5L12 17.4 6.1 20.5l1.2-6.5L2.5 9.4l6.6-.9z"/></svg><span>Star</span></button><button class="engage-btn" id="modalBell" aria-pressed="false" aria-label="Toggle episode alerts for this show" hidden><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.7 21a2 2 0 0 1-3.4 0"/></svg><span>Alerts</span></button></div><h2 id="modalTitle"></h2><p id="modalDescription"></p><p class="modal-cast" id="modalCast"></p><p class="modal-rating" id="modalRating"></p><div class="wtw" id="wtwSection" aria-label="Where to watch" hidden></div><div class="modal-actions"><button class="cta" data-beta-open>Join the open beta</button><button class="cta textual" data-modal-close="showModal">Close</button></div></div></article></div>
  <div class="modal" id="seriesModal" role="dialog" aria-modal="true" aria-labelledby="seriesTitle" aria-hidden="true"><article class="modal-card"><button class="modal-close" data-modal-close="seriesModal" aria-label="Close series">×</button><div class="series-stage" id="seriesStage" aria-label="Episode player"></div><div class="modal-body"><div class="meta" id="seriesMeta"></div><h2 id="seriesTitle"></h2><p id="seriesDesc"></p><div class="series-eps-head"><span id="seriesEpsCount"></span><a class="cta textual" id="seriesChannelLink" href="#" target="_blank" rel="noopener">Official channel →</a></div><div class="series-eps" id="seriesEps" role="list"></div><div class="modal-actions"><button class="cta textual" data-modal-close="seriesModal">Close</button></div></div></article></div>
  <div class="modal" id="podModal" role="dialog" aria-modal="true" aria-labelledby="podTitle" aria-hidden="true"><article class="modal-card"><button class="modal-close" data-modal-close="podModal" aria-label="Close podcast">×</button><div class="modal-body"><div class="meta" id="podMeta"></div><h2 id="podTitle"></h2><p id="podPitch"></p><div class="modal-actions pod-actions"><a class="cta" id="podWatchBtn" href="#" target="_blank" rel="noopener">Watch on YouTube</a><button class="cta textual" data-modal-close="podModal">Close</button></div><div class="series-eps-head"><span>Latest episodes</span><span class="pod-eps-note">from the official channel</span></div><div class="series-eps" id="podEps" role="list"></div></div></article></div>

      <div class="modal" id="epModal" role="dialog" aria-modal="true" aria-labelledby="epTitle" aria-hidden="true"><div class="ep-panel" role="document"><div class="ep-handle" aria-hidden="true"></div><button class="modal-close" data-modal-close="epModal" aria-label="Close episode">×</button><p class="ep-kicker" id="epKicker"></p><h2 class="ep-title" id="epTitle"></h2><p class="ep-meta" id="epMeta"></p><div class="ep-about"><p class="ep-about-label">About the show</p><p class="ep-about-text" id="epAbout"></p></div><div class="ep-actions"><button class="ep-follow" id="epFollowBtn" type="button" aria-pressed="false">Follow</button><a class="cta" id="epWatchBtn" href="#" target="_blank" rel="noopener">Watch on YouTube</a></div><section class="ep-news" id="epNews" hidden aria-label="Related coverage"><h3>Related coverage</h3><p class="ep-news-sub">News reporting on this case, from the web — not the show's sources.</p><div class="ep-news-list" id="epNewsList"></div></section></div></div>

  <div class="modal" id="signinModal" role="dialog" aria-modal="true" aria-labelledby="signinTitle" aria-hidden="true"><article class="modal-card beta-card signin-card"><button class="modal-close" data-modal-close="signinModal" aria-label="Close sign in">×</button><div class="modal-body">
    <div class="eyebrow">Previously account</div>
    <h2 id="signinTitle">Sign in.</h2>
    <form id="signinForm" class="beta-form" novalidate>
      <p class="signin-sub">One email, one link, no password to forget. Your library, alerts, and preferences follow you to every device.</p>
      <div class="field"><label for="signinEmail">Email address</label><input id="signinEmail" type="email" autocomplete="email" inputmode="email" placeholder="you@example.com" required></div>
      <div class="form-status" id="signinStatus" role="alert"></div>
      <div class="form-actions"><button class="cta" id="signinSubmit" type="submit">Email me a sign-in link</button></div>
      <p class="form-note">The link is single-use and expires in 15 minutes. We never see or store a password — there isn't one.</p>
    </form>
    <div id="signinSent" hidden>
      <p class="signin-sub"><b>Check your email.</b><br>We sent a sign-in link to <b id="signinSentEmail"></b>. Tap it and you're in — it expires in 15 minutes.</p>
      <div class="form-actions acct-mt18"><button class="cta secondary compact" id="signinBack" type="button">Use a different email</button></div>
      <p class="signin-mailto">Nothing arrived? Check spam, then try again — the mail service hiccups sometimes.</p>
    </div>
  </div></article></div>
  <div class="modal" id="helpModal" role="dialog" aria-modal="true" aria-labelledby="helpTitle" aria-hidden="true"><article class="modal-card beta-card"><button class="modal-close" data-modal-close="helpModal" aria-label="Close help">×</button><div class="modal-body">
    <div class="eyebrow">Help &amp; contact</div>
    <h2 id="helpTitle">Talk to a human.</h2>
    <p class="signin-sub">Something broken, a show missing, or just want to say hi — a real person reads every message, usually within a day or two.</p>
    <div class="acct-row tour-replay-row"><div class="grow"><b>Replay quick tour</b><p><span class="svc-note">Missed the tour? Take the 10-second walkthrough — welcome, drag-and-drop, done.</span></p></div><button class="ghost-btn" id="tourReplayBtnSignedOut" type="button">Replay tour</button></div>
    <div class="form-actions acct-mt20"><a class="cta compact acct-no-deco" href="/cdn-cgi/l/email-protection#5d3f38293c1d2a3c293e352d2f382b3432282e3124733e3230622e283f37383e29600d2f382b3432282e3124786f6d3538312d">Email <span class="__cf_email__" data-cfemail="8ae8effeebcafdebfee9e2faf8effce3e5fff9e6f3a4e9e5e7">[email&#160;protected]</span></a><button class="cta textual" data-modal-close="helpModal" type="button">Close</button></div>
  </div></article></div>
  <div class="modal" id="inboxModal" role="dialog" aria-modal="true" aria-labelledby="inboxTitle" aria-hidden="true"><article class="modal-card inbox-card"><button class="modal-close" data-modal-close="inboxModal" aria-label="Close inbox">×</button><div class="modal-body"><div class="eyebrow">Tonight</div><h2 id="inboxTitle">Your shows air tonight.</h2><p class="inbox-sub" id="inboxSub"></p><div class="inbox-list" id="inboxList"></div><div class="modal-actions"><button class="cta secondary compact" id="inboxClear" type="button">Mark all read</button><button class="cta textual" data-modal-close="inboxModal">Close</button></div></div></article></div>

  <div class="modal" id="inboxModal" role="dialog" aria-modal="true" aria-labelledby="inboxTitle" aria-hidden="true"><article class="modal-card inbox-card"><button class="modal-close" data-modal-close="inboxModal" aria-label="Close inbox">×</button><div class="modal-body"><div class="eyebrow">Tonight</div><h2 id="inboxTitle">Your shows air tonight.</h2><p class="inbox-sub" id="inboxSub"></p><div class="inbox-list" id="inboxList"></div><div class="modal-actions"><button class="cta secondary compact" id="inboxClear" type="button">Mark all read</button><button class="cta textual" data-modal-close="inboxModal">Close</button></div></div></article></div>

<div class="modal" id="betaModal" role="dialog" aria-modal="true" aria-labelledby="betaModalTitle" aria-hidden="true"><article class="modal-card beta-card"><button class="modal-close" data-modal-close="betaModal" aria-label="Close beta request">×</button><div class="modal-body"><div class="eyebrow">Open beta</div><h2 id="betaModalTitle">Join the open beta.</h2><ul class="beta-benefits"><li>Early access to the Previously app before public launch</li><li>Your watchlist, ready on every screen.</li><li>A direct say in what we build next</li></ul><p class="next-step">We'll email your invite as soon as your spot opens.</p><form class="beta-form" id="betaForm" action="https://beta.watchpreviously.com" method="POST"><input class="sr-only" type="text" name="_honey" tabindex="-1" autocomplete="off" aria-hidden="true"><div class="form-row"><div class="field"><label for="betaName">Name</label><input id="betaName" name="name" autocomplete="name" required placeholder="Your name"></div><div class="field"><label for="betaDevice">Primary device</label><select id="betaDevice" name="device"><option>Android</option><option>iPhone</option><option>Web</option><option>Other</option></select></div></div><div class="field"><label for="betaEmail">Email</label><input id="betaEmail" name="email" type="email" autocomplete="email" required placeholder="you@example.com"><p class="privacy-note" id="privacy-note">We'll only email you about the beta. Unsubscribe anytime.</p></div><div class="form-actions"><button class="cta" id="betaSubmit" type="submit">Join the open beta</button></div><div class="form-status" id="formStatus" role="status" aria-live="polite"></div><div class="manual-fallback" id="manualFallback"><div class="manual-copy"><strong>Prefer to email it yourself?</strong><a id="betaEmailLink" href="/cdn-cgi/l/email-protection#492b2c3d28093e283d2a21393b2c3f20263c3a2530672a2624"><span class="__cf_email__" data-cfemail="ddbfb8a9bc9daabca9beb5adafb8abb4b2a8aeb1a4f3beb2b0">[email&#160;protected]</span></a></div><div class="manual-actions"><button class="mini-btn" type="button" id="copyRequest">Copy request</button><a class="mini-btn" id="openEmail" href="/cdn-cgi/l/email-protection#d2b0b7a6b392a5b3a6b1baa2a0b7a4bbbda7a1beabfcb1bdbf">Open email</a></div></div></form></div></article></div>

    <footer><div class="footer-shell"><div class="footer-main"><div class="footer-brand"><span class="wordmark-inline footer-wordmark"><svg class="wm-glyph" width="30" height="20" viewBox="0 0 48 32" fill="none" aria-hidden="true"><path d="M21 5 L8 16 L21 27" stroke="#E8321E" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/><path d="M39 5 L26 16 L39 27" stroke="#E8321E" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/></svg>Previously</span><p>Tonight's schedule, movies, and shows in one place.</p></div><nav class="footer-group" aria-label="Explore"><h2>Explore</h2><button data-go="home">Home</button><a href="/culture/">Culture</a><button data-go="browse">Browse</button><button data-go="podcasts">Podcasts</button><button data-go="library">Library</button></nav><nav class="footer-group" aria-label="Company"><h2>Company</h2><button data-beta-open>Join the open beta</button><a href="/cdn-cgi/l/email-protection#187a7d6c79586f796c7b70686a7d6e71776d6b7461367b7775"><span class="__cf_email__" data-cfemail="85e7e0f1e4c5f2e4f1e6edf5f7e0f3eceaf0f6e9fcabe6eae8">[email&#160;protected]</span></a><a href="https://instagram.com/watchpreviously" target="_blank" rel="noopener">Instagram · @watchpreviously</a></nav><nav class="footer-group" aria-label="Legal"><h2>Legal</h2><button data-go="how-we-rank">How we rank</button><button data-go="terms">Terms</button><button data-go="privacy">Privacy</button><button data-go="cookies">Cookies</button><button data-go="dmca">DMCA</button><button data-go="affiliates">Affiliate disclosure</button><a href="#tmdb-note">TMDB notice</a></nav></div><div class="footer-base"><p id="tmdb-note" class="sr-anchor">This product uses the TMDB API but is not endorsed or certified by TMDB.</p><p class="neutral-line">Ranked for viewers, never for advertisers — <button class="text-link" data-go="how-we-rank">how we rank</button>.</p><span>© 2026 <span class="wordmark-inline">Previously</span>.</span></div></div></footer>

  <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script type="application/json" id="catalog-data">[{"id":"varnell","title":"The Varnell Hill Show","type":"Series","genre":"Comedy","network":"Paramount+","meta":"Series","image":"assets/artwork/varnell.jpg","format":"hero","trailer":"FChcXRz9wEM","desc":"Tommy Davidson returns as Martin's flamboyant talk-show host Varnell Hill, fighting to stay relevant behind the scenes of his late-night show — new episodes Tuesdays on Paramount+."},{"id":"drop","title":"The Drop: A Snowfall Saga","type":"Series","genre":"Drama · Crime","network":"FX / Hulu","meta":"Series","image":"assets/artwork/drop.jpg","format":"wide","trailer":"3Yy_6OaAk3Q","desc":"Wanda and Leon chase the rise of West Coast hip-hop in this Snowfall spinoff — new episodes Tuesdays on FX and Hulu."},{"id":"signs","title":"Signs of a Psychopath","type":"Series","genre":"Crime","network":"Investigation Discovery","meta":"Series","image":"assets/artwork/signs.jpg","format":"wide","trailer":"","desc":"Investigators and experts break down the warning signs in real cases, tracing how killers hid in plain sight."},{"id":"mobland","title":"MobLand","type":"Series","genre":"Drama · Crime","network":"Paramount+","meta":"Season 2","image":"assets/artwork/mobland.jpg","format":"wide","trailer":"VvYl1a1Px5Y","cast":"Tom Hardy, Pierce Brosnan, Helen Mirren","desc":"Family power and shifting loyalties open a new season in this crime drama."},{"id":"severance","title":"Severance","type":"Series","genre":"Drama · Mystery","network":"Apple TV+","meta":"TV series","image":"assets/posters/severance.jpg","format":"portrait","trailer":"_UXKlYvLGJY","cast":"Adam Scott, Britt Lower, Zach Cherry","desc":"Lumon employees whose memories are split between work and home start questioning what the company is hiding."},{"id":"bear","title":"The Bear","type":"Series","genre":"Drama · Comedy","network":"FX / Hulu","meta":"TV series","image":"assets/posters/the-bear.jpg","format":"portrait","trailer":"ojjCvICC86c","cast":"Jeremy Allen White, Ayo Edebiri, Ebon Moss-Bachrach","desc":"A kitchen, a family, and the pressure of trying to build something better without losing each other."},{"id":"last-of-us","title":"The Last of Us","type":"Series","genre":"Drama · Action","network":"HBO","meta":"TV series","image":"assets/posters/last-of-us.jpg","format":"portrait","trailer":"_zHPsmXCjB0","cast":"Pedro Pascal, Bella Ramsey","desc":"A dangerous cross-country journey grounded in survival, trust, and the people we choose to protect."},{"id":"shogun","title":"Shōgun","type":"Series","genre":"Drama","network":"FX / Hulu","meta":"Limited series","image":"assets/posters/shogun.jpg","format":"portrait","trailer":"yAN5uspO_hk","cast":"Hiroyuki Sanada, Cosmo Jarvis, Anna Sawai","desc":"Power, loyalty, and cultural collision unfold against the political stakes of feudal Japan."},{"id":"wednesday","title":"Wednesday","type":"Series","genre":"Comedy · Mystery","network":"Netflix","meta":"TV series","image":"assets/posters/wednesday.jpg","format":"portrait","trailer":"03u4xyj0TH4","cast":"Jenna Ortega, Emma Myers","desc":"A sharp young investigator faces a new school, a string of mysteries, and a world stranger than she expected."},{"id":"dune","title":"Dune: Part Two","type":"Movie","genre":"Drama · Action","network":"","meta":"Feature film","image":"assets/posters/dune.jpg","format":"portrait","trailer":"ABfQGtUEEzA","cast":"Timothée Chalamet, Zendaya, Rebecca Ferguson","desc":"The struggle for Arrakis grows into a sweeping conflict of power, belief, and destiny."},{"id":"spiderverse","title":"Spider-Man: Across the Spider-Verse","type":"Movie","genre":"Action · Adventure","network":"","meta":"Feature film","image":"assets/posters/spiderverse.jpg","format":"portrait","trailer":"shW9i6k8cB0","cast":"Shameik Moore, Hailee Steinfeld","desc":"Miles Morales is pulled across the multiverse into a vivid conflict over what a hero's story should be."},{"id":"everything","title":"Everything Everywhere All at Once","type":"Movie","genre":"Comedy · Adventure","network":"","meta":"Feature film","image":"assets/posters/everything.jpg","format":"portrait","trailer":"wxN1T1uxQ2g","cast":"Michelle Yeoh, Ke Huy Quan, Stephanie Hsu","desc":"A family story explodes across possibilities, balancing absurdity, action, and a deeply human center."}]</script>
  <!-- Star + labels: one-time hint (touch) -->
  <div class="star-hint" id="starHint" hidden><p>Tap <b>★</b> to save shows to your Library.</p><button type="button" id="starHintDismiss">Got it</button></div>
  <script type="application/json" id="schedule-data">{"generated":"2026-09-23","windowStart":"2026-09-22","maxDate":"2027-07-09","count":547,"episodes":[{"show":"The Varnell Hill Show","net":"Paramount+","s":1,"e":5,"ep":"Varnell Hill Keeps It Real","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":"varnell"},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":1,"ep":"Lo Spadino","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":2,"ep":"Il Circuito","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":3,"ep":"Il Furto","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":4,"ep":"La Licenza","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":5,"ep":"La Gara","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":6,"ep":"La Guerra","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":7,"ep":"Il Mak P","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Minerva - La scuola","net":"Netflix","s":1,"e":8,"ep":"Il Ballo","ts":"2026-09-22T12:00:00+00:00","timed":0,"id":""},{"show":"Good Morning Football","net":"NFL Network","s":11,"e":169,"ep":"Episode 169","ts":"2026-09-22T12:00:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":23,"ep":"Episode 23","ts":"2026-09-22T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":24,"ep":"Episode 24","ts":"2026-09-22T13:30:00+00:00","timed":1,"id":""},{"show":"First Take","net":"ESPN","s":20,"e":252,"ep":"Episode 252","ts":"2026-09-22T14:00:00+00:00","timed":1,"id":""},{"show":"GMA3","net":"ABC","s":6,"e":260,"ep":"Episode 260","ts":"2026-09-22T17:00:00+00:00","timed":1,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":174,"ep":"Episode 373","ts":"2026-09-22T18:00:00+00:00","timed":1,"id":""},{"show":"Dana White's Tuesday Night Contender Series","net":"ESPN+","s":10,"e":7,"ep":"Week 7","ts":"2026-09-22T23:00:00+00:00","timed":1,"id":""},{"show":"WNBA Countdown","net":"ESPN","s":5,"e":16,"ep":"Episode 16","ts":"2026-09-22T23:30:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":2,"ep":"The Blind Auditions Part 2","ts":"2026-09-23T00:00:00+00:00","timed":1,"id":""},{"show":"Bobby's Triple Threat","net":"Food Network","s":5,"e":5,"ep":"Titans vs Kenny Gilbert","ts":"2026-09-23T00:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":3,"ep":"","ts":"2026-09-23T00:00:00+00:00","timed":1,"id":""},{"show":"A Very Haunted Renovation","net":"HGTV","s":1,"e":2,"ep":"Ghosts in the Gathering Rooms","ts":"2026-09-23T00:00:00+00:00","timed":1,"id":""},{"show":"House Shock","net":"HGTV","s":1,"e":1,"ep":"","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":""},{"show":"America's Got Talent","net":"NBC","s":21,"e":22,"ep":"Finale Performances","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":""},{"show":"Doc","net":"FOX","s":3,"e":1,"ep":"Wherefore Art Thou","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":""},{"show":"The Proof Is Out There","net":"History","s":6,"e":20,"ep":"Nazi Flying Saucers, Real-Life Aquaman, and Bigfoot Family","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":""},{"show":"Bobby Flay's The Line","net":"Food Network","s":1,"e":3,"ep":"Leah Cohen: Pig & Khao","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":""},{"show":"The Drop: A Snowfall Saga","net":"FX","s":1,"e":3,"ep":"Family Matters","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":"drop"},{"show":"1000-lb Sisters","net":"TLC","s":9,"e":4,"ep":"Another BBQ Bites the Dust","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":""},{"show":"Signs of a Psychopath","net":"Investigation Discovery","s":11,"e":10,"ep":"The Apocalyptic End","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":"signs"},{"show":"Tyler Perry's Assisted Living","net":"BET","s":7,"e":3,"ep":"The Home Remedy","ts":"2026-09-23T01:00:00+00:00","timed":1,"id":""},{"show":"Signs of a Psychopath","net":"Investigation Discovery","s":11,"e":11,"ep":"Something Took Control of Me","ts":"2026-09-23T01:30:00+00:00","timed":1,"id":"signs"},{"show":"R.J. Decker","net":"ABC","s":2,"e":2,"ep":"Manos: Hands of Fate","ts":"2026-09-23T02:00:00+00:00","timed":1,"id":""},{"show":"Cocktail Wars","net":"E!","s":1,"e":7,"ep":"All The Cocktails","ts":"2026-09-23T02:00:00+00:00","timed":1,"id":""},{"show":"The Proof Is Out There","net":"History","s":6,"e":21,"ep":"Area 51 Crash, Yeti Footprints, and Human Pin Cushion","ts":"2026-09-23T02:03:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":104,"ep":"","ts":"2026-09-23T03:00:00+00:00","timed":1,"id":""},{"show":"Late Night with Seth Meyers","net":"NBC","s":2026,"e":81,"ep":"Jon Hamm, Sabrina Impacciatore, Taylor Tomlinson","ts":"2026-09-23T04:35:00+00:00","timed":1,"id":""},{"show":"Ted Lasso","net":"Apple TV","s":4,"e":8,"ep":"Follow the Anger","ts":"2026-09-23T12:00:00+00:00","timed":0,"id":""},{"show":"Last Seen","net":"Apple TV","s":1,"e":4,"ep":"The Truth","ts":"2026-09-23T12:00:00+00:00","timed":0,"id":""},{"show":"Slow Horses","net":"Apple TV","s":6,"e":2,"ep":"Daddy Issues","ts":"2026-09-23T12:00:00+00:00","timed":0,"id":""},{"show":"Made in Korea","net":"Disney+","s":2,"e":5,"ep":"","ts":"2026-09-23T12:00:00+00:00","timed":0,"id":""},{"show":"Made in Korea","net":"Disney+","s":2,"e":6,"ep":"","ts":"2026-09-23T12:00:00+00:00","timed":0,"id":""},{"show":"Good Morning Football","net":"NFL Network","s":11,"e":170,"ep":"Episode 170","ts":"2026-09-23T12:00:00+00:00","timed":1,"id":""},{"show":"Re:Zero kara Hajimeru Isekai Seikatsu","net":"AT-X","s":4,"e":18,"ep":"Episode 18","ts":"2026-09-23T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":25,"ep":"Episode 25","ts":"2026-09-23T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":26,"ep":"Episode 26","ts":"2026-09-23T13:30:00+00:00","timed":1,"id":""},{"show":"First Take","net":"ESPN","s":20,"e":253,"ep":"Episode 253","ts":"2026-09-23T14:00:00+00:00","timed":1,"id":""},{"show":"GMA3","net":"ABC","s":6,"e":261,"ep":"Episode 261","ts":"2026-09-23T17:00:00+00:00","timed":1,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":175,"ep":"Episode 374","ts":"2026-09-23T18:00:00+00:00","timed":1,"id":""},{"show":"Cook's Country from America's Test Kitchen","net":"PBS","s":19,"e":3,"ep":"L.A. Sandwiches","ts":"2026-09-23T19:30:00+00:00","timed":1,"id":""},{"show":"NFL Live","net":"ESPN","s":28,"e":101,"ep":"Episode 101","ts":"2026-09-23T20:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":3,"ep":"The Blind Auditions Part 3","ts":"2026-09-24T00:00:00+00:00","timed":1,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":1,"ep":"Permanent Uncertainty","ts":"2026-09-24T00:00:00+00:00","timed":1,"id":""},{"show":"Tyler Perry's The Oval","net":"BET","s":7,"e":21,"ep":"Agent Stan Bennett","ts":"2026-09-24T01:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":10,"ep":"Knowledge Keepers","ts":"2026-09-24T01:00:00+00:00","timed":1,"id":""},{"show":"America's Got Talent","net":"NBC","s":21,"e":23,"ep":"Finale Results","ts":"2026-09-24T01:00:00+00:00","timed":1,"id":""},{"show":"Totally ‘90s House","net":"HGTV","s":1,"e":5,"ep":"Episode 5","ts":"2026-09-24T01:00:00+00:00","timed":1,"id":""},{"show":"The Great American Road Rally: Celebrity Edition","net":"The CW","s":1,"e":2,"ep":"Gateway West","ts":"2026-09-24T01:00:00+00:00","timed":1,"id":""},{"show":"ER: Caught on Camera","net":"TLC","s":1,"e":6,"ep":"Episode 3","ts":"2026-09-24T01:00:00+00:00","timed":1,"id":""},{"show":"The Ark","net":"Syfy","s":3,"e":9,"ep":"Critical Failure","ts":"2026-09-24T02:00:00+00:00","timed":1,"id":""},{"show":"Big Brother","net":"CBS","s":28,"e":33,"ep":"Episode 33","ts":"2026-09-24T02:00:00+00:00","timed":1,"id":""},{"show":"How to Catch a Dirtbag","net":"Discovery","s":1,"e":8,"ep":"Beverly Hills Banger","ts":"2026-09-24T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":105,"ep":"","ts":"2026-09-24T03:00:00+00:00","timed":1,"id":""},{"show":"Late Night with Seth Meyers","net":"NBC","s":2026,"e":82,"ep":"Ethan Hawke, Zara Larsson","ts":"2026-09-24T04:35:00+00:00","timed":1,"id":""},{"show":"Star Trek: Strange New Worlds","net":"Paramount+","s":4,"e":10,"ep":"Tomorrow's Enterprise","ts":"2026-09-24T12:00:00+00:00","timed":0,"id":""},{"show":"Good Morning Football","net":"NFL Network","s":11,"e":171,"ep":"Episode 171","ts":"2026-09-24T12:00:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":27,"ep":"Episode 27","ts":"2026-09-24T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":28,"ep":"Episode 28","ts":"2026-09-24T13:30:00+00:00","timed":1,"id":""},{"show":"First Take","net":"ESPN","s":20,"e":254,"ep":"Episode 254","ts":"2026-09-24T14:00:00+00:00","timed":1,"id":""},{"show":"GMA3","net":"ABC","s":6,"e":262,"ep":"Episode 262","ts":"2026-09-24T17:00:00+00:00","timed":1,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":176,"ep":"Episode 375","ts":"2026-09-24T18:00:00+00:00","timed":1,"id":""},{"show":"Cook's Country from America's Test Kitchen","net":"PBS","s":19,"e":4,"ep":"Surprising Sheet-Pan Suppers","ts":"2026-09-24T19:30:00+00:00","timed":1,"id":""},{"show":"NFL Live","net":"ESPN","s":28,"e":102,"ep":"Episode 102","ts":"2026-09-24T20:00:00+00:00","timed":1,"id":""},{"show":"College Football Countdown","net":"ESPN","s":21,"e":7,"ep":"Week 4B","ts":"2026-09-24T23:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":3,"ep":"The Traitors Are Watching","ts":"2026-09-25T00:00:00+00:00","timed":1,"id":""},{"show":"Hell's Kitchen","net":"FOX","s":25,"e":1,"ep":"25th Premiere Party","ts":"2026-09-25T00:00:00+00:00","timed":1,"id":""},{"show":"Big Brother","net":"CBS","s":28,"e":34,"ep":"Episode 34--Live Eviction","ts":"2026-09-25T00:00:00+00:00","timed":1,"id":""},{"show":"The Real Housewives of Orange County","net":"Bravo","s":20,"e":12,"ep":"Lei It on Me","ts":"2026-09-25T00:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":4,"ep":"The Death Parade","ts":"2026-09-25T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":1,"ep":"13","ts":"2026-09-25T01:00:00+00:00","timed":1,"id":""},{"show":"TNA iMPACT!","net":"AMC","s":2026,"e":39,"ep":"Episode 39","ts":"2026-09-25T01:00:00+00:00","timed":1,"id":""},{"show":"Engineering From Above","net":"History","s":1,"e":7,"ep":"Engineering for the Extreme","ts":"2026-09-25T01:00:00+00:00","timed":1,"id":""},{"show":"A Killer Story","net":"HBO","s":1,"e":3,"ep":"A Dangerous Notion","ts":"2026-09-25T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":2,"ep":"1:13 AM","ts":"2026-09-25T01:30:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":3,"ep":"Rauhnacht","ts":"2026-09-25T02:00:00+00:00","timed":1,"id":""},{"show":"Engineering From Above","net":"History","s":1,"e":8,"ep":"Bizarre Engineering","ts":"2026-09-25T02:03:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":106,"ep":"","ts":"2026-09-25T03:00:00+00:00","timed":1,"id":""},{"show":"Dark Matter","net":"Apple TV","s":2,"e":5,"ep":"Love and Be Loved","ts":"2026-09-25T12:00:00+00:00","timed":0,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":2,"ep":"Song 2","ts":"2026-09-25T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"Good Morning Football","net":"NFL Network","s":11,"e":172,"ep":"Episode 172","ts":"2026-09-25T12:00:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":29,"ep":"Episode 29","ts":"2026-09-25T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":30,"ep":"Episode 30","ts":"2026-09-25T13:30:00+00:00","timed":1,"id":""},{"show":"First Take","net":"ESPN","s":20,"e":255,"ep":"Episode 255","ts":"2026-09-25T14:00:00+00:00","timed":1,"id":""},{"show":"GMA3","net":"ABC","s":6,"e":263,"ep":"Episode 263","ts":"2026-09-25T17:00:00+00:00","timed":1,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":177,"ep":"Episode 376","ts":"2026-09-25T18:00:00+00:00","timed":1,"id":""},{"show":"Cook's Country from America's Test Kitchen","net":"PBS","s":19,"e":5,"ep":"Cozy Baking","ts":"2026-09-25T19:30:00+00:00","timed":1,"id":""},{"show":"The Loud House","net":"Nickelodeon","s":10,"e":19,"ep":"All Pets Are Off","ts":"2026-09-25T21:30:00+00:00","timed":1,"id":""},{"show":"The Loud House","net":"Nickelodeon","s":10,"e":20,"ep":"Brain Man","ts":"2026-09-25T21:30:00+00:00","timed":1,"id":""},{"show":"The Patrick Star Show","net":"Nickelodeon","s":5,"e":17,"ep":"Gone Bootin'","ts":"2026-09-25T22:00:00+00:00","timed":1,"id":""},{"show":"The Patrick Star Show","net":"Nickelodeon","s":5,"e":18,"ep":"Roller Bunny","ts":"2026-09-25T22:15:00+00:00","timed":1,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":39,"ep":"#1412 - Gainbridge Fieldhouse in Indianapolis, IN","ts":"2026-09-26T00:00:00+00:00","timed":1,"id":""},{"show":"JAŸ-Z IN 8","net":"HBO","s":1,"e":3,"ep":"Chapter Three","ts":"2026-09-26T00:00:00+00:00","timed":1,"id":""},{"show":"Deadliest Catch","net":"Discovery","s":22,"e":19,"ep":"Father, Brother, Sailor, Son","ts":"2026-09-26T00:00:00+00:00","timed":1,"id":""},{"show":"On Patrol: First Shift","net":"REELZ","s":5,"e":19,"ep":"#519","ts":"2026-09-26T00:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":2,"ep":"The Veil of Time","ts":"2026-09-26T00:04:00+00:00","timed":1,"id":""},{"show":"JAŸ-Z IN 8","net":"HBO","s":1,"e":4,"ep":"Chapter Four","ts":"2026-09-26T00:50:00+00:00","timed":1,"id":""},{"show":"Fightland","net":"STARZ","s":1,"e":8,"ep":"You Won't See Me Coming","ts":"2026-09-26T01:00:00+00:00","timed":1,"id":""},{"show":"Put a Ring on It: Cheathab","net":"Oprah Winfrey Network","s":1,"e":9,"ep":"The Final Decision","ts":"2026-09-26T01:00:00+00:00","timed":1,"id":""},{"show":"Scariest House in America","net":"HGTV","s":3,"e":2,"ep":"Horror in the Ominous Ozarks","ts":"2026-09-26T01:00:00+00:00","timed":1,"id":""},{"show":"Totally Funny Animals","net":"The CW","s":2,"e":23,"ep":"WILD Animals","ts":"2026-09-26T01:00:00+00:00","timed":1,"id":""},{"show":"Age Inappropriate","net":"WE tv","s":1,"e":8,"ep":"Commit or Quit","ts":"2026-09-26T01:00:00+00:00","timed":1,"id":""},{"show":"Totally Funny Animals","net":"The CW","s":2,"e":24,"ep":"Hip Hop Hooray","ts":"2026-09-26T01:30:00+00:00","timed":1,"id":""},{"show":"Anna Pigeon","net":"USA Network","s":1,"e":8,"ep":"The Death Grin","ts":"2026-09-26T02:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":1,"ep":"Clean Entry","ts":"2026-09-26T02:00:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":5,"ep":"Episode 5","ts":"2026-09-26T12:20:00+00:00","timed":1,"id":""},{"show":"Ask Us Anything","net":"jTBC","s":2026,"e":35,"ep":"Episode 546","ts":"2026-09-26T12:40:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":31,"ep":"Episode 31","ts":"2026-09-26T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":32,"ep":"Episode 32","ts":"2026-09-26T13:30:00+00:00","timed":1,"id":""},{"show":"Cook Like an Italian With Gabe Bertaccini","net":"Food Network","s":1,"e":6,"ep":"Italian Classics","ts":"2026-09-26T16:00:00+00:00","timed":1,"id":""},{"show":"SEC on ABC","net":"ABC","s":3,"e":3,"ep":"TBD at TBD","ts":"2026-09-26T19:30:00+00:00","timed":1,"id":""},{"show":"Farm Aid","net":"CNN","s":2026,"e":1,"ep":"Farm Aid 41","ts":"2026-09-26T23:00:00+00:00","timed":1,"id":""},{"show":"Svengoolie","net":"Me-TV","s":32,"e":40,"ep":"Night Of The Living Dead","ts":"2026-09-27T00:00:00+00:00","timed":1,"id":""},{"show":"Crossroad Springs","net":"Great American Pure Flix","s":2,"e":4,"ep":"Winds of Change","ts":"2026-09-27T00:00:00+00:00","timed":1,"id":""},{"show":"On Patrol: First Shift","net":"REELZ","s":5,"e":20,"ep":"#520","ts":"2026-09-27T00:00:00+00:00","timed":1,"id":""},{"show":"Have I Got News for You","net":"CNN","s":5,"e":3,"ep":"","ts":"2026-09-27T01:00:00+00:00","timed":1,"id":""},{"show":"Austin City Limits","net":"PBS","s":52,"e":4,"ep":"Miguel","ts":"2026-09-27T03:00:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":1,"ep":"Jalen Brunson / KATSEYE","ts":"2026-09-27T03:29:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":6,"ep":"Episode 6","ts":"2026-09-27T12:20:00+00:00","timed":1,"id":""},{"show":"RV There Yet?","net":"Discovery","s":5,"e":11,"ep":"Season Five Finale","ts":"2026-09-27T12:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":33,"ep":"Episode 33","ts":"2026-09-27T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":34,"ep":"Episode 34","ts":"2026-09-27T13:30:00+00:00","timed":1,"id":""},{"show":"Fantasy Focus Countdown","net":"ESPN2","s":2026,"e":4,"ep":"Episode 4","ts":"2026-09-27T14:00:00+00:00","timed":1,"id":""},{"show":"Sunday NFL Countdown","net":"ESPN","s":42,"e":3,"ep":"Week 3","ts":"2026-09-27T14:00:00+00:00","timed":1,"id":""},{"show":"One Piece","net":"Fuji TV","s":2026,"e":25,"ep":"Episode 1180","ts":"2026-09-27T14:15:00+00:00","timed":1,"id":""},{"show":"American Hostage","net":"MGM+","s":1,"e":3,"ep":"Magic Ticket Sweepstakes","ts":"2026-09-27T16:00:00+00:00","timed":0,"id":""},{"show":"The NFL Today","net":"CBS","s":2026,"e":3,"ep":"Week 3","ts":"2026-09-27T16:00:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":4,"ep":"Kansas City Chiefs at Miami Dolphins","ts":"2026-09-27T17:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":3,"ep":"Week 3","ts":"2026-09-27T17:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":5,"ep":"Baltimore Ravens at Dallas Cowboys","ts":"2026-09-27T20:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":4,"ep":"Week 3","ts":"2026-09-27T23:00:00+00:00","timed":1,"id":""},{"show":"America's Funniest Home Videos","net":"ABC","s":37,"e":1,"ep":"","ts":"2026-09-27T23:00:00+00:00","timed":1,"id":""},{"show":"MTV Video Music Awards","net":"CBS","s":2026,"e":1,"ep":"43rd Annual Video Music Awards","ts":"2026-09-27T23:30:00+00:00","timed":1,"id":""},{"show":"The Simpsons","net":"FOX","s":38,"e":1,"ep":"The Children's Book Job","ts":"2026-09-28T00:00:00+00:00","timed":1,"id":""},{"show":"America's Funniest Home Videos","net":"ABC","s":37,"e":2,"ep":"","ts":"2026-09-28T00:00:00+00:00","timed":1,"id":""},{"show":"90 Day Fiancé","net":"TLC","s":12,"e":21,"ep":"Tell All Part 3","ts":"2026-09-28T00:00:00+00:00","timed":1,"id":""},{"show":"Animal Control","net":"FOX","s":5,"e":1,"ep":"Seahawks and Piglets","ts":"2026-09-28T00:30:00+00:00","timed":1,"id":""},{"show":"Marble Hall Murders","net":"PBS","s":1,"e":4,"ep":"Episode 4","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"Universal Basic Guys","net":"FOX","s":3,"e":1,"ep":"Rhoda","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"High Value Target: The Hunt for Saddam","net":"TNT","s":1,"e":6,"ep":"The Devil You Know","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"Lanterns","net":"HBO","s":1,"e":7,"ep":"The Jordan Boys Legacy","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"The Detour with David Chang","net":"CNN","s":1,"e":3,"ep":"Dallas to San Antonio with Cristela Alonzo","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"Halloween Wars","net":"Food Network","s":16,"e":3,"ep":"Back from the Dead: Misfit Monsters","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"Paranormal Caught on Camera","net":"Travel Channel","s":12,"e":3,"ep":"The Green Lady of Scotland and More","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"Snapped","net":"Oxygen True Crime","s":36,"e":22,"ep":"Jennifer Reali","ts":"2026-09-28T01:00:00+00:00","timed":1,"id":""},{"show":"Grimsburg","net":"FOX","s":3,"e":1,"ep":"The Zast of Zus","ts":"2026-09-28T01:30:00+00:00","timed":1,"id":""},{"show":"Big Brother","net":"CBS","s":28,"e":35,"ep":"Episode 35","ts":"2026-09-28T01:30:00+00:00","timed":1,"id":""},{"show":"Youth","net":"HBO","s":1,"e":3,"ep":"Welcome to the Rat's Nest","ts":"2026-09-28T02:00:00+00:00","timed":1,"id":""},{"show":"A Tale Of Two Cities","net":"MGM+","s":1,"e":4,"ep":"Resurrection Man","ts":"2026-09-28T02:00:00+00:00","timed":1,"id":""},{"show":"The Detour with David Chang","net":"CNN","s":1,"e":4,"ep":"Miami to Key West with Eric Andre","ts":"2026-09-28T02:00:00+00:00","timed":1,"id":""},{"show":"In the Eye of the Storm","net":"Discovery","s":4,"e":12,"ep":"The 40-State Storm","ts":"2026-09-28T02:00:00+00:00","timed":1,"id":""},{"show":"President Curtis","net":"Adult Swim","s":1,"e":10,"ep":"Timber","ts":"2026-09-28T03:30:00+00:00","timed":1,"id":""},{"show":"Hey A.J.!","net":"Disney Junior","s":1,"e":54,"ep":"Halloween","ts":"2026-09-28T11:30:00+00:00","timed":1,"id":""},{"show":"Has Fallen","net":"Canal+","s":2,"e":4,"ep":"Episode 4","ts":"2026-09-28T12:00:00+00:00","timed":0,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":35,"ep":"Episode 35","ts":"2026-09-28T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":36,"ep":"Episode 36","ts":"2026-09-28T13:30:00+00:00","timed":1,"id":""},{"show":"Futurama","net":"Hulu","s":14,"e":10,"ep":"Final Ending: The Last Conclusion","ts":"2026-09-28T16:00:00+00:00","timed":0,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":178,"ep":"Episode 377","ts":"2026-09-28T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Live","net":"ESPN","s":28,"e":103,"ep":"Episode 103","ts":"2026-09-28T19:00:00+00:00","timed":1,"id":""},{"show":"Monday Night Countdown","net":"ESPN","s":34,"e":3,"ep":"Week 3","ts":"2026-09-28T22:00:00+00:00","timed":1,"id":""},{"show":"All American","net":"The CW","s":8,"e":13,"ep":"To Live and Die in L.A.","ts":"2026-09-29T00:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":4,"ep":"The Blind Auditions Part 4","ts":"2026-09-29T00:00:00+00:00","timed":1,"id":""},{"show":"Name That Tune","net":"FOX","s":6,"e":2,"ep":"Comedy Clash!","ts":"2026-09-29T00:00:00+00:00","timed":1,"id":""},{"show":"High Value Target: The Hunt for Saddam","net":"TNT","s":1,"e":7,"ep":"The Reckoning","ts":"2026-09-29T01:00:00+00:00","timed":1,"id":""},{"show":"Fatal Attraction","net":"TV One","s":17,"e":8,"ep":"The Boiling Point","ts":"2026-09-29T01:00:00+00:00","timed":1,"id":""},{"show":"It's Always Sunny in Philadelphia","net":"FXX","s":18,"e":8,"ep":"Mac and Dennis Tear Their ACLs","ts":"2026-09-29T01:00:00+00:00","timed":1,"id":""},{"show":"Halloween Baking Championship","net":"Food Network","s":12,"e":3,"ep":"Halloween Haunts","ts":"2026-09-29T01:00:00+00:00","timed":1,"id":""},{"show":"120 Hours Behind Bars","net":"Discovery","s":2,"e":11,"ep":"Tennessee Dyer County Jail","ts":"2026-09-29T01:00:00+00:00","timed":1,"id":""},{"show":"Line of Fire","net":"NBC","s":1,"e":2,"ep":"A Bigger Picture","ts":"2026-09-29T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":107,"ep":"","ts":"2026-09-29T03:00:00+00:00","timed":1,"id":""},{"show":"The Varnell Hill Show","net":"Paramount+","s":1,"e":6,"ep":"Episode 6","ts":"2026-09-29T12:00:00+00:00","timed":0,"id":"varnell"},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":37,"ep":"Episode 37","ts":"2026-09-29T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":38,"ep":"Episode 38","ts":"2026-09-29T13:30:00+00:00","timed":1,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":179,"ep":"Episode 378","ts":"2026-09-29T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Live","net":"ESPN","s":28,"e":104,"ep":"Episode 104","ts":"2026-09-29T20:00:00+00:00","timed":1,"id":""},{"show":"Dana White's Tuesday Night Contender Series","net":"ESPN+","s":10,"e":8,"ep":"Week 8","ts":"2026-09-29T23:00:00+00:00","timed":1,"id":""},{"show":"TrueSouth","net":"SEC Network","s":9,"e":2,"ep":"Arkansas Flyway","ts":"2026-09-30T00:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":4,"ep":"","ts":"2026-09-30T00:00:00+00:00","timed":1,"id":""},{"show":"Bobby's Triple Threat","net":"Food Network","s":5,"e":6,"ep":"Titans vs Chris Oh","ts":"2026-09-30T00:00:00+00:00","timed":1,"id":""},{"show":"Best Medicine","net":"FOX","s":2,"e":2,"ep":"Breakin' in Is Hard to Do","ts":"2026-09-30T00:00:00+00:00","timed":1,"id":""},{"show":"A Very Haunted Renovation","net":"HGTV","s":1,"e":3,"ep":"A Very Haunted Renovation","ts":"2026-09-30T00:00:00+00:00","timed":1,"id":""},{"show":"The Proof Is Out There","net":"History","s":6,"e":22,"ep":"Alien Radiation Burns, Real-Life Werewolf, Police UFO Recording","ts":"2026-09-30T01:00:00+00:00","timed":1,"id":""},{"show":"The Drop: A Snowfall Saga","net":"FX","s":1,"e":4,"ep":"The Big Push","ts":"2026-09-30T01:00:00+00:00","timed":1,"id":"drop"},{"show":"Doc","net":"FOX","s":3,"e":2,"ep":"Ready or Not","ts":"2026-09-30T01:00:00+00:00","timed":1,"id":""},{"show":"Bobby Flay's The Line","net":"Food Network","s":1,"e":4,"ep":"David Viana: Lita","ts":"2026-09-30T01:00:00+00:00","timed":1,"id":""},{"show":"1000-lb Sisters","net":"TLC","s":9,"e":5,"ep":"Amy Was Afraid, She Was Petrified","ts":"2026-09-30T01:00:00+00:00","timed":1,"id":""},{"show":"Signs of a Psychopath","net":"Investigation Discovery","s":11,"e":12,"ep":"The Biggest Adrenaline Rush","ts":"2026-09-30T01:00:00+00:00","timed":1,"id":"signs"},{"show":"Signs of a Psychopath","net":"Investigation Discovery","s":11,"e":13,"ep":"That's What You Do With a Knife","ts":"2026-09-30T01:30:00+00:00","timed":1,"id":"signs"},{"show":"R.J. Decker","net":"ABC","s":2,"e":3,"ep":"Arms and Armadillos","ts":"2026-09-30T02:00:00+00:00","timed":1,"id":""},{"show":"Cocktail Wars","net":"E!","s":1,"e":8,"ep":"Primetime Cocktails","ts":"2026-09-30T02:00:00+00:00","timed":1,"id":""},{"show":"The Proof Is Out There","net":"History","s":6,"e":23,"ep":"Helicopter UFO Chase, Mysterious Lost City, and Historic Bigfoot Photo","ts":"2026-09-30T02:03:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":108,"ep":"","ts":"2026-09-30T03:00:00+00:00","timed":1,"id":""},{"show":"Ted Lasso","net":"Apple TV","s":4,"e":9,"ep":"Episode 9","ts":"2026-09-30T12:00:00+00:00","timed":0,"id":""},{"show":"Last Seen","net":"Apple TV","s":1,"e":5,"ep":"The Prophet","ts":"2026-09-30T12:00:00+00:00","timed":0,"id":""},{"show":"Slow Horses","net":"Apple TV","s":6,"e":3,"ep":"Resurrection","ts":"2026-09-30T12:00:00+00:00","timed":0,"id":""},{"show":"Re:Zero kara Hajimeru Isekai Seikatsu","net":"AT-X","s":4,"e":19,"ep":"Episode 19 (Season Finale)","ts":"2026-09-30T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":39,"ep":"Episode 39","ts":"2026-09-30T13:30:00+00:00","timed":1,"id":""},{"show":"Against the Current","net":"Tencent QQ","s":1,"e":40,"ep":"Episode 40","ts":"2026-09-30T13:30:00+00:00","timed":1,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":180,"ep":"Episode 379","ts":"2026-09-30T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Live","net":"ESPN","s":28,"e":105,"ep":"Episode 105","ts":"2026-09-30T20:00:00+00:00","timed":1,"id":""},{"show":"WNBA Countdown","net":"ESPN","s":5,"e":17,"ep":"Episode 17","ts":"2026-09-30T23:00:00+00:00","timed":1,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":2,"ep":"","ts":"2026-10-01T00:00:00+00:00","timed":1,"id":""},{"show":"Tyler Perry's The Oval","net":"BET","s":7,"e":22,"ep":"Episode 22","ts":"2026-10-01T01:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":11,"ep":"Stone Age Masterpiece","ts":"2026-10-01T01:00:00+00:00","timed":1,"id":""},{"show":"Totally ‘90s House","net":"HGTV","s":1,"e":6,"ep":"Episode 6","ts":"2026-10-01T01:00:00+00:00","timed":1,"id":""},{"show":"The Great American Road Rally: Celebrity Edition","net":"The CW","s":1,"e":3,"ep":"Three-State Run","ts":"2026-10-01T01:00:00+00:00","timed":1,"id":""},{"show":"ER: Caught on Camera","net":"TLC","s":1,"e":7,"ep":"Episode 4","ts":"2026-10-01T01:00:00+00:00","timed":1,"id":""},{"show":"The Ark","net":"Syfy","s":3,"e":10,"ep":"It All Happened So Fast","ts":"2026-10-01T02:00:00+00:00","timed":1,"id":""},{"show":"South Park","net":"Comedy Central","s":29,"e":2,"ep":"","ts":"2026-10-01T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":109,"ep":"","ts":"2026-10-01T03:00:00+00:00","timed":1,"id":""},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":181,"ep":"Episode 380","ts":"2026-10-01T18:00:00+00:00","timed":1,"id":""},{"show":"WNBA Countdown","net":"ESPN","s":5,"e":18,"ep":"Episode 18","ts":"2026-10-01T22:30:00+00:00","timed":1,"id":""},{"show":"Big Brother","net":"CBS","s":28,"e":36,"ep":"Episode 36","ts":"2026-10-02T00:00:00+00:00","timed":1,"id":""},{"show":"Hell's Kitchen","net":"FOX","s":25,"e":2,"ep":"A Tale of Two Kitchens","ts":"2026-10-02T00:00:00+00:00","timed":1,"id":""},{"show":"The Real Housewives of Orange County","net":"Bravo","s":20,"e":13,"ep":"","ts":"2026-10-02T00:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":4,"ep":"Is That All There Is?","ts":"2026-10-02T01:00:00+00:00","timed":1,"id":""},{"show":"TNA iMPACT!","net":"AMC","s":2026,"e":40,"ep":"Episode 40","ts":"2026-10-02T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":5,"ep":"Date Night","ts":"2026-10-02T01:30:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":6,"ep":"The Return of Devil's Night","ts":"2026-10-02T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":110,"ep":"","ts":"2026-10-02T03:00:00+00:00","timed":1,"id":""},{"show":"Dark Matter","net":"Apple TV","s":2,"e":6,"ep":"What the Universe Is Made Of","ts":"2026-10-02T12:00:00+00:00","timed":0,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":3,"ep":"Bonzo Goes to Bitburg","ts":"2026-10-02T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"Beyond the Gates","net":"CBS","s":2026,"e":182,"ep":"Episode 381","ts":"2026-10-02T18:00:00+00:00","timed":1,"id":""},{"show":"Cook's Country from America's Test Kitchen","net":"PBS","s":19,"e":6,"ep":"Dinners With Big, Bold Flavors","ts":"2026-10-02T19:30:00+00:00","timed":1,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":40,"ep":"#1413 - Ball Arena in Denver, CO","ts":"2026-10-03T00:00:00+00:00","timed":1,"id":""},{"show":"JAŸ-Z IN 8","net":"HBO","s":1,"e":5,"ep":"Chapter Five","ts":"2026-10-03T00:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":3,"ep":"Rabbits Don't Swim","ts":"2026-10-03T00:00:00+00:00","timed":1,"id":""},{"show":"JAŸ-Z IN 8","net":"HBO","s":1,"e":6,"ep":"Chapter Six","ts":"2026-10-03T00:45:00+00:00","timed":1,"id":""},{"show":"Scariest House in America","net":"HGTV","s":3,"e":3,"ep":"The Eeriest of the East","ts":"2026-10-03T01:00:00+00:00","timed":1,"id":""},{"show":"Diners, Drive-Ins and Dives","net":"Food Network","s":2026,"e":17,"ep":"Sandwiches, Seafood & Soba Noodles","ts":"2026-10-03T01:00:00+00:00","timed":1,"id":""},{"show":"Anna Pigeon","net":"USA Network","s":1,"e":9,"ep":"Nature Nurture","ts":"2026-10-03T02:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":2,"ep":"Not One But Two","ts":"2026-10-03T02:00:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":7,"ep":"Episode 7","ts":"2026-10-03T12:20:00+00:00","timed":1,"id":""},{"show":"Ask Us Anything","net":"jTBC","s":2026,"e":36,"ep":"Episode 547","ts":"2026-10-03T12:40:00+00:00","timed":1,"id":""},{"show":"SEC on ABC","net":"ABC","s":3,"e":4,"ep":"TBD at TBD","ts":"2026-10-03T19:30:00+00:00","timed":1,"id":""},{"show":"Crossroad Springs","net":"Great American Pure Flix","s":2,"e":5,"ep":"The Waiting Game","ts":"2026-10-04T00:00:00+00:00","timed":1,"id":""},{"show":"Have I Got News for You","net":"CNN","s":5,"e":4,"ep":"","ts":"2026-10-04T01:00:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":2,"ep":"Dakota Johnson / Turnstile","ts":"2026-10-04T03:29:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":8,"ep":"Episode 8","ts":"2026-10-04T12:20:00+00:00","timed":1,"id":""},{"show":"Sunday NFL Countdown","net":"ESPN","s":42,"e":4,"ep":"Week 4","ts":"2026-10-04T14:00:00+00:00","timed":1,"id":""},{"show":"One Piece","net":"Fuji TV","s":2026,"e":26,"ep":"Episode 1181","ts":"2026-10-04T14:15:00+00:00","timed":1,"id":""},{"show":"American Hostage","net":"MGM+","s":1,"e":4,"ep":"A Taste of Indianapolis","ts":"2026-10-04T16:00:00+00:00","timed":0,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":6,"ep":"New England Patriots at Buffalo Bills","ts":"2026-10-04T17:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":4,"ep":"Week 4","ts":"2026-10-04T17:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":7,"ep":"Denver Broncos at San Francisco 49ers","ts":"2026-10-04T20:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":5,"ep":"Week 4","ts":"2026-10-04T23:00:00+00:00","timed":1,"id":""},{"show":"60 Minutes","net":"CBS","s":59,"e":3,"ep":"Episode 3","ts":"2026-10-04T23:00:00+00:00","timed":1,"id":""},{"show":"The Simpsons","net":"FOX","s":38,"e":2,"ep":"Diary of a Chimpy Kid","ts":"2026-10-05T00:00:00+00:00","timed":1,"id":""},{"show":"Animal Control","net":"FOX","s":5,"e":2,"ep":"Crows and Lizard Legs","ts":"2026-10-05T00:31:00+00:00","timed":1,"id":""},{"show":"Marble Hall Murders","net":"PBS","s":1,"e":5,"ep":"Episode 5","ts":"2026-10-05T01:00:00+00:00","timed":1,"id":""},{"show":"High Value Target: The Hunt for Saddam","net":"TNT","s":1,"e":8,"ep":"Debriefing the President","ts":"2026-10-05T01:00:00+00:00","timed":1,"id":""},{"show":"Lanterns","net":"HBO","s":1,"e":8,"ep":"","ts":"2026-10-05T01:00:00+00:00","timed":1,"id":""},{"show":"The Detour with David Chang","net":"CNN","s":1,"e":5,"ep":"","ts":"2026-10-05T01:00:00+00:00","timed":1,"id":""},{"show":"Halloween Wars","net":"Food Network","s":16,"e":4,"ep":"Back from the Dead: Storybook Nightmares","ts":"2026-10-05T01:00:00+00:00","timed":1,"id":""},{"show":"Universal Basic Guys","net":"FOX","s":3,"e":2,"ep":"La Gloire Du Bouffon","ts":"2026-10-05T01:00:00+00:00","timed":1,"id":""},{"show":"Grimsburg","net":"FOX","s":3,"e":2,"ep":"Stanbiscuit","ts":"2026-10-05T01:31:00+00:00","timed":1,"id":""},{"show":"Youth","net":"HBO","s":1,"e":4,"ep":"Episode 4","ts":"2026-10-05T02:00:00+00:00","timed":1,"id":""},{"show":"The Detour with David Chang","net":"CNN","s":1,"e":6,"ep":"","ts":"2026-10-05T02:00:00+00:00","timed":1,"id":""},{"show":"Has Fallen","net":"Canal+","s":2,"e":5,"ep":"Episode 5","ts":"2026-10-05T12:00:00+00:00","timed":0,"id":""},{"show":"Monday Night Countdown","net":"ESPN","s":34,"e":4,"ep":"Week 4","ts":"2026-10-05T22:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":5,"ep":"","ts":"2026-10-06T00:00:00+00:00","timed":1,"id":""},{"show":"FBI","net":"CBS","s":9,"e":1,"ep":"Rendition","ts":"2026-10-06T00:00:00+00:00","timed":1,"id":""},{"show":"CIA","net":"CBS","s":2,"e":1,"ep":"The Deep","ts":"2026-10-06T01:00:00+00:00","timed":1,"id":""},{"show":"Fatal Attraction","net":"TV One","s":17,"e":9,"ep":"Nothing to Lose","ts":"2026-10-06T01:00:00+00:00","timed":1,"id":""},{"show":"It's Always Sunny in Philadelphia","net":"FXX","s":18,"e":9,"ep":"Frank's Team: A Dark Day for Baseball","ts":"2026-10-06T01:00:00+00:00","timed":1,"id":""},{"show":"Halloween Baking Championship","net":"Food Network","s":12,"e":4,"ep":"Who's Ruining Your Ruin?","ts":"2026-10-06T01:00:00+00:00","timed":1,"id":""},{"show":"Line of Fire","net":"NBC","s":1,"e":3,"ep":"There Are Two Wolves","ts":"2026-10-06T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":111,"ep":"","ts":"2026-10-06T03:00:00+00:00","timed":1,"id":""},{"show":"The Varnell Hill Show","net":"Paramount+","s":1,"e":7,"ep":"Episode 7","ts":"2026-10-06T12:00:00+00:00","timed":0,"id":"varnell"},{"show":"Dana White's Tuesday Night Contender Series","net":"ESPN+","s":10,"e":9,"ep":"Week 9","ts":"2026-10-06T23:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":6,"ep":"","ts":"2026-10-07T00:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":5,"ep":"","ts":"2026-10-07T00:00:00+00:00","timed":1,"id":""},{"show":"Bobby's Triple Threat","net":"Food Network","s":5,"e":7,"ep":"Titans vs Yia Vang","ts":"2026-10-07T00:00:00+00:00","timed":1,"id":""},{"show":"Best Medicine","net":"FOX","s":2,"e":3,"ep":"","ts":"2026-10-07T00:00:00+00:00","timed":1,"id":""},{"show":"A Very Haunted Renovation","net":"HGTV","s":1,"e":4,"ep":"A Game of Haunts","ts":"2026-10-07T00:00:00+00:00","timed":1,"id":""},{"show":"Doc","net":"FOX","s":3,"e":3,"ep":"","ts":"2026-10-07T01:00:00+00:00","timed":1,"id":""},{"show":"The Drop: A Snowfall Saga","net":"FX","s":1,"e":5,"ep":"Homecoming","ts":"2026-10-07T01:00:00+00:00","timed":1,"id":"drop"},{"show":"Bobby Flay's The Line","net":"Food Network","s":1,"e":5,"ep":"Spike Mendelsohn: Good Stuff Eatery","ts":"2026-10-07T01:00:00+00:00","timed":1,"id":""},{"show":"1000-lb Sisters","net":"TLC","s":9,"e":6,"ep":"Episode 6","ts":"2026-10-07T01:00:00+00:00","timed":1,"id":""},{"show":"Cocktail Wars","net":"E!","s":1,"e":9,"ep":"","ts":"2026-10-07T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":112,"ep":"","ts":"2026-10-07T03:00:00+00:00","timed":1,"id":""},{"show":"Ted Lasso","net":"Apple TV","s":4,"e":10,"ep":"Episode 10","ts":"2026-10-07T12:00:00+00:00","timed":0,"id":""},{"show":"Last Seen","net":"Apple TV","s":1,"e":6,"ep":"The Choice","ts":"2026-10-07T12:00:00+00:00","timed":0,"id":""},{"show":"Slow Horses","net":"Apple TV","s":6,"e":4,"ep":"Lost and Found","ts":"2026-10-07T12:00:00+00:00","timed":0,"id":""},{"show":"WNBA Countdown","net":"ESPN","s":5,"e":19,"ep":"Episode 19","ts":"2026-10-07T23:00:00+00:00","timed":1,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":3,"ep":"","ts":"2026-10-08T00:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":12,"ep":"Space Wars","ts":"2026-10-08T01:00:00+00:00","timed":1,"id":""},{"show":"ER: Caught on Camera","net":"TLC","s":1,"e":8,"ep":"Episode 8","ts":"2026-10-08T01:00:00+00:00","timed":1,"id":""},{"show":"The Ark","net":"Syfy","s":3,"e":11,"ep":"A Pretty Nasty One","ts":"2026-10-08T02:00:00+00:00","timed":1,"id":""},{"show":"Chicago P.D.","net":"NBC","s":14,"e":1,"ep":"Demolition","ts":"2026-10-08T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":113,"ep":"","ts":"2026-10-08T03:00:00+00:00","timed":1,"id":""},{"show":"College Football Countdown","net":"ESPN","s":21,"e":8,"ep":"Week 5","ts":"2026-10-08T23:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":5,"ep":"Wake of the Living Dead","ts":"2026-10-09T00:00:00+00:00","timed":1,"id":""},{"show":"The Real Housewives of Orange County","net":"Bravo","s":20,"e":14,"ep":"","ts":"2026-10-09T00:00:00+00:00","timed":1,"id":""},{"show":"Law & Order: Special Victims Unit","net":"NBC","s":28,"e":1,"ep":"Volition","ts":"2026-10-09T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":7,"ep":"The Baddest Witch of Them All","ts":"2026-10-09T01:00:00+00:00","timed":1,"id":""},{"show":"TNA iMPACT!","net":"AMC","s":2026,"e":41,"ep":"Episode 41","ts":"2026-10-09T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":8,"ep":"Hell No","ts":"2026-10-09T01:30:00+00:00","timed":1,"id":""},{"show":"Law & Order","net":"NBC","s":26,"e":1,"ep":"Ghost in the Machine","ts":"2026-10-09T02:00:00+00:00","timed":1,"id":""},{"show":"The Daily Show","net":"Comedy Central","s":4,"e":114,"ep":"","ts":"2026-10-09T03:00:00+00:00","timed":1,"id":""},{"show":"Dark Matter","net":"Apple TV","s":2,"e":7,"ep":"The Pyramid","ts":"2026-10-09T12:00:00+00:00","timed":0,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":4,"ep":"Blank Curtain","ts":"2026-10-09T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":41,"ep":"#1414 - Cajundome in Lafayette, LA","ts":"2026-10-10T00:00:00+00:00","timed":1,"id":""},{"show":"JAŸ-Z IN 8","net":"HBO","s":1,"e":7,"ep":"Chapter Seven","ts":"2026-10-10T00:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":4,"ep":"A Portion of My Soul","ts":"2026-10-10T00:00:00+00:00","timed":1,"id":""},{"show":"JAŸ-Z IN 8","net":"HBO","s":1,"e":8,"ep":"Chapter Eight","ts":"2026-10-10T00:47:00+00:00","timed":1,"id":""},{"show":"Scariest House in America","net":"HGTV","s":3,"e":4,"ep":"Scares of the Mysterious Midwest","ts":"2026-10-10T01:00:00+00:00","timed":1,"id":""},{"show":"Triple D Nation","net":"Food Network","s":8,"e":9,"ep":"Triple D Nation: Burgers, Breakfast and Barbecue","ts":"2026-10-10T01:00:00+00:00","timed":1,"id":""},{"show":"Anna Pigeon","net":"USA Network","s":1,"e":10,"ep":"Episode 10","ts":"2026-10-10T02:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":3,"ep":"The Project","ts":"2026-10-10T02:00:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":9,"ep":"Episode 9","ts":"2026-10-10T12:20:00+00:00","timed":1,"id":""},{"show":"SEC on ABC","net":"ABC","s":3,"e":5,"ep":"TBD at TBD","ts":"2026-10-10T19:30:00+00:00","timed":1,"id":""},{"show":"Notre Dame Football on NBC","net":"NBC","s":36,"e":4,"ep":"Stanford Cardinal at Notre Dame Fighting Irish","ts":"2026-10-10T19:30:00+00:00","timed":1,"id":""},{"show":"Have I Got News for You","net":"CNN","s":5,"e":5,"ep":"","ts":"2026-10-11T01:00:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":3,"ep":"Shane Gillis / Rosalía","ts":"2026-10-11T03:29:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":10,"ep":"Episode 10","ts":"2026-10-11T12:20:00+00:00","timed":1,"id":""},{"show":"American Hostage","net":"MGM+","s":1,"e":5,"ep":"WIBC Mystery Science Theater","ts":"2026-10-11T16:00:00+00:00","timed":0,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":8,"ep":"Indianapolis Colts at Pittsburgh Steelers","ts":"2026-10-11T17:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":5,"ep":"Week 5","ts":"2026-10-11T17:30:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":6,"ep":"Week 5","ts":"2026-10-11T23:00:00+00:00","timed":1,"id":""},{"show":"Marble Hall Murders","net":"PBS","s":1,"e":6,"ep":"Episode 6","ts":"2026-10-12T01:00:00+00:00","timed":1,"id":""},{"show":"Halloween Wars","net":"Food Network","s":16,"e":5,"ep":"Back from the Dead: Nightmare Pet Shop","ts":"2026-10-12T01:00:00+00:00","timed":1,"id":""},{"show":"Youth","net":"HBO","s":1,"e":5,"ep":"Episode 5","ts":"2026-10-12T02:00:00+00:00","timed":1,"id":""},{"show":"Has Fallen","net":"Canal+","s":2,"e":6,"ep":"Episode 6","ts":"2026-10-12T12:00:00+00:00","timed":0,"id":""},{"show":"Monday Night Countdown","net":"ESPN","s":34,"e":5,"ep":"Week 5","ts":"2026-10-12T22:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":7,"ep":"","ts":"2026-10-13T00:00:00+00:00","timed":1,"id":""},{"show":"FBI","net":"CBS","s":9,"e":2,"ep":"Omissions","ts":"2026-10-13T00:00:00+00:00","timed":1,"id":""},{"show":"Fatal Attraction","net":"TV One","s":17,"e":10,"ep":"Sudden Silence","ts":"2026-10-13T01:00:00+00:00","timed":1,"id":""},{"show":"It's Always Sunny in Philadelphia","net":"FXX","s":18,"e":10,"ep":"","ts":"2026-10-13T01:00:00+00:00","timed":1,"id":""},{"show":"Halloween Baking Championship","net":"Food Network","s":12,"e":5,"ep":"Doll Trouble","ts":"2026-10-13T01:00:00+00:00","timed":1,"id":""},{"show":"CIA","net":"CBS","s":2,"e":2,"ep":"Dead Drop","ts":"2026-10-13T01:00:00+00:00","timed":1,"id":""},{"show":"Line of Fire","net":"NBC","s":1,"e":4,"ep":"Paper Trail","ts":"2026-10-13T02:00:00+00:00","timed":1,"id":""},{"show":"The Varnell Hill Show","net":"Paramount+","s":1,"e":8,"ep":"Episode 8","ts":"2026-10-13T12:00:00+00:00","timed":0,"id":"varnell"},{"show":"Dana White's Tuesday Night Contender Series","net":"ESPN+","s":10,"e":10,"ep":"Week 10","ts":"2026-10-13T23:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":8,"ep":"","ts":"2026-10-14T00:00:00+00:00","timed":1,"id":""},{"show":"TrueSouth","net":"SEC Network","s":9,"e":3,"ep":"Buford Highway, Atlanta","ts":"2026-10-14T00:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":6,"ep":"","ts":"2026-10-14T00:00:00+00:00","timed":1,"id":""},{"show":"Bobby's Triple Threat","net":"Food Network","s":5,"e":8,"ep":"Titans vs Angelo Sosa","ts":"2026-10-14T00:00:00+00:00","timed":1,"id":""},{"show":"Best Medicine","net":"FOX","s":2,"e":4,"ep":"","ts":"2026-10-14T00:00:00+00:00","timed":1,"id":""},{"show":"A Very Haunted Renovation","net":"HGTV","s":1,"e":5,"ep":"The Exterior Exorcism","ts":"2026-10-14T00:00:00+00:00","timed":1,"id":""},{"show":"Doc","net":"FOX","s":3,"e":4,"ep":"","ts":"2026-10-14T01:00:00+00:00","timed":1,"id":""},{"show":"The Drop: A Snowfall Saga","net":"FX","s":1,"e":6,"ep":"Exit Wounds","ts":"2026-10-14T01:00:00+00:00","timed":1,"id":"drop"},{"show":"Bobby Flay's The Line","net":"Food Network","s":1,"e":6,"ep":"Leia Gaccione: The Saint Clair","ts":"2026-10-14T01:00:00+00:00","timed":1,"id":""},{"show":"1000-lb Sisters","net":"TLC","s":9,"e":7,"ep":"Episode 7","ts":"2026-10-14T01:00:00+00:00","timed":1,"id":""},{"show":"Cocktail Wars","net":"E!","s":1,"e":10,"ep":"","ts":"2026-10-14T02:00:00+00:00","timed":1,"id":""},{"show":"R.J. Decker","net":"ABC","s":2,"e":4,"ep":"The Angler","ts":"2026-10-14T02:00:00+00:00","timed":1,"id":""},{"show":"Slow Horses","net":"Apple TV","s":6,"e":5,"ep":"Sayonara","ts":"2026-10-14T12:00:00+00:00","timed":0,"id":""},{"show":"WNBA Countdown","net":"ESPN","s":5,"e":20,"ep":"Episode 20","ts":"2026-10-14T23:30:00+00:00","timed":1,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":4,"ep":"","ts":"2026-10-15T00:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":13,"ep":"Evolution: Brain Power","ts":"2026-10-15T01:00:00+00:00","timed":1,"id":""},{"show":"The Ark","net":"Syfy","s":3,"e":12,"ep":"We Can't Save Everyone","ts":"2026-10-15T02:00:00+00:00","timed":1,"id":""},{"show":"South Park","net":"Comedy Central","s":29,"e":3,"ep":"","ts":"2026-10-15T02:00:00+00:00","timed":1,"id":""},{"show":"Chicago P.D.","net":"NBC","s":14,"e":2,"ep":"","ts":"2026-10-15T02:00:00+00:00","timed":1,"id":""},{"show":"College Football Countdown","net":"ESPN","s":21,"e":9,"ep":"Week 6","ts":"2026-10-15T23:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":6,"ep":"","ts":"2026-10-16T00:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":9,"ep":"The Devil Is in the Details","ts":"2026-10-16T01:00:00+00:00","timed":1,"id":""},{"show":"TNA iMPACT!","net":"AMC","s":2026,"e":42,"ep":"Episode 42","ts":"2026-10-16T01:00:00+00:00","timed":1,"id":""},{"show":"Law & Order: Special Victims Unit","net":"NBC","s":28,"e":2,"ep":"","ts":"2026-10-16T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":10,"ep":"The Prodigal Son","ts":"2026-10-16T01:30:00+00:00","timed":1,"id":""},{"show":"Grey's Anatomy","net":"ABC","s":23,"e":1,"ep":"","ts":"2026-10-16T02:00:00+00:00","timed":1,"id":""},{"show":"Dark Matter","net":"Apple TV","s":2,"e":8,"ep":"The Basic Oneness of Everything","ts":"2026-10-16T12:00:00+00:00","timed":0,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":5,"ep":"Birdland","ts":"2026-10-16T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":42,"ep":"#1415 - Golden 1 Center in Sacramento, CA","ts":"2026-10-17T00:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":5,"ep":"Forgive Me, Father","ts":"2026-10-17T00:00:00+00:00","timed":1,"id":""},{"show":"Scariest House in America","net":"HGTV","s":3,"e":5,"ep":"Nightmares in New England","ts":"2026-10-17T01:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":4,"ep":"Hate Crime","ts":"2026-10-17T02:00:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":11,"ep":"Episode 11","ts":"2026-10-17T12:20:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":12,"ep":"Episode 12","ts":"2026-10-18T12:20:00+00:00","timed":1,"id":""},{"show":"American Hostage","net":"MGM+","s":1,"e":6,"ep":"Moon News and Markets","ts":"2026-10-18T16:00:00+00:00","timed":0,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":9,"ep":"Carolina Panthers at Philadelphia Eagles","ts":"2026-10-18T17:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":6,"ep":"Week 6","ts":"2026-10-18T17:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":10,"ep":"Los Angeles Chargers at Kansas City Chiefs","ts":"2026-10-18T20:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":7,"ep":"Week 6","ts":"2026-10-18T23:00:00+00:00","timed":1,"id":""},{"show":"Halloween Wars","net":"Food Network","s":16,"e":6,"ep":"Back from the Dead: Final Four","ts":"2026-10-19T01:00:00+00:00","timed":1,"id":""},{"show":"Youth","net":"HBO","s":1,"e":6,"ep":"Episode 6","ts":"2026-10-19T02:00:00+00:00","timed":1,"id":""},{"show":"Has Fallen","net":"Canal+","s":2,"e":7,"ep":"Episode 7","ts":"2026-10-19T12:00:00+00:00","timed":0,"id":""},{"show":"Monday Night Countdown","net":"ESPN","s":34,"e":6,"ep":"Week 6","ts":"2026-10-19T22:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":9,"ep":"","ts":"2026-10-20T00:00:00+00:00","timed":1,"id":""},{"show":"FBI","net":"CBS","s":9,"e":3,"ep":"White Rock","ts":"2026-10-20T00:00:00+00:00","timed":1,"id":""},{"show":"Fatal Attraction","net":"TV One","s":17,"e":11,"ep":"Monsters in the Night","ts":"2026-10-20T01:00:00+00:00","timed":1,"id":""},{"show":"Halloween Baking Championship","net":"Food Network","s":12,"e":6,"ep":"Masters of the Macabre","ts":"2026-10-20T01:00:00+00:00","timed":1,"id":""},{"show":"CIA","net":"CBS","s":2,"e":3,"ep":"Radio Active","ts":"2026-10-20T01:00:00+00:00","timed":1,"id":""},{"show":"Line of Fire","net":"NBC","s":1,"e":5,"ep":"Episode 5","ts":"2026-10-20T02:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":7,"ep":"","ts":"2026-10-21T00:00:00+00:00","timed":1,"id":""},{"show":"Bobby's Triple Threat","net":"Food Network","s":5,"e":9,"ep":"Titans vs Sara Bradley","ts":"2026-10-21T00:00:00+00:00","timed":1,"id":""},{"show":"A Very Haunted Renovation","net":"HGTV","s":1,"e":6,"ep":"The Final Fright","ts":"2026-10-21T00:00:00+00:00","timed":1,"id":""},{"show":"Doc","net":"FOX","s":3,"e":5,"ep":"","ts":"2026-10-21T01:00:00+00:00","timed":1,"id":""},{"show":"The Drop: A Snowfall Saga","net":"FX","s":1,"e":7,"ep":"Blood In, Blood Out","ts":"2026-10-21T01:00:00+00:00","timed":1,"id":"drop"},{"show":"Bobby Flay's The Line","net":"Food Network","s":1,"e":7,"ep":"Byron Gomez: Bruto","ts":"2026-10-21T01:00:00+00:00","timed":1,"id":""},{"show":"1000-lb Sisters","net":"TLC","s":9,"e":8,"ep":"Episode 8","ts":"2026-10-21T01:00:00+00:00","timed":1,"id":""},{"show":"Slow Horses","net":"Apple TV","s":6,"e":6,"ep":"Judgment Day","ts":"2026-10-21T12:00:00+00:00","timed":0,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":5,"ep":"","ts":"2026-10-22T00:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":14,"ep":"Evolution: Need to Feed","ts":"2026-10-22T01:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":7,"ep":"","ts":"2026-10-23T00:00:00+00:00","timed":1,"id":""},{"show":"TNA iMPACT!","net":"AMC","s":2026,"e":43,"ep":"Episode 43","ts":"2026-10-23T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":11,"ep":"Madison's Happy Ending","ts":"2026-10-23T01:00:00+00:00","timed":1,"id":""},{"show":"Law & Order: Special Victims Unit","net":"NBC","s":28,"e":3,"ep":"","ts":"2026-10-23T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":12,"ep":"Sisters in Arms","ts":"2026-10-23T01:30:00+00:00","timed":1,"id":""},{"show":"Dark Matter","net":"Apple TV","s":2,"e":9,"ep":"How to Build the Box","ts":"2026-10-23T12:00:00+00:00","timed":0,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":6,"ep":"A Different Corner","ts":"2026-10-23T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":43,"ep":"#1416 - Toyota Arena in Ontario, CA","ts":"2026-10-24T00:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":6,"ep":"Small Mercies","ts":"2026-10-24T00:00:00+00:00","timed":1,"id":""},{"show":"Scariest House in America","net":"HGTV","s":3,"e":6,"ep":"From Frightening to Fabulous","ts":"2026-10-24T01:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":5,"ep":"Edgemount","ts":"2026-10-24T02:00:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":13,"ep":"Episode 13","ts":"2026-10-24T12:20:00+00:00","timed":1,"id":""},{"show":"A Love Other Than Yours","net":"KBS2","s":1,"e":14,"ep":"Episode 14","ts":"2026-10-25T12:20:00+00:00","timed":1,"id":""},{"show":"American Hostage","net":"MGM+","s":1,"e":7,"ep":"Tomorrow Is Here","ts":"2026-10-25T16:00:00+00:00","timed":0,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":11,"ep":"Indianapolis Colts at Minnesota Vikings","ts":"2026-10-25T17:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":7,"ep":"Week 7","ts":"2026-10-25T17:30:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":8,"ep":"Week 7","ts":"2026-10-25T23:00:00+00:00","timed":1,"id":""},{"show":"Youth","net":"HBO","s":1,"e":7,"ep":"Episode 7","ts":"2026-10-26T02:00:00+00:00","timed":1,"id":""},{"show":"Has Fallen","net":"Canal+","s":2,"e":8,"ep":"Episode 8","ts":"2026-10-26T12:00:00+00:00","timed":0,"id":""},{"show":"Monday Night Countdown","net":"ESPN","s":34,"e":7,"ep":"Week 7","ts":"2026-10-26T22:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":10,"ep":"","ts":"2026-10-27T00:00:00+00:00","timed":1,"id":""},{"show":"Fatal Attraction","net":"TV One","s":17,"e":12,"ep":"No Perfect Murder","ts":"2026-10-27T01:00:00+00:00","timed":1,"id":""},{"show":"Line of Fire","net":"NBC","s":1,"e":6,"ep":"Episode 6","ts":"2026-10-27T02:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":8,"ep":"","ts":"2026-10-28T00:00:00+00:00","timed":1,"id":""},{"show":"The Drop: A Snowfall Saga","net":"FX","s":1,"e":8,"ep":"Hercules","ts":"2026-10-28T01:00:00+00:00","timed":1,"id":"drop"},{"show":"Survivor","net":"CBS","s":51,"e":6,"ep":"","ts":"2026-10-29T00:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":15,"ep":"Evolution: Body Builders","ts":"2026-10-29T01:00:00+00:00","timed":1,"id":""},{"show":"South Park","net":"Comedy Central","s":29,"e":4,"ep":"","ts":"2026-10-29T02:00:00+00:00","timed":1,"id":""},{"show":"College Football Countdown","net":"ESPN","s":21,"e":10,"ep":"Week 7A","ts":"2026-10-29T23:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":8,"ep":"","ts":"2026-10-30T00:00:00+00:00","timed":1,"id":""},{"show":"TNA iMPACT!","net":"AMC","s":2026,"e":44,"ep":"Episode 44","ts":"2026-10-30T01:00:00+00:00","timed":1,"id":""},{"show":"American Horror Story","net":"FX","s":13,"e":13,"ep":"Devil of a Good Time","ts":"2026-10-30T01:00:00+00:00","timed":1,"id":""},{"show":"Law & Order: Special Victims Unit","net":"NBC","s":28,"e":4,"ep":"","ts":"2026-10-30T01:00:00+00:00","timed":1,"id":""},{"show":"Dark Matter","net":"Apple TV","s":2,"e":10,"ep":"No Quiet Life","ts":"2026-10-30T12:00:00+00:00","timed":0,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":7,"ep":"Episode 7","ts":"2026-10-30T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"College Football Countdown","net":"ESPN","s":21,"e":11,"ep":"Week 7B","ts":"2026-10-30T23:00:00+00:00","timed":1,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":44,"ep":"#1417 - Charleston Coliseum in Charleston, WV","ts":"2026-10-31T00:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":7,"ep":"Heart of the Highlands","ts":"2026-10-31T00:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":6,"ep":"Molotov Cocktail Attire","ts":"2026-10-31T02:00:00+00:00","timed":1,"id":""},{"show":"Cook's Country from America's Test Kitchen","net":"PBS","s":19,"e":7,"ep":"Takeout at Home","ts":"2026-10-31T19:30:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":4,"ep":"Inde Navarrette / Gracie Abrams","ts":"2026-11-01T03:29:00+00:00","timed":1,"id":""},{"show":"American Hostage","net":"MGM+","s":1,"e":8,"ep":"Break the Bank","ts":"2026-11-01T17:00:00+00:00","timed":0,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":12,"ep":"Cleveland Browns at Pittsburgh Steelers","ts":"2026-11-01T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":8,"ep":"Week 8","ts":"2026-11-01T18:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":13,"ep":"Kansas City Chiefs at Denver Broncos","ts":"2026-11-01T21:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":9,"ep":"Week 8","ts":"2026-11-02T00:00:00+00:00","timed":1,"id":""},{"show":"Youth","net":"HBO","s":1,"e":8,"ep":"Episode 8","ts":"2026-11-02T03:00:00+00:00","timed":1,"id":""},{"show":"Monday Night Countdown","net":"ESPN","s":34,"e":8,"ep":"Week 8","ts":"2026-11-02T23:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":11,"ep":"","ts":"2026-11-03T02:00:00+00:00","timed":1,"id":""},{"show":"Line of Fire","net":"NBC","s":1,"e":7,"ep":"Episode 7","ts":"2026-11-03T03:00:00+00:00","timed":1,"id":""},{"show":"TrueSouth","net":"SEC Network","s":9,"e":4,"ep":"Rayne, La.","ts":"2026-11-04T01:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":9,"ep":"","ts":"2026-11-04T01:00:00+00:00","timed":1,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":7,"ep":"","ts":"2026-11-05T01:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":16,"ep":"Evolution: The Mating Game","ts":"2026-11-05T02:00:00+00:00","timed":1,"id":""},{"show":"College Football Countdown","net":"ESPN","s":21,"e":12,"ep":"Week 8","ts":"2026-11-06T00:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":9,"ep":"","ts":"2026-11-06T01:00:00+00:00","timed":1,"id":""},{"show":"Law & Order: Special Victims Unit","net":"NBC","s":28,"e":5,"ep":"","ts":"2026-11-06T02:00:00+00:00","timed":1,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":8,"ep":"Episode 8","ts":"2026-11-06T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":45,"ep":"#1418","ts":"2026-11-07T01:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":8,"ep":"The Dance","ts":"2026-11-07T01:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":7,"ep":"Take the Shot","ts":"2026-11-07T03:00:00+00:00","timed":1,"id":""},{"show":"Cook's Country from America's Test Kitchen","net":"PBS","s":19,"e":8,"ep":"Skillet Suppers","ts":"2026-11-07T20:30:00+00:00","timed":1,"id":""},{"show":"B1G College Countdown","net":"NBC","s":4,"e":4,"ep":"From South Bend, IN","ts":"2026-11-08T00:00:00+00:00","timed":1,"id":""},{"show":"Notre Dame Football on NBC","net":"NBC","s":36,"e":5,"ep":"Miami Hurricanes at Notre Dame Fighting Irish","ts":"2026-11-08T00:30:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":5,"ep":"","ts":"2026-11-08T04:29:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":14,"ep":"New York Jets at Kansas City Chiefs","ts":"2026-11-08T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":9,"ep":"Week 9","ts":"2026-11-08T18:30:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":10,"ep":"Week 9","ts":"2026-11-09T00:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":12,"ep":"","ts":"2026-11-10T02:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":10,"ep":"","ts":"2026-11-11T01:00:00+00:00","timed":1,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":8,"ep":"","ts":"2026-11-12T01:00:00+00:00","timed":1,"id":""},{"show":"NOVA","net":"PBS","s":53,"e":17,"ep":"Evolution: On the Run","ts":"2026-11-12T02:00:00+00:00","timed":1,"id":""},{"show":"South Park","net":"Comedy Central","s":29,"e":5,"ep":"","ts":"2026-11-12T03:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":10,"ep":"","ts":"2026-11-13T01:00:00+00:00","timed":1,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":9,"ep":"Episode 9","ts":"2026-11-13T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":46,"ep":"#1419 - Amerant Bank Arena in Fort Lauderdale, FL","ts":"2026-11-14T01:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":9,"ep":"Another Man's Shadow","ts":"2026-11-14T01:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":8,"ep":"The Vault","ts":"2026-11-14T03:00:00+00:00","timed":1,"id":""},{"show":"Notre Dame Football on NBC","net":"NBC","s":36,"e":6,"ep":"Boston College Eagles at Notre Dame Fighting Irish","ts":"2026-11-14T20:30:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":6,"ep":"","ts":"2026-11-15T04:29:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":15,"ep":"Kansas City Chiefs at Atlanta Falcons","ts":"2026-11-15T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":10,"ep":"Week 10","ts":"2026-11-15T18:30:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":11,"ep":"Week 10","ts":"2026-11-16T00:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":13,"ep":"","ts":"2026-11-17T02:00:00+00:00","timed":1,"id":""},{"show":"TrueSouth","net":"SEC Network","s":9,"e":5,"ep":"Behind-the-scenes","ts":"2026-11-18T01:00:00+00:00","timed":1,"id":""},{"show":"Dancing with the Stars","net":"ABC","s":35,"e":11,"ep":"","ts":"2026-11-18T01:00:00+00:00","timed":1,"id":""},{"show":"Survivor","net":"CBS","s":51,"e":9,"ep":"","ts":"2026-11-19T01:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":11,"ep":"","ts":"2026-11-20T01:00:00+00:00","timed":1,"id":""},{"show":"The Traitors: New Blood","net":"NBC","s":1,"e":12,"ep":"","ts":"2026-11-20T02:00:00+00:00","timed":1,"id":""},{"show":"MobLand","net":"Paramount+","s":2,"e":10,"ep":"Episode 10","ts":"2026-11-20T12:00:00+00:00","timed":0,"id":"mobland"},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":47,"ep":"#1420 - Ford Center in Evansville, IN","ts":"2026-11-21T01:00:00+00:00","timed":1,"id":""},{"show":"Outlander: Blood of My Blood","net":"STARZ","s":2,"e":10,"ep":"Twelfth Night","ts":"2026-11-21T01:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":9,"ep":"Burn Zone","ts":"2026-11-21T03:00:00+00:00","timed":1,"id":""},{"show":"B1G College Countdown","net":"NBC","s":4,"e":5,"ep":"From South Bend, IN","ts":"2026-11-22T00:00:00+00:00","timed":1,"id":""},{"show":"Notre Dame Football on NBC","net":"NBC","s":36,"e":7,"ep":"SMU Mustangs at Notre Dame Fighting Irish","ts":"2026-11-22T00:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":16,"ep":"Tampa Bay Buccaneers at Detroit Lions","ts":"2026-11-22T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":11,"ep":"Week 11","ts":"2026-11-22T18:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":17,"ep":"Pittsburgh Steelers at Philadelphia Eagles","ts":"2026-11-22T21:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":12,"ep":"Week 11","ts":"2026-11-23T00:00:00+00:00","timed":1,"id":""},{"show":"30 for 30","net":"ESPN","s":4,"e":50,"ep":"Give Me The Ball!","ts":"2026-11-23T01:30:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":14,"ep":"","ts":"2026-11-24T02:00:00+00:00","timed":1,"id":""},{"show":"South Park","net":"Comedy Central","s":29,"e":6,"ep":"","ts":"2026-11-26T03:00:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":18,"ep":"Chicago Bears at Detroit Lions","ts":"2026-11-26T18:00:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":13,"ep":"Week 12A","ts":"2026-11-27T00:00:00+00:00","timed":1,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":48,"ep":"#1421 - Intrust Bank Arena in Wichita, KS","ts":"2026-11-28T01:00:00+00:00","timed":1,"id":""},{"show":"S.W.A.T.: Exiles","net":"STARZ","s":1,"e":10,"ep":"Hard Exit","ts":"2026-11-28T03:00:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":19,"ep":"Baltimore Ravens at Houston Texans","ts":"2026-11-29T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":12,"ep":"Week 12","ts":"2026-11-29T18:30:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":14,"ep":"Week 12B","ts":"2026-11-30T00:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":15,"ep":"","ts":"2026-12-01T02:00:00+00:00","timed":1,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":49,"ep":"#1422 - Van Andel Arena in Grand Rapids, MI","ts":"2026-12-05T01:00:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":7,"ep":"","ts":"2026-12-06T04:29:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":20,"ep":"Cincinnati Bengals at Cleveland Browns","ts":"2026-12-06T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":13,"ep":"Week 13","ts":"2026-12-06T18:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":21,"ep":"Buffalo Bills at New England Patriots","ts":"2026-12-06T21:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":15,"ep":"Week 13","ts":"2026-12-07T00:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":16,"ep":"","ts":"2026-12-08T02:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":17,"ep":"","ts":"2026-12-09T01:00:00+00:00","timed":1,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":50,"ep":"#1423 - RAC Arena in Perth, Australia","ts":"2026-12-12T01:00:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":8,"ep":"","ts":"2026-12-13T04:29:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":22,"ep":"Houston Texans at Washington Commanders","ts":"2026-12-13T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":14,"ep":"Week 14","ts":"2026-12-13T18:30:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":16,"ep":"Week 14","ts":"2026-12-14T00:00:00+00:00","timed":1,"id":""},{"show":"The Voice","net":"NBC","s":30,"e":18,"ep":"","ts":"2026-12-15T02:00:00+00:00","timed":1,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":51,"ep":"#1424","ts":"2026-12-19T01:00:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":23,"ep":"Chicago Bears at Buffalo Bills","ts":"2026-12-20T01:20:00+00:00","timed":1,"id":""},{"show":"Saturday Night Live","net":"NBC","s":52,"e":9,"ep":"","ts":"2026-12-20T04:29:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":24,"ep":"Baltimore Ravens at Pittsburgh Steelers","ts":"2026-12-20T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":15,"ep":"Week 15","ts":"2026-12-20T18:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":25,"ep":"Dallas Cowboys at Los Angeles Rams","ts":"2026-12-20T21:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":17,"ep":"Week 15","ts":"2026-12-21T00:00:00+00:00","timed":1,"id":""},{"show":"Harry Potter","net":"HBO","s":1,"e":1,"ep":"","ts":"2026-12-25T17:00:00+00:00","timed":0,"id":""},{"show":"WWE Friday Night SmackDown","net":"USA Network","s":27,"e":52,"ep":"#1425","ts":"2026-12-26T01:00:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":26,"ep":"New England Patriots at New York Jets","ts":"2026-12-27T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":16,"ep":"Week 16","ts":"2026-12-27T18:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":27,"ep":"San Francisco 49ers at Kansas City Chiefs","ts":"2026-12-27T21:25:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":18,"ep":"Week 16","ts":"2026-12-28T00:00:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":19,"ep":"Week 17A","ts":"2027-01-02T20:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":28,"ep":"Minnesota Vikings at New York Jets","ts":"2027-01-03T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":17,"ep":"Week 17","ts":"2027-01-03T18:30:00+00:00","timed":1,"id":""},{"show":"Football Night in America","net":"NBC","s":21,"e":20,"ep":"Week 17B","ts":"2027-01-04T00:00:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":29,"ep":"TBD at TBD","ts":"2027-01-10T18:00:00+00:00","timed":1,"id":""},{"show":"NFL Primetime","net":"ESPN","s":2026,"e":18,"ep":"Week 18","ts":"2027-01-10T18:30:00+00:00","timed":1,"id":""},{"show":"NFL on CBS","net":"CBS","s":2026,"e":30,"ep":"TBD at TBD","ts":"2027-01-10T21:25:00+00:00","timed":1,"id":""},{"show":"Family Guy","net":"FOX","s":25,"e":1,"ep":"Acts of Crime","ts":"2027-02-22T01:00:00+00:00","timed":1,"id":""},{"show":"Silo","net":"Apple TV","s":4,"e":1,"ep":"","ts":"2027-07-09T12:00:00+00:00","timed":0,"id":""}]}</script>
  <script defer src="data/catalog.c3540a80.js"></script>
  <script defer src="data/watch-providers.3d99dc20.js"></script>
  <script defer src="data/free-catalog.b12f08cc.js"></script>
  <script defer src="data/series-catalog.65712668.js"></script>
  <script defer src="data/podcast-library.3ba54e17.js"></script>
  <script defer src="data/podcast-playlists.js"></script>
  <script defer src="podcast-player.js"></script>
  <script defer src="data/companion-map.0a1e4a27.js"></script>
    <script defer src="data/podcast-featured.4ca10f1c.js"></script>
<script defer src="data/true-crime-news.980d6a30.js"></script>
<script defer src="pod-episode.7c588014.js"></script>
<script defer src="free.367225e9.js"></script>
<script defer src="batch.98645f9e.js"></script>
  <!-- Drag-to-favorites surfaces (2026-09-24): floating folder, coaching bubble,
       remove zone, Favorites popup, toast. -->
  <button id="pvFolder" type="button" aria-label="Open favorites" title="Favorites">&#9733;<span id="pvFavCount">0</span></button>
  <div id="pvCoach" class="pv-hide" role="note"><b>Try it:</b> press &amp; hold any title, then drag it here &#9733;</div>
  <div id="pvRemoveZone" aria-hidden="true">&#128465;&nbsp; Release to remove from Favorites</div>
  <div class="modal" id="favModal" role="dialog" aria-modal="true" aria-labelledby="favModalTitle" aria-hidden="true">
    <article class="modal-card fav-panel">
      <button class="modal-close" data-modal-close="favModal" aria-label="Close favorites">&times;</button>
      <div class="modal-body fav-body">
        <div class="eyebrow">Your Library</div>
        <h2 id="favModalTitle">Favorites</h2>
        <p class="fav-sub" id="favSub"></p>
        <ul class="fav-list" id="favList"></ul>
      </div>
    </article>
  </div>
  <div id="pvToast" role="status" aria-live="polite"></div>
  <script>
/* ============================================================
   Previously — main site script (rewritten 2026-09-23)
   Catalog data ships in catalog.js (async); anonymous retention state lives
   in localStorage (this device only). Signed-in visitors get the account
   layer (account.js, via window.__PV below): profile, preferences, and the
   synced library backed by the previously-api Worker.

   Sections:
     1. Data boot (starter catalog + TMDB catalog merge)
     2. Local retention store (favorites, alerts, recent, visits)
     3. Artwork helpers (HD URLs, branded placeholders)
     4. Date/time helpers (Pacific)
     5. Cards (poster / wide, hover overlays, star toggles)
     6. Hero
     7. Schedule ("Tonight, in order." + freshness + artwork)
     8. Home rails (Tonight for you, Recently viewed)
     9. Library (favorites + per-show alert toggles)
    10. Inbox ("Your shows air tonight")
    11. Title detail modal (star, alerts, trailer, cast, rating)
    12. Browse (search, filters, chunked rendering)
    13. Router (views)
    14. Beta signup (previously-beta Worker + D1 — our own endpoint)
    15. Global wiring + boot
   ============================================================ */
(function(){
"use strict";

/* ================= 1. DATA BOOT ================= */
var starter=[], schedule={episodes:[]};
try{starter=JSON.parse(document.getElementById("catalog-data").textContent)||[];}catch(e){starter=[];}
try{schedule=JSON.parse(document.getElementById("schedule-data").textContent)||{episodes:[]};}
catch(e){schedule={episodes:[]};}
if(!schedule.episodes)schedule.episodes=[];

var titles=[], titleMap={}, nameIndex={};

function normalizeText(s){
  var text=String(s==null?"":s).toLowerCase();
  return text.normalize?text.normalize("NFD").replace(/[\u0300-\u036f]/g,""):text;
}
function esc(s){
  return String(s==null?"":s).replace(/[&<>"]/g,function(c){
    return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c];
  });
}
/* Starter catalog wins on title collisions (verified trailers, local art). */
function buildIndex(){
  titles=[];titleMap={};nameIndex={};
  var seenTitles={};
  function add(t){
    if(!t||!t.title)return;
    var n=normalizeText(t.title);
    if(seenTitles[n])return;
    seenTitles[n]=true;
    titles.push(t);titleMap[t.id]=t;nameIndex[n]=t;
  }
  starter.forEach(add);
  (window.PREVIOUSLY_CATALOG||[]).forEach(add);
  buildSearchHay();
}
/* Precomputed search corpus: built once per index build, never per keystroke. */
var searchHay=[];
function buildSearchHay(){
  searchHay=titles.map(function(t){
    return normalizeText(t.title+" "+t.genre+" "+t.type+" "+(t.network||"")+" "+(t.cast||"")+" "+(t.desc||""));
  });
}
function byId(id){return titleMap[id]||freeTitleById(id)||null;}
function freeTitleById(id){
  if(!id||id.indexOf("free-yt-")!==0)return null;
  var yt=id.slice(8),cat=window.PREVIOUSLY_FREE_CATALOG||[],i,e;
  for(i=0;i<cat.length;i++){e=cat[i];if(e&&e.id===yt){
    return {id:id,title:e.t,type:"Movie",meta:"Free with ads",genre:"",desc:"",
      image:"https://i.ytimg.com/vi/"+e.id+"/hqdefault.jpg",freeYtId:e.id,freeChannel:e.channel};}}
  return null;
}
function matchTitle(ep){
  if(ep&&ep.id&&titleMap[ep.id])return titleMap[ep.id];
  if(ep&&ep.show)return nameIndex[normalizeText(ep.show)]||null;
  return null;
}
/* Artwork-only timeline (approved 2026-09-24): exact-title schedule art for
   shows with no catalog match. Keys MUST be exact schedule titles — never
   fake-map a different show. Verified via TMDB 2026-09-24. */
var SCHEDULE_ART={
  "cook's country from america's test kitchen":{tmdb:18940,
    backdrop:"/mBV27trF7gkA9RBFwVwnFAepCN6.jpg",
    poster:"/vSe1ojqtDBiEvnUiU1c5GFxVuia.jpg"},
  "nfl live":{tmdb:135811,poster:"/2b0gSpRT3rnWtMOf0PAMilqGABK.jpg"}
};
var TMDB_IMG_BASE="https://image.tmdb.org/t/p/";
function scheduleArtFor(ep){
  var m=SCHEDULE_ART[normalizeText(ep.show)];
  if(!m)return null;
  var path=m.backdrop||m.poster;
  return {t:{image:TMDB_IMG_BASE+"w780"+path,title:ep.show},
    src:TMDB_IMG_BASE+"w780"+path,kind:"schedule"};
}
/* timelineArt(ep): real artwork for a timeline card, or null when the show
   has none. Resolution: catalog match with a real image/backdrop first,
   then exact verified schedule artwork. Never a monogram. */
function timelineArt(ep){
  var t=matchTitle(ep);
  if(t&&(t.image||t.backdrop))return {t:t,src:artSrc(t),kind:"catalog"};
  var s=scheduleArtFor(ep);
  if(s)return s;
  return null;
}

/* ================= 2. RETENTION STORE ================= */
var store={
  get:function(k,d){try{var v=localStorage.getItem("pv1:"+k);return v==null?d:JSON.parse(v);}catch(e){return d;}},
  set:function(k,v){try{localStorage.setItem("pv1:"+k,JSON.stringify(v));return true;}catch(e){return false;}},
  del:function(k){try{localStorage.removeItem("pv1:"+k);}catch(e){}}
};
var favs=store.get("favs",{});            /* id -> {alert:bool, added:ms} */
var recentIds=store.get("recent",[]);      /* [id...] newest first */
var lastVisit=store.get("lastVisit",0);    /* ms; 0 = first visit */
var inboxRead=store.get("inboxRead",0);    /* ms */
function saveFavs(){return store.set("favs",favs);}
function isFav(id){return !!favs[id];}
function toggleFav(id){
  var t=byId(id);if(!t)return false;
  var nowOn,snap=null;
  if(favs[id]){snap={alert:!!favs[id].alert,added:favs[id].added||Date.now()};delete favs[id];nowOn=false;}
  else{favs[id]={alert:(t.type==="Series"),added:Date.now()};nowOn=true;}
  saveFavs();
  document.querySelectorAll('.star-btn[data-tid="'+id+'"]').forEach(function(b){syncStarBtn(b,t);});
  renderLibrary();renderTonightForYou();updateInboxBadge();
  /* Favorites filter would otherwise keep showing the just-unstarred card. */
  if(currentGenre==="favorites")renderCatalog();
  if(modalTitleId===id)syncModalEngage(t);
  pvSyncBadge(nowOn);
  if(nowOn){pvToast("Saved to your Library.");pvDismissCoach();}
  else pvRemovedToast(id,snap);
  return nowOn;
}
/* One-time star hint (touch / coarse-pointer devices only). Anchors near the
   first visible .star-btn, follows it on scroll, and shows exactly once ever
   (dismissal persisted as pv1:starHintSeen via the existing store helper). */
var starHintAnchor=null;
var starHintTimer=null;
function positionStarHint(){
  var hint=document.getElementById("starHint");
  if(!hint||hint.hidden||!starHintAnchor)return;
  var r=starHintAnchor.getBoundingClientRect();
  if(r.top<-60||r.top>window.innerHeight||r.width===0){hint.hidden=true;return;}
  hint.style.top=(r.bottom+10)+"px";
  hint.style.left=Math.min(Math.max(8,r.right-232),window.innerWidth-240)+"px";
}
function dismissStarHint(){
  var hint=document.getElementById("starHint");
  if(hint)hint.hidden=true;
  starHintAnchor=null;
  if(starHintTimer){clearInterval(starHintTimer);starHintTimer=null;}
  store.set("starHintSeen",true);
}
function maybeShowStarHint(){
  if(!window.matchMedia||!window.matchMedia("(hover: none), (pointer: coarse)").matches)return;
  if(store.get("starHintSeen",false))return;
  if(starHintTimer)return; /* watcher already running */
  /* Persistent watcher: the first .star-btn sits far below the fold, so the
     old fixed 10s window expired before any star was ever visible and the
     hint never appeared. Keep a cheap 400ms watch until dismissal: park the
     bubble near the first visible star, hide it when none is on screen, and
     never show it again once dismissed (pv1:starHintSeen). */
  starHintTimer=setInterval(function(){
    if(store.get("starHintSeen",false)){clearInterval(starHintTimer);starHintTimer=null;return;}
    var hint=document.getElementById("starHint");
    if(!hint)return;
    if(document.querySelector(".modal.open")){hint.hidden=true;starHintAnchor=null;return;} /* never coach over an open modal */
    var target=null,btns=document.querySelectorAll(".star-btn");
    for(var i=0;i<btns.length;i++){
      var r=btns[i].getBoundingClientRect();
      if(r.width>0&&r.top>=0&&r.top<window.innerHeight*0.75){target=btns[i];break;}
    }
    if(target){
      starHintAnchor=target;
      hint.hidden=false;
      positionStarHint();
    }else{
      starHintAnchor=null;
      hint.hidden=true;
    }
  },400);
}
function setAlert(id,on){
  var t=byId(id);if(!t||t.type!=="Series")return false;
  var prev=favs[id]?{alert:!!favs[id].alert,added:favs[id].added||Date.now()}:null;
  if(!favs[id])favs[id]={alert:on,added:Date.now()};
  else favs[id].alert=!!on;
  if(!saveFavs()){if(prev)favs[id]=prev;else delete favs[id];return false;}
  renderLibrary();updateInboxBadge();
  if(modalTitleId===id)syncModalEngage(t);
  return true;
}

/* ================= 3. ARTWORK ================= */
/* Posters: TMDB w780 minimum. Backdrops: w1280. No thumbnails-as-posters. */
function posterSrc(t){return t.image||"";}
function backdropSrc(t){return t.backdrop||t.image||"";}
function placeholderURI(t){
  var initial=esc((t.title||"?").trim().charAt(0).toUpperCase()||"?");
  var svg="<svg xmlns='http://www.w3.org/2000/svg' width='400' height='600' viewBox='0 0 400 600'>"+
    "<defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='1'>"+
    "<stop offset='0' stop-color='#1e1a18'/><stop offset='1' stop-color='#222226'/></linearGradient></defs>"+
    "<rect width='400' height='600' fill='url(#g)'/>"+
    "<text x='200' y='310' text-anchor='middle' font-family='Georgia,serif' font-size='150' fill='#ede6d6' opacity='.92'>"+initial+"</text>"+
    "<text x='200' y='545' text-anchor='middle' font-family='Georgia,serif' font-size='24' letter-spacing='6' fill='#ede6d6' opacity='.5'>PREVIOUSLY</text></svg>";
  return "data:image/svg+xml;utf8,"+encodeURIComponent(svg);
}
function artSrc(t,useBackdrop){
  var u=useBackdrop?backdropSrc(t):posterSrc(t);
  return u||placeholderURI(t);
}
/* Responsive artwork: local assets get <picture> with WebP + JPEG fallback;
   remote TMDB images get srcset across TMDB's own size variants (w342/w500/w780).
   Alt text, loading="lazy", decoding="async", and data-art are always preserved. */
var CARD_SIZES="(max-width:600px) 44vw, (max-width:820px) 30vw, (max-width:1100px) 22vw, 232px";
var WIDE_SIZES="(max-width:820px) 92vw, (max-width:1100px) 45vw, 560px";
var LOCAL_POSTER_W={dune:780,everything:780,"last-of-us":780,severance:600,shogun:672,spiderverse:600,"the-bear":600,wednesday:780};
function localWebpFor(src){
  var m=/^(assets\/(posters|artwork|trailers)\/)([^\/]+)\.jpg$/.exec(src);
  if(!m)return null;
  var base=m[1]+m[3],dir=m[2];
  if(dir==="posters")return{set:base+"-480.webp 480w, "+base+".webp "+(LOCAL_POSTER_W[m[3]]||780)+"w"};
  if(dir==="artwork")return{set:base+"-800.webp 800w, "+base+".webp 1600w"};
  return{single:base+".webp"};
}
function artImgHTML(t,alt,sizes,useBackdrop){
  var src=artSrc(t,!!useBackdrop);
  var imgAttrs='alt="'+esc(alt!==undefined?alt:((t&&t.title?t.title:"")+" key art"))+'" loading="lazy" decoding="async"'+(t&&t.title?' data-art="'+esc(t.title)+'"':"");
  if(src.indexOf("data:")===0)return '<img src="'+src+'" '+imgAttrs+'>';
  var lw=localWebpFor(src);
  if(lw){
    var inner=lw.set
      ?'<source type="image/webp" srcset="'+esc(lw.set)+'" sizes="'+(sizes||CARD_SIZES)+'">'
      :'<source type="image/webp" srcset="'+esc(lw.single)+'">';
    return '<picture>'+inner+'<img src="'+esc(src)+'" '+imgAttrs+'></picture>';
  }
  var tm=/^(https:\/\/image\.tmdb\.org\/t\/p\/)w\d+(\/.+)$/.exec(src);
  if(tm){
    var set=tm[1]+"w342"+tm[2]+" 342w, "+tm[1]+"w500"+tm[2]+" 500w, "+tm[1]+"w780"+tm[2]+" 780w";
    return '<img src="'+esc(src)+'" srcset="'+esc(set)+'" sizes="'+(sizes||CARD_SIZES)+'" '+imgAttrs+'>';
  }
  return '<img src="'+esc(src)+'" '+imgAttrs+'>';
}
function initialOf(s){return esc((String(s||"?").trim().charAt(0)||"?").toUpperCase());}
/* Honest artwork: a remote image that fails to load swaps to the branded monogram
   tile — a visitor never sees the browser's broken-image glyph. Capture phase:
   img error events do not bubble. */
/* Honest artwork: a remote image that fails to load swaps to the branded monogram
   tile — a visitor never sees the browser's broken-image glyph. Capture phase:
   img error events do not bubble.
   EXCEPTION (artwork-only timeline, approved 2026-09-24): timeline imgs carry
   data-hidecard="1" — those cards are removed on error, never monogrammed. */
function artErrorSwap(e){
  var img=e.target;
  if(!img||img.tagName!=="IMG"||!img.getAttribute("data-art"))return;
  if(img.getAttribute("data-art-swapped"))return;
  img.setAttribute("data-art-swapped","1");
  /* Artwork-only timeline (approved 2026-09-24): a timeline card whose image
     fails to load is removed, never swapped to a monogram placeholder. */
  if(img.getAttribute("data-hidecard")==="1"){
    var card=img.closest?img.closest(".tl-btn"):null;
    if(card&&card.parentNode){card.parentNode.removeChild(card);}
    return;
  }
  img.removeAttribute("srcset");img.removeAttribute("sizes");
  var pic=img.parentNode;
  if(pic&&pic.tagName==="PICTURE"){var ss=pic.querySelectorAll("source");for(var i=0;i<ss.length;i++)ss[i].remove();}
  /* James 2026-09-25: hero images carry data-jpg — a failed WebP candidate
     falls back to the real JPG, never to the monogram. The hero always shows
     real artwork when it exists. */
  var jpgFb=img.getAttribute("data-jpg");
  if(jpgFb){img.removeAttribute("src");img.src=jpgFb;return;}
  img.src=placeholderURI({title:img.getAttribute("data-art")});
}
document.addEventListener("error",artErrorSwap,true);

/* ================= 4. DATE/TIME (Pacific) ================= */
function partsFor(date,options){
  return new Intl.DateTimeFormat("en-US",Object.assign({timeZone:"America/Los_Angeles"},options)).formatToParts(date);
}
function part(parts,type){var f=parts.filter(function(x){return x.type===type;})[0];return f?f.value:"";}
function dateKeyPT(date){
  var p=partsFor(date,{year:"numeric",month:"2-digit",day:"2-digit"});
  return part(p,"year")+"-"+part(p,"month")+"-"+part(p,"day");
}
function dateLabelPT(date){
  var p=partsFor(date,{weekday:"long",month:"long",day:"numeric"});
  return part(p,"weekday")+" · "+part(p,"month")+" "+part(p,"day");
}
function timePT(ep){
  return ep.timed?new Intl.DateTimeFormat("en-US",{timeZone:"America/Los_Angeles",hour:"numeric",minute:"2-digit"}).format(new Date(ep.ts)):"Streaming";
}
function episodeCode(ep){
  var bits=[];if(ep.s)bits.push("S"+ep.s);if(ep.e)bits.push("E"+ep.e);return bits.join(" ");
}
function freshnessLabel(){
  var g=schedule.generated;if(!g)return "";
  var ms=Date.parse(g);if(isNaN(ms))return "";
  var h=Math.max(0,(Date.now()-ms)/36e5);
  if(h<1)return "Updated just now";
  if(h<24)return "Updated "+Math.floor(h)+"h ago";
  return "";
}

/* NEW-episode tracking: titles with episodes since the previous visit. */
var newTitleIds={};
function computeNewTitles(){
  newTitleIds={};
  if(!lastVisit)return;
  var end=new Date();end.setHours(23,59,59,999);
  var endMs=end.getTime();
  schedule.episodes.forEach(function(ep){
    var ts=new Date(ep.ts).getTime();
    if(isNaN(ts)||ts<=lastVisit||ts>endMs)return;
    var t=matchTitle(ep);if(t)newTitleIds[t.id]=1;
  });
}
function epIsNew(ep){
  if(!lastVisit)return false;
  var ts=new Date(ep.ts).getTime();
  return !isNaN(ts)&&ts>lastVisit;
}

/* ================= 5. CARDS ================= */
var STAR_SVG='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="m12 2.5 2.9 6 6.6.9-4.8 4.6 1.2 6.5L12 17.4 6.1 20.5l1.2-6.5L2.5 9.4l6.6-.9z"/></svg>';
function syncStarBtn(b,t){
  var on=isFav(t.id);
  b.setAttribute("aria-pressed",on?"true":"false");
  b.setAttribute("aria-label",(on?"Unfavorite ":"Favorite ")+t.title);
  b.setAttribute("data-tip",on?"Unfavorite":"Favorite");
}
function makeStarBtn(t){
  var b=document.createElement("button");
  b.type="button";b.className="star-btn";b.setAttribute("data-tid",t.id);
  b.innerHTML=STAR_SVG;syncStarBtn(b,t);
  b.addEventListener("click",function(e){
    e.stopPropagation();
    var on=toggleFav(t.id);
    if(on){b.classList.remove("pop");void b.offsetWidth;b.classList.add("pop");}
  });
  return b;
}
function cardRating(t){
  if(!t.rating)return "";
  return '<span class="card-rating">★ '+Number(t.rating).toFixed(1)+'</span>';
}
function posterCard(t,opts){
  opts=opts||{};
  var isNew=!!(opts.isNew||newTitleIds[t.id]);
  var card=document.createElement("div");
  card.className="poster-card";
  card.setAttribute("data-dragid",t.id); /* drag-to-favorites: sitewide long-press */
  card.innerHTML=
    '<button class="card-open" type="button" aria-label="View details for '+esc(t.title)+'">'+
    '<span class="poster-art">'+artImgHTML(t)+
    '<span class="poster-badge">'+esc(t.type)+'</span>'+
    (isNew?'<span class="new-badge">NEW</span>':'')+
    '<span class="card-hover" aria-hidden="true"><span class="hover-actions">'+
    (t.trailer?'<span class="hover-chip" data-tip="Watch the trailer">▶ Trailer</span>':'')+
    '<span class="hover-chip" data-tip="Open full details">Details →</span></span></span></span>'+
    '<span class="poster-copy"><h3>'+esc(t.title)+'</h3><span class="genre">'+esc(t.genre||"")+'</span>'+cardRating(t)+
    '<span class="card-action">View details</span></span></button>';
  var open=card.querySelector(".card-open");
  open.addEventListener("click",function(){if(card._pvDragged)return;openShow(t,open);});
  card.appendChild(makeStarBtn(t));
  return card;
}
function wideCard(t,opts){
  opts=opts||{};
  var isNew=!!(opts.isNew||newTitleIds[t.id]);
  var card=document.createElement("div");
  card.className="wide-card";
  card.setAttribute("data-dragid",t.id); /* drag-to-favorites: sitewide long-press */
  card.innerHTML=
    '<button class="card-open" type="button" aria-label="View details for '+esc(t.title)+'">'+
    artImgHTML(t,null,WIDE_SIZES,true)+
    (isNew?'<span class="new-badge">NEW</span>':'')+
    '<span class="card-hover" aria-hidden="true"><span class="hover-actions">'+
    (t.trailer?'<span class="hover-chip" data-tip="Watch the trailer">▶ Trailer</span>':'')+
    '<span class="hover-chip" data-tip="Open full details">Details →</span></span></span>'+
    '<span class="wide-copy"><span>'+esc(t.type)+' · '+esc(t.genre||"")+'</span><h3>'+esc(t.title)+'</h3>'+
    '<span class="card-action">View details</span></span></button>';
  var open=card.querySelector(".card-open");
  open.addEventListener("click",function(){if(card._pvDragged)return;openShow(t,open);});
  card.appendChild(makeStarBtn(t));
  return card;
}

/* ================= 6. HERO (frozen design) ================= */
var heroItems=[],heroIndex=0,autoTimer=null;
function heroTitleMarkup(title){
  var words=title.replace(/\.$/,"").split(" ");
  if(words.length<2)return esc(title)+"<em>.</em>";
  var last=words.pop();
  return esc(words.join(" "))+"<em>"+esc(last)+".</em>";
}
/* James 2026-09-24: the featured hero is STRICTLY movies and TV series, in
   English, no soaps. A dedicated pick (James's Pick) bypasses these filters. */
var HERO_FOREIGN_NETS={
  "tencent qq":1,"kbs2":1,"canal+":1,"at-x":1,"jtbc":1,"fuji tv":1,
  "tencent video":1,"kbs":1,"mbc":1,"sbs":1,"tvn":1,"tv tokyo":1,"nhk":1,
  "tf1":1,"france 2":1,"france 3":1,"zdf":1,"ard":1,"rtl":1,"bbc one":0
};
var HERO_SOAP_BLOCK={
  "beyond the gates":1,"the young and the restless":1,"the bold and the beautiful":1,
  "general hospital":1,"days of our lives":1
};
var HERO_SOAP_HINT=/\b(soap opera|soap-opera|daytime drama|daytime soap|daytime serial)\b/i;
function heroNetworkForeign(t){
  var net=String((t&&t.network)||"").trim().toLowerCase();
  if(!net)return false;
  if(HERO_FOREIGN_NETS[net])return true;
  return /\b(tencent|qq|kbs|mbc|sbs|tvn|at-x|jtbc|fuji tv|canal\+|tf1|france [23]|zdf|nhk|tv tokyo)\b/i.test(net);
}
function heroEpOK(ep){
  /* The foreign-network signal lives on the EPISODE (ep.net), not the catalog
     title (many titles carry network:""). One source of truth: the same
     foreign-network test the title path uses. */
  return !heroNetworkForeign({network:ep&&ep.net});
}
function heroTitleOK(t,strict){
  /* strict: the schedule/fallback path. A dedicated explicit pick bypasses. */
  if(!strict)return true;
  if(!t)return false;
  var type=t.type;
  if(type!=="Movie"&&type!=="Series")return false;
  var nt=normalizeText(t.title||"");
  if(HERO_SOAP_BLOCK[nt])return false;
  if(HERO_SOAP_HINT.test(String(t.desc||""))||/\bsoap\b/i.test(String(t.genre||"")))return false;
  var lang=String(t.language||t.original_language||"").toLowerCase();
  if(lang&&lang!=="en"&&lang!=="english")return false;
  if(heroNetworkForeign(t))return false;
  return true;
}
/* HERO single-commit (James 2026-09-26): the hero paints ONCE.
   First paint is a branded shimmer skeleton (see .hero-loading in CSS) — no
   hardcoded title ever shows first. The real slides commit a single time after
   schedule + catalog data have settled (onCatalogReady arms the commit; a
   2.5s fallback arms it if the async catalog never lands). Any later
   buildHero() call (async catalog arrival, re-renders) only repaints when the
   picked selection actually changed — identical picks never touch the DOM, so
   async arrivals can't flicker the hero. Selection rules are unchanged:
   strictly movies/series, English, no soaps, no foreign networks,
   no-picture-no-hero, day-rotated picks from the pool. */
var heroCommittedKeys=null;  /* "~"-joined heroItemKey() of what's painted; null = skeleton showing */
var heroCommitArmed=false;   /* true once schedule + catalog have settled and painting is allowed */
function heroItemKey(item){
  var t=item.title,ep=item.episode;
  return t.id+"|"+(ep?((ep.ts||"")+"#"+episodeCode(ep)):"feat");
}
function pickHeroItems(){
  var seen={};heroItems=[];
  /* FIX 2026-09-24: dedupe by normalized title AND id. The catalog holds
     shadowed same-title records, so id-only dedup let near-duplicate titles
     ("Foo" vs "Foo!") share the hero. */
  function heroClaim(t){
    var nt=normalizeText(t.title);
    if(seen[t.id]||seen["nt:"+nt])return false;
    seen[t.id]=true;seen["nt:"+nt]=true;return true;
  }
  tonightEpisodes.forEach(function(ep){
    if(heroItems.length>=3)return;
    if(!heroEpOK(ep))return; /* James 2026-09-24: foreign-language networks never feed the hero */
    var t=matchTitle(ep);if(!t||!heroClaim(t))return;
    /* James 2026-09-24: English movies/series only — no soaps, no foreign nets. */
    if(!heroTitleOK(t,true))return;
    /* James 2026-09-25: no picture, no hero — hard rule, enforced in code. */
    if(!(t.backdrop||t.image))return;
    heroItems.push({title:t,episode:ep});
  });
  /* Fallback: day-rotated picks from the full catalog. Tonight's schedule
     still leads. (The old hardcoded trio lived in the HTML first paint —
     now the first paint is a skeleton.) */
  dayPick(heroPool(),3,3,seen).forEach(function(t){
    if(heroItems.length>=3)return;
    heroItems.push({title:t,episode:null});
  });
}
function paintHeroItems(){
  document.querySelectorAll(".hero-slide").forEach(function(el,i){
    var item=heroItems[i],pic=el.querySelector("picture");
    if(item){
      var t=item.title,src=artSrc(t,true),lw=localWebpFor(src);
      var webpSet=lw?(lw.set||lw.single):"";
      pic.innerHTML=(webpSet?'<source type="image/webp" srcset="'+esc(webpSet)+'" sizes="100vw">':"")+
        '<img src="'+esc(src)+'" alt="'+esc(t.title)+' key art" data-art="'+esc(t.title)+'" data-jpg="'+esc(src)+'">';
      el.hidden=false;
    }
    else el.hidden=true;
    /* Drop the skeleton chrome on the single commit. */
    el.classList.remove("hero-skel");
    var sh=el.querySelector(".hero-skel-shimmer");
    if(sh)sh.parentNode.removeChild(sh);
  });
  document.querySelectorAll(".hero-dot").forEach(function(dot,i){dot.hidden=!heroItems[i];});
  var heroSec=document.querySelector(".hero");
  if(heroSec)heroSec.classList.remove("hero-loading");
  heroIndex=Math.min(heroIndex,Math.max(0,heroItems.length-1));
  heroCommittedKeys=heroItems.map(heroItemKey).join("~");
  setHero(heroIndex,false);
}
function buildHero(){
  pickHeroItems();
  if(!heroCommitArmed)return; /* settled data hasn't arrived yet — keep the skeleton */
  if(!heroItems.length)return; /* nothing real to show — keep the skeleton, retry on next call */
  var keys=heroItems.map(heroItemKey).join("~");
  if(heroCommittedKeys===keys)return; /* identical selection — never rewrite identical content */
  paintHeroItems();
}
function setHero(next,manual){
  if(!heroItems.length)return;
  heroIndex=(next+heroItems.length)%heroItems.length;
  var item=heroItems[heroIndex],t=item.title;
  document.querySelectorAll(".hero-slide").forEach(function(el,i){
    el.classList.toggle("active",i===heroIndex);
    var im=el.querySelector("img");
    if(im){if(i===heroIndex)im.setAttribute("fetchpriority","high");else im.removeAttribute("fetchpriority");}
  });
  document.querySelectorAll(".hero-dot").forEach(function(el,i){
    var active=i===heroIndex;
    el.classList.toggle("active",active);
    el.setAttribute("aria-pressed",active?"true":"false");
  });
  var eyebrow=t.network||t.type;
  if(item.episode){
    eyebrow="Tonight · "+timePT(item.episode)+(item.episode.timed?" PT":"")+
      (episodeCode(item.episode)?" · "+episodeCode(item.episode):"");
  }
  document.getElementById("heroEyebrow").textContent=eyebrow;
  document.getElementById("heroTitle").innerHTML='<span class="sr-only">What to watch, and when</span>'+heroTitleMarkup(t.title);
  document.getElementById("heroText").textContent=t.desc;
  heroTrailerFor(heroIndex);
  if(manual)restartHero();
}
function restartHero(){
  if(autoTimer)clearInterval(autoTimer);
  if(!window.matchMedia("(prefers-reduced-motion: reduce)").matches)
    autoTimer=setInterval(function(){setHero(heroIndex+1,false);},6500);
}

/* ================= 6b. TRAILER POOL + HERO/MODAL TRAILER PLAYERS (Amendment A) =================
   Ported 2026-09-24 from the verified staging trailer-hero tree onto the live
   baseline. The live HERO CONTENT pipeline is untouched (buildHero stays
   exactly as-is); this section only adds trailer playback, keyed off the live
   hero items' {title, episode} shape. Key resolution: the catalog title's own
   `trailer` key wins, else the verified trailer-pool.json lookup by normalized
   title. Titles with no key get no facade and no player — static hero, honest. */
var trailerPool=[],poolByTitle={},poolReady=false,poolStarted=false;
function poolNorm(s){return String(s||"").toLowerCase().replace(/[^a-z0-9]+/g," ").replace(/^ | $/g,"");}
/* Verified pool entry: oEmbed-checked, Trailer type, carries a YouTube key. */
function poolTrailerOK(x){return !!(x&&x.status==="ok"&&x.trailer_type==="Trailer"&&x.youtube_key);}
function poolFind(title){return poolByTitle[poolNorm(title)]||null;}
function loadTrailerPool(){
  if(poolStarted||!("fetch" in window))return;poolStarted=true;
  fetch("data/trailer-pool.json").then(function(r){
    if(!r.ok)throw new Error("pool "+r.status);return r.json();
  }).then(function(d){
    trailerPool=d.pool||[];
    trailerPool.forEach(function(x){
      if(!poolTrailerOK(x))return;
      poolByTitle[poolNorm(x.title)]=x;
      if(x.tmdb_name&&x.tmdb_name!==x.title)poolByTitle[poolNorm(x.tmdb_name)]=x;
    });
    poolReady=true;
    /* Pool arrived after the hero committed: re-run trailer resolution for the
       current slide only. This mounts a facade/player — it never rewrites the
       slide's art, title, or copy, so pool arrival can't flicker the hero.
       Harmless when a player or facade already exists. */
    if(!heroTrailer.iframe)heroTrailerFor(heroIndex);
  }).catch(function(){poolReady=false;/* schedule-driven hero stays trailerless, honest */});
}
/* Trailer key for a live hero item (catalog object, NOT a pool item). */
function heroTrailerKey(t){
  if(!t)return "";
  var k=String(t.trailer||"").trim();
  if(k)return k;
  var hit=poolFind(t.title);
  return hit?hit.youtube_key:"";
}
/* Motion/data gates shared by hero + modal trailer autoplay. */
function trailerMotionOK(){
  if(window.matchMedia("(prefers-reduced-motion: reduce)").matches)return false;
  var c=navigator.connection||navigator.mozConnection||navigator.webkitConnection;
  if(c&&c.saveData)return false;
  if(window.matchMedia("(max-width: 600px)").matches)return false;
  return true;
}
function anyModalOpen(){return !!document.querySelector(".modal.open");}
/* One hero trailer player at a time. The youtube-nocookie iframe starts with
   mute=1; mute/unmute goes through postMessage (enablejsapi=1), so no YouTube
   API script is needed. Mute state is tracked locally. */
var heroTrailer={iframe:null,index:-1,muted:true};
var heroInView=true;
function heroAutoplayAllowed(){
  if(!trailerMotionOK())return false;
  if(document.hidden||!heroInView||anyModalOpen())return false;
  return true;
}
function ytCmd(iframe,func){
  if(!iframe||!iframe.contentWindow)return;
  try{iframe.contentWindow.postMessage(JSON.stringify({event:"command",func:func,args:""}),"https://www.youtube-nocookie.com");}catch(e){}
}
function heroTrailerStop(){
  var f=heroTrailer.iframe;
  if(f&&f.parentNode)f.parentNode.removeChild(f);
  heroTrailer.iframe=null;heroTrailer.index=-1;
  updateHeroTrailerBtns();
}
function heroTrailerFor(i){
  heroTrailerStop();
  var item=heroItems[i];
  if(!item||anyModalOpen())return;
  if(!heroTrailerKey(item.title))return; /* static hero, honest */
  if(heroAutoplayAllowed())mountHeroTrailer(i,false);
  else showHeroFacade(i);
}
/* Tap-to-play facade for reduced-motion / Save-Data / small screens. The tap is
   a user gesture, so playback starts with sound — same as the modal facade. */
function showHeroFacade(i){
  var slides=document.querySelectorAll(".hero-slide"),slide=slides[i];
  if(!slide)return;
  /* One facade at a time: clear stale ones from other slides. */
  document.querySelectorAll(".hero-slide .hero-facade").forEach(function(f){
    if(f.parentNode!==slide)f.parentNode.removeChild(f);
  });
  if(slide.querySelector(".hero-facade")||slide.querySelector(".hero-trailer"))return;
  var item=heroItems[i],t=item&&item.title;
  var b=document.createElement("button");
  b.type="button";b.className="hero-facade";
  b.setAttribute("aria-label","Play "+(t?t.title:"")+" trailer");
  b.innerHTML='<span class="trailer-play" aria-hidden="true">▶</span>';
  b.addEventListener("click",function(){mountHeroTrailer(i,true);});
  slide.appendChild(b);
}
function mountHeroTrailer(i,withSound){
  var item=heroItems[i];
  if(!item)return;
  var key=heroTrailerKey(item.title);
  if(!key)return;
  var slides=document.querySelectorAll(".hero-slide"),slide=slides[i];
  if(!slide)return;
  heroTrailerStop();
  var old=slide.querySelector(".hero-facade");if(old)old.remove();
  var iframe=document.createElement("iframe");
  iframe.className="hero-trailer";
  iframe.title=item.title.title+" trailer"+(withSound?"":" (muted)");
  iframe.tabIndex=-1;iframe.setAttribute("aria-hidden","true");
  iframe.src="https://www.youtube-nocookie.com/embed/"+encodeURIComponent(key)+
    "?autoplay=1&mute="+(withSound?"0":"1")+"&loop=1&playlist="+encodeURIComponent(key)+
    "&controls=0&rel=0&playsinline=1&enablejsapi=1&iv_load_policy=3";
  iframe.allow="autoplay; encrypted-media; picture-in-picture";
  iframe.setAttribute("referrerpolicy","strict-origin-when-cross-origin");
  slide.insertBefore(iframe,slide.firstChild);
  heroTrailer={iframe:iframe,index:i,muted:!withSound};
  updateHeroTrailerBtns();
}
function updateHeroTrailerBtns(){
  var on=!!heroTrailer.iframe;
  var mute=document.getElementById("heroMute"),full=document.getElementById("heroFull");
  if(mute){mute.hidden=!on;mute.classList.toggle("is-muted",heroTrailer.muted);
    mute.setAttribute("aria-label",heroTrailer.muted?"Unmute trailer":"Mute trailer");}
  if(full)full.hidden=!on;
}
function heroToggleMute(){
  if(!heroTrailer.iframe)return;
  heroSetMuted(!heroTrailer.muted);
}
function heroSetMuted(m){
  heroTrailer.muted=m;
  ytCmd(heroTrailer.iframe,m?"mute":"unMute");
  updateHeroTrailerBtns();
}
function heroToggleFullscreen(){
  var hero=document.querySelector(".hero");
  if(document.fullscreenElement){if(document.exitFullscreen)document.exitFullscreen();}
  else if(hero&&hero.requestFullscreen){hero.requestFullscreen();}
}
if("IntersectionObserver" in window){
  var heroEl=document.querySelector(".hero");
  if(heroEl)new IntersectionObserver(function(entries){
    entries.forEach(function(en){
      heroInView=en.isIntersecting;
      if(!heroInView)heroTrailerStop();
      else if(!anyModalOpen())heroTrailerFor(heroIndex);
    });
  },{threshold:0.12}).observe(heroEl);
}
document.addEventListener("visibilitychange",function(){
  if(document.hidden)heroTrailerStop();
  else if(!anyModalOpen())heroTrailerFor(heroIndex);
});
/* Thumbnail markup, lifted verbatim from the live pre-autoplay facade path:
   local WebP art for curated titles, TMDB backdrop otherwise. */
function thumbMarkupFor(t,title){
  var localThumb=t&&t.image&&t.image.indexOf("assets/")===0;
  var src=localThumb?("assets/trailers/"+encodeURIComponent(t.id)+".jpg")
                    :((t&&(t.backdrop||t.image))||placeholderURI(t||{title:title}));
  return {src:src,local:!!localThumb,
    html:localThumb
      ?'<picture><source type="image/webp" srcset="assets/trailers/'+encodeURIComponent(t.id)+'.webp"><img src="'+esc(src)+'" alt="'+esc(title)+' trailer thumbnail" loading="lazy" decoding="async"></picture>'
      :'<img src="'+esc(src)+'" alt="'+esc(title)+' trailer thumbnail" loading="lazy" decoding="async">'};
}

/* ================= 7. SCHEDULE ================= */
var tonightEpisodes=[],scheduleExpanded=false;
var tlEps=[],tlStartMin=0,tlPxMin=0;
var tlEps=[],tlStartMin=0,tlPxMin=0;
function renderSchedule(){
  var now=new Date(),nowMs=now.getTime(),today=dateKeyPT(now),graceMs=30*60*1000;
  var fresh=freshnessLabel();
  document.getElementById("scheduleFresh").textContent=fresh?(" · "+fresh):"";
  tonightEpisodes=schedule.episodes.filter(function(ep){
    var air=new Date(ep.ts);
    if(isNaN(air.getTime()))return false;
    if(dateKeyPT(air)!==today)return false;
    if(ep.timed&&air.getTime()<nowMs-graceMs)return false;
    return true;
  }).sort(function(a,b){return new Date(a.ts)-new Date(b.ts);});
  renderScheduleRows();
  buildHero();
  renderTonightForYou();
  updateInboxBadge();
}
function nowLabelPT(d){
  var p=partsFor(d,{hour:"numeric",minute:"2-digit"});
  return part(p,"hour")+":"+part(p,"minute")+" "+part(p,"dayPeriod").toUpperCase();
}
function ptMinutes(d){
  var p=partsFor(d,{hour:"numeric",minute:"2-digit",hour12:false});
  return ((+part(p,"hour"))%24)*60+(+part(p,"minute"));
}
function airStatus(ep,nowMs){
  var air=new Date(ep.ts).getTime();
  if(air<=nowMs)return{tag:"ON NOW",live:true};
  if(air-nowMs<=90*60*1000)return{tag:"UP NEXT",live:false};
  return{tag:"TONIGHT",live:false};
}
function timelineCard(ep,i){
  /* Artwork-only timeline (approved 2026-09-24): a card renders only when
     real artwork exists. No monograms, no blank frames, no cheap
     placeholders — a show without artwork is excluded, never faked. */
  var res=timelineArt(ep);
  if(!res)return null;
  var t=res.kind==="catalog"?res.t:null,nowMs=Date.now(),st=airStatus(ep,nowMs);
  var meta=[episodeCode(ep),ep.ep?'"'+ep.ep+'"':"",ep.net].filter(Boolean).join(" · ");
  var art=artImgHTML(res.t,"",WIDE_SIZES,res.kind!=="catalog");
  var pill=ep.e===1?'<span class="new-pill">Season premiere</span>':(epIsNew(ep)?'<span class="new-pill">NEW</span>':"");
  var btn=document.createElement("button");
  btn.type="button";btn.className="tl-btn";btn.setAttribute("data-i",i);
  if(t)btn.setAttribute("data-dragid",t.id); /* drag-to-favorites: episode rows save the matched title */
  btn.setAttribute("aria-label",ep.show+" — "+timePT(ep)+(t?" — view details":" — view airing info"));
  btn.innerHTML='<article class="event">'+
    '<div class="art">'+art+'<span class="air"><small>'+st.tag+'</small>'+esc(timePT(ep))+'</span></div>'+
    '<div class="body"><h3>'+esc(ep.show)+pill+(st.live?'<span class="live-pill">On now</span>':"")+'</h3>'+
    '<p class="meta">'+esc(meta)+'</p>'+
    '<div class="foot"><span class="net">'+esc(ep.net||"TV")+'</span><span class="go">'+(t?"View details":"Airing info")+' →</span></div></div></article>';
  /* Artwork-only timeline: mark the card image so a load failure removes the
     card instead of swapping in a placeholder. */
  var artImg=btn.querySelector(".art img");
  if(artImg)artImg.setAttribute("data-hidecard","1");
  btn.addEventListener("click",function(){
    if(btn._pvDragged)return;
    if(t)openShow(t,btn);else openEpisode(ep,btn);
  });
  return btn;
}
function miniBtn(ep){
  var t=matchTitle(ep);
  var b=document.createElement("button");
  b.type="button";b.className="mini";
  if(t)b.setAttribute("data-dragid",t.id); /* drag-to-favorites: mini rows save the matched title */
  b.setAttribute("aria-label",ep.show+" — "+(ep.timed?timePT(ep):"streaming")+(t?" — view details":" — view airing info"));
  b.innerHTML='<span class="mt">'+esc(ep.timed?timePT(ep):"Streaming")+'</span><span class="mini-copy"><span class="ms">'+esc(ep.show)+'</span><span class="mn">'+esc(ep.net||"")+'</span></span>';
  b.addEventListener("click",function(){
    if(b._pvDragged)return;
    if(t)openShow(t,b);else openEpisode(ep,b);
  });
  return b;
}
function renderScheduleRows(){
  var timeline=document.getElementById("timeline"),
      emptyBox=document.getElementById("timelineEmpty"),
      toggle=document.getElementById("scheduleToggle"),
      nowMarker=document.getElementById("nowMarker"),
      streamStrip=document.getElementById("streamStrip"),
      streamGrid=document.getElementById("streamGrid"),
      earlierStrip=document.getElementById("earlierStrip"),
      earlierGrid=document.getElementById("earlierGrid");
  streamGrid.innerHTML="";earlierGrid.innerHTML="";
  streamStrip.hidden=true;earlierStrip.hidden=true;
  if(!tonightEpisodes.length){
    var today=dateKeyPT(new Date());
    emptyBox.hidden=false;timeline.hidden=true;
    emptyBox.textContent=today>schedule.maxDate?
      "The schedule is refreshing right now — check back in a bit for tonight's times.":
      "Nothing on tonight. Check back tomorrow — the lineup updates every day.";
    toggle.classList.remove("visible");
    return;
  }
  timeline.hidden=false;emptyBox.hidden=true;
  var now=new Date(),nowMs=now.getTime(),today=dateKeyPT(now),graceMs=30*60*1000;
  var timed=tonightEpisodes.filter(function(ep){return ep.timed;});
  /* Artwork-only timeline (approved 2026-09-24): only episodes with real
     artwork reach the timeline. Shows without artwork are hidden entirely. */
  var artTimed=timed.filter(function(ep){return timelineArt(ep);});
  var seenTs={};artTimed=artTimed.filter(function(ep){var k=ep.show+"|"+ep.ts;if(seenTs[k])return false;seenTs[k]=1;return true;});
  var visible=scheduleExpanded?artTimed:artTimed.slice(0,10);
  tlEps=visible;
  var startH=17,endH=22;
  if(artTimed.length){
    startH=24;endH=-1;
    artTimed.forEach(function(ep){
      var h=Math.floor(ptMinutes(new Date(ep.ts))/60);
      if(h<startH)startH=h;if(h>endH)endH=h;
    });
  }
  startH=Math.max(0,startH);endH=Math.min(23,Math.max(endH,startH));
  /* Hour-banded timeline (2026-09-26): each hour is a row; a card renders inside its
     badge's hour row, so cards always sit at their hour markers. No cascade drift. */
  var hoursBox=document.getElementById("timelineHours");
  hoursBox.innerHTML="";
  var byHour={};
  visible.forEach(function(ep){
    var hh=Math.floor(ptMinutes(new Date(ep.ts))/60);
    (byHour[hh]=byHour[hh]||[]).push(ep);
  });
  for(var h=startH;h<=endH;h++){
    var hr=h%12===0?12:h%12,ap=h<12?"AM":"PM";
    var dp=h===17?'<span class="daypart">Prime time</span>':(h===22?'<span class="daypart">Late night</span>':"");
    var row=document.createElement("div");
    row.className="tl-hrow";row.setAttribute("data-h",h);
    row.innerHTML='<div class="tl-tick"><div class="tick'+((h>=17&&h<=22)?" major":"")+'">'+dp+'<div class="t">'+hr+"<small>"+ap+"</small></div></div></div>"+
      '<div class="tl-hcards"></div>';
    var cell=row.querySelector(".tl-hcards");
    (byHour[h]||[]).forEach(function(ep){
      var c=timelineCard(ep,visible.indexOf(ep));
      if(c)cell.appendChild(c);
    });
    hoursBox.appendChild(row);
  }
  var ptNow=ptMinutes(now),nowH=Math.floor(ptNow/60);
  if(ptNow>=startH*60&&ptNow<=(endH+1)*60){
    var nowRow=hoursBox.querySelector('.tl-hrow[data-h="'+nowH+'"]');
    if(nowRow){
      nowMarker.style.display="flex";
      nowMarker.style.top=(nowRow.offsetTop+((ptNow-nowH*60)/60)*118)+"px";
      document.getElementById("nowPill").textContent="NOW · "+nowLabelPT(now);
    }else{nowMarker.style.display="none";}
  }else{nowMarker.style.display="none";}
  var streaming=tonightEpisodes.filter(function(ep){return !ep.timed;}).slice(0,6);
  if(streaming.length){
    streaming.forEach(function(ep){streamGrid.appendChild(miniBtn(ep));});
    streamStrip.hidden=false;
  }
  var earlier=schedule.episodes.filter(function(ep){
    var air=new Date(ep.ts);
    if(isNaN(air.getTime())||dateKeyPT(air)!==today||!ep.timed)return false;
    return air.getTime()<nowMs-graceMs;
  }).sort(function(a,b){return new Date(b.ts)-new Date(a.ts);}).slice(0,6);
  if(earlier.length){
    earlier.forEach(function(ep){earlierGrid.appendChild(miniBtn(ep));});
    earlierStrip.hidden=false;
  }
  if(artTimed.length>10){
    toggle.textContent=scheduleExpanded?"Show fewer":"Show all "+artTimed.length+" airings";
    toggle.classList.add("visible");
  }else toggle.classList.remove("visible");
}
function layoutTimeline(){/* Hour-banded timeline: CSS handles positioning; no cascade. */}
/* Unmatched rows (sports, news, specials) open an honest airing-info card. */
function openEpisode(ep,trigger){
  var when=dateLabelPT(new Date(ep.ts))+" at "+timePT(ep)+(ep.timed?" PT":"");
  openShow({
    id:"ep:"+normalizeText(ep.show)+":"+ep.ts,
    title:ep.show,type:"Airing",genre:ep.net||"",network:ep.net||"",
    meta:(ep.net||"TV")+" · "+timePT(ep)+(ep.timed?" PT":""),
    image:"",backdrop:"",trailer:"",cast:"",
    desc:(episodeCode(ep)?episodeCode(ep):"")+(ep.ep?' — "'+ep.ep+'"':"")+". Airs "+when+". Schedules change — check the network for the latest.",
    epInfo:true
  },trigger,{isEp:true});
}

/* ================= 8. HOME RAILS ================= */
function tonightFavTitles(){
  var seen={},out=[];
  tonightEpisodes.forEach(function(ep){
    var t=matchTitle(ep);
    if(t&&favs[t.id]&&!seen[t.id]){seen[t.id]=1;out.push(t);}
  });
  return out;
}
function renderTonightForYou(){
  var sec=document.getElementById("tonightForYouSection"),
      rail=document.getElementById("tonightForYou");
  if(!sec)return;
  var items=tonightFavTitles();
  sec.hidden=!items.length;
  rail.innerHTML="";
  items.forEach(function(t){rail.appendChild(posterCard(t,{isNew:true}));});
}
function pushRecent(id){
  recentIds=recentIds.filter(function(x){return x!==id;});
  recentIds.unshift(id);
  recentIds=recentIds.slice(0,12);
  store.set("recent",recentIds);
  renderRecent();
}
function renderRecent(){
  var sec=document.getElementById("recentSection"),rail=document.getElementById("recentRail");
  if(!sec)return;
  var items=recentIds.map(byId).filter(Boolean);
  sec.hidden=!items.length;
  rail.innerHTML="";
  items.forEach(function(t){rail.appendChild(posterCard(t));});
}

/* ================= 9. LIBRARY ================= */
function renderLibrary(){
  var grid=document.getElementById("libraryGrid"),
      empty=document.getElementById("libraryEmpty"),
      alerts=document.getElementById("libraryAlerts"),
      alertsList=document.getElementById("libraryAlertsList");
  if(!grid)return;
  var ids=Object.keys(favs).filter(function(id){return byId(id);})
    .sort(function(a,b){return (favs[b].added||0)-(favs[a].added||0);});
  grid.innerHTML="";
  ids.forEach(function(id){grid.appendChild(posterCard(byId(id)));});
  empty.classList.toggle("visible",!ids.length);
  var series=ids.filter(function(id){return byId(id).type==="Series";});
  alerts.hidden=!series.length;
  if(alertsList){
    alertsList.innerHTML="";
    series.forEach(function(id){
      var t=byId(id),on=!!(favs[id]&&favs[id].alert);
      var row=document.createElement("div");
      row.className="alert-row";
      row.innerHTML=artImgHTML(t,"")+
        '<div class="alert-copy"><h3>'+esc(t.title)+'</h3><p>'+(on?"Alerts on — we'll flag it in your inbox":"Alerts off")+'</p></div>';
      var tog=document.createElement("button");
      tog.type="button";tog.className="alert-toggle";
      tog.setAttribute("aria-pressed",on?"true":"false");
      tog.setAttribute("aria-label","Episode alerts for "+t.title);
      tog.addEventListener("click",function(){
        var nowOn=!(favs[id]&&favs[id].alert);
        if(!setAlert(id,nowOn))pvToast("Couldn't save that alert — your browser is blocking storage.","",null,"error");
      });
      row.appendChild(tog);
      alertsList.appendChild(row);
    });
  }
}

/* ================= 10. INBOX ================= */
function tonightAlertEps(){
  return tonightEpisodes.filter(function(ep){
    var t=matchTitle(ep);
    return t&&favs[t.id]&&favs[t.id].alert;
  });
}
function updateInboxBadge(){
  var badge=document.getElementById("inboxBadge");
  if(!badge)return;
  var unread=tonightAlertEps().filter(function(ep){
    var t=new Date(ep.ts).getTime();
    /* Only episodes that have actually aired count as unread: otherwise
       "Mark all read" can never clear the badge while later-tonight
       episodes are still upcoming. */
    return t>inboxRead&&t<=Date.now();
  }).length;
  badge.hidden=!unread;
  badge.textContent=unread>9?"9+":String(unread);
}
function comingSoonReminders(){
  /* Reminders set on the Coming Soon page land here — inbox first, email later. */
  var out=[];
  try{
    var raw=JSON.parse(localStorage.getItem("prev-comingsoon-notify")||"{}");
    Object.keys(raw).forEach(function(k){
      var r=raw[k];
      if(r&&r.date&&r.title)out.push(r);
    });
    out.sort(function(a,b){return a.date<b.date?-1:a.date>b.date?1:0;});
  }catch(e){}
  return out;
}
function removeReminder(id){
  try{
    var raw=JSON.parse(localStorage.getItem("prev-comingsoon-notify")||"{}");
    delete raw[id];
    localStorage.setItem("prev-comingsoon-notify",JSON.stringify(raw));
  }catch(e){}
  openInbox();
}
function openInbox(){
  var eps=tonightAlertEps(),list=document.getElementById("inboxList"),
      sub=document.getElementById("inboxSub"),
      rems=comingSoonReminders();
  list.innerHTML="";
  if(!eps.length&&!rems.length){
    sub.textContent="Star a show and turn its alerts on — tonight's episodes land here.";
    list.innerHTML='<div class="inbox-empty">Nothing on tonight for your alerted shows.<br>Your library is one tap away.</div>';
  }else{
    var parts=[];
    if(eps.length)parts.push(eps.length+" episode"+(eps.length===1?"":"s")+" tonight from shows you follow");
    if(rems.length)parts.push(rems.length+" coming-soon reminder"+(rems.length===1?"":"s"));
    sub.textContent=parts.join(" · ")+".";
    eps.forEach(function(ep){
      var t=matchTitle(ep);
      var meta=[episodeCode(ep),ep.ep,timePT(ep)+(ep.timed?" PT":"")].filter(Boolean).join(" · ");
      var item=document.createElement("button");
      item.type="button";item.className="inbox-item";
      item.setAttribute("aria-label","View details for "+t.title);
      item.innerHTML=artImgHTML(t,"")+
        '<span class="inbox-copy"><h3>'+esc(t.title)+'</h3><p>'+esc(meta)+'</p></span>';
      item.addEventListener("click",function(){closeModal("inboxModal");openShow(t,item);});
      list.appendChild(item);
    });
    if(rems.length){
      var div=document.createElement("div");
      div.className="inbox-div";
      div.textContent="Coming soon reminders";
      list.appendChild(div);
      rems.forEach(function(r){
        var d=new Date(r.date+"T00:00:00");
        var dline=d.toLocaleDateString("en-US",{month:"short",day:"numeric"})+" · "+d.toLocaleDateString("en-US",{weekday:"long"});
        var row=document.createElement("div");
        row.className="inbox-item inbox-rem";
        row.innerHTML='<img data-art="'+esc(r.title)+'" src="'+esc(r.img||"")+'" alt="" loading="lazy" decoding="async">'+
          '<span class="inbox-copy"><h3>'+esc(r.title)+'</h3><p>'+esc(dline+(r.meta?" · "+r.meta:""))+'</p></span>';
        var rm=document.createElement("button");
        rm.type="button";rm.className="text-link inbox-remove";
        rm.textContent="Remove";
        rm.setAttribute("aria-label","Remove reminder: "+r.title);
        (function(id){rm.addEventListener("click",function(ev){ev.stopPropagation();removeReminder(id);});})(r.id);
        row.appendChild(rm);
        list.appendChild(row);
      });
    }
  }
  openModal("inboxModal",document.getElementById("inboxBtn"));
}

/* ================= 11. DETAIL MODAL ================= */
var modalTitleId=null,lastFocus=null;
function openModal(id,trigger){
  lastFocus=trigger||document.activeElement;
  var modal=document.getElementById(id);
  modal.classList.add("open");
  modal.setAttribute("aria-hidden","false");
  document.body.classList.add("no-scroll");
  if(autoTimer){clearInterval(autoTimer);autoTimer=null;}
  document.getElementById("mainContent").inert=true;
  document.querySelector("header.topbar").inert=true;
  document.querySelector("footer").inert=true;
  setTimeout(function(){
    var focus=modal.querySelector("input,button,a[href]");
    if(focus)focus.focus();
  },80);
}
function closeModal(id){
  var modal=document.getElementById(id);
  modal.classList.remove("open");
  modal.setAttribute("aria-hidden","true");
  if(id==="showModal"){var ts=document.getElementById("trailerStageTop");if(ts)ts.innerHTML="";destroyTopPlayer();freePlayerStop();var wf=document.getElementById("wtwFreeSection");if(wf&&wf.parentNode)wf.parentNode.removeChild(wf);modalTitleId=null;}
  if(!document.querySelector(".modal.open")){
    document.body.classList.remove("no-scroll");
    document.getElementById("mainContent").inert=false;
    document.querySelector("header.topbar").inert=false;
    document.querySelector("footer").inert=false;
    restartHero();
  }
  if(lastFocus&&lastFocus.focus)lastFocus.focus();
}
function syncModalEngage(t){
  var s=document.getElementById("modalStar"),b=document.getElementById("modalBell");
  var on=isFav(t.id);
  s.setAttribute("aria-pressed",on?"true":"false");
  s.querySelector("span").textContent=on?"Saved":"Save";
  if(t.type==="Series"){
    b.hidden=false;
    b.setAttribute("aria-pressed",(favs[t.id]&&favs[t.id].alert)?"true":"false");
  }else b.hidden=true;
}
function openShow(t,trigger,opts){
  opts=opts||{};
  if(!t)return;
  heroTrailerStop(); /* one trailer at a time: the hero player yields to the modal */
  freePlayerStop(); /* a free movie in the top stage must not survive a title switch */
  modalTitleId=t.id;
  if(!opts.isEp)pushRecent(t.id);
  renderTrailer(t);
  var metaBits=[t.meta,t.genre].filter(Boolean);
  document.getElementById("modalMeta").textContent=metaBits.join(" · ");
  document.getElementById("modalTitle").textContent=t.title;
  document.getElementById("modalDescription").textContent=t.desc||"";
  var castEl=document.getElementById("modalCast");
  if(t.cast){castEl.innerHTML="<strong>Cast&nbsp;</strong>"+esc(t.cast);castEl.style.display="block";}
  else{castEl.style.display="none";castEl.innerHTML="";}
  var ratingEl=document.getElementById("modalRating");
  if(t.rating){
    var votes=t.votes?(" · "+compactVotes(t.votes)+" votes"):"";
    ratingEl.innerHTML="<strong>★ "+Number(t.rating).toFixed(1)+"</strong>"+esc(votes)+(t.year?esc(" · "+t.year):"");
    ratingEl.style.display="block";
  }else{ratingEl.style.display="none";ratingEl.innerHTML="";}
  var engage=document.querySelector(".modal-engage");
  engage.style.display=opts.isEp?"none":"flex";
  if(!opts.isEp)syncModalEngage(t);
  renderTrailer(t);
  renderWatchProviders(t,opts);
  renderWatchFree(t,opts);
  openModal("showModal",trigger);
  if(!opts.isEp&&typeof bingeProbe==="function")bingeProbe(t); /* Binge Calculator eligibility */
}
/* Where to watch — provider data baked at build time from TMDB /watch/providers
   (US, checked 2026-09-23). No live key in client code; no affiliate URLs. */
var WTW_DEST={
  "8":"https://www.netflix.com/","9":"https://www.primevideo.com/",
  "15":"https://www.hulu.com/","337":"https://www.disneyplus.com/",
  "384":"https://www.max.com/","350":"https://tv.apple.com/",
  "386":"https://www.peacocktv.com/","531":"https://www.paramountplus.com/",
  "192":"https://www.youtube.com/movies","68":"https://tv.microsoft.com/",
  "2":"https://tv.apple.com/","3":"https://play.google.com/store/movies",
  "7":"https://www.vudu.com/"
};
function wtwDestUrl(pid,kind,tmdbId,name){
  if(WTW_DEST[pid])return WTW_DEST[pid];
  if(kind&&(kind==="movie"||kind==="tv")&&/^\d+$/.test(String(tmdbId==null?"":tmdbId)))
    return "https://www.themoviedb.org/"+kind+"/"+encodeURIComponent(String(tmdbId))+"/watch?locale=US";
  return "https://www.google.com/search?q="+encodeURIComponent("watch "+name);
}
function renderWatchProviders(t,opts){
  var sec=document.getElementById("wtwSection");
  sec.innerHTML="";sec.hidden=true;
  if(!t||!sec||(opts&&opts.isEp))return;
  var head='<h3>Where to watch</h3><p class="wtw-disclosure">We may earn a commission when you sign up through these links.</p>';
  var fresh='<p class="wtw-fresh">Provider availability from TMDB &middot; checked Sept 23, 2026 &middot; US region. Lineups change &mdash; confirm with the service.</p>';
  var data=(window.PREVIOUSLY_WATCH_PROVIDERS||{})[t.id];
  var dir=window.PREVIOUSLY_WATCH_DIRECTORY||{};
  if(!data||(!data.f&&!data.r&&!data.b)){
    sec.hidden=false;
    sec.innerHTML=head+'<p class="wtw-empty">No streaming info available for this title right now.</p>'+fresh;
    return;
  }
  function card(pid,sub,primary){
    var info=dir[String(pid)]||["Service",""];
    var name=info[0]||"Service",logo=info[1]||"";
    var url=wtwDestUrl(String(pid),t.kind,t.tmdb,name);
    var img=logo?'<img class="wtw-logo" src="https://image.tmdb.org/t/p/w92'+logo+'" alt="" aria-hidden="true" loading="lazy" data-wtw-logo>':'<span class="wtw-logo" aria-hidden="true"></span>';
    return '<a class="wtw-svc'+(primary?" wtw-primary":"")+'" href="'+url+'" target="_blank" rel="noopener" aria-label="'+esc(name)+" — "+esc(sub)+' (opens in a new tab)">'+img+'<span class="wtw-txt"><b>'+esc(name)+'</b><span>'+esc(sub)+'</span></span>'+(primary?'<span class="wtw-tag">Watch now</span>':"")+"</a>";
  }
  function group(label,ids,sub){
    if(!ids||!ids.length)return "";
    var cards=ids.map(function(pid,i){return card(pid,sub,label==="Stream"&&i===0);}).join("");
    return '<div class="wtw-group"><div class="wtw-label">'+label+'</div><div class="wtw-btns">'+cards+"</div></div>";
  }
  sec.hidden=false;
  sec.innerHTML=head+group("Stream",data.f,"Subscription")+group("Rent",data.r,"Rent")+group("Buy",data.b,"Buy")+fresh;
  /* CSP hardening: no inline handlers — hide broken provider logos via listener (was onerror=). */
  var _logos=sec.querySelectorAll("img[data-wtw-logo]");
  for(var _li=0;_li<_logos.length;_li++)(function(_img){
    _img.addEventListener("error",function(){_img.style.display="none";});
  })(_logos[_li]);
}
/* ============ WATCH FREE (Phase 1 deep links + Phase 2 plays-here) ============
   Gate 3 staging, 2026-09-24. The Watch Free block lives in the title popup,
   BELOW the trailer/synopsis and ABOVE paid "Where to watch" (free first).
   It renders ONLY from real data:
     (a) TMDB free-provider entries baked in data/watch-providers.js
         (US, checked 2026-09-23) — filtered to the honest free set;
     (b) the verified free-play allowlist in data/free-catalog.js — 49
         official/rightsholder YouTube uploads, each oEmbed-verified
         (HTTP 200 + embed HTML) on 2026-09-24, re-checked monthly.
   A title with no free source gets NO section node at all — it is absent from
   the DOM, never hidden, never empty, never "coming soon".
   Deep-link honesty (spec 2.2): title-page patterns are NOT verified from the
   sandbox, so buttons link to the provider's verified search page (or homepage
   where even the search path is unverified) and carry "(search)" where they
   land on search. The monthly sweep re-verifies every pattern; a dead pattern
   drops the button rather than shipping a 404. */
var FREE_ADS_SOURCES=[
  /* TMDB provider id, display name, sub-label, URL builder. Order below is
     overridden at render by alphabetical sort (no paid placement). */
  {pid:"73",  name:"Tubi",           search:true, url:function(q){return "https://tubitv.com/search/"+encodeURIComponent(q);}},
  {pid:"300", name:"Pluto TV",       search:true, url:function(){return "https://pluto.tv/us/search";}},
  {pid:"207", name:"Roku Channel",   search:false,url:function(){return "https://therokuchannel.roku.com/";}},
  {pid:"538", name:"Plex",           search:true, url:function(q){return "https://watch.plex.tv/search?query="+encodeURIComponent(q);}},
  {pid:"2077",name:"Plex",           search:true, url:function(q){return "https://watch.plex.tv/search?query="+encodeURIComponent(q);}},
  {pid:"1963",name:"Xumo Play",      search:false,url:function(){return "https://play.xumo.com/";}}
];
var FREE_LIB_SOURCES=[
  {pid:"212", name:"Hoopla", url:function(){return "https://www.hoopladigital.com/";}},
  {pid:"191", name:"Kanopy", url:function(){return "https://www.kanopy.com/";}}
];
var freePlayer={iframe:null,seq:0,yt:null};
function freePlayerStop(){
  freePlayer.seq++; /* invalidate in-flight load callbacks and failure timers */
  if(freePlayer.yt){try{freePlayer.yt.destroy();}catch(e){} freePlayer.yt=null;}
  if(freePlayer.iframe){try{freePlayer.iframe.src="about:blank";}catch(e){}}
  freePlayer.iframe=null;
}
/* YouTube IFrame Player API, loaded lazily on the first free play so the
   player can report its own errors (101/150 embedding-disabled, 100 removed,
   153 restricted). The API host is allowlisted in the CSP meta tag. If the
   API can never load (offline/blocked), the 12s timer stays the backstop. */
var freeYTAPI={loading:false,queue:[]};
function freeYTEnsure(cb){
  if(window.YT&&YT.Player){cb();return;}
  freeYTAPI.queue.push(cb);
  if(freeYTAPI.loading)return;
  freeYTAPI.loading=true;
  var s=document.createElement("script");
  s.src="https://www.youtube.com/iframe_api";s.async=true;
  s.onerror=function(){freeYTAPI.loading=false;freeYTAPI.queue=[];};
  document.head.appendChild(s);
  var prev=window.onYouTubeIframeAPIReady;
  window.onYouTubeIframeAPIReady=function(){
    if(prev){try{prev();}catch(e){}}
    freeYTAPI.loading=false;
    var q=freeYTAPI.queue;freeYTAPI.queue=[];
    for(var i=0;i<q.length;i++){try{q[i]();}catch(e){}}
  };
}
/* Honest fallback card inside the top stage: the video cannot play on the
   site (owner disabled embedding, removed it, or restricted it).
   Never a gray YouTube error box. */
function freeTopFallback(t,entry,my){
  if(my!==freePlayer.seq)return; /* a newer attempt owns the stage */
  freePlayerStop();
  var stage=document.getElementById("trailerStageTop");
  if(!stage||!stage.isConnected)return;
  stage.innerHTML='<div class="top-free-fallback" role="status"><p>Couldn\u2019t load this title.</p>'+
    '<p class="free-fb-sub">The owner may have disabled embedding or removed the video.</p>'+
    '<button type="button" class="cta free-retry">Try again</button></div>';
  var rb=stage.querySelector(".free-retry");
  if(rb)rb.addEventListener("click",function(){
    /* Honest retry: a fresh attempt, immediately. The click is a user
       gesture, so the movie starts right away — no second tap on play. */
    freeTopPlayAttempt(t,entry);
  });
}
function freeNorm(s){
  return normalizeText(s).replace(/[^a-z0-9]/g,"");
}
function freeCatalogFind(title,ytId){
  var cat=window.PREVIOUSLY_FREE_CATALOG||[],nt=freeNorm(title),i,e;
  if(ytId){for(i=0;i<cat.length;i++){e=cat[i];if(e&&e.id===ytId)return e;}}
  for(i=0;i<cat.length;i++){e=cat[i];if(e&&freeNorm(e.t)===nt)return e;}
  return null;
}
function freeProviderCard(src,pid,sub,dir,t){
  var info=dir[String(pid)]||[src.name,""],logo=info[1]||"";
  var url=src.url(t.title||"");
  var img=logo?'<img class="wtw-logo" src="https://image.tmdb.org/t/p/w92'+logo+'" alt="" aria-hidden="true" loading="lazy" data-wtw-logo>':'<span class="wtw-logo" aria-hidden="true"></span>';
  var ariaName=src.name+(src.search?" (search)":"")+" — "+sub;
  return '<a class="wtw-svc" href="'+esc(url)+'" target="_blank" rel="noopener" aria-label="'+esc(ariaName)+' (opens in a new tab)">'+img+'<span class="wtw-txt"><b>'+esc(src.name)+(src.search?'<span class="wtw-search-tag"> (search)</span>':"")+'</b><span>'+esc(sub)+'</span></span></a>';
}
function watchFreeHTML(t){
  var data=(window.PREVIOUSLY_WATCH_PROVIDERS||{})[t.id]||{};
  var dir=window.PREVIOUSLY_WATCH_DIRECTORY||{};
  var freeIds=data.f||[];
  var seen={},ads=[],lib=[],i,p;
  for(i=0;i<freeIds.length;i++){
    var pid=String(freeIds[i]),j,src=null,lib2=false;
    for(j=0;j<FREE_ADS_SOURCES.length;j++)if(FREE_ADS_SOURCES[j].pid===pid)src=FREE_ADS_SOURCES[j];
    for(j=0;j<FREE_LIB_SOURCES.length;j++)if(FREE_LIB_SOURCES[j].pid===pid){src=FREE_LIB_SOURCES[j];lib2=true;}
    if(!src||seen[src.name])continue;seen[src.name]=true;
    (lib2?lib:ads).push({src:src,pid:pid});
  }
  ads.sort(function(a,b){return a.src.name.localeCompare(b.src.name);});
  lib.sort(function(a,b){return a.src.name.localeCompare(b.src.name);});
  var entry=freeCatalogFind(t.title,t.freeYtId);
  if(!ads.length&&!lib.length&&!entry)return "";
  var out='<h3>Watch free &mdash; plays here where available</h3>'+
    '<p class="wtw-disclosure">Every legal free option for this title, in one place.</p>';
  if(entry){
    var tm=thumbMarkupFor(t,t.title);
    out+='<div class="free-plays-head">'+
      '<span class="free-src">YouTube &middot; '+esc(entry.channel||"Official upload")+'</span></div>'+
      '<div class="trailer-stage free-stage" aria-label="Free full playback">'+
      '<button type="button" class="trailer-facade" id="freePlayBtn" aria-label="Play '+esc(t.title)+' free \u2014 full movie">'+
      tm.html.replace('alt="'+esc(t.title)+' trailer thumbnail"','alt="'+esc(t.title)+' full movie thumbnail"')+
      '<span class="trailer-play" aria-hidden="true">\u25B6</span><span class="trailer-loading">Loading&hellip;</span>'+
      '</button></div>'+
      '<p class="free-disc">Free with ads (YouTube) &mdash; ads support the studio that posted it.</p>';
  }
  function group(label,cls,items,sub){
    if(!items.length)return "";
    var cards=items.map(function(x){return freeProviderCard(x.src,x.pid,sub(x),dir,t);}).join("");
    return '<div class="wtw-group"><div class="wtw-label'+(cls?" "+cls:"")+'">'+label+'</div><div class="wtw-btns">'+cards+'</div></div>';
  }
  out+=group("Free with ads","free-ads",ads,function(x){return x.src.search?"Free with ads on "+x.src.name+" (search)":"Free with ads on "+x.src.name;});
  out+=group("Free with library card","",lib,function(x){return "Free on "+x.src.name+" \u2014 library card required";});
  out+='';
  return out;
}
/* The full movie plays in the large top stage (#trailerStageTop) — the same
   hero player the trailers use, with mute + fullscreen controls.
   The tap is the user gesture, so the attempt starts with sound on. */
function freeTopPlayAttempt(t,entry){
  /* One play attempt, fenced by a monotonic sequence: if the popup closes,
     the title switches, or Retry fires, freePlayerStop() bumps the sequence
     and every stale load/timeout callback bails out. */
  var stage=document.getElementById("trailerStageTop");
  if(!stage||!entry)return;
  freePlayerStop(); /* stop any trailer/free playback; this attempt owns the stage */
  destroyTopPlayer();
  if(typeof heroTrailerStop==="function")heroTrailerStop();
  var my=freePlayer.seq;
  var note=document.getElementById("noTrailerNote");if(note)note.hidden=true;
  setStageArt(stage,t);
  var badge=document.createElement("span");
  badge.className="free-now";badge.textContent="Free \u00b7 Full movie";
  stage.appendChild(badge);
  var box=document.createElement("div");box.className="player";
  var iframe=document.createElement("iframe");
  iframe.title=t.title+" \u2014 free on YouTube";
  iframe.src="https://www.youtube-nocookie.com/embed/"+encodeURIComponent(entry.id)+
    "?autoplay=1&rel=0&playsinline=1&enablejsapi=1";
  iframe.allow="autoplay; encrypted-media; picture-in-picture";
  iframe.setAttribute("referrerpolicy","strict-origin-when-cross-origin");
  iframe.allowFullscreen=true;
  var ld=document.createElement("span");
  ld.className="trailer-loading visible";ld.textContent="Loading\u2026";
  stage.appendChild(ld);
  var done=false;
  iframe.addEventListener("load",function(){
    if(my!==freePlayer.seq)return; /* stale: closed, switched, or retried */
    done=true;
    ld.classList.remove("visible");
  },{once:true});
  box.appendChild(iframe);
  /* stage controls: mute toggle + fullscreen, like the trailers */
  var ctrls=document.createElement("div");ctrls.className="stage-ctrls";
  var muted=false;
  var muteBtn=document.createElement("button");
  muteBtn.type="button";muteBtn.className="stage-btn";muteBtn.setAttribute("aria-label","Mute");
  muteBtn.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><g><path d="M4 9v6h4l5 4V5L8 9H4z" fill="currentColor" stroke="none"/><path d="M16 9a4.2 4.2 0 010 6M18.5 6.5a8 8 0 010 11" stroke-linecap="round"/></g><g><path d="M4 9v6h4l5 4V5L8 9H4z" fill="currentColor" stroke="none"/><path d="M16 9l6 6M22 9l-6 6" stroke-linecap="round"/></g></svg>';
  var onG=muteBtn.querySelectorAll("g")[0],offG=muteBtn.querySelectorAll("g")[1];
  offG.style.display="none"; /* CSP: no style attributes in innerHTML — CSSOM is allowed */
  muteBtn.addEventListener("click",function(){
    if(my!==freePlayer.seq)return;
    muted=!muted;
    try{
      iframe.contentWindow.postMessage(JSON.stringify({event:"command",func:muted?"mute":"unMute",args:[]}),"https://www.youtube-nocookie.com");
      iframe.contentWindow.postMessage(JSON.stringify({event:"command",func:"setVolume",args:[muted?0:80]}),"https://www.youtube-nocookie.com");
    }catch(e){}
    muteBtn.setAttribute("aria-label",muted?"Unmute":"Mute");
    onG.style.display=muted?"none":"";offG.style.display=muted?"":"none";
  });
  var fsBtn=document.createElement("button");
  fsBtn.type="button";fsBtn.className="stage-btn";fsBtn.setAttribute("aria-label","Watch fullscreen");
  fsBtn.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5" stroke-linecap="round" stroke-linejoin="round"/></svg>';
  fsBtn.addEventListener("click",function(){
    if(my!==freePlayer.seq)return;
    try{
      if(stage.requestFullscreen)stage.requestFullscreen();
      else if(stage.webkitRequestFullscreen)stage.webkitRequestFullscreen();
    }catch(e){}
  });
  ctrls.appendChild(muteBtn);ctrls.appendChild(fsBtn);
  stage.appendChild(box);stage.appendChild(ctrls);
  freePlayer.iframe=iframe;
  /* the large player is at the top: bring it into view inside the popup */
  var mcard=document.querySelector("#showModal .modal-card");
  if(mcard){try{mcard.scrollTo({top:0,behavior:"smooth"});}catch(e){mcard.scrollTop=0;}}
  /* Failure path 1: the iframe never loads (blocked network). Failure path 2
     (below, via the IFrame API): YouTube loads its own error screen inside
     the player — the load event fires, so this timer alone can never catch
     embedding-disabled videos. */
  setTimeout(function(){
    if(my!==freePlayer.seq)return; /* a newer attempt owns the stage */
    if(done||!iframe.isConnected)return;
    freeTopFallback(t,entry,my);
  },12000);
  /* Failure path 2: listen to the player's own error events. On 101/150
     (embedding disabled), 100 (removed), 153/5 (restricted/broken), swap
     the stage for the honest fallback card immediately. */
  freeYTEnsure(function(){
    if(my!==freePlayer.seq)return;
    try{
      var player=new YT.Player(iframe,{events:{onError:function(e){
        if(my!==freePlayer.seq)return;
        var code=e&&e.data;
        if(code===101||code===150||code===100||code===153||code===5){
          freeTopFallback(t,entry,my);
        }
      }}});
      freePlayer.yt=player;
    }catch(err){/* API bind failed: the 12s timer stays the backstop */}
  });
}
function wireFreePlayer(sec,t){
  var btn=document.getElementById("freePlayBtn");
  if(!btn)return;
  var entry=freeCatalogFind(t.title,t.freeYtId);
  if(!entry)return;
  btn.addEventListener("click",function(){
    /* the facade tap is the gesture: the full movie starts in the large
       top stage — same hero player as the trailers. */
    freeTopPlayAttempt(t,entry);
  });
}
function renderWatchFree(t,opts){
  freePlayerStop();
  var old=document.getElementById("wtwFreeSection");
  if(old&&old.parentNode)old.parentNode.removeChild(old);
  if(!t||!opts||opts.isEp)return;
  var html=watchFreeHTML(t);
  if(!html)return; /* no free source: the node stays absent from the DOM */
  var sec=document.createElement("div");
  sec.className="wtw wtw-free";sec.id="wtwFreeSection";
  sec.setAttribute("aria-label","Watch free");
  sec.innerHTML=html;
  var wtw=document.getElementById("wtwSection");
  wtw.parentNode.insertBefore(sec,wtw);
  wireFreePlayer(sec,t);
  /* CSP: no inline handlers — hide broken provider logos via listener. */
  var _fl=sec.querySelectorAll("img[data-wtw-logo]");
  for(var _fi=0;_fi<_fl.length;_fi++)(function(_img){
    _img.addEventListener("error",function(){_img.style.display="none";});
  })(_fl[_fi]);
}
function compactVotes(v){
  v=Number(v)||0;
  if(v>=1e6)return (v/1e6).toFixed(1)+"M";
  if(v>=1e3)return (v/1e3).toFixed(1)+"k";
  return String(v);
}
/* ---------- Trailer at the top of the title-detail popup (2026-09-24 Gate 2 Rev 2) ----------
   Full-bleed stage ABOVE the title: no right-side dead space, same Emerald play
   treatment as the rest of the site. Verified pool keys win over catalog keys
   (the pool was oEmbed-checked); only verified, Trailer-type pool entries
   autoplay. The reusable player is destroyed when the popup closes. */
var topPlayer={iframe:null,muted:true,seq:0};
function setStageArt(stage,t){
  stage.innerHTML='<img class="stage-art" alt="'+esc(t.title)+' key art">';
  var img=stage.querySelector(".stage-art");
  var src=artSrc(t,true);
  var lw=localWebpFor(src);
  var tm=/^(https:\/\/image\.tmdb\.org\/t\/p\/)w\d+(\/.+)$/.exec(src);
  if(lw&&lw.set){img.src=src;img.setAttribute("srcset",lw.set);img.setAttribute("sizes",WIDE_SIZES);}
  else if(tm){img.src=src;img.setAttribute("srcset",tm[1]+"w342"+tm[2]+" 342w, "+tm[1]+"w780"+tm[2]+" 780w");img.setAttribute("sizes",WIDE_SIZES);}
  else{img.src=src;img.removeAttribute("srcset");img.removeAttribute("sizes");}
  img.onerror=function(){
    if(img.getAttribute("data-art-swapped"))return;
    img.setAttribute("data-art-swapped","1");
    img.onerror=null;
    img.removeAttribute("srcset");img.removeAttribute("sizes");
    img.src=placeholderURI({title:t.title});
  };
}
function destroyTopPlayer(){topPlayer.seq++;topPlayer.iframe=null;topPlayer.muted=true;}
function mountTopTrailer(stage,key,t){
  var my=topPlayer.seq;
  setStageArt(stage,t);
  var muted=true;
  var box=document.createElement("div");box.className="player";
  var iframe=document.createElement("iframe");
  iframe.setAttribute("allowfullscreen","");
  iframe.setAttribute("allow","autoplay; encrypted-media; picture-in-picture");
  iframe.title=esc(t.title)+" trailer";
  iframe.src="https://www.youtube-nocookie.com/embed/"+key+"?autoplay=1&mute=1&rel=0&enablejsapi=1";
  iframe.addEventListener("load",function(){
    if(my!==topPlayer.seq)return;
    try{
      iframe.contentWindow.postMessage(JSON.stringify({event:"command",func:"setVolume",args:[0]}),"https://www.youtube-nocookie.com");
      iframe.contentWindow.postMessage(JSON.stringify({event:"command",func:"mute",args:[]}),"https://www.youtube-nocookie.com");
    }catch(e){}
    topPlayer.muted=true;
  });
  box.appendChild(iframe);
  var ctrls=document.createElement("div");ctrls.className="stage-ctrls";
  var muteBtn=document.createElement("button");muteBtn.type="button";muteBtn.className="stage-btn";
  muteBtn.setAttribute("aria-label","Unmute trailer");
  muteBtn.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M11 5 6 9H2v6h4l5 4V5z"/><path class="snd-on is-off" d="M15.5 8.5a5 5 0 0 1 0 7"/><path class="snd-off" d="m16 9 6 6M22 9l-6 6"/></svg>';
  muteBtn.addEventListener("click",function(){
    if(my!==topPlayer.seq)return;
    muted=!muted;
    try{
      iframe.contentWindow.postMessage(JSON.stringify({event:"command",func:muted?"mute":"unMute",args:[]}),"https://www.youtube-nocookie.com");
      iframe.contentWindow.postMessage(JSON.stringify({event:"command",func:"setVolume",args:[muted?0:80]}),"https://www.youtube-nocookie.com");
    }catch(e){}
    topPlayer.muted=muted;
    muteBtn.setAttribute("aria-label",muted?"Unmute trailer":"Mute trailer");
    muteBtn.querySelector(".snd-on").style.display=muted?"none":"";
    muteBtn.querySelector(".snd-off").style.display=muted?"":"none";
  });
  var fsBtn=document.createElement("button");fsBtn.type="button";fsBtn.className="stage-btn";
  fsBtn.setAttribute("aria-label","Watch trailer fullscreen");
  fsBtn.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>';
  fsBtn.addEventListener("click",function(){
    if(my!==topPlayer.seq)return;
    try{if(box.requestFullscreen)box.requestFullscreen();
    else if(box.webkitRequestFullscreen)box.webkitRequestFullscreen();}catch(e){}
  });
  ctrls.appendChild(muteBtn);ctrls.appendChild(fsBtn);
  box.appendChild(ctrls);
  stage.appendChild(box);
  topPlayer.iframe=iframe;
  topPlayer.muted=true;
}
function mountTopFacade(stage,key,title,t){
  setStageArt(stage,t);
  var facade=document.createElement("button");
  facade.type="button";facade.className="trailer-facade";
  facade.setAttribute("aria-label","Play trailer for "+title);
  facade.innerHTML=thumbMarkupFor(t,title).html+'<span class="play-wrap"><span class="play-btn" aria-hidden="true"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></span><span class="watch-label">Watch trailer</span></span><span class="trailer-loading">Loading trailer\u2026</span>';
  facade.addEventListener("click",function(){
    facade.querySelector(".trailer-loading").classList.add("visible");
    mountTopTrailer(stage,key,t);
  });
  stage.appendChild(facade);
}
function renderTrailer(t){
  var stage=document.getElementById("trailerStageTop");
  var note=document.getElementById("noTrailerNote");
  stage.innerHTML="";destroyTopPlayer();
  /* Verified pool keys win over catalog keys (the pool was oEmbed-checked).
     Only verified, Trailer-type pool entries autoplay. */
  var poolX=poolFind(t.title);
  var key=(poolX&&poolX.youtube_key)||(t.trailer||"");
  if(!key){
    setStageArt(stage,t);
    note.hidden=false;
    return;
  }
  note.hidden=true;
  if(trailerMotionOK()){mountTopTrailer(stage,key,t);return;}
  /* Tap-to-play facade: reduced-motion, Save-Data, or small screens. */
  mountTopFacade(stage,key,t.title,t);
}

/* ================= 12. BROWSE ================= */
var currentGenre="all",browseShown=60,BROWSE_PAGE=60;
var byVotes=function(a,b){return (b.votes||0)-(a.votes||0);};

/* ============ DAY-SEEDED ROTATION (no hardcoded pins) ============
   James 2026-09-24: the same 12 starter titles were pinned to the front of
   every home section (and varnell/drop/signs filled any empty hero slot),
   so the site showed the same faces on every visit. Every home surface now
   rotates deterministically by Pacific day over the FULL merged catalog:
   the same order all day on every device, a new order tomorrow, and a
   pool/stride pairing chosen so no title repeats within 7 days. */
var DAY_MS=86400000;
function dayIndexPT(){
  var k=dateKeyPT(new Date()).split("-");
  return Math.floor(Date.UTC(+k[0],+k[1]-1,+k[2])/DAY_MS);
}
/* First `count` titles of the day's rotated block. `stride` is the section's
   page size, so consecutive days share nothing on the visible page and
   day d+7 lands on a different block (stride*7 < pool). Deterministic. */
function dayBlock(pool,count,stride){
  var n=pool.length;if(!n||count<1)return[];
  var off=((dayIndexPT()*stride)%n+n)%n,out=[];
  for(var k=0;k<n&&out.length<count;k++)out.push(pool[(off+k)%n]);
  return out;
}
/* Day-rotated pick that also skips ids already used (hero fallback). */
function dayPick(pool,count,stride,seen){
  var n=pool.length;if(!n)return[];
  var off=((dayIndexPT()*stride)%n+n)%n,out=[];
  for(var k=0;k<n&&out.length<count;k++){
    var t=pool[(off+k)%n];
    var nt=normalizeText(t.title);
    if(seen&&(seen[t.id]||seen["nt:"+nt]))continue;
    if(seen){seen[t.id]=true;seen["nt:"+nt]=true;}
    out.push(t);
  }
  return out;
}
/* Rotation pools: the full merged catalog, most-voted first (never pinned). */
function heroPool(){
  return titles.filter(function(t){return (t.backdrop||t.image)&&heroTitleOK(t,true);}).sort(byVotes).slice(0,200);
}
function spotlightPool(){
  return titles.filter(function(t){return t.type==="Series"&&(t.backdrop||t.image);}).sort(byVotes).slice(0,60);
}
function widePool(){
  return titles.filter(function(t){return t.backdrop||t.image;}).sort(byVotes).slice(0,240);
}
function filteredTitles(){
  var q=normalizeText(document.getElementById("catalogSearch").value.trim());
  return titles.filter(function(t,i){
    var typeMatch=currentGenre==="all"||
      (currentGenre==="favorites"&&isFav(t.id))||
      (currentGenre==="series"&&t.type==="Series")||
      (currentGenre==="movie"&&t.type==="Movie")||
      (genrePillDef(currentGenre)?genreTokenMatch(t,currentGenre):(normalizeText(t.genre).indexOf(currentGenre)>-1));
    return typeMatch&&(!q||searchHay[i].indexOf(q)>-1);
  });
}
function renderCatalog(){
  var list=filteredTitles();
  if(browseShown>list.length)browseShown=list.length;
  var el=document.getElementById("catalog");
  el.innerHTML="";
  list.slice(0,browseShown).forEach(function(t){el.appendChild(posterCard(t));});
  var more=document.getElementById("showMore");
  more.hidden=browseShown>=list.length;
  more.textContent="Show more ("+(list.length-browseShown)+" of "+list.length+")";
  document.getElementById("emptyState").classList.toggle("visible",!list.length);
}
function setFilter(filter){
  var target=document.querySelector('.chip[data-genre="'+CSS.escape(String(filter))+'"]')||document.querySelector('.chip[data-genre="all"]');
  currentGenre=target.dataset.genre;
  browseShown=BROWSE_PAGE;
  document.querySelectorAll(".chip").forEach(function(c){
    var active=c===target;
    c.classList.toggle("active",active);
    c.setAttribute("aria-pressed",active?"true":"false");
  });
  skelRender("catalog","catalog",10,"card",renderCatalog);
}
/* ================= GENRE PILL SLIDER (rev2 logic tucked into Browse) ============
   The 22 approved display genres render as a horizontal pill slider at the top
   of Browse. Token mapping is the approved Genre rev2 mapping (TMDB-faithful). */
var GENRE_PILLS=[
 {id:"drama",name:"Drama",tokens:["Drama"]},
 {id:"comedy",name:"Comedy",tokens:["Comedy"]},
 {id:"action",name:"Action",tokens:["Action","Action & Adventure"]},
 {id:"adventure",name:"Adventure",tokens:["Adventure","Action & Adventure"]},
 {id:"animation",name:"Animation",tokens:["Animation"]},
 {id:"crime",name:"Crime",tokens:["Crime"]},
 {id:"documentary",name:"Documentary",tokens:["Documentary"]},
 {id:"fantasy",name:"Fantasy",tokens:["Fantasy","Sci-Fi & Fantasy"]},
 {id:"history",name:"History",tokens:["History"]},
 {id:"horror",name:"Horror",tokens:["Horror"]},
 {id:"kids",name:"Kids & Family",tokens:["Kids","Family"]},
 {id:"music",name:"Music",tokens:["Music"]},
 {id:"mystery",name:"Mystery",tokens:["Mystery"]},
 {id:"news",name:"News",tokens:["News"]},
 {id:"reality",name:"Reality",tokens:["Reality"]},
 {id:"romance",name:"Romance",tokens:["Romance"]},
 {id:"scifi",name:"Sci-Fi",tokens:["Science Fiction","Sci-Fi & Fantasy"]},
 {id:"soap",name:"Soap",tokens:["Soap"]},
 {id:"talk",name:"Talk",tokens:["Talk"]},
 {id:"thriller",name:"Thriller",tokens:["Thriller"]},
 {id:"war",name:"War",tokens:["War","War & Politics"]},
 {id:"western",name:"Western",tokens:["Western"]}
];
function genrePillDef(id){ for(var i=0;i<GENRE_PILLS.length;i++) if(GENRE_PILLS[i].id===id) return GENRE_PILLS[i]; return null; }
function genreTokensOf(t){ var out=[]; String(t.genre||"").split(/[,\u00B7]/).forEach(function(part){ var pp=normalizeText(part.trim()); if(pp) out.push(pp); }); return out; }
function genreTokenMatch(t,id){ var def=genrePillDef(id); if(!def) return false; var toks=def.tokens.map(function(x){ return normalizeText(x); }); var gt=genreTokensOf(t); for(var j=0;j<gt.length;j++) if(toks.indexOf(gt[j])>-1) return true; return false; }
function genrePillCount(id){ var n=0; for(var k=0;k<titles.length;k++) if(genreTokenMatch(titles[k],id)) n++; return n; }
function renderGenrePills(){
  var host=document.getElementById("genrePills"); if(!host) return;
  if(!host.getAttribute("data-done")){
    host.setAttribute("data-done","1");
    var html="";
    for(var i=0;i<GENRE_PILLS.length;i++){ var g=GENRE_PILLS[i];
      html+='<button class="chip" type="button" data-genre="'+g.id+'" aria-pressed="false">'+esc(g.name)+'<span class="gct" data-gct="'+g.id+'"></span></button>'; }
    host.innerHTML=html;
    var pills=host.querySelectorAll(".chip");
    for(var b=0;b<pills.length;b++){ (function(c){ c.addEventListener("click",function(){ setFilter(c.getAttribute("data-genre")); }); })(pills[b]); }
  }
  var spans=host.querySelectorAll("[data-gct]");
  for(var s=0;s<spans.length;s++){ spans[s].textContent=genrePillCount(spans[s].getAttribute("data-gct")).toLocaleString("en-US"); }
}
/* ================= TOP 10 CHARTS =================
   Ranks come from the hourly trending pipeline (server-side only; the browser
   never touches TMDB). Rank numerals are never invented: 404/503/network
   failure renders the designed empty state — never catalog filler.
   QA-only simulation: ?top10=fresh|stale|short|empty loads
   data/top10-fixture.json instead of the live API; ?top10=live (or no param)
   uses the live route. */
var TOP10_API="https://previously-freshness.james-moore2013.workers.dev/api/trending";
var TOP10_GENRE_TV={"10759":"Action & Adventure","16":"Animation","35":"Comedy","80":"Crime","99":"Documentary","18":"Drama","10751":"Family","10762":"Kids","9648":"Mystery","10763":"News","10764":"Reality","10765":"Sci-Fi & Fantasy","10766":"Soap","10767":"Talk","10768":"War & Politics","37":"Western"};
var TOP10_GENRE_MOVIE={"28":"Action","12":"Adventure","16":"Animation","35":"Comedy","80":"Crime","99":"Documentary","18":"Drama","10751":"Family","14":"Fantasy","36":"History","27":"Horror","10402":"Music","9648":"Mystery","10749":"Romance","878":"Science Fiction","10770":"TV Movie","53":"Thriller","10752":"War","37":"Western"};
var TOP10_STALE_MS=2*36e5;
var top10Data=null; /* cached trending payload: {tv:[],movies:[],updatedAt} */
function top10Mode(){
  var m=(location.search.match(/[?&]top10=([a-z]+)/)||[])[1]||"live";
  return (m==="fresh"||m==="stale"||m==="short"||m==="empty")?m:"live";
}
function top10GenreName(item){
  var map=item.media_type==="tv"?TOP10_GENRE_TV:TOP10_GENRE_MOVIE;
  var id=(item.genre_ids&&item.genre_ids[0]!=null)?String(item.genre_ids[0]):"";
  return map[id]||"";
}
/* Prefer the site catalog entry (same id shape: tmdb-{kind}-{tmdb}) so the
   modal, favorites, recents, trailer, and provider blocks work fully.
   Unmatched items become minimal honest titles — openShow already handles
   empty trailer / no providers / no rating honestly. */
function top10Title(item){
  var key="tmdb-"+item.media_type+"-"+item.tmdb_id;
  var cat=byId(key);
  if(cat)return cat;
  var year=(item.first_air_date||item.release_date||"").slice(0,4);
  return {
    id:key,
    title:item.title||"Untitled",
    type:item.media_type==="tv"?"Series":"Film",
    genre:top10GenreName(item),
    image:item.poster_path?("https://image.tmdb.org/t/p/w780"+item.poster_path):"",
    backdrop:item.backdrop_path?("https://image.tmdb.org/t/p/w1280"+item.backdrop_path):"",
    trailer:"",cast:"",
    desc:item.overview||"",
    rating:item.vote_average!=null?Math.round(item.vote_average*10)/10:null,
    votes:0,
    year:year||"",
    kind:item.media_type,tmdb:item.tmdb_id
  };
}
function top10FreshText(updatedAt,stale){
  var ms=typeof updatedAt==="number"?updatedAt:Date.parse(updatedAt);
  if(isNaN(ms))return "Trending now";
  var mins=Math.max(0,(Date.now()-ms)/6e4);
  var ago;
  if(mins<1)ago="just now";
  else if(mins<60)ago=Math.floor(mins)+" min ago";
  else if(mins<48*60)ago=Math.floor(mins/60)+"h ago";
  else ago=Math.floor(mins/1440)+"d ago";
  return stale?("Last updated "+ago+" — refreshing."):("Updated "+ago);
}
function top10Card(t,rank,chartName){
  var btn=document.createElement("button");
  btn.type="button";btn.className="tcard";btn.setAttribute("role","listitem");
  btn.setAttribute("aria-label","View details for "+t.title+", ranked #"+rank+" in "+chartName+".");
  var genre=esc(t.genre||"");
  /* Badge follows the approved mockups: "TV" / "Film" (catalog uses "Series"/"Movie"). */
  var badge=(t.kind==="tv"||t.type==="Series")?"TV":"Film";
  var rate=t.rating!=null?'<span class="trate">★ '+Number(t.rating).toFixed(1)+"</span>":"";
  var sep=(genre&&rate)?" · ":"";
  btn.innerHTML=
    '<span class="artwrap"><span class="art">'+artImgHTML(t,t.title+" key art")+
    '<span class="ptype">'+badge+"</span>"+
    (genre?'<span class="pgenre">'+genre+"</span>":"")+
    '<span class="ptitle">'+esc(t.title)+"</span></span>"+
    '<span class="rank'+(rank===1?" r1":"")+'" aria-hidden="true">'+rank+"</span></span>"+
    '<span class="meta"><span class="t">'+esc(t.title)+'</span><span class="g">'+genre+sep+rate+"</span></span>";
  btn.addEventListener("click",function(){openShow(t,btn);});
  return btn;
}
function top10RenderChart(cfg,items,updatedAt){
  var rail=document.getElementById(cfg.rail),fresh=document.getElementById(cfg.fresh);
  if(!rail||!fresh)return;
  clearSkeletons(rail);
  var list=(items||[]).slice(0,10).map(top10Title);
  var n=list.length;
  var feedMs=typeof updatedAt==="number"?updatedAt:Date.parse(updatedAt);
  var stale=!isNaN(feedMs)&&(Date.now()-feedMs)>TOP10_STALE_MS;
  /* Header stays honest about the real count — never padded, never faked. */
  var chartName=(n>0&&n<10)?("Top "+n+" "+cfg.plural):("Top 10 "+cfg.plural);
  document.getElementById(cfg.eyebrow).textContent=(n>0&&n<10)?("Top "+n+" · "+cfg.kindLabel):("Top 10 · "+cfg.kindLabel);
  document.getElementById(cfg.title).textContent=chartName+".";
  rail.setAttribute("aria-label",chartName);
  rail.classList.toggle("is-empty",!n);
  if(!n){
    /* Empty: no rank numerals at all — the designed update state. */
    rail.innerHTML="";
    fresh.innerHTML="";fresh.classList.remove("stale");
    var empty=document.createElement("div");
    empty.className="top10-empty";
    empty.innerHTML='<h3>The Top 10 is updating.</h3><p>Fresh ranks land every hour — check back shortly.</p>';
    var btn=document.createElement("button");
    btn.type="button";btn.className="cta secondary";btn.setAttribute("data-go","browse");
    btn.textContent="Browse the full catalog";
    btn.addEventListener("click",function(){showView("browse");});
    empty.appendChild(btn);
    rail.appendChild(empty);
    return;
  }
  fresh.classList.toggle("stale",stale);
  fresh.innerHTML='<span class="dot" aria-hidden="true"></span>'+esc(top10FreshText(updatedAt,stale));
  rail.innerHTML="";
  list.forEach(function(t,i){rail.appendChild(top10Card(t,i+1,chartName));});
}
var TOP10_CFG=[
  {rail:"top10TvRail",fresh:"top10TvFresh",eyebrow:"top10-tv-eyebrow",title:"top10-tv-title",kindLabel:"TV",plural:"TV Shows",feed:"tv"},
  {rail:"top10MovieRail",fresh:"top10MovieFresh",eyebrow:"top10-movie-eyebrow",title:"top10-movie-title",kindLabel:"Movies",plural:"Movies",feed:"movies"}
];
/* Arrow-key horizontal scroll when a chart rail is focused (cards stay in tab
   order natively; the digit itself is the rank — never color alone). */
function top10InitKeys(){
  TOP10_CFG.forEach(function(cfg){
    var rail=document.getElementById(cfg.rail);
    if(!rail||rail._top10Keys)return;rail._top10Keys=true;
    rail.addEventListener("keydown",function(e){
      if(e.key!=="ArrowRight"&&e.key!=="ArrowLeft")return;
      var card=rail.querySelector(".tcard,.skel");
      var step=card?card.getBoundingClientRect().width+14:240;
      rail.scrollBy({left:(e.key==="ArrowRight"?1:-1)*step,behavior:"smooth"});
      e.preventDefault();
    });
  });
}
function renderTop10(){
  if(!document.getElementById("top10TvRail"))return;
  top10InitKeys();
  if(top10Data){renderTop10Charts();return;}
  TOP10_CFG.forEach(function(cfg){
    var rail=document.getElementById(cfg.rail);
    showSkeletons(rail,10,"card");
  });
  var mode=top10Mode();
  var url=mode==="live"?TOP10_API:"data/top10-fixture.json";
  fetch(url,{cache:"no-store"}).then(function(res){
    if(!res.ok)throw new Error("HTTP "+res.status);
    return res.json();
  }).then(function(payload){
    if(mode!=="live"){
      /* QA fixture: per-state timestamps are computed at demo time so the
         states stay honest no matter when the demo runs. */
      var fx=payload[mode]||{tv:[],movies:[]};
      var agoMin=fx.updatedAtAgoMin||0;
      top10Data={tv:fx.tv||[],movies:fx.movies||[],updatedAt:agoMin?Date.now()-agoMin*6e4:Date.now()};
    }else{
      top10Data={tv:payload.tv||[],movies:payload.movies||[],updatedAt:payload.updatedAt||null};
    }
    renderTop10Charts();
  }).catch(function(){
    /* Any failure (404/503/offline) → the honest empty state. */
    top10Data={tv:[],movies:[],updatedAt:null};
    renderTop10Charts();
  });
}
function renderTop10Charts(){
  if(!top10Data)return;
  TOP10_CFG.forEach(function(cfg){
    top10RenderChart(cfg,top10Data[cfg.feed],top10Data.updatedAt);
  });
}
function renderWide(){
  var grid=document.getElementById("wideGrid");
  grid.innerHTML="";
  /* Day-rotated wide cards from the full catalog (any title with backdrop
     art) — the three pinned starter wide cards are gone. */
  dayBlock(widePool(),12,12).forEach(function(t){grid.appendChild(wideCard(t));});
}
/* Editorial spotlight: one rotating pick a day from the full catalog.
   The eyebrow stays honest ("Spotlight") since the pick is no longer
   guaranteed to be a new season. */
function renderSpotlight(){
  var art=document.querySelector(".spotlight");if(!art)return;
  var pick=dayBlock(spotlightPool(),1,1)[0];if(!pick)return;
  var src=artSrc(pick,true),lw=(typeof localWebpFor==="function")?localWebpFor(src):null;
  var webpSet=lw?(lw.set||lw.single):"";
  art.innerHTML=
    '<div class="spotlight-copy"><div class="eyebrow">Spotlight</div>'+
    '<h2 id="spot-title">'+heroTitleMarkup(pick.title)+"</h2>"+
    "<p>"+esc(pick.desc||"")+"</p>"+
    '<button class="cta" id="spotCta" type="button">View details</button></div>'+
    '<div class="spotlight-media"><picture>'+
    (webpSet?'<source type="image/webp" srcset="'+esc(webpSet)+'" sizes="(max-width:600px) 100vw, 45vw">':"")+
    '<img src="'+esc(src)+'" alt="'+esc(pick.title)+' key art" loading="lazy" decoding="async"></picture></div>';
  document.getElementById("spotCta").addEventListener("click",function(){openShow(pick,this);});
}

/* ================= 13. ROUTER ================= */
var VIEWS=["home","browse","free","podcasts","library","account","how-we-rank","terms","privacy","cookies","dmca","affiliates"];
function viewFromHash(){
  var h=location.hash.replace(/^#\/?/,"");
  var params={};
  var qi=h.indexOf("?");
  if(qi>-1){
    h.slice(qi+1).split("&").forEach(function(p){
      var kv=p.split("=");
      if(kv[0])params[decodeURIComponent(kv[0])]=decodeURIComponent(kv[1]||"");
    });
    h=h.slice(0,qi);
  }
  window.__PV=window.__PV||{};
  window.__PV.hashParams=params;
  return VIEWS.indexOf(h)>-1?h:"home";
}
function showView(name,preset,fromHistory){
  if(VIEWS.indexOf(name)<0)name="home";
  /* the account view requires a signed-in session */
  if(name==="account" && !(window.ACCT && window.ACCT.signedIn())){ name="home"; }
  var open=document.querySelector(".modal.open");
  if(open)closeModal(open.id);
  document.querySelectorAll(".view").forEach(function(v){
    v.classList.toggle("active",v.id==="view-"+name);
  });
  document.querySelectorAll(".nav-btn").forEach(function(b){
    var active=b.dataset.view===name;
    b.classList.toggle("active",active);
    if(active)b.setAttribute("aria-current","page");else b.removeAttribute("aria-current");
  });
  window.scrollTo({top:0,left:0,behavior:"instant"});
  var viewMeta={
    home:{title:"Previously — What to watch, and when",desc:"Tonight's TV lineup in Pacific time, every show and movie in one search, and the open beta."},
    browse:{title:"Browse — Previously",desc:"Search every show and movie on Previously — series and films, trailers, and airtimes."},
    library:{title:"Library — Previously",desc:"Your Previously library — star shows, get tonight's inbox, and carry your lineup into the app."},
    account:{title:"Account Settings — Previously",desc:"Your Previously account settings — profile, streaming services, appearance, and notifications."},
    free:{title:"Free on YouTube — Previously",desc:"Every free movie on Previously — official YouTube uploads, free with ads."},
    podcasts:{title:"Podcasts — Previously",desc:"144 video-first podcasts, streaming from official YouTube channels — hip-hop, comedy, fight sports, and more."},
    terms:{title:"Terms — Previously",desc:"Previously terms of use."},
    privacy:{title:"Privacy — Previously",desc:"How Previously handles your information."},
    cookies:{title:"Cookie Notice — Previously",desc:"Previously doesn't use cookies. How on-device storage works."},
    dmca:{title:"Copyright & DMCA — Previously",desc:"How to report copyright issues on Previously."},
    affiliates:{title:"Affiliate Disclosure — Previously",desc:"How Previously makes money, and the rules that don't bend."},
    "how-we-rank":{title:"How We Rank — Previously",desc:"No one pays for placement on Previously. How every part of the site is ordered, in plain English."}
  };
  var vm=viewMeta[name]||viewMeta.home;
  document.title=vm.title;
  var metaDesc=document.querySelector('meta[name="description"]');
  if(metaDesc)metaDesc.setAttribute("content",vm.desc);
  if(name==="home")restartHero();
  else if(autoTimer){clearInterval(autoTimer);autoTimer=null;}
  if(!fromHistory){
    var route={browse:"#/browse",free:"#/free",podcasts:"#/podcasts",library:"#/library",account:"#/account","how-we-rank":"#/how-we-rank",terms:"#/terms",privacy:"#/privacy",
      cookies:"#/cookies",dmca:"#/dmca",affiliates:"#/affiliates"}[name];
    history.pushState({view:name},"",route||(location.pathname+location.search));
  }
  if(name==="browse"){
    if(preset)setFilter(preset);
    if(window.matchMedia("(pointer:fine)").matches)setTimeout(function(){
      document.getElementById("catalogSearch").focus();
    },120);
  }
  if(name==="library"){ renderLibrary(); }
  if(name==="free"&&!fromHistory&&window.PV_FREE)window.PV_FREE.resetView(); /* nav click resets Free filter to match the #/free URL */
  if(name==="account" && window.ACCT && typeof window.ACCT.renderAccountView === "function"){ window.ACCT.renderAccountView(); }
}

/* ================= 14. BETA SIGNUP (previously-beta Worker + D1 — our own endpoint) ================= */
/* DEPLOY: BETA_ENDPOINT is the beta-signup Worker created in the Cloudflare dashboard.
   Option A (recommended, no edit needed): give the worker the custom domain
   beta.watchpreviously.com (Workers & Pages → previously-beta → Settings →
   Domains & Routes → Add custom domain). Cloudflare adds the DNS automatically.
   Option B: paste the worker's https://previously-beta.<subdomain>.workers.dev
   URL here instead, then redeploy the Pages project. */
var BETA_ENDPOINT="https://beta.watchpreviously.com";
function requestText(){
  var name=document.getElementById("betaName").value.trim()||"[Your name]",
      email=document.getElementById("betaEmail").value.trim()||"[Your email]",
      device=document.getElementById("betaDevice").value;
  return "Previously open beta request\n\nName: "+name+"\nEmail: "+email+"\nPrimary device: "+device;
}
function updateEmailLinks(){
  var href="mailto:beta@watchpreviously.com?subject="+encodeURIComponent("Previously open beta request")+
    "&body="+encodeURIComponent(requestText());
  document.getElementById("betaEmailLink").href=href;
  document.getElementById("openEmail").href=href;
}
function setStatus(message,error){
  var el=document.getElementById("formStatus");
  el.textContent=message;
  el.classList.add("visible");
  el.classList.toggle("error",!!error);
}
function fallbackCopy(text){
  var area=document.createElement("textarea");
  area.className="copy-buffer";area.value=text;area.setAttribute("readonly","");
  document.body.appendChild(area);area.focus();area.select();
  area.setSelectionRange(0,area.value.length);
  var ok=false;try{ok=document.execCommand("copy");}catch(e){ok=false;}
  document.body.removeChild(area);return ok;
}
function copyRequest(){
  var form=document.getElementById("betaForm");
  if(!form.reportValidity())return;
  var text=requestText(),
      modern=navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(text):Promise.reject();
  modern.then(function(){setStatus("Request copied. Paste it into an email to beta@watchpreviously.com.",false);},
  function(){
    if(fallbackCopy(text))setStatus("Request copied. Paste it into an email to beta@watchpreviously.com.",false);
    else{setStatus("Copy is blocked here. Use Open email below—the recipient, subject, and request are already filled in.",true);
      document.getElementById("manualFallback").classList.add("prominent");
      pvToast("Copy is blocked in this browser — use Open email below instead.","",null,"error");}
  });
}

/* ================= 15. WIRING + BOOT ================= */
document.querySelectorAll("[data-view]").forEach(function(b){
  b.addEventListener("click",function(){showView(b.dataset.view,b.dataset.filter);});
});
document.querySelectorAll("[data-go]").forEach(function(b){
  b.addEventListener("click",function(){showView(b.dataset.go,b.dataset.filter);});
});
document.querySelectorAll("[data-beta-open]").forEach(function(b){
  b.addEventListener("click",function(){
    var open=document.querySelector(".modal.open");
    if(open)closeModal(open.id);
    openModal("betaModal",b);updateEmailLinks();
  });
});
document.querySelectorAll("[data-modal-close]").forEach(function(b){
  b.addEventListener("click",function(){closeModal(b.dataset.modalClose);});
});
document.querySelectorAll("[data-show]").forEach(function(b){
  b.addEventListener("click",function(){openShow(byId(b.dataset.show),b);});
});
document.querySelectorAll(".modal").forEach(function(m){
  m.addEventListener("click",function(e){if(e.target===m)closeModal(m.id);});
});
document.getElementById("heroDetails").addEventListener("click",function(){
  if(!heroItems.length)return;openShow(heroItems[heroIndex].title,this);
});
document.getElementById("heroMute").addEventListener("click",function(){heroToggleMute();});
document.getElementById("heroFull").addEventListener("click",function(){heroToggleFullscreen();});
document.querySelectorAll(".hero-dot").forEach(function(dot){
  dot.addEventListener("click",function(){setHero(Number(dot.dataset.hero),true);});
});
document.getElementById("scheduleToggle").addEventListener("click",function(){
  scheduleExpanded=!scheduleExpanded;skelRender("timeline","scheduleList",4,"row",renderScheduleRows);
});
var tlResizeT=null;
window.addEventListener("resize",function(){
  if(tlResizeT)clearTimeout(tlResizeT);
  tlResizeT=setTimeout(function(){
    if(document.getElementById("timeline")&&!document.getElementById("timeline").hidden)renderScheduleRows();
  },250);
});
var searchT=null;
document.getElementById("catalogSearch").addEventListener("input",function(){
  if(searchT)clearTimeout(searchT);
  searchT=setTimeout(function(){browseShown=BROWSE_PAGE;skelRender("catalog","catalog",10,"card",renderCatalog);},180);
});
document.getElementById("emptyClear").addEventListener("click",function(){
  document.getElementById("catalogSearch").value="";setFilter("all");
});
document.getElementById("showMore").addEventListener("click",function(){
  browseShown+=BROWSE_PAGE;skelRender("catalog","catalog",10,"card",renderCatalog);
});
document.querySelectorAll(".chip").forEach(function(c){
  c.addEventListener("click",function(){setFilter(c.dataset.genre);});
});
document.getElementById("inboxBtn").addEventListener("click",openInbox);
document.getElementById("inboxClear").addEventListener("click",function(){
  inboxRead=Date.now();store.set("inboxRead",inboxRead);
  updateInboxBadge();openInbox();
});
document.getElementById("clearRecent").addEventListener("click",function(){
  recentIds=[];store.set("recent",recentIds);renderRecent();
});
document.getElementById("modalStar").addEventListener("click",function(){
  if(!modalTitleId)return;
  var on=toggleFav(modalTitleId),b=this;
  if(on){b.classList.remove("pop");void b.offsetWidth;b.classList.add("pop");}
});
document.getElementById("modalBell").addEventListener("click",function(){
  if(!modalTitleId)return;
  var t=byId(modalTitleId);if(!t)return;
  var nowOn=!(favs[modalTitleId]&&favs[modalTitleId].alert);
  if(!setAlert(modalTitleId,nowOn))pvToast("Couldn't save that alert — your browser is blocking storage.","",null,"error");
  if(nowOn){this.classList.remove("ring");void this.offsetWidth;this.classList.add("ring");}
});
  /* ============ Catch-Up / Binge Calculator (Gate 2 approved 2026-09-24) ============
     Server-side data only: GET /api/seasons?media_type=tv&tmdb_id= (the worker
     holds the TMDB key; the browser never touches it). The premiere date used
     here is the shared nextPremiere contract — the marquee-ticket share screen
     reads the same field, so the two features can never contradict each other.
     Per-show settings + watched progress stay device-local (accounts aren't live). */
  var BC_PROBE_TTL=6*60*60*1000, BC_MAX_DAY=8;
  function bcTmdbOf(t){
    var m=t&&t.id&&String(t.id).match(/^tmdb-(tv|movie)-(\d+)$/);
    if(m)return{mediaType:m[1]==="tv"?"tv":"movie",id:m[2],isSeries:m[1]==="tv"&&t.type==="Series"};
    /* Starter-catalog slug ids (e.g. "bear") win title collisions by design, so
       resolve them to the same show's TMDB entry by title. The detail keeps its
       curated display data; only the calculator uses the TMDB identity. */
    if(t&&t.title&&typeof normalizeText==="function"){
      var want=normalizeText(t.title),arr=window.PREVIOUSLY_CATALOG||[];
      for(var i=0;i<arr.length;i++){
        var c=arr[i];
        if(c&&c.id!==t.id&&c.title&&normalizeText(c.title)===want)return bcTmdbOf(c);
      }
    }
    return null;
  }
  function bcTodayStr(){var d=new Date();function p(n){return String(n).padStart(2,"0");}return d.getFullYear()+"-"+p(d.getMonth()+1)+"-"+p(d.getDate());}
  function bcDaysBetween(a,b){return Math.round((Date.parse(a+"T00:00:00")-Date.parse(b+"T00:00:00"))/86400000);}
  function bcGet(k){try{var v=localStorage.getItem(k);return v?JSON.parse(v):null;}catch(e){return null;}}
  function bcSet(k,v){try{localStorage.setItem(k,JSON.stringify(v));}catch(e){}}
  function bcFmtDate(iso){try{return new Date(iso+"T00:00:00").toLocaleDateString("en-US",{month:"short",day:"numeric"});}catch(e){return iso;}}
  function bcHM(min){min=Math.round(min);var h=Math.floor(min/60),m=min%60;return h>0?(h+"h"+(m?" "+m+"m":"")):(m+"m");}
  var bc={title:null,tmdb:null,probe:null,full:null,allLoaded:false,h:2,buffer:30,pacing:"even",earlier:false,watched:{},err:null};
  function bcKeyEp(sn,n){return "S"+sn+"E"+n;}
  function bcPersistSettings(){if(bc.tmdb)bcSet("bc-settings:"+bc.tmdb.id,{h:bc.h,buffer:bc.buffer,pacing:bc.pacing,earlier:bc.earlier});}
  function bcPersistWatched(){if(bc.tmdb)bcSet("bc-watched:"+bc.tmdb.id,Object.keys(bc.watched));}
  /* ---- eligibility probe: runs when a title detail opens ---- */
  function bingeProbe(t){
    var btn=document.getElementById("modalBinge");
    bc.probe=null;bc.title=null;bc.tmdb=null;
    if(btn)btn.hidden=true;
    var info=bcTmdbOf(t);
    if(!info||!info.isSeries)return;
    bc.tmdb=info;
    var myId=t.id;
    var cached=bcGet("bc-probe:"+info.id);
    if(cached&&cached.data&&Date.now()-cached.ts<BC_PROBE_TTL){bcApplyProbe(myId,t,cached.data);return;}
    fetch("https://previously-freshness.james-moore2013.workers.dev/api/seasons?media_type=tv&tmdb_id="+encodeURIComponent(info.id)+"&seasons=prev")
      .then(function(r){if(!r.ok)throw new Error("http "+r.status);return r.json();})
      .then(function(j){
        if(!j||!j.ok||typeof j.mode!=="string")return; /* stay hidden: progressive enhancement */
        bcSet("bc-probe:"+info.id,{ts:Date.now(),data:j});
        bcApplyProbe(myId,t,j);
      })
      .catch(function(){/* stay hidden on network failure */});
  }
  function bcApplyProbe(myId,t,j){
    if(typeof modalTitleId==="undefined"||modalTitleId!==myId)return; /* user moved on */
    bc.probe=j;bc.title=t;
    var btn=document.getElementById("modalBinge");
    if(btn)btn.hidden=!(j.mode==="catchup"||j.mode==="leisure");
  }
  /* ---- open ---- */
  function bcOpen(){
    if(!bc.probe||!bc.title||!bc.tmdb)return;
    var st=bcGet("bc-settings:"+bc.tmdb.id)||{};
    bc.h=(typeof st.h==="number"&&st.h>0)?st.h:2;
    bc.buffer=(typeof st.buffer==="number")?st.buffer:30;
    bc.pacing=st.pacing==="front"?"front":"even";
    bc.earlier=!!st.earlier;
    bc.watched={};(bcGet("bc-watched:"+bc.tmdb.id)||[]).forEach(function(k){bc.watched[k]=1;});
    bc.full=null;bc.allLoaded=false;bc.err=null;
    document.getElementById("bcTitle").textContent="Loading your plan…";
    document.getElementById("bcSub").textContent="";
    document.getElementById("bcEpisodes").innerHTML="";
    document.getElementById("bcNote").textContent="";
    document.querySelector(".bc-eps-head").style.display="";
    document.getElementById("bcAdjust").hidden=true;
    document.getElementById("bcAdjustBtn").setAttribute("aria-expanded","false");
    openModal("bingeModal",document.getElementById("modalBinge"));
    /* openModal's 80ms focus fires mid-transition (still hidden); focus for real
       after it. Retried once in case load delays the transition; never steals
       focus that already moved inside. */
    (function bcFocusCalc(attempt){
      setTimeout(function(){
        var m=document.getElementById("bingeModal");
        if(!m||!m.classList.contains("open"))return;
        if(m.contains(document.activeElement))return;
        var c=m.querySelector(".modal-close");
        if(c)c.focus();
        if(attempt<1)bcFocusCalc(attempt+1);
      },attempt?900:320);
    })(0);
    bcFetchFull(bc.earlier);
  }
  function bcFetchFull(all){
    var info=bc.tmdb;if(!info)return;
    fetch("https://previously-freshness.james-moore2013.workers.dev/api/seasons?media_type=tv&tmdb_id="+encodeURIComponent(info.id)+"&seasons="+(all?"all":"prev"))
      .then(function(r){if(!r.ok)throw new Error("http "+r.status);return r.json();})
      .then(function(j){
        if(!j||!j.ok)throw new Error("bad payload");
        bc.probe=j;bc.full=j;bc.err=null;
        bcSet("bc-probe:"+info.id,{ts:Date.now(),data:j});
        if(all)bc.allLoaded=true;
        bcRender();
      })
      .catch(function(){bc.err=true;bcRender();});
  }
  /* ---- pure plan math ---- */
  function bcCollectEps(){
    var out=[];
    if(!bc.full||!bc.full.seasons)return out;
    var withEps=bc.full.seasons.filter(function(s){return s&&Array.isArray(s.episodes);});
    var view=bc.earlier?withEps:withEps.slice(-1); /* default: immediately previous season */
    view.forEach(function(s){
      s.episodes.forEach(function(e){out.push({sn:s.season_number,n:e.n,name:e.name,runtime:e.runtime});});
    });
    return out;
  }
  function bcPlan(){
    var p=bc.probe;if(!p)return{state:"loading"};
    if(bc.err)return{state:"error"};
    if(!bc.full)return{state:"loading"};
    var eps=bcCollectEps();
    var failedSeason=bc.full.seasons.some(function(s){return s&&s.episodes===null&&s.episode_count>0;});
    if(!eps.length)return{state:failedSeason?"error":"fresh",eps:eps};
    var watched=function(e){return !!bc.watched[bcKeyEp(e.sn,e.n)];};
    var un=eps.filter(function(e){return !watched(e);});
    if(!un.length)return{state:"caughtup",eps:eps,total:eps.length};
    var known=un.filter(function(e){return e.runtime!=null;});
    var avg=known.length?known.reduce(function(a,e){return a+e.runtime;},0)/known.length:null;
    if(avg==null)return{state:"noruntime",eps:eps,total:eps.length};
    var est=un.filter(function(e){return e.runtime==null;}).length;
    var totalMin=Math.round(un.reduce(function(a,e){return a+(e.runtime!=null?e.runtime:avg);},0))+bc.buffer;
    var base={eps:eps,un:un,avg:avg,est:est,totalMin:totalMin};
    var np=p.nextPremiere;
    if(p.mode==="catchup"&&np){
      if(!np.air_date)return Object.assign({state:"tba",seasonN:np.season_number},base);
      var daysLeft=bcDaysBetween(np.air_date,bcTodayStr());
      if(daysLeft<=0)return Object.assign({state:"sprint",seasonN:np.season_number,airDate:np.air_date},base);
      var reqH=Math.ceil(totalMin/60/daysLeft*2)/2;
      var st=reqH<=bc.h?"comfortable":(reqH<=BC_MAX_DAY?"tight":"impossible");
      return Object.assign({state:st,seasonN:np.season_number,airDate:np.air_date,daysLeft:daysLeft,reqH:reqH},base);
    }
    if(p.mode==="leisure"&&p.recentAired){
      var days=Math.max(1,Math.ceil(totalMin/60/bc.h));
      return Object.assign({state:"leisure",seasonN:p.recentAired.season_number,airDate:p.recentAired.air_date,days:days},base);
    }
    return Object.assign({state:"fresh"},base);
  }
  function bcPacingLine(plan){
    if(plan.state!=="comfortable"&&plan.state!=="tight"&&plan.state!=="impossible")return"";
    if(bc.pacing!=="front")return"Even pace: about "+Math.ceil(plan.totalMin/plan.daysLeft)+" min a day.";
    var first=Math.ceil(plan.daysLeft/2),rest=Math.max(1,plan.daysLeft-first);
    var hi=Math.ceil(plan.totalMin*0.6/first),lo=Math.ceil(plan.totalMin*0.4/rest);
    return"Front-loaded: about "+hi+" min on early days, easing to "+lo+" min near the end.";
  }
  /* ---- render ---- */
  function bcShow(ids,show){ids.forEach(function(id){var el=document.getElementById(id);if(el)el.style.display=show?"":"none";});}
  function bcRender(){
    var plan=bcPlan();
    var title=document.getElementById("bcTitle"),sub=document.getElementById("bcSub"),
        note=document.getElementById("bcNote"),epsEl=document.getElementById("bcEpisodes"),
        epsHead=document.querySelector(".bc-eps-head");
    title.classList.remove("is-bad");
    bcShow(["bcChips","bcEarlier","bcAdjustBtn"],false);
    var adjust=document.getElementById("bcAdjust");
    var bcWasOpen=!adjust.hidden;
    adjust.hidden=true;
    document.getElementById("bcAdjustBtn").setAttribute("aria-expanded","false");
    epsHead.style.display="";epsEl.style.display="";note.textContent="";note.innerHTML="";
    /* sync controls */
    Array.prototype.forEach.call(document.querySelectorAll("#bcChips .bc-chip"),function(c){c.classList.toggle("is-on",Number(c.getAttribute("data-h"))===bc.h);});
    document.getElementById("bcHoursVal").textContent=bc.h.toFixed(1);
    Array.prototype.forEach.call(document.querySelectorAll("#bcBuffer button"),function(b){b.classList.toggle("is-on",Number(b.getAttribute("data-b"))===bc.buffer);});
    Array.prototype.forEach.call(document.querySelectorAll("#bcPacing button"),function(b){b.classList.toggle("is-on",b.getAttribute("data-p")===bc.pacing);});
    var eb=document.getElementById("bcEarlier");eb.setAttribute("aria-pressed",bc.earlier?"true":"false");
    var withEps=bc.full&&bc.full.seasons?bc.full.seasons.filter(function(s){return (s.episode_count||0)>0;}).length:0;
    eb.style.visibility=withEps>1?"visible":"hidden";
    if(withEps>1)document.getElementById("bcEarlierLabel").textContent="Include earlier seasons ("+(withEps-1)+" more)";
    function rtLabel(e){
      if(e.runtime!=null)return e.runtime+" min";
      return "≈"+Math.round(plan.avg||0)+" min*";
    }
    function epRows(list){
      epsEl.innerHTML="";
      var lastSn=null;
      list.forEach(function(e){
        if(bc.earlier&&e.sn!==lastSn){var lab=document.createElement("div");lab.className="bc-season-label";lab.textContent="Season "+e.sn;epsEl.appendChild(lab);lastSn=e.sn;}
        var b=document.createElement("button");b.type="button";
        var key=bcKeyEp(e.sn,e.n),w=!!bc.watched[key];
        b.className="bc-ep"+(w?" is-watched":"");
        b.setAttribute("aria-pressed",w?"true":"false");
        b.setAttribute("aria-label",(w?"Mark unwatched: ":"Mark watched: ")+"Season "+e.sn+" episode "+e.n+", "+e.name);
        b.innerHTML='<span class="bc-check" aria-hidden="true">✓</span><span class="bc-ep-main"><span class="bc-ep-name"></span></span><span class="bc-ep-rt"></span>';
        b.querySelector(".bc-ep-name").textContent="S"+e.sn+" E"+e.n+" · "+e.name;
        b.querySelector(".bc-ep-rt").textContent=rtLabel(e);
        (function(k){b.addEventListener("click",function(){var wasOn=!!bc.watched[k];if(wasOn)delete bc.watched[k];else bc.watched[k]=1;bcPersistWatched();bcRender();
          /* account sync: history + continue-watching (no-op unless signed in) */
          try{
            if(window.ACCT && typeof window.ACCT.bcEpisodeToggled === "function"){
              var snap=(plan&&plan.eps)?plan.eps.filter(function(e){return !!bc.watched[bcKeyEp(e.sn,e.n)];}):[];
              window.ACCT.bcEpisodeToggled(plan,k,!wasOn,snap);
            }
          }catch(acctErr){}
        });})(key);
        epsEl.appendChild(b);
      });
    }
    function estNote(){return plan.est>0?' <span class="bc-est">*≈ means estimated</span> from this season\u2019s known runtimes':"";}
    if(plan.state==="loading"){title.textContent="Loading your plan…";sub.textContent="Pulling real episode data.";epsHead.style.display="none";return;}
    if(plan.state==="error"){
      title.textContent="We couldn't load the episode list right now.";
      sub.textContent="The connection dropped before the real data arrived — nothing here is guessed.";
      epsHead.style.display="none";
      var rb=document.createElement("button");rb.type="button";rb.className="cta compact bc-retry";rb.textContent="Try again";
      rb.addEventListener("click",function(){bc.err=null;title.textContent="Loading your plan…";bcFetchFull(bc.earlier);});
      note.appendChild(rb);return;
    }
    if(plan.state==="fresh"){
      var np=bc.probe.nextPremiere;
      title.textContent=np&&np.air_date?("Season "+np.season_number+" drops "+bcFmtDate(np.air_date)+" — nothing to catch up on yet."):"A new season is on its way — nothing to catch up on yet.";
      sub.textContent="There's no earlier season to binge for this one. We'll build you a plan the moment there's something to watch.";
      epsHead.style.display="none";return;
    }
    if(plan.state==="tba"){
      title.textContent="Date TBA — we can't build a countdown plan yet.";
      sub.textContent="Season "+plan.seasonN+" is announced but undated. Mark episodes below if you like — your countdown appears the moment the date drops.";
      epRows(plan.eps);
      document.getElementById("bcEpsTitle").textContent="Episodes to watch";
      note.innerHTML="Runtimes are real TMDB data."+estNote()+".";
      return;
    }
    if(plan.state==="noruntime"){
      title.textContent="We don't have runtimes for these episodes yet.";
      sub.textContent="Without real episode lengths we won't guess a plan. Check back — the moment TMDB lists runtimes, your countdown is ready.";
      epsHead.style.display="none";return;
    }
    if(plan.state==="caughtup"){
      var cnp=bc.probe.nextPremiere;
      title.textContent="You're all caught up — enjoy the premiere.";
      sub.textContent="Every episode is checked off."+(cnp?(" Season "+cnp.season_number+" can't come soon enough."):"");
      epRows(plan.eps);
      document.getElementById("bcEpsTitle").textContent="All episodes ("+plan.eps.length+")";
      return;
    }
    if(plan.state==="sprint"){
      title.textContent="Season "+plan.seasonN+" drops today — here's the sprint.";
      sub.textContent="That's "+bcHM(plan.totalMin)+" of episodes left. About "+(Math.ceil(plan.totalMin/60*2)/2)+" hrs today gets it done.";
      epRows(plan.un);
      document.getElementById("bcEpsTitle").textContent="Still to watch ("+plan.un.length+")";
      note.innerHTML="Runtimes are real TMDB data."+estNote()+".";
      return;
    }
    if(plan.state==="leisure"){
      title.textContent="Season "+plan.seasonN+" is already out — no race to run.";
      sub.textContent="At "+bc.h+" hrs a day, that's about "+plan.days+" relaxed day"+(plan.days===1?"":"s")+" for "+plan.un.length+" episode"+(plan.un.length===1?"":"s")+" ("+bcHM(plan.totalMin)+").";
      bcShow(["bcChips","bcEarlier"],true);
      epRows(plan.un);
      document.getElementById("bcEpsTitle").textContent="Episodes to watch ("+plan.un.length+")";
      note.innerHTML="Runtimes are real TMDB data."+estNote()+".";
      return;
    }
    /* comfortable / tight / impossible */
    var dateStr=plan.airDate?bcFmtDate(plan.airDate):"";
    bcShow(["bcChips","bcEarlier","bcAdjustBtn"],true);
    adjust.hidden=!bcWasOpen;
    document.getElementById("bcAdjustBtn").setAttribute("aria-expanded",bcWasOpen?"true":"false");
    document.getElementById("bcBufferRow").style.display="";
    if(plan.state==="comfortable"){title.textContent="Yes — "+bc.h+" hrs a day gets you caught up by "+dateStr+".";}
    else if(plan.state==="tight"){title.textContent="Tight but doable — "+plan.reqH+" hrs a day gets you there by "+dateStr+".";}
    else{title.textContent="Not quite — you'd need "+plan.reqH+" hrs a day.";title.classList.add("is-bad");}
    var pace=bcPacingLine(plan);
    sub.textContent=plan.un.length+" episodes · "+bcHM(plan.totalMin)+" total · "+plan.daysLeft+" days to go."+(pace?" "+pace:"");
    epRows(plan.un);
    document.getElementById("bcEpsTitle").textContent="Still to watch ("+plan.un.length+")";
    note.innerHTML="Runtimes are real TMDB data."+estNote()+"."+(plan.state==="impossible"?" Check off episodes you've already seen — the math updates instantly.":"");
  }
  /* ---- control wiring ---- */
  document.getElementById("modalBinge").addEventListener("click",bcOpen);
  /* Focus trap: Tab cycles inside the calculator while it is the top modal. */
  document.getElementById("bingeModal").addEventListener("keydown",function(e){
    if(e.key!=="Tab")return;
    var modal=document.getElementById("bingeModal");
    var els=modal.querySelectorAll('button,[href],input,select,textarea,[tabindex]:not([tabindex="-1"])');
    var f=Array.prototype.filter.call(els,function(el){return !el.disabled&&el.offsetParent!==null;});
    if(!f.length)return;
    var first=f[0],last=f[f.length-1];
    if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();}
    else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();}
  });
  Array.prototype.forEach.call(document.querySelectorAll("#bcChips .bc-chip"),function(c){
    c.addEventListener("click",function(){bc.h=Number(c.getAttribute("data-h"));bcPersistSettings();bcRender();});
  });
  document.getElementById("bcEarlier").addEventListener("click",function(){
    bc.earlier=!bc.earlier;bcPersistSettings();
    if(bc.earlier&&!bc.allLoaded){bcFetchFull(true);}else{bcRender();}
  });
  document.getElementById("bcAdjustBtn").addEventListener("click",function(){
    var p=document.getElementById("bcAdjust"),open=p.hidden;
    p.hidden=!open;this.setAttribute("aria-expanded",open?"true":"false");
  });
  Array.prototype.forEach.call(document.querySelectorAll("#bcBuffer button"),function(b){
    b.addEventListener("click",function(){bc.buffer=Number(b.getAttribute("data-b"));bcPersistSettings();bcRender();});
  });
  Array.prototype.forEach.call(document.querySelectorAll("#bcPacing button"),function(b){
    b.addEventListener("click",function(){bc.pacing=b.getAttribute("data-p");bcPersistSettings();bcRender();});
  });
  document.getElementById("bcMinus").addEventListener("click",function(){bc.h=Math.max(0.5,Math.round((bc.h-0.5)*2)/2);bcPersistSettings();bcRender();});
  document.getElementById("bcPlus").addEventListener("click",function(){bc.h=Math.min(8,Math.round((bc.h+0.5)*2)/2);bcPersistSettings();bcRender();});
  document.getElementById("bcReset").addEventListener("click",function(){bc.watched={};bcPersistWatched();bcRender();});

document.addEventListener("keydown",function(e){
  var open=document.querySelector(".modal.open");
  if(e.key==="Escape"&&open){closeModal(open.id);return;}
  if(e.key==="Tab"&&open){
    var focusable=Array.prototype.slice.call(open.querySelectorAll('button:not([disabled]),input:not([disabled]),select:not([disabled]),a[href]'))
      .filter(function(el){return el.offsetParent!==null;});
    if(!focusable.length)return;
    var first=focusable[0],last=focusable[focusable.length-1];
    if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();}
    else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();}
    return;
  }
  if(!open&&document.getElementById("view-home").classList.contains("active")&&
     !/INPUT|SELECT|TEXTAREA/.test(document.activeElement.tagName)){
    if(e.key==="ArrowLeft")setHero(heroIndex-1,true);
    if(e.key==="ArrowRight")setHero(heroIndex+1,true);
  }
});
["betaName","betaEmail","betaDevice"].forEach(function(id){
  document.getElementById(id).addEventListener("input",updateEmailLinks);
  document.getElementById(id).addEventListener("change",updateEmailLinks);
});
document.getElementById("betaForm").addEventListener("submit",function(e){
  e.preventDefault();
  var form=this;
  if(!form.reportValidity())return;
  var submit=document.getElementById("betaSubmit"),
      fallback=document.getElementById("manualFallback"),
      controller=window.AbortController?new AbortController():null,
      timeout=controller?setTimeout(function(){controller.abort();},15000):null;
  submit.disabled=true;submit.textContent="Joining…";
  fallback.classList.remove("prominent");
  setStatus("Sending your request…",false);
  var payload={};
  new FormData(form).forEach(function(value,key){payload[key]=value;});
  fetch(BETA_ENDPOINT,{method:"POST",
    headers:{"Content-Type":"application/json","Accept":"application/json"},
    body:JSON.stringify(payload),signal:controller?controller.signal:undefined})
  .then(function(response){
    return response.json().catch(function(){return {};}).then(function(data){
      if(!response.ok||data.success===false||data.success==="false")throw new Error("Submission rejected");
      return data;
    });
  })
  .then(function(){
    setStatus("You're on the list — watch your inbox for your invite.",false);
    form.reset();updateEmailLinks();
  })
  .catch(function(){
    setStatus("That didn't go through — no worries, your info is still here. Copy it or send it by email below.",true);
    fallback.classList.add("prominent");
    pvToast("Signup didn't go through — check your connection and try again. Your info is still here.","",null,"error");
  })
  .then(function(){
    if(timeout)clearTimeout(timeout);
    submit.disabled=false;submit.textContent="Join the open beta";
  });
});
document.getElementById("copyRequest").addEventListener("click",copyRequest);

var observer="IntersectionObserver" in window?new IntersectionObserver(function(entries){
  entries.forEach(function(entry){
    if(entry.isIntersecting){entry.target.classList.add("in");observer.unobserve(entry.target);}
  });
},{threshold:.12}):null;
document.querySelectorAll(".reveal").forEach(function(el){if(observer)observer.observe(el);});

window.addEventListener("popstate",function(){showView(viewFromHash(),null,true);});

/* ================= 12. THEME TOGGLE (website-only; the Previously app is unaffected) ================= */
(function(){
  var btn=document.getElementById("themeToggle");
  if(!btn)return;
  function currentTheme(){return document.documentElement.getAttribute("data-theme")==="light"?"light":"dark";}
  function syncUI(){
    var t=currentTheme();
    btn.setAttribute("aria-label",t==="light"?"Switch to dark theme":"Switch to light theme");
    btn.setAttribute("aria-pressed",t==="light"?"true":"false");
  }
  function applyTheme(t,persist){
    document.documentElement.setAttribute("data-theme",t);
    if(persist){try{localStorage.setItem("prev-theme",t);}catch(e){}}
    var metas=document.getElementsByTagName("meta"),i;
    for(i=0;i<metas.length;i++){
      if(metas[i].getAttribute("name")==="theme-color")metas[i].setAttribute("content",t==="light"?"#ffffff":"#161114");
      if(metas[i].getAttribute("name")==="color-scheme")metas[i].setAttribute("content",t);
    }
    syncUI();
  }
  /* Explicit user choice — persisted. */
  function setTheme(t){applyTheme(t,true);}
  btn.addEventListener("click",function(){setTheme(currentTheme()==="light"?"dark":"light");});
  /* Exposed so the account module's appearance control uses the same path (and syncs this button). */
  window.__prevApplyTheme = applyTheme;
  /* Sync with whatever the pre-paint script chose. */
  syncUI();
  /* Follow the OS only while the user has never chosen (first-visit behavior).
     An OS-followed change is NOT persisted — it never becomes a stored choice. */
  if(window.matchMedia){
    var mq=window.matchMedia("(prefers-color-scheme: light)");
    var follow=function(e){try{if(!localStorage.getItem("prev-theme"))applyTheme(e.matches?"light":"dark",false);}catch(err){}};
    if(mq.addEventListener)mq.addEventListener("change",follow);
  }
})();

/* ================= 16. DRAG-TO-FAVORITES =================
   Sitewide long-press drag (350ms). Every title card — home grids/rails,
   browse catalog, search results, schedule rows, Library — can be dragged
   into the floating star folder. The folder opens a Favorites popup (HD
   thumbnails); popup rows drag OUT to a remove zone. One shared store:
   pv1:favs (local). Cross-device sync stays dormant until the account build
   (spec signin-account-spec-2026-09-23.md) calls the hooks at the bottom. */
var DRAG_PRESS_MS=350,DRAG_TOL=12;
var pvFolder=document.getElementById("pvFolder"),
    pvCountEl=document.getElementById("pvFavCount"),
    pvCoachEl=document.getElementById("pvCoach"),
    pvToastEl=document.getElementById("pvToast"),
    pvZoneEl=document.getElementById("pvRemoveZone"),
    pvListEl=document.getElementById("favList"),
    pvSubEl=document.getElementById("favSub");

function pvFavIds(){
  return Object.keys(favs).filter(function(id){return byId(id);})
    .sort(function(a,b){return (favs[b].added||0)-(favs[a].added||0);});
}
function pvSyncBadge(bump){
  pvCountEl.textContent=pvFavIds().length;
  if(bump){pvCountEl.classList.remove("pv-bump");void pvCountEl.offsetWidth;pvCountEl.classList.add("pv-bump");}
}
/* ---------- toast ---------- */
var pvToastTimer=null;
function pvToast(msg,actionLabel,actionFn,type){
  pvToastEl.innerHTML="";
  var isErr=type==="error";
  if(isErr){
    var g=document.createElement("span");g.className="pv-glyph";g.setAttribute("aria-hidden","true");
    g.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#f2614d" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3 2.5 20h19L12 3z"/><line x1="12" y1="9.5" x2="12" y2="13.5"/><circle cx="12" cy="16.8" r=".4" fill="#f2614d"/></svg>';
    pvToastEl.appendChild(g);
  }
  var s=document.createElement("span");s.textContent=msg;pvToastEl.appendChild(s);
  if(actionLabel){
    var b=document.createElement("button");b.type="button";b.textContent=actionLabel;
    b.addEventListener("click",function(){pvHideToast();if(actionFn)actionFn();});
    pvToastEl.appendChild(b);
  }
  pvToastEl.classList.toggle("pv-error",isErr);
  pvToastEl.classList.add("pv-show");
  if(pvToastTimer)clearTimeout(pvToastTimer);
  pvToastTimer=setTimeout(pvHideToast,isErr||actionLabel?5000:2600);
}
function pvHideToast(){pvToastEl.classList.remove("pv-show");pvToastEl.classList.remove("pv-error");if(pvToastTimer){clearTimeout(pvToastTimer);pvToastTimer=null;}}
/* ---------- loading skeletons ---------- */
/* Show shimmer skeletons while a grid re-renders. kind: "card" (poster grids)
   or "row" (timeline). Skeletons are aria-hidden; the grid carries aria-busy.
   Shimmer is fully disabled under prefers-reduced-motion (CSS). */
function showSkeletons(grid,count,kind){
  if(!grid)return;
  grid.setAttribute("aria-busy","true");
  var html="";
  for(var i=0;i<count;i++){
    html+=kind==="row"
      ?'<div class="skel skel-row" aria-hidden="true"></div>'
      :'<div class="skel skel-card" aria-hidden="true"><div class="skel-line skel-w62"></div><div class="skel-line skel-w38"></div></div>';
  }
  grid.innerHTML=html;
}
function clearSkeletons(grid){if(grid)grid.removeAttribute("aria-busy");}
/* skelRender: shimmer for at least SKEL_FLOOR ms, then run the real render.
   Rapid repeats (search typing) cancel the pending render so only the latest runs. */
var SKEL_FLOOR=260,skelTimers={};
function skelRender(key,gridId,count,kind,renderFn){
  var grid=document.getElementById(gridId);
  if(!grid){renderFn();return;}
  if(skelTimers[key]){clearTimeout(skelTimers[key]);skelTimers[key]=null;}
  showSkeletons(grid,count,kind);
  skelTimers[key]=setTimeout(function(){skelTimers[key]=null;clearSkeletons(grid);renderFn();},SKEL_FLOOR);
}
/* ---------- add/remove with undo ---------- */
function pvRestoreFav(id,snap){
  var t=byId(id);if(!t)return;
  favs[id]=snap||{alert:t.type==="Series",added:Date.now()};
  saveFavs();
  document.querySelectorAll('.star-btn[data-tid="'+id+'"]').forEach(function(b){syncStarBtn(b,t);});
  renderLibrary();renderTonightForYou();updateInboxBadge();
  if(currentGenre==="favorites")renderCatalog();
  if(modalTitleId===id)syncModalEngage(t);
  pvSyncBadge(true);pvRenderFavList();
  pvToast("Saved to your Library.");
}
function pvRemovedToast(id,snap){
  pvToast("Removed from your Library.","Undo",function(){pvRestoreFav(id,snap);});
}
function pvAddFav(id){
  var t=byId(id);if(!t)return false;
  if(isFav(id)){pvToast("Already in your Library.");return false;}
  toggleFav(id); /* syncs UI, badge, toast, coach */
  return true;
}
function pvRemoveFav(id){
  var t=byId(id);if(!t||!isFav(id))return false;
  toggleFav(id); /* syncs UI, badge, removed-toast with Undo */
  return true;
}
/* ---------- coaching bubble (one time) ---------- */
var pvCoachTimer=null;
function pvMaybeCoach(){
  if(store.get("dragCoachSeen",false)){pvCoachEl.classList.add("pv-hide");return;}
  pvCoachTimer=setTimeout(function(){
    var r=pvFolder.getBoundingClientRect(); /* park left of wherever the star sits */
    pvCoachEl.style.right="auto";pvCoachEl.style.bottom="auto";
    pvCoachEl.style.left=Math.max(8,Math.min(r.left-238,window.innerWidth-238))+"px";
    pvCoachEl.style.top=Math.max(8,r.top-6)+"px";
    pvCoachEl.classList.remove("pv-hide");
  },1200);
  setTimeout(function(){pvDismissCoach();},11000);
}
function pvDismissCoach(){
  pvCoachEl.classList.add("pv-hide");
  if(pvCoachTimer){clearTimeout(pvCoachTimer);pvCoachTimer=null;}
  store.set("dragCoachSeen",true);
}
/* ---------- favorites popup ---------- */
function pvRenderFavList(){
  var ids=pvFavIds();
  pvSubEl.textContent=ids.length?(ids.length+(ids.length===1?" title":" titles")+" saved"):"";
  pvListEl.innerHTML="";
  if(!ids.length){
    var e=document.createElement("div");e.className="fav-empty";
    e.innerHTML='<span class="big">&#9733;</span>Nothing saved yet.<br>Press &amp; hold any title and drag it into the &#9733; folder.';
    pvListEl.appendChild(e);return;
  }
  ids.forEach(function(id){
    var t=byId(id);
    var li=document.createElement("li");
    li.className="fav-row";li.setAttribute("data-dragid",id);
    var meta=[t.type,t.genre].filter(Boolean).join(" \u00B7 ");
    var go=document.createElement("button");
    go.type="button";go.className="fav-go";
    go.setAttribute("aria-label","View details for "+t.title);
    /* HD thumbnail: TMDB w780 posters, local curated art, or branded fallback —
       rendered at 60px wide, always downscaled from a much larger source. */
    go.innerHTML='<span class="fav-thumb">'+artImgHTML(t,t.title+" artwork")+'</span>'+
      '<span class="fav-meta"><strong>'+esc(t.title)+'</strong><span>'+esc(meta)+'</span></span>';
    go.addEventListener("click",function(){if(li._pvDragged)return;closeModal("favModal");openShow(t,go);});
    var rm=document.createElement("button");
    rm.type="button";rm.className="fav-rm";
    rm.setAttribute("aria-label","Remove "+t.title+" from favorites");
    rm.textContent="\u00D7";
    rm.addEventListener("click",function(ev){ev.stopPropagation();pvRemoveFav(id);pvRenderFavList();});
    li.appendChild(go);li.appendChild(rm);pvListEl.appendChild(li);
  });
}
function pvOpenFavs(){pvRenderFavList();openModal("favModal",pvFolder);}
/* ---------- long-press drag engine (delegated, covers every card surface) ---------- */
var pvPress=null,pvDrag=null;
var DRAG_SEL=".poster-card,.wide-card,button.tl-btn,button.mini,.fav-row";
function pvVibrate(ms){if(navigator.vibrate){try{navigator.vibrate(ms);}catch(e){}}}
function pvDraggableFromEvent(e){
  var el=e.target&&e.target.closest?e.target.closest(DRAG_SEL):null;
  if(!el)return null;
  if(e.target.closest(".star-btn"))return null;                    /* quick-star keeps its tap */
  if(el.classList.contains("fav-row")&&e.target.closest(".fav-rm"))return null;
  var id=el.getAttribute("data-dragid");
  if(!id||!byId(id))return null;
  return el;
}
document.addEventListener("pointerdown",function(e){
  if(e.pointerType==="mouse"&&e.button!==0)return;
  if(pvDrag||pvPress)return;
  var el=pvDraggableFromEvent(e);
  if(!el)return;
  var sx=e.clientX,sy=e.clientY,pid=e.pointerId;
  el._pvDragged=false;
  pvPress={el:el,id:el.getAttribute("data-dragid"),sx:sx,sy:sy,pid:pid,
    timer:setTimeout(function(){pvPress=null;pvStartDrag(el,sx,sy);},DRAG_PRESS_MS)};
  window.addEventListener("pointermove",pvPressMove);
  window.addEventListener("pointerup",pvPressUp,{once:true});
  window.addEventListener("pointercancel",pvPressUp,{once:true});
});
function pvPressMove(e){
  if(!pvPress||e.pointerId!==pvPress.pid)return;
  if(Math.hypot(e.clientX-pvPress.sx,e.clientY-pvPress.sy)>DRAG_TOL)pvKillPress();
}
function pvPressUp(e){
  if(!pvPress)return;
  if(e.pointerId!==undefined&&e.pointerId!==pvPress.pid)return;
  pvKillPress();
}
function pvKillPress(){
  if(pvPress){clearTimeout(pvPress.timer);pvPress=null;}
  window.removeEventListener("pointermove",pvPressMove);
}
document.addEventListener("contextmenu",function(e){
  if(!(pvPress||pvDrag))return;
  if(e.target.closest&&e.target.closest(DRAG_SEL))e.preventDefault();
});
function pvHitRect(elm,x,y,pad){
  var r=elm.getBoundingClientRect();
  return x>=r.left-pad&&x<=r.right+pad&&y>=r.top-pad&&y<=r.bottom+pad;
}
function pvStartDrag(el,sx,sy){
  var id=el.getAttribute("data-dragid"),t=byId(id);
  if(!t)return;
  var fromRow=el.classList.contains("fav-row");
  if(!fromRow&&document.getElementById("favModal").classList.contains("open"))closeModal("favModal");
  var artImg=el.querySelector("img");
  var ghost=document.createElement("div");
  ghost.className="pv-ghost";
  var gw=Math.max(72,Math.min(artImg?artImg.getBoundingClientRect().width:120,168));
  var gh=Math.round(gw*1.5);
  ghost.style.width=gw+"px";ghost.style.height=gh+"px";
  if(artImg&&artImg.src){
    var c=document.createElement("img");
    c.src=artImg.currentSrc||artImg.src;c.alt="";
    c.style.width="100%";c.style.height="100%";c.style.objectFit="cover";c.style.display="block";
    ghost.appendChild(c);
  }else{
    var mono=document.createElement("div");
    mono.style.cssText="width:100%;height:100%;display:grid;place-items:center;background:linear-gradient(135deg,#1e1a18,#2b2b30 130%);color:#ede6d6;font-family:Georgia,serif;font-size:52px";
    mono.textContent=(t.title||"?").charAt(0).toUpperCase();
    ghost.appendChild(mono);
  }
  document.body.appendChild(ghost);
  pvDrag={el:el,id:id,t:t,ghost:ghost,gw:gw,gh:gh,fromRow:fromRow,hot:false,
    baseX:sx-gw/2,baseY:sy-gh/2};
  el.classList.add("pv-lifting");el._pvDragged=true;pvFolder._pvDragged=true;
  document.body.classList.add("pv-dragging");
  pvVibrate(15);
  if(fromRow)pvZoneEl.classList.add("pv-show");
  pvMoveGhost(sx,sy);
  window.addEventListener("pointermove",pvDragMove);
  document.addEventListener("touchmove",pvBlockTouchMove,{passive:false});
  window.addEventListener("pointerup",pvDragUp,{once:true});
  window.addEventListener("pointercancel",pvDragCancel,{once:true});
}
function pvMoveGhost(x,y){
  if(!pvDrag)return;
  var d=pvDrag;
  d.ghost.style.transform="translate("+(x-d.gw/2)+"px,"+(y-d.gh/2)+"px) scale(1.05) rotate(2deg)";
  var target=d.fromRow?pvZoneEl:pvFolder;
  var hot=pvHitRect(target,x,y,d.fromRow?14:30);
  if(hot!==d.hot){d.hot=hot;target.classList.toggle("pv-hot",hot);}
}
function pvDragMove(e){if(pvDrag)pvMoveGhost(e.clientX,e.clientY);}
/* While a drag is hot, block the browser from stealing the gesture for scroll
   (prevents pointercancel killing the drag on touch devices). Registered at
   drag start, before any movement, so no scroll can have begun. Removed in
   pvEndCommon. */
function pvBlockTouchMove(e){e.preventDefault();}
function pvSnapBack(d){
  d.ghost.style.transition="transform .25s ease-out,opacity .25s ease-out";
  d.ghost.style.transform="translate("+d.baseX+"px,"+d.baseY+"px) scale(1)";
  d.ghost.style.opacity="0.85";
  setTimeout(function(){if(d.ghost.parentNode)d.ghost.parentNode.removeChild(d.ghost);},260);
}
function pvFlyTo(d,elm,scale,done){
  var r=elm.getBoundingClientRect();
  d.ghost.style.transition="transform .28s ease-in,opacity .28s ease-in";
  d.ghost.style.transform="translate("+(r.left+r.width/2-d.gw/2)+"px,"+(r.top+r.height/2-d.gh/2)+"px) scale("+scale+")";
  d.ghost.style.opacity="0";
  setTimeout(function(){
    if(d.ghost.parentNode)d.ghost.parentNode.removeChild(d.ghost);
    if(done)done();
  },300);
}
function pvEndCommon(d){
  document.body.classList.remove("pv-dragging");
  pvFolder.classList.remove("pv-hot");
  pvZoneEl.classList.remove("pv-show","pv-hot");
  window.removeEventListener("pointermove",pvDragMove);
  document.removeEventListener("touchmove",pvBlockTouchMove,{passive:false});
  /* Keep _pvDragged true briefly so the release click is swallowed. */
  setTimeout(function(){
    if(d.el)d.el.classList.remove("pv-lifting");
    pvFolder._pvDragged=false;
  },90);
}
function pvDragUp(e){
  if(!pvDrag)return;
  var d=pvDrag;pvDrag=null;
  window.removeEventListener("pointercancel",pvDragCancel);
  if(d.fromRow){
    if(d.hot){
      pvEndCommon(d);
      pvFlyTo(d,pvZoneEl,0.1,function(){});
      pvVibrate(25);
      pvRemoveFav(d.id);
      pvRenderFavList();
    }else{
      pvEndCommon(d);
      pvSnapBack(d);
    }
  }else{
    if(d.hot){
      pvEndCommon(d);
      pvFlyTo(d,pvFolder,0.08,function(){});
      pvFolder.classList.remove("pv-pop");void pvFolder.offsetWidth;pvFolder.classList.add("pv-pop");
      pvVibrate(25);
      pvAddFav(d.id);
    }else{
      pvEndCommon(d);
      pvSnapBack(d);
    }
  }
}
function pvDragCancel(){
  if(!pvDrag)return;
  var d=pvDrag;pvDrag=null;
  pvEndCommon(d);
  if(d.ghost.parentNode)d.ghost.parentNode.removeChild(d.ghost);
}
/* ---------- folder move + hide (2026-09-24) ----------
   Drag the floating star itself to move it (spot persists on this device).
   Long-press it for Hide / Reset spot. Bring it back from the Library view. */
var pvMenuEl=null;
function pvApplyFolderPos(){
  var pos=store.get("pvFolderPos",null);
  if(pos&&typeof pos.x==="number"&&typeof pos.y==="number"){
    var maxX=Math.max(8,window.innerWidth-76),maxY=Math.max(8,window.innerHeight-76);
    pvFolder.style.left=Math.min(Math.max(8,pos.x),maxX)+"px";
    pvFolder.style.top=Math.min(Math.max(8,pos.y),maxY)+"px";
    pvFolder.classList.add("pv-placed");
  }else{
    pvFolder.style.left="";pvFolder.style.top="";
    pvFolder.classList.remove("pv-placed");
  }
}
function pvDismissMenu(){
  if(pvMenuEl)pvMenuEl.classList.add("pv-hide");
  document.removeEventListener("pointerdown",pvMenuOutside,true);
}
function pvMenuOutside(e){
  if(pvMenuEl&&!pvMenuEl.classList.contains("pv-hide")&&
     !pvMenuEl.contains(e.target)&&e.target!==pvFolder&&!pvFolder.contains(e.target)){
    pvDismissMenu();
  }
}
function pvEnsureMenu(){
  if(pvMenuEl)return pvMenuEl;
  var m=document.createElement("div");
  m.id="pvMenu";m.className="pv-hide";m.setAttribute("role","menu");
  m.setAttribute("aria-label","Floating star options");
  var b1=document.createElement("button");b1.type="button";b1.textContent="Hide star";
  b1.addEventListener("click",function(){pvSetFolderHidden(true);});
  var b2=document.createElement("button");b2.type="button";b2.textContent="Reset spot";
  b2.addEventListener("click",function(){store.del("pvFolderPos");pvApplyFolderPos();pvDismissMenu();pvToast("Star back in its corner.");});
  var hint=document.createElement("span");hint.className="pv-menu-hint";
  hint.textContent="Tip: drag the star itself to move it.";
  m.appendChild(b1);m.appendChild(b2);m.appendChild(hint);
  document.body.appendChild(m);
  pvMenuEl=m;return m;
}
function pvShowMenu(){
  var m=pvEnsureMenu();
  var r=pvFolder.getBoundingClientRect();
  m.style.left=Math.min(Math.max(8,r.left+r.width/2-86),window.innerWidth-180)+"px";
  m.style.top="auto";
  m.style.bottom=(window.innerHeight-r.top+12)+"px";
  m.classList.remove("pv-hide");
  document.addEventListener("pointerdown",pvMenuOutside,true);
}
function pvSyncStarToggle(){
  var b=document.getElementById("libraryStarToggle");if(!b)return;
  b.textContent=pvFolder.classList.contains("pv-hidden")?"Show floating \u2605":"Hide floating \u2605";
}
function pvSetFolderHidden(hide,silent){
  pvFolder.classList.toggle("pv-hidden",!!hide);
  pvFolder.setAttribute("aria-hidden",hide?"true":"false");
  store.set("pvFolderHidden",!!hide);
  pvDismissMenu();
  pvSyncStarToggle();
  if(!silent)pvToast(hide?"Star hidden. Bring it back from your Library.":"Floating star is back.");
}
function pvWireFolderMove(){
  var down=false,sx=0,sy=0,ox=0,oy=0,moving=false,pressT=null;
  function cancelPress(){if(pressT){clearTimeout(pressT);pressT=null;}}
  function suppressClick(){
    pvFolder._pvDragged=true;
    setTimeout(function(){pvFolder._pvDragged=false;},200);
  }
  pvFolder.addEventListener("pointerdown",function(e){
    if(pvFolder.classList.contains("pv-hidden"))return;
    if(e.pointerType==="mouse"&&e.button!==0)return;
    down=true;moving=false;sx=e.clientX;sy=e.clientY;
    var r=pvFolder.getBoundingClientRect();ox=r.left;oy=r.top;
    try{pvFolder.setPointerCapture(e.pointerId);}catch(err){}
    cancelPress();
    pressT=setTimeout(function(){
      pressT=null;
      if(!moving&&down){pvVibrate(15);pvShowMenu();suppressClick();}
    },600);
  });
  pvFolder.addEventListener("pointermove",function(e){
    if(!down)return;
    var dx=e.clientX-sx,dy=e.clientY-sy;
    if(!moving&&Math.abs(dx)+Math.abs(dy)>12){
      moving=true;cancelPress();pvDismissMenu();
      pvFolder._pvDragged=true;
      pvFolder.classList.add("pv-moving");
    }
    if(moving){
      var nx=Math.min(Math.max(8,ox+dx),Math.max(8,window.innerWidth-76));
      var ny=Math.min(Math.max(8,oy+dy),Math.max(8,window.innerHeight-76));
      pvFolder.style.left=nx+"px";pvFolder.style.top=ny+"px";
      pvFolder.classList.add("pv-placed");
    }
  });
  function up(){
    if(!down)return;
    down=false;cancelPress();
    if(moving){
      moving=false;
      pvFolder.classList.remove("pv-moving");
      var r=pvFolder.getBoundingClientRect();
      store.set("pvFolderPos",{x:Math.round(r.left),y:Math.round(r.top)});
      suppressClick();
    }
  }
  pvFolder.addEventListener("pointerup",up);
  pvFolder.addEventListener("pointercancel",up);
}
/* ---------- folder + wiring ---------- */
pvFolder.addEventListener("click",function(){
  if(pvFolder._pvDragged)return;
  if(document.getElementById("favModal").classList.contains("open"))closeModal("favModal");
  else pvOpenFavs();
});
pvCoachEl.addEventListener("click",pvDismissCoach);
function pvDragInit(){
  pvSyncBadge(false);
  pvApplyFolderPos();
  if(store.get("pvFolderHidden",false)){
    pvFolder.classList.add("pv-hidden");
    pvFolder.setAttribute("aria-hidden","true");
  }
  pvWireFolderMove();
  pvSyncStarToggle();
  var tgl=document.getElementById("libraryStarToggle");
  if(tgl)tgl.addEventListener("click",function(){
    pvSetFolderHidden(!pvFolder.classList.contains("pv-hidden"));
  });
  pvMaybeCoach();
}
/* ---------- ACCOUNT MIGRATION HOOKS (DORMANT) ----------
   The account system (spec signin-account-spec-2026-09-23.md) is NOT built yet.
   When it ships, it calls these on first sign-in to merge the anonymous
   pv1:favs store into the account Library (dedupe by title ID, keep earliest
   added, OR the alert flags — per spec section 6). Until then: local
   persistence only, no cross-device sync, no sign-in dropdown. */
window.PREVIOUSLY_ACCOUNT=window.PREVIOUSLY_ACCOUNT||{};
window.PREVIOUSLY_ACCOUNT.exportAnonymousFavorites=function(){
  try{return JSON.parse(JSON.stringify(favs));}catch(e){return {};}
};
window.PREVIOUSLY_ACCOUNT.mergeAnonymousFavorites=function(serverFavs){
  serverFavs=serverFavs||{};
  var merged={},now=Date.now();
  Object.keys(serverFavs).forEach(function(id){
    if(byId(id))merged[id]={alert:!!serverFavs[id].alert,added:serverFavs[id].added||now};
  });
  Object.keys(favs).forEach(function(id){
    if(!byId(id))return;
    if(!merged[id])merged[id]=favs[id];
    else merged[id]={alert:!!(merged[id].alert||favs[id].alert),
      added:Math.min(merged[id].added||now,favs[id].added||now)};
  });
  favs=merged;saveFavs();
  document.querySelectorAll(".star-btn[data-tid]").forEach(function(b){
    var t=byId(b.getAttribute("data-tid"));if(t)syncStarBtn(b,t);
  });
  renderLibrary();renderTonightForYou();updateInboxBadge();
  if(currentGenre==="favorites")renderCatalog();
  pvSyncBadge(false);pvRenderFavList();
  return merged;
};

/* ---------- boot ---------- */
buildIndex();
renderGenrePills();
computeNewTitles();
showView(viewFromHash(),null,true);
renderSchedule();
loadTrailerPool(); /* verified YouTube keys for hero/modal trailers; pool arrival mounts silently, never rewrites hero content */
renderTop10();
renderWide();
renderSpotlight();
renderCatalog();
renderLibrary();
renderRecent();
updateEmailLinks();

/* Star + labels: one-time touch hint wiring (scroll-follow + dismiss). */
document.getElementById("starHintDismiss").addEventListener("click",dismissStarHint);
window.addEventListener("scroll",positionStarHint,{passive:true});
window.addEventListener("resize",positionStarHint);
maybeShowStarHint();

/* TMDB catalog arrives async (catalog.js, deferred): merge + re-render. */
function onCatalogReady(){
  buildIndex();
  computeNewTitles();
  browseShown=BROWSE_PAGE; renderGenrePills(); /* refresh genre pill counts on the full catalog */
  heroCommitArmed=true; /* schedule + catalog have settled — the single hero commit may paint now */
  renderSchedule();
  renderTop10();
  renderWide();
  renderSpotlight();
  skelRender("catalog","catalog",10,"card",renderCatalog);
  skelRender("library","libraryGrid",6,"card",renderLibrary);
  renderRecent();
  maybeShowStarHint(); /* catalog re-render replaces cards; re-anchor if hint pending */
  pvSyncBadge(); /* TMDB ids only resolve after the merge; re-sync the count. */
}
if(window.PREVIOUSLY_CATALOG&&window.PREVIOUSLY_CATALOG.length)onCatalogReady();
else document.addEventListener("previously:catalog-ready",onCatalogReady,{once:true});
/* Hero settle fallback (James 2026-09-26): if the async catalog hasn't landed
   within 2.5s of boot, commit the hero from the inline featured catalog
   anyway. The skeleton never sits longer than this; a later catalog arrival
   repaints only if the picked selection actually changed. */
setTimeout(function(){
  if(heroCommitArmed)return;
  heroCommitArmed=true;
  renderSchedule();
},2500);
/* Catalog data fetch failure: if the async catalog never arrives, say so plainly
   instead of silently showing the featured-only lineup. */
setTimeout(function(){
  if((!window.PREVIOUSLY_CATALOG||!window.PREVIOUSLY_CATALOG.length)&&!document.querySelector(".skel")){
    pvToast("The full catalog didn't load — showing the featured lineup. Check your connection and reload to see everything.","",null,"error");
  }
},12000);

/* Mark this visit AFTER newness was computed above. */
store.set("lastVisit",Date.now());
pvDragInit();

/* ============ account-module bridge (Gate 3) ============
   The script above is one IIFE, so nothing inside is global. account.js
   needs read access to a few internals and the ability to wrap the four
   renderer/mutation entry points. This bridge is the ONLY coupling point:
   plain getters for reads, named setters for the four wrappable bindings
   (direct assignment rebinds the IIFE-local declaration, so every internal
   caller picks up the wrapped version automatically). */
window.__PV = {
  byId: byId,
  matchTitle: matchTitle,
  esc: esc,
  openShow: openShow,
  openModal: openModal,
  closeModal: closeModal,
  updateInboxBadge: updateInboxBadge,
  pvToast: pvToast,
  showView: showView,
  viewFromHash: viewFromHash,
  openInbox: openInbox,
  posterCard: posterCard,
  getFavs: function(){ return favs; },
  getToggleFav: function(){ return toggleFav; },
  getSetAlert: function(){ return setAlert; },
  getRenderWatchProviders: function(){ return renderWatchProviders; },
  getRenderLibrary: function(){ return renderLibrary; },
  getModalTitleId: function(){ return modalTitleId; },
  getTonightAlertEps: function(){ return tonightAlertEps; },
  setToggleFav: function(v){ toggleFav = v; },
  setSetAlert: function(v){ setAlert = v; },
  setRenderWatchProviders: function(v){ renderWatchProviders = v; },
  setRenderLibrary: function(v){ renderLibrary = v; },
  setTonightAlertEps: function(v){ tonightAlertEps = v; }
};
})();
/* ---------- Live nav dot: driven by the live-now worker (60s poll) ---------- */
(function(){
"use strict";
var LIVE_URL="https://previously-live-now.james-moore2013.workers.dev/live-now.json";
var KEY="pv-live-state";
function paint(on){var d=document.querySelectorAll(".spa-live-dot");for(var i=0;i<d.length;i++){d[i].hidden=!on;}}
function paintCached(){try{var s=JSON.parse(localStorage.getItem(KEY)||"null");if(s&&s.at&&Date.now()-s.at<5*60*1000)paint(!!s.live);}catch(e){}}
function poll(){try{fetch(LIVE_URL,{cache:"no-store"}).then(function(r){if(!r.ok)throw new Error("http "+r.status);return r.json();}).then(function(d){var on=!!(d&&d.live&&d.live.length);try{localStorage.setItem(KEY,JSON.stringify({live:on,at:Date.now()}));}catch(e){}paint(on);}).catch(function(){});}catch(e){}}
paintCached();poll();setInterval(poll,60000);
})();
  </script>
  <!-- Account & Library module: auth, profile settings, streaming-service
       preferences, appearance, notifications, and the tabbed Library. -->
  <!-- Real shared modules (batch3-2026-09-26/shared/, byte-identical copies):
       user-state first (auth/favorites source), then drag-drop, then nudges,
       then the account/library module that adapts to their contracts. -->
  <script src="shared/user-state/user-state.js"></script>
  <script src="shared/drag-drop/drag-drop.js"></script>
<script src="section-reorder.js" defer></script>
  <script src="shared/nudges/nudges.js"></script>
  <script src="account.253f7fad.js"></script>
  <script src="trakt.16a6232c.js"></script>
  <script src="hero-bleed.f28cff96.js"></script>
  <!-- Guided first-run tour (2026-09-25): self-contained tour.js + tour.css -->
  <script src="tour.af673134.js"></script>
<script src="sb-banner.js" defer></script>
<script src="spotlight.js" defer></script>
</body>
</html>
