/* ============================================================
   eye/carousel — core Text & Media elements in a row
   ============================================================

   Each slide is a whole core element, rendered by its own definition.
   This file sets the row — how many slides stand side by side, the gap
   between them, the rail and the buttons — and, inside a slide, only the
   card round it and the order of image area, header and text.

   --visible is the editor's number. Tablets show at most two and phones
   one, whatever was chosen — a slide narrower than that is too narrow to
   read. Embla measures the slides as drawn here, so these widths are the
   only place the number lives.

   Gaps are padding inside each slide with the track pulled back by the
   same amount, the way Embla expects them: a slide's width then includes
   its gap, and every snap lands on a slide's own edge.

   The row does not end on a card's edge: the next card shows at the right,
   a gap's width after the last whole one — its border and its padding, and
   not a pixel of what is inside. It says there is more to come, and the right edge is never a card's own border
   — a hairline on the very edge of the clip, which the browser drew late
   while the row was still easing in. No peek when there is nothing to come:
   a single slide, or every slide already in view (.is-static, set by
   frontend.js). Nor on phones, where the one card takes the whole width.
   ------------------------------------------------------------ */
.carousel {
  --carousel-per-view: var(--visible, 1);
  --carousel-gap: 32px;
  --carousel-peek: var(--carousel-card-padding);
  /* What the row keeps back after its last whole card: a gap, and the peek
     beyond it. Without a peek, nothing — the last card meets the edge. */
  --carousel-reserve: calc(var(--carousel-gap) + var(--carousel-peek));
  --carousel-card-padding: 24px;
  --carousel-media: 96px;             /* the editor's "Image area" overrides it */
  --carousel-media-gap: 1.334em;
  --carousel-button: 44px;

  margin: 0 0 2.668em;
}

.carousel__viewport {
  /* Without frontend.js: a plain sideways scroller, snapping to slides. */
  overflow-x: auto;
  scroll-snap-type: x mandatory;
}

/* Embla moves the track itself; the viewport only has to clip it. */
.carousel.is-ready .carousel__viewport {
  overflow: hidden;
  scroll-snap-type: none;
}

.carousel__track {
  display: flex;
  margin-left: calc(-1 * var(--carousel-gap));
  touch-action: pan-y pinch-zoom;   /* swipes sideways are the carousel's */
}

.carousel__slide {
  /* 100% is the track: the viewport plus one gap. Take away the reserve,
     and the rest is shared by the whole cards. */
  flex: 0 0 calc((100% - var(--carousel-reserve)) / var(--carousel-per-view));
  min-width: 0;
  padding-left: var(--carousel-gap);
  box-sizing: border-box;
  scroll-snap-align: start;
}

/* Nothing to come: the whole width goes to the cards. One slide is known
   before the script runs; all-in-view only after it has measured. */
.carousel:not(:has(.carousel__slide + .carousel__slide)),
.carousel.is-static { --carousel-reserve: 0px; }

/* ---- the image area ------------------------------------------ */
/* Every slide keeps the same room above its text — --carousel-media, the
   editor's "Image area" — so the texts of a row start on one line whatever
   their images, and a slide without one keeps the room empty.

   The core lays a Text & Media element out with floats and puts the media
   above, below or beside the text as the editor chose. In a carousel the
   order is fixed instead: image area, header, text. The element becomes a
   column, its .ce-textpic wrapper steps aside (display: contents) so the
   gallery and the text are items of that column too, and `order` sets them.

   An image keeps the size its Media tab gives it — that is how a logo with
   heavier proportions is set smaller — and is only scaled down when it would
   overflow the area or the card. It stands on the area's bottom edge,
   left, centred or right as its own alignment says. One row of images is
   what the area is for; anything past it is cut. */
.carousel__slide .frame-type-textmedia {
  display: flex;
  flex-direction: column;
}

.carousel__slide .ce-textpic { display: contents; }

/* .ce-textpic in the selector: the core's margins for media beside the text
   are written with three classes, and these have to outrank them. */
.carousel__slide .ce-textpic .ce-gallery,
.carousel__slide .frame-type-textmedia:not(:has(.ce-gallery))::before {
  order: 1;
  flex: none;
  height: var(--carousel-media);
  margin: 0 0 var(--carousel-media-gap);
}

.carousel__slide .frame-type-textmedia:not(:has(.ce-gallery))::before { content: ""; }

.carousel__slide .frame-type-textmedia > header { order: 2; }

/* With the media beside the text, the core puts the header inside the text
   block instead, already in the right place. Either way the header starts
   right under the image area: the area's own gap is the space above it. */
.carousel__slide .frame-type-textmedia > header > :first-child,
.carousel__slide .ce-bodytext > header:first-child > :first-child { margin-top: 0; }
.carousel__slide .ce-bodytext { order: 3; }

.carousel__slide .ce-gallery {
  display: flex;
  align-items: flex-end;
  float: none;
  max-width: 100%;
}

.carousel__slide .ce-center .ce-gallery { justify-content: center; }
.carousel__slide .ce-right .ce-gallery { justify-content: flex-end; }

/* The core's centring floats, undone: the gallery itself does the aligning. */
.carousel__slide .ce-outer,
.carousel__slide .ce-inner {
  position: static;
  float: none;
  min-width: 0;
  max-width: 100%;
}

.carousel__slide .ce-row {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  margin: 0;
  max-width: 100%;
}

.carousel__slide .ce-column {
  float: none;
  min-width: 0;
  margin: 0;
}

.carousel__slide .ce-gallery figure { display: block; }

/* The width stays the one the Media tab rendered, the height follows it,
   and both are capped. When the cap bites, object-fit keeps the proportions
   and object-position stands the picture on the bottom edge, on the side the
   gallery is aligned to. */
.carousel__slide .ce-gallery img {
  max-width: 100%;
  max-height: var(--carousel-media);
  margin: 0;
  object-fit: contain;
  object-position: left bottom;
}

.carousel__slide .ce-center .ce-gallery img { object-position: center bottom; }
.carousel__slide .ce-right .ce-gallery img { object-position: right bottom; }

/* ---- the cards ----------------------------------------------- */
/* Each slide's element is a card: a 1px frame in ink, the page's rule drawn
   round it, red under the pointer as everything else that answers to it.
   The slides of a row are as tall as the tallest, and the cards fill them,
   so the frames end level however long the text. */
.carousel__slide { display: flex; }

.carousel__slide > * {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: var(--carousel-card-padding);
  border: 1px solid var(--ink);
  transition: border-color 0.2s ease;
}

@media (hover: hover) {
  .carousel__slide > :hover { border-color: var(--eye-red); }
}

.carousel.is-ready:not(.is-static) .carousel__viewport { cursor: grab; }
.carousel.is-dragging .carousel__viewport { cursor: grabbing; }

/* ---- the rail and the buttons -------------------------------- */
/* Under the row, the motif of the page title: a red bullet on a 1px line.
   The line is the row from first slide to last, the bullet where the reader
   is in it, and the line behind the bullet is red — what has been seen. The
   buttons stand at its end, as the menu stands at the end of the title's
   rule. It is a slider too: a press on the line goes there, the bullet can
   be dragged — so the rail is as tall as the buttons, the height a thumb
   can hit, with the line drawn through its middle. */
.carousel__controls {
  display: none;
  align-items: center;
  gap: 8px;
  margin-top: 24px;
}

.carousel.is-ready:not(.is-static) .carousel__controls { display: flex; }

.carousel__rail {
  --carousel-travel: calc(var(--carousel-at, 0) * (100% - var(--bullet)));

  position: relative;
  flex: 1;
  height: var(--carousel-button);
  margin-right: 8px;
  cursor: pointer;
  touch-action: pan-y;              /* sideways is the bullet's */
  -webkit-tap-highlight-color: transparent;
  outline: none;
}

.carousel__rail::before,
.carousel__rail::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  height: 1px;
}

.carousel__rail::before { right: 0; background: var(--ink); }

.carousel__rail::after {
  width: var(--carousel-travel);
  background: var(--eye-red);
  transition: width var(--carousel-glide, 0.45s) ease;
}

.carousel__bullet {
  position: absolute;
  top: calc(50% - var(--bullet) / 2);
  left: var(--carousel-travel);
  z-index: 1;
  width: var(--bullet);
  height: var(--bullet);
  border-radius: 50%;
  background: var(--eye-red);
  transition: left var(--carousel-glide, 0.45s) ease, transform 0.2s ease, box-shadow 0.2s ease;
}

/* Under the pointer the bullet grows a little — it can be taken hold of —
   and held, it follows the pointer without lagging behind. */
.carousel.is-scrubbing .carousel__bullet { transform: scale(1.3); }

@media (hover: hover) {
  .carousel__rail:hover .carousel__bullet { transform: scale(1.3); }
}

.carousel.is-scrubbing .carousel__rail { cursor: grabbing; }

.carousel.is-scrubbing .carousel__rail::after,
.carousel.is-scrubbing .carousel__bullet { transition: transform 0.2s ease; }

.carousel__rail:focus-visible .carousel__bullet {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--eye-red);
}

/* Autoplay's countdown: one ring per slide, spreading from the bullet over
   the whole delay and gone as the next slide comes in. Under the mouse or the
   keyboard, autoplay holds, and so does the ring — it is simply not there. */
.carousel.is-counting .carousel__bullet::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid var(--eye-red);
  animation: carousel-countdown var(--carousel-delay, 5s) linear forwards;
}

@keyframes carousel-countdown {
  from { transform: scale(1); opacity: 1; }
  to   { transform: scale(3.5); opacity: 0; }
}

/* Two rings at the rail's end: ink at rest, red under the pointer or the
   keyboard, as everything else on the page that answers to them. 44px, the
   size a thumb can find. */
.carousel__button {
  display: grid;
  flex: none;
  place-items: center;
  width: var(--carousel-button);
  height: var(--carousel-button);
  padding: 0;
  border: 1px solid var(--ink);
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}

.carousel__button svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.2s ease;
}

/* Red under the pointer, under the keyboard, and while pressed. Hover only
   where there is a pointer that hovers: a touch screen keeps the last tapped
   button in :hover until the next tap elsewhere, which left it red. */
.carousel__button:active,
.carousel__button:focus-visible {
  border-color: var(--eye-red);
  background: var(--eye-red);
  color: var(--paper);
}

@media (hover: hover) {
  .carousel__button:hover {
    border-color: var(--eye-red);
    background: var(--eye-red);
    color: var(--paper);
  }

  /* The chevron leans the way it goes. */
  .carousel__button--prev:hover svg { transform: translateX(-2px); }
  .carousel__button--next:hover svg { transform: translateX(2px); }
}

.carousel__button:active { transform: scale(0.94); }

.carousel__button:focus-visible {
  outline: 2px solid var(--eye-red);
  outline-offset: 2px;
}

.carousel__button:disabled {
  opacity: 0.3;
  cursor: default;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .carousel__button,
  .carousel__button svg,
  .carousel__rail::after,
  .carousel__bullet,
  .carousel.is-scrubbing .carousel__bullet { transition: none; }
}

/* ---- smaller screens ---------------------------------------- */
@media (max-width: 1023px) {
  .carousel {
    --carousel-per-view: min(var(--visible, 1), 2);
    --carousel-gap: 24px;
    --carousel-card-padding: 20px;
  }
}

@media (max-width: 639px) {
  .carousel {
    --carousel-per-view: 1;
    --carousel-gap: 16px;
    --carousel-reserve: 0px;
    --carousel-card-padding: 16px;
  }
}
