/* ScrollVars: UI presets (marquee, accordion) for the React kit and
 * vanilla markup alike. */

/* Marquee: an infinite strip (logos, taglines). The track holds TWO copies
   of the content and slides one copy-width; knobs: --sv-marquee-duration
   (one loop) and --sv-gap. Pauses on hover by default
   (--sv-marquee-hover: running to disable). */
.sv-marquee {
  overflow: hidden;
  display: flex;
}
.sv-marquee-track {
  display: flex;
  align-items: center;
  gap: var(--sv-gap, 48px);
  width: max-content;
  padding-right: var(--sv-gap, 48px);
  animation: sv-marquee var(--sv-marquee-duration, 30s) linear infinite;
}
/* the duplicate copy: a class, not inline style, so reduced motion below
   overrides it without !important. */
.sv-marquee-track > .sv-marquee-dup {
  display: contents;
}
.sv-marquee:hover .sv-marquee-track,
.sv-marquee:focus-within .sv-marquee-track {
  animation-play-state: var(--sv-marquee-hover, paused);
}
/* While the track itself holds focus, present it statically and wrapped
   with the duplicate hidden (WCAG 2.4.7): pausing only stops the slide, and
   a focused item can sit translated off the strip for most of the loop.
   Keyed on the TRACK, not .sv-marquee: the controlled marquee's pause
   button is inside .sv-marquee but outside the track, so focusing it must
   not reflow the strip. */
.sv-marquee-track:focus-within {
  animation: none;
  width: auto;
  flex-wrap: wrap;
}
.sv-marquee-track:focus-within > .sv-marquee-dup {
  display: none;
}
@keyframes sv-marquee {
  to {
    translate: -50% 0;
  }
}

/* A controlled strip stays still until its pause button has been wired. */
.sv-marquee-controlled { position: relative; }
.sv-marquee-controlled > .sv-marquee-track:not(.sv-ui) {
  animation: none; width: auto; flex-wrap: wrap;
}
.sv-marquee-controlled > .sv-marquee-track:not(.sv-ui) > .sv-marquee-dup { display: none; }
.sv-marquee-controlled > .sv-marquee-track.sv-paused { animation-play-state: paused; }
/* Off screen or the tab in the background (toggles(), IntersectionObserver
   + visibilitychange): paused independently of the user's own pause
   button above, either one holds it. */
.sv-marquee-track.sv-marquee-offscreen { animation-play-state: paused; }
.sv-marquee-pause { display: none; }
.sv-marquee-track.sv-ui + .sv-marquee-pause {
  display: block; position: absolute; right: 8px; bottom: 8px; z-index: 1;
  padding: 6px 10px; border: 1px solid currentColor; border-radius: 4px;
  background: Canvas; color: CanvasText; font: inherit; font-size: 12px; cursor: pointer;
}
.sv-marquee-pause[aria-pressed="true"] { font-weight: bold; }

/* Accordion: native <details> animated: accessibility for free, exclusive
   groups via the native name attribute. Needs interpolate-size (Chrome 129+);
   older browsers open/close without the height animation. */
.sv-accordion {
  interpolate-size: allow-keywords;
}
.sv-accordion > summary {
  cursor: pointer;
}
.sv-accordion::details-content {
  opacity: 0;
  block-size: 0;
  overflow: hidden;
  transition:
    block-size var(--sv-duration, 350ms) var(--sv-ease, ease),
    opacity var(--sv-duration, 350ms) var(--sv-ease, ease),
    content-visibility var(--sv-duration, 350ms) allow-discrete;
}
.sv-accordion[open]::details-content {
  opacity: 1;
  block-size: auto;
}

@media (prefers-reduced-motion: reduce) {
  .sv-marquee-track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
  }
  /* wins on source order, no !important; narrower than [aria-hidden] so
     a consumer's own aria-hidden child is not caught. */
  .sv-marquee-track > .sv-marquee-dup {
    display: none;
  }
  .sv-accordion::details-content {
    transition: none;
  }
}

/* The same under the page's own switch, html[data-sv-motion="reduce"]
   (core/motion.ts): a test keeps every rule in step with the block above. */
:where([data-sv-motion="reduce"]) .sv-marquee-track {
  animation: none;
  width: auto;
  flex-wrap: wrap;
}
:where([data-sv-motion="reduce"]) .sv-marquee-track > .sv-marquee-dup {
  display: none;
}
:where([data-sv-motion="reduce"]) .sv-accordion::details-content {
  transition: none;
}
