/* ==========================================================================
   layout-cinematic — the premium studio homepage for default_v2.
   Loaded ONLY when the tenant's active layout is `cinematic`
   (global_header.html gates the <link> on $web_layout).

   Design intent: one commanding image, then air. The billboard fills the
   screen and dissolves into the page instead of ending on a seam; rails run
   one card sparser than classic so artwork is large; headings are bold and
   tightly tracked; chrome stays out of the way until you scroll.

   White-label: every value below is derived from the tenant's own palette via
   the vxl system tokens (see layouts.css). No colour is designed here.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Scale overrides — the personality of the layout
   -------------------------------------------------------------------------- */
[data-layout="cinematic"] {
  --vxl-gutter: 4.5%;
  --vxl-section-gap: var(--vxl-space-7);        /* 48 */
  --vxl-card-gap: 10px;
  --vxl-card-radius: var(--vxl-radius-md);      /* 8 */
  --vxl-rail-title-size: clamp(1.25rem, 1.7vw, 1.6rem);
  --vxl-rail-title-weight: 700;
  --vxl-hero-h: 86vh;
}

/* dense rail arrangement — ⚠ mirrors GAPS.cinematic (dense) in
   _layout_resolver.html; change both or rails drift from grids */
@media (min-width: 992px) {
  body[data-layout="cinematic"][data-lo-rail-density="dense"] {
    --vxl-card-gap: 8px;
  }
}

/* --------------------------------------------------------------------------
   Billboard — a letterboxed dissolve. The bottom gradient melts the artwork
   into the page background and the sides are vignetted, so the image has no
   hard edge anywhere. Scrims come from the tenant's body colour, so a light
   palette dissolves to white just as correctly.
   -------------------------------------------------------------------------- */
[data-layout="cinematic"] .featureSlider {
  position: relative;
}
@media (min-width: 992px) {
  /* Scrims live on `.relative`, not on `.featureSlider` — see the grid layout
     note: the billboard sits inside a `z-index: 1` stacking context, so an
     overlay on `.featureSlider` paints over the hero text as well as the art.

     ::before = left scrim (the title's ground) + soft side/top vignettes. */
  [data-layout="cinematic"] .featureSlider .relative::before {
    background:
      linear-gradient(90deg,
        var(--vxl-scrim) 0%,
        var(--vxl-scrim-weak) 30%,
        transparent 58%),
      linear-gradient(270deg, var(--vxl-scrim-weak) 0%, transparent 22%),
      linear-gradient(180deg, var(--vxl-scrim-weak) 0%, transparent 16%);
  }
  /* ::after = the deep bottom dissolve that melts the billboard into the page */
  [data-layout="cinematic"] .featureSlider .relative::after {
    height: 40vh;
    background: linear-gradient(0deg,
      var(--vxl-scrim-solid) 0%,
      var(--vxl-scrim-solid) 6%,
      var(--vxl-scrim) 42%,
      transparent 100%);
  }
}

/* Type: the single loudest thing on the page */
[data-layout="cinematic"] .featureSlider .vxe-billboard .slideTitle {
  font-size: clamp(2.4rem, 5vw, 4.5rem) !important;
  font-weight: 700;
  letter-spacing: var(--vxl-tracking-tight);
  line-height: 1.05;
  max-width: 16ch;
}
[data-layout="cinematic"] .featureSlider .vxe-billboard .slideLogo img.innerSlideLogo {
  max-width: clamp(240px, 34vw, 500px) !important;
  max-height: clamp(100px, 15vw, 230px) !important;
}
[data-layout="cinematic"] .featureSlider .vxe-billboard .text_description,
[data-layout="cinematic"] .featureSlider .vxe-billboard .text_description1 {
  max-width: 46ch;
  color: var(--vxl-ink-muted);
}
/* Hero CTAs: a rounded RECTANGLE, as the reference draws them — the pill
   read as a different design language from the detail page's slab (6px) and
   from the reference itself. Sized rather than em-padded so all three keep
   one height whatever their label length. */
[data-layout="cinematic"] .featureSlider .vxe-billboard .sldieBtns .btn {
  border-radius: var(--vxl-radius-pill, 999px) !important;
  /* Matches the re-cut --lg tier in components.css (46/15.5/26, down from
     54/17/30) so the billboard CTA and the detail page's Watch Now are one
     control at one size. */
  height: 46px;
  padding: 0 26px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 9px;
  font-size: 15.5px !important;
  font-weight: 700;
}
/* Glyphs track the label so the pairing stays balanced at the larger size. */
[data-layout="cinematic"] .featureSlider .vxe-billboard .sldieBtns .btn .vxm-ico,
[data-layout="cinematic"] .featureSlider .vxe-billboard .sldieBtns .btn svg,
[data-layout="cinematic"] .featureSlider .vxe-billboard .sldieBtns .btn i {
  width: 22px !important;
  height: 22px !important;
  font-size: 22px !important;
}

/* Maturity rating — the stock style is a tab welded to the viewport edge at
   bottom:35%, which floats mid-artwork with no gutter and reads as a clipped
   fragment rather than a label. Bring it onto the page gutter and align its
   baseline with the billboard's button row (both measured in the same 7vw the
   billboard pads with), so it belongs to the content block. */
[data-layout="cinematic"] .featureSlider .maturityLevel.vxe-agetag,
[data-layout="cinematic"] .featureSlider .maturityLevel {
  right: var(--vxl-gutter) !important;
  bottom: 7vw !important;
  padding: 5px var(--vxl-space-3) !important;
  border-left-width: 3px !important;
  border-radius: var(--vxl-radius-sm) !important;
  font-size: var(--vxl-text-sm) !important;
  min-height: 0 !important;
  /* owner call (critique round): the chip vanished on light artwork — a
     scrim ground + soft blur keep it legible everywhere */
  background: color-mix(in srgb, var(--vod-body-back-color, #0e0e10) 52%, transparent) !important;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
}

/* --------------------------------------------------------------------------
   Rails — generous air, bold headings. Density (one card sparser) comes from
   vodlixLayout.railSlides(); this only handles type.
   -------------------------------------------------------------------------- */
[data-layout="cinematic"] .swiperHolder .swiperTitle {
  letter-spacing: -0.01em;
  /* the rail-title markup carries Bootstrap's .font-weight-normal utility
     (400 !important), which silently beats the token consumer in cards.css */
  font-weight: var(--vxl-rail-title-weight, 700) !important;
}

/* --------------------------------------------------------------------------
   Cards — the Netflix dwell-expansion panel is suppressed; a calm lift is all
   that replaces it.

   An accent underline used to sit here too, as an inset box-shadow. It is gone:
   an inset shadow follows the card's border-radius, so a 3px bar meant for the
   bottom edge curved up both sides and read as a red BORDER around the card
   rather than an underline. On anything part-watched it also landed beside the
   continue-watch bar — two red 3px rules stacked on one corner.

   It was the only accent chrome in the layout, which is the deeper reason to
   drop it: everything else here signals with elevation, scale and hairlines and
   keeps the accent for actions. Scale plus shadow says "this is the one you are
   pointing at" without decorating the artwork.
   -------------------------------------------------------------------------- */
/* No dwell panel. Hovering a card shows the artwork and nothing else — this
   layout sells on the picture, and a slab of buttons sliding out over the rail
   is the Netflix habit it exists to avoid.

   This was briefly restored and is now removed again, correctly this time. The
   first removal stranded desktop viewers: the panel is where More Info lived,
   and the poster's own link points at `/watch/` on desktop, so a card had no
   route to the title at all. That is fixed at the source instead — `thumbUrl`
   in video.html / series.html now returns the detail page for this layout, the
   way it always did on mobile — so the poster IS the way in and the panel has
   nothing left to offer. */
[data-layout="cinematic"] .videoBlock.vxc.vxc-open {
  transform: none !important;
  z-index: 5 !important;
}
[data-layout="cinematic"] .videoBlock.vxc.vxc-open .videoInfo,
[data-layout="cinematic"] .videoBlock.vxc:hover .videoInfo {
  display: none !important;
}
[data-layout="cinematic"] .videoBlock.vxc {
  transition: transform var(--vxl-dur-2) var(--vxl-ease),
              box-shadow var(--vxl-dur-2) var(--vxl-ease);
}
[data-layout="cinematic"] .videoBlock.vxc:hover,
[data-layout="cinematic"] .videoBlock.vxc.vxc-open {
  transform: scale(1.04) !important;
  box-shadow: var(--vxl-shadow-3);
}

/* --------------------------------------------------------------------------
   Header — transparent over the billboard, glass once you scroll
   -------------------------------------------------------------------------- */
[data-layout="cinematic"] .vxh {
  background: linear-gradient(180deg, var(--vxl-scrim) 0%, transparent 100%);
}
[data-layout="cinematic"] .vxh.is-scrolled::before {
  background: var(--vxl-glass);
  -webkit-backdrop-filter: var(--vxl-glass-blur);
  backdrop-filter: var(--vxl-glass-blur);
  border-bottom: 1px solid var(--vxl-line);
}
@supports not (backdrop-filter: blur(1px)) {
  /* never a see-through bar: fall back to the tenant's own scroll gradient */
  [data-layout="cinematic"] .vxh.is-scrolled::before {
    background: linear-gradient(139deg,
      var(--vod-scroll-header-gradient-left) 39%,
      var(--vod-scroll-header-gradient-right) 100%);
  }
}
[data-layout="cinematic"] .vxh__navLink {
  letter-spacing: 0.01em;
}

/* --------------------------------------------------------------------------
   Mobile web — the billboard keeps its presence without swallowing the screen
   -------------------------------------------------------------------------- */
/* ==========================================================================
   MOBILE — the HBO Max shape.

   An earlier revision deliberately had NO cinematic mobile hero: the native
   app's design was made the shared baseline for every layout, on the reasoning
   that web and app matching each other mattered more than the layouts differing
   on a phone. That call has been reversed on purpose. Cinematic is the layout a
   tenant picks when they want the premium studio look, and on a phone that look
   is one full-bleed portrait image — it is the whole point of choosing it.

   Measured off HBO Max (iPhone, 1284x2778):
   - artwork is FULL-BLEED 9:16, starting at y=0 behind the status bar, and the
     header + nav sit ON it rather than above it
   - nav is underlined text, not filled pills
   - title / meta / actions are overlaid on the bottom of the artwork
   - the primary action is bare text ("▶ Watch Now"), with a lone "+" opposite
   - dots sit under the artwork, above the first rail

   Classic keeps the inset card that matches the native app. This is the
   difference between the two on a phone, and it is a large one.
   ========================================================================== */
@media (max-width: 991.98px) {
  /* Gutter is pinned to the app's 16px on phones, and pinning it HERE is not
     redundant with mobile-app.css declaring it on `body`: `[data-layout="…"]`
     is an attribute selector and outranks a bare `body`, so the layout's own
     desktop percentage would otherwise keep applying all the way down. */
  [data-layout="cinematic"] {
    --vxl-gutter: 16px;
    /* How far the detail screen's info block overlaps the artwork. Read by the
       overlap itself AND by the trailer mute disc, which is positioned inside
       it — one number, so they cannot drift apart. */
    --vxc-info-pull: 104px;
    --vxl-section-gap: var(--vxl-space-6);      /* 32 */
    /* 9:16 full-bleed. Every consumer of --vxe-media-h (the dot strip, the
       overlay anchoring) derives from this one value, so the hero's height is
       stated once. */
    --vxe-media-h: calc(100vw * 16 / 9);
  }

  /* ---- 1. Full-bleed artwork, up behind the header -------------------- */
  /* mobile-app.css insets the hero as a 16px card and pushes it clear of the
     fixed header + nav strip. Cinematic undoes all three: edge to edge, no
     radius, and no top clearance so the art runs to y=0. The selectors carry
     `[data-layout]` purely for weight against those base rules. */
  body[data-layout="cinematic"].page-home #new-editorpick,
  body[data-layout="cinematic"].page-movies #new-editorpick,
  body[data-layout="cinematic"].page-tv_shows #new-editorpick,
  body[data-layout="cinematic"].page-content_list_group #new-editorpick {
    margin-top: 0 !important;
    margin-inline: calc(50% - 50vw) !important;
    width: 100vw !important;
    border-radius: 0 !important;
  }
  body[data-layout="cinematic"].page-content_list_group #vxe-ep-mount {
    padding-top: 0 !important;
  }
  /* `.featureSlider` — the wrapper AROUND the swiper — carries its own 64px top
     margin, which held the artwork below the header even with the hero's own
     clearance removed. Full-bleed means from y=0. The `#items-list` variant is
     not redundant: editorpick.css sets that margin through an ID selector, and
     an ID outranks any number of classes. */
  body[data-layout="cinematic"] .featureSlider,
  body[data-layout="cinematic"] #items-list .featureSlider {
    margin-top: 0 !important;
  }

  /* ---- The frame follows the backend setting -------------------------
     `mobile_editors_pick_design` already decides which ARTWORK is fetched
     (editorpick.html → editorBackdrop). These two blocks used to be one
     rule pinning BOTH orientations to 9/16, so a section switched to
     landscape fetched a 16:9 still and then poured it into a portrait
     frame — scaled ~2.4x and centre-cropped, losing roughly half the
     image. Portrait keeps the full-bleed 9:16 canvas; landscape gets the
     aspect it was authored at. */
  [data-layout="cinematic"] .vxe-mob-portrait .ratio,
  [data-layout="cinematic"] .vxe-mob-portrait .ratio.ratio-16x9 {
    aspect-ratio: 9 / 16 !important;
    border-radius: 0 !important;
  }
  [data-layout="cinematic"] .vxe-mob-portrait,
  [data-layout="cinematic"] .vxe-mob-portrait .relative {
    --vxe-media-h: calc(100vw * 16 / 9);
  }
  [data-layout="cinematic"] .vxe-mob-landscape .ratio,
  [data-layout="cinematic"] .vxe-mob-landscape .ratio.ratio-16x9 {
    aspect-ratio: 16 / 9 !important;
    border-radius: 0 !important;
  }
  [data-layout="cinematic"] .vxe-mob-landscape,
  [data-layout="cinematic"] .vxe-mob-landscape .relative {
    --vxe-media-h: calc(100vw * 9 / 16);
  }

  /* ---- Landscape: the still, then the copy beneath it ----------------
     A 16:9 still is ~56vw tall and cannot carry the hero on its own, so
     the copy stops overlaying the picture and stacks under it. The
     ambient extension — the same frame, scaled and blurred — fills that
     band, which is what keeps the hero full-bleed without cropping the
     still or inventing artwork. It is decorative and aria-hidden. */
  [data-layout="cinematic"] .vxe-mob-landscape .relative {
    overflow: hidden;
    /* the site chrome on a phone is two rows — the bar plus the category
       nav — which is ~126px. Against a 693px portrait canvas that is
       nothing; against a 219px still it is most of the picture. */
    --vxe-chrome: calc(var(--vxm-header-h, 68px) + 58px);
  }
  /* Landscape stacks plainly: header bar, then the pills menu on page
     colour, then the still. Owner call (seedtest 2026-08-26) — with the
     ambient gone, artwork behind the menu read as a dead band behind the
     header, so the still now clears BOTH chrome rows (--vxe-chrome =
     header + pills) and the menu stays out of the hero entirely. */
  [data-layout="cinematic"] .vxe-mob-landscape .ratio {
    margin-top: var(--vxe-chrome, calc(var(--vxm-header-h, 68px) + 58px));
  }
  /* The band the ambient fills is a BACKGROUND, so it takes the tenant's
     background colour — `--vod-body-bg`, set from branding_bg_color — and the
     blurred frame sits on top of it. `brightness()` alone assumed a dark
     theme: on a tenant with a light background it produced a dark band
     floating on a white page. */
  [data-layout="cinematic"] .vxe-mob-landscape .relative,
  [data-layout="cinematic"] .vxe-mob-landscape,
  [data-layout="cinematic"] .featureSlider:has(.vxe-mob-landscape) {
    background-color: var(--vod-body-bg, #000);
  }
  /* The band under the still is the tenant's background colour, flat. The
     blurred ambient (and a briefly-restored, desaturated variant) is OUT for
     landscape — owner call, seedtest 2026-08-26: "the gradients doesn't look
     so good". Landscape stacks plainly instead: header, then the menu, then
     the still (see the .ratio margin below). The element stays in the DOM
     should the treatment ever come back. */
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-ambient,
  body[data-layout="cinematic"] .vxm-hero-ambient {
    display: none !important;
  }
  /* Tint toward the tenant's background instead of dimming toward black, so
     the band belongs to the page whatever colour the page is. */
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-ambient::after {
    content: "";
    position: absolute;
    inset: 0;
    /* 46% flattened the blur into a single wash — the reference keeps the
       frame readable behind the copy. Lighter tint, and it deepens toward the
       page so the band still resolves to the tenant's background. */
    background: linear-gradient(180deg,
      color-mix(in srgb, var(--vod-body-bg, #000) 18%, transparent) 0%,
      color-mix(in srgb, var(--vod-body-bg, #000) 40%, transparent) 55%,
      var(--vod-body-bg, #000) 100%);
  }
  [data-layout="cinematic"] .vxe-mob-landscape .ratio {
    position: relative;
    z-index: 1;
  }
  /* The copy leaves the artwork and sits below it, overlapping the still's
     lower edge so the logo lands on the darkened ambient rather than on a
     face. */
  [data-layout="cinematic"] .vxe-mob-landscape .swiperInfo.vxe-billboard {
    position: relative !important;
    bottom: auto !important;
    z-index: 3;
    margin-top: -26px;
    padding: 0 var(--vxl-gutter) 14px !important;
  }
  /* The slide keeps the height the portrait hero needed — 644px against 562px
     of content here — so the row below it started 82px lower than it should.
     Sized to its content instead; the column's own trailing margin goes with
     it. Together with the padding above, this is the ~110px of dead band
     between the CTA row and the first rail. */
  [data-layout="cinematic"] .vxe-mob-landscape .swiper-slide,
  [data-layout="cinematic"] .vxe-mob-landscape .swiper-wrapper {
    height: auto !important;
  }
  /* The height is imposed above the slide: the slider, its container and the
     wrapper all computed 625px while the content measured 543. Sized for the
     portrait canvas, it left ~80px of empty band under the CTA row. */
  body[data-layout="cinematic"] .featureSlider:has(.vxe-mob-landscape),
  body[data-layout="cinematic"] .vxe-mob-landscape.swiper-container,
  body[data-layout="cinematic"] .featureSlider:has(.vxe-mob-landscape) .swiper-container {
    /* It is an ASPECT-RATIO, not a height — 390/625.3 = 0.624, a portrait
       ratio on the slider itself. `height: auto` cannot defeat that, which is
       why the first attempt changed nothing. */
    aspect-ratio: auto !important;
    height: auto !important;
    min-height: 0 !important;
  }
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .row > [class*="col-"] {
    margin-bottom: 6px !important;
    padding-bottom: 0 !important;
  }

  /* ---- The logo sits in a fixed well ---------------------------------
     Logo art has no common aspect: across these five slides the rendered
     heights are 48, 58, 130, 130 and 64px, and because the copy is IN FLOW
     on this variant, each one pushed its slide to a different height —
     485, 496, 567, 567, 502. The carousel sizes every slide to the tallest,
     so a title with a short logo showed ~82px of empty band under its CTAs
     while a tall one looked right.

     A fixed well decouples the two: the artwork scales inside a constant
     box, so every slide is the same height whatever the logo's dimensions.
     Bottom-aligned, because the gap that matters visually is the one
     between the logo and the genres line — that stays constant, and the
     slack collects above the logo, against the still. */
  /* `body` prefix on purpose: the shared logo rules earlier in this file carry
     !important at equal specificity and sit later in source order, so they win
     a tie. This has to outrank them, not merely follow them. */
  body[data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .slideLogo {
    height: 96px !important;
    display: flex !important;
    align-items: flex-end !important;
    justify-content: center !important;
    margin: 0 auto 2px !important;
  }
  body[data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .slideLogo img.innerSlideLogo {
    max-height: 96px !important;
    max-width: min(68vw, 300px) !important;
    width: auto !important;
    height: auto !important;
    object-fit: contain;
  }
  /* A title with no logo art renders the text heading instead — same well, so
     it cannot reintroduce the variance it was meant to remove. */
  body[data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .vxe-mobTitle {
    min-height: 96px;
    display: flex !important;
    align-items: flex-end !important;
    justify-content: center !important;
  }
  /* The scrim covers only the still. Since the plain stack (26.410.1) the
     still starts BELOW both chrome rows, so the scrim is pinned to the
     still's own box — sized to the old header-only clearance it ended 58px
     above the still's bottom, and its solid bottom edge cut a hard
     dark-to-bright seam across the picture (seedtest report). The fixed
     top band is gone with it: the chrome sits on page colour now, so there
     is no nav on artwork to protect — only the bottom dissolve remains,
     blending the still into the copy that overlaps its lower edge. */
  [data-layout="cinematic"] .vxe-mob-landscape .relative::after {
    top: var(--vxe-chrome, calc(var(--vxm-header-h, 68px) + 58px)) !important;
    height: calc(100vw * 9 / 16) !important;
    background:
      linear-gradient(0deg,
        var(--vxl-scrim-solid) 0%,
        var(--vxl-scrim) 26%,
        transparent 46%) bottom / 100% 100% no-repeat !important;
  }
  /* The dots belong to the picture's foot, not its middle: on the portrait
     canvas they sit low in a tall frame, but over a 219px still the same
     offset lands them across the subject. */
  /* The dots read as the hero's own footer, sitting directly above the first
     rail — not over the artwork, where they compete with the picture, and not
     mid-stack between the logo and the genres. */
  [data-layout="cinematic"] .vxe-mob-landscape .swiper-pagination,
  [data-layout="cinematic"] .vxe-mob-landscape .swiper-pagination-bullets,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-dots {
    top: auto !important;
    bottom: 16px !important;
    z-index: 4;
  }
  /* Bigger, and they animate: the active dot grows into a pill rather than
     just changing colour, so the transition reads as movement between slides.
     Width and border-radius both transition, which is what makes it stretch
     instead of pop. */
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-dots .swiper-pagination-bullet {
    width: 9px !important;
    height: 9px !important;
    margin: 0 4px !important;
    opacity: 0.5;
    background: var(--vxl-ink-muted) !important;
    transition:
      width var(--vxl-dur-3, 320ms) var(--vxl-ease, cubic-bezier(.215,.61,.355,1)),
      border-radius var(--vxl-dur-3, 320ms) var(--vxl-ease, cubic-bezier(.215,.61,.355,1)),
      opacity var(--vxl-dur-2) var(--vxl-ease),
      background-color var(--vxl-dur-2) var(--vxl-ease),
      transform var(--vxl-dur-2) var(--vxl-ease);
  }
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-dots .swiper-pagination-bullet-active {
    width: 26px !important;
    border-radius: 999px !important;
    opacity: 1;
    background: var(--vxl-ink) !important;
  }
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-dots .swiper-pagination-bullet:active {
    transform: scale(0.86);
  }
  @media (prefers-reduced-motion: reduce) {
    [data-layout="cinematic"] .vxe-mob-landscape .vxe-dots .swiper-pagination-bullet {
      transition: opacity var(--vxl-dur-2) var(--vxl-ease), background-color var(--vxl-dur-2) var(--vxl-ease);
    }
  }

  /* Scrim. mobile-app.css switches these off because its hero is a card with
     the text below it; here the text sits ON the picture and cannot be read
     without one. Mixed from the tenant's own body colour, so a light palette
     dissolves to white rather than to an assumed black. */
  [data-layout="cinematic"] .vxe-mob-portrait .relative::after,
  [data-layout="cinematic"] .vxe-mob-landscape .relative::after {
    content: "";
    display: block !important;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: var(--vxe-media-h);
    z-index: 2;
    pointer-events: none;
    /* Two independent layers.

       The BOTTOM one is proportional — it dissolves the picture into the page
       and should scale with the hero.

       The TOP one is a FIXED 210px, and that is the point: it exists to keep
       the logo and the nav readable, and those sit at a fixed distance from the
       top of the screen no matter how tall the artwork is. As a percentage it
       was 20% of the hero, which on bright artwork left the nav sitting on open
       sky. Sized to the chrome instead (header ~68 + nav ~44, plus fade), so a
       white or busy image cannot swallow the menu. */
    background:
      linear-gradient(0deg,
        var(--vxl-scrim-solid) 0%,
        var(--vxl-scrim-solid) 10%,
        var(--vxl-scrim) 40%,
        transparent 72%) bottom / 100% 100% no-repeat,
      linear-gradient(180deg,
        var(--vxl-scrim-solid) 0%,
        var(--vxl-scrim) 42%,
        transparent 100%) top / 100% 210px no-repeat;
  }

  /* ---- 2. Title / meta / actions overlaid on the artwork -------------- */
  /* Portrait only: the copy sits ON the artwork, which is 9:16 and has room
     for it. Landscape stacks the copy BELOW the still instead — see the
     landscape block above — so it must not be pinned to the bottom here. */
  [data-layout="cinematic"] .vxe-mob-portrait .swiperInfo.vxe-billboard {
    position: absolute !important;
    inset-inline: 0;
    bottom: 0;
    z-index: 3;
    padding: 0 var(--vxl-gutter) 30px !important;
  }
  [data-layout="cinematic"] .vxe-billboard .row > [class*="col-"] {
    display: block !important;
  }
  /* The reference centers the whole hero column: logo/title, meta,
     description, actions, dots — one centered stack on the artwork. */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .vxe-mobTitle,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .vxe-mobTitle {
    display: -webkit-box !important;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    /* `margin: 0` alone left the BOX at the column's left edge while the
       desktop rule above still capped it at `max-width: 16ch` — 283px inside
       a 343px column on a phone. `text-align: center` then centred the text
       inside that narrower box, so the title sat 30px left of the genre line,
       synopsis and buttons under it (owner report). The measure is a
       desktop concern; on a phone the column IS the measure. */
    max-width: 100% !important;
    margin: 0 auto !important;
    font-size: clamp(1.6rem, 7vw, 2.2rem) !important;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: var(--vxl-tracking-tight);
    text-transform: none !important;
    text-align: center;
  }
  /* A title WITH logo art shows the logo, centered — the text title stands
     in only when there is no logo (the logo branch renders no .slideLogo). */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .slideLogo,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .slideLogo {
    display: block !important;
    margin: 0 auto 2px !important;
    text-align: center;
  }
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .slideLogo img.innerSlideLogo,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .slideLogo img.innerSlideLogo {
    max-width: min(68vw, 300px) !important;
    max-height: 130px !important;
  }
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard [class*="col-"]:has(.slideLogo) .vxe-mobTitle,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard [class*="col-"]:has(.slideLogo) .vxe-mobTitle {
    display: none !important;
  }
  /* Meta line: "18+ · 2018 · Comedy" — quiet, centered under the title. */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .vxe-genres,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .vxe-genres {
    display: block !important;
    margin: 8px 0 0 !important;
    font-size: 13px;
    line-height: 1.4;
    color: var(--vxl-ink-muted);
    text-align: center !important;
  }
  /* One short description line, centered — the reference shows it. */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .text_description,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .text_description {
    display: -webkit-box !important;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    max-width: 92%;
    margin: 8px auto 0 !important;
    font-size: 14px;
    line-height: 1.45;
    color: var(--vxl-ink);
    text-align: center;
  }
  [data-layout="cinematic"] .vxe-billboard .text_description1 {
    display: none !important;
  }

  /* ---- 3. Actions: centered white slab + square "+" (the reference) ---- */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns {
    display: flex !important;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    margin-top: 16px !important;
  }
  /* Primary: the reference's "Watch …" slab. Its paint used to be pinned to
     --vxl-ink / the page colour, which is why the Buttons panel stopped dead
     at 992px — desktop's hero wore the tenant's primary, the phone's wore
     white. It now runs the same chain the desktop billboard does, and only
     falls back to the ink slab for a theme carrying no primary at all. */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns .btn,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns .btn {
    flex: 0 0 auto !important;
    display: inline-flex !important;
    align-items: center !important;
    width: auto !important;
    min-width: 0 !important;
    /* Phone measure, re-cut with the desktop tier (was 48/17/24). 44px is
       the floor, not a target: it is the touch minimum the icon discs
       beside it also hold, so the pair reads as one row rather than a slab
       next to a button. */
    height: 44px !important;
    padding: 0 20px !important;
    border: 0 !important;
    border-radius: var(--vxl-radius-pill, 999px) !important;
    background: var(--vod-btn-primary-bg, var(--vxl-ink)) !important;
    color: var(--vod-btn-primary-text, var(--vod-body-bg, #000)) !important;
    font-size: 15px !important;
    font-weight: 700 !important;
    gap: 8px;
    transition: background-color var(--vxl-dur-1, 0.15s) var(--vxl-ease, ease),
                color var(--vxl-dur-1, 0.15s) var(--vxl-ease, ease);
  }
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns .btn:hover,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns .btn:hover,
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns .btn:focus,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns .btn:focus {
    background: var(--vod-btn-primary-hover-bg, var(--vod-btn-primary-bg, var(--vxl-ink))) !important;
    color: var(--vod-btn-primary-text, var(--vod-body-bg, #000)) !important;
  }
  [data-layout="cinematic"] .vxe-billboard .sldieBtns .btn .vxm-ico,
  [data-layout="cinematic"] .vxe-billboard .sldieBtns .btn i {
    width: 20px !important;
    height: 20px !important;
    font-size: 20px !important;
    color: inherit !important;
  }
  [data-layout="cinematic"] .vxe-billboard .sldieBtns .btn > span {
    color: inherit !important;
  }
  /* More Info goes — tapping the artwork already opens the title (the ≤992px
     tap handler in editorpick.html). Trailer stays, as the dark secondary
     slab beside the white Play. */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns .btn.btn-secondary,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns .btn.btn-secondary {
    display: none !important;
  }
  body[data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns a.btn.btn-editors-pick[data-stats-event="trailer_play"],
  body[data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns a.btn.btn-editors-pick[data-stats-event="trailer_play"] {
    /* mobile-app.css hides the hero trailer — its landscape selector
       identifies the button by SHAPE (a[href*="/watch/"]:has(outline
       icon):not(:has(filled play))), and the :has() arguments push it to
       (0,7,1). This selector is deliberately heavier — body + a.btn
       .btn-editors-pick + the stats attr = (0,7,2) — so Cinematic's
       re-show wins. */
    display: inline-flex !important;
    /* DOM order already puts Trailer before Play — keep it there */
    order: 0;
    /* Trailer is a .btn-editors-pick, i.e. a PRIMARY on every other surface —
       desktop's hero paints Play and Trailer the same. Pinning it to a neutral
       surface token here put it outside the Buttons panel's reach; it now runs
       the primary chain like its twin. */
    background: var(--vod-btn-primary-bg, var(--vxl-surface-2)) !important;
    color: var(--vod-btn-primary-text, var(--vxl-ink)) !important;
  }
  body[data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns a.btn.btn-editors-pick[data-stats-event="trailer_play"]:hover,
  body[data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns a.btn.btn-editors-pick[data-stats-event="trailer_play"]:hover,
  body[data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns a.btn.btn-editors-pick[data-stats-event="trailer_play"]:focus,
  body[data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns a.btn.btn-editors-pick[data-stats-event="trailer_play"]:focus {
    background: var(--vod-btn-primary-hover-bg, var(--vod-btn-primary-bg, var(--vxl-surface-2))) !important;
    color: var(--vod-btn-primary-text, var(--vxl-ink)) !important;
  }
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns .btn[data-stats-event="trailer_play"] .vxm-ico,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns .btn[data-stats-event="trailer_play"] .vxm-ico,
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .sldieBtns .btn[data-stats-event="trailer_play"] > span,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .sldieBtns .btn[data-stats-event="trailer_play"] > span {
    /* follows the button it sits in — otherwise the label kept the old ink
       colour while the chip took the tenant's primary */
    color: var(--vod-btn-primary-text, var(--vxl-ink)) !important;
  }
  /* My List: the dark rounded square beside the slab. */
  [data-layout="cinematic"] .vxe-mob-portrait .vxe-billboard .vxe-mylist,
  [data-layout="cinematic"] .vxe-mob-landscape .vxe-billboard .vxe-mylist {
    order: 9;
    flex: 0 0 auto !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    margin-inline-start: 0 !important;
    width: 44px !important;
    height: 44px !important;
    padding: 0 !important;
    border-radius: var(--vxl-radius-pill, 999px) !important;
    background: var(--vxl-surface-2) !important;
    color: var(--vxl-ink) !important;
  }
  [data-layout="cinematic"] .vxe-billboard .vxe-mylist .boxBtn,
  [data-layout="cinematic"] .vxe-billboard .vxe-mylist .rundedBtn {
    width: 44px !important;
    height: 44px !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
    color: inherit !important;
  }
  [data-layout="cinematic"] .vxe-billboard .vxe-mylist__label {
    display: none !important;
  }
  [data-layout="cinematic"] .vxe-billboard .vxe-mylist .vxm-ico {
    width: 24px !important;
    height: 24px !important;
  }

  /* The scrim above does most of the work, but a gradient is a probability, not
     a guarantee — a near-white still can still wash out white text. The logo
     and nav therefore carry their own shadow, which costs nothing on dark
     artwork and is what makes "readable on ANY thumbnail" actually true.
     Derived from the tenant's background, so it stays a shadow rather than
     becoming a halo on a light palette. */
  [data-layout="cinematic"] .vxh__logo img,
  [data-layout="cinematic"] .vxm-pill {
    filter: drop-shadow(0 1px 3px var(--vxl-scrim-solid));
  }
  [data-layout="cinematic"] .vxm-pill {
    text-shadow: 0 1px 3px var(--vxl-scrim-solid);
  }

  /* ---- Episodes as a swipeable ROW on the phone too -------------------
     Desktop already lays the episodes out as the reference's horizontal
     strip; the phone kept the app's stacked list. Same structure here,
     sized for a thumb: cards at 74vw so the next one peeks and the row
     reads as scrollable. These override mobile-app.css's list treatment
     (thumbnail-left, full-width rows), so each of its rules is answered. */
  body[data-layout="cinematic"].page-series_details .vxc-epScroll {
    display: flex;
    flex: 0 0 100%;
    width: 100%;
    flex-wrap: nowrap;
    gap: 14px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding: 2px 0 12px;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep {
    display: block !important;
    flex: 0 0 74vw;
    width: 74vw;
    scroll-snap-align: start;
    margin: 0 !important;
    padding: 0 !important;
  }
  /* the list furniture the row does not use */
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep hr,
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep > .row > .col-1 {
    display: none !important;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep > .row {
    display: block !important;
    margin-inline: 0 !important;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep > .row > [class*="col-"]:not(.col-1) {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    flex: none !important;
    padding: 0 !important;
  }
  /* still on top, text beneath — mobile-app.css floats it left at 108px */
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu {
    display: block !important;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu > a.img {
    display: block !important;
    flex: none !important;
    width: 100% !important;
    margin: 0 0 10px !important;
    /* 4px — the corner the poster cards and the home rails use */
    border-radius: 4px;
    overflow: hidden;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu .vid-description {
    display: -webkit-box !important;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0 !important;
    font-size: 13px;
    line-height: 1.45;
  }
  /* Title / duration head. The markup pairs them with `justify-content:
     space-between` plus a `pr-4`, which on a 74vw card pushed the duration
     off the edge: the title link is not shrinkable by default, so it won
     the row and the duration was clipped. Let the title shrink and clamp,
     and pin the duration as a nowrap column. */
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu > div > div:first-child {
    align-items: baseline;
    gap: 10px;
    padding-right: 0 !important;
    margin-bottom: 6px !important;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu > div > div:first-child > a {
    flex: 1 1 auto;
    min-width: 0;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu > div > div:first-child > span {
    flex: 0 0 auto;
    white-space: nowrap;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu h2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 15px !important;
    line-height: 1.3;
  }

  /* ---- Season picker: a compact field, not a full-width bar -----------
     Sized to its own label like the reference's "Season 1" control, on the
     gutter under the heading.
     NOTE: the detail PAGE now renders .vxc-seasonPick (see the SEASON PICKER
     section at the foot of this file) — these rules are the fallback <select>
     that surfaces without cineDetail still show. */
  body[data-layout="cinematic"].page-series_details .vxm-epList select.form-select,
  body[data-layout="cinematic"].page-series_details .vxm-epList select.form-control {
    width: auto !important;
    min-width: 168px;
    max-width: 100%;
    height: 44px !important;
    margin: 0 0 4px !important;
    padding: 0 42px 0 16px !important;
    border: 1px solid var(--vxl-line) !important;
    border-radius: 8px !important;
    background-color: var(--vxl-surface-2) !important;
    color: var(--vxl-ink) !important;
    font-size: 15px;
    font-weight: 600;
    /* own caret: the platform arrow is invisible on a dark fill */
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-image:
      linear-gradient(45deg, transparent 50%, currentColor 50%),
      linear-gradient(135deg, currentColor 50%, transparent 50%) !important;
    background-position: calc(100% - 20px) center, calc(100% - 15px) center !important;
    background-size: 5px 5px, 5px 5px !important;
    background-repeat: no-repeat !important;
  }
  body[data-layout="cinematic"].page-series_details .vxm-epList select.form-select:focus {
    outline: none;
    border-color: var(--vxl-ink-faint) !important;
    box-shadow: none !important;
  }
  /* the OS renders option rows itself — keep them legible on dark */
  body[data-layout="cinematic"].page-series_details .vxm-epList select option {
    background-color: #1a1a1a;
    color: #fff;
  }

  /* Detail-page More Like This wall — uniform poster cells, but ONLY when
     the wall is actually portrait: the detail blocks emit `.portrait` on
     these frames only when the tenant's display_thumb_type is portrait
     (owner report: landscape tenants got a poster wall regardless). A
     landscape wall keeps .ratio-16x9's own sizing — still uniform, since
     every cell shares the one class. Within the portrait wall a title
     with no portrait artwork falls back to a landscape still and the
     frame crops it, same as before. */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .ratio.portrait,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .ratio.portrait {
    /* the rails' own poster shape and square corners — see the desktop rule
       for why 177.78% rather than 2/3, and why no radius */
    aspect-ratio: auto !important;
    height: 0 !important;
    padding: 0 0 177.78% !important;
    border-radius: 4px;
    overflow: hidden;
  }
  /* ...and the layers around it, which carry their own corners (the card
     wrapper at 8px, the anchor and image at 6px on top). The desktop block
     zeroes these too; without the same here the phone showed a rounded
     wrapper clipping a 4px frame — two different corners on one card. */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg,
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg > a,
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .ratio > div,
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .ratio img,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg > a,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .ratio > div,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .ratio img {
    border-radius: 0 !important;
  }
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .ratio img,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .ratio img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .card-img-overlay,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .card-img-overlay {
    display: none !important;
  }
}

/* Desktop carries the same protection, for the same reason: the header is
   transparent over artwork on the homepage billboard AND now on the detail
   page, so a bright still can wash the nav out exactly as it did on a phone.
   Cheap on dark artwork, decisive on light. */
@media (min-width: 992px) {
  [data-layout="cinematic"] .vxh__logo img {
    filter: drop-shadow(0 1px 3px var(--vxl-scrim-solid));
  }
  [data-layout="cinematic"] .vxh__navLink,
  [data-layout="cinematic"] .vxh__iconBtn,
  [data-layout="cinematic"] .vxh__userName {
    text-shadow: 0 1px 3px var(--vxl-scrim-solid);
  }
}

/* ==========================================================================
   ALL WIDTHS — the sections below were authored for the phone (their own
   comments say so: underlined pills, hero dots, the 3:4 detail screen, the
   poster walls, the More screen) but sat inside the DESKTOP media block
   above, so the mobile components (.vxm-pills / .vxe-mob-* / .vxm-more__*)
   never got them. They cannot simply move to a mobile query either: the
   desktop detail block further down BUILDS ON several of them (the episode
   row grid, the search wall). So they apply at every width — which is the
   pre-existing desktop behavior plus, at last, the phone they were written
   for. Desktop-only overrides stay in the (min-width: 992px) block below.
   ========================================================================== */
@media all {
  /* ---- 4. Nav ----------------------------------------------------------
     Cinematic used to strip the phone chips back to underlined text nav
     (borderless, 17px, an inset underline on the active item). The mobile
     chrome is now one design across every layout — outlined chips from
     mobile-app.css (owner call: match the reference app) — so those
     overrides are gone rather than fighting the shared sheet. Only the
     row's own spacing is restated here. */
  [data-layout="cinematic"] .vxm-pills {
    background: none !important;
    padding-inline: var(--vxl-gutter);
  }
  [data-layout="cinematic"] .vxm-pill {
    flex: 0 0 auto;
  }

  /* ---- 5. Dots sit ON the artwork, below the action row --------------- */
  /* Not below the artwork: `#new-editorpick` is `overflow: hidden` (it has to
     be, or the next slide bleeds past the card on the desktop billboard), so
     anything pinned past the media height is simply clipped away — which is
     what happened to the first attempt. HBO puts them inside the frame anyway,
     a little under the CTA row. */
  [data-layout="cinematic"] .vxe-dots {
    top: calc(var(--vxe-media-h) - 24px);
  }
  [data-layout="cinematic"] .vxe-mob-portrait .swiperInfo.vxe-billboard,
  [data-layout="cinematic"] .vxe-mob-landscape .swiperInfo.vxe-billboard {
    padding-top: 0 !important;
    /* clearance for the dot strip below the actions — tight: the 58px it
       used to reserve read as a dead band between the hero and the rail */
    padding-bottom: 34px !important;
  }
  /* ...and no extra margin under the frame; the rail's own heading spacing
     is the gap. The utility on the container (mb-4) is !important. */
  body[data-layout="cinematic"] .featured-swiper-container,
  body[data-layout="cinematic"] #new-editorpick {
    margin-bottom: 6px !important;
  }

  /* Rail headings keep the layout's heavier voice at a phone-appropriate size. */
  [data-layout="cinematic"] .swiperHolder .swiperTitle {
    font-size: 20px !important;
  }

  /* ======================================================================
     PROFILE & MORE.

     No reference screenshot for this screen — HBO's bottom bar has no More tab
     — so it is built to this layout's own language rather than copied: grouped
     rows separated by hairlines, not a stack of individually rounded chips.
     Eight identical floating chips is the generic tell Cinematic exists to
     avoid, and it also makes the list read as eight unrelated things rather
     than one set.
     ====================================================================== */
  body[data-layout="cinematic"] .vxm-more__title {
    letter-spacing: var(--vxl-tracking-tight);
    font-weight: 700;
  }
  /* One surface per group, with the rows flat inside it. */
  body[data-layout="cinematic"] .vxm-more__section {
    background: var(--vxl-surface-1);
    border-radius: var(--vxl-radius-md);
    overflow: hidden;
  }
  body[data-layout="cinematic"] .vxm-more__row {
    position: relative;
    min-height: 56px;
    margin: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    font-weight: 600;
  }
  /* Hairline between rows, never after the last one — an inset border on the
     row itself rather than a divider element, so it survives rows being added
     or reordered by config. */
  body[data-layout="cinematic"] .vxm-more__row + .vxm-more__row,
  body[data-layout="cinematic"] .vxm-more__section > details + details .vxm-more__row,
  body[data-layout="cinematic"] .vxm-more__section > a + a.vxm-more__row {
    box-shadow: inset 0 1px 0 0 var(--vxl-line);
  }
  /* A row that navigates should say so. Drawn as a rotated border box so it
     needs no icon and no markup change; the disclosure rows (<summary>) are
     excluded because they already carry their own caret. */
  body[data-layout="cinematic"] a.vxm-more__row::after {
    content: "";
    position: absolute;
    inset-inline-end: 16px;
    top: 50%;
    width: 7px;
    height: 7px;
    margin-top: -4px;
    border-top: 2px solid var(--vxl-ink-muted);
    border-inline-end: 2px solid var(--vxl-ink-muted);
    transform: rotate(45deg);
  }
  body[data-layout="cinematic"] a.vxm-more__row {
    padding-inline-end: 38px;
  }
  /* Centred while everything around it is on the gutter — the same mismatch the
     My List heading had. It was also a 21px tap target, half the 44px minimum,
     while being the only route to profile management; the padding is cancelled
     by an equal negative margin so the row does not grow. */
  body[data-layout="cinematic"] .vxm-more__manage {
    justify-content: flex-start !important;
    text-align: start !important;
    min-height: 44px;
    padding-block: 12px;
    margin-block: -12px;
  }

  /* ======================================================================
     SEARCH + MY LIST — poster walls.

     The reference's search screen is a big rounded field over rows of 2:3
     posters, three across, with NO captions: the poster carries the title.
     `_grid_layout` now passes an orientation down for this layout, so the rows
     render portrait; the rest is here.

     Dropping the caption is not just fidelity. At a third of the width almost
     every title overflows, and an overflowing title on a phone gets the shared
     marquee — so the alternative was a wall of nine independently scrolling
     text tickers. The title is still in the DOM and still read aloud; it is
     hidden from sight only where the artwork already states it.
     ====================================================================== */
  body[data-layout="cinematic"].page-search #searchPage .videoBlock p.title,
  body[data-layout="cinematic"].page-content_list #lists .videoBlock p.title {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  /* The card's action strip goes too, and this is a BUG FIX rather than styling:
     it carries a Play link straight to /watch/, it is a hover affordance with no
     hover on touch, and on a poster wall it sat over the artwork — so tapping a
     poster started playback instead of opening the title. The poster's own link
     (to the detail page) is now the only target on the card, which is what every
     other template does and what the reference does. */
  body[data-layout="cinematic"].page-search #searchPage .videoBlock .videoInfo,
  body[data-layout="cinematic"].page-content_list #lists .videoBlock .videoInfo {
    display: none !important;
  }
  /* Continue-watch progress. The card ships this as a sibling BELOW the artwork
     with its own margins, so on a poster wall it floated in the gap between
     rows — and its track is Bootstrap's near-white #e9ecef, which on a dark
     page reads as a bright rule rather than as the unwatched remainder. Seat it
     inside the poster, flush to the bottom, on a token track. */
  body[data-layout="cinematic"].page-search #searchPage .videoBlock,
  body[data-layout="cinematic"].page-content_list #lists .videoBlock {
    position: relative;
  }
  body[data-layout="cinematic"].page-search #searchPage .videoBlock .progress,
  body[data-layout="cinematic"].page-content_list #lists .videoBlock .progress {
    position: absolute;
    left: 8px;
    right: 8px;
    bottom: 8px;
    z-index: 3;
    width: auto !important;
    height: 3px !important;
    margin: 0 !important;
    border-radius: var(--vxl-radius-pill, 999px);
    background: var(--vxl-surface-3) !important;
    overflow: hidden;
  }
  /* Posters get the card radius and sit tight; the row gap does the spacing. */
  body[data-layout="cinematic"].page-search #searchPage .videoBlock .ratio,
  body[data-layout="cinematic"].page-content_list #lists .videoBlock .ratio {
    border-radius: var(--vxl-card-radius);
    overflow: hidden;
  }
  /* On a poster wall the artwork IS the card, so the card's own fill has
     nothing to do: it was painting the card colour (rgb 23,23,28) behind a
     poster on a page surfaced in rgb(11,11,16), which shows as a mismatched
     edge wherever the art does not reach. */
  body[data-layout="cinematic"].page-search #searchPage .videoBlock .card,
  body[data-layout="cinematic"].page-content_list #lists .videoBlock .card {
    background: transparent !important;
  }

  /* Search field: the shared mobile rule now derives its fill and ink from the
     tokens, so only the placeholder needs saying here. */
  body[data-layout="cinematic"].page-search #searchPage .searchBlock input::placeholder {
    color: var(--vxl-ink-muted);
  }
  /* Section headings match the rail headings elsewhere in the layout. */
  body[data-layout="cinematic"].page-search .vxm-search-suggest-head,
  body[data-layout="cinematic"].page-content_list #lists h2.h3,
  body[data-layout="cinematic"].page-content_list #lists > .insidePadding > h1,
  body[data-layout="cinematic"].page-content_list #lists > .insidePadding > h2 {
    font-size: 20px !important;
    font-weight: 700 !important;
    letter-spacing: -0.01em;
    /* Centred by the shared page style. Every other heading in this layout sits
       on the gutter, and a lone centred title over a left-aligned poster wall
       reads as a different page. */
    text-align: start !important;
  }

  /* ======================================================================
     DETAIL SCREEN — the HBO Max content page.

     Measured off the same reference (iPhone, 1284x2778, so ÷3 for points):
     a tall 3:4 portrait frame from y=0, the title sitting ON its lower edge,
     an inverted full-width CTA, a LEFT-aligned action row, and section tabs
     underlined in ink over a hairline rule.

     The shared mobile detail screen (mobile-app.css) is a 16:9 frame with the
     title below it and the actions spread edge to edge — that stays, for
     Classic and everything else. This is Cinematic's alone.
     ====================================================================== */

  /* ---- Frame: 3:4 portrait, full bleed -------------------------------- */
  body[data-layout="cinematic"].page-video_details .detailsThumb .ratio-16x9,
  body[data-layout="cinematic"].page-series_details .detailsThumb .ratio-16x9 {
    aspect-ratio: 3 / 4 !important;
    height: auto !important;
    border-radius: 0 !important;
  }
  /* The artwork COVERS the frame. A title with only landscape art renders
     that still at its natural 16:9 otherwise, leaving the lower two thirds
     of the portrait frame black. (The desktop block carries the same rule
     for its own frame.) */
  body[data-layout="cinematic"].page-video_details .detailsThumb .ratio-16x9 img,
  body[data-layout="cinematic"].page-video_details .detailsThumb .ratio-16x9 video,
  body[data-layout="cinematic"].page-series_details .detailsThumb .ratio-16x9 img,
  body[data-layout="cinematic"].page-series_details .detailsThumb .ratio-16x9 video {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  /* Scrim so the overlaid title is readable, and so the picture ends by
     dissolving into the page rather than on a hard seam. Mixed from the
     tenant's own body colour. */
  body[data-layout="cinematic"].page-video_details .detailsThumb .ratio-16x9::after,
  body[data-layout="cinematic"].page-series_details .detailsThumb .ratio-16x9::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(0deg,
      var(--vxl-scrim-solid) 0%,
      var(--vxl-scrim-solid) 8%,
      var(--vxl-scrim) 34%,
      transparent 66%);
  }

  /* ---- Title sits ON the lower edge of the frame ---------------------- */
  /* Only the title overlaps: the reference has the logo inside the picture and
     the meta row just below it. Pulling the whole info block up by roughly the
     title's own height lands both. */
  body[data-layout="cinematic"].page-video_details .detailsThumb .overlapData,
  body[data-layout="cinematic"].page-series_details .detailsThumb .overlapData {
    position: relative;
    z-index: 3;
    /* !important because the shared mobile detail rules zero this margin with
       !important of their own — their frame is 16:9 with the title below it. */
    margin-top: calc(-1 * var(--vxc-info-pull)) !important;
  }
  body[data-layout="cinematic"] .vxm-info__title {
    font-size: clamp(1.6rem, 7vw, 2.1rem) !important;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: var(--vxl-tracking-tight);
  }

  /* ---- Resume progress: inside the button, under the label ------------
     The reference draws how far you are through as a short rule beneath
     the CTA's own text, not as a separate bar above it. Nesting the bar in
     the label makes it exactly the label's width for free. Colours come
     from `currentColor`, so it reads correctly on the inverted primary
     (dark ink on the light slab) without hard-coding either. */
  /* Not scoped to the detail row: the homepage hero's Resume CTA draws the
     same rule, and both are `.vxc-resumeLabel` wrapping the label text. */
  body[data-layout="cinematic"] .vxc-resumeLabel {
    position: relative;
  }
  body[data-layout="cinematic"] .vxc-resumeBar {
    position: absolute;
    left: 0;
    right: 0;
    bottom: -7px;
    height: 3px;
    border-radius: var(--vxl-radius-pill, 999px);
    background: color-mix(in srgb, currentColor 26%, transparent);
    overflow: hidden;
  }
  body[data-layout="cinematic"] .vxc-resumeBar__fill {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: currentColor;
  }
  /* The in-button progress bar is the shared component now: the templates
     emit .vxl-btn__progress (components.css) as a direct child of the CTA —
     detail pages via .vxl-btn--progress, the hero via the host rule below.
     The whole optical-nudge/bar-lift machinery that aligned the old
     under-label rule is gone with the rule itself; nothing hangs off the
     label anymore. The base .vxc-resumeBar rules above STAY: the card
     overflow menu (cwMenuMarkup in video.html/series.html) still draws its
     miniature under-label bar inside menu items, which is that surface's
     own design. */
  body[data-layout="cinematic"] .vxe-billboard .sldieBtns .btn {
    position: relative;
    overflow: hidden; /* the bottom-edge bar clips to the pill radius */
  }

  /* ...so the standalone bar above the CTA has nothing left to say. */
  body[data-layout="cinematic"].page-video_details .vxm-info__progressRow,
  body[data-layout="cinematic"].page-series_details .vxm-info__progressRow {
    display: none !important;
  }

  /* ---- Phone title: the LOGO when the item has one --------------------
     mobile-app.css hides .videoLogo on the phone detail screen in favour of
     the info head's text <h1>. Cinematic shows the logo art, desktop parity.
     Only the PHONE copy is re-shown (its column carries .d-sm-none, so at
     ≥576px nothing doubles up with the desktop copy), and only its IMG: the
     block's own text fallback stays hidden so a title with no logo shows one
     h1 (the info head's), not two. A logo that 404s flips logoFailed, the
     img leaves the DOM, and :has() puts the text title straight back. */
  /* The column itself is hidden by modal.css (.vxm .overlapData
     .vxm-heroCol.d-lg-none) — re-shown for PHONES only: above 576px this
     heavier rule would also beat the column's own d-sm-none utility and
     double the desktop copy, so it is pinned under the breakpoint. */
  @media (max-width: 575.98px) {
    body[data-layout="cinematic"].page-video_details .vxm .overlapData .vxm-heroCol.d-sm-none,
    body[data-layout="cinematic"].page-series_details .vxm .overlapData .vxm-heroCol.d-sm-none {
      display: block !important;
      padding: 0 !important;
    }
  }
  body[data-layout="cinematic"].page-video_details .vxm-heroCol.d-sm-none .videoLogo,
  body[data-layout="cinematic"].page-series_details .vxm-heroCol.d-sm-none .videoLogo {
    display: block !important;
    margin: 0 0 10px !important;
  }
  body[data-layout="cinematic"].page-video_details .vxm-heroCol.d-sm-none .videoLogo h1,
  body[data-layout="cinematic"].page-video_details .vxm-heroCol.d-sm-none .videoLogo h2,
  body[data-layout="cinematic"].page-series_details .vxm-heroCol.d-sm-none .videoLogo h1,
  body[data-layout="cinematic"].page-series_details .vxm-heroCol.d-sm-none .videoLogo h2 {
    display: none !important;
  }
  body[data-layout="cinematic"].page-video_details .vxm-heroCol.d-sm-none .videoLogo img,
  body[data-layout="cinematic"].page-series_details .vxm-heroCol.d-sm-none .videoLogo img {
    max-width: min(64vw, 280px);
    max-height: 110px;
  }
  body[data-layout="cinematic"].page-video_details .overlapData .row:has(.vxm-heroCol.d-sm-none .videoLogo img) .vxm-info__title,
  body[data-layout="cinematic"].page-series_details .overlapData .row:has(.vxm-heroCol.d-sm-none .videoLogo img) .vxm-info__title {
    display: none !important;
  }

  /* ---- CTA: tenant primary, every width -------------------------------- */
  /* OWNER DECISION (26.314.x): the detail CTA wears the tenant's action
     colour, same as the hero — the HBO reference's inverted light-on-dark
     slab is retired. Stated here with page weight because the legacy cascade
     (mobile-app page rules, old chip paints) still fights the bare component
     tier at some widths; the values are the .vxl-btn primary tier's own.
     Trailer and "Play from beginning" re-paint themselves right below. */
  body[data-layout="cinematic"].page-video_details .detailsIcon .playResumeBtn,
  body[data-layout="cinematic"].page-series_details .detailsIcon .playResumeBtn {
    /* through the curated button chain, same as the component tier — this
       guard must not cut the customizer's Primary Button controls out of
       cinematic pages (#5350 items 15/16) */
    background: var(--vod-btn-primary-bg, var(--vxl-accent)) !important;
    border: 0 !important;
    color: var(--vod-btn-primary-text, var(--vxl-on-accent)) !important;
    border-radius: var(--vxl-radius-pill, 999px) !important;
  }
  body[data-layout="cinematic"].page-video_details .detailsIcon .playResumeBtn:hover,
  body[data-layout="cinematic"].page-series_details .detailsIcon .playResumeBtn:hover {
    /* the guard's !important would otherwise freeze the tier's hover */
    background: var(--vod-btn-primary-hover-bg, var(--vxl-accent-hover)) !important;
  }
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn .vxm-ico,
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn i {
    color: inherit !important;
  }
  /* The secondary CTA (Play from beginning) keeps a surface fill so the pair
     still reads as primary + secondary once the primary is inverted.

     It needs the same page-class prefix as the rule above: the secondary button
     IS a `.playResumeBtn`, so a shorter selector loses the tie and it inverted
     too — two identical light slabs stacked on top of each other.

     Trailer used to be listed here too, back when it was a filled chip beside
     Play. It is a quiet text link now (see the trailer rule further down), and
     this rule was still winning that argument — it carries one more class
     (`.page-series_details`), so it outranked the newer rule's
     `background: transparent !important` and kept painting an 8% slab with
     square corners in the middle of a row of circles. Removed from the list
     rather than out-specified further down: one rule, one owner. */
  body[data-layout="cinematic"].page-video_details .detailsIcon .playResumeBtn.vxm-info__cta--secondary,
  body[data-layout="cinematic"].page-series_details .detailsIcon .playResumeBtn.vxm-info__cta--secondary {
    background: var(--vxl-surface-2) !important;
    color: var(--vxl-ink) !important;
  }
  /* Only the PRIMARY CTA inverts. Trailer is also a `.playResumeBtn`, so it was
     inverting too — and a base rule paints its label `rgba(255,255,255,.92)`,
     which on an inverted (near-white) button is white on white: the button
     rendered as an empty white slab. The label colour has to be restated, not
     just the fill. */
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] > span,
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] .vxm-ico,
  body[data-layout="cinematic"] .detailsIcon .vxm-info__cta--secondary > span,
  body[data-layout="cinematic"] .detailsIcon .vxm-info__cta--secondary .vxm-ico {
    color: var(--vxl-ink) !important;
  }
  /* ...and the trailer's FILL has to be neutralised with the same page-class
     weight as the inverted-CTA rule above, or the white slab wins and the
     button renders empty (white label on white). On phones it is a quiet
     inline chip beside the icons; desktop restyles it in its own block. */
  body[data-layout="cinematic"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"],
  body[data-layout="cinematic"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] {
    flex: 0 0 auto !important;
    width: auto !important;
    padding: 0 12px !important;
    background: transparent !important;
    border: 0 !important;
    color: var(--vxl-ink) !important;
  }

  /* The trailer mute disc is pinned with `calc(56.25vw - 52px)` — the height of
     a 16:9 frame — so on this 3:4 frame it sat ~340px high, on top of the Play
     button.

     It cannot simply be re-pointed at the 3:4 height either: the disc lives
     inside `.overlapData`, and making that `position: relative` (for the
     z-index above) turned it into the disc's containing block. So the offset is
     measured from there — the block is pulled up by exactly one
     `--vxc-info-pull`, so `pull - 52` puts the disc 52px above the artwork's
     bottom edge wherever that is. Both sides read the same variable, so
     changing the overlap cannot silently move the disc again. */
  body[data-layout="cinematic"].page-video_details .detailsIcon .playPausePage,
  body[data-layout="cinematic"].page-video_details .detailsIcon .playPauseModal,
  body[data-layout="cinematic"].page-series_details .detailsIcon .iframePlayPauseSeries {
    top: calc(var(--vxc-info-pull) - 52px);
  }

  /* ---- Actions: left-aligned, not spread ------------------------------ */
  /* Four columns pinned to both edges reads as a toolbar; the reference groups
     them at the start, which reads as a set belonging to the title above. */
  body[data-layout="cinematic"].page-video_details .detailsIcon,
  body[data-layout="cinematic"].page-series_details .detailsIcon {
    justify-content: flex-start !important;
    column-gap: 34px !important;
  }
  /* On PHONES the row distributes instead: with fixed gaps, a title without
     a trailer left its four icons clustered at the start and a dead band at
     the right edge. space-between keeps the row balanced at any count —
     four icons or five. (Desktop replaces this row with its own grid.) */
  @media (max-width: 991.98px) {
    body[data-layout="cinematic"].page-video_details .detailsIcon,
    body[data-layout="cinematic"].page-series_details .detailsIcon {
      justify-content: space-between !important;
      column-gap: 0 !important;
    }
  }
  body[data-layout="cinematic"] .detailsIcon .vxm-actCol {
    flex: 0 0 auto !important;
  }
  /* ...but the CTAs still span the full width — they are not part of that
     group. ⚠ this is the PHONE design (stacked full-width CTAs) and is
     scoped to phones. History: it used to be bare-scoped in this @media all
     section and leaked into the desktop info modal (stacked slabs — owner:
     "buttons too large"); the first fix rescoped it to `.vxm-page`, which
     accidentally OUT-SPECIFIED the desktop page rule below
     (`.page-video_details … flex: 0 0 auto`, min-width 992) that had always
     kept desktop-page CTAs compact — turning the routed pages into slabs.
     A max-width guard restores the original design everywhere: phones get
     the slab (page and sheet alike), desktop pages and the desktop modal
     keep the compact row. */
  @media (max-width: 991.98px) {
    body[data-layout="cinematic"] .detailsIcon .playResumeBtn,
    body[data-layout="cinematic"] .detailsIcon .vxm-info__body {
      flex: 1 1 100% !important;
    }
  }
  /* Reference order is CTA → actions → synopsis. The markup emits the synopsis
     before the action columns, so reorder visually rather than move it in the
     template — the DOM order is the sensible reading order for a screen reader
     (what it is, then what you can do about it) and worth keeping. */
  /* One explicit sequence for the whole row. Ordering `.vxr` is useless — the
     shared rules give it `display: contents`, so it has no box and the flex
     items are really its hoisted like/dislike buttons, which carry order 4 and
     5 of their own and therefore landed AFTER the synopsis. They have to be
     numbered here alongside everything else.

     The like/dislike pair is addressed by position, not by class, because the
     pop's DOM order is dislike-then-like while the intended reading order is
     the reverse — the same language-agnostic trick the shared rules use. */
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn { order: 1; }
  body[data-layout="cinematic"] .detailsIcon .vxm-actCol--list { order: 2; }
  body[data-layout="cinematic"] .detailsIcon .vxr__pop .vxr__optBtn:nth-child(2) { order: 3; }
  body[data-layout="cinematic"] .detailsIcon .vxr__pop .vxr__optBtn:nth-child(1) { order: 4; }
  body[data-layout="cinematic"] .detailsIcon .vxm-actCol--share { order: 5; }
  body[data-layout="cinematic"] .detailsIcon .vxm-info__body {
    order: 6;
    margin-block: 20px 0 !important;
  }
  /* `.copyDiv` is the clipboard SOURCE behind the Share button, not a control —
     but it is a flex item, and it was claiming a full 321px row of blank space
     between the actions and the synopsis. Kept in the DOM (clipboard.js reads
     from it) and in flow, just collapsed and moved to the end. */
  body[data-layout="cinematic"] .detailsIcon .copyDiv {
    order: 7;
    flex: 0 0 100% !important;
    height: 0 !important;
    margin: 0 !important;
    overflow: hidden;
  }

  /* ---- Section tabs: ink underline over a hairline --------------------- */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > h2.h5,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > h2.h5 {
    border-bottom: 3px solid var(--vxl-ink) !important;
    padding-bottom: 10px !important;
  }
  /* The rule runs the full width behind the active tab, as a tab strip should —
     without it the underline floats with nothing to sit on. */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > h2.h5::after,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > h2.h5::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -3px;
    height: 1px;
    background: var(--vxl-line);
    z-index: -1;
  }
  body[data-layout="cinematic"] .videoDetails > .insidePadding > h2.h5 {
    position: relative;
  }

  /* ---- Episodes: heading over a full-width season field --------------- */
  /* The markup puts "Episodes" and the season picker in two columns of one
     row. The reference stacks them — an underlined section heading, then the
     season as a full-width field — which also gives the picker a 46px target
     instead of the 32px chip it was. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-epList > [class*="col"] {
    flex: 0 0 100% !important;
    max-width: 100% !important;
  }
  /* Mirrors the base rule's shape exactly, plus the layout attribute — the base
     is `body.page-series_details .vxm-epList > .col:first-child > h2`, and
     `:first-child` counts as a class, so a shorter selector here lost and the
     underline stayed the accent red instead of ink. */
  body[data-layout="cinematic"].page-series_details .vxm-epList > .col:first-child > h2,
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-epList h2.h4 {
    display: inline-block;
    margin-bottom: 14px !important;
    padding-bottom: 10px;
    border-bottom: 3px solid var(--vxl-ink) !important;
    font-size: 20px !important;
    font-weight: 700 !important;
  }
  /* ---- Episode rows: thumbnail left, text beside it --------------------
     The Netflix row: number, a 16:9 still with a play affordance, then title
     (duration right-aligned) with the synopsis directly under it — all beside
     the still, not below it. The first cut ran the synopsis full-width under
     the whole row, which with a short description left the right two-thirds
     of every row empty and made the list read as broken. The markup is three
     levels of Bootstrap columns wrapping a card that stacks vertically, so
     the layers in between are flattened with `display: contents` and the
     whole row is laid out as one grid. Nothing moves in the DOM — reading
     order is untouched, which matters because that order (number, title,
     synopsis) is the sensible one to hear read aloud. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep {
    display: grid;
    grid-template-columns: 18px 148px minmax(0, 1fr);
    grid-template-areas:
      "num thumb head"
      "num thumb desc"
      "rule rule rule";
    /* `1fr` pins the synopsis directly under the title row: with two auto
       rows, the still (which spans both) donates its spare height to the
       FIRST track too, and the synopsis floated mid-row. */
    grid-template-rows: auto 1fr auto;
    column-gap: 12px;
    row-gap: 6px;
    align-items: start;
    padding: 0 !important;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep > .row,
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep > .row > [class*="col-"],
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu,
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu > div,
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu > div > a {
    display: contents !important;
  }
  /* ...except the column holding the episode number, which is a real cell —
     it spans both text rows now, centred on the still's height. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep > .row > .col-1 {
    display: block !important;
    grid-area: num;
    align-self: center;
    padding: 0 !important;
    text-align: start !important;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .seriesIndex {
    font-size: 18px;
    font-weight: 600;
    color: var(--vxl-ink-muted);
    line-height: 1;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu > a.img {
    grid-area: thumb;
    display: block !important;
    width: 100%;
    margin: 0 !important;
    border-radius: var(--vxl-radius-sm, 4px);
    overflow: hidden;
  }
  /* A still with no affordance reads as decoration. The reference puts a play
     triangle on it; drawn in CSS so it needs no icon and no markup change. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu > a.img::after {
    content: "";
    position: absolute;
    left: 10px;
    bottom: 10px;
    z-index: 3;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 7px 0 7px 12px;
    border-color: transparent transparent transparent var(--vxl-ink);
    filter: drop-shadow(0 1px 2px var(--vxl-scrim));
  }
  /* The card's hover play chip would be a SECOND play affordance on top of the
     triangle above — and it ships in the accent colour, which is exactly the
     shout this layout avoids. One affordance is enough. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu .playBtn {
    display: none !important;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu > div > div:first-child {
    grid-area: head;
    display: flex !important;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin: 0 !important;
    padding: 0 !important;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu h2 {
    font-size: 15px !important;
    font-weight: 700 !important;
    line-height: 1.3;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu .vid-description {
    grid-area: desc;
    margin: 0 !important;
    font-size: 13px;
    line-height: 1.45;
    color: var(--vxl-ink-muted) !important;
  }
  /* The divider is the row separator, so it spans everything and uses the line
     token rather than Bootstrap's default rule colour. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep > div:last-child {
    grid-area: rule;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep hr {
    margin: 4px 0 14px !important;
    border: 0;
    border-top: 1px solid var(--vxl-line);
  }

  body[data-layout="cinematic"] .vxm.vxm-page .vxm-epList select.form-select {
    width: 100% !important;
    height: 46px;
    padding: 0 16px !important;
    border: 0 !important;
    border-radius: 6px !important;
    background-color: var(--vxl-surface-2) !important;
    color: var(--vxl-ink) !important;
    font-size: 15px;
    font-weight: 600;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-layout="cinematic"] .videoBlock.vxc {
    transition: none;
  }
  /* No transform, so elevation alone has to carry the hover state. */
  [data-layout="cinematic"] .videoBlock.vxc:hover,
  [data-layout="cinematic"] .videoBlock.vxc.vxc-open {
    transform: none !important;
    box-shadow: var(--vxl-shadow-3);
  }
}

/* --------------------------------------------------------------------------
   Billboard → first rail: give it air.

   The rail was starting 48px BEFORE the billboard ended and its heading sat
   26px under the CTA row, so the hero and the first list read as one crowded
   block. A billboard needs the pause after it — that gap is what makes it a
   billboard rather than the top of a list.
   -------------------------------------------------------------------------- */
@media (min-width: 992px) {
  body[data-layout="cinematic"].page-home #new-editorpick {
    margin-bottom: 64px !important;
  }
  /* The first rail carries `margin-top: -72px` — the Netflix habit of riding the
     rails up over the billboard so the next row peeks. Cinematic wants the
     opposite: the billboard finishes, then the page begins. Neutralised and
     given real space instead. */
  /* The element after the billboard carries `margin-top: -5vw !important` from
     editorpick.css — the Netflix habit of riding the first rail up over the
     hero so the next row peeks. Cinematic wants the opposite: the billboard
     finishes, then the page begins. Mirrors that selector exactly (it is an ID
     rule, so nothing shorter can win) and turns the pull into space. */
  body[data-layout="cinematic"] #items-list .featureSlider + div {
    margin-top: 32px !important;
  }
}

/* ==========================================================================
   DETAIL PAGE — DESKTOP, the HBO Max pattern.

   The first attempt bled `.detailsThumb` itself, which also moved the info
   block nested inside it — the logo and CTA row lost the page gutter and
   clipped off the left edge. The reference does not do that: the ARTWORK runs
   edge to edge while the text stays on the page's own left margin.

   `.ratio` and `.overlapData` are siblings, so only the artwork is bled and the
   info block is left exactly where the page already puts it, then pulled up
   onto the picture. Decoupled, as it should have been the first time.
   ========================================================================== */
@media (min-width: 992px) {
  /* Three ancestors carry `overflow: hidden` and all three are the width of the
     page container, so a bled child was laid out full-width and then simply
     clipped back to the container — the artwork measured 1440 wide while only
     the middle 1110 of it painted. They have to be opened for the bleed to be
     visible at all; the artwork is the only bled child, so nothing else spills. */
  body[data-layout="cinematic"].page-video_details .detailsThumb,
  body[data-layout="cinematic"].page-series_details .detailsThumb,
  body[data-layout="cinematic"] .card.videoDetails,
  body[data-layout="cinematic"] .videoDetails.detail {
    overflow: visible !important;
  }

  /* The artwork runs BEHIND the header, as the editors-pick billboard does on
     the homepage — the header is transparent over this layout, so a bar of page
     background above the picture is just a gap. `.contentHolder` carries
     Bootstrap's `pt-5 mt-5`, which is exactly the 96px the artwork was sitting
     below; the hero is the only thing at the top of this page, so zeroing it
     here costs nothing else. */
  body[data-layout="cinematic"].page-video_details .contentHolder,
  body[data-layout="cinematic"].page-series_details .contentHolder {
    padding-top: 0 !important;
    margin-top: 0 !important;
  }

  body[data-layout="cinematic"].page-video_details .detailsThumb .ratio-16x9,
  body[data-layout="cinematic"].page-series_details .detailsThumb .ratio-16x9 {
    margin-inline: calc(50% - 50vw);
    width: 100vw;
    /* Fills the viewport the way the editors-pick billboard does, rather than
       being a 16:9 band that happens to be wide. A fixed height instead of an
       aspect-ratio means the frame is the same commanding shape on every
       screen and never letterboxes; `object-fit: cover` on the image does the
       cropping. 86vh matches the home hero — the two should feel like the same
       layout, because they are. */
    height: 86vh !important;
    min-height: 520px;
    /* the ratio classes size with a padding-top hack; aspect-ratio alone does
       not defeat it */
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-radius: 0 !important;
  }
  body[data-layout="cinematic"] .detailsThumb .ratio-16x9 img,
  body[data-layout="cinematic"] .detailsThumb .ratio-16x9 video {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  /* Left-weighted wash for the text, plus a bottom dissolve into the page. */
  body[data-layout="cinematic"].page-video_details .detailsThumb .ratio-16x9::after,
  body[data-layout="cinematic"].page-series_details .detailsThumb .ratio-16x9::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background:
      linear-gradient(0deg, var(--vxl-scrim-solid) 0%, var(--vxl-scrim) 34%, transparent 68%),
      linear-gradient(90deg, var(--vxl-scrim) 0%, var(--vxl-scrim-weak) 34%, transparent 60%);
  }

  /* Info block: untouched horizontally — it keeps the page gutter — and
     lifted well onto the artwork, the reference's position: the logo sits
     around the vertical midpoint of the first screen, not on the fold.

     ONE number owns the lift. The ambient-trailer discs are positioned
     against this same block and measure from its top (see their rule), so
     they read the same variable — change the pull and they follow. The
     original -190 was tuned when the block held only title + CTA + icons;
     the hero now carries the meta, synopsis and genres too, so the taller
     block earns a deeper pull without the rows colliding. */
  body[data-layout="cinematic"].page-video_details,
  body[data-layout="cinematic"].page-series_details {
    --vxc-desktop-pull: 330px;
  }
  body[data-layout="cinematic"].page-video_details .detailsThumb .overlapData,
  body[data-layout="cinematic"].page-series_details .detailsThumb .overlapData {
    position: relative;
    z-index: 3;
    margin-top: calc(-1 * var(--vxc-desktop-pull)) !important;
  }
  /* The hero column carries the reference's width: the description runs to
     roughly half the screen (905px at 1920), not a narrow 56ch strip. The
     CTA and icon rows size themselves, so only the text gets wider. */
  body[data-layout="cinematic"] .detailsThumb .overlapData .vxm-heroCol {
    max-width: min(48vw, 920px);
  }
  body[data-layout="cinematic"] .detailsIcon .vxm-info__body {
    max-width: 56ch;
  }
  /* Title logo at the reference's presence — about a third of the screen.
     width (not just max-width) so small logo assets scale up to it too;
     contain keeps the art's own aspect. */
  body[data-layout="cinematic"].page-video_details .detailsThumb .overlapData .videoLogo img,
  body[data-layout="cinematic"].page-series_details .detailsThumb .overlapData .videoLogo img {
    width: min(32vw, 620px);
    max-width: min(32vw, 620px) !important;
    height: auto;
    max-height: 210px;
    object-fit: contain;
    object-position: left bottom;
  }
  body[data-layout="cinematic"] .vxm-info__title,
  body[data-layout="cinematic"] .videoLogo h1 {
    font-size: clamp(2rem, 3.4vw, 3.2rem) !important;
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: var(--vxl-tracking-tight);
  }

  /* ---- Actions row: ARRANGEMENT ONLY -----------------------------------
     The buttons' paint and geometry moved to the shared component tier
     (components.css): the templates co-class the primary CTA as
     .vxl-btn--lg (tenant primary via the legacy adapter), Trailer as
     .vxl-btn--ghost --lg, "Play from beginning" as --secondary --lg, and
     every icon as .vxl-btn--icon. What remains here is what makes the
     cinematic ROW cinematic: flex behaviour, ordering, group separation,
     and guards against legacy rules that hid labels or sprinkled margins. */
  body[data-layout="cinematic"].page-video_details .detailsIcon .playResumeBtn,
  body[data-layout="cinematic"].page-series_details .detailsIcon .playResumeBtn {
    /* `flex: 0 0 auto` is load-bearing: the mobile rules make this CTA
       `flex: 1 1 100%` so it spans the phone's width, and that leaked to
       desktop — the button stretched across the whole row. */
    flex: 0 0 auto !important;
    width: auto;
    min-height: 0;
    /* a step more air after the CTA than between the icons; when Trailer
       follows, its own 20px margin takes over the group separation */
    margin: 0 8px 0 0 !important;
  }
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn > span {
    display: inline !important;
    color: inherit !important;
  }
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn .vxm-ico,
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn i {
    color: inherit !important;
    margin: 0 !important; /* templates carry mr utilities on glyphs */
  }
  /* Trailer sits second, with the CTA-pair-to-icons separation. Its ghost
     paint is .vxl-btn--ghost --lg now — one pill, one measure with Play. */
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] {
    order: 0;
    margin-right: 20px !important;
  }
  /* Icon strip: geometry+paint are .vxl-btn--icon (hardened against the
     legacy disc rules in components.css). The glyph WRAPPER divs between the
     button and the svg are this markup's quirk, so their sizing stays here;
     no `display` on them — the components toggle two glyphs via inline
     style, and an !important display would print both. */
  body[data-layout="cinematic"] .detailsIcon .rundedBtn > *,
  body[data-layout="cinematic"] .detailsIcon .boxBtn > * {
    width: 24px !important;
    height: 24px !important;
    margin: 0 !important;
    color: inherit !important;
  }
  body[data-layout="cinematic"] .detailsIcon .rundedBtn svg,
  body[data-layout="cinematic"] .detailsIcon .boxBtn svg {
    width: 24px !important;
    height: 24px !important;
    stroke-width: 1.75;
  }

  /* ---- Ambient-trailer controls: pinned to the artwork's corner --------
     Mute and play/pause act on the artwork behind the text (the background
     trailer), not on the title — mixed into the action strip they read as two
     more mystery icons, and the toggle's play glyph collided with Play itself.
     They keep a thin ring (they are player controls, not actions) and sit in
     the hero's lower-right corner, where the reference pins its mute disc.
     Selector carries one class more than the bare `.rundedBtn` rule above, so
     the ring wins the tie. */
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.playPausePage,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.playPauseModal,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.iframePlayPauseSeries,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.trailerPlayPauseBtn {
    order: 11;
    border: 0 !important;
    color: var(--vxl-ink-muted) !important;
  }
  /* Corner pinning, DETAIL PAGES only — the intended containing block is
     `.overlapData` (`.insidePadding` is `position: relative`), whose padding
     is the same `var(--vxl-gutter)` the inset resolves against, so the pair
     lands on the info block's opposite gutter. Bootstrap makes every column
     `position: relative`, which would capture the discs inside the 56ch hero
     column instead — the column is made static here; nothing inside it
     anchors to it on desktop (the reactions pop anchors to its own trigger).
     `top: auto` matters too: an older rule aims these discs with a `top:`
     calc, and with the height pinned a set `top` beats `bottom`. */
  body[data-layout="cinematic"].page-video_details .detailsThumb .overlapData .vxm-heroCol,
  body[data-layout="cinematic"].page-series_details .detailsThumb .overlapData .vxm-heroCol {
    position: static;
  }
  body[data-layout="cinematic"].page-video_details .detailsIcon .rundedBtn.playPausePage,
  body[data-layout="cinematic"].page-series_details .detailsIcon .rundedBtn.iframePlayPauseSeries,
  body[data-layout="cinematic"].page-video_details .detailsIcon .rundedBtn.trailerPlayPauseBtn,
  body[data-layout="cinematic"].page-series_details .detailsIcon .rundedBtn.trailerPlayPauseBtn {
    position: absolute;
    top: auto;
    bottom: 34px;
    z-index: 4;
  }
  body[data-layout="cinematic"].page-video_details .detailsIcon .rundedBtn.trailerPlayPauseBtn,
  body[data-layout="cinematic"].page-series_details .detailsIcon .rundedBtn.trailerPlayPauseBtn {
    inset-inline-end: var(--vxl-gutter, 3%);
  }
  body[data-layout="cinematic"].page-video_details .detailsIcon .rundedBtn.playPausePage,
  body[data-layout="cinematic"].page-series_details .detailsIcon .rundedBtn.iframePlayPauseSeries {
    inset-inline-end: calc(var(--vxl-gutter, 3%) + 56px);
  }
  /* The info MODAL can open on top of a detail page (related titles), and the
     series modal reuses the very same classes — inside a modal the pair goes
     back into the row, hugging its right edge. The margin has to be restated:
     modal.css pins it with a weaker selector than the bare `.rundedBtn`
     margin reset above. */
  body[data-layout="cinematic"] .modal .detailsIcon .rundedBtn.playPausePage,
  body[data-layout="cinematic"] .modal .detailsIcon .rundedBtn.iframePlayPauseSeries,
  body[data-layout="cinematic"] .modal .detailsIcon .rundedBtn.trailerPlayPauseBtn {
    position: static;
  }
  body[data-layout="cinematic"] .modal .detailsIcon .rundedBtn.playPauseModal,
  body[data-layout="cinematic"] .modal .detailsIcon .rundedBtn.iframePlayPauseSeries {
    margin-left: auto !important;
  }
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.playPausePage:hover,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.playPauseModal:hover,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.iframePlayPauseSeries:hover,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.trailerPlayPauseBtn:hover {
    border: 0 !important;
    background: transparent !important;
    color: var(--vxl-ink) !important;
  }
  /* their glyphs stay a step smaller than the social icons' */
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.playPausePage svg,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.playPauseModal svg,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.iframePlayPauseSeries svg,
  body[data-layout="cinematic"] .detailsIcon .rundedBtn.trailerPlayPauseBtn svg {
    width: 20px !important;
    height: 20px !important;
  }

  /* The bare action icons already read as a set; drop their captions. */
  body[data-layout="cinematic"] .detailsIcon .vxm-actLabel {
    display: none !important;
  }
  /* 12px is what "close to each other" means once the rings are gone; the
     !important is needed because the older detail-screen rule pins 34px with
     one of its own. */
  body[data-layout="cinematic"].page-video_details .detailsIcon,
  body[data-layout="cinematic"].page-series_details .detailsIcon {
    align-items: center;
    column-gap: 12px !important;
  }
  /* One explicit sequence: Play, Trailer, then My List / rate / share, then
     the ambient controls (11/12 above). The two detail templates emit their
     controls in different orders, and the reactions pop's DOM order is
     dislike-then-like, so every slot is numbered rather than left to DOM
     order. The `.vxm-actCol` wrappers are `display: contents` on desktop, so
     the order has to land on the hoisted child, not the wrapper. */
  body[data-layout="cinematic"] .detailsIcon .playResumeBtn {
    order: -1;
  }
  body[data-layout="cinematic"] .detailsIcon .vxm-actCol--list > * {
    order: 1;
  }
  /* The reactions widget's flex item is its trigger — the option buttons live
     inside the pop, which lays itself out. */
  body[data-layout="cinematic"] .detailsIcon .vxr__trigger,
  body[data-layout="cinematic"] .detailsIcon .vxr {
    order: 2;
  }
  body[data-layout="cinematic"] .detailsIcon .vxr__pop .vxr__optBtn:nth-child(2) {
    order: 2;
  }
  body[data-layout="cinematic"] .detailsIcon .vxr__pop .vxr__optBtn:nth-child(1) {
    order: 3;
  }
  body[data-layout="cinematic"] .detailsIcon .vxm-actCol--share > .copyButton {
    order: 4;
  }
  /* The clipboard source div is a flex item ordered mid-row by an older rule;
     anything with `flex-basis: 100%` placed before order 11 would break the
     line and dump the ambient controls onto their own row. Send it last. */
  body[data-layout="cinematic"] .detailsIcon .copyDiv {
    order: 20;
  }
  /* The synopsis on the series page runs the full page width; the movie page
     caps it. Same measure for both — a line that long is hard to track back to
     its start. */
  body[data-layout="cinematic"] .detailsThumb .overlapData p {
    max-width: 62ch;
  }

  /* Meta reads as one spaced caption line, as the reference's does. */
  body[data-layout="cinematic"] .vxm-info__meta,
  body[data-layout="cinematic"] .detailsThumb .overlapData .vxm-meta {
    gap: 18px;
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--vxl-ink-muted);
  }

  /* "12m remaining" beside the bar. The bar is a 3px line; on its own it shows
     a proportion but never answers the only question worth asking, which is how
     much is left. */
  body[data-layout="cinematic"] .detailsThumb .overlapData .vxm-info__progressRow {
    display: flex;
    align-items: center;
    gap: 14px;
    max-width: 420px;
    margin: 6px 0 18px !important;
  }
  body[data-layout="cinematic"] .detailsThumb .overlapData .vxm-info__progressRow .progress {
    flex: 1 1 0;
    margin: 0 !important;
  }
  body[data-layout="cinematic"] .vxm-info__remaining {
    flex: 0 0 auto;
    font-size: 13px;
    color: var(--vxl-ink-muted);
    white-space: nowrap;
  }

  /* ---- Everything BELOW the hero -------------------------------------
     The page is built as a CARD: `.videoDetails` and `.card.videoDetails` both
     paint the card colour across a 1110px column. That was invisible while the
     artwork sat inside it — bleeding the artwork out exposed the panel below as
     a grey slab with hard edges, which is why the lower half looked unfinished
     next to a full-bleed top half. The page is the surface here, as it is in
     the reference; the panel has nothing left to do. */
  body[data-layout="cinematic"] .videoDetails.detail,
  body[data-layout="cinematic"] .card.videoDetails,
  body[data-layout="cinematic"] .detailsContainer {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
  }

  /* No close control on a PAGE. The ✕ belongs to the modal this template is
     shared with; arrived at by navigation there is nothing to close, and the
     reference has none — the browser's back is the way out. */
  body[data-layout="cinematic"].page-video_details .series-detail-close,
  body[data-layout="cinematic"].page-series_details .series-detail-close {
    display: none !important;
  }

  /* Continue-watch bar: it was a stray 215px rule floating under the logo.
     Give it the text column's width, a token track, and a place in the stack —
     directly under the title, where it reads as "you are 40% through this". */
  body[data-layout="cinematic"] .detailsThumb .overlapData .progress {
    width: 100% !important;
    max-width: 420px;
    height: 3px !important;
    margin: 6px 0 18px !important;
    border-radius: var(--vxl-radius-pill, 999px);
    background: var(--vxl-surface-3) !important;
    overflow: hidden;
  }

  /* ---- Related row: even, compact cards ------------------------------
     The columns came out 696 / 348 / 348 — a Bootstrap grid meant for a
     different breakpoint — so the first card was double width and the row read
     as a mistake. One even grid instead, sized like the reference's Extras row,
     and the cards lose the date and synopsis: at this size they are a wall of
     grey text under a picture that already says what the thing is. */
  /* `:has(.cardBg)` matters — the related row is not the only direct-child
     `.row` here. Without it this also caught the meta/synopsis row and turned
     its `col-lg-8` into a 210px grid cell, so the description wrapped at four
     words while two thirds of the page sat empty. Only the row that actually
     holds cards becomes a grid. */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.cardBg),
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.cardBg) {
    display: grid !important;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 18px;
    margin-inline: 0 !important;
  }
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.cardBg) > [class*="col-"],
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.cardBg) > [class*="col-"] {
    width: auto !important;
    max-width: none !important;
    flex: none !important;
    padding: 0 !important;
    margin: 0 !important;
  }
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg {
    background: transparent !important;
  }
  /* Corner radius, matched to the homepage rails. A rail card is rounded by
     `.card.no-border` — 4px with `overflow: hidden` — NOT by `.ratio`, which
     is why reading `.ratio` alone suggested the rails were square. The wall
     has no `.card` layer, so the poster frame carries the same 4px and does
     the clipping; every other layer is zeroed, because with four stacked
     wrappers (card, anchor, frame, image) any one left rounded shows through
     as a mismatched corner. */
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg,
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg > a,
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg .ratio > div,
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg .ratio img {
    border-radius: 0 !important;
  }
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg .ratio {
    border-radius: 4px !important;
    overflow: hidden;
  }
  /* keep the title, drop the date badge and the synopsis */
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg p,
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg .badge-secondary,
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg .vid-description {
    display: none !important;
  }
  body[data-layout="cinematic"] .videoDetails > .insidePadding .cardBg h2 {
    margin-top: 10px !important;
    font-size: 14px !important;
    font-weight: 600 !important;
  }

  /* ---- Episode rows on desktop ---------------------------------------
     The row grid is shared with the phone, where the still is 148px because
     that is most of a 375pt screen. On a 1044px row that same still is a
     thumbnail with a paragraph of empty space beside it. Same structure, bigger
     picture, and the row is pulled back onto the page gutter — Bootstrap's
     negative row margin had it sitting 15px left of every other element. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep {
    grid-template-columns: 28px 260px minmax(0, 1fr);
    column-gap: 20px;
    row-gap: 8px;
    margin-inline: 0 !important;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-epList {
    margin-inline: 0 !important;
  }
  /* Removing the row's negative margin leaves the columns' own 15px padding
     behind, which put the heading and the season field 15px right of the
     episode rows and everything else on the page. Zero both, so the whole
     section shares one left edge. */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-epList > [class*="col"] {
    padding-inline: 0 !important;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu h2 {
    font-size: 17px !important;
  }
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu .vid-description {
    font-size: 14px;
    max-width: 78ch;
  }
  /* the play triangle scales with the larger still */
  body[data-layout="cinematic"] .vxm.vxm-page .vxm-ep .listMenu > a.img::after {
    left: 14px;
    bottom: 14px;
    border-width: 9px 0 9px 15px;
  }

  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > h2.h5,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > h2.h5 {
    display: inline-block;
    padding-bottom: 10px;
    border-bottom: 3px solid var(--vxl-ink) !important;
  }

  /* ======================================================================
     DETAIL PAGE — HBO MAX PASS (desktop reference, movie page).

     The reference's hero column reads title → meta → Watch CTA → labeled
     icon row → synopsis → genres, with the CTA on its own line and the
     icons as small captioned columns beneath it. The template renders the
     meta (.vxc-heroMeta) and synopsis/genres (.vxc-heroBody) into the hero
     for cinematic pages (see videoDetailBlock.html cineDetail); everything
     visual is here.
     ====================================================================== */

  /* Title is ink — it inherited a muted heading colour and read as a ghost. */
  body[data-layout="cinematic"] .videoLogo h1 {
    color: var(--vxl-ink) !important;
  }

  /* Meta: one quiet caption line directly under the title. */
  body[data-layout="cinematic"] .detailsThumb .overlapData .vxc-heroMeta {
    align-items: center;
    gap: 4px 6px;
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--vxl-ink-muted);
    /* one vertical rhythm for the whole stack: meta→CTA equals the action
       grid's own 22px row-gap (the utility mb-3 gave 16 and the block read
       unevenly spaced) */
    margin-bottom: 22px !important;
  }

  /* CTA: a pill sized by its own label, like the hero's — the reference's
     420px column-spanning slab put ~120px of empty red on either side of a
     six-letter word, which reads as a banner, not a button. Width comes
     from content + the base rule's 28px padding; the bottom-edge resume
     bar sizes with it for free. */
  body[data-layout="cinematic"].page-video_details .detailsIcon .playResumeBtn,
  body[data-layout="cinematic"].page-series_details .detailsIcon .playResumeBtn {
    border-radius: var(--vxl-radius-pill, 999px) !important;
    width: auto;
    max-width: none;
    min-width: 0;
    justify-content: center !important;
  }

  /* ---- actions_style arrangement option --------------------------------
     Everything from here to the .copyDiv clip is the LABELED treatment:
     two-row grid, icon columns with captions, Trailer as a column. It is
     scoped to body[data-lo-actions-style="labeled"] (the default) so that
     "bare" simply falls back to the earlier treatment already above in
     this sheet: one flex row, tight bare icons, Trailer as a ghost pill.
     No bare-specific rules exist — absence IS the bare look. */
  /* The action area becomes a two-row grid: CTA line, then the icon row.
     Flexbox has no forced line break, so the wrap is stated as placement. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon {
    display: grid !important;
    /* the trailing 1fr lets the full-width CTA span the hero column instead
       of being capped at the icon tracks' summed width */
    grid-template-columns: repeat(4, max-content) 1fr;
    justify-items: center;
    align-items: start;
    column-gap: 40px !important;
    row-gap: 22px;
  }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn:not([data-stats-event="trailer_play"]),
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn:not([data-stats-event="trailer_play"]) {
    grid-row: 1;
    grid-column: 1 / -1;
    justify-self: start;
  }
  /* Part-watched: Resume + "Play from beginning" share row 1 as a pair, the
     way the reference pairs Resume with Restart. The wrapper (not the
     buttons) is the grid item, so the two sit side by side inside it and
     split the width evenly — placing both buttons at `1 / -1` would stack
     them in the same cell. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxc-ctaPair,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxc-ctaPair {
    display: flex !important;
    grid-row: 1;
    grid-column: 1 / -1;
    justify-self: start;
    order: -1;
    align-items: center;
    gap: 12px;
    /* content-sized, same reasoning as the solo CTA above: stretching the
       pair to split 640px put "Resume" in a 314px pill */
    width: auto;
    max-width: none;
  }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxc-ctaPair .playResumeBtn,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxc-ctaPair .playResumeBtn {
    flex: 0 0 auto !important;
    width: auto;
    min-width: 0;
    max-width: none;
    margin: 0 !important;
    /* same 30px as the solo CTA and the hero — one control, one measure */
    padding-inline: 30px !important;
  }
  /* Icon order under the CTA: My List, Rate, Trailer, Share. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxm-actCol--list,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxm-actCol--list { order: 1; }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxm-actCol--rate,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxm-actCol--rate { order: 2; }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"],
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] { order: 3; }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxm-actCol--share,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxm-actCol--share { order: 4; }

  /* Labeled icon columns — glyph over a small caption, as the reference. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxm-actCol,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxm-actCol {
    display: inline-flex !important;
    flex-direction: column;
    align-items: center;
    gap: 6px;
  }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxm-actLabel,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxm-actLabel {
    display: block !important;
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    color: var(--vxl-ink-muted);
  }
  /* Inside a column the glyph comes first, the caption second — the older
     row-ordering rules (.vxr order 2, --share > .copyButton order 4) would
     otherwise sort the caption ABOVE its icon. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .vxm-actCol > *,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .vxm-actCol > * {
    order: 0;
  }

  /* Trailer joins the icon row as a labeled column (it was a ghost pill).
     The attribute selector outweighs the CTA rule above, so every slab
     property has to be restated. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"],
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] {
    flex-direction: column;
    width: auto !important;
    height: auto !important;
    min-width: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    gap: 6px;
    font-size: 12px !important;
    font-weight: 600;
    color: var(--vxl-ink) !important;
  }
  /* 10px vertical margins seat the 24px glyph in the same 44px optical box
     as the circled icons beside it, so the caption baselines line up. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] .vxm-ico,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] svg,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] i,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] .vxm-ico,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] svg,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] i {
    width: 24px !important;
    height: 24px !important;
    font-size: 24px !important;
    margin: 10px 0 !important;
  }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] > span,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"] > span {
    color: var(--vxl-ink-muted) !important;
  }
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"]:hover > span,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .playResumeBtn[data-stats-event="trailer_play"]:hover > span {
    color: var(--vxl-ink) !important;
  }

  /* The related section starts exactly at the hero's bottom edge, and the
     unclipped 16:9 artwork spills ~50px past that line under the melt — the
     dimmed spill painted over the heading's top half. Clearance puts the
     heading below the melt zone. */
  body[data-layout="cinematic"].page-video_details .card.videoDetails > .insidePadding,
  body[data-layout="cinematic"].page-series_details .card.videoDetails > .insidePadding {
    padding-top: 64px;
  }

  /* The clipboard source must not occupy a grid cell — a zero-height item
     still owns a row, and the row gap paints as dead space. */
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-video_details .detailsIcon .copyDiv,
  body[data-layout="cinematic"][data-lo-actions-style="labeled"].page-series_details .detailsIcon .copyDiv {
    position: absolute;
    width: 1px;
    height: 1px !important;
    overflow: hidden;
    clip-path: inset(50%);
  }

  /* Ambient trailer discs stay on the artwork's corner. They anchor to
     .overlapData, whose BOTTOM has moved down (the hero now carries the
     synopsis), so bottom-offsets drifted off the picture. Measured from the
     top instead: the block is pulled up by --vxc-desktop-pull, so the
     artwork's bottom edge is that far below the block's top — minus the
     44px disc and its 34px inset. Same variable as the pull, so retuning
     the lift cannot strand the discs again. */
  body[data-layout="cinematic"].page-video_details .detailsIcon .rundedBtn.playPausePage,
  body[data-layout="cinematic"].page-video_details .detailsIcon .rundedBtn.trailerPlayPauseBtn,
  body[data-layout="cinematic"].page-series_details .detailsIcon .rundedBtn.iframePlayPauseSeries,
  body[data-layout="cinematic"].page-series_details .detailsIcon .rundedBtn.trailerPlayPauseBtn {
    top: calc(var(--vxc-desktop-pull, 190px) - 78px);
    bottom: auto;
  }

  /* Synopsis + genre line under the actions — the reference gives the
     description real presence: it fills the hero column (about half the
     screen) at reading size, two lines, with the genre line quiet below. */
  body[data-layout="cinematic"] .vxc-heroBody {
    max-width: 100%;
    margin-top: 26px;
  }
  /* Heavy selector on purpose: the shared synopsis-measure rule
     (.detailsThumb .overlapData p, 62ch) would otherwise cap this at a
     strip and defeat the half-screen presence. */
  body[data-layout="cinematic"] .detailsThumb .overlapData p.vxc-heroDesc {
    max-width: none;
    margin: 0 0 14px;
    font-size: clamp(17px, 1.15vw, 22px);
    line-height: 1.5;
    color: var(--vxl-ink);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  /* Genres are spans separated by air, not commas ("Action  Fantasy & Sci-Fi"). */
  body[data-layout="cinematic"] .vxc-heroGenres {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 26px;
    margin: 0;
    font-size: 14px;
    letter-spacing: 0.03em;
    color: var(--vxl-ink-muted);
  }

  /* Related titles: the reference is a six-across portrait poster wall with
     no captions — the poster carries the title (same call as the search
     wall; the h2 stays in the DOM for screen readers). */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.cardBg),
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.cardBg) {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 16px 12px;
  }
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg h2,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg h2 {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    margin: 0 !important;
  }
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .card-img-overlay,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .card-img-overlay {
    display: none !important;
  }
  /* Every PORTRAIT cell keeps the RAILS' poster shape — 9:16, the 177.78%
     padding hack `.ratio.portrait` uses in cards.css — so a title is
     identical here and on the homepage. (This used to force 2:3, which made
     the wall's cards visibly shorter than the same card in a rail.) Scoped
     to `.portrait` since 26.443.x: the detail blocks emit that class only
     when display_thumb_type is portrait, so a landscape tenant's wall stays
     .ratio-16x9 (owner report). A title with no portrait artwork falls back
     to a landscape still; the frame crops it with object-fit below. */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .ratio.portrait,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .ratio.portrait {
    aspect-ratio: auto !important;
    height: 0 !important;
    padding: 0 0 177.78% !important;
  }
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg .ratio img,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg .ratio img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* ---- Reference pass 2 (HBO Max, Two Towers screenshots) --------------- */

  /* Meta is plain quiet text — "13+ 3h 2002" — not outlined chips. */
  body[data-layout="cinematic"] .vxc-heroMeta .badge-secondary-outline {
    border: 0 !important;
    padding: 0 !important;
    background: none !important;
    font-weight: 400;
    color: inherit;
  }

  /* The detail page runs (nearly) full-bleed like the reference: the grid and
     tabs span the viewport minus the 48px inside gutter, instead of floating
     in a centered column. The hero artwork's own bleed is measured from the
     container, so it stays edge-to-edge either way. !important because the
     base theme caps .detailsContainer at 1440px with one of its own; the
     modal and every other layout keep that cap. */
  body[data-layout="cinematic"].page-video_details .container.vxm-page,
  body[data-layout="cinematic"].page-video_details .detailsContainer,
  body[data-layout="cinematic"].page-series_details .container.vxm-page,
  body[data-layout="cinematic"].page-series_details .detailsContainer {
    max-width: 100% !important;
  }

  /* Poster wall: the SAME cards as the homepage rails, so a title is the
     same size wherever it appears. The rails run 8 portrait cards at this
     width on cinematic (base 9, less the layout's -1 density delta) at a
     10px gap — GAPS.cinematic in _layout_resolver.html and the swiper's
     own `spaceBetween` — so the grid mirrors both. Column counts follow the
     rails' breakpoints further down; the row gap is a touch larger because
     rows need separating where a single rail does not. */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.cardBg),
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.cardBg) {
    grid-template-columns: repeat(8, minmax(0, 1fr));
    gap: 18px var(--vxl-card-gap, 10px);
    margin-inline: 0 !important;
  }

  /* The rails step down at exactly these widths (new-swiper.html
     breakpoints, minus the cinematic delta): 9-1=8 from 1450, 8-1=7 from
     1200, 7-1=6 from 992. The wall steps with them so the two never show
     different card sizes on the same screen. */
  @media (max-width: 1449.98px) {
    body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.cardBg),
    body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.cardBg) {
      grid-template-columns: repeat(7, minmax(0, 1fr));
    }
  }
  @media (max-width: 1199.98px) {
    body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.cardBg),
    body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.cardBg) {
      grid-template-columns: repeat(6, minmax(0, 1fr));
    }
  }

  /* ---- Landscape wall (display_thumb_type = landscape) ------------------
     Everything above sizes the PORTRAIT wall (poster-rail counts minus the
     cinematic delta). Since the detail blocks emit `.portrait` only when
     the tenant's default thumbnail shape is portrait (owner report), a
     landscape wall mirrors the LANDSCAPE rails instead — 7/6/5 minus the
     delta = 6/5/4 across the same steps — and gets its caption back: a
     16:9 still, unlike a poster, does not carry the title in the artwork.

     Tracks are `minmax(0, 1fr)`, NOT `1fr`. A bare `1fr` is
     `minmax(auto, 1fr)`, so no track may shrink below its content's
     min-content width — and the caption below carries `white-space:
     nowrap`, whose min-content width is the WHOLE untruncated title. The
     wall then sized every column to its own title: 506px for "The
     Neighborhood - S07E19 - …" beside 168px for "Thumbs Testing", cards
     at six different widths (owner report). Zeroing the floor lets the
     ellipsis do its job. The portrait counts above carry it too — they
     hide their caption today, but the same trap is one edit away. */
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.ratio-16x9),
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.ratio-16x9) {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
  @media (max-width: 1449.98px) {
    body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.ratio-16x9),
    body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.ratio-16x9) {
      grid-template-columns: repeat(5, minmax(0, 1fr));
    }
  }
  @media (max-width: 1199.98px) {
    body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding > .row:has(.ratio-16x9),
    body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding > .row:has(.ratio-16x9) {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
  }
  body[data-layout="cinematic"].page-video_details .videoDetails > .insidePadding .cardBg:has(.ratio-16x9) h2,
  body[data-layout="cinematic"].page-series_details .videoDetails > .insidePadding .cardBg:has(.ratio-16x9) h2 {
    position: static;
    width: auto;
    height: auto;
    clip-path: none;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    margin: 8px 2px 0 !important;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--vxl-ink);
  }

  /* ---- Episodes as the reference's horizontal row ----------------------
     HBO's series screen runs the episodes as one scrollable row of landscape
     cards (still on top, then "E1: …", then a clamped synopsis) with a
     compact season picker above — not the vertical Netflix list, which
     phones keep. The wrapper is display:contents everywhere else, so only
     cinematic desktop reflows. */
  body[data-layout="cinematic"].page-series_details .vxc-epScroll {
    display: flex;
    flex: 0 0 100%;
    width: 100%;
    flex-wrap: nowrap;
    gap: 18px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    padding: 4px 0 14px;
    scrollbar-width: thin;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep {
    display: block !important;
    /* six cards per screen (5 gaps × 18px), minus a sliver so the seventh
       peeks in and says the row scrolls — the reference's density */
    flex: 0 0 calc((100% - 130px) / 6);
    width: calc((100% - 130px) / 6);
    min-width: 220px;
    margin: 0 !important;
    padding: 0 !important;
  }
  /* the vertical list's furniture: episode number and divider */
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep > .row > .col-1,
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep hr {
    display: none !important;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep > .row > [class*="col-"]:not(.col-1) {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    flex: none !important;
    padding: 0 !important;
  }
  /* still on top, then text under it */
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu > a.img {
    display: block !important;
    width: 100% !important;
    margin: 0 0 10px !important;
    /* 4px — the corner the poster cards and the home rails use */
    border-radius: 4px;
    overflow: hidden;
  }
  body[data-layout="cinematic"].page-series_details .vxc-epScroll .vxm-ep .listMenu .vid-description {
    display: -webkit-box !important;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0 !important;
    max-width: none;
  }
  /* compact "Season 1 ▾" picker, like the reference — not a full-width bar,
     and seated LEFT under the heading: its Bootstrap column would otherwise
     keep its 4/12 width and park the picker at the right edge. */
  body[data-layout="cinematic"].page-series_details .vxm-epList > [class*="col"]:not(.vxm-ep) {
    flex: 0 0 100% !important;
    max-width: 100% !important;
  }
  /* Desktop picker: same field as the phone (see the shared rules above),
     one step larger. modal.css pushes it to the right edge with
     `margin-left: auto` (the page shares the .vxm wrapper); the reference
     seats it LEFT, under the heading. Fallback <select> only — the page's
     own control is .vxc-seasonPick, at the foot of this file. */
  body[data-layout="cinematic"].page-series_details .vxm-epList select.form-select {
    width: auto !important;
    min-width: 200px;
    height: 46px !important;
    padding: 0 46px 0 18px !important;
    margin-inline: 0 !important;
    background-position: calc(100% - 22px) center, calc(100% - 17px) center !important;
  }
}

/* ==========================================================================
   CONTINUE WATCHING — the resume row.

   Landscape stills (forced for this rail alone, see new-swiper.html's
   forceThumbType), a progress rule welded to the artwork's bottom edge, the
   episode caption underneath, and an overflow menu in the corner. The menu
   is not decoration: this layout hides the dwell panel, which is where
   "Remove from Continue Watching" used to live, so without it a finished
   title could not be taken off the row.
   ========================================================================== */
body[data-layout="cinematic"] .swiper--continue-watching .card.no-border {
  background: transparent !important;
}
/* The slide is sized by an aspect-ratio spacer and the card is laid over it,
   so the caption hangs BELOW the track without adding to its height — its
   last line landed on the next rail's heading. The caption is bounded (title
   clamped to two lines, then one meta line), so the row reserves exactly
   that much underneath. */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-caption {
  min-height: 66px;
}
body[data-layout="cinematic"] .swiper--continue-watching {
  /* !important: the rail carries Bootstrap's .pb-4 utility, which is itself
     !important and would otherwise keep the row at 24px. */
  padding-bottom: 84px !important;
}
/* The rule sits ON the still, flush to its bottom edge — as a sibling below
   it (the stock position) it floated in the gap between card and caption. */
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock {
  position: relative;
}
/* Flush with the card's bottom edge, inside it. The bar lives in the card
   now (see video.html / series.html), so `bottom: 0` seats it on the tile's
   own edge rather than leaving it at its static position — which is what
   made it read as a separate strip sitting under the artwork.
   `border-radius: 0` on purpose: the card already clips to its 4px corners,
   so the bar takes the tile's shape and its ends meet the rounded edge
   instead of curving away from it. */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  width: auto !important;
  margin: 0 !important;
  border-radius: 0;
  background: color-mix(in srgb, var(--vxl-ink) 28%, transparent) !important;
  overflow: hidden;
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-progress .progress-bar {
  background: var(--vod-primary, #e50914) !important;
}
/* ---- Preview media stays inside the card -------------------------------
   The preview is absolutely positioned, and an absolutely-positioned
   element is clipped ONLY by an ancestor that is its containing block —
   `overflow: hidden` on the card does nothing if the card is not that
   block. When the anchor and the card are both static, the preview
   resolves against whatever is positioned further up (the rail wrapper is
   1920x299 and starts ABOVE the card), so it escapes the tile entirely and
   paints over the row heading and the neighbouring cards.

   So the containing block is pinned to the card rather than the preview
   being resized: the card and its anchor are made positioned, which puts
   the card's own `overflow: hidden` back in charge of the preview. The
   size caps only ever shrink — nothing here can make a preview larger,
   which an earlier `inset: 0` version could when the ancestor it resolved
   against was bigger than the card.

   An embedded trailer needs this most: it arrives as raw provider markup
   through `v-html` (`emebedTrailer` is the API's `embed_code`) carrying its
   own `width="560" height="315"`. */
/* `a.relative` is the ARTWORK link specifically — not `.card > a`, which
   also matches the play affordance and, at higher specificity than its own
   rule, would strip its absolute positioning and drop it into the flow. */
[data-layout="cinematic"] .videoBlock.vxc .card,
[data-layout="cinematic"] .videoBlock.vxc .card > a.relative {
  position: relative;
}
/* With the containing block pinned above, filling it is safe: `inset: 0`
   can now only ever mean the card. Without that guarantee it was the bug —
   it stretched the preview to whichever larger ancestor happened to be
   positioned. Capped as well as stretched, so a provider's own width can
   never win. */
[data-layout="cinematic"] .videoBlock.vxc .card iframe,
[data-layout="cinematic"] .videoBlock.vxc .card video,
[data-layout="cinematic"] .videoBlock.vxc .card .video-js,
[data-layout="cinematic"] .videoBlock.vxc .card .vjs-tech {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
  max-width: 100% !important;
  max-height: 100% !important;
  border: 0;
  object-fit: cover;
}

/* ---- Resume affordance, bottom-left of the still -----------------------
   The reference puts a bare white triangle there on every resume card, and
   it earns its place: the still itself opens the title's page, so without
   it the row has no one-click way back into playback. Always visible, like
   the ⋮ — there is no dwell at all on touch.
   Bare glyph again, no disc: legibility over a bright frame comes from a
   drop-shadow, which darkens only what is behind the triangle. It clears
   the progress rule at the card's base. */
/* The padding is the tap target, not the glyph: at 22px the triangle alone
   would be a 22px target, under the 30px a thumb needs. The inset is
   reduced by the same 4px so the glyph still sits 12px off the card's
   edges — the padding grows the hit area inward, invisibly. */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-play {
  position: absolute;
  left: 8px;
  bottom: 8px;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  color: var(--vxl-ink, #fff);
  line-height: 0;
  text-decoration: none;
  opacity: 1;
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-play .vxm-ico {
  width: 22px;
  height: 22px;
  /* ink and scrim both derive from the tenant's branding, so the glyph stays
     legible on a light-branded site instead of being white-on-white */
  color: var(--vxl-ink, #fff);
  filter: drop-shadow(0 1px 5px color-mix(in srgb, var(--vxl-scrim-solid) 88%, transparent));
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-play:hover {
  opacity: 0.85;
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-play:focus-visible {
  outline: 2px solid var(--vxl-ink, #fff);
  outline-offset: 3px;
}

/* The bar must not move when the card is focused. cards.css re-margins it on
   hover (`margin: 0 12px 10px !important`, for the legacy expanding card),
   which lifted it 10.4px off the bottom edge and detached it from the tile —
   measured. Restated here for every focus state, at a specificity that
   outranks that rule, so the bar is simply always where it is at rest. */
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc.hoverOnVideo:hover .progress.vxcw-progress,
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc.hoverOnVideo:active .progress.vxcw-progress,
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc.vxc-open .progress.vxcw-progress,
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc:hover .progress.vxcw-progress {
  display: flex;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  width: auto !important;
  margin: 0 !important;
  border-radius: 0;
}

/* The row keeps the lift and transitions every other rail uses — it was
   briefly opted out of both, along with a white focus ring on the card.
   The ring is gone: `outline` on the card is drawn outside its border box,
   and the slide clips it on three sides, so only the bottom edge survived
   and it read as a stray underline rather than a frame. */

/* No panel behind a resume card. The block paints rgb(13,13,13) at a 6px
   radius, which on the near-black page shows as a slab wrapping BOTH the
   artwork and the caption — the card stops reading as a still with text
   under it and starts reading as a tile with a backing. The artwork and the
   ring supply all the edge this row needs. */
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc,
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc:hover,
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc:active,
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc.hoverOnVideo:hover,
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock.vxc.vxc-open {
  background: transparent !important;
  border-radius: 0 !important;
}

/* ---- Caption: "S1 E2  Family Statements", then a quiet meta line -------- */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-caption {
  padding: 10px 2px 0;
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-title {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--vxl-ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* the episode number reads as a label, so it stays quiet next to the title */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-ep {
  margin-inline-end: 6px;
  font-weight: 400;
  color: var(--vxl-ink-muted);
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-meta {
  margin-top: 3px;
  font-size: 12px;
  letter-spacing: 0.03em;
  color: var(--vxl-ink-muted);
}
/* the stock mobile-only title would duplicate the caption */
body[data-layout="cinematic"] .swiper--continue-watching .videoBlock > .title {
  display: none !important;
}

/* ---- Overflow menu ------------------------------------------------------ */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu {
  position: absolute;
  top: 4px;
  inset-inline-end: 4px;
  z-index: 6;
}
/* Bare glyph — no chip, no ring, no fill. The reference draws three white
   dots straight onto the still, and a scrim disc around them read as a
   button floating over the artwork. Legibility on a bright frame comes from
   a drop-shadow instead: it darkens only what is behind the dots
   themselves, so nothing box-shaped appears.
   Always visible, as the reference has it: hiding it until dwell makes the
   row's only affordance for Remove/Restart undiscoverable, and there is no
   dwell at all on touch. */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu__trigger,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  outline: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  color: var(--vxl-ink, #fff);
  opacity: 1;
  transition: opacity var(--vxl-dur-2) var(--vxl-ease);
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu__trigger:hover,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu__trigger:hover,
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu__trigger:focus,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu__trigger:focus,
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu.is-open .vxcw-menu__trigger,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu.is-open .vxcw-menu__trigger {
  background: transparent;
  box-shadow: none;
  outline: 0;
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu__trigger:hover,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu__trigger:hover,
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu.is-open .vxcw-menu__trigger,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu.is-open .vxcw-menu__trigger {
  opacity: 0.75;
}
/* keyboard users still get a ring — removing the outline is about the
   resting state, not about making the control untabbable */
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu__trigger:focus-visible,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu__trigger:focus-visible {
  outline: 2px solid var(--vxl-ink, #fff);
  outline-offset: 2px;
}
body[data-layout="cinematic"] .swiper--continue-watching .vxcw-menu__trigger .vxm-ico,
body[data-layout="cinematic"] .swiper--my-list .vxcw-menu__trigger .vxm-ico {
  width: 22px;
  height: 22px;
  color: var(--vxl-ink, #fff);
  filter: drop-shadow(0 1px 4px color-mix(in srgb, var(--vxl-scrim-solid) 85%, transparent));
}
/* Placed from JS as `position: fixed` (see toggleCwMenu) — the swiper track
   and the card both clip their overflow, which sliced an absolutely
   positioned panel off at the card's edge, and Swiper's transform on the
   track made `fixed` resolve against IT rather than the viewport. The panel
   is therefore re-parented to <body> while open, which is exactly why these
   rules must NOT be scoped under .swiper--continue-watching: detached, it
   would match nothing and render unstyled. */
body[data-layout="cinematic"] .vxcw-menu__pop {
  position: fixed;
  z-index: 1200;
  min-width: 264px;
  padding: 8px 0;
  border-radius: 8px;
  /* opaque by construction: the surface token is a translucent white, which
     over artwork left the labels unreadable. Same trick as the login card —
     stack it on the page colour so a tenant's own palette still shows. */
  background:
    linear-gradient(var(--vxl-surface-2), var(--vxl-surface-2)),
    var(--vod-body-bg, #0b0b10);
  border: 1px solid var(--vxl-line);
  box-shadow: var(--vxl-shadow-3);
}
body[data-layout="cinematic"] .vxcw-menu__item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 18px;
  border: 0;
  background: transparent;
  color: var(--vxl-ink);
  font-size: 14px;
  font-weight: 600;
  text-align: start;
  text-decoration: none;
  white-space: nowrap;
}
body[data-layout="cinematic"] .vxcw-menu__item:hover {
  background: color-mix(in srgb, var(--vxl-ink) 10%, transparent);
  color: var(--vxl-ink);
  text-decoration: none;
}
body[data-layout="cinematic"] .vxcw-menu__item .vxm-ico {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
}
/* "Resume S1 E1" carries its progress rule here too, as on the CTA buttons.
   The row has room below the text, so the rule hangs closer than the 7px the
   buttons use. */
body[data-layout="cinematic"] .vxcw-menu__item .vxc-resumeBar {
  bottom: -5px;
}
/* Edge cases (a card at the row's right edge, or one low in the viewport)
   are handled by toggleCwMenu, which flips the panel left/up; nothing else
   is needed per breakpoint. */

/* --------------------------------------------------------------------------
   Info modal + detail page (.vxm / .vxm-page) — CINEMATIC
   A layout is the site's identity, not a homepage skin: body[data-layout] is
   stamped on every page (cb_active_web_layout), so the modal and the content
   detail page wear the same personality as the billboard — full-bleed art,
   heavy type, pill actions, deep elevation. All from tenant tokens.
   -------------------------------------------------------------------------- */
[data-layout="cinematic"] .vxm .modal-content {
  border-radius: var(--vxl-radius-lg);
  box-shadow: var(--vxl-shadow-3);
}
[data-layout="cinematic"] .vxm .modal-dialog.detailsModal {
  max-width: 1000px;                    /* a cinematic sheet reads wider */
}
/* title: the same tight, heavy voice as the billboard */
[data-layout="cinematic"] .vxm .videoLogo h1,
[data-layout="cinematic"] .vxm .insidePadding > h2.h4:has(span) {
  font-weight: 700;
  letter-spacing: var(--vxl-tracking-tight);
}
[data-layout="cinematic"] .vxm .videoLogo h1 {
  font-size: clamp(1.6rem, 2.6vw, 2.4rem);
  line-height: 1.08;
}
/* actions: pills, matching the hero */
[data-layout="cinematic"] .vxm .playResumeBtn,
[data-layout="cinematic"] .vxm .rundedBtn {
  border-radius: var(--vxl-radius-pill);
}
/* The art dissolves into whatever is beneath it — the sheet body in the modal,
   the page on the detail screen.

   This was written for the modal and hard-coded `--vod-card-bg` as the end
   colour. But `.vxm` is on the detail PAGE as well as the sheet, so the page
   got a gradient resolving to the card colour (rgb 23,23,28) over a body that
   is rgb(11,11,16) — a visibly wrong block behind the synopsis, and a seam
   where the gradient ended. The end colour is now a variable that defaults to
   the page background and is re-pointed at the sheet colour inside the modal,
   so each context dissolves into its own surface. */
[data-layout="cinematic"] .vxm .detailsThumb::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 45%;
  pointer-events: none;
  background: linear-gradient(0deg,
    var(--vxc-dissolve-to, var(--vod-body-bg, #000)) 0%,
    transparent 100%);
}
[data-layout="cinematic"] .vxm .modal-content {
  --vxc-dissolve-to: var(--vod-card-bg, var(--vxl-scrim-solid));
}
[data-layout="cinematic"] .vxm .detailsThumb {
  position: relative;
}
/* "More Like This" cards get the same calm lift as the rails */
[data-layout="cinematic"] .vxm .cardBg {
  border-radius: var(--vxl-card-radius);
  transition: transform var(--vxl-dur-2) var(--vxl-ease),
              box-shadow var(--vxl-dur-2) var(--vxl-ease);
}
[data-layout="cinematic"] .vxm .cardBg:hover {
  transform: translateY(-3px);
  box-shadow: var(--vxl-shadow-2);
}
@media (prefers-reduced-motion: reduce) {
  [data-layout="cinematic"] .vxm .cardBg {
    transition: none;
  }
  [data-layout="cinematic"] .vxm .cardBg:hover {
    transform: none;
  }
}

/* ==========================================================================
   Info screen — landscape source (phone)
   The twin of the editors-pick hero. `detailBackdrop` used to take the
   portrait asset for EVERY cinematic phone, so a tenant switching the mobile
   hero design to landscape got a landscape home screen and a portrait title
   screen. It now reads the same knob, and this is the frame that follows it.
   ========================================================================== */
@media (max-width: 991.98px) {
  body[data-layout="cinematic"] .detailsThumb.vxm-hero-landscape {
    --vxm-chrome: 56px;
    overflow: hidden;
  }
  /* The still runs whole at 16:9, clear of the back control. */
  body[data-layout="cinematic"] .detailsThumb.vxm-hero-landscape .ratio,
  body[data-layout="cinematic"] .detailsThumb.vxm-hero-landscape .ratio.ratio-16x9 {
    aspect-ratio: 16 / 9 !important;
    height: auto !important;
    padding-bottom: 0 !important;
    margin-top: 0;
    position: relative;
    z-index: 1;
  }
  body[data-layout="cinematic"] .detailsThumb.vxm-hero-landscape .ratio > div,
  body[data-layout="cinematic"] .detailsThumb.vxm-hero-landscape .ratio img {
    height: 100% !important;
    object-fit: cover;
  }
  /* Same ambient extension as the hero: the frame itself, scaled and blurred,
     carries the canvas past the still so the screen stays full-bleed without
     cropping the picture or inventing artwork. Decorative — aria-hidden. */
  body[data-layout="cinematic"] .detailsThumb.vxm-hero-landscape {
    background-color: var(--vod-body-bg, #000);
  }
  body[data-layout="cinematic"] .vxm-hero-ambient {
    position: absolute;
    left: -14%;
    right: -14%;
    top: -6%;
    height: calc(100vw * 9 / 16 + 320px);
    background-size: cover;
    background-position: center;
    filter: blur(46px) saturate(1.45);
    transform: scale(1.1);
    z-index: 0;
    pointer-events: none;
  }
  body[data-layout="cinematic"] .vxm-hero-ambient::after {
    content: "";
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, var(--vod-body-bg, #000) 46%, transparent);
  }
  /* A scrim sized to THIS canvas — the portrait screen's is mixed for a 520px
     picture and would dim a 219px still end to end. Top band covers only the
     back control; the bottom fade is confined to the last third. */
  body[data-layout="cinematic"] .detailsThumb.vxm-hero-landscape::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: calc(100vw * 9 / 16 + var(--vxm-chrome, 56px));
    z-index: 2;
    pointer-events: none;
    background:
      linear-gradient(0deg,
        var(--vxl-scrim-solid) 0%,
        var(--vxl-scrim) 26%,
        transparent 48%) bottom / 100% 100% no-repeat,
      linear-gradient(180deg,
        var(--vxl-scrim-solid) 0%,
        var(--vxl-scrim) 60%,
        transparent 100%) top / 100% var(--vxm-chrome, 56px) no-repeat;
  }
}

/* ==========================================================================
   SEASON PICKER — the episodes section's season control.

   Replaces the native <select> on the cinematic detail page (see
   .vxc-seasonPick in seriesDetailBlock.html; every other surface still
   renders the <select>, which the rules further up this file style).

   One shape on both: a list anchored under the field and sized to it —
   the panel is exactly as wide as the closed "Season 1" field above it, as
   the reference app draws it, on phone and desktop alike. Only the metrics
   differ between the two (row height, radius, how far it may scroll).

   Rows carry the episode count under the season name, which the OS popup
   could never show: the choice is "Season 2 · 8 Episodes", not "Season 2".
   ========================================================================== */
body[data-layout="cinematic"] .vxc-seasonPick {
  position: relative;
  display: inline-block;
  max-width: 100%;
}

/* ---- The closed field ---------------------------------------------------- */
body[data-layout="cinematic"] .vxc-seasonPick__field {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 180px;
  max-width: 100%;
  height: 44px;
  margin: 0;
  padding: 0 14px 0 16px;
  border: 1px solid var(--vxl-line);
  border-radius: 10px;
  background: var(--vxl-surface-2);
  color: var(--vxl-ink);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition:
    background-color var(--vxl-dur-2, 0.25s) var(--vxl-ease),
    border-color var(--vxl-dur-2, 0.25s) var(--vxl-ease);
}
body[data-layout="cinematic"] .vxc-seasonPick__field:hover,
body[data-layout="cinematic"] .vxc-seasonPick.is-open .vxc-seasonPick__field {
  border-color: var(--vxl-ink-faint);
  background: var(--vxl-surface-3);
}
body[data-layout="cinematic"] .vxc-seasonPick__field:focus {
  outline: none;
}
body[data-layout="cinematic"] .vxc-seasonPick__field:focus-visible {
  outline: 2px solid var(--vxl-ink);
  outline-offset: 2px;
}
/* The label is the shrinkable part — a long tenant-authored season name
   ellipsises rather than pushing the caret out of the field. */
body[data-layout="cinematic"] .vxc-seasonPick__value {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: start;
}
body[data-layout="cinematic"] .vxc-seasonPick__caret {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  opacity: 0.7;
  transition: transform var(--vxl-dur-2, 0.25s) var(--vxl-ease, ease);
}
body[data-layout="cinematic"] .vxc-seasonPick.is-open .vxc-seasonPick__caret {
  transform: rotate(180deg);
  opacity: 1;
}

/* ---- Scrim ---------------------------------------------------------------
   Desktop: an invisible full-viewport click target, so a click anywhere off
   the menu closes it without a document-level listener. Phones: the sheet's
   dimmer (see the ≤991.98px block). */
body[data-layout="cinematic"] .vxc-seasonPick__scrim {
  position: fixed;
  inset: 0;
  z-index: 2040;
  background: transparent;
}

/* ---- The list ------------------------------------------------------------ */
body[data-layout="cinematic"] .vxc-seasonPick__menu {
  position: absolute;
  z-index: 2050;
  top: calc(100% + 8px);
  inset-inline-start: 0;
  /* Exactly the field's width, on every screen: the wrapper is inline-block
     so it is sized by the button, and the panel takes 100% of it. Open and
     closed are one column — the two can never drift apart. */
  width: 100%;
  max-height: 300px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px;
  border: 1px solid var(--vxl-line);
  border-radius: 12px;
  background: var(--vxl-scrim-strong);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: var(--vxl-shadow-3, 0 20px 48px rgba(0, 0, 0, 0.46));
  scrollbar-width: thin;
  animation: vxcSeasonPop 0.16s var(--vxl-ease, ease) both;
}
@keyframes vxcSeasonPop {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
body[data-layout="cinematic"] .vxc-seasonPick__list {
  margin: 0;
  padding: 0;
  list-style: none;
}
body[data-layout="cinematic"] .vxc-seasonPick__opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--vxl-ink-muted);
  text-align: start;
  cursor: pointer;
  transition:
    background-color var(--vxl-dur-1, 0.15s) var(--vxl-ease),
    color var(--vxl-dur-1, 0.15s) var(--vxl-ease);
}
body[data-layout="cinematic"] .vxc-seasonPick__opt:hover,
body[data-layout="cinematic"] .vxc-seasonPick__opt:focus-visible {
  outline: none;
  background: var(--vxl-surface-2);
  color: var(--vxl-ink);
}
body[data-layout="cinematic"] .vxc-seasonPick__opt.is-active {
  background: var(--vxl-surface-3);
  color: var(--vxl-ink);
}
body[data-layout="cinematic"] .vxc-seasonPick__optText {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}
body[data-layout="cinematic"] .vxc-seasonPick__optName {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.25;
}
body[data-layout="cinematic"] .vxc-seasonPick__opt.is-active .vxc-seasonPick__optName {
  font-weight: 700;
}
body[data-layout="cinematic"] .vxc-seasonPick__optMeta {
  color: var(--vxl-ink-faint);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.2;
}
/* The tick holds its cell whether or not it is showing, so the names of the
   selected and unselected rows share one left edge. */
body[data-layout="cinematic"] .vxc-seasonPick__tick {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--vxl-accent, var(--vod-primary, #e50914));
  opacity: 0;
}
body[data-layout="cinematic"] .vxc-seasonPick__opt.is-active .vxc-seasonPick__tick {
  opacity: 1;
}

/* ---- Phones: the same dropdown, one step tighter ------------------------
   Pinned to the field's width (the base rule) and to its leading edge, so
   the open panel and the closed field are one column — the shape the
   reference app uses. Nothing here is allowed to widen the panel. */
@media (max-width: 991.98px) {
  body[data-layout="cinematic"] .vxc-seasonPick__field {
    height: 42px;
    min-width: 168px;
    font-size: 14px;
  }
  body[data-layout="cinematic"] .vxc-seasonPick__menu {
    top: calc(100% + 6px);
    /* enough for ~5 rows before it scrolls, so the panel never swallows
       the episode row behind it */
    max-height: 252px;
    padding: 5px;
    border-radius: 10px;
  }
  /* 46px rows — a real touch target, which the 32px pill never was */
  body[data-layout="cinematic"] .vxc-seasonPick__opt {
    min-height: 46px;
    gap: 8px;
    padding: 8px 10px;
  }
  body[data-layout="cinematic"] .vxc-seasonPick__optName {
    font-size: 14px;
  }
  body[data-layout="cinematic"] .vxc-seasonPick__optMeta {
    font-size: 11.5px;
  }
  body[data-layout="cinematic"] .vxc-seasonPick__tick {
    width: 16px;
    height: 16px;
  }
}

/* ---- Desktop: a touch more room ------------------------------------------ */
@media (min-width: 992px) {
  body[data-layout="cinematic"] .vxc-seasonPick__field {
    min-width: 200px;
    height: 46px;
    padding: 0 16px 0 18px;
  }
  /* Width comes from the base rule — the panel is the field, exactly, on
     every screen. It was briefly allowed to grow to its content here, and
     the result read as a loose slab hanging past the field's right edge
     rather than as one column. Desktop only gets more height. */
  body[data-layout="cinematic"] .vxc-seasonPick__menu {
    max-height: 340px;
  }
}

@media (prefers-reduced-motion: reduce) {
  body[data-layout="cinematic"] .vxc-seasonPick__menu,
  body[data-layout="cinematic"] .vxc-seasonPick__scrim {
    animation: none !important;
  }
  body[data-layout="cinematic"] .vxc-seasonPick__caret {
    transition: none !important;
  }
}
