/* Greybox Phase 6.1 — cinematic detail foundation (/movie/:id, /tv/:id).
 * The route-backed modal (index.html #modal) is the detail page. Scoped under
 * .gx-detail; consumes Phase 1 tokens + the existing .gx-btn pill system
 * (css/hero.css). No red, no neon, no emoji, no new color system, no trailer
 * lifecycle here (hero.js untouched). Vanilla CSS, no library. */

/* ---------------- panel (wider than the old max-w-4xl) ---------------- */

.gx-detail {
  background:
    radial-gradient(60% 30% at 50% 0%, rgba(255, 255, 255, 0.09), transparent 70%),
    linear-gradient(170deg, rgba(46, 51, 59, 0.9) 0%, rgba(35, 39, 46, 0.93) 55%, rgba(32, 36, 42, 0.95) 100%);
  -webkit-backdrop-filter: blur(20px) saturate(1.15);
  backdrop-filter: blur(20px) saturate(1.15);
  border-color: var(--gx-border-strong);
  box-shadow: var(--gx-shadow-pop), var(--gx-glass-highlight);
}

/* A little wider than before (62rem -> ~65rem) while staying inside the viewport. */
#modal .gx-detail {
  width: min(65rem, calc(100vw - 2rem));
  max-width: 65rem;
}

/* ---------------- detail side rails (Ads: detail-left / detail-right) ---
 * The panel centers itself, so real blank space only exists on wide
 * viewports (>= 1720px: a ~330px flank on each side of the 65rem panel).
 * js/ads.js moves the two anchors between two homes to match:
 *   wide  -> the #modal gutter containers below, parked in the blank area
 *            left/right of the panel (fixed-size rail, one aligned row of
 *            wrapped cells inside — multiple ads stack within the flank);
 *   narrow -> the in-flow wrapper just above the Similar section, where
 *            the slots stack one after another (phones/tablets/small
 *            laptops have no flank, so nothing may sit beside the card).
 * Each home hides while the other is active, so an unmoved anchor (or a
 * blocked/void row) can never leave a stray gap in either layout. */
.gx-detail-adsides {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 1.25rem;
}
.gx-detail-rail {
  display: none;
}
@media (min-width: 1720px) {
  .gx-detail-adsides { display: none; }
  .gx-detail-rail {
    display: block;
    position: absolute;
    top: 13vh;
    width: 300px;
  }
  .gx-detail-rail--l { left: calc(50vw - 840px); }
  .gx-detail-rail--r { right: calc(50vw - 840px); }
}

/* The page behind recedes while a card is up: every background layer
 * (ambient, header, hero, content, footer) sinks backwards and shrinks while
 * the modal rises — dim kept so the card stays the focus. The modal itself
 * is a separate fixed layer, so its positioning is untouched. Toggled via
 * body.gx-modal-open in showModal/hideModal; the reduced-motion switch
 * below makes the recede instant. */
#page-ambient, #site-header, #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 #site-header,
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 rising panel. */
#modal-bg {
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

/* Icon buttons feel smooth: gentle grow on hover, settled by default. */
#modal-close {
  transition: transform var(--gx-transition), background var(--gx-transition);
}
#modal-close:hover { transform: scale(1.08); }
#modal-close:active { transform: scale(0.96); }

/* ---------------- modal open animation (pop up from the bottom) ---------------- */

@keyframes gx-detail-rise {
  from { opacity: 0; transform: translateY(140px) scale(0.99); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes gx-modal-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

#modal:not(.hidden) #modal-bg {
  animation: gx-modal-fade 0.3s ease-out both;
}

#modal:not(.hidden) .gx-detail {
  animation: gx-detail-rise 0.48s cubic-bezier(0.22, 1, 0.36, 1) both;
  transform-origin: 50% 100%;
  will-change: transform, opacity;
}

/* ---------------- cinematic header ---------------- */

.gx-detail-hero {
  position: relative;
  overflow: hidden;
  background: var(--gx-bg-0);
  isolation: isolate;
}

/* Artwork fills the header; JS hides it when no backdrop/poster exists, so a
 * broken icon can never flash (the dark header + shade remain valid).
 * Cinematic banner: clears 70vh on desktop so the artwork dominates the card
 * (title + actions ride overlaid at its base); shorter on phones. */
.gx-detail-backdrop {
  object-position: center 22%;
  display: block;
  height: 72vh;
  height: 72svh;
  height: 72dvh;
  min-height: 380px;
}

/* Restrained cinematic treatment: top scrim (close control legibility),
 * readable text band, strong bottom fade into the panel. */
.gx-detail-shade {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(27, 30, 35, 0.5), transparent 22%),
    linear-gradient(to top, #23272e 2%, rgba(35, 39, 46, 0.88) 30%, rgba(35, 39, 46, 0.35) 62%, transparent 88%);
}

.gx-detail-head {
  z-index: 2;
  min-width: 0;
}

.gx-detail-title {
  letter-spacing: -0.015em;
  line-height: 1.08;
  color: var(--gx-text);
  overflow-wrap: break-word;
  text-wrap: balance;
  max-width: 22ch;
}

/* Official TMDB title treatment in the modal header: the transparent artwork
 * keeps its own aspect ratio inside these caps — never stretched into a
 * fixed box, 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(22rem, 72%);
  max-height: 6.5rem;
  width: auto;
  height: auto;
  object-fit: contain;
  object-position: left bottom;
  margin-bottom: 0.45rem;
  filter: drop-shadow(0 6px 24px rgba(0, 0, 0, 0.55));
}
.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-meta {
  color: var(--gx-text-dim);
}

.gx-detail-meta .gx-star { color: var(--gx-accent-strong); }

/* 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);
  background: rgba(10, 10, 14, 0.72);
  border: 1px solid var(--gx-accent-border);
  border-radius: var(--gx-radius-pill);
  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); border-color: var(--gx-border-faint); }

.gx-detail-actions { align-items: center; }

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

/* ---------------- poster / information ---------------- */

.gx-detail-body {
  display: grid;
  grid-template-columns: 176px minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}

.gx-detail-poster {
  grid-column: 1;
  grid-row: 1;
  width: 100%;
  aspect-ratio: 2/3;
  object-fit: cover;
  display: block;
  border-radius: 0.8rem;
  background: var(--gx-surface);
  border: 1px solid var(--gx-border-faint);
  background-clip: padding-box;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
}

.gx-detail-poster.hidden { display: none; }

.gx-detail-main { min-width: 0; grid-column: 2; grid-row: 1; }

/* BUG FIX: when the poster is hidden (no artwork), the grid must collapse to a
 * single full-width column. Otherwise .gx-detail-main falls into the narrow
 * 176px track and every word wraps — the squeezed column in the report.
 * Covered three ways: explicit JS class (.is-no-poster, primary), plus :has()
 * fallbacks for the `.hidden` class and the inline `display:none` style that
 * setDetailArtwork() uses. */
.gx-detail-body.is-no-poster,
.gx-detail-body:has(.gx-detail-poster.hidden),
.gx-detail-body:has(.gx-detail-poster[style*="none"]) {
  grid-template-columns: minmax(0, 1fr);
}

.gx-detail-body.is-no-poster .gx-detail-main,
.gx-detail-body:has(.gx-detail-poster.hidden) .gx-detail-main,
.gx-detail-body:has(.gx-detail-poster[style*="none"]) .gx-detail-main {
  grid-column: 1;
}

/* Synopsis: professional long-form reading type. Inter-first system stack
 * (matches the app shell), comfortable size + generous leading, soft
 * off-white for sustained reading, natural wrapping. */
.gx-detail-overview {
  font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 0.975rem;
  font-weight: 400;
  line-height: 1.75;
  letter-spacing: 0.002em;
  color: #d7d7df;
  max-width: 65ch;
  overflow-wrap: break-word;
  word-break: normal;
  white-space: pre-line;
}

/* Collapsed state: 4 readable lines, then a native ellipsis. Expanded state
 * removes the clamp and shows the full synopsis. */
.gx-detail-overview.is-clamped {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
}

.gx-overview-toggle {
  margin-top: 0.5rem;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--gx-accent-strong);
}

.gx-overview-toggle:hover {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.gx-overview-toggle:focus-visible {
  outline: 2px solid var(--gx-accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* "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;
}

/* ---------------- quiet sub-sections (cast / providers / episodes keep
 * their existing markup + behavior; only the error/link accents align) ---- */

.gx-detail #m-back { margin-top: 1rem; }

/* ---------------- episodes: horizontal rail (fast, no-lag) ----------------
 * Reference look: 16:9 thumb cards in a snap-scroll row, E-badge top-left,
 * runtime pill bottom-right, title + 2-line overview below. Whole card plays.
 * Perf rules: flat colors only (no per-card blur/shadow — those jank a
 * 48-episode rail), transform/opacity-only hovers (compositor thread),
 * content-visibility skips offscreen cards, 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). */

/* Modal panel owns the card's vertical scroll: contain wheel chaining and
 * give its bar a touch more presence (it is the page while a card is up). */
.gx-detail {
  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); }

/* 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; }
.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: min(17rem, 72vw);
  scroll-snap-align: start;
  content-visibility: auto;
  contain-intrinsic-size: 272px 264px;
  cursor: pointer;
  border-radius: 0.8rem;
  outline-offset: 3px;
}

.gx-ep-card:focus-visible { outline: 2px solid var(--gx-accent); }

.gx-ep-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 0.75rem;
  overflow: hidden;
  background: #1c2027;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.gx-ep-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #1c2027;
  transition: transform 0.25s ease, filter 0.25s ease;
}

.gx-ep-card:hover .gx-ep-thumb img { transform: scale(1.04); filter: brightness(1.06); }

.gx-ep-num,
.gx-ep-dur {
  position: absolute;
  font-size: 0.7rem;
  font-weight: 800;
  line-height: 1;
  color: #fff;
  background: rgba(0, 0, 0, 0.65);
  border-radius: 999px;
  padding: 0.32rem 0.55rem;
  pointer-events: none;
}

.gx-ep-num { top: 0.55rem; left: 0.55rem; }
.gx-ep-dur { bottom: 0.55rem; right: 0.55rem; }

.gx-ep-play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.6rem;
  height: 2.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.95rem;
  color: #0b0b10;
  background: var(--gx-accent, #d0a24f);
  border-radius: 999px;
  transform: translate(-50%, -50%) scale(0.9);
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}

.gx-ep-card:hover .gx-ep-play,
.gx-ep-card:focus-visible .gx-ep-play { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* Touch: no hover — keep a small always-visible affordance instead. */
@media (hover: none) {
  .gx-ep-play {
    width: 2.1rem;
    height: 2.1rem;
    font-size: 0.8rem;
    top: auto;
    bottom: 0.55rem;
    left: 0.55rem;
    transform: none;
    opacity: 0.92;
  }
  .gx-ep-card:hover .gx-ep-thumb img { transform: none; }
}

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

.gx-ep-title {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--gx-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.gx-ep-ov {
  margin-top: 0.25rem;
  font-size: 0.8rem;
  line-height: 1.5;
  color: #a1a1aa;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.gx-ep-meta { margin-top: 0.3rem; font-size: 0.72rem; color: #71717a; }
.gx-ep-resume { color: #6ee7b7; }

/* Skeleton cards while the season loads (no images — pure CSS). */
.gx-ep-card.is-skel { pointer-events: 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: min(13.5rem, 68vw); contain-intrinsic-size: 216px 230px; }
}

/* ---------------- "Similar like {name}" grid ----------------
 * Multi-row poster grid (NOT a horizontal rail): ten-plus rows paint up
 * front and more append as the modal scrolls (infinite load from
 * js/pages.js). No arrows, no drag, no snap — the modal's own vertical
 * scroll owns movement. Perf rules match episode cards: fixed aspect boxes
 * (no CLS), transform/opacity-only hovers, content-visibility offscreen
 * skip. */

#m-similar { min-width: 0; }
/* Empty grid stays hidden even against utility display rules. */
#m-similar.hidden { display: none; }

.gx-sim-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
  gap: 1.4rem 1rem;
  align-items: start;
  margin-top: 0.9rem;
}

.gx-sim-card {
  min-width: 0;
  content-visibility: auto;
  contain-intrinsic-size: 216px 372px;
  border-radius: 0.8rem;
  outline-offset: 3px;
  color: inherit;
  text-decoration: none;
}
.gx-sim-card img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  border-radius: 0.8rem;
  background: #1c2027;
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45), 0 2px 8px rgba(0, 0, 0, 0.4);
  transition: transform 0.25s ease, filter 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.gx-sim-card:hover img,
.gx-sim-card:focus-visible img {
  transform: scale(1.03) translateY(-2px);
  filter: brightness(1.08);
  border-color: rgba(255, 255, 255, 0.22);
  box-shadow: 0 16px 38px rgba(0, 0, 0, 0.55), 0 4px 12px rgba(0, 0, 0, 0.45);
}
.gx-sim-card:focus-visible { outline: 2px solid var(--gx-accent); }
.gx-sim-title {
  display: block;
  margin-top: 0.55rem;
  font-size: 0.88rem;
  font-weight: 650;
  color: var(--gx-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gx-sim-year { display: block; margin-top: 0.1rem; font-size: 0.78rem; color: #a1a1aa; }

/* Infinite-load sentinel: spinner row pinned full-width at the grid end. */
.gx-sim-more {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 1.1rem 0 0.4rem;
  font-size: 0.8rem;
  color: #a1a1aa;
}
.gx-sim-spin {
  width: 1rem;
  height: 1rem;
  flex: 0 0 auto;
  border-radius: 9999px;
  border: 2px solid rgba(255, 255, 255, 0.18);
  border-top-color: var(--gx-accent);
  animation: gx-sim-spin 0.8s linear infinite;
}
@keyframes gx-sim-spin { to { transform: rotate(360deg); } }

/* ---------------- responsive ---------------- */

@media (max-width: 640px) {
  .gx-detail-head { left: 1.1rem; right: 1.1rem; bottom: 0.9rem; }
  .gx-detail-title { font-size: 1.5rem; max-width: none; }
  /* Natural stack: modest poster on top, full-width overview below. */
  .gx-detail-body { grid-template-columns: minmax(0, 1fr); gap: 0.9rem; }
  .gx-detail-poster { width: 112px; }
  .gx-detail-overview { font-size: 0.92rem; }
  /* Shorter cinematic banner on phones; smaller logo + rail cards. */
  .gx-detail-backdrop {
    height: 46vh;
    height: 46svh;
    height: 46dvh;
    min-height: 300px;
  }
  .gx-detail-logo { max-width: 78%; max-height: 4.5rem; }
  /* Larger premium cards on phones: 2 across instead of 3. */
  .gx-sim-grid { grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: 1.1rem 0.8rem; }
}

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

@media (prefers-reduced-motion: reduce) {
  .gx-detail-badge { transition: none; }
  #modal:not(.hidden) #modal-bg,
  #modal:not(.hidden) .gx-detail { animation: none; }
  .gx-ep-thumb img,
  .gx-ep-play { transition: none; }
  .gx-ep-card.is-skel .gx-ep-thumb::after { animation: none; }
  .gx-eps-rail { scroll-snap-type: none; }
  .gx-sim-spin { animation: none; }
  /* Background recede is instant: no shrink/sink animation. */
  #page-ambient, #site-header, #hero, .gx-page, body > footer {
    transition: none;
    transform: none;
  }
  .gx-sim-card img { transition: none; }
}
