/* Greybox detail — kool.ws-parity rebuild of the route-backed modal
 * (#modal, /movie/:id, /tv/:id). Structure, tokens, keyframes and section
 * styling copy kool.ws item pages: a FULL-PAGE item view with the floating
 * left icon rail (kool's .sidebar: brand, primary nav, settings at the
 * bottom), a full-bleed hero (backdrop + dual gradients, badge/logo/title/
 * meta, rating pill, folded synopsis, action row) that runs UNDER that rail,
 * then the body sections (Episodes → Cast → Recommended → Similar → Details),
 * each with the red-underlined uppercase title and the reveal-on-scroll
 * entrance. The Recommended row is kool's landscape card row (16:9
 * backdrops), Similar keeps the portrait posters.
 * Established Greybox contracts stay intact: the panel scroll containment,
 * the background recede, the title-logo treatment, the episode shelf
 * steppers and the hidden providers block (all test-locked). Since the panel
 * is full-bleed now there is no blank flank left for the ad side rails, so
 * both detail-left / detail-right anchors live in the in-flow home forever
 * (js/ads.js never relocates them — see SPEC CHANGE there).
 * The play button keeps css/watch-cta.css (loads after this sheet and wins);
 * this file only frames it. Vanilla CSS. Kool tokens live under --gx-k* so
 * they can never collide with the site-wide --gx-* namespace. */

/* ---------------- kool rail metrics (read by the rail AND the scroller) ----
 * The rail is a sibling of .gx-detail, so its metrics hang off #modal (the
 * only common ancestor): --gx-krail-w is the fully padded rail width kool
 * reserves with .cached-view padding-left, --gx-krail-open the hover
 * expansion (kool --rail/--rail-gap/--rail-open). */
#modal {
  --gx-krail: 64px;
  --gx-krail-gap: 14px;
  --gx-krail-w: calc(var(--gx-krail) + 2 * var(--gx-krail-gap));
  --gx-krail-open: 244px;
  --gx-krail-t: 0.38s;
  --gx-kglass: linear-gradient(180deg, rgba(48, 53, 59, 0.9) 0%, rgba(36, 41, 47, 0.84) 50%, rgba(24, 29, 35, 0.88) 100%);
  --gx-knav-h: 48px;
  --gx-knav-gap: 4px;
  /* The ambient wash is intentionally oversized; clip it to the overlay
     instead of letting the blur create off-screen scrollable overflow. */
  overflow: hidden;
}

/* ---------------- kool tokens ---------------- */

.gx-detail {
  --gx-kb0: #1b222c;
  --gx-kb1: #1e2631;
  --gx-kb2: #303845;
  --gx-kt1: #ffffff;
  --gx-kt2: #b8b8b8;
  --gx-kt3: #909090;
  --gx-kred: #ff3d44;
  --gx-kprimary: #d90007;
  --gx-kyellow: #ff9900;
  --gx-kborder: rgba(255, 255, 255, 0.08);
  --gx-kborder-h: rgba(255, 255, 255, 0.16);
  --gx-kglass: linear-gradient(180deg, rgba(48, 53, 59, 0.82) 0%, rgba(38, 43, 49, 0.68) 50%, rgba(26, 31, 38, 0.72) 100%);
  --gx-kease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --gx-kease-enter: cubic-bezier(0.22, 1, 0.36, 1);
  --gx-kpad: 36px;
  --gx-kgap: 14px;
  --gx-khero: min(60vh, calc(100vh - 260px));
  --gx-fav-size: 46px;
}

/* ---------------- left rail (kool .sidebar / .sidebar-dock / .nav-item) ---
 * A full-height glass dock in the top-left corner of the overlay, hover-
 * expanded like kool's rail. The hero bleeds underneath it; the body keeps
 * its distance through .gx-detail's padding-left. */

.gx-detail-nav {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  z-index: 6;
  width: var(--gx-krail-w);
  padding: var(--gx-krail-gap);
  display: flex;
  flex-direction: column;
}

/* The dock is always laid out at its OPEN width. The 92px rail box never
 * changes size; clip-path reveals the right-hand 152px on hover/focus. That
 * keeps the expansion out of layout entirely (the old width transition
 * reflowed every row + label on every frame). The glass is static too: a
 * backdrop-filter that switched on at hover forced a full-rail re-blur on
 * the first frame, which was the second source of jank. */
.gx-detail-nav-dock {
  position: relative;
  flex: 1;
  min-height: 0;
  width: calc(var(--gx-krail-open) - 2 * var(--gx-krail-gap));
  display: flex;
  flex-direction: column;
  padding: 10px 8px;
  border-radius: 26px;
  background: var(--gx-kglass, linear-gradient(180deg, rgba(48, 53, 59, 0.9), rgba(24, 29, 35, 0.88)));
  border: 1px solid var(--gx-kborder, rgba(255, 255, 255, 0.08));
  border-top-color: rgba(255, 255, 255, 0.15);
  box-shadow: 0 24px 60px -18px rgba(0, 0, 0, 0.6), 0 2px 8px rgba(0, 0, 0, 0.3), inset 0 1px rgba(255, 255, 255, 0.08);
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
  clip-path: inset(0 calc(100% - var(--gx-krail)) 0 0 round 26px);
  transition: clip-path var(--gx-krail-t) cubic-bezier(0.22, 1, 0.36, 1);
  will-change: clip-path;
}
.gx-detail-nav-dock::-webkit-scrollbar { display: none; }

/* Hover / keyboard focus opens the clipped dock; no width, background,
 * shadow or filter transition runs. */
.gx-detail-nav:hover .gx-detail-nav-dock,
.gx-detail-nav:focus-within .gx-detail-nav-dock {
  clip-path: inset(0 0 0 0 round 26px);
}

.gx-detail-nav-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  height: var(--gx-knav-h);
  padding: 0 11px;
  margin-bottom: 12px;
  border-radius: 16px;
  color: var(--gx-kt1, #fff);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
}
.gx-detail-nav-brand img { width: 26px; height: 26px; flex-shrink: 0; border-radius: 8px; }

.gx-detail-nav-links {
  display: flex;
  flex-direction: column;
  gap: var(--gx-knav-gap);
}
.gx-detail-nav-bottom {
  position: relative;
  margin-top: auto;
  padding-top: 10px;
  display: flex;
  flex-direction: column;
  gap: var(--gx-knav-gap);
}
.gx-detail-nav-bottom::before {
  content: "";
  position: absolute;
  top: 0;
  left: 10px;
  right: 10px;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.18) 50%, transparent 100%);
}

/* Rail entries override the site-wide .nav-btn pill (navbar.css) with kool's
 * .nav-item: 48px slots, 22px stroked glyphs, red-glow active state. */
.gx-detail-nav .nav-btn {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  height: var(--gx-knav-h);
  min-height: var(--gx-knav-h);
  padding: 0 11px;
  border: 0;
  border-radius: 16px;
  background: transparent;
  color: var(--gx-kt2, #b8b8b8);
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  cursor: pointer;
  transition: color 0.2s var(--gx-kease, ease), transform 0.22s var(--gx-kease, ease);
}

/* Two paint-only highlight layers keep the collapsed rail visually intact:
 * ::before is the 48px icon chip (always the size of the closed dock slot),
 * ::after is the full-row tint that fades in only while the rail is open.
 * Neither one changes width, so nothing reflows during the reveal. */
.gx-detail-nav .nav-btn::before,
.gx-detail-nav .nav-btn::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  border-radius: 16px;
  pointer-events: none;
  background: transparent;
  opacity: 0;
  transition: opacity 0.2s var(--gx-kease, ease), background-color 0.2s var(--gx-kease, ease);
}
.gx-detail-nav .nav-btn::before {
  width: 48px;
  opacity: 1;
}
.gx-detail-nav .nav-btn::after { right: 0; }
.gx-detail-nav:hover .nav-btn::after,
.gx-detail-nav:focus-within .nav-btn::after { opacity: 1; }
.gx-detail-nav .nav-btn:hover::before,
.gx-detail-nav .nav-btn:hover::after {
  background: rgba(255, 255, 255, 0.06);
}
.gx-detail-nav .nav-btn.active::before,
.gx-detail-nav .nav-btn.is-active::before {
  background: rgba(255, 61, 68, 0.1);
  box-shadow: inset 0 0 0 1px rgba(255, 61, 68, 0.22), 0 0 18px rgba(255, 61, 68, 0.12);
}
.gx-detail-nav .nav-btn.active::after,
.gx-detail-nav .nav-btn.is-active::after {
  background: rgba(255, 61, 68, 0.1);
  box-shadow: inset 0 0 0 1px rgba(255, 61, 68, 0.22), inset 0 1px rgba(255, 255, 255, 0.05);
}
.gx-detail-nav .nav-btn:hover { color: var(--gx-kt1, #fff); }
.gx-detail-nav .nav-btn:active { transform: scale(0.985); }
.gx-detail-nav .nav-btn.active,
.gx-detail-nav .nav-btn.is-active {
  color: var(--gx-kred, #ff3d44);
  border-color: transparent;
}
.gx-detail-nav .nav-btn:focus-visible {
  outline: 2px solid var(--gx-accent, #d0a24f);
  outline-offset: 2px;
}
.gx-detail-nav-ico {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  transition: transform 0.25s var(--gx-kease, ease), filter 0.25s var(--gx-kease, ease);
}
.gx-detail-nav .nav-btn:hover .gx-detail-nav-ico { transform: scale(1.1); }
.gx-detail-nav .nav-btn.active .gx-detail-nav-ico,
.gx-detail-nav .nav-btn.is-active .gx-detail-nav-ico {
  filter: drop-shadow(0 0 8px rgba(255, 61, 68, 0.55));
}

/* Entry labels only exist once the rail expands (kool's --open fade/slide). */
.gx-detail-nav-word {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity 0.22s var(--gx-kease, ease), transform 0.26s var(--gx-kease, ease);
}
.gx-detail-nav:hover .gx-detail-nav-word,
.gx-detail-nav:focus-within .gx-detail-nav-word {
  opacity: 1;
  transform: none;
}

/* ---------------- panel (full-page scroller; the rail insets it) --------- */

.gx-detail {
  position: absolute;
  inset: 0;
  width: 100%;
  margin: 0 auto;
  padding-left: var(--gx-krail-w);
  background: var(--gx-kb0);
  color: var(--gx-kt1);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
}
.gx-detail::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.26); }
.gx-detail::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, 0.44); }

/* ---------------- ambient background wash ----------------
 * The surface below the hero is never plain black: a blurred, saturated copy
 * of the title artwork sits behind the whole detail view and tints the slate
 * base (#1b222c), the same idea as Atlantic's artwork-tinted page surface.
 * It is a fixed layer (not a per-section background), so the tint stays put
 * while the detail scrolls, and it fades in with the panel. The URL is set
 * per title from js/pages.js via --gx-detail-wash; titles without artwork
 * keep the soft slate/radial fallback. A cool radial sits above the artwork
 * so dark posters (Fight Club, horror, sci-fi) still resolve as a lightly
 * tinted slate instead of collapsing to black. Image decode cost is already
 * paid by the hero backdrop cache, and the heavy blur keeps this layer cheap. */
.gx-detail::before {
  content: "";
  position: fixed;
  inset: -14%;
  z-index: 0;
  pointer-events: none;
  background-color: var(--gx-kb0);
  background-image:
    radial-gradient(92% 72% at 50% 0%, rgba(119, 143, 171, 0.3), transparent 74%),
    linear-gradient(180deg, rgba(40, 51, 65, 0.16), rgba(14, 19, 26, 0.08) 64%, transparent),
    var(--gx-detail-wash, none);
  background-position: center top;
  background-size: cover;
  filter: blur(62px) saturate(1.5) brightness(0.9);
  opacity: 0.56;
  transform: translateZ(0);
}

/* ---------------- detail ad slots (detail-left / detail-right) ------------
 * SPEC CHANGE (kool full-page detail): the panel spans the whole viewport at
 * every width, so the old wide-screen flank parking is gone — both anchors
 * always live in the in-flow home above the Recommended/Similar rows
 * (js/ads.js no longer relocates anything). The legacy #gx-detail-rail-l/-r
 * hosts stay in index.html for admin/tests and are permanently hidden. */
.gx-detail-adsides {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 1.25rem;
}
.gx-detail-rail {
  display: none;
}

/* The page behind recedes while a card is up: the content layers sink
 * backwards and shrink while the modal rises — dim kept so the card stays
 * the focus. The fixed header is deliberately EXCLUDED: transform/filter on
 * it would make it the containing block for the fixed mobile dock (and
 * override its .is-hidden tuck), which is what made the navbar jump/slide
 * after closing a detail. The modal backdrop already covers it. Toggled via
 * body.gx-modal-open in showModal/hideModal; the reduced-motion switch
 * below makes the recede instant. */
#page-ambient, #hero, .gx-page, body > footer {
  transition: filter 0.38s ease, transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  transform-origin: 50% 0;
}
body.gx-modal-open #page-ambient,
body.gx-modal-open #hero,
body.gx-modal-open .gx-page,
body.gx-modal-open > footer {
  transform: scale(0.94) translateY(1.5%);
  filter: brightness(0.68) saturate(0.88);
}

/* Backdrop glass: softens the receded page behind the panel. The open/close
 * transition is driven by .gx-open (js/components.js showModal/hideModal):
 * the panel fades, the scrim fades, and on close the overlay is removed from
 * layout only after the exit has finished. No display:none snap. */
#modal-bg {
  opacity: 0;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  transition: opacity 0.32s var(--gx-kease, ease);
}
#modal.gx-open #modal-bg { opacity: 1; }
#modal.gx-closing #modal-bg { opacity: 0; transition-duration: 0.2s; }

#modal .gx-detail {
  opacity: 0;
  transition: opacity 0.3s var(--gx-kease, ease);
}
#modal.gx-open .gx-detail { opacity: 1; }
#modal.gx-closing .gx-detail { opacity: 0; transition-duration: 0.2s; }

#modal .gx-detail-nav {
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity 0.32s var(--gx-kease, ease), transform 0.42s var(--gx-kease-enter, ease);
}
#modal.gx-open .gx-detail-nav { opacity: 1; transform: none; }
#modal.gx-closing .gx-detail-nav { opacity: 0; transition-duration: 0.18s; }

/* kool has no close button contract of its own (history/Escape exit); our
 * overlay keeps one as a glass circle top-right of the hero. */
.gx-modal-close {
  position: absolute;
  top: 18px;
  right: 18px;
  z-index: 5;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  cursor: pointer;
  color: var(--gx-kt1);
  background: rgba(26, 31, 38, 0.72);
  border: 1px solid var(--gx-kborder-h);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  font-size: 16px;
  line-height: 1;
  transition: transform var(--gx-transition, 0.2s ease), background 0.2s var(--gx-kease);
}
.gx-modal-close:hover { transform: scale(1.08); background: rgba(255, 255, 255, 0.14); }
.gx-modal-close:active { transform: scale(0.96); }

/* ---------------- content reveal ----------------
 * The panel itself fades with .gx-open; this quieter chain runs exactly once
 * when the fetched data replaces the skeleton (js/components.js revealDetail).
 * The hero artwork never scales again, which is what made a second load pass
 * feel like a jump-cut. Children resolve in reading order with short delays. */
@keyframes gx-detail-rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes gx-detail-rise-sm {
  from { opacity: 0; transform: translateY(9px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes gx-detail-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes gx-shimmer {
  from { background-position: 120% 0; }
  to { background-position: -120% 0; }
}

.gx-enter .gx-detail-content { animation: gx-detail-rise 0.46s var(--gx-kease-enter) both; }
.gx-enter .gx-detail-logo { animation: gx-detail-fade 0.34s var(--gx-kease-enter) both; }
.gx-enter .gx-detail-title { animation: gx-detail-rise-sm 0.4s var(--gx-kease-enter) 0.045s both; }
.gx-enter .gx-detail-meta { animation: gx-detail-rise-sm 0.38s var(--gx-kease-enter) 0.09s both; }
.gx-enter .gx-detail-badges { animation: gx-detail-rise-sm 0.36s var(--gx-kease-enter) 0.12s both; }
.gx-enter .gx-detail-desc { animation: gx-detail-rise-sm 0.4s var(--gx-kease-enter) 0.15s both; }
.gx-enter .gx-release { animation: gx-detail-rise-sm 0.4s var(--gx-kease-enter) 0.19s both; }
.gx-enter .gx-detail-actions { animation: gx-detail-rise-sm 0.4s var(--gx-kease-enter) 0.23s both; }
.gx-enter .gx-detail-body { animation: gx-detail-fade 0.5s var(--gx-kease-enter) 0.12s both; }

/* ---------------- loading skeleton ----------------
 * A stable silhouette instead of the old "Loading..." word salad. It keeps
 * the hero geometry and action row in place, so swapping in real data is a
 * reveal — not a re-layout. removed by revealDetail(). */
.gx-detail.gx-loading .gx-detail-title {
  width: min(64%, 390px);
  height: clamp(30px, 4.4vw, 44px);
  margin-bottom: 12px;
  border-radius: 9px;
  color: transparent;
  text-shadow: none;
  background: linear-gradient(100deg, rgba(255,255,255,0.055) 24%, rgba(255,255,255,0.14) 42%, rgba(255,255,255,0.055) 60%);
  background-size: 220% 100%;
  animation: gx-shimmer 1.35s linear infinite;
}
.gx-detail.gx-loading .gx-detail-meta {
  width: min(46%, 270px);
  height: 9px;
  margin-bottom: 15px;
  border-radius: 6px;
  color: transparent;
  background: linear-gradient(100deg, rgba(255,255,255,0.05) 24%, rgba(255,255,255,0.12) 42%, rgba(255,255,255,0.05) 60%);
  background-size: 220% 100%;
  animation: gx-shimmer 1.35s linear infinite;
}
.gx-detail.gx-loading .gx-detail-badges { display: none; }
.gx-detail.gx-loading .gx-detail-desc::before {
  content: "";
  display: block;
  max-width: 540px;
  height: 3.5em;
  margin-bottom: 16px;
  border-radius: 6px;
  background:
    linear-gradient(100deg, rgba(255,255,255,0.04) 24%, rgba(255,255,255,0.1) 42%, rgba(255,255,255,0.04) 60%) 0 0 / 100% 7px no-repeat,
    linear-gradient(100deg, rgba(255,255,255,0.04) 24%, rgba(255,255,255,0.1) 42%, rgba(255,255,255,0.04) 60%) 0 1.35em / 92% 7px no-repeat,
    linear-gradient(100deg, rgba(255,255,255,0.04) 24%, rgba(255,255,255,0.1) 42%, rgba(255,255,255,0.04) 60%) 0 2.7em / 68% 7px no-repeat;
}
.gx-detail.gx-loading .gx-detail-actions { opacity: 0.32; filter: saturate(0.25); pointer-events: none; }
.gx-detail.gx-loading .gx-detail-body { opacity: 0.45; }
.gx-detail.gx-loading .gx-release { display: none !important; }

/* ---------------- hero ---------------- */

.gx-detail-hero {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  min-height: var(--gx-khero);
  /* Full-bleed: pulled back out of the scroller's rail inset (kool's
   * `.hero { margin-left: calc(-1 * var(--rail-w)); width: calc(100% + var(--rail-w)) }`)
   * so the backdrop runs edge-to-edge UNDER the floating rail, while the text
   * keeps clear of it through the extra left padding. */
  margin-left: calc(-1 * var(--gx-krail-w));
  width: calc(100% + var(--gx-krail-w));
  padding: 138px var(--gx-kpad) calc(var(--gx-kpad) + 24px) calc(var(--gx-kpad) + var(--gx-krail-w));
  /* kool `.hero { margin-bottom: -8px }`: the body block tucks up under the
   * hero's faded bottom edge. Transparent on purpose: the ambient wash below
   * must be able to show through the last few pixels of the hero fade. */
  margin-bottom: -8px;
  background: transparent;
  overflow: hidden;
  isolation: isolate;
}

/* kool .hero-bg: absolute fill, art fades in on load, dual gradients (left
 * scrim for text, bottom fade into the page), whole block masked out at the
 * very bottom so the hero dissolves into the tinted section background. */
.gx-detail-hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--gx-kb1);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 52%, rgba(0, 0, 0, 0.62) 78%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 52%, rgba(0, 0, 0, 0.62) 78%, transparent 100%);
}
.gx-detail-backdrop {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: calc(100% - 2px);
  object-fit: cover;
  object-position: center 25%;
  opacity: 0;
  transition: opacity 0.38s var(--gx-kease, ease);
}
.gx-detail-backdrop.loaded { opacity: 1; }
.gx-detail-hero-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(21, 25, 32, 0.93) 0%, rgba(21, 25, 32, 0.72) 24%, rgba(21, 25, 32, 0.3) 55%, rgba(21, 25, 32, 0.06) 82%, transparent 100%),
    linear-gradient(0deg, rgba(21, 25, 32, 0.32) 0%, transparent 42%);
}
.gx-detail-hero-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg,
    rgba(16, 20, 26, 0.42) 0%,
    rgba(16, 20, 26, 0.08) 18%,
    transparent 36%,
    rgba(18, 22, 29, 0.24) 58%,
    rgba(18, 22, 29, 0.68) 82%,
    rgba(27, 34, 44, 0.94) 96%,
    var(--gx-kb0) 100%);
}

.gx-detail-hero-body {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1120px;
  display: flex;
  align-items: flex-end;
}
.gx-detail-content {
  flex: 1;
  min-width: 0;
  width: 100%;
  max-width: 720px;
  padding-bottom: 8px;
}
.gx-detail-head { min-width: 0; }

/* Greybox Pick / custom badge: quiet amber pill, secondary to the title. */
.gx-detail-badge {
  display: inline-block;
  margin-bottom: 0.55rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gx-accent-strong, #d0a24f);
  background: rgba(10, 10, 14, 0.72);
  border: 1px solid var(--gx-accent-border, rgba(208, 162, 79, 0.5));
  border-radius: var(--gx-radius-pill, 999px);
  padding: 0.2rem 0.65rem;
}
.gx-detail-badge.hidden { display: none; }

/* Custom-tag badges: same pill, dimmer — secondary to the override badge. */
.gx-detail-tagbadge { margin-right: 0.4rem; color: var(--gx-text-dim, var(--gx-kt2)); border-color: var(--gx-border-faint, var(--gx-kborder)); }

/* Official TMDB title treatment: the transparent artwork keeps its own
 * aspect ratio inside these caps — never stretched, cropped or distorted.
 * The text title stays in the DOM (screen readers, no-logo fallback) and is
 * only clipped visually while the logo shows — never both visible. */
.gx-detail-logo {
  display: block;
  max-width: min(460px, 72%);
  height: clamp(52px, 9vh, 100px);
  width: auto;
  object-fit: contain;
  object-position: left center;
  margin-bottom: 13px;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.9)) drop-shadow(0 8px 24px rgba(0, 0, 0, 0.68));
}
.gx-detail-logo.hidden { display: none; }
#m-title.has-logo {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.gx-detail-title {
  font-size: 2.35rem;
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.16;
  color: var(--gx-kt1);
  margin-bottom: 8px;
  overflow-wrap: break-word;
  text-wrap: balance;
  max-width: 24ch;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.62);
}

/* Hero meta line: uppercase micro type, one line (kool). */
.gx-detail-meta {
  font-size: 0.69rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.66);
  margin-bottom: 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
}
.gx-detail-meta .gx-star { color: var(--gx-kyellow); }

/* Rating pill (kool .rating): sits in the badges row under the head. */
.gx-detail-badges {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.gx-detail-badges:empty { margin-bottom: 0; }
.gx-rating {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-weight: 700;
  font-size: 0.8rem;
  height: 26px;
  padding: 0 10px 0 8px;
  border-radius: 999px;
  background: rgba(10, 14, 20, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.17);
  color: var(--gx-kt1);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
.gx-rating.hidden { display: none; }
.gx-rating svg { width: 13px; height: 13px; fill: var(--gx-kyellow); }
.gx-rating-src {
  margin-left: 3px;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-style: normal;
  color: var(--gx-kt2);
}

/* Synopsis: kool hero-desc — 4-line clamp + fade mask, click expands
 * (.foldable/.expanded are managed by js/detail-pages.js). */
.gx-detail-desc { min-width: 0; }
.gx-desc {
  font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 0.88rem;
  line-height: 1.62;
  color: rgba(255, 255, 255, 0.72);
  margin-bottom: 16px;
  max-width: 620px;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: pre-line;
  overflow-wrap: break-word;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.35);
}
.gx-desc.foldable {
  --gx-fold-fade: 14px;
  --gx-fold-gap: 6px;
  cursor: pointer;
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - var(--gx-fold-fade) - var(--gx-fold-gap)), transparent calc(100% - var(--gx-fold-gap)));
  mask-image: linear-gradient(180deg, #000 calc(100% - var(--gx-fold-fade) - var(--gx-fold-gap)), transparent calc(100% - var(--gx-fold-gap)));
}
.gx-desc.foldable.expanded {
  --gx-fold-fade: 0px;
  --gx-fold-gap: 0px;
  -webkit-line-clamp: unset;
  line-clamp: unset;
  -webkit-mask-image: none;
  mask-image: none;
}

/* ---------------- hero actions ---------------- */

.gx-detail-actions {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  padding: 2px 0;
}
.gx-release + .gx-detail-actions { margin-top: 14px; }

/* ---------------- unreleased countdown ----------------
 * One quiet glass panel, not a row of tiny boxes: a short "Coming soon"
 * header + date on the left and four typographic values on the right with
 * hairline separators. It is the primary action for an unreleased title,
 * so it sits above the secondary Trailer/List/Share row. Values use
 * tabular numerals (no width jitter); js/detail-pages.js ticks only the
 * digits that actually changed. Toggled by js/detail-pages.js; hidden state
 * uses both the utility class and inline display so the previous title can
 * never flash through. */
.gx-release {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 13px 24px;
  width: min(100%, 680px);
  margin: 2px 0 0;
  padding: 14px 18px;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  background:
    radial-gradient(120% 160% at 8% 0%, rgba(255, 255, 255, 0.08), transparent 48%),
    linear-gradient(180deg, rgba(17, 22, 29, 0.72), rgba(10, 14, 19, 0.58));
  -webkit-backdrop-filter: blur(18px) saturate(1.15);
  backdrop-filter: blur(18px) saturate(1.15);
  box-shadow: 0 22px 46px -28px rgba(0, 0, 0, 0.86), inset 0 1px rgba(255, 255, 255, 0.12);
}
.gx-release.hidden { display: none; }
.gx-release-copy { min-width: 0; }
.gx-release-kicker {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 3px;
  font-size: 0.61rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.88);
}
.gx-release-kicker::before {
  content: "";
  width: 6px;
  height: 6px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--gx-accent-strong, #d0a24f);
  box-shadow: 0 0 0 3px rgba(208, 162, 79, 0.1), 0 0 10px rgba(208, 162, 79, 0.45);
  animation: gx-release-pulse 2.6s var(--gx-kease, ease) infinite;
}
@keyframes gx-release-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(0.82); }
}
.gx-release-text {
  margin: 0;
  font-size: 0.83rem;
  font-weight: 500;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.55);
}
.gx-release-timer {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: center;
  min-width: 300px;
  padding-left: 20px;
  border-left: 1px solid rgba(255, 255, 255, 0.11);
}
.gx-release-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  min-width: 0;
  padding: 0 10px;
  text-align: center;
}
.gx-release-cell:first-child { padding-left: 0; }
.gx-release-cell:last-child { padding-right: 0; }
.gx-release-cell + .gx-release-cell::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9%;
  bottom: 9%;
  width: 1px;
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.16) 30%, rgba(255, 255, 255, 0.16) 70%, transparent);
}
.gx-release-cell b {
  display: block;
  font-size: 1.38rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--gx-kt1);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.4);
  will-change: transform, opacity;
}
.gx-release-cell i {
  margin-top: 6px;
  font-style: normal;
  font-size: 0.54rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.46);
}

/* Shared frame for the kool glass pills and circle buttons inside the hero.
 * #m-watch is excluded on purpose: css/watch-cta.css (loads last) owns the
 * play pill's look and must win every tie. */
.gx-detail .gx-btn-glass {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: var(--gx-fav-size);
  padding: 0 17px;
  border-radius: 999px;
  background: rgba(18, 22, 29, 0.43);
  color: var(--gx-kt1);
  border: 1px solid rgba(255, 255, 255, 0.17);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: inset 0 1px rgba(255, 255, 255, 0.07);
  font-family: inherit;
  font-size: 0.87rem;
  font-weight: 600;
  letter-spacing: 0.015em;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color 0.25s var(--gx-kease), transform 0.22s var(--gx-kease), box-shadow 0.25s var(--gx-kease), border-color 0.25s var(--gx-kease);
}
.gx-detail .gx-btn-glass:hover {
  background: rgba(255, 255, 255, 0.13);
  border-color: rgba(255, 255, 255, 0.28);
  transform: translateY(-1px);
}
.gx-detail .gx-btn-glass:active { transform: scale(0.97); }
.gx-detail .gx-btn-glass .gx-ico { width: 16px; height: 16px; flex-shrink: 0; }

/* My List / Download ride the circle slot (kool's favourite circle). */
.gx-detail .gx-btn-icon {
  width: var(--gx-fav-size);
  min-width: var(--gx-fav-size);
  height: var(--gx-fav-size);
  padding: 0;
}
.gx-detail .gx-btn-icon .gx-ico { width: 18px; height: 18px; }

/* Visible keyboard focus inside the detail shell (global rule fallback). */
.gx-detail .gx-btn:focus-visible {
  outline: 2px solid var(--gx-accent, #d0a24f);
  outline-offset: 2px;
}
.gx-modal-close:focus-visible {
  outline: 2px solid var(--gx-accent, #d0a24f);
  outline-offset: 2px;
}

/* Status line under the actions (resume / share / source status): a quiet
 * glass chip with a semantic status dot instead of the old saturated alert
 * box, so it reads as part of the dark kool surface, not a form warning. */
.gx-stream-msg {
  display: inline-flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 14px;
  padding: 9px 15px 9px 13px;
  font-size: 0.82rem;
  line-height: 1.5;
  letter-spacing: 0.01em;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(18, 22, 28, 0.62);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.24);
  color: var(--gx-kt2);
  max-width: 560px;
}
.gx-stream-msg::before {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  margin-top: 0.45em;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.05);
}
.gx-stream-msg.gx-stream-ok { color: rgba(255, 255, 255, 0.8); }
.gx-stream-msg.gx-stream-ok::before {
  background: #34d399;
  box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.12), 0 0 12px rgba(52, 211, 153, 0.4);
}
.gx-stream-msg.gx-stream-warn {
  color: rgba(255, 255, 255, 0.8);
  border-color: rgba(245, 158, 11, 0.24);
}
.gx-stream-msg.gx-stream-warn::before {
  background: #f59e0b;
  box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12), 0 0 12px rgba(245, 158, 11, 0.35);
}
.gx-stream-msg.hidden { display: none; }

/* ---------------- body sections ---------------- */

.gx-detail-body {
  position: relative;
  z-index: 2;
  padding: 14px var(--gx-kpad) calc(var(--gx-kpad) + 52px);
}

/* The poster stays in the DOM for admin/tests but the kool layout has no
 * poster column — it never paints. */
.gx-detail-poster { display: none; }
.gx-detail-poster.hidden { display: none; }

/* The route-back action only belongs to the error state. `.gx-detail
 * .gx-btn-glass` (loaded here) outranks the global `.hidden` utility, so the
 * hidden state needs an ID rule with equal-or-higher specificity. */
.gx-detail #m-back { margin-top: 1rem; }
.gx-detail #m-back.hidden { display: none; }
/* .gx-cast-row sets display:flex later than the global .hidden utility, so
 * the admin "hide cast" flag and the error-state cleanup need an explicit
 * hidden rule too. */
.gx-cast-row.hidden { display: none; }

/* Trailer box: same 16:9 glass frame as before. */
.gx-video-wrap {
  margin-top: 1.25rem;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  background: #000;
  border: 1px solid var(--gx-kborder);
}
.gx-video-frame { width: 100%; height: 100%; border: 0; display: block; }
.gx-video-wrap.hidden { display: none; }

.gx-section {
  padding-top: 20px;
  margin-top: 4px;
  margin-bottom: 32px;
}
.gx-section.hidden { display: none; }

/* Section title: white, compact, and marked by a short brand rule instead
 * of a full-width underline. The short rule reads as a label, not a divider,
 * which keeps the artwork-tinted surface calm. */
.gx-section-title {
  display: inline-block;
  position: relative;
  font-size: 1.08rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.065em;
  color: var(--gx-kt1);
  padding-bottom: 8px;
  margin-bottom: 14px;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35);
}
.gx-section-title::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 28px;
  border-radius: 2px;
  background: var(--gx-kred);
  box-shadow: 0 0 12px rgba(255, 61, 68, 0.28);
}
.gx-section-title.hidden { display: none; }

.gx-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}
.gx-section-head .gx-section-title { margin-bottom: 14px; }

/* Season select: kool glass control. */
.gx-season {
  height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: var(--gx-kt1);
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  outline: none;
}
.gx-season:focus-visible { outline: 2px solid var(--gx-accent, #d0a24f); outline-offset: 2px; }

/* Section reveal (kool .section.reveal → .is-in): armed by
 * observeDetailReveals() only when an IntersectionObserver exists, so no-IO
 * environments keep every section plainly visible. */
.gx-section.reveal.is-armed {
  opacity: 0;
  transform: translateY(28px);
}
.gx-section.reveal.is-armed.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 0.5s var(--gx-kease-enter), transform 0.5s var(--gx-kease-enter);
}

/* ---------------- cast row (kool circles) ---------------- */

.gx-cast-row {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 12px 0;
  /* kool .cast-row: the rail reaches out from under the floating rail (the
   * section pad plus --row-bleed = --rail-w) while the first circle stays
   * aligned with the section title. */
  margin-left: calc(-1 * (var(--gx-kpad) + var(--gx-krail-w)));
  padding-left: calc(var(--gx-kpad) + var(--gx-krail-w));
  scroll-padding-left: calc(var(--gx-kpad) + var(--gx-krail-w));
  mask-image: linear-gradient(to right, #000 0, #000 92%, transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 92%, transparent 100%);
}
.gx-cast-row::-webkit-scrollbar { display: none; }
.gx-cast-card {
  flex-shrink: 0;
  text-align: center;
  width: 134px;
  min-width: 0;
  border-radius: 10px;
}
.gx-cast-avatar {
  width: 112px;
  height: 112px;
  border-radius: 50%;
  background: var(--gx-kb2);
  border: 2px solid var(--gx-kborder);
  margin: 0 auto 6px;
  overflow: hidden;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--gx-kt3);
}
.gx-cast-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gx-cast-empty {
  margin: 0;
  padding: 2px 0;
  font-size: 0.82rem;
  color: rgba(255, 255, 255, 0.5);
}
.gx-cast-name {
  display: block;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--gx-kt1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gx-cast-role {
  display: block;
  margin-top: 3px;
  font-size: 0.69rem;
  color: var(--gx-kt3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------------- RECOMMENDED + SIMILAR rows (kool row-wrap) ------------ */

#m-similar, #m-recommended { min-width: 0; }
/* Empty rows stay hidden even against utility display rules. */
#m-similar.hidden { display: none; }

.gx-row-wrap { position: relative; }

/* The track: horizontal flex scroller that bleeds past the section pad AND
 * out from under the rail (kool `--row-bleed: var(--rail-w)` +
 * `.row{margin-left:calc(-1 * (var(--pad) + var(--row-bleed)))}` +
 * `scroll-padding-left`), so cards slide beneath the floating rail exactly
 * like kool's rows do under its .sidebar. The mask fades both edges (kool's
 * .row mask, 20px feather). Scroll itself is native (arrows, wheel, touch);
 * it is intentionally NOT a pointer-drag track. */
.gx-sim-grid {
  display: flex;
  gap: var(--gx-kgap);
  overflow-x: auto;
  scrollbar-width: none;
  scroll-behavior: smooth;
  scroll-snap-type: x proximity;
  padding: 6px var(--gx-kpad) 8px calc(var(--gx-kpad) + var(--gx-krail-w));
  margin: 0 calc(-1 * var(--gx-kpad)) 0 calc(-1 * (var(--gx-kpad) + var(--gx-krail-w)));
  scroll-padding-left: calc(var(--gx-kpad) + var(--gx-krail-w));
  mask-image: linear-gradient(to right, transparent 0, #000 20px, #000 calc(100% - 20px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 20px, #000 calc(100% - 20px), transparent 100%);
}
.gx-sim-grid::-webkit-scrollbar { display: none; }

.gx-sim-card {
  flex: 0 0 auto;
  width: 176px;
  min-width: 0;
  scroll-snap-align: start;
  content-visibility: auto;
  contain-intrinsic-size: 176px 278px;
  border-radius: 8px;
  outline-offset: 3px;
  color: inherit;
  text-decoration: none;
}
.gx-sim-card:focus-visible { outline: 2px solid var(--gx-accent, #d0a24f); }

.gx-sim-media {
  position: relative;
  display: block;
  aspect-ratio: 2 / 3;
  border-radius: 8px;
  overflow: hidden;
  background: var(--gx-kb2);
  border: 1px solid var(--gx-kborder);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: box-shadow 0.15s var(--gx-kease), border-color 0.15s var(--gx-kease), transform 0.15s var(--gx-kease);
}
.gx-sim-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gx-sim-card:hover .gx-sim-media,
.gx-sim-card:focus-visible .gx-sim-media {
  transform: translateY(-4px);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4);
  border-color: rgba(255, 255, 255, 0.55);
}

/* kool .card-landscape (item-view Recommended row): the 16:9 backdrop card at
 * kool's --card-land-w (300px; 230px ≤1024px; 180px ≤599px, see the
 * responsive blocks below). The wide flavor only lands on cards that carry a
 * backdrop (js/pages.js), so a backdrop-less recommendation keeps the
 * portrait poster look. */
.gx-sim-card-wide { width: 300px; contain-intrinsic-size: 300px 169px; }
.gx-sim-card-wide .gx-sim-media { aspect-ratio: 16 / 9; }

/* kool card-overlay: badge on top, title/rating below, revealed on hover. */
.gx-sim-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-start;
  gap: 6px;
  padding: 8px;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.2) 40%, rgba(0, 0, 0, 0.1));
  opacity: 0;
  transition: opacity 0.12s;
  pointer-events: none;
  z-index: 2;
}
.gx-sim-card:hover .gx-sim-overlay,
.gx-sim-card:focus-visible .gx-sim-overlay { opacity: 1; }

.gx-card-badge {
  padding: 3px 8px;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: var(--gx-kt1);
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.gx-card-badge-tv {
  background: var(--gx-kprimary);
  border-color: transparent;
}

.gx-sim-text {
  display: block;
  width: 100%;
  min-width: 0;
}
.gx-sim-title {
  display: block;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--gx-kt1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}
.gx-sim-year {
  display: block;
  margin-top: 2px;
  font-size: 0.78rem;
  color: var(--gx-kt2);
}

/* kool row arrows: circular glass buttons, hidden until hover, disabled at
 * the ends via the state classes wireDetailRow() maintains. */
.gx-row-arrow {
  display: none;
  position: absolute;
  top: 50%;
  z-index: 6;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #fff;
  background: rgba(16, 20, 26, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5), inset 0 1px rgba(255, 255, 255, 0.08);
  opacity: 0;
  transform: translateY(-50%) scale(0.9);
  transition: opacity 0.22s var(--gx-kease), transform 0.22s var(--gx-kease), background-color 0.2s var(--gx-kease);
}
.gx-row-wrap.row-can-scroll .gx-row-arrow { display: flex; }
.gx-row-wrap:hover .gx-row-arrow {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}
.gx-row-arrow:hover { background: rgba(26, 31, 38, 0.95); }
.gx-row-arrow:active { transform: translateY(-50%) scale(0.94); }
.gx-row-arrow svg { width: 20px; height: 20px; }
/* kool's final arrow anchors (.row-wrap .row-arrow-l/-r { left/right: 6px }):
 * pinned inside the row-wrap, i.e. just beside the section content edge —
 * never stranded behind the floating rail when the row is scrolled. */
.gx-row-arrow-l {
  left: 6px;
}
.gx-row-arrow-l svg { transform: rotate(180deg); }
.gx-row-arrow-r { right: 6px; }
.gx-row-wrap.row-at-start .gx-row-arrow-l,
.gx-row-wrap.row-at-end .gx-row-arrow-r {
  opacity: 0;
  pointer-events: none;
}
@media (hover: none) {
  .gx-row-arrow { display: none; }
  /* Touch devices have no hover: keep the card's title/rating readable
     instead of hiding the overlay until an impossible hover. */
  .gx-sim-overlay {
    opacity: 1;
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.32) 46%, rgba(0, 0, 0, 0.04) 72%);
  }
  .gx-sim-card:hover .gx-sim-media,
  .gx-sim-card:focus-visible .gx-sim-media { transform: none; }
}

/* ---------------- DETAILS drawer (kool item-facts) ---------------- */

.gx-facts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 18px 32px;
  max-width: 1160px;
  padding: 4px 0;
  margin-top: 14px;
}
.gx-fact { min-width: 0; }
.gx-facts dt {
  font-size: 0.69rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--gx-kt3);
  margin-bottom: 5px;
}
.gx-facts dd {
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--gx-kt1);
  margin: 0;
  overflow-wrap: anywhere;
}
.gx-facts dd a {
  color: inherit;
  text-decoration: none;
  font-weight: 600;
}
.gx-facts dd a:hover,
.gx-facts dd a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.gx-fact-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-right: 10px;
}
.gx-fact-link svg { width: 12px; height: 12px; }

/* ---------------- providers: markup kept, never paints ---------------- */
/* "Where to watch legally" is removed from the detail card entirely. The
 * markup stays in index.html (admin/tests reference the IDs) but never
 * paints — including the interim "Finding where to watch…" loader. */
#m-providers,
#m-providers-head {
  display: none !important;
}

/* ---------------- episodes: horizontal rail (fast, no-lag) ----------------
 * kool ep-tile look: 200px cards, 16:9 still, "N. Title", date · duration
 * meta (plus Greybox's overview line, admin-togglable). The rail chrome
 * (viewport + shelf steppers + data-* states) is the shared js/shelves.js
 * contract — untouched. Perf rules: flat colors only (no per-card blur on
 * a 48-episode rail), transform/opacity-only hovers, content-visibility
 * offscreen skip, fixed-size images (no CLS). */

#m-episodes { min-width: 0; }

.gx-eps-rail {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0.25rem 0.15rem 0.9rem;
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}
/* Rail bars come from the site-wide slim system (css/tokens.css). */

/* Episode rail steppers: same buttons as shelf rails (base .gx-shelf-btn
 * lives in css/shelves.css). The viewport positions them and owns the
 * show/hide rules, mirroring .gx-shelf-viewport exactly. */
.gx-eps-nav { position: relative; }
.gx-eps-viewport { position: relative; overflow: hidden; }
/* kool's episode row is a .row too: the clip frame (viewport) starts at the
 * viewport edge so tiles slide under the floating rail, the rail keeps its
 * first tile aligned with the section title, and the prev stepper stays next
 * to that content edge instead of hiding behind the rail. */
#m-episodes .gx-eps-viewport {
  margin-left: calc(-1 * (var(--gx-kpad) + var(--gx-krail-w)));
}
#m-episodes .gx-eps-rail {
  padding-left: calc(var(--gx-kpad) + var(--gx-krail-w));
  scroll-padding-left: calc(var(--gx-kpad) + var(--gx-krail-w));
}
#m-episodes .gx-shelf-btn[data-dir="prev"] {
  left: calc(var(--gx-kpad) + var(--gx-krail-w) + 8px);
}
.gx-eps-viewport:hover .gx-shelf-btn,
.gx-eps-viewport:focus-within .gx-shelf-btn { opacity: 1; }
.gx-eps-viewport:hover .gx-shelf-btn:disabled,
.gx-eps-viewport:focus-within .gx-shelf-btn:disabled { opacity: 0.25; }
.gx-eps-viewport[data-overflow="false"] .gx-shelf-btn { display: none; }
@media (hover: none) {
  .gx-eps-viewport .gx-shelf-btn { display: none; }
}

.gx-ep-card {
  flex: 0 0 auto;
  width: 200px;
  scroll-snap-align: start;
  content-visibility: auto;
  contain-intrinsic-size: 200px 236px;
  cursor: pointer;
  border: 2px solid transparent;
  border-radius: 4px;
  overflow: hidden;
  outline: none;
  transition: border-color 0.15s var(--gx-kease), transform 0.15s var(--gx-kease), box-shadow 0.15s var(--gx-kease);
}
.gx-ep-card:hover {
  transform: translateY(-4px);
  border-color: rgba(255, 255, 255, 0.55);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4);
}
.gx-ep-card:focus-visible { outline: 2px solid var(--gx-accent, #d0a24f); }

.gx-ep-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--gx-kb2);
  overflow: hidden;
}
.gx-ep-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--gx-kb2);
}

.gx-ep-body { padding: 0; min-width: 0; }

.gx-ep-title {
  margin-top: 6px;
  padding: 0 6px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--gx-kt1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.gx-ep-ov {
  margin-top: 3px;
  padding: 0 6px;
  font-size: 0.69rem;
  line-height: 1.45;
  color: var(--gx-kt3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.gx-ep-meta {
  margin: 2px 0 0;
  padding: 0 6px 6px;
  font-size: 0.62rem;
  color: var(--gx-kt2);
}
.gx-ep-resume { color: #6ee7b7; }

/* Skeleton cards while the season loads (no images — pure CSS). */
.gx-ep-card.is-skel { pointer-events: none; border-color: transparent; }
.gx-ep-card.is-skel:hover { transform: none; box-shadow: none; }
.gx-ep-card.is-skel .gx-ep-thumb {
  border: none;
}
.gx-ep-card.is-skel .gx-ep-thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.12), transparent);
  animation: gx-ep-shimmer 1.3s infinite;
}
.gx-ep-skbar { height: 0.8rem; border-radius: 0.4rem; background: #2e343d; margin-top: 0.6rem; }
.gx-ep-skbar.short { width: 55%; }
@keyframes gx-ep-shimmer { 100% { transform: translateX(100%); } }

@media (max-width: 640px) {
  .gx-ep-card { width: 176px; contain-intrinsic-size: 176px 220px; }
}

/* ---------------- responsive (kool mobile scale) ---------------- */

/* kool's ≤1024px scale: the section pad tightens and the landscape cards
 * step down to --card-land-w 230px. */
@media (max-width: 1024px) {
  .gx-detail { --gx-kpad: 24px; }
  .gx-sim-card-wide { width: 230px; contain-intrinsic-size: 230px 129px; }
}

/* Phones: a single 18px gutter, a fully bleed hero, a full-width Watch CTA,
 * and a fixed 44px+ secondary control row. The old mobile rule set the hero
 * padding from --gx-khero and relied on the rail variable, which collapsed
 * completely when --gx-krail-w was unitless; this block is self-contained. */
@media (max-width: 640px) {
  .gx-detail {
    --gx-kpad: 18px;
    --gx-kgap: 12px;
    --gx-khero: min(68vh, 660px);
    --gx-fav-size: 46px;
  }
  .gx-row-arrow { display: none !important; }
  .gx-detail-hero {
    padding: calc(98px + env(safe-area-inset-top, 0px)) var(--gx-kpad) calc(30px + env(safe-area-inset-bottom, 0px));
    min-height: var(--gx-khero);
  }
  .gx-detail-hero-body { align-items: flex-end; }
  .gx-detail-content { max-width: none; padding-bottom: 0; }
  .gx-detail-logo {
    max-width: min(76%, 330px);
    height: clamp(44px, 7.5vh, 68px);
    margin-bottom: 10px;
  }
  .gx-detail-title {
    font-size: 1.82rem;
    line-height: 1.16;
    letter-spacing: -0.03em;
    max-width: none;
    margin-bottom: 7px;
  }
  /* Long genre/runtime lines wrap instead of truncating on narrow phones. */
  .gx-detail-meta {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    line-height: 1.55;
    letter-spacing: 0.1em;
    margin-bottom: 8px;
  }
  .gx-detail-badges { margin-bottom: 10px; }
  .gx-detail-desc { max-width: none; }
  .gx-desc {
    -webkit-line-clamp: 3;
    line-clamp: 3;
    max-width: 100%;
    font-size: 0.85rem;
    line-height: 1.62;
    margin-bottom: 15px;
  }
  .gx-detail-actions { gap: 8px; width: 100%; }
  /* Watch owns a full row (52px touch target); Trailer flexes; the three
   * utility actions become equal circles. Hidden buttons simply leave the
   * flex line, so the unreleased row (Trailer/List/Share) stays balanced. */
  .gx-detail-actions > #m-watch {
    flex: 1 0 100%;
    width: 100%;
    min-height: 52px;
    padding: 0 22px;
    font-size: 15px;
  }
  .gx-detail-actions > #m-trailer {
    flex: 1 1 auto;
    min-width: 0;
    height: 46px;
  }
  .gx-detail-actions > #m-list,
  .gx-detail-actions > #m-download,
  .gx-detail-actions > #m-share {
    flex: 0 0 46px;
    width: 46px;
    min-width: 46px;
    height: 46px;
    padding: 0;
  }
  .gx-detail-actions > #m-share .gx-btn-word { display: none; }
  .gx-detail .gx-btn-glass { padding: 0 15px; font-size: 0.84rem; }
  .gx-detail .gx-btn-icon .gx-ico { width: 19px; height: 19px; }
  /* Countdown: one column, header above the four values. */
  .gx-release {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
    width: 100%;
    margin: 1px 0 0;
    padding: 14px 15px;
    border-radius: 16px;
  }
  .gx-release-timer {
    width: 100%;
    min-width: 0;
    padding: 12px 0 0;
    border-left: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
  }
  .gx-release-cell { padding: 0 6px; }
  .gx-release-cell:first-child { padding-left: 0; }
  .gx-release-cell:last-child { padding-right: 0; }
  .gx-release-cell b { font-size: 1.2rem; }
  .gx-release-cell i { margin-top: 5px; font-size: 0.5rem; }
  /* Section rhythm: roomy but not sparse. */
  .gx-section { padding-top: 22px; margin-bottom: 30px; }
  .gx-section-title { font-size: 1rem; margin-bottom: 12px; }
  .gx-detail-body { padding: 12px var(--gx-kpad) calc(44px + env(safe-area-inset-bottom, 0px)); }
  .gx-sim-grid { padding-top: 4px; padding-bottom: 10px; }
  .gx-sim-card { width: 156px; contain-intrinsic-size: 156px 246px; border-radius: 10px; }
  .gx-sim-card .gx-sim-media { border-radius: 10px; }
  /* Touch/mobile: the hover overlay is always visible so titles + ratings
     stay readable (there is no hover to reveal them). */
  .gx-sim-overlay {
    opacity: 1;
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.32) 46%, rgba(0, 0, 0, 0.04) 72%);
  }
  .gx-cast-card { width: 102px; }
  .gx-cast-avatar { width: 80px; height: 80px; }
  .gx-facts { grid-template-columns: minmax(0, 1fr); }
  .gx-modal-close {
    top: calc(14px + env(safe-area-inset-top, 0px));
    right: calc(14px + env(safe-area-inset-right, 0px));
    width: 42px;
    height: 42px;
    background: rgba(16, 19, 24, 0.58);
  }
  /* The backdrop now stretches with the hero content and dissolves into the
   * ambient page tint (no hard art cap, no side scrim). */
  .gx-detail-hero-bg { height: 100%; }
  .gx-detail-hero-bg::after { background: none; }
  .gx-detail-hero-bg::before {
    background: linear-gradient(180deg,
      rgba(16, 20, 26, 0.28) 0%,
      rgba(16, 20, 26, 0.04) 22%,
      transparent 38%,
      rgba(18, 22, 29, 0.38) 60%,
      rgba(18, 22, 29, 0.78) 82%,
      rgba(27, 34, 44, 0.96) 96%,
      var(--gx-kb0) 100%);
  }
}

/* ≤380px: guard the tightest phones without changing the composition. */
@media (max-width: 380px) {
  .gx-detail { --gx-kpad: 16px; --gx-fav-size: 44px; }
  .gx-detail-title { font-size: 1.68rem; }
  .gx-release-cell b { font-size: 1.1rem; }
  .gx-release-cell i { font-size: 0.47rem; letter-spacing: 0.1em; }
  .gx-detail-actions > #m-list,
  .gx-detail-actions > #m-download,
  .gx-detail-actions > #m-share { flex-basis: 44px; width: 44px; min-width: 44px; height: 44px; }
  .gx-detail-actions > #m-trailer { height: 44px; }
}

/* kool ≤599px: the rail disappears entirely and its reserved width collapses
 * to ZERO PIXELS, so every bleed, the hero pull-out and the scroller inset
 * resolve to the plain mobile layout with no further overrides. The unit
 * matters: `0` made calc(<length> + 0) invalid, which silently dropped the
 * hero's entire padding shorthand and pinned the title to x=0. */
@media (max-width: 640px) {
  #modal { --gx-krail-w: 0px; }
  .gx-detail-nav { display: none; }
  .gx-sim-card-wide { width: 240px; contain-intrinsic-size: 240px 135px; }
}

/* ---------------- reduced motion ---------------- */

@media (prefers-reduced-motion: reduce) {
  .gx-detail-badge { transition: none; }
  /* Open/close fade snaps to its end state; no panel travel. */
  #modal #modal-bg,
  #modal .gx-detail,
  #modal .gx-detail-nav { transition-duration: 0.001s; }
  .gx-detail.gx-loading .gx-detail-title,
  .gx-detail.gx-loading .gx-detail-meta,
  .gx-release-kicker::before { animation: none; }
  /* Enter chain jumps to its end state instantly (durations ~0 + no delay
   * keep the `both` fill styles applied without any visible motion). */
  #modal .gx-enter,
  #modal .gx-enter * {
    animation-duration: 0.001s !important;
    animation-delay: 0s !important;
  }
  .gx-section.reveal.is-armed {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .gx-ep-thumb img { transition: none; }
  .gx-ep-card { transition: none; }
  .gx-ep-card.is-skel .gx-ep-thumb::after { animation: none; }
  .gx-eps-rail { scroll-snap-type: none; }
  .gx-sim-media,
  .gx-sim-overlay { transition: none; }
  .gx-sim-card:hover .gx-sim-media,
  .gx-sim-card:focus-visible .gx-sim-media { transform: none; }
  /* The rail still expands on hover, it just snaps instead of sliding. */
  .gx-detail-nav,
  .gx-detail-nav-dock,
  .gx-detail-nav-word,
  .gx-detail-nav .nav-btn,
  .gx-detail-nav-ico { transition: none; }
  /* Background recede is instant: no shrink/sink animation. */
  #page-ambient, #hero, .gx-page, body > footer {
    transition: none;
    transform: none;
  }
}
