/* Mobile-only sideways carousel — paired with cards-rail.js.
   Replaces the old swipeable card stack (cards-stack.*), and modelled on
   the Blocks section of the Wabi testsite (miniapps.joonas.wtf/testsite):
   a horizontal rail of cards, each with its own caption under it, that
   the browser's own scroll-snap settles one card at a time.

   Two things make it read as a carousel rather than a scrolling row:
     · the rail is FULL-BLEED and runs off both edges, so the neighbouring
       cards are visibly there — that is what says there is more of it;
     · the inline padding is half the viewport minus half a card, so the
       FIRST and LAST cards can reach the middle too. Without that they
       have nowhere to scroll to and sit against the edges while only the
       middle ones snap. */

.cards-rail {
  position: relative;
  /* Generous air top + bottom so the rail reads as its own section
     rather than something crammed between two paragraphs. Matches the
     rhythm the stack had. */
  margin: 56px 0 88px;
  /* Full-bleed out of the padded, centred hero column. `.hero-line` is
     viewport-centred, so 50% of it IS the middle of the screen and this
     lays exactly 100vw across it.
     ⚠ AFTER the `margin` shorthand, never before — a shorthand later in
     the block would reset the inline margins back to 0. */
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  z-index: 2;
  /* The one width every other length here is a share of. */
  --card-w: min(330px, 84vw);
  /* Per-rail aspect, set by the caller (work is 4:3, experiments 4:5). */
  --card-aspect: 4 / 5;
  --rail-gap: clamp(14px, 4vw, 22px);
}

.cards-rail-track {
  display: flex;
  align-items: flex-start;
  gap: var(--rail-gap);
  overflow-x: auto;
  /* Hidden, or a tall caption would give the rail its own vertical
     scroll. The cost is that the cards' shadows are cropped at the
     track's edge, which the padding below pays for. */
  overflow-y: hidden;
  /* `mandatory` is what makes a flick settle on the NEXT card instead of
     sliding past two; `center` needs the inline padding below to be able
     to bring the first and last card to the middle at all. */
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  padding: 16px calc((100vw - var(--card-w)) / 2) 10px;
  /* The scrollbar is the browser's answer to a question the rail already
     answers by running off both edges. */
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
}
.cards-rail-track::-webkit-scrollbar { display: none; }
.cards-rail-track:active { cursor: grabbing; }

.cards-rail-item {
  flex: 0 0 auto;
  width: var(--card-w);
  display: flex;
  flex-direction: column;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}

/* ── The card ──────────────────────────────────────────────────────
   Whatever the caller's markup looked like in fan mode (.fan-card, which
   is absolutely positioned and carries its own translate/rotate driven
   by the desktop scroll-progress var), the rail puts it back IN FLOW at
   the item's full width. The !important flags are aimed at exactly those
   fan-mode layout properties and nothing else. */
.cards-rail .rail-card {
  position: relative !important;
  top: auto !important;
  left: auto !important;
  width: 100% !important;
  height: auto !important;
  aspect-ratio: var(--card-aspect);
  margin: 0 !important;
  /* Cancel the longhand translate/rotate/scale the fan rule applies —
     they compose with `transform` and would re-offset every card. */
  translate: none !important;
  rotate: none !important;
  scale: none !important;
  transform: none !important;
  opacity: 1 !important;
  transition: none !important;
  display: block;
  text-decoration: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* Belt and braces with `draggable = false` in the JS — a card is a
     link, and a link is draggable by default under a mouse. */
  -webkit-user-drag: none;
  outline: none;
}

/* The in-card frame fills the new box. The shadow stack is the site's
   signature depth: a soft outer drop + a darker top-left inset highlight
   and a faint bottom-right counter — that asymmetry is what makes a card
   read as a slightly-recessed pane rather than a flat rectangle.
   Background-image is painted by the caller once meta.json resolves, so
   the poster is on screen before the <video> negotiates its first frame. */
.cards-rail .fan-card-frame {
  background: transparent;
  background-size: cover;
  background-position: center;
  /* ⚠ !important AND a literal: the fan's own radius is
     `calc(64px - 44px * var(--p))`, and --p does not exist outside the
     desktop scroll engine, so that declaration is invalid at
     computed-value time and the corners come out square. */
  border-radius: clamp(20px, 5vw, 28px) !important;
  inset: 0 !important;
  box-shadow:
    inset 0 0 0 1px rgba(25, 25, 25, 0.06),
    0 22px 44px -20px rgba(0, 0, 0, 0.22),
    0 4px 12px -4px rgba(0, 0, 0, 0.06) !important;
}
/* Second inset layer drawn ON TOP of the media — a single inset on the
   frame would be hidden by the absolutely-positioned img/video under it.
   pointer-events:none so it doesn't eat the tap. */
.cards-rail .fan-card-frame::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow:
    -2px -2px 2px 0 rgba(0, 0, 0, 0.20) inset,
    2px 2px 2px 0 rgba(0, 0, 0, 0.03) inset;
  pointer-events: none;
  z-index: 3;
}
/* The fan fades media in only at the very end of its unfurl
   (`calc((var(--p) - 0.85) * 6.667)`), which is meaningless here. */
.cards-rail .fan-card-img .fan-card-media { opacity: 1 !important; }

/* The per-card meta is the rail's own caption (below), not the fan's. */
.cards-rail .fan-card-meta { display: none !important; }

/* The "See more" card in experiments carries its own content block. */
.cards-rail .fan-card-see-more {
  display: flex !important;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
  height: 100%;
}

/* ── Caption ───────────────────────────────────────────────────────
   Under its own card, left-aligned, so a card reads as a picture and
   then its words. The height is RESERVED — a one-line title next to a
   two-line one would otherwise leave the rail's cards sitting at
   different depths on the page. */
.cards-rail-cap {
  margin-top: 14px;
  padding-inline: 2px;
  min-height: 62px;
  /* ⚠ Explicit — the hero column this rail lives inside is centred type,
     so the caption inherits `center` and floats free of its own card. The
     card's left edge is the axis a rail reads along. */
  text-align: left;
}
.cards-rail-cap-title {
  font-family: 'Edict Display', Georgia, serif;
  font-weight: 400;
  font-size: 19px;
  line-height: 1.22;
  letter-spacing: -0.012em;
  color: #1a1a2e;
  margin: 0;
  /* Long work titles would otherwise run to four lines and break the
     reserved height. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cards-rail-cap-sub {
  font-family: 'Inter', sans-serif;
  font-weight: 400;
  font-size: 13.5px;
  letter-spacing: -0.005em;
  color: rgba(26, 26, 46, 0.6);
  margin: 5px 0 0;
}
