/* logo-wall — the client/partner brand-mark wall: the "trusted by" strip.
 * Each mark is a logo image (a MARK — the image atom's documented mark
 * exemption: contain posture, own class, never content photography) or a
 * set-in-type WORDMARK when the row carries no image; a row with an href
 * renders as a real link. This sheet is band + strip geometry only (layout
 * contract): every paint reads the --sk-* indirections, so tones restyle
 * the wall for free.
 *
 *   grid    — the default: marks wrap into a responsive grid, `columns`
 *     wide on desktop, stepping down a fit ladder as the band narrows
 *     (the dial is a ceiling, never a floor — features-grid's rule). A
 *     `maxLogos` cap under a longer roster rotates the wall through it
 *     (the Rotation block below; the pass lives in logo-wall.js).
 *   marquee — one seamless auto-scrolling strip. The section composes ONE
 *     sequence; logo-wall.js appends presentation-only clones until the
 *     track covers two viewports and stamps data-marquee="on" — only then
 *     does the keyframe arm. The loop DURATION composes from the roster
 *     size ({logos|count}, stamped --sk-logo-count at compose time) × a
 *     per-mark beat (the `speed` axis) × the clone factor, so the pace
 *     survives roster edits. Degradation is structural (§7): scripts off,
 *     the strip rests hand-scrollable; reduced motion stills it, hides the
 *     clones, and keeps it hand-scrollable. */

.sk-logo-wall {
  /* Mark box height — ×-body per the ratio rule (§3), never raw px. */
  --sk-logo-wall-tile-h: calc(var(--kit-type-base) * 5);
  /* The marquee's per-mark beat — seconds each mark takes to cross. */
  --sk-logo-wall-beat: 3s;
}
.sk-logo-wall[data-speed="slow"] {
  --sk-logo-wall-beat: 5s;
}
.sk-logo-wall[data-speed="fast"] {
  --sk-logo-wall-beat: 1.5s;
}

.sk-logo-wall-seq {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sk-logo-wall-mark {
  display: flex;
  min-width: 0;
}

.sk-logo-wall-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: var(--sk-logo-wall-tile-h);
  box-sizing: border-box;
  padding: var(--kit-space-2) var(--kit-space-4);
  color: var(--sk-ink);
  text-decoration: none;
}

.sk-logo-wall-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* The set-in-type wordmark — the imageless row's mark (§9: "not yet" is
 * designed — a roster without artwork still reads as a wall of brands).
 * Title voice, tracked wide, set in caps: a nameplate, not body copy. */
.sk-logo-wall-wordmark {
  font-family: var(--kit-font-title);
  font-style: var(--kit-slant-title);
  font-size: calc(var(--kit-type-base) * 1.2);
  font-weight: var(--kit-weight-title);
  letter-spacing: calc(var(--kit-track-title) * 1em + 0.08em);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── The look axis — `ink` (default) is the classic wall treatment: marks
 * rest grayscale and dimmed, lifting to full strength under a pointer or
 * keyboard focus. `ink-lighten` is its reverse: marks rest at full
 * strength and recede to the same ink state under a pointer or keyboard
 * focus. `natural` rests every mark at full strength. The lift's
 * TRANSITION rides the reduced-motion floor (§8); the states themselves
 * hold everywhere. */
.sk-logo-wall[data-look="ink"] .sk-logo-wall-tile,
.sk-logo-wall[data-look="ink-lighten"] .sk-logo-wall-tile:is(:hover, :focus-visible) {
  filter: grayscale(1);
  opacity: 0.55;
}
.sk-logo-wall[data-look="ink"] .sk-logo-wall-tile:is(:hover, :focus-visible) {
  filter: none;
  opacity: 1;
}
@media (prefers-reduced-motion: no-preference) {
  .sk-logo-wall[data-look="ink"] .sk-logo-wall-tile,
  .sk-logo-wall[data-look="ink-lighten"] .sk-logo-wall-tile {
    transition:
      opacity 0.25s var(--sk-ease-out),
      filter 0.25s var(--sk-ease-out);
  }
}

/* ── Grid — the track dissolves (it exists for the marquee's translate);
 * the sequence is the grid. The effective track count is the lesser of the
 * dial and the fit ladder's rung — the same min() indirection features-grid
 * rests on. */
.sk-logo-wall[data-variant="grid"] .sk-logo-wall-track {
  display: contents;
}
.sk-logo-wall[data-variant="grid"] .sk-logo-wall-seq {
  --sk-logo-wall-fit: 6;
  --sk-logo-wall-active: min(var(--sk-columns, 4), var(--sk-logo-wall-fit));
  display: grid;
  grid-template-columns: repeat(var(--sk-logo-wall-active), minmax(0, 1fr));
  gap: var(--kit-space-3) var(--kit-space-4);
}
@media (max-width: 900px) {
  .sk-logo-wall[data-variant="grid"] .sk-logo-wall-seq {
    --sk-logo-wall-fit: 3;
  }
}
@media (max-width: 560px) {
  .sk-logo-wall[data-variant="grid"] .sk-logo-wall-seq {
    --sk-logo-wall-fit: 2;
  }
}

/* ── Rotation — the grid's roster cap. `maxLogos` under a longer roster:
 * logo-wall.js hides the overflow (data-off) and, each beat, swaps ONE
 * random visible mark for a random benched one (never repeating the
 * previous pick on either side) — the outgoing tile leaves (data-out), the
 * incoming one arrives (data-in — the transitionless from-state, released
 * a frame later) in the SAME grid position (the script hands it the
 * outgoing mark's `order`), so the rest of the wall never shifts.
 * Both halves play AT ONCE — no blank beat: the script overlays the
 * incoming mark on the outgoing cell absolutely (why the seq below is the
 * positioned anchor) while the outgoing leaves in place. The exchange
 * beat is SWAP_MS in logo-wall.js — keep it and
 * the 1s here in step. Everything is gated on data-rotate="on" (stamped
 * only by the script, which declines under reduced motion), so scripts
 * off, print, and reduced motion all rest as the FULL wall — the cap is
 * presentation, never missing content. */
.sk-logo-wall[data-rotate="on"] .sk-logo-wall-seq {
  position: relative;
}
.sk-logo-wall[data-rotate="on"] .sk-logo-wall-mark[data-off] {
  display: none;
}
@media (prefers-reduced-motion: no-preference) {
  /* GOTCHA: every rule here carries the html[data-sk-js] prefix because the
   * entrance engine's REVEALED rule (base.css: `html[data-sk-js] [data-anim]
   * [data-sk-reveal].sk-in { opacity: 1; transform: none }`, specificity
   * (0,4,1)) pins every revealed mark — and `[data-anim]` matches even
   * data-anim="none". Unprefixed, these sat at (0,4,0) and the swap's
   * opacity/transform silently lost; the prefix lifts them to (0,5,1). The
   * marks are managed by the script, which only runs where data-sk-js is
   * stamped, so the prefix costs nothing. */
  html[data-sk-js] .sk-logo-wall[data-rotate="on"] .sk-logo-wall-mark {
    transition:
      opacity 1s var(--sk-ease-out),
      transform 1s var(--sk-ease-out);
  }
  html[data-sk-js] .sk-logo-wall[data-rotate="on"] .sk-logo-wall-mark:is([data-out], [data-in]) {
    opacity: 0;
  }
  /* Flip — the outgoing mark pivots away over its top edge WHILE the
   * incoming one pivots in from below it — opposite phases of one roll,
   * overlapped in the same cell, each fading at its edge-on end. */
  html[data-sk-js] .sk-logo-wall[data-rotate="on"][data-swap="flip"] .sk-logo-wall-mark[data-out] {
    transform: perspective(600px) rotateX(90deg);
  }
  html[data-sk-js] .sk-logo-wall[data-rotate="on"][data-swap="flip"] .sk-logo-wall-mark[data-in] {
    transform: perspective(600px) rotateX(-90deg);
  }
  html[data-sk-js] .sk-logo-wall[data-rotate="on"] .sk-logo-wall-mark[data-in] {
    transition: none;
  }
}

/* ── Marquee ── */
.sk-logo-wall[data-variant="marquee"] .sk-logo-wall-inner {
  /* The strip bleeds; the soft edge fade is its page edge, so marks enter
   * and exit gently instead of clipping hard. */
  padding-inline: 0;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
/* The resting strip — scripts off, or before the clone pass lands: the one
 * composed sequence, reachable by hand. */
.sk-logo-wall[data-variant="marquee"]:not([data-marquee="on"]) .sk-logo-wall-inner {
  overflow-x: auto;
}
.sk-logo-wall[data-variant="marquee"] .sk-logo-wall-track {
  display: flex;
  width: max-content;
}
.sk-logo-wall[data-variant="marquee"] .sk-logo-wall-seq {
  display: flex;
  gap: var(--kit-space-5);
  /* The wrap seam — matches the gap, so the loop point reads like any
   * other gap. */
  padding-inline-end: var(--kit-space-5);
}
.sk-logo-wall[data-variant="marquee"] .sk-logo-wall-mark {
  flex: none;
}
.sk-logo-wall[data-variant="marquee"] .sk-logo-wall-tile {
  width: auto;
  min-width: calc(var(--kit-type-base) * 7.5);
}

@media (prefers-reduced-motion: no-preference) {
  .sk-logo-wall[data-variant="marquee"][data-marquee="on"] .sk-logo-wall-track {
    animation: sk-logo-wall-scroll
      calc(var(--sk-logo-count, 8) * var(--sk-logo-wall-beat) * var(--sk-logo-wall-loops, 1)) linear
      infinite;
  }
  /* Pause for inspection — a pointer resting on the strip, or keyboard
   * focus landing on a linked mark inside it. */
  .sk-logo-wall[data-variant="marquee"][data-marquee="on"]
    .sk-logo-wall-track:is(:hover, :focus-within) {
    animation-play-state: paused;
  }
}
@media (prefers-reduced-motion: reduce) {
  .sk-logo-wall-seq[data-clone] {
    display: none;
  }
  .sk-logo-wall[data-variant="marquee"] .sk-logo-wall-inner {
    overflow-x: auto;
    mask-image: none;
  }
}

@keyframes sk-logo-wall-scroll {
  to {
    /* Exactly half the track — the clone pass keeps the second half a
     * repeat of the first, so the wrap is seamless. */
    transform: translateX(-50%);
  }
}
