/* ==========================================================================
   vxg — unified content grid + skeleton for styles/default
   The layout that both the real grid pages and their skeleton loaders share,
   so the placeholders line up with the cards by construction. Column counts
   mirror the swiper breakpoints (2/3/4/5/6/7); orientation (portrait 2:3 vs
   landscape 16:9) is driven by window.vodlixLayout and applied via a modifier
   class. Consumes only --vod-* variables; vodlix.css is untouched.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Grid container — responsive columns matching the swiper breakpoints
   -------------------------------------------------------------------------- */
.vxg {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--vxl-card-gap, 5px);
  /* match the swiper's .insidePadding (3% each side) so skeleton cells sit at
     the same x as the real cards */
  padding-left: var(--vxl-gutter, 3%);
  padding-right: var(--vxl-gutter, 3%);
  margin-bottom: var(--vxl-section-gap, 24px);
}
@media (max-width: 619.98px) { .vxg.vxg--landscape { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 620px)  { .vxg { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 768px)  { .vxg { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1040px) { .vxg { grid-template-columns: repeat(5, 1fr); } }
@media (min-width: 1200px) { .vxg { grid-template-columns: repeat(6, 1fr); } }
@media (min-width: 1450px) { .vxg { grid-template-columns: repeat(7, 1fr); } }

/* Density column maps — ⚠ these mirror the density words' rail deltas in
   block/_layout_resolver.html (spacious = one card fewer); change both or
   skeletons drift from the content. The base rules above ARE the
   comfortable map. */
@media (min-width: 620px)  { body[data-lo-rail-density="spacious"] .vxg { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 768px)  { body[data-lo-rail-density="spacious"] .vxg { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1040px) { body[data-lo-rail-density="spacious"] .vxg { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1200px) { body[data-lo-rail-density="spacious"] .vxg { grid-template-columns: repeat(5, 1fr); } }

/* --------------------------------------------------------------------------
   Skeleton hero — the editors-pick banner. Contained (inset + rounded, not
   edge-to-edge) with a bounded height so it reads as a hero placeholder, not a
   giant blank rectangle, and a bottom margin so it never overlaps the row
   below. Faint logo + button bars echo the real hero's overlay.
   -------------------------------------------------------------------------- */
.vxg-hero {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  /* full-bleed like the real editors-pick hero, pulled up behind the header the
     same way .featureSlider is (margin-top: -6rem); bottom margin keeps it off
     the first row. Height is a touch shorter than a full 16:9 so the empty area
     below the placeholder content isn't overbearing before the first row. */
  margin: -6rem 0 28px;
  height: clamp(340px, 50vw, 720px);
  background-color: var(--vod-menu-bg);
}
@media (max-width: 767px) {
  .vxg-hero {
    margin-top: -3rem;
  }
}
/* full-screen hero (view_type 2/3) — fills the viewport minus the header on
   desktop, matching .featureSlider.heroimage */
.vxg-hero--full {
  aspect-ratio: 16 / 9;
}
@media (min-width: 992px) {
  .vxg-hero--full {
    aspect-ratio: auto;
    height: calc(100vh - 64px);
  }
}
.vxg-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--vod-white-color, #fff) 7%, transparent), transparent);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--vod-white-color) 7%, transparent), transparent);
  animation: vxs-shimmer 1.4s ease-in-out infinite;
}
.vxg-hero__meta {
  position: relative;
  z-index: 1;
  padding: 0 0 clamp(22px, 4vw, 44px) clamp(24px, 4vw, 48px);
}
.vxg-hero__logo {
  width: clamp(170px, 24vw, 300px);
  height: clamp(26px, 3.6vw, 42px);
  margin-bottom: 16px;
  border-radius: 6px;
  background-color: color-mix(in srgb, var(--vod-white-color, #fff) 10%, transparent);
  background-color: color-mix(in srgb, var(--vod-white-color) 10%, transparent);
}
.vxg-hero__btns {
  display: flex;
  gap: 10px;
}
.vxg-hero__btn {
  width: clamp(92px, 11vw, 132px);
  height: clamp(32px, 3.6vw, 42px);
  border-radius: 6px;
  background-color: color-mix(in srgb, var(--vod-white-color, #fff) 10%, transparent);
  background-color: color-mix(in srgb, var(--vod-white-color) 10%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .vxg-hero::after { animation: none; }
}

/* Content-list-group hero placeholder: shown until the editors-pick hero
   reveals itself (its own JS drops `.d-none` on `.featureSlider`) or the EP
   resolves empty (`body.notEditorPick`). Wrapped so it doesn't disturb the
   `.featureSlider + .overLapEditor` adjacency the group page relies on. */
.clg-hero-ph:has(+ .featureSlider:not(.d-none)),
body.notEditorPick .clg-hero-ph {
  display: none;
}
/* While the hero is still a skeleton (real hero hidden), the rails sit BELOW
   it instead of overlapping — the -13vw pull (`.featureSlider + .overLapEditor`)
   only makes sense once the real editors-pick hero is showing. The extra
   `.d-none` outranks every responsive variant of that rule (all 0,2,0), so no
   !important is needed and the empty-EP `notEditorPick` rule stays in charge. */
.featureSlider.d-none + .overLapEditor {
  margin-top: 0;
}

/* --------------------------------------------------------------------------
   Skeleton rail — a row heading + one horizontal strip of cells, matching the
   home/movies/tv-shows swiper rows. Columns per view mirror the swiper
   breakpoints; extra cells overflow off the right like the real rail.
   -------------------------------------------------------------------------- */
.vxg-rail {
  padding-left: var(--vxl-gutter, 3%);
  padding-right: var(--vxl-gutter, 3%);
  margin-bottom: var(--vxl-section-gap, 28px);
}
.vxg-rail__title {
  position: relative;
  overflow: hidden;
  width: 190px;
  max-width: 45%;
  height: 20px;
  margin-bottom: 12px;
  border-radius: 6px;
  background-color: var(--vod-menu-bg);
}
.vxg-rail__row {
  display: flex;
  gap: var(--vxl-card-gap, 5px);
  overflow: hidden;
}
/* one cell per column-slot; width tracks the swiper's slidesPerView so the
   strip shows the same number of cards as the real rail */
.vxg-rail__row .vxg-cell {
  flex: 0 0 calc(100% / 2 - var(--vxl-card-gap, 5px));
}
@media (min-width: 620px)  { .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 3 - var(--vxl-card-gap, 5px)); } }
@media (min-width: 768px)  { .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 4 - var(--vxl-card-gap, 5px)); } }
@media (min-width: 1040px) { .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 5 - var(--vxl-card-gap, 5px)); } }
@media (min-width: 1200px) { .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 6 - var(--vxl-card-gap, 5px)); } }
@media (min-width: 1450px) { .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 7 - var(--vxl-card-gap, 5px)); } }

/* Spacious rail-skeleton cells — same mirror as the .vxg overrides above;
   the rails run one slide sparser (DELTAS), which these counts absorb. */
body[data-lo-rail-density="spacious"] .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 2 - var(--vxl-card-gap, 5px)); }
@media (min-width: 768px)  { body[data-lo-rail-density="spacious"] .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 3 - var(--vxl-card-gap, 5px)); } }
@media (min-width: 1040px) { body[data-lo-rail-density="spacious"] .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 4 - var(--vxl-card-gap, 5px)); } }
@media (min-width: 1200px) { body[data-lo-rail-density="spacious"] .vxg-rail__row .vxg-cell { flex-basis: calc(100% / 5 - var(--vxl-card-gap, 5px)); } }

.vxg-rail__title::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--vod-white-color, #fff) 7%, transparent), transparent);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--vod-white-color) 7%, transparent), transparent);
  animation: vxs-shimmer 1.4s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .vxg-rail__title::after { animation: none; }
}

/* --------------------------------------------------------------------------
   Skeleton cells — orientation-aware, shimmer shared with the vxs system
   -------------------------------------------------------------------------- */
.vxg-cell {
  position: relative;
  overflow: hidden;
  border-radius: var(--vxl-card-radius, 6px);
  background-color: var(--vod-menu-bg);
}
/* portrait (9:16 — the platform's portrait art standard, see cards.css
   portrait-ratio note) is the default; .vxg--landscape swaps to 16:9 */
.vxg-cell {
  aspect-ratio: 9 / 16;
}
.vxg--landscape .vxg-cell {
  aspect-ratio: 16 / 9;
}
/* top-10 aspect variants — match the real slide geometry in cards.css
   (card at 55%/72% of the slide, 9:16 / 16:9) */
.vxg--top10-portrait .vxg-cell {
  aspect-ratio: 1 / 0.978;
}
.vxg--top10-landscape .vxg-cell {
  aspect-ratio: 1 / 0.405;
}
/* flat info-card variant (e.g. bundles) — fixed height, not a poster aspect */
.vxg-cell--flat {
  aspect-ratio: auto;
  height: 88px;
}

.vxg-cell::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--vod-white-color, #fff) 7%, transparent), transparent);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--vod-white-color) 7%, transparent), transparent);
  animation: vxs-shimmer 1.4s ease-in-out infinite;
}
/* vxs-shimmer keyframes live in cards.css (loaded first); no need to redefine */

@media (prefers-reduced-motion: reduce) {
  .vxg-cell::after {
    animation: none;
  }
}

/* ==========================================================================
   vxw — the home wall (arrangement: home_feed="grid").

   One grid of the latest uploads under whatever rows the home page kept
   (block/_home_feed.html). The markup only exists when the word is "grid",
   so nothing here can reach a rails home.

   A cell is a rail slide in everything but name: an aspect-ratio spacer with
   the card absolutely laid over it (.videoBlockDiv). That is what lets the
   dwell panel grow over its neighbours without moving the rows below, and
   why a caption — which hangs under the card — needs its height reserved on
   the cell, exactly as a captioned rail reserves it under the track.

   Columns: 1 on a phone, 2 from 620, 3 from 992, 4 from 1280, 5 from 1920,
   6 from 2560. The column gap follows the density word (--vxl-card-gap) with
   10px added: a rail's 5px seam is fine between stills, but under a wall of
   captions it set one title against the next.
   ========================================================================== */
.vxw {
  padding-left: var(--vxl-gutter, 3%);
  padding-right: var(--vxl-gutter, 3%);
  margin-bottom: var(--vxl-section-gap, 28px);
  --vxw-gap: calc(var(--vxl-card-gap, 5px) + 10px);
}
.vxw__grid {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  column-gap: var(--vxw-gap);
  /* stills alone read as a mosaic: the same seam both ways */
  row-gap: var(--vxw-gap);
}
@media (min-width: 620px)  { .vxw__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 992px)  { .vxw__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .vxw__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1920px) { .vxw__grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (min-width: 2560px) { .vxw__grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
/* rail_density on the wall: dense one column more, spacious one fewer, from
   620 up (a phone stays one card wide either way). The gap alone moved 1px
   between dense and comfortable, so the three words looked the same here. */
@media (min-width: 620px)  { body[data-lo-rail-density="dense"] .vxw__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 992px)  { body[data-lo-rail-density="dense"] .vxw__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1280px) { body[data-lo-rail-density="dense"] .vxw__grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (min-width: 1920px) { body[data-lo-rail-density="dense"] .vxw__grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (min-width: 2560px) { body[data-lo-rail-density="dense"] .vxw__grid { grid-template-columns: repeat(7, minmax(0, 1fr)); } }
@media (min-width: 992px)  { body[data-lo-rail-density="spacious"] .vxw__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1280px) { body[data-lo-rail-density="spacious"] .vxw__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1920px) { body[data-lo-rail-density="spacious"] .vxw__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 2560px) { body[data-lo-rail-density="spacious"] .vxw__grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* The pointed-at cell rises above its neighbours — the next cell in the row
   AND the row beneath, both later in the document. A rail only has to lower
   the one slide that follows (.slideBlock:hover + .swiper-slide). */
.vxw__cell:hover,
.vxw__cell:has(.videoBlock.vxc-open) {
  z-index: 12;
}

/* The dwell panel (card_hover="panel") grows a card by 35% in a rail, where
   a card is ~220px wide: about 39px a side. A wall card is half as wide
   again, and the same 35% threw a 440px panel across its neighbours'
   captions. 1.2 keeps the growth a rail's (~33px a side at 1440). */
.vxw__cell .videoBlock.vxc.vxc-open {
  transform: scale(1.2);
}
/* card_meta="below": reserve the caption — two title lines and a meta line —
   then a row's breath. 24px after a two-line title, 43px after one line. */
.vxw--captioned .vxw__cell {
  padding-bottom: 68px;
}
.vxw--captioned .vxw__grid {
  row-gap: 24px;
}

/* The heading borrows the rail heading's classes for its type; as a holder
   it is only a wrapper, so it drops the rail's own entrance and (on phones)
   its off-screen size estimate — 280px held for a 30px line. */
.vxw__head.swiperHolder {
  animation: none;
  content-visibility: visible;
  contain-intrinsic-size: auto;
}

/* Loading cells: the shared skeleton tile at the wall's shape. */
.vxw__cell--sk .vxg-cell {
  aspect-ratio: 16 / 9;
}
.vxw__retry {
  display: flex;
  justify-content: center;
  padding-top: 24px;
}
/* in flow, zero-height: only a line for the observer to watch */
.vxw__sentinel {
  height: 1px;
}

/* One column (<620px): nothing sits beside a card and there is no dwell
   panel on touch, so the card does not need to float over a spacer at all.
   It goes back into normal flow, the caption with it, and each row is as
   tall as its own text — a fixed two-line reserve left 43px of air under
   every one-line title. Covers the stock phone title too (card_meta
   "hover" still shows it under the card below 576px). */
@media (max-width: 619.98px) {
  .vxw__cell > .ratio {
    display: none;
  }
  .vxw__cell > .videoBlockDiv {
    position: static;
  }
  .vxw--captioned .vxw__cell {
    padding-bottom: 0;
  }
  .vxw--captioned .vxw__grid {
    row-gap: 24px;
  }
  .vxw:not(.vxw--captioned) .vxw__grid {
    row-gap: 16px;
  }
}

/* ==========================================================================
   vxk — category chips (arrangement: category_chips="on", desktop).

   One row above the home page's titles (block/_home_chips.html): "All", then
   the categories. Above the wall a chip filters it in place; above rows a
   chip is a link to that category's page. The markup only exists when the
   word is on, and the row only shows from 992px — phones have their own
   Categories sheet in the pills.

   A chip is a button, so it takes the button word's corners
   (--vxl-btn-radius). Resting chips are a wash of the ink; the chosen one is
   the ink itself with the page colour for its text, which stays legible on
   any palette without naming a colour.
   ========================================================================== */
.vxk {
  display: none;
}
@media (min-width: 992px) {
  .vxk {
    display: block;
    position: relative;
    /* the same layer as a rail (.hoverBlock): under a Full screen hero the
       first row rides up over the hero's foot, and at z-index auto the chips
       were painted beneath it — only their arrow showed */
    z-index: 3;
    min-height: 32px; /* holds the row's place while the categories load */
    margin: 0 var(--vxl-gutter, 3%) 16px;
  }
  /* With chips on, they stand in for the wall's heading — on the screens
     that show chips. A phone has none, so it keeps the heading. */
  .vxw--chips .vxw__head {
    display: none;
  }
  .vxk__track {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
  }
  .vxk__track::-webkit-scrollbar {
    display: none;
  }
  /* the row dissolves under whichever arrow is showing */
  .vxk:not(.is-start) .vxk__track {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 56px);
    mask-image: linear-gradient(to right, transparent 0, #000 56px);
  }
  .vxk:not(.is-end) .vxk__track {
    -webkit-mask-image: linear-gradient(to left, transparent 0, #000 56px);
    mask-image: linear-gradient(to left, transparent 0, #000 56px);
  }
  .vxk:not(.is-start):not(.is-end) .vxk__track {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 56px, #000 calc(100% - 56px), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 56px, #000 calc(100% - 56px), transparent 100%);
  }
  /* right-to-left: the row starts at the right, so the fades swap sides */
  body.rtl .vxk:not(.is-start) .vxk__track {
    -webkit-mask-image: linear-gradient(to left, transparent 0, #000 56px);
    mask-image: linear-gradient(to left, transparent 0, #000 56px);
  }
  body.rtl .vxk:not(.is-end) .vxk__track {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 56px);
    mask-image: linear-gradient(to right, transparent 0, #000 56px);
  }
  body.rtl .vxk:not(.is-start):not(.is-end) .vxk__track {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 56px, #000 calc(100% - 56px), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 56px, #000 calc(100% - 56px), transparent 100%);
  }
  .vxk__chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    height: 32px;
    padding: 0 12px;
    border: 0;
    border-radius: var(--vxl-btn-radius, 8px);
    background-color: color-mix(in srgb, var(--vxl-ink) 10%, transparent);
    color: var(--vxl-ink);
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--vxl-dur-1) var(--vxl-ease),
                color var(--vxl-dur-1) var(--vxl-ease);
  }
  .vxk__chip:hover,
  .vxk__chip:focus-visible {
    background-color: color-mix(in srgb, var(--vxl-ink) 18%, transparent);
    color: var(--vxl-ink);
    text-decoration: none;
  }
  .vxk__chip.is-active,
  .vxk__chip.is-active:hover {
    background-color: var(--vxl-ink);
    color: var(--vod-body-bg);
    font-weight: 600;
    cursor: default;
  }
  .vxk__arrow {
    position: absolute;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background-color: var(--vod-body-bg);
    color: var(--vxl-ink);
    cursor: pointer;
    transition: background-color var(--vxl-dur-1) var(--vxl-ease);
  }
  .vxk__arrow:hover {
    background-color: color-mix(in srgb, var(--vxl-ink) 14%, var(--vod-body-bg));
  }
  .vxk__arrow--prev {
    inset-inline-start: 0;
  }
  .vxk__arrow--next {
    inset-inline-end: 0;
  }
  .vxk__arrow .vxm-ico {
    width: 18px;
    height: 18px;
  }
  body.rtl .vxk__arrow .vxm-ico {
    transform: scaleX(-1);
  }
}
@media (min-width: 992px) and (prefers-reduced-motion: reduce) {
  .vxk__chip,
  .vxk__arrow {
    transition: none;
  }
}
