/* Content Carousel
   Horizontally snapping carousel of two-column cards.
   Image covers one column edge-to-edge, content sits in the other.
   No JS dependency for scrolling — native scroll-snap handles it.
   module.js only adds the dots and the autoplay toggle. */

.content-carousel {
  --cc-max: var(--section-width, 1240px);
  --cc-gap: 2.5rem;
  --cc-card-border: rgba(0, 0, 0, 0.12);
  --cc-radius: 24px;
  --cc-card-bg: var(--grey-light, #f2f2f4);

  /* Fallback for browsers without container queries. */
  --cc-gutter: max(1.25rem, calc((100vw - var(--cc-max)) / 2));
  --cc-card-width: min(var(--cc-max), calc(100vw - 2 * max(1.25rem, calc((100vw - var(--cc-max)) / 2))));

  container-type: inline-size;
  padding-block: 3rem;
}

/* Every length below is measured against this element's inline size via cqw.
   Mixing %, vw and cqw is what broke the last card's alignment: % resolves
   against the scroll container, cqw against this element, and the two differ
   by the dnd-section's padding. One reference frame keeps the arithmetic
   exact, so gutter + card + gutter always equals the available width and the
   final card can reach the leading gutter precisely. */
@supports (width: 1cqw) {
  .content-carousel {
    --cc-gutter: max(1.25rem, calc((100cqw - var(--cc-max)) / 2));
    --cc-card-width: min(var(--cc-max), calc(100cqw - 2 * var(--cc-gutter)));
  }
}

/* ---------- Section header ---------- */

.content-carousel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-inline: var(--cc-gutter);
  margin-bottom: 2rem;
}

.content-carousel__title {
  margin: 0;
}

.content-carousel__head-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
  color: var(--primary);
  white-space: nowrap;
}

.content-carousel__head-link:hover,
.content-carousel__head-link:focus-visible {
  text-decoration: underline;
}

.content-carousel__head-icon {
  flex: 0 0 auto;
}

/* ---------- Scroller ---------- */

.content-carousel__viewport {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-inline-start: var(--cc-gutter);
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.content-carousel__viewport::-webkit-scrollbar {
  display: none;
}

.content-carousel__viewport:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 4px;
}

.content-carousel__track {
  display: flex;
  gap: var(--cc-gap);
  /* Leading gutter only. padding-inline-end is deliberately NOT used here:
     on a horizontally scrolling flex container the end padding computes but
     contributes nothing to scrollable overflow, so the scroller runs out of
     travel early and strands the last card. The trailing gutter is carried
     by a margin on the last card instead, which does extend the scroll area. */
  padding-inline: var(--cc-gutter) 0;
  margin: 0;
  list-style: none;
}

/* A real flex item is the only reliable way to add trailing scroll travel
   here: on this scroller both padding-inline-end and a margin on the last
   card compute correctly but contribute nothing to scrollable overflow, so
   the final card could never reach the leading gutter. Subtracting the gap
   keeps the total trailing space equal to exactly one gutter. */
.cc-spacer {
  /* Always a full gutter wide, never zero: a zero-area box is skipped when
     scrollable overflow is computed, which took the preceding gap with it and
     left the last card flush against the edge wherever the gutter was smaller
     than the gap (i.e. mobile). The negative start margin cancels that gap so
     the trailing space is exactly one gutter at every width. */
  flex: 0 0 var(--cc-gutter);
  margin-inline-start: calc(-1 * var(--cc-gap));
  list-style: none;
}

/* ---------- Card ---------- */

.cc-card {
  flex: 0 0 auto;
  width: var(--cc-card-width);
  scroll-snap-align: start;
  display: grid;
  grid-template-columns: 1fr;
  background: var(--cc-card-bg);
  border: 1px solid var(--cc-card-border);
  border-radius: var(--cc-radius);
  box-sizing: border-box;
  overflow: hidden;
}

.cc-card__media,
.cc-card__body {
  min-width: 0;
}

.cc-card__media {
  position: relative;
  min-height: 15rem;
  background: var(--grey-light, #f2f2f4);
}

/* Absolute fill so the image never dictates the column height —
   it always covers whatever height the content column produces. */
.cc-card__media img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cc-card__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.5rem;
  padding: 2rem 1.5rem;
}

.cc-card__body > *:last-child {
  margin-bottom: 0;
}

.cc-card__content {
  overflow-wrap: break-word;
}

.cc-card__heading {
  margin-bottom: 0.5rem;
}

@media (min-width: 992px) {
  /* Image column 40%, content column 60%. The media-right variant reorders
     the image to column 2, so the track sizes flip to keep image at 40%. */
  .cc-card {
    grid-template-columns: 2fr 3fr;
    min-height: 30rem;
  }

  .content-carousel--media-right .cc-card {
    grid-template-columns: 3fr 2fr;
  }

  .cc-card__media {
    min-height: 0;
  }

  .cc-card__body {
    padding: 3.5rem 3rem;
  }

  .content-carousel--media-right .cc-card__media {
    order: 2;
  }
}

/* ---------- Icon list (carried over from Content and Image) ---------- */

.content-carousel .icon-list-wrapper {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: 1rem;
  margin-top: 0.5rem;
}

.content-carousel .icon-list-wrapper .list-item {
  display: flex;
  gap: 1rem;
  align-items: center;
}

.content-carousel .icon-list-wrapper .list-image {
  width: 48px;
  flex: 0 0 48px;
  aspect-ratio: 1 / 1;
  display: flex;
  justify-content: center;
}

.content-carousel .icon-list-wrapper .list-image img {
  object-fit: contain;
  width: 100%;
  height: 100%;
}

.content-carousel .icon-list-wrapper p.list-item-title,
.content-carousel .icon-list-wrapper p.list-item-description {
  margin-bottom: 0;
}

@media (min-width: 1200px) {
  .content-carousel .icon-list-wrapper {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ---------- Buttons ---------- */

.content-carousel .btn-wrap {
  margin-top: 1.5rem;
}

.content-carousel .btn-wrap-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

/* ---------- Controls ---------- */

.content-carousel__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Tight, because each control already carries ~12px of invisible padding
     inside its 44px touch target. */
  gap: 0.5rem;
  margin-top: 2.5rem;
  padding-inline: var(--cc-gutter);
}

.content-carousel__dots {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

/* Scoped for the same reason as the arrows: these are <button> elements, so
   the theme's global button:hover would otherwise repaint them on hover. */
.content-carousel .content-carousel__dot,
.content-carousel .content-carousel__dot:hover,
.content-carousel .content-carousel__dot:focus {
  width: 12px;
  height: 12px;
  padding: 0;
  border: 0;
  border-radius: 99px;
  background: var(--grey-medium, #9e9e9e);
  box-shadow: none;
  cursor: pointer;
}

.content-carousel .content-carousel__dot {
  opacity: 0.45;
  transition: width 0.3s ease, opacity 0.3s ease;
}

.content-carousel .content-carousel__dot:hover {
  opacity: 0.75;
}

.content-carousel .content-carousel__dot[aria-selected="true"],
.content-carousel .content-carousel__dot[aria-selected="true"]:hover {
  width: 48px;
  opacity: 1;
  background: var(--primary);
}

.content-carousel__dot:focus-visible,
.content-carousel__arrow:focus-visible,
.content-carousel__toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

/* Chrome-free, matching the dots: state is carried by opacity alone.
   These are scoped with .content-carousel because the theme styles every
   bare <button> globally — `button` sets a background and a pill radius,
   and `button:hover` (0-1-1) outranks an unscoped single class, which is
   what was painting a turquoise circle on hover. Every state is reset here
   so no theme rule can reintroduce it. */
.content-carousel .content-carousel__arrow,
.content-carousel .content-carousel__toggle,
.content-carousel .content-carousel__arrow:hover,
.content-carousel .content-carousel__toggle:hover,
.content-carousel .content-carousel__arrow:focus,
.content-carousel .content-carousel__toggle:focus,
.content-carousel .content-carousel__arrow[disabled],
.content-carousel .content-carousel__arrow[disabled]:hover {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--primary);
  text-transform: none;
}

.content-carousel .content-carousel__arrow,
.content-carousel .content-carousel__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  opacity: 0.45;
  cursor: pointer;
  transition: opacity 0.3s ease;
}

.content-carousel .content-carousel__arrow svg,
.content-carousel .content-carousel__toggle svg {
  width: 20px;
  height: 20px;
}

/* The theme also forces svg fill on buttons. Chevrons are stroked and must
   stay unfilled; the play/pause glyphs are the opposite. */
.content-carousel .content-carousel__arrow svg path,
.content-carousel .content-carousel__arrow:hover svg path {
  fill: none;
  stroke: currentColor;
}

.content-carousel .content-carousel__toggle svg rect,
.content-carousel .content-carousel__toggle svg path,
.content-carousel .content-carousel__toggle:hover svg rect,
.content-carousel .content-carousel__toggle:hover svg path {
  fill: currentColor;
  stroke: none;
}

.content-carousel .content-carousel__arrow:hover:not([disabled]),
.content-carousel .content-carousel__toggle:hover {
  opacity: 1;
}

/* No wrap-around, so the arrows go inert at the ends. */
.content-carousel .content-carousel__arrow[disabled] {
  opacity: 0.12;
  cursor: default;
}

@media (prefers-reduced-motion: reduce) {
  .content-carousel .content-carousel__arrow,
  .content-carousel .content-carousel__toggle {
    transition: none;
  }
}

/* Icon swaps with playing state */
.content-carousel__icon-play {
  display: none;
}

.content-carousel__toggle[data-playing="false"] .content-carousel__icon-play {
  display: block;
}

.content-carousel__toggle[data-playing="false"] .content-carousel__icon-pause {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .content-carousel__viewport {
    scroll-behavior: auto;
  }

  .content-carousel__dot {
    transition: none;
  }
}

/* If the module is dropped into a narrow column, the viewport-based
   breakpoint above would still force two columns. Collapse on the
   container's own width instead. */
@container (max-width: 991px) {
  .cc-card {
    grid-template-columns: 1fr;
    min-height: 0;
  }

  .cc-card__body {
    padding: 2rem 1.5rem;
  }
}
