/* One row of images, scrolled sideways, running to both edges of the viewport.

   Full bleed is two moves that have to cancel out exactly: the section undoes
   the body margin with a negative one of the same size, and the track pays it
   back as padding inside its own scroller. The row then reaches the viewport
   edges while the first image still starts on the body margin and the last one
   still ends on it — and the images in between pass under the edges of the
   screen rather than stopping short of them.

   Each slide carries --slide-width, how wide its image actually draws. */

/* No height cap declared here: nothing in this file reads one. The cap reaches
   the slides already folded into --slide-width, which the component computes
   because the `sizes` attribute needs the very same figure and cannot read a
   custom property. See site/plugins/gallery. */
.carousel {
  --carousel-gap: var(--fs-base);

  margin-top: calc(var(--lh-base) * 2);
  margin-inline: calc(var(--page-margin) * -1);
}

/* Larger arrows on a phone than the sitewide token gives. A below-desktop query
   rather than the usual mobile-first one, so the desktop size stays defined
   only in base/variables.css. Overridden here rather than there because the
   slideshow subtracts the arrow width from its own track, and that must not
   move with this. The controls' pull-up below reads the same property, so it
   follows. */
@media (width < 60em) {
  .carousel {
    --arrow-width: calc(var(--fs-base) * 4.5);
  }
}

/* One arrow over each end of the row, lined up with the body margin the first
   and last image sit on, and straddling the images' top edge: half the arrow
   above it, half over the pictures.

   The pull-up is half the button's height, not the drawing's — the drawing is
   centred in the button, so the two share a midline, and on a phone the button
   is the taller of the two (arrow.css stretches it to 44px). That height is
   restated here from the same two figures arrow.css uses.

   The row paints above the track, which would otherwise cover it by coming
   later in the source. Only the arrows take the pointer: the stretch of row
   between them lies over the images, and a swipe or scroll there belongs to
   the track. */
.carousel__controls {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: space-between;
  margin-inline: var(--page-margin);
  margin-bottom: calc(max(44px, var(--arrow-width) * 902 / 1280) / -2);
  pointer-events: none;
}

.carousel__controls .arrow {
  pointer-events: auto;
}

/* `display` above outranks the UA rule behind `hidden`, so the attribute has to
   be honoured explicitly — the row ships hidden and carousel.js reveals it. */
.carousel__controls[hidden] {
  display: none;
}

/* Images of different heights hang from a common top line rather than being
   centred on each other, so the row reads as one band across the top.

   Snapping is `proximity`, not `mandatory`: with several images in view the
   reader is as likely to be scanning the row as stepping through it, and
   mandatory snapping would fight every free scroll. scroll-padding puts a
   snapped image on the body margin instead of against the viewport edge, which
   is also where the arrows land it.

   The scrollbar is hidden in both engines' dialects — it is a strip of chrome
   across the foot of the artwork, and the arrows already say the row moves.
   Hiding it costs nothing in reach: the track keeps its tabindex and stays
   keyboard-scrollable, and a swipe still works. */
.carousel__track {
  display: flex;
  align-items: flex-start;
  gap: var(--carousel-gap);
  padding-inline: var(--page-margin);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-inline-start: var(--page-margin);
  scrollbar-width: none;
}

.carousel__track::-webkit-scrollbar {
  display: none;
}

/* Never wider than the room between the body margins: on a phone that holds a
   landscape image to the width the rest of the page uses, instead of letting a
   single slide fill the screen and hide that there is a row at all. */
.carousel__slide {
  flex: 0 0 auto;
  width: min(var(--slide-width, 100%), 100%);
  scroll-snap-align: start;
}

/* `display: block` drops the inline baseline gap under the image, which would
   otherwise show up as uneven space below the shorter ones. */
.carousel__image {
  display: block;
  width: 100%;
  height: auto;
}

/* An arrow moves the row by one image, and the row is what the eye has to
   follow: it travels rather than cutting, so the images that stay on screen
   carry the reader across. Declared in CSS rather than asked for in JS, which
   is what lets the preference switch it off. */
@media (prefers-reduced-motion: no-preference) {
  .carousel__track {
    scroll-behavior: smooth;
  }
}
