/* ═══════════════════════════════════════════════════════════════
   SWIPER-N — CSS-first carousel
   Scroll-snap positioning, container-query responsive,
   JS-stamped pagination dots + prev/next paddles.

   Structure (JS-stamped):
     swiper-ui                    ← flex column wrapper
       [data-swiper-track]       ← grid scroll container
         <slide children>
       [data-swiper-dots]        ← pagination dots (below track)
       [data-swiper-btn prev]    ← absolute left paddle
       [data-swiper-btn next]    ← absolute right paddle

   Native ::scroll-marker / ::scroll-button is Chrome-135-only and
   not yet on Safari/Firefox roadmaps. Until cross-engine, JS-stamped
   dots are the single source of pagination UI; re-introduce native
   paths gated on CSS.supports('selector(::scroll-marker)') when both
   other engines ship.
   ═══════════════════════════════════════════════════════════════ */

@scope (swiper-ui) {
  :where(:scope) {
    /* ── Layout ── */
    --swiper-gap:           var(--a-gap-self, var(--a-gap));
    --swiper-peek:          var(--a-space-8);
    --swiper-snap:          start;
    --swiper-columns:       1;

    /* ── Pagination dots ── */
    /* Component-intrinsic visual constant; no --a-space-* equivalent */
    --swiper-dot-size:        6px;
    /* Active dot is one space token (4px @ density=1) larger than the
       inactive dot — small, deliberate emphasis without rearranging
       the row. The hitbox stays at 1rem; only the visible circle grows. */
    --swiper-dot-size-active: calc(var(--swiper-dot-size) + var(--a-space-1));
    --swiper-dot-gap:         var(--a-space-2);
    --swiper-dot-bg:          var(--a-border);
    --swiper-dot-bg-active:   var(--a-fg);
    --swiper-dot-radius:      var(--a-radius-full);

    /* ── Host vertical rhythm ── */
    --swiper-gap-vertical:  var(--a-space-3);

    /* ── Paddle bottom offset ── */
    --swiper-btn-bottom:    var(--a-space-3);

    /* ── Autoplay pause button offset ── */
    --swiper-pause-top:     var(--a-space-2);
    --swiper-pause-right:   var(--a-space-2);

    /* ── Paddles ── */
    --swiper-btn-size:      3rem;
    --swiper-btn-bg:        transparent;
    --swiper-btn-bg-hover:  var(--a-bg-muted);
    --swiper-btn-fg:        var(--a-fg);
    --swiper-btn-radius:    var(--a-radius-full);
    --swiper-btn-shadow:    none;
    --swiper-btn-offset:    var(--a-space-2);

    /* ── Motion ── */
    --swiper-duration:      var(--a-duration);
    --swiper-easing:        var(--a-easing);
  }

  /* ── Host: flex column so dots sit below the scroll track ── */

  :scope {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: var(--swiper-gap-vertical);
    width: 100%;
    position: relative;
    /* Host is the container so @container queries below read the
       swiper's own width, not a wider ancestor's. Named to avoid
       collision with any ancestor that also queries by size. */
    container-type: inline-size;
    container-name: swiper;
  }

  /* ── Scroll track (JS wraps slides into this) ── */

  :scope > [data-swiper-track] {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc(
      (100% - (var(--swiper-columns) - 1) * var(--swiper-gap)) / var(--swiper-columns)
    );
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    gap: var(--swiper-gap);
  }

  :scope > [data-swiper-track]::-webkit-scrollbar { display: none; }

  /* Click-and-drag affordance for cursor users — touch keeps native pan. */
  @media (hover: hover) {
    :scope > [data-swiper-track] { cursor: grab; }
    :scope > [data-swiper-track][data-dragging] {
      cursor: grabbing;
      scroll-snap-type: none;       /* let the pointer track 1:1 during drag */
      user-select: none;
    }
  }

  /* ── Slides ── */

  :scope > [data-swiper-track] > * {
    scroll-snap-align: var(--swiper-snap);
    scroll-snap-stop: always;
    min-width: 0;
  }

  /* ── Snap alignment ── */

  :scope[snap="center"] { --swiper-snap: center; }
  :scope[snap="end"]    { --swiper-snap: end; }

  /* ── Peek: show partial adjacent slides ── */

  :scope[peek] > [data-swiper-track] {
    padding-inline: var(--swiper-peek);
    scroll-padding-inline: var(--swiper-peek);
  }

  /* ── Explicit slides-per-view ── */

  :scope[slides-per-view="1"] { --swiper-columns: 1; }
  :scope[slides-per-view="2"] { --swiper-columns: 2; }
  :scope[slides-per-view="3"] { --swiper-columns: 3; }
  :scope[slides-per-view="4"] { --swiper-columns: 4; }

  /* ── Responsive auto (container queries) ──
     The host IS the named `swiper` container, so @container queries
     match descendants of it. `:scope` can't be its own descendant —
     we target the track (a descendant) so the cv resolves against
     the swiper's own width. */

  :scope:not([slides-per-view]) {
    --swiper-columns: 1;
  }

  @container swiper (min-width: 640px) {
    :scope:not([slides-per-view]) > [data-swiper-track] { --swiper-columns: 2; }
  }

  @container swiper (min-width: 960px) {
    :scope:not([slides-per-view]) > [data-swiper-track] { --swiper-columns: 3; }
  }

  /* ══════════════════════════════════════════════════════════
     JS-stamped paddles
     Centered vertically on the track area only.
     Native ::scroll-button is Chrome-135-only — re-introduce
     when cross-engine.
     ══════════════════════════════════════════════════════════ */

  :scope > [data-swiper-btn] {
    position: absolute;
    top: 0;
    bottom: var(--swiper-btn-bottom);
    margin-block: auto;
    height: fit-content;
    z-index: 2;
    --button-size: var(--swiper-btn-size);
    --button-radius: var(--swiper-btn-radius);
  }

  :scope > [data-swiper-prev] { left: var(--swiper-btn-offset); }
  :scope > [data-swiper-next] { right: var(--swiper-btn-offset); }

  /* ══════════════════════════════════════════════════════════
     JS-stamped pagination dots
     Normal flow below the track — not inside the scroll area.
     ══════════════════════════════════════════════════════════ */

  :scope [data-swiper-dots] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--swiper-dot-gap);
    min-height: 1.5rem;
  }

  /* Dot geometry — every dot has the same 1rem hitbox so the row layout
     is invariant across state changes. The visible circle inside is
     `--swiper-dot-size` for idle dots and `--swiper-dot-size-active`
     for the active one (one space token larger). Padding is computed
     from the size so the dot stays centered in the hitbox. */
  :scope [data-swiper-dots] > button {
    width: var(--swiper-dot-size);
    height: var(--swiper-dot-size);
    border-radius: var(--swiper-dot-radius);
    background: var(--swiper-dot-bg);
    border: none;
    padding: calc((1rem - var(--swiper-dot-size)) / 2);
    background-clip: content-box;
    box-sizing: content-box;
    cursor: pointer;
    transition: background var(--swiper-duration) var(--swiper-easing);
  }

  /* Long-hand `background-color` (not the `background` shorthand!) so
     `background-clip: content-box` from the base rule isn't reset to
     its initial `border-box` value — the colored area would otherwise
     fill the full 1rem hitbox and turn into a huge circle. */
  :scope [data-swiper-dots] > button:hover {
    background-color: var(--swiper-dot-bg-active);
  }

  /* Focus ring is rendered INSIDE the padding area (inset shadow), so
     the dot's visual footprint stays the size of every other dot. */
  :scope [data-swiper-dots] > button:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 var(--a-focus-width) var(--a-focus-color);
  }

  :scope [data-swiper-dots] > button[aria-current="true"] {
    background-color: var(--swiper-dot-bg-active);
    width: var(--swiper-dot-size-active);
    height: var(--swiper-dot-size-active);
    padding: calc((1rem - var(--swiper-dot-size-active)) / 2);
  }

  /* ══════════════════════════════════════════════════════════
     Toolbar chrome — [chrome="toolbar"]
     Header row: label | spacer | paddles
     Footer row: counter | spacer | dots
     Replaces the overlay paddles + centered dots layout.
     ══════════════════════════════════════════════════════════ */

  :scope[chrome="toolbar"] > [data-swiper-head],
  :scope[chrome="toolbar"] > [data-swiper-foot] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--a-space-3);
    min-height: 2rem;
  }

  :scope[chrome="toolbar"] > [data-swiper-head] > [data-swiper-label] {
    font-size: var(--a-ui-md);
    font-weight: var(--a-weight-semibold);
    color: var(--a-fg);
  }

  :scope[chrome="toolbar"] > [data-swiper-head] > [data-swiper-paddles] {
    display: flex;
    gap: var(--a-space-1);
  }

  :scope[chrome="toolbar"] > [data-swiper-foot] > [data-swiper-counter] {
    font-size: var(--a-ui-sm);
    color: var(--a-fg-subtle);
    font-variant-numeric: tabular-nums;
  }

  /* In toolbar mode, the dots cluster lives inside the footer and is
     right-aligned via space-between on the parent — drop the default
     justify-content: center and zero out vertical breathing room. */
  :scope[chrome="toolbar"] > [data-swiper-foot] > [data-swiper-dots] {
    min-height: 0;
    justify-content: flex-end;
  }

  /* ── Autoplay indicator ── */

  :scope[autoplay] > [data-swiper-pause] {
    position: absolute;
    top: var(--swiper-pause-top);
    right: var(--swiper-pause-right);
    z-index: 1;
  }

  /* ── Reduced motion ── */

  @media (prefers-reduced-motion: reduce) {
    :scope > [data-swiper-track] {
      scroll-behavior: auto;
    }
  }
}
