.embla,
.editor-embla {
  position: relative;
}

/* Global slider control colors: theme.json settings.custom.brandy.slider.*
   feeds the --embla-* tokens; blocks only emit an inline override when the
   editor changed a color from the brand default.

   `.is-editor-preview` is on this list because the editor canvas has NO
   `.embla` element — the control skeleton hangs directly off the block's own
   wrapper, with no Embla instance to build one. Declared on `.embla` alone,
   every token below went undefined in the editor: the arrows fell back to the
   hard-coded defaults in their own declarations (white on a white canvas), and
   the dots, whose background had no fallback at all, resolved to nothing and
   painted transparent — present in the DOM at full size, and invisible. */
.embla,
.is-editor-preview {
  --embla-button-icon-color: var(--wp--custom--brandy--slider--nav-icon-color, #122940);
  --embla-button-icon-color-hover: var(--wp--custom--brandy--slider--nav-icon-color-hover, #808890);
  --embla-button-background-color: var(--wp--custom--brandy--slider--nav-bg, #ffffff);
  --embla-button-background-color-hover: var(--wp--custom--brandy--slider--nav-bg-hover, #eff2f4);
  --embla-pagination-bullet-color: var(--wp--custom--brandy--slider--dot-color, #d3dce5);
  --embla-pagination-bullet-color-active: var(--wp--custom--brandy--slider--dot-active-color, #122940);
  /* Track behind a filling/expanded bullet (progress-pill style dots). */
  --embla-pagination-bullet-track-color: var(
    --wp--custom--brandy--slider--dot-track-color,
    rgba(0, 0, 0, 0.12)
  );
}

/* ---------------------------------------------------------------------------
   Controls placement (data-controls-placement)

   A third axis alongside data-nav-style / data-dots-style: WHERE the control
   cluster sits, independent of how the arrows and dots look. CSS-only — no JS
   renderer. The `.embla__controls` wrapper is emitted by SliderControlsMarkup
   only for grouped placements, so `default` keeps the historical markup
   (edge-pinned arrows, dots below) untouched.

   Structure only. Colors and sizes belong to the theme.
   --------------------------------------------------------------------------- */
.embla__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  column-gap: var(--embla-controls-gap, 1.2rem);
}

/* Undo the edge-pinning .embla__button carries for the default placement. */
.embla__controls .embla__button {
  position: relative;
  top: auto;
  transform: none;
}

/* Keep a disabled arrow in flow — hiding it would re-center the row mid-use. */
.embla__controls .embla__button:disabled {
  display: inline-flex;
  opacity: 0.35;
  pointer-events: none;
}

.embla__controls .embla__dots {
  margin-top: 0;
}

/* Placement selectors key off the attribute alone rather than `.embla[…]` so the
   editor's static skeleton — which has no .embla node — matches the same rules.
   Both hosts establish a positioning context: `.embla` is already relative, and
   the editor preview wrapper is made relative in each block's editor.scss. */

/* Floating over the slide. The row itself is click-through so it never blocks
   drag/swipe on the slide beneath; only its children take pointer events. */
[data-controls-placement="grouped-bottom"] > .embla__controls {
  position: absolute;
  inset-inline: 0;
  bottom: var(--embla-controls-offset, 3rem);
  pointer-events: none;
}

[data-controls-placement="grouped-bottom"] > .embla__controls > * {
  pointer-events: auto;
}

/* Same row, in normal flow beneath the slider (product collections, where an
   overlay would cover the last row of cards). */
[data-controls-placement="grouped-below"] > .embla__controls {
  margin-top: var(--embla-controls-offset, 2rem);
}

@media screen and (max-width: 767.98px) {
  [data-controls-placement="grouped-bottom"] > .embla__controls {
    --embla-controls-offset: 2rem;
  }
}

/* Slides all fit: no snap to move to, so no controls (mirrors .embla__dots). */
.embla.embla--static .embla__controls {
  display: none;
}

/* Editor canvas: the static control skeleton has no `.embla` host and no JS to
   opt the dots in, so give it the positioning context and visibility the
   frontend gets from `.embla` + the block's --embla-pagination-display. Scoped
   to .is-editor-preview, which only the Edit components emit. */
.is-editor-preview[data-controls-placement] {
  position: relative;
}

.is-editor-preview .embla__dots {
  display: flex;
}

/* ---------------------------------------------------------------------------
   Controls reveal (data-controls-reveal)

   A fourth axis alongside placement/nav/dots: WHETHER the cluster is visible at
   rest. CSS-only, like placement — no JS renderer, nothing to register.

   Each control returns from the edge it lives on, so the motion reads as the
   cluster arriving from outside the slider rather than one block fading up:
   the prev arrow travels left-to-right, the next arrow right-to-left, and the
   dots and scrollbar rise from below.

   MOTION IS ON `translate`, NOT `transform`. `.embla__button` already carries
   `transform: translateY(-50%)` to centre itself against the viewport, and the
   grouped placement resets that to `none`. Writing the reveal offset into
   `transform` would clobber the centring in one placement and be clobbered in
   the other; the individual `translate` property composes with `transform`
   instead of replacing it, so both placements keep their own vertical maths.

   The whole section sits behind `hover: hover` and `pointer: fine`. A touch
   device has no hover state to reveal anything with, so the controls would be
   permanently invisible and the slider would lose its arrows outright.
   --------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  /* Direct children only. In a grouped placement the dots sit INSIDE
     `.embla__controls`, and matching them here as well would stack the row's
     translate on top of their own and send them twice as far. */
  [data-controls-reveal="hover"] .embla__buttons .embla__button,
  [data-controls-reveal="hover"] > .embla__dots,
  [data-controls-reveal="hover"] > .embla__progress,
  [data-controls-reveal="hover"] > .embla__controls {
    opacity: 0;
    /* No `pointer-events` juggling here, deliberately. The obvious version —
       `none` while hidden, `auto` while shown — collides with the click-through
       `grouped-bottom` sets up (row `none`, children `auto`, so a swipe reaches
       the slide underneath): the reveal's `:hover` selector outranks it and
       would hand the row back its clicks. It also breaks its own trigger, since
       a `pointer-events: none` arrow cannot be hovered, and the arrows hang half
       outside the slider where they are the first thing a pointer meets.
       Nothing is lost by omitting it: reaching a hidden control means hovering
       the slider, which is what makes it visible. */
    transition:
      opacity var(--embla-reveal-duration, 0.35s) ease,
      translate var(--embla-reveal-duration, 0.35s) cubic-bezier(0.4, 0, 0.2, 1);
  }

  /* Arrows are scoped to `.embla__buttons`, the wrapper only the default
     placement emits. In a grouped placement the arrows ride the row up from the
     bottom with the dots — animating them sideways inside a rising row reads as
     two unrelated movements at once. */
  [data-controls-reveal="hover"] .embla__buttons .embla__button--prev {
    translate: calc(var(--embla-reveal-distance, 1rem) * -1) 0;
  }

  [data-controls-reveal="hover"] .embla__buttons .embla__button--next {
    translate: var(--embla-reveal-distance, 1rem) 0;
  }

  [data-controls-reveal="hover"] > .embla__dots,
  [data-controls-reveal="hover"] > .embla__progress,
  [data-controls-reveal="hover"] > .embla__controls {
    translate: 0 var(--embla-reveal-distance, 1rem);
  }

  /* `:focus-within` is not decoration. Without it a keyboard user tabs onto an
     arrow that is still at opacity 0 and cannot see what they have focused. */
  [data-controls-reveal="hover"]:hover .embla__buttons .embla__button,
  [data-controls-reveal="hover"]:focus-within .embla__buttons .embla__button,
  [data-controls-reveal="hover"]:hover > .embla__dots,
  [data-controls-reveal="hover"]:focus-within > .embla__dots,
  [data-controls-reveal="hover"]:hover > .embla__progress,
  [data-controls-reveal="hover"]:focus-within > .embla__progress,
  [data-controls-reveal="hover"]:hover > .embla__controls,
  [data-controls-reveal="hover"]:focus-within > .embla__controls {
    opacity: 1;
    translate: 0 0;
  }
}

/* The reveal itself is the feature, so it still happens when motion is reduced
   — the controls just fade in where they belong instead of travelling to it. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
  [data-controls-reveal="hover"] .embla__buttons .embla__button,
  [data-controls-reveal="hover"] > .embla__dots,
  [data-controls-reveal="hover"] > .embla__progress,
  [data-controls-reveal="hover"] > .embla__controls {
    translate: none;
    transition: opacity var(--embla-reveal-duration, 0.35s) ease;
  }
}

/* A slide's shadow is painted outside the slide, so the clip boundary has to
   sit a little outside the track or every card's shadow ends in a straight cut
   at the slider's edge.

   `overflow` clips at the PADDING box, which is the whole reason this rule has
   the shape it does: 20px of padding pushes the boundary outwards, and a
   negative margin plus a wider box hand the layout back what the padding took.

   The modern-looking alternative was tried and does not work. `clip-path:
   inset(-20px)` moves the boundary with no padding at all, but a clip-path
   clips paint only — the off-screen half of the strip stays in the scrollable
   overflow, and the whole PAGE becomes horizontally scrollable by its width
   (measured on a five-slide row: 781px of stray sideways scroll). The one
   property that separates "clip the paint" from "contain the scroll" is
   `overflow-clip-margin`, and Safari implements none of it — nothing through 27,
   nothing on iOS through 26.6. So padding it is, and that is also why every
   carousel library ends up here.

   The block axis is compensated on .embla__viewport alone, below, not in this
   rule: .editor-embla is a block wrapper in the editor with no flow-root parent
   to stop a negative margin escaping into the editor's own layout. */
.embla__viewport,
.editor-embla {
  /* Named because the same number has to be known in three more places: the
     compensation below, the vertical rules that drop both, and the edge fade,
     whose gradient starts at the visible track edge rather than at the box
     edge and would be off by exactly this much if it guessed. */
  --embla-shadow-room: 20px;

  overflow: hidden !important;
  padding: var(--embla-shadow-room);
  margin-left: calc(var(--embla-shadow-room) * -1);
  width: calc(100% + var(--embla-shadow-room) * 2);
}

/* .embla contains the negative block margins below. Without a flow-root here
   the viewport's -20px top margin collapses straight through .embla and drags
   the whole slider — controls and all — up by 20px, instead of letting only the
   shadow paint up there. Which is what makes the compensation below look broken
   if it is added on its own. */
.embla {
  display: flow-root;
}

/* Give back the 40px the block-axis padding costs. The inline axis has always
   been compensated (the negative margin and the wider box above); this axis was
   not, so every slider on the page carried 40px of dead height to rent 20px of
   shadow room at the top and bottom. */
.embla__viewport {
  margin-block: calc(var(--embla-shadow-room) * -1);
}

/* ---------------------------------------------------------------------------
   Faded edges (.embla--fade-edges)

   The strip dissolves into the background where it leaves the viewport instead
   of ending on a ruled edge, which is what says "this continues" without
   spending a control on saying it.

   A MASK, NOT AN OVERLAY. A gradient overlay has to know the colour behind the
   slider to fade into it, so it breaks the moment the section sits on an image,
   a gradient, or a dark background. A mask takes alpha out of the slides
   themselves, so whatever is behind shows through and nothing has to be
   declared twice.

   Two things the gradient has to be told, because it cannot see them:

   1. WHERE THE TRACK ACTUALLY STARTS. The mask covers the border box, which
      reaches --embla-shadow-room past the visible track on each side (see
      above). A gradient starting at 0 would begin fading in the shadow gutter
      and reach full opacity before the first card, missing by exactly that
      much. Hence every stop is offset by the room.

   2. WHICH SIDES HAVE ANYTHING LEFT TO SHOW. Fading the left edge of a slider
      already parked on its first slide is a lie — nothing is hidden there, so
      the fade reads as a rendering fault. --embla-fade-start/-end are 0/1
      switches the JS flips from Embla's scroll progress (see the registry's
      fade.attach); at 0 both stops for that side collapse to 0 and the mask is
      opaque right out to the box edge, shadow gutter included.

   Direction and room are variables so the vertical rules can retarget the same
   single declaration instead of restating the gradient per breakpoint. On that
   axis the room is 0, because the vertical rules drop the block padding. */
.embla.embla--fade-edges .embla__viewport {
  --embla-fade-in-from: calc(
    var(--embla-fade-room, var(--embla-shadow-room)) * var(--embla-fade-start, 0)
  );
  --embla-fade-in-to: calc(
    (var(--embla-fade-room, var(--embla-shadow-room)) + var(--embla-fade-size, 48px)) *
      var(--embla-fade-start, 0)
  );
  --embla-fade-out-from: calc(
    (var(--embla-fade-room, var(--embla-shadow-room)) + var(--embla-fade-size, 48px)) *
      var(--embla-fade-end, 0)
  );
  --embla-fade-out-to: calc(
    var(--embla-fade-room, var(--embla-shadow-room)) * var(--embla-fade-end, 0)
  );

  -webkit-mask-image: linear-gradient(
    var(--embla-fade-direction, to right),
    transparent var(--embla-fade-in-from),
    #000 var(--embla-fade-in-to),
    #000 calc(100% - var(--embla-fade-out-from)),
    transparent calc(100% - var(--embla-fade-out-to))
  );
  mask-image: linear-gradient(
    var(--embla-fade-direction, to right),
    transparent var(--embla-fade-in-from),
    #000 var(--embla-fade-in-to),
    #000 calc(100% - var(--embla-fade-out-from)),
    transparent calc(100% - var(--embla-fade-out-to))
  );
}

/* Set on .embla, read on the viewport — the switches ride down by inheritance
   so the JS only ever touches one element. */
.embla.embla--fade-edges.is-fade-start {
  --embla-fade-start: 1;
}

.embla.embla--fade-edges.is-fade-end {
  --embla-fade-end: 1;
}

.embla__container,
.editor-embla ul {
  display: flex !important;
  touch-action: pan-y pinch-zoom;
  gap: 0 !important;
  max-width: unset !important;
  margin-left: calc(var(--embla-gap, 30px) * -1);
  flex-wrap: nowrap !important;
}

.wp-block-brandy-testimonials .embla__container {
  margin-left: 0;
}

.embla__container:not(.block-editor-block-list__layout) {
  user-select: none;
}

.embla__slide,
.editor-embla ul li {
  transform: translate3d(0, 0, 0);
  min-width: 0;
}

.embla__slide:not(.wp-block-brandy-testimonial-card),
.editor-embla ul li {
  flex: 0 0 calc(100% / var(--embla-slides-desktop, 4));
  padding-left: var(--embla-gap, 30px);
}

.wp-block-brandy-testimonial-card {
  flex: 0 0
    calc(
      (100% - var(--embla-gap, 30px) * (var(--embla-slides-desktop, 4) - 1)) /
        var(--embla-slides-desktop, 4)
    );
  margin-right: var(--embla-gap, 30px) !important;
}

@media screen and (min-width: 480px) and (max-width: 1023px) {
  .embla__slide:not(.wp-block-brandy-testimonial-card),
  .editor-embla ul li {
    flex: 0 0 calc(100% / var(--embla-slides-tablet, 3));
  }

  .wp-block-brandy-testimonial-card {
    flex: 0 0
      calc(
        (100% - var(--embla-gap, 30px) * (var(--embla-slides-tablet, 3) - 1)) /
          var(--embla-slides-tablet, 3)
      );
  }
}

@media screen and (max-width: 479px) {
  .embla__slide:not(.wp-block-brandy-testimonial-card),
  .editor-embla ul li {
    flex: 0 0 calc(100% / var(--embla-slides-mobile, 2));
  }

  .wp-block-brandy-testimonial-card {
    flex: 0 0
      calc(
        (100% - var(--embla-gap, 30px) * (var(--embla-slides-mobile, 2) - 1)) /
          var(--embla-slides-mobile, 2)
      );
  }
}

/* ---------------------------------------------------------------------------
   Vertical axis.

   Embla scrolls whichever axis it is given, but the slide sizing above is
   width-only: in a column track `flex-basis` resolves against the HEIGHT, so a
   vertical rail needs its own basis, its gap moved from the inline to the block
   side, and — unlike a horizontal one — a bounded viewport. Without a height
   every slide is on screen at once and there is nothing left to scroll.

   The per-breakpoint classes are stamped by LoopLayout::render_slider(), and
   the media queries below are the same ranges the widths use, so the engine's
   axis (set from the matching data-axis-* attributes in embla-extra.js) and the
   layout always agree.
   --------------------------------------------------------------------------- */
/* The fade follows the scroll axis. Room is 0 here because the vertical rules
   drop the block padding, so the gradient's stops need no offset on this axis. */
.embla.embla--axis-y-desktop {
  --embla-fade-direction: to bottom;
  --embla-fade-room: 0px;
}

.embla.embla--axis-y-desktop .embla__container {
  /* The horizontal rules pull the track left by one gap to cancel the leading
     slide's padding; on this axis that offset belongs on the block edge. */
  margin-left: 0;
  width: 100%;
}

.embla.embla--axis-y-desktop .embla__viewport {
  height: var(--embla-viewport-height, 600px);
  /* Shadow room belongs on the cross axis, and the cross axis has swapped: the
     strip scrolls up and down now, so room on the block axis is no longer room
     — it is the next slide showing through as a stray band under the track.
     Dropping the padding drops the need for its compensation with it. The
     inline inset stays; that is the cross axis here. */
  padding-block: 0;
  margin-block: 0;
}

.embla.embla--axis-y-desktop .embla__container {
  flex-direction: column;
  margin-top: calc(var(--embla-gap, 30px) * -1);
  height: 100%;
  touch-action: pan-x pinch-zoom;
}

.embla.embla--axis-y-desktop .embla__container > * {
  flex: 0 0 calc(100% / var(--embla-slides-desktop, 4));
  padding-left: 0;
  padding-top: var(--embla-gap, 30px);
}

@media screen and (min-width: 480px) and (max-width: 1023px) {
  /* Fade follows the scroll axis — see the desktop rule. */
  .embla.embla--axis-y-tablet {
    --embla-fade-direction: to bottom;
    --embla-fade-room: 0px;
  }

  .embla.embla--axis-y-tablet .embla__container {
    /* The horizontal rules pull the track left by one gap to cancel the leading
       slide's padding; on this axis that offset belongs on the block edge. */
    margin-left: 0;
    width: 100%;
  }

  .embla.embla--axis-y-tablet .embla__viewport {
    height: var(--embla-viewport-height, 600px);
    /* Shadow room follows the cross axis — see the desktop rule. */
    padding-block: 0;
    margin-block: 0;
  }

  .embla.embla--axis-y-tablet .embla__container {
    flex-direction: column;
    margin-top: calc(var(--embla-gap, 30px) * -1);
    height: 100%;
    touch-action: pan-x pinch-zoom;
  }

  .embla.embla--axis-y-tablet .embla__container > * {
    flex: 0 0 calc(100% / var(--embla-slides-tablet, 3));
    padding-left: 0;
    padding-top: var(--embla-gap, 30px);
  }

  /* Vertical on desktop, horizontal here: undo the column track rather than
     leave the desktop class winning on a narrower screen. */
  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) {
    --embla-fade-direction: to right;
    --embla-fade-room: var(--embla-shadow-room, 20px);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) .embla__viewport {
    height: auto;
    /* Horizontal again, so the block-axis room and its compensation come back. */
    padding-block: var(--embla-shadow-room);
    margin-block: calc(var(--embla-shadow-room) * -1);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) .embla__container {
    flex-direction: row;
    margin-top: 0;
    margin-left: calc(var(--embla-gap, 30px) * -1);
    height: auto;
    touch-action: pan-y pinch-zoom;
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) .embla__container > * {
    padding-top: 0;
    padding-left: var(--embla-gap, 30px);
  }
}

@media screen and (max-width: 479px) {
  /* Fade follows the scroll axis — see the desktop rule. */
  .embla.embla--axis-y-mobile {
    --embla-fade-direction: to bottom;
    --embla-fade-room: 0px;
  }

  .embla.embla--axis-y-mobile .embla__container {
    /* The horizontal rules pull the track left by one gap to cancel the leading
       slide's padding; on this axis that offset belongs on the block edge. */
    margin-left: 0;
    width: 100%;
  }

  .embla.embla--axis-y-mobile .embla__viewport {
    height: var(--embla-viewport-height, 600px);
    /* Shadow room follows the cross axis — see the desktop rule. */
    padding-block: 0;
    margin-block: 0;
  }

  .embla.embla--axis-y-mobile .embla__container {
    flex-direction: column;
    margin-top: calc(var(--embla-gap, 30px) * -1);
    height: 100%;
    touch-action: pan-x pinch-zoom;
  }

  .embla.embla--axis-y-mobile .embla__container > * {
    flex: 0 0 calc(100% / var(--embla-slides-mobile, 2));
    padding-left: 0;
    padding-top: var(--embla-gap, 30px);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) {
    --embla-fade-direction: to right;
    --embla-fade-room: var(--embla-shadow-room, 20px);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) .embla__viewport {
    height: auto;
    /* Horizontal again, so the block-axis room and its compensation come back. */
    padding-block: var(--embla-shadow-room);
    margin-block: calc(var(--embla-shadow-room) * -1);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) .embla__container {
    flex-direction: row;
    margin-top: 0;
    margin-left: calc(var(--embla-gap, 30px) * -1);
    height: auto;
    touch-action: pan-y pinch-zoom;
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) .embla__container > * {
    padding-top: 0;
    padding-left: var(--embla-gap, 30px);
  }
}

/* ---------------------------------------------------------------------------
   Vertical axis — controls.

   The chrome has to turn with the track. Left/right arrows on a rail that
   scrolls up and down point at nothing, and a chevron still lying on its side
   says "previous is that way" while the slide arrives from above.

   Arrows therefore move to the top and bottom edges, centred horizontally, and
   their glyphs rotate a quarter turn: the prev chevron points left, and a
   clockwise quarter turn is exactly what makes it point up (and the next one
   down). Rotating the existing icon keeps one set of markup for both axes.

   Dots stack into a column beside the track for the same reason — a horizontal
   row of dots under a vertical rail reads as belonging to something else.

   Written per breakpoint, mirroring the layout rules above, because the desktop
   class stays on the element at every width and has to be undone wherever a
   narrower breakpoint runs horizontally.
   --------------------------------------------------------------------------- */

.embla.embla--axis-y-desktop .embla__buttons .embla__button--prev,
.embla.embla--axis-y-desktop > .embla__button--prev {
  top: calc(var(--embla-button-height, 50px) / 2 * -1);
  bottom: auto;
  left: 50%;
  right: auto;
  transform: translateX(-50%);
}

.embla.embla--axis-y-desktop .embla__buttons .embla__button--next,
.embla.embla--axis-y-desktop > .embla__button--next {
  top: auto;
  bottom: calc(var(--embla-button-height, 50px) / 2 * -1);
  left: 50%;
  right: auto;
  transform: translateX(-50%);
}

.embla.embla--axis-y-desktop .embla__button svg {
  transform: rotate(90deg);
}

.embla.embla--axis-y-desktop > .embla__dots {
  position: absolute;
  top: 50%;
  right: calc(var(--embla-pagination-bullet-size, 12px) * -1 - 12px);
  flex-direction: column;
  margin-top: 0;
  transform: translateY(-50%);
}

/* Reveal-on-hover slides each control in from the edge it lives on; on this
   axis the arrows live on the top and bottom edges, and the dots on the right. */
@media (hover: hover) and (pointer: fine) {
  .embla.embla--axis-y-desktop[data-controls-reveal="hover"]
    .embla__buttons
    .embla__button--prev {
    translate: 0 calc(var(--embla-reveal-distance, 1rem) * -1);
  }

  .embla.embla--axis-y-desktop[data-controls-reveal="hover"]
    .embla__buttons
    .embla__button--next {
    translate: 0 var(--embla-reveal-distance, 1rem);
  }

  .embla.embla--axis-y-desktop[data-controls-reveal="hover"] > .embla__dots {
    translate: var(--embla-reveal-distance, 1rem) 0;
  }

  .embla.embla--axis-y-desktop[data-controls-reveal="hover"]:hover
    > .embla__dots,
  .embla.embla--axis-y-desktop[data-controls-reveal="hover"]:focus-within
    > .embla__dots {
    translate: 0 0;
  }
}

@media screen and (min-width: 480px) and (max-width: 1023px) {
  .embla.embla--axis-y-tablet .embla__buttons .embla__button--prev,
  .embla.embla--axis-y-tablet > .embla__button--prev {
    top: calc(var(--embla-button-height, 50px) / 2 * -1);
    bottom: auto;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
  }

  .embla.embla--axis-y-tablet .embla__buttons .embla__button--next,
  .embla.embla--axis-y-tablet > .embla__button--next {
    top: auto;
    bottom: calc(var(--embla-button-height, 50px) / 2 * -1);
    left: 50%;
    right: auto;
    transform: translateX(-50%);
  }

  .embla.embla--axis-y-tablet .embla__button svg {
    transform: rotate(90deg);
  }

  .embla.embla--axis-y-tablet > .embla__dots {
    position: absolute;
    top: 50%;
    right: calc(var(--embla-pagination-bullet-size, 12px) * -1 - 12px);
    flex-direction: column;
    margin-top: 0;
    transform: translateY(-50%);
  }

  /* Vertical on desktop, horizontal here: put the chrome back on the sides. */
  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) .embla__buttons .embla__button--prev,
  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) > .embla__button--prev {
    top: 50%;
    bottom: auto;
    left: -20px;
    right: auto;
    transform: translateY(-50%);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) .embla__buttons .embla__button--next,
  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) > .embla__button--next {
    top: 50%;
    bottom: auto;
    left: auto;
    right: -20px;
    transform: translateY(-50%);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) .embla__button svg {
    transform: none;
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-tablet) > .embla__dots {
    position: static;
    flex-direction: row;
    margin-top: 20px;
    transform: none;
  }
}

@media screen and (max-width: 479px) {
  .embla.embla--axis-y-mobile .embla__buttons .embla__button--prev,
  .embla.embla--axis-y-mobile > .embla__button--prev {
    top: -20px;
    bottom: auto;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
  }

  .embla.embla--axis-y-mobile .embla__buttons .embla__button--next,
  .embla.embla--axis-y-mobile > .embla__button--next {
    top: auto;
    bottom: -20px;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
  }

  .embla.embla--axis-y-mobile .embla__button svg {
    transform: rotate(90deg);
  }

  .embla.embla--axis-y-mobile > .embla__dots {
    position: absolute;
    top: 50%;
    right: calc(var(--embla-pagination-bullet-size, 12px) * -1 - 8px);
    flex-direction: column;
    margin-top: 0;
    transform: translateY(-50%);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) .embla__buttons .embla__button--prev,
  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) > .embla__button--prev {
    top: 50%;
    bottom: auto;
    left: -20px;
    right: auto;
    transform: translateY(-50%);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) .embla__buttons .embla__button--next,
  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) > .embla__button--next {
    top: 50%;
    bottom: auto;
    left: auto;
    right: -20px;
    transform: translateY(-50%);
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) .embla__button svg {
    transform: none;
  }

  .embla.embla--axis-y-desktop:not(.embla--axis-y-mobile) > .embla__dots {
    position: static;
    flex-direction: row;
    margin-top: 20px;
    transform: none;
  }
}

/* The trailing gap on the last card only spaces the wrap-around in loop mode.
   Outside loop it is overflow Embla counts as scrollable slack, which fakes an
   extra snap when every card already fits. embla-extra.js sets this class from
   Embla's resolved loop option (it turns loop off itself when there are too few
   slides to wrap) and re-measures. */
.embla--no-loop
  .embla__container
  > .wp-block-brandy-testimonial-card:last-child {
  margin-right: 0 !important;
}

/* Slides all fit: no snap to move to, so no controls. */
.embla.embla--static .embla__dots,
.embla.embla--static .embla__progress {
  display: none;
}

.embla__buttons {
  display: flex;
  gap: 0.6rem;
  align-items: center;
}
.embla__button {
  cursor: pointer;
  display: inline-flex;
  width: var(--embla-button-width, 50px);
  height: var(--embla-button-height, 50px);
  /* --embla-nav-* is the per-instance override layer (SliderControls::nav_colors).
     It is deliberately NOT seeded on .embla above: a seeded property is always
     defined, so `var(seeded, fallback)` can never reach its fallback and a nav
     variant could not keep its own colour model when the author has chosen
     nothing. Unseeded, "unset" is expressible, which is what lets the theme's
     `blank` chevrons go on inheriting until someone picks a colour.

     `color` carries the override as well as `background` because three blocks
     (Slider, MediaGallery, ShowcaseSlider) emit their chevron without the
     .embla__button__svg class, so it strokes from currentColor rather than from
     --embla-button-icon-color. Routing the override through `color` reaches
     those without rewriting six render paths' markup. */
  background: var(--embla-nav-bg-color, var(--embla-button-background-color, #ffffff));
  color: var(--embla-nav-icon-color, var(--embla-button-color, #122940));
  border: var(--embla-button-border, none);
  border-radius: var(--embla-button-radius, 50%);
  box-shadow: var(--embla-button-shadow, 0px 10px 25px 0px #377e620d);
  align-items: center;
  justify-content: center;
  transition: background var(--theme-component-transition-duration, 0.2s)
      ease-in-out,
    border var(--theme-component-transition-duration, 0.2s) ease-in-out,
    box-shadow var(--theme-component-transition-duration, 0.2s) ease-in-out;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
.embla__button:disabled {
  display: none;
}
.embla__button__svg {
  width: var(--embla-button-icon-width, 14px);
  height: var(--embla-button-icon-height, 14px);
}
.embla__button__svg path {
  stroke: var(--embla-nav-icon-color, var(--embla-button-icon-color, #808890));
  fill: var(--embla-button-icon-fill-color, transparent);
  transition: all ease-in-out var(--theme-component-transition-duration, 0.2s);
}
.embla__button:hover {
  background: var(
    --embla-nav-bg-color-hover,
    var(--embla-button-background-color-hover, #edf3f9)
  );
  box-shadow: var(--embla-button-shadow-hover, 0px 10px 25px 0px #12294026);
  border: var(--embla-button-border-hover, none);
  color: var(
    --embla-nav-icon-color-hover,
    var(--embla-button-color-hover, #122940)
  );
}

.embla__button:hover .embla__button__svg path {
  stroke: var(
    --embla-nav-icon-color-hover,
    var(--embla-button-icon-color-hover, #122940)
  );
  fill: var(--embla-button-icon-fill-color-hover, transparent);
}

.embla__button--prev {
  left: calc(var(--embla-button-width, 50px) / 2 * -1);
}

.embla__button--next {
  right: calc(var(--embla-button-width, 50px) / 2 * -1);
}

@media screen and (max-width: 783px) {
  .embla__button--prev {
    left: -20px;
  }

  .embla__button--next {
    right: -20px;
  }

}

/* 40px, not 20px, because the viewport's 20px of block padding used to sit
   between the track and this row and is now compensated away — the gap readers
   have always seen is the sum of the two. Declaring it here keeps the spacing a
   decision instead of a side effect of the shadow room. */
.embla__dots {
  display: var(--embla-pagination-display, none);
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  margin-top: 40px;
  gap: var(--embla-pagination-bullet-spacing, 10px);
}
.embla__dot {
  appearance: none;
  /* Fallback repeated from the token block above. Every other control property
     in this file carries one; these two were the exception, which is why a
     missing token host turned the dots invisible rather than merely off-brand. */
  background-color: var(
    --embla-dots-color,
    var(--embla-pagination-bullet-color, #d3dce5)
  );
  touch-action: manipulation;
  display: inline-flex;
  text-decoration: none;
  cursor: pointer;
  border: 0;
  padding: 0;
  margin: 0;
  width: var(--embla-pagination-bullet-size, 15px);
  height: var(--embla-pagination-bullet-size, 15px);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
}

.embla__dot--selected {
  background-color: var(
    --embla-dots-color-active,
    var(--embla-pagination-bullet-color-active, #122940)
  );
}

.embla__progress {
  display: var(--embla-scrollbar-display, none);
  border-radius: 10px;
  background-color: var(--embla-scrollbar-bg-color);
  position: relative;
  height: 9px;
  justify-self: flex-end;
  align-self: center;
  width: 100%;
  overflow: hidden;
  /* Same 40px as .embla__dots, and for the same reason: this row sits directly
     under the track, where the viewport's block padding used to add the other
     half of the gap. A scrollbar slider and a dots slider have to sit the same
     distance from their track. */
  margin-top: 40px;
}
.embla__progress__bar {
  background-color: var(--embla-scrollbar-drag-bg-color);
  position: absolute;
  width: 100%;
  top: 0;
  bottom: 0;
  left: -100%;
  border-radius: 10px;
}

/* Reference dots variant: "NN / NN" fraction instead of bullets. */
.embla__dots--fraction {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-numeric: tabular-nums;
  font-size: var(--embla-pagination-fraction-size, 16px);
  letter-spacing: 0.05em;
  /* The fraction has no bullets, so the ACTIVE dot colour is its text colour —
     one choice keeps a slider's pagination consistent whichever style it wears. */
  color: var(
    --embla-dots-color-active,
    var(--embla-pagination-bullet-color-active, #122940)
  );
}

/* ---------------------------------------------------------------------------
   Dim inactive slides — opt-in, stamped as `data-dim-inactive` on `.embla` by
   SliderControls::data_attrs() when a block enables the setting.

   Targets `.embla__container > *` rather than `.embla__slide`, because the
   slide class is not uniform across the blocks that share this stylesheet:
   Testimonials slides are `.wp-block-brandy-testimonial-card`, loop blocks
   render plain `li`, and only the Slider block emits `.embla__slide`. The
   container's children ARE `emblaApi.slideNodes()`, which is exactly the set
   embla-slide-motion.js toggles `.is-center` on, so the two agree by
   construction.

   Lights the CENTRE BAND and dims the outermost visible slide on each side, so
   a row reads as framed: 3 on show leaves 1 centred, 4 leaves 2, 5 leaves 3.
   A slide therefore stays dimmed on its way in, lights as it reaches the
   middle, and dims again on its way out.

   Desktop only. A phone shows one slide edge-to-edge with no surround to frame
   it against, and the tracker leaves a run that short fully lit anyway.

   No opacity transition, deliberately. The band is recomputed every frame the
   strip moves, so a fade would still be catching up to a slide's previous state
   while it travels — the highlight lags the slide it belongs to. Switching
   instantly keeps the lit slide and the centre of the viewport in step, and
   leaves nothing for prefers-reduced-motion to turn off.
   --------------------------------------------------------------------------- */
@media (min-width: 768px) {
  /* `.is-dim-ready` is the tracker's signal that it has measured the band. It
     gates the dim so the effect can never darken slides before one is lit:
     without it the whole slider renders grey from first paint until Embla
     boots, and stays grey anywhere the tracker cannot run. */
  .embla[data-dim-inactive].is-dim-ready
    .embla__container
    > *:not(.is-center) {
    opacity: var(--embla-slide-dim-opacity, 0.2);
  }
}
