/* coverflow — a wall of media lanes on a cylindrical curve. TWO RENDERS, ONE
 * MARKUP: flat is the composed grid and the scripts-off render; band applies
 * only under data-coverflow="on", which the section's script stamps. The
 * engine writes the per-tile curve on the MEDIA, never the cell, whose
 * transform belongs to the entrance part. Geometry only. */

/* A cell that IS an anchor: block posture, no underline. */
.sk-coverflow-cell {
  display: block;
  position: relative;
  text-decoration: none;
  color: inherit;
}

/* Sheds the scaffold's block padding, at slideshow's (0,2,0) rank. */
.sk-component[data-sk="coverflow"] {
  padding-block: 0;
}

.sk-coverflow {
  /* Lane gutter — fixed --kit-space scale (gutters don't ride Density). */
  --sk-coverflow-gap: var(--kit-space-4);
  /* Marquee pace: seconds per tile pitch. */
  --sk-coverflow-beat: 3;
  /* One shape dial, the half-angle at the band edge; the radius and so the
     * recede are derived from it, never a second dial. Perspective is the
     * independent axis and sits on the BAND so every row shares one eye. */
  --sk-coverflow-curve-deg: 16;
  --sk-coverflow-perspective: 1400px;
  /* +1 seats tiles on the inner face, -1 flips the drum. Same radius. */
  --sk-coverflow-curve-sign: 1;
  /* A grabbed lane tightens around the same axis, so the same drag sweeps
     * further around it. */
  --sk-coverflow-drag-radius: 0.68;
  /* Two halves, because the ends need both. --edge-fade is a MASK over the page
     * edge. --dissolve fades a tile as an OBJECT and is what stops a loop reading
     * as a teleport: a mask alone goes transparent at a tile's leading edge while
     * the rest is still solid. The Edge Fade control moves the mask only, so the
     * dissolve is always on. */
  --sk-coverflow-edge-fade: 7%;
  --sk-coverflow-dissolve: 0.35;
  /* How far the picture may slide inside its frame, as a percentage of it. The
     * zoom is the material that slide consumes. */
  --sk-coverflow-portal: 0;
  --sk-coverflow-portal-zoom: 1;
  --sk-coverflow-media-radius: var(--sk-media-radius);
  /* Room for the cylinder's projected bleed so the section crop never bites a
     * tile. Zero when flat. */
  --sk-coverflow-safe: 0;
  /* Base tile ratio (+ its w/h number, for content-height lane math). */
  --sk-coverflow-aspect: 3 / 4;
  --sk-coverflow-ratio: 0.75;
  /* A drag surface: a selection swept in from outside would paint across the
     * tiles and stick. Nothing here is text worth selecting. */
  -webkit-user-select: none;
  user-select: none;
}
.sk-coverflow[data-gap="none"] {
  --sk-coverflow-gap: 0px;
}
.sk-coverflow[data-gap="tight"] {
  --sk-coverflow-gap: var(--kit-space-2);
}
.sk-coverflow[data-gap="airy"] {
  --sk-coverflow-gap: var(--kit-space-5);
}
.sk-coverflow[data-speed="slow"] {
  --sk-coverflow-beat: 5;
}
.sk-coverflow[data-speed="fast"] {
  --sk-coverflow-beat: 1.5;
}
.sk-coverflow[data-curve="none"] {
  --sk-coverflow-curve-deg: 0;
}
/* A tighter radius seen from far away flattens back out. */
.sk-coverflow[data-curve="deep"] {
  --sk-coverflow-curve-deg: 30;
  --sk-coverflow-perspective: 1000px;
}
.sk-coverflow[data-curve-facing="outward"] {
  --sk-coverflow-curve-sign: -1;
}
.sk-coverflow[data-corners="small"] {
  --sk-coverflow-media-radius: 0.5rem;
}
.sk-coverflow[data-corners="large"] {
  --sk-coverflow-media-radius: 1.25rem;
}
/* Outward needs more: tiles grow past the band plane. */
.sk-coverflow[data-coverflow="on"]:not([data-curve="none"]) {
  --sk-coverflow-safe: clamp(1.25rem, 3vh, 2rem);
}
.sk-coverflow[data-coverflow="on"][data-curve="deep"] {
  --sk-coverflow-safe: clamp(1.75rem, 4.5vh, 2.75rem);
}
.sk-coverflow[data-coverflow="on"]:not([data-curve="none"])[data-curve-facing="outward"] {
  --sk-coverflow-safe: clamp(3rem, 10vh, 6rem);
}
.sk-coverflow[data-coverflow="on"][data-curve="deep"][data-curve-facing="outward"] {
  --sk-coverflow-safe: clamp(4rem, 14vh, 8rem);
}
.sk-coverflow[data-parallax="subtle"] {
  --sk-coverflow-portal: 10;
  --sk-coverflow-portal-zoom: 1.2;
}
.sk-coverflow[data-parallax="deep"] {
  --sk-coverflow-portal: 40;
  --sk-coverflow-portal-zoom: 1.8;
}
.sk-coverflow[data-edge-fade="small"] {
  --sk-coverflow-edge-fade: 3%;
}
.sk-coverflow[data-edge-fade="large"] {
  --sk-coverflow-edge-fade: 14%;
}
.sk-coverflow[data-aspect="1:1"] {
  --sk-coverflow-aspect: 1 / 1;
  --sk-coverflow-ratio: 1;
}
.sk-coverflow[data-aspect="3:2"] {
  --sk-coverflow-aspect: 3 / 2;
  --sk-coverflow-ratio: 1.5;
}
.sk-coverflow[data-aspect="2:3"] {
  --sk-coverflow-aspect: 2 / 3;
  --sk-coverflow-ratio: 0.6667;
}
.sk-coverflow[data-aspect="4:3"] {
  --sk-coverflow-aspect: 4 / 3;
  --sk-coverflow-ratio: 1.3333;
}
.sk-coverflow[data-aspect="16:9"] {
  --sk-coverflow-aspect: 16 / 9;
  --sk-coverflow-ratio: 1.7778;
}
/* The cross-axis seat of a mixed-ratio tile inside its lane. */
.sk-coverflow[data-valign="top"] {
  --sk-coverflow-valign: flex-start;
}
.sk-coverflow[data-valign="center"] {
  --sk-coverflow-valign: center;
}
.sk-coverflow[data-valign="bottom"] {
  --sk-coverflow-valign: flex-end;
}

/* ── FLAT — the composed fallback grid. A shared .sk-cell-grid; only the
 * --sk-columns-fit seam is re-declared, which the BAND reads for tile pitch. */
.sk-coverflow .sk-coverflow-cells {
  --sk-columns-fit: var(--sk-columns, 4);
  gap: var(--sk-coverflow-gap);
}
@media (max-width: 1200px) {
  .sk-coverflow .sk-coverflow-cells {
    --sk-columns-fit: min(var(--sk-columns, 4), 4);
  }
}
@media (max-width: 900px) {
  .sk-coverflow .sk-coverflow-cells {
    --sk-columns-fit: min(var(--sk-columns, 4), 3);
  }
}
@media (max-width: 560px) {
  .sk-coverflow .sk-coverflow-cells {
    --sk-columns-fit: min(var(--sk-columns, 4), 2);
  }
}

/* Only the INSIDE offset is coverflow's: cells sit flush in a clipped lane,
 * so an outside ring would be cropped. */
.sk-coverflow-cell {
  --sk-focus-ring-offset: -2px;
}

.sk-coverflow-media {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--sk-surface);
  aspect-ratio: var(--sk-coverflow-aspect);
  border-radius: var(--sk-coverflow-media-radius);
}
.sk-coverflow-media .sk-art {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--sk-focal-x, 50%) var(--sk-focal-y, 50%);
}
/* Presence-keyed on the item and EXCLUDING auto, whose row value must keep the
 * section's base var. :where() keeps the per-value rank. */
.sk-coverflow-media[data-aspect]:where(:not([data-aspect="auto"], [data-aspect=""])) {
  aspect-ratio: var(--sk-aspect);
}

/* ── BAND — everything below is gated on data-coverflow="on", which only the
 * section's script stamps, so scripts-off and print never see it. ── */

.sk-coverflow[data-coverflow="on"] .sk-coverflow-inner {
  /* The gradient paints MASK ALPHA, not pixels — --sk-ink is just an opaque
     * stop. Cross-axis SAFE sits inside the clip. */
  padding-inline: 0;
  padding-block: 0;
  overflow: hidden;
  box-sizing: border-box;
  /* ONE gradient, angle-parameterized, so the stops cannot drift between the two
     * orientations. The -webkit- twin must stay: Safari still prefixes it. */
  -webkit-mask-image: linear-gradient(
    var(--sk-coverflow-fade-angle, 90deg),
    transparent 0,
    var(--sk-ink) var(--sk-coverflow-edge-fade),
    var(--sk-ink) calc(100% - var(--sk-coverflow-edge-fade)),
    transparent 100%
  );
  mask-image: linear-gradient(
    var(--sk-coverflow-fade-angle, 90deg),
    transparent 0,
    var(--sk-ink) var(--sk-coverflow-edge-fade),
    var(--sk-ink) calc(100% - var(--sk-coverflow-edge-fade)),
    transparent 100%
  );
}
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-inner {
  --sk-coverflow-fade-angle: 90deg;
  padding-block: var(--sk-coverflow-safe);
  padding-inline: 0;
}
.sk-coverflow[data-coverflow="on"][data-orientation="vertical"] .sk-coverflow-inner {
  --sk-coverflow-fade-angle: 180deg;
  padding-inline: var(--sk-coverflow-safe);
  padding-block: 0;
}
.sk-coverflow[data-coverflow="on"][data-edge-fade="none"] .sk-coverflow-inner {
  -webkit-mask-image: none;
  mask-image: none;
}
/* Vertical keeps its clamp so the section still stacks. Excluded rather than
   * out-ranked, so the row scope stays one selector. */
.sk-section:is([data-height="full"], [data-height="custom"])
  .sk-coverflow[data-coverflow="on"]:not([data-orientation="vertical"])
  .sk-coverflow-inner {
  height: var(--sk-band-stage);
}
.sk-coverflow[data-coverflow="on"][data-orientation="vertical"] .sk-coverflow-inner {
  height: var(--sk-coverflow-h, clamp(28rem, 55vw, 40rem));
}

/* The cells container becomes the lane stack. It KEEPS .sk-cell-grid, so the
 * fit-ladder seam above still resolves — the band's tile width reads it. */
.sk-coverflow[data-coverflow="on"] .sk-coverflow-cells {
  display: flex;
  gap: var(--sk-coverflow-gap);
  height: 100%;
  --sk-coverflow-cols: var(--sk-columns-fit, var(--sk-columns, 4));
}
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-cells {
  flex-direction: column;
  /* Tile pitch: N tiles visible across the bleed, N−1 interior gutters.
   * UNIFORM on the drag axis — the invariant the curve arithmetic rides. */
  --sk-coverflow-tile: calc(
    (100vw - (var(--sk-coverflow-cols) - 1) * var(--sk-coverflow-gap)) / var(--sk-coverflow-cols)
  );
}
.sk-coverflow[data-coverflow="on"][data-orientation="vertical"] .sk-coverflow-cells {
  flex-direction: row;
  --sk-coverflow-tile: calc(
    (100svh - (var(--sk-rows, 2) - 1) * var(--sk-coverflow-gap)) / var(--sk-rows, 2)
  );
}
/* Stated plainly rather than as a negation: an ancestor negation would also
   * catch the armed state. */
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-cells {
  height: auto;
}
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-lane {
  flex: none;
  height: calc(var(--sk-coverflow-tile) / var(--sk-coverflow-ratio));
}
/* The stage arm above sizes .sk-coverflow-inner alone, so the lanes need their
   * own height or a full-height band leaves them short. */
.sk-section:is([data-height="full"], [data-height="custom"])
  .sk-coverflow[data-coverflow="on"][data-orientation="horizontal"]
  .sk-coverflow-cells {
  height: 100%;
}
.sk-section:is([data-height="full"], [data-height="custom"])
  .sk-coverflow[data-coverflow="on"][data-orientation="horizontal"]
  .sk-coverflow-lane {
  flex: 1;
  height: auto;
}

/* touch-action: pan-y is the scroll-trap covenant: a touch swipe down is
   * ALWAYS the page's. */
/* THE LANE DOES NOT CLIP — .sk-coverflow-inner does, for all of them. A track
 * running out leaves the inner box at the same moment, where its overflow
 * already cuts it. A per-lane clip also bites off a receding row's overhang
 * and seals each lane into its own 3D context, where overlapping rows have no
 * shared depth and the wrong one can paint in front. */
.sk-coverflow-lane {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 0;
  touch-action: pan-y;
  cursor: grab;
}
/* ONE DRUM, ONE VIEWER. Perspective belongs to the BAND, not to a lane and not
 * to each tile: per-tile `perspective()` gives every tile its own vanishing
 * point, and a per-lane one gives every row its own eye and its own 3D context.
 * The cost is the preserve-3d chain below, which must stay UNBROKEN from lane
 * to media — any grouping property (overflow, opacity < 1, filter, mask,
 * clip-path) on track/seq/cell flattens the tiles back into the lane plane and
 * silently restores that look. It stays on even when Curve is none: hover tilt
 * needs a 3D eye, and without one the tilt reads as a sheer. */
.sk-coverflow[data-coverflow="on"] .sk-coverflow-cells {
  perspective: var(--sk-coverflow-perspective);
  perspective-origin: 50% 50%;
}
.sk-coverflow[data-coverflow="on"] .sk-coverflow-lane,
.sk-coverflow[data-coverflow="on"] .sk-coverflow-track,
.sk-coverflow[data-coverflow="on"] .sk-coverflow-seq,
.sk-coverflow[data-coverflow="on"] .sk-coverflow-cell {
  transform-style: preserve-3d;
}
.sk-coverflow-lane[data-dragging] {
  cursor: grabbing;
}
/* The track's children are whole PERIODS, not tiles, so it adds no gutter of
 * its own: the engine wraps by the sequence's size, and a gutter here would
 * push the next copy past the wrap distance and snap back every loop. The
 * gutter lives in ONE place, the sequence's trailing padding. */
.sk-coverflow-track {
  display: flex;
  gap: 0;
  will-change: transform;
}
.sk-coverflow-seq {
  display: flex;
  gap: var(--sk-coverflow-gap);
}
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-track {
  width: max-content;
  height: 100%;
}
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-seq {
  height: 100%;
  /* The wrap seam matches the gutter, so the loop point reads like any
   * other gap. */
  padding-inline-end: var(--sk-coverflow-gap);
}
.sk-coverflow[data-coverflow="on"][data-orientation="vertical"] .sk-coverflow-track {
  flex-direction: column;
  height: max-content;
  width: 100%;
}
.sk-coverflow[data-coverflow="on"][data-orientation="vertical"] .sk-coverflow-seq {
  flex-direction: column;
  width: 100%;
  padding-block-end: var(--sk-coverflow-gap);
}

/* The cell is a flex seat: uniform on the drag axis, the media inside varies
   * on the cross axis and sits per valign. */
.sk-coverflow[data-coverflow="on"] .sk-coverflow-cell {
  flex: none;
  display: flex;
}
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-cell {
  width: var(--sk-coverflow-tile);
  height: 100%;
  align-items: var(--sk-coverflow-valign, center);
}
.sk-coverflow[data-coverflow="on"][data-orientation="vertical"] .sk-coverflow-cell {
  height: var(--sk-coverflow-tile);
  width: 100%;
  justify-content: var(--sk-coverflow-valign, center);
}
.sk-coverflow[data-coverflow="on"][data-orientation="horizontal"] .sk-coverflow-media {
  width: 100%;
  height: auto;
  max-height: 100%;
}
.sk-coverflow[data-coverflow="on"][data-orientation="vertical"] .sk-coverflow-media {
  height: 100%;
  width: auto;
  max-width: 100%;
}
/* The engine writes opacity every frame, and transform whenever a curve or
 * hover tilt/magnet is live — promote both on the band. */
.sk-coverflow[data-coverflow="on"] .sk-coverflow-media {
  will-change: transform, opacity;
}

/* PARALLAX PORTAL. The engine writes --sk-cf-portal per tile: how far the
 * picture has slid inside its frame, in percent, along the drag axis.
 * Percentages in translate resolve against the UNTRANSFORMED box, so the
 * excursion stays honest whatever the zoom is, and zoom = 1 + 2 x excursion is
 * what keeps the crop inside the picture. Scoped to a live curve: an always-on
 * transform would promote a layer per tile for nothing. */
.sk-coverflow[data-coverflow="on"]:not([data-curve="none"]):not([data-parallax="none"])
  .sk-coverflow-media
  .sk-art {
  will-change: transform;
}
.sk-coverflow[data-coverflow="on"]:not([data-curve="none"]):not(
    [data-parallax="none"]
  )[data-orientation="horizontal"]
  .sk-coverflow-media
  .sk-art {
  transform: translate3d(var(--sk-cf-portal, 0%), 0, 0) scale(var(--sk-coverflow-portal-zoom));
}
.sk-coverflow[data-coverflow="on"]:not([data-curve="none"]):not(
    [data-parallax="none"]
  )[data-orientation="vertical"]
  .sk-coverflow-media
  .sk-art {
  transform: translate3d(0, var(--sk-cf-portal, 0%), 0) scale(var(--sk-coverflow-portal-zoom));
}
