/* ==========================================================================
   Homepage hero slider
   Replaces the two-photo collage with one rounded slide area of the same
   footprint. The floating badges are not part of this — they sit over it
   as siblings and must not move when the image behind them changes.
   ========================================================================== */

.hero-slider {
  position: relative;
  /* The collage's own proportion, so the hero keeps its height and the
     badges keep their positions. Also reserves the box before the image
     loads, which is what stops the layout shifting. */
  aspect-ratio: 16 / 10;
  border-radius: 1.5rem;
  overflow: hidden;
  box-shadow: var(--shadow-lift, 0 18px 40px rgba(20, 20, 40, .16));
  background: #f2f2f5;
  /* A left-to-right swipe on the hero is a request for the previous
     slide, not for the previous page. Without this, Chrome and Safari
     read it as the back gesture and navigate away mid-swipe. */
  overscroll-behavior-x: contain;
  touch-action: pan-y;
}
.hero-slider:focus-visible {
  outline: 3px solid var(--violet, #5B3FA0);
  outline-offset: 3px;
}

.hero-slider__track { position: absolute; inset: 0; }

.hero-slider__slide {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  /* Crossfade rather than a horizontal slide: the badges sit on top, and
     movement underneath them reads as the badges drifting. A fade leaves
     them visually still. */
  transition: opacity .55s ease-in-out;
  will-change: opacity;
}
.hero-slider__slide.is-current { opacity: 1; }
.hero-slider__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---- controls ---- */

.hero-slider__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 2.4rem;
  height: 2.4rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .9);
  color: #1f2230;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .16);
  cursor: pointer;
  opacity: 0;
  transition: opacity .2s ease, background .2s ease;
}
.hero-slider__arrow--prev { left: .75rem; }
.hero-slider__arrow--next { right: .75rem; }

/* Revealed on hover, but always present for keyboard and touch — an
   arrow that only exists on hover is unreachable on a phone. */
.hero-slider:hover .hero-slider__arrow,
.hero-slider:focus-within .hero-slider__arrow { opacity: 1; }
.hero-slider__arrow:focus-visible {
  opacity: 1;
  outline: 3px solid var(--violet, #5B3FA0);
  outline-offset: 2px;
}
.hero-slider__arrow:hover { background: #fff; }

@media (hover: none) {
  .hero-slider__arrow { opacity: 1; }
}

.hero-slider__dots {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: .8rem;
  transform: translateX(-50%);
  display: flex;
  gap: .4rem;
  padding: .3rem .5rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, .28);
  backdrop-filter: blur(3px);
}
.hero-slider__dot {
  width: .5rem;
  height: .5rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .55);
  cursor: pointer;
  transition: background .2s ease, width .2s ease;
}
.hero-slider__dot.is-current { background: #fff; width: 1.25rem; border-radius: 999px; }
.hero-slider__dot:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ---- reduced motion ---- */
/* Asked not to be moved: no fade, and hero-slider.js does not autoplay.
   The controls still work, so the slider is not taken away. */
.hero-slider.is-reduced .hero-slider__slide { transition: none; }

@media (prefers-reduced-motion: reduce) {
  .hero-slider__slide { transition: none; }
  .hero-slider__arrow { transition: none; }
}

/* ---- responsive ---- */
/* The old collage was hidden below md (d-none d-md-block on .hero-visual)
   and the slider inherits that from the same wrapper, so small screens
   behave exactly as they did. These only soften the controls where the
   slide area itself gets short. */
@media (max-width: 991.98px) {
  .hero-slider { border-radius: 1.25rem; }
  .hero-slider__arrow { width: 2.1rem; height: 2.1rem; }
}

/* ---- Filling the hero ----
   .hero-visual carries the hero's height (min-height, and the badges are
   positioned against it). Sized by its own aspect-ratio the slider came
   out shorter than that box, leaving a strip of background showing under
   it. Pinning it to the wrapper's edges makes the slide exactly the area
   it sits in, and the badges — positioned against the same wrapper — do
   not move. */
.hero-visual { position: relative; }

.hero-visual .hero-slider {
  position: absolute;
  inset: 0;
  /* The wrapper's height is the authority now; a ratio here would fight
     it. The box is still reserved before the image loads, because
     .hero-visual's min-height is fixed — so this costs no layout shift. */
  aspect-ratio: auto;
}

/* Taller than the collage needed, now that one image has to carry the
   whole area rather than two overlapping cards with gaps between them. */
@media (min-width: 992px) {
  .hero-visual { min-height: 460px; }
}
@media (min-width: 1400px) {
  .hero-visual { min-height: 520px; }
}

/* ---- Filling the hero on large screens ----
   The image used to sit as a card in the right column, leaving ~320px of
   empty page to its right and the hero's vertical padding above and below
   it. Pinned to the hero instead, it runs from the horizontal midpoint to
   the right edge of the viewport and the full height of the section.

   Pinned rather than bled with negative margins because the distance to
   the viewport edge depends on the container's width at each breakpoint,
   and `right: 0` on the hero is exact at every one of them.

   The copy deliberately does NOT sit on the image. Slides are uploaded by
   an admin, so a photo could be light, busy, or white-backgrounded — text
   over it would be legible on some uploads and unreadable on others. It
   stays on the page's own background, where it is legible whatever is
   uploaded. */
@media (min-width: 992px) {
  .hero { position: relative; overflow: hidden; }

  /* .container is position:relative, which made *it* the containing block
     for the absolute .hero-visual below — so "right: 0" meant the
     container's right edge, not the window's, and the image stopped
     320px short. Static here hands that job to .hero. The hero's
     decorative blobs are siblings of .container, so they are unaffected. */
  .hero > .container { position: static; }

  .hero .hero-visual {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    left: 48%;
    width: auto;
    height: auto;
    min-height: 0;
    margin: 0;
  }

  /* Only the left corners: a rounded corner against the window edge reads
     as a mistake rather than a choice. */
  .hero .hero-visual .hero-slider {
    border-radius: 1.5rem 0 0 1.5rem;
  }

  /* The section's height now comes from the copy, which is no longer
     sharing the row with anything. */
  .hero { min-height: 640px; }

  /* The badges were positioned as a percentage of a short card. Against a
     full-height hero those same percentages put the shipping pill at 43px
     — behind the sticky header, whose bottom edge is at 75px. Fixed
     offsets here instead, so they clear the header regardless of how tall
     the hero grows. */
  /* Superseded by the full-width block below, which moves both badges to
     the right so they clear the copy panel. Kept only as the split-hero
     fallback if that block is ever removed. */
  .hero .badge-shipping { top: 132px; left: 4%; }
  .hero .badge-rating   { bottom: 84px; right: 5%; }
}

/* ==========================================================================
   Full-width hero, copy above the image
   The copy had been sitting on the slide in a panel of its own. That panel
   was only ever there to keep it readable over an admin-uploaded photo,
   and a card that large floating on the image read as heavier than the
   thing it sat on. Stacking removes the need for it: the copy keeps the
   page's own background, and the slide gets the full width underneath.
   ========================================================================== */
@media (min-width: 992px) {

  /* Undo the pinning the side-by-side and overlay versions used. */
  .hero .hero-visual {
    position: relative;
    inset: auto;
    left: auto;
    right: auto;
    width: auto;
    min-height: 0;
  }

  /* One column, image band first. Flex rather than block so the order
     can be set here: the markup keeps copy-then-visual, which is the
     order a screen reader and a no-CSS render should get, and only
     the visual arrangement is flipped. */
  .hero .row { display: flex; flex-direction: column; }
  .hero .row > [class^="col-lg-"] { width: 100%; max-width: none; flex: none; }

  /* No card — the copy is back on the page, where it needs no help. */
  .hero-copy {
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-radius: 0;
    padding: 0;
    box-shadow: none;
    /* Centred: left-aligned copy was a habit of the two-column layout,
       and in a full-width row it left most of the line empty to the
       right. Stacked above a full-bleed image, a centred column is what
       the shape asks for. */
    max-width: 46rem;
    margin-inline: auto;
    text-align: center;
  }
  .hero-copy .eyebrow { justify-content: center; }
  .hero-copy .d-flex { justify-content: center; }
  .hero-copy .hero-stats { justify-content: center; }
  .hero-copy .hero-stats { border-top: 0; padding-top: 0; }

  /* The band. Bled to both edges of the window from inside the centred
     container: 50vw out from the container's own midpoint reaches the
     window on either side at every breakpoint, with no dependence on the
     container's width. */
  .hero .hero-visual {
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    margin-top: 0;
    margin-bottom: 1.25rem;
  }
  /* Back into flow. The side-by-side layout had this absolute so it could
     fill a pinned wrapper; here the wrapper takes its height *from* the
     slider, and an absolute child gave it none — the band laid out but
     contributed 0px, so the hero ended above it. */
  .hero .hero-visual .hero-slider {
    position: relative;
    inset: auto;
    border-radius: 0;
    height: 460px;
  }

  /* Both badges belong to the band now, not to a half of the hero, and
     they inset symmetrically. The rating badge had been pushed in to
     13% to clear the WhatsApp launcher, which is fixed to the bottom
     right of the viewport; with the band at the top of the page that
     badge now sits around y=417 and the launcher near the viewport
     floor, and the band can only ever scroll further away from it. */
  /* A white pill on a white photograph is a white pill on nothing. The
     badges sit on whatever an admin uploads, and a pale slide left them
     defined by their drop shadow alone — the brush-on-white cosmetics
     slide is exactly that case. A hairline edge and a slightly deeper
     shadow give them an outline that does not depend on the photo. */
  .hero .hero-float-badge {
    border: 1px solid rgba(20, 20, 40, .09);
    box-shadow: 0 6px 20px rgba(20, 20, 40, .16);
  }

  .hero .badge-shipping { top: 2.5rem; left: 6%; right: auto; }
  .hero .badge-rating   { bottom: 2.5rem; right: 6%; }

  .hero .hero-slider__arrow--prev { left: 1.6rem; right: auto; }
  .hero .hero-slider__arrow--next { right: 1.6rem; }
  .hero .hero-slider__dots { left: 50%; right: auto; transform: translateX(-50%); }

  /* The top-right blob is decoration for a layout where an image covered
     that corner. Stacked, it sits bare behind the header on empty
     background — and --violet is a near-black (#100e0e) on several
     business themes, so it renders as a grey smudge rather than a tint.
     Nothing to decorate here, so it goes at lg+. blob-2 went with it once
     the band moved to the top of the section: it had been hidden behind
     the band, and with the band gone from the bottom it washed the same
     grey across the copy's lower-left. */
  .hero .blob-1,
  .hero .blob-2 { display: none; }

  /* The band is the first thing in the section now, so the hero's 7.5rem
     of top padding would open a gap between it and the header. The
     bottom padding comes back instead — the copy is last, and without
     it the stats row butts straight into the next section.
     No overflow clipping here: `overflow-x: clip` forces the other axis
     to compute away from `visible` too, which cut the band off
     entirely. The bleed overshoots by the scrollbar width and the page
     does not scroll sideways for it — measured at 390, 820 and 1400. */
  /* 75px, not 0: .navbar is `position: fixed`, so it does not reserve
     space and the band ran underneath it — the top 75px of every
     photograph was behind a 90%-opaque bar, and the shipping badge
     with it. This is that bar's unscrolled height, measured; it
     shrinks to ~64px once scrolled, by which point the band has moved
     up anyway. */
  .hero { min-height: 0; padding-top: 75px; padding-bottom: 5rem; }
}

/* ==========================================================================
   Slide area above the copy
   The image leads and the words follow it. Done with `order` rather than by
   moving the markup: source order stays copy-then-visual, which is what a
   screen reader reads and what a no-CSS render shows — the heading should
   still come first there. Only the visual arrangement is flipped.

   From md up, which is exactly where .hero-visual stops being `d-none` —
   below that there is no image on the page to put first.
   ========================================================================== */
@media (min-width: 768px) {
  .hero .row > .col-lg-7 { order: 1; }
  .hero .row > .col-lg-5 { order: 2; }
}
