/*
Carousel

<div class="carousel" role="region" aria-roledescription="carousel" data-orientation>
  <button class="carousel-rotation">                 autoplay only; first tab stop (APG)
  <div class="carousel-viewport">                    the viewport: clips
    <div class="carousel-container" aria-live>      the track: a flex row
      <div class="carousel-item" role="group" aria-roledescription="slide">
  <button class="carousel-previous" data-carousel-prev>
  <button class="carousel-next" data-carousel-next>
  <div class="carousel-dots" role="group">          dots only
    <button class="carousel-dot" data-state>

Slides size with flex-basis (class on CarouselItem, or --carousel-item-size)
and space with --carousel-gap. The engine moves the track with transform,
so nothing around the carousel ever moves.
*/

/* The package's layer order, repeated in every sheet so it holds whichever sheet loads first. */
@layer reset, tokens, base, components, templates, utilities, overrides;

@layer templates {

.carousel {
  position:  relative;
}

.carousel-viewport {
  overflow: hidden;
  border-radius: inherit;
}

.carousel-container {
  display:             flex;
  margin-inline-start: calc(-1 * var(--carousel-gap));
  touch-action:        pan-y pinch-zoom;
  backface-visibility: hidden;
}

.carousel[data-orientation="vertical"] .carousel-container {
  flex-direction:      column;
  height:              100%;
  margin-inline-start: 0;
  margin-top:          calc(-1 * var(--carousel-gap));
  touch-action:        pan-x pinch-zoom;
}

.carousel-item {
  flex:                 0 0 var(--carousel-item-size, 100%);
  min-width:            0;
  min-height:           0;
  padding-inline-start: var(--carousel-gap);
  transform:            translate3d(0, 0, 0);
}

.carousel[data-orientation="vertical"] .carousel-item {
  padding-inline-start: 0;
  padding-top:          var(--carousel-gap);
}

/* Previous and next sit outside the track by --space-3 whatever their size:
   the inset puts the button's inner edge there and translate moves it out by
   its own size. */

.carousel > .carousel-previous.button,
.carousel > .carousel-next.button {
  position:      absolute;
  border-radius: var(--radius-pill);
  top:           50%;
}

.carousel > .carousel-previous.button {
  inset-inline-start: calc(-1 * var(--space-3));
  translate:          -100% -50%;
}

.carousel > .carousel-next.button {
  inset-inline-end: calc(-1 * var(--space-3));
  translate:        100% -50%;
}

.carousel:dir(rtl) > .carousel-previous.button {
  translate: 100% -50%;
}

.carousel:dir(rtl) > .carousel-next.button {
  translate: -100% -50%;
}

.carousel[data-orientation="vertical"] > .carousel-previous.button,
.carousel[data-orientation="vertical"] > .carousel-next.button {
  inset-inline-start: 50%;
  inset-inline-end:   auto;
}

.carousel[data-orientation="vertical"] > .carousel-previous.button {
  top:       calc(-1 * var(--space-3));
  translate: -50% -100%;
}

.carousel[data-orientation="vertical"] > .carousel-next.button {
  top:       auto;
  bottom:    calc(-1 * var(--space-3));
  translate: -50% 100%;
}

.carousel[data-orientation="vertical"]:dir(rtl) > .carousel-previous.button {
  translate: 50% -100%;
}

.carousel[data-orientation="vertical"]:dir(rtl) > .carousel-next.button {
  translate: 50% 100%;
}

.carousel[data-orientation="vertical"] > .carousel-previous .icon,
.carousel[data-orientation="vertical"] > .carousel-next .icon {
  rotate: 90deg;
}

/* :dir() follows the nearest dir, so dir="ltr" inside an rtl page stays ltr. */
.carousel:dir(rtl) .carousel-previous .icon,
.carousel:dir(rtl) .carousel-next .icon {
  scale: -1 1;
}

.carousel-previous.button:disabled,
.carousel-next.button:disabled,
.carousel-previous.button[aria-disabled="true"],
.carousel-next.button[aria-disabled="true"] {
  opacity: var(--opacity-disabled);
}

/* Where the page has no room beside the track (a phone, or a carousel as
   wide as its column, which the script marks data-controls="inside"), the
   buttons sit over the track's edges on an elevated fill. The fill is the
   outline button's own --control-bg, so hover and press still paint. */
.carousel[data-orientation="horizontal"][data-controls="inside"] > .carousel-previous.button {
  inset-inline-start: var(--space-2);
}

.carousel[data-orientation="horizontal"][data-controls="inside"] > .carousel-next.button {
  inset-inline-end: var(--space-2);
}

.carousel[data-orientation="horizontal"][data-controls="inside"] > :is(.carousel-previous, .carousel-next).button {
  --control-bg: var(--bg-elevated);

  translate: 0 -50%;
}

.carousel[data-orientation="horizontal"][data-controls="inside"] > :is(.carousel-previous, .carousel-next).button.is-ghost:not(:hover, :active) {
  background: var(--bg-elevated);
}

@media (max-width: 40rem) {
  .carousel[data-orientation="horizontal"] > .carousel-previous.button {
    inset-inline-start: var(--space-2);
  }

  .carousel[data-orientation="horizontal"] > .carousel-next.button {
    inset-inline-end: var(--space-2);
  }

  .carousel[data-orientation="horizontal"] > :is(.carousel-previous, .carousel-next).button {
    --control-bg: var(--bg-elevated);

    translate: 0 -50%;
  }

  .carousel[data-orientation="horizontal"] > :is(.carousel-previous, .carousel-next).button.is-ghost:not(:hover, :active) {
    background: var(--bg-elevated);
  }
}

/* Rotation Control */

.carousel > .carousel-rotation.button {
  position:           absolute;
  top:                var(--space-2);
  inset-inline-start: var(--space-2);
  z-index:            1;
  border-radius:      var(--radius-pill);
}

/* Play and pause share one cell; only the current one shows. */
.carousel-swap {
  display: inline-grid;
}

.carousel-swap > * {
  grid-area: 1 / 1;
  display:   inline-grid;
}

.carousel-swap[data-state="off"] > .swap-on,
.carousel-swap[data-state="on"] > .swap-off {
  visibility: hidden;
}

/* Pickers */

.carousel-dots {
  display:         flex;
  justify-content: center;
  flex-wrap:       wrap;
  padding-top:     var(--space-2);
}

.carousel-dot {
  display:       inline-grid;
  place-items:   center;
  width:         var(--control-height-sm);
  height:        var(--control-height-sm);
  padding:       0;
  border:        0;
  background:    none;
  border-radius: var(--radius-pill);
  cursor:        pointer;
}

.carousel-dot::before {
  content:       "";
  width:         var(--space-2);
  height:        var(--space-2);
  border-radius: var(--radius-pill);
  background:    var(--rule-strong);
  transition:    background-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
}

.carousel-dot:hover::before {
  background: var(--ink-dim);
}

.carousel-dot[data-state="active"]::before {
  background: var(--accent);
  transform:  scale(1.25);
}

.carousel-dot[aria-disabled="true"] {
  cursor: default;
}

.carousel-dot:focus-visible {
  outline:    none;
  box-shadow: var(--focus-ring);
}

/* Auto height plugin: slides keep their own height and the track takes the
   selected one's. */

.carousel-container[data-auto-height] {
  align-items: flex-start;
  transition:  height var(--duration-normal) var(--ease-out);
}

}
