/* ---------------------------------------------------------------------------
   Front-page sliders — the hero, and the shop-category row.

   Loaded only on the front page, and only when at least one of those two is
   actually a slider (see inc/enqueue.php). A single-slide hero above three
   categories downloads neither this sheet nor Swiper.

   Nothing here restyles the things being slid. A hero slide is the same
   .hero__banner the static hero draws and a category slide is the same
   .cattile the grid draws; this sheet adds only the chrome around them, and
   the equal-height rules that stop a card resizing under the reader when the
   slide changes.
--------------------------------------------------------------------------- */

.hero__swiper {
  /* Swiper's own custom properties, pointed at the theme's tokens so the
     chrome inherits the palette instead of shipping Swiper's blue. */
  --swiper-theme-color: var(--brand);
  --swiper-pagination-color: var(--brand);
  --swiper-pagination-bullet-inactive-color: var(--ink-muted);
  --swiper-pagination-bullet-inactive-opacity: .3;
  --swiper-pagination-bullet-size: 9px;
  --swiper-pagination-bullet-horizontal-gap: 5px;
  --swiper-pagination-bottom: 0;
  --swiper-navigation-size: 18px;
  --swiper-navigation-color: var(--ink);
  --swiper-navigation-sides-offset: var(--s5);

  position: relative;
  /* Room for the dots below the card. They sit outside the banner rather than
     over it: centred on the card they would land on the picture panel, and a
     dot row over a photograph needs a scrim, a shadow and an opinion about
     every image an editor ever uploads. */
  padding-bottom: 40px;
}

/* Equal-height slides. Swiper gives each slide the height of the container,
   but the container takes its height from the first slide — so a second slide
   with one more line of copy gets clipped, and a shorter one leaves the card
   half empty. Letting the slide grow and stretching the banner inside it
   makes every slide as tall as the tallest, which also means the page does
   not reflow on each change. */
.hero__swiper .swiper-slide {
  height: auto;
  display: flex;
}

.hero__swiper .hero__banner {
  flex: 1 1 auto;
  width: 100%;
}

/* Fade needs the slides stacked, and stacked slides cannot be measured for
   height — so the cross-fade keeps the tallest card by holding all of them in
   the same grid cell rather than by Swiper's transform. */
.hero__swiper.swiper-fade .swiper-slide { height: auto; }

/* The arrows float over the banner, so the banner has to give them room or
   they land on the last word of the description — which is exactly where the
   trailing arrow falls at 1440px. The gutter is derived from the arrow's own
   geometry rather than typed as a number, so changing the arrow size or the
   side offset cannot quietly put the collision back. */
@media (min-width: 901px) {
  .hero--slider .hero__banner {
    padding-inline: calc(var(--swiper-navigation-sides-offset) + 44px + var(--s3));
  }
}

/* ----------------------------------------------------------------- Arrows */

/* Matches .carousel__btn elsewhere on the site: same 44px circle, same border,
   same hover. A visitor should not have to learn two arrow buttons. 44px is
   also the smallest comfortable touch target, which Swiper's 27px default is
   not. */
.hero__nav {
  width: 44px;
  height: 44px;
  top: calc(50% - 20px);
  margin-top: -22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .07);
  cursor: pointer;
  padding: 0;
  transition: border-color .15s ease, transform .15s ease;
}

.hero__nav::after { font-size: var(--swiper-navigation-size); font-weight: 700; }
.hero__nav:hover { border-color: var(--ink); }
.hero__nav:active { transform: scale(.95); }

/* The focus ring has to clear the card behind it, which is why it is offset
   rather than drawn on the border. */
.hero__nav:focus-visible {
  outline: 2px solid var(--brand-btn);
  outline-offset: 2px;
}

.hero__nav.swiper-button-disabled { opacity: .35; }

/* ------------------------------------------------------------------- Dots */

.hero__dots { line-height: 0; }

.hero__dots .swiper-pagination-bullet {
  transition: width .2s ease, background-color .2s ease;
}

/* The current slide reads as a short bar rather than a slightly darker dot.
   Four dots where one is 30% more opaque is not a position indicator anyone
   can find at a glance. */
.hero__dots .swiper-pagination-bullet-active {
  width: 22px;
  border-radius: var(--r-pill);
}

/* ------------------------------------------------- No JavaScript, no Swiper */

/* Until Swiper initialises — and forever, if the script never arrives — the
   slides are a real swipeable row rather than one banner with the rest
   clipped behind it. The chrome is hidden because neither control does
   anything without the script. */
.hero__swiper:not(.swiper-initialized) .swiper-wrapper {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  gap: var(--s4);
  scrollbar-width: none;
}

.hero__swiper:not(.swiper-initialized) .swiper-wrapper::-webkit-scrollbar { display: none; }
.hero__swiper:not(.swiper-initialized) .swiper-slide { scroll-snap-align: start; }
.hero__swiper:not(.swiper-initialized) .hero__nav,
.hero__swiper:not(.swiper-initialized) .hero__dots { display: none; }

@media (max-width: 900px) {
  /* On a phone the card runs nearly edge to edge, so an arrow floating over
     it covers the copy. The row is swipeable by hand there — which is how it
     is actually used — and the dots carry the position. */
  .hero__nav { display: none; }
  .hero__swiper { padding-bottom: 32px; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__swiper .swiper-wrapper { transition-duration: 0ms !important; }
  .hero__dots .swiper-pagination-bullet { transition: none; }
}

/* ---------------------------------------------------- Shop-category slider */

/* The row keeps the grid's own tile — same border, same hover, same label
   underneath. What changes is only how many are on screen and that the rest
   are a swipe away instead of a scroll away. */

.cattiles-slider { position: relative; }

/* Swiper measures the track, so the grid's `display: grid` has to go here —
   .cattiles carries the tile styling and the wrapper carries the flex track,
   and the two are the same element. */
.cattiles-slider .swiper-wrapper.cattiles {
  display: flex;
  gap: 0;
}

/* Equal-height tiles. Category names run to one line or two — «غذا» beside
   «اکسسوری و لوازم جانبی» — and without this the shorter tile ends up a
   different height from the one next to it, which reads as a broken row
   rather than as a shorter word. */
.cattiles-slider .swiper-slide {
  height: auto;
  display: flex;
}

.cattiles-slider .swiper-slide > .cattile {
  flex: 1 1 auto;
  width: 100%;
}

/* The tile's hover lift must not be clipped by the track. Swiper hides
   overflow on both axes; a little vertical room keeps the border transition
   and the image scale from being sliced off at the top. */
.cattiles__swiper {
  padding-block: 2px;
  margin-block: -2px;
}

/* -------------------------------------------------------- Slider nav pair */

/* Shared by any front-page slider whose arrows sit outside the track rather
   than over it. Matches .carousel__btn in petsaze.css: same 40px circle, same
   border, same hover — a visitor should not have to learn two arrow buttons
   on one page. */
.sw-nav {
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  padding: 0;
  transition: border-color .15s ease, transform .15s ease, opacity .15s ease;
}

.sw-nav:hover:not(.swiper-button-disabled) { border-color: var(--ink); }
.sw-nav:active { transform: scale(.95); }

.sw-nav:focus-visible {
  outline: 2px solid var(--brand-btn);
  outline-offset: 2px;
}

/* Swiper marks the end of the track. Disabled, not hidden: a control that
   vanishes at the end of a row makes the remaining one jump sideways. */
.sw-nav.swiper-button-disabled {
  opacity: .35;
  cursor: default;
}

/* Every tile already fits, so there is nothing to page through. Swiper marks
   both buttons `swiper-button-lock` in that case; hide the pair rather than
   leave two permanently greyed-out arrows under a row that is complete — a
   disabled control implies there is somewhere to go. */
.cattiles__nav:has(.swiper-button-lock) { display: none; }

.cattiles__nav {
  display: flex;
  gap: var(--s2);
  justify-content: flex-end;
  margin-top: var(--s4);
}

/* In RTL the leading arrow points right. The icons are the theme's own
   chevrons, drawn for a right-to-left reading order, so neither is flipped. */

@media (max-width: 760px) {
  /* The row is swiped by hand at this width — which is how it is actually
     used — so the pair is dead weight beside a thumb. */
  .cattiles__nav { display: none; }
}

/* ------------------------------------------------- No JavaScript, no Swiper */

.cattiles__swiper:not(.swiper-initialized) .swiper-wrapper.cattiles {
  overflow-x: auto;
  gap: var(--s4);
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.cattiles__swiper:not(.swiper-initialized) .swiper-wrapper.cattiles::-webkit-scrollbar { display: none; }

.cattiles__swiper:not(.swiper-initialized) .swiper-slide {
  scroll-snap-align: start;
  flex: 0 0 clamp(120px, 30vw, 200px);
}

.cattiles-slider:not(:has(.swiper-initialized)) .cattiles__nav { display: none; }
