/* ==========================================================================
   Satya Since 1973 — Home page sections
   Hero slider · mosaic · category carousel · product rails
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hero slider
   -------------------------------------------------------------------------- */

.s-slider {
  position: relative;
  overflow: hidden;
  border-radius: var(--s-radius-lg);
  background-color: var(--s-maroon-950);
}

.s-slider__track { display: grid; }

/* Every slide occupies the same grid cell and only opacity moves. A transform
   track would need the whole strip laid out side by side, which fights the
   mosaic sitting next to it at desktop width. */
.s-slider__slide {
  grid-area: 1 / 1;
  position: relative;
  display: block;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--s-slow) var(--s-ease);
}
.s-slider__slide.is-active { opacity: 1; visibility: visible; }

.s-slider__slide img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  aspect-ratio: 16 / 9;
}
@media (max-width: 47.99rem) { .s-slider__slide img { aspect-ratio: 4 / 5; } }

/* Copy sits over the photograph, so it needs a wash underneath it to stay
   readable whatever that photograph happens to be doing. */
/* The inline padding clears the arrows rather than running underneath them:
   the arrows sit at the vertical middle, which is exactly where the top line
   of this block lands, and "READY TO USE" was being half-covered by one. */
.s-slider__body {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding: var(--s-10) 4.25rem var(--s-8);
  background-image: linear-gradient(to top, rgb(28 0 1 / 0.88), rgb(28 0 1 / 0.45) 55%, transparent);
  color: var(--s-white);
}
@media (min-width: 48rem) { .s-slider__body { padding: var(--s-12) 4.75rem var(--s-8); } }

.s-slider__eyebrow {
  font-size: var(--s-text-2xs);
  font-weight: 700;
  letter-spacing: var(--s-tracking-caps);
  text-transform: uppercase;
  color: var(--s-gold-300);
}
.s-slider__title {
  margin-block: var(--s-2) var(--s-3);
  font-size: var(--s-text-2xl);
  color: var(--s-white);
}
@media (min-width: 48rem) { .s-slider__title { font-size: var(--s-text-4xl); } }
.s-slider__title em { font-style: normal; color: var(--s-gold-400); }

.s-slider__lede {
  max-inline-size: 32rem;
  color: rgb(255 255 255 / 0.85);
  font-size: var(--s-text-md);
}
.s-slider__cta { margin-block-start: var(--s-5); }

.s-slider__arrow {
  position: absolute;
  inset-block-start: 50%;
  translate: 0 -50%;
  z-index: 3;
  display: grid;
  place-items: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border-radius: 50%;
  background-color: rgb(255 255 255 / 0.9);
  color: var(--s-maroon-800);
  box-shadow: var(--s-shadow);
  transition: background-color var(--s-fast) var(--s-ease), color var(--s-fast) var(--s-ease);
}
.s-slider__arrow:hover { background-color: var(--s-maroon-700); color: var(--s-white); }
.s-slider__arrow--prev { inset-inline-start: var(--s-3); }
.s-slider__arrow--next { inset-inline-end: var(--s-3); }
.s-slider__arrow svg { inline-size: 1.15rem; block-size: 1.15rem; }

.s-slider__dots {
  position: absolute;
  inset-block-end: var(--s-3);
  inset-inline: 0;
  z-index: 3;
  display: flex;
  justify-content: center;
  gap: var(--s-2);
}

/* Wherever the phone's fixed bottom navigation shows, the dots sit at the TOP
   of the slide, on a small dark pill so they read over any photograph.

   At the bottom they could not win. On 12 September 2026 at 375×812 they sat
   under the bar (y=753, the bar covered 750 to 812), so a tap aimed at the
   second slide opened Shop instead. Lifting them 74px fixed that one screen,
   but put them 4px inside the top of "Shop everything", and at 360×740 — a very
   common Android size — they were under the bar again: how far the slide runs
   into the bar depends on the height of each phone, so no fixed lift clears it
   on all of them. The top of the slide is always on screen when the page opens,
   never under the bar, and nowhere near the copy, which sits at the bottom.

   The picture and the copy share one grid cell instead of the copy floating
   over the picture, so a slide is as tall as whichever is taller: at 320 pixels
   wide a long title and subtitle are taller than the 4:5 picture, and the top of
   the copy was being cut off by the slider's rounded frame. The copy's top
   padding keeps it clear of the pill: its offset, its height, then --s-4. */
@media (max-width: 61.99rem) {
  .s-slider__dots {
    inset-block-start: var(--s-3);
    inset-block-end: auto;
    inline-size: max-content;
    margin-inline: auto;
    padding: 0.375rem 0.625rem;
    border-radius: var(--s-radius-pill);
    background-color: rgb(28 0 1 / 0.45);
  }

  .s-slider__slide { display: grid; }
  .s-slider__slide > picture,
  .s-slider__body { grid-area: 1 / 1; }
  .s-slider__body {
    position: relative;
    align-self: end;
    padding-block-start: calc(var(--s-3) + 1.25rem + var(--s-4));
  }
}
.s-slider__dot {
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: var(--s-radius-pill);
  background-color: rgb(255 255 255 / 0.45);
  transition: inline-size var(--s-base) var(--s-ease), background-color var(--s-base) var(--s-ease);
}
.s-slider__dot.is-active { inline-size: 1.6rem; background-color: var(--s-gold-400); }

/* --------------------------------------------------------------------------
   Slider plus mosaic
   -------------------------------------------------------------------------- */

.s-showcase { display: grid; gap: var(--s-3); }
@media (min-width: 62rem) {
  .s-showcase { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: var(--s-4); }
}

/* The mosaic is a desktop luxury. On a phone it would be three more things to
   scroll past before reaching the products. */
.s-mosaic { display: none; grid-template-rows: 1.15fr 1fr; gap: var(--s-4); }
@media (min-width: 62rem) { .s-mosaic { display: grid; } }

/*
 * The tiles under the big one — as many as the merchant has put there.
 *
 * Fixed at two columns until 9 September 2026, which quietly limited the whole
 * band to three tiles: a fourth was saved in the admin and never drawn. The
 * columns are worked out from how many there are instead, so three tiles look
 * exactly as they always did and four, five or six simply share the row.
 */
.s-mosaic__pair {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--s-4);
}

.s-mosaic__tile {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--s-radius);
  background-color: var(--s-line-soft);
}
.s-mosaic__tile img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform var(--s-slow) var(--s-ease);
}
.s-mosaic__tile:hover img { transform: scale(1.05); }

.s-mosaic__label {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding: var(--s-6) var(--s-4) var(--s-3);
  background-image: linear-gradient(to top, rgb(28 0 1 / 0.85), transparent);
  color: var(--s-white);
  font-size: var(--s-text-sm);
  font-weight: 700;
}

/* --------------------------------------------------------------------------
   Category carousel — the round-tile strip a shopper expects at the top
   -------------------------------------------------------------------------- */

.s-catstrip { background-color: var(--s-surface); border-block-end: 1px solid var(--s-line); }
.s-catstrip .s-wrap { padding-block: var(--s-5); }

.s-catrail { position: relative; }

/* The selector is `.s-catrail .s-catrail__track`, not `.s-catrail__track`.

   The track is a `ul[role="list"]`, and base.css zeroes padding on those. An
   attribute selector out-specifies a single class, so the vertical padding
   below was silently dropped — which matters because of the next paragraph. */
.s-catrail .s-catrail__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 5.25rem;
  gap: var(--s-4);
  overflow-x: auto;
  scroll-behavior: smooth;
  scroll-snap-type: x proximity;
  scrollbar-width: none;

  /* Asking for `overflow-x: auto` makes the browser compute `overflow-y` as
     auto too — the pair cannot be scroll-one-axis-and-overflow-the-other. So
     this is a clipping box, and a tile that lifts 3px on hover and casts a
     shadow above itself was being sliced off along the top edge.

     The padding gives the lift and its shadow somewhere to go inside the box;
     the matching negative margin takes the space back, so the strip is exactly
     as tall as it was before. */
  padding-block: 1rem 0.75rem;
  margin-block: -1rem -0.75rem;
}
.s-catrail__track::-webkit-scrollbar { display: none; }
/* These carry the same two-class specificity as the base rule above. Left as
   a single class they lost to it, the tiles stayed at their smallest size at
   every width, the strip stopped overflowing and the carousel arrow
   disappeared along with it. */
@media (min-width: 48rem) { .s-catrail .s-catrail__track { grid-auto-columns: 7rem; gap: var(--s-6); } }
@media (min-width: 62rem) { .s-catrail .s-catrail__track { grid-auto-columns: 8rem; } }

.s-cattile {
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  scroll-snap-align: start;
  text-align: center;
}

.s-cattile__figure {
  inline-size: 4.25rem;
  block-size: 4.25rem;
  border-radius: 50%;
  overflow: hidden;
  background-color: var(--s-cream);
  border: 2px solid var(--s-line);
  transition: border-color var(--s-base) var(--s-ease),
              transform var(--s-base) var(--s-ease),
              box-shadow var(--s-base) var(--s-ease);
}
@media (min-width: 48rem) { .s-cattile__figure { inline-size: 5.5rem; block-size: 5.5rem; } }
@media (min-width: 62rem) { .s-cattile__figure { inline-size: 6.25rem; block-size: 6.25rem; } }

.s-cattile__figure img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.s-cattile:hover .s-cattile__figure { border-color: var(--s-gold-500); transform: translateY(-3px); box-shadow: var(--s-shadow); }

.s-cattile__name {
  font-size: var(--s-text-xs);
  font-weight: 600;
  line-height: 1.3;
  color: var(--s-ink);
  /* Clamped to two lines so a long category name never makes its tile taller
     than its neighbours, and given two lines of height even when it only needs
     one — the clamp was a ceiling with no floor, so "Festival Special Kits"
     sat a line shorter than everything beside it and the row read as ragged.
     2 x the 1.3 line-height, in em so it follows the font-size at 48rem. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-block-size: 2.6em;
}
@media (min-width: 48rem) { .s-cattile__name { font-size: var(--s-text-sm); } }
.s-cattile:hover .s-cattile__name { color: var(--s-maroon-700); }

/* --------------------------------------------------------------------------
   Rail arrows — shown only where there is a pointer to use them
   -------------------------------------------------------------------------- */

.s-rail-arrow {
  position: absolute;
  z-index: 2;
  display: none;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  border-radius: 50%;
  background-color: var(--s-surface);
  border: 1px solid var(--s-line);
  box-shadow: var(--s-shadow);
  color: var(--s-maroon-800);
  transition: background-color var(--s-fast) var(--s-ease), color var(--s-fast) var(--s-ease);
}
/* Shown at every width, on a phone as well.

   They were behind `(hover: hover) and (min-width: 62rem)` — the reasoning being
   that a rail swipes on a phone, so an arrow is only for somebody with a
   pointer. The client asked in session 7 for them everywhere: a rail that gives
   no sign it continues reads as a row that simply ends, and swiping is only
   discoverable once you already know there is more. The script hides each arrow
   at its own end, so neither is ever a control that does nothing. */
.s-rail-arrow { display: grid; }
.s-rail-arrow:hover { background-color: var(--s-maroon-700); color: var(--s-white); border-color: transparent; }

/* Hidden at the ends rather than left as a control that does nothing. */
.s-rail-arrow[hidden] { display: none !important; }

.s-rail-arrow svg { inline-size: 1rem; block-size: 1rem; }

/* Outside the rail where the page has margins to spare, and **inside** it on a
   phone. Hung off the edge at 320 they would sit in the page's own gutter, and
   a `position: absolute` box beyond the wrap is exactly how a document starts
   scrolling sideways — the one thing this project refuses everywhere. */
.s-rail-arrow--prev { inset-inline-start: 0; }
.s-rail-arrow--next { inset-inline-end: 0; }

@media (min-width: 62rem) {
  .s-rail-arrow--prev { inset-inline-start: -1.25rem; }
  .s-rail-arrow--next { inset-inline-end: -1.25rem; }
}

/* A smaller target on a phone, so it covers less of the picture behind it. */
@media (max-width: 61.999rem) {
  .s-rail-arrow { inline-size: 2.125rem; block-size: 2.125rem; }
  .s-rail-arrow svg { inline-size: 0.85rem; block-size: 0.85rem; }
}

/* Level with the middle of the round tiles, not the middle of the tile plus its
   two-line caption. */
.s-catrail .s-rail-arrow { inset-block-start: 2.4rem; }

/* The reviews rail has no picture to line up with, so its arrows sit at the
   middle of the cards. Without a rule of their own they fell back to
   `inset-block-start: auto` and took their static position — one beside the
   top of the row, one dropped below it, which is how the client found them. */
.s-reviewrail .s-rail-arrow {
  /* Half the track's own bottom padding back off, so the arrow centres on the
     cards rather than on the card plus the strip of room left for the scroll. */
  inset-block-start: calc(50% - (var(--s-2) / 2));
  transform: translateY(-50%);
}

/* --------------------------------------------------------------------------
   Product rail — the same card, scrolled rather than wrapped
   -------------------------------------------------------------------------- */

.s-railwrap { position: relative; }
.s-railwrap .s-rail-arrow { inset-block-start: 35%; }

/* A wrapping grid, not a scrolling strip.

   It used to be `grid-auto-flow: column` with `grid-auto-columns: minmax(0,
   16rem)`. The `0` is the trap: it lets every column shrink without limit, so
   eleven products in one row squeezed to about 130px each — names cut to two
   words, "Add to bag" wrapping onto two lines. A row that has to fit whatever
   it is given will always do this.

   Wrapping fixes the squeeze and gives two real columns on a phone, which is
   what a shopper expects to thumb through. */
/* Flex, not grid, and every card exactly the same width.

   This was a grid with "stretch the leftovers" rules underneath it, and on a
   category holding three products that made the first card three times the
   width of the other two. Filling the row is not worth deforming the row: a
   shop where one tile is a different size from its neighbours looks broken,
   not designed.

   `justify-content: center` is what replaces those rules. A short last row —
   or a whole section that only has two products in it — sits centred, with
   even margins either side, which reads as deliberate. The hole on the right
   that the client objected to is gone without any card changing size. */
.s-prail {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  --s-col-gap: var(--s-3);
  gap: var(--s-5) var(--s-col-gap);
}
.s-prail > * { flex: 0 1 calc((100% - 1 * var(--s-col-gap)) / 2); }

@media (min-width: 40rem) {
  .s-prail { --s-col-gap: var(--s-4); }
  .s-prail > * { flex-basis: calc((100% - 2 * var(--s-col-gap)) / 3); }
}
@media (min-width: 62rem) {
  .s-prail > * { flex-basis: calc((100% - 3 * var(--s-col-gap)) / 4); }
}

/* Five across on a wide screen — about 250px a card. Four columns on a 1536px
   screen gave 317px cards with a 317px photograph on each, which read as a
   furniture catalogue rather than a shop. */
@media (min-width: 78rem) {
  .s-prail > * { flex-basis: calc((100% - 4 * var(--s-col-gap)) / 5); }
}

/* --------------------------------------------------------------------------
   Equal cards, centred rows

   A block of `:nth-last-child` rules used to live here, stretching the
   leftovers on a final row so that the row would fill. It filled the row and
   ruined the section: a category holding three products drew one card three
   columns wide and two at one column each, and every sparse collection on the
   home page looked broken.

   Centring the flex rows does the same job without touching any card size, so
   the rules are gone rather than tuned. A short row now sits centred with even
   margins either side, which reads as deliberate.
   -------------------------------------------------------------------------- */

.s-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  --s-col-gap: var(--s-3);
  gap: var(--s-5) var(--s-col-gap);
}
.s-grid > * { flex: 0 1 calc((100% - 1 * var(--s-col-gap)) / 2); }

@media (min-width: 40rem) {
  .s-grid { --s-col-gap: var(--s-4); }
  .s-grid > * { flex-basis: calc((100% - 2 * var(--s-col-gap)) / 3); }
}
@media (min-width: 62rem) {
  .s-grid > * { flex-basis: calc((100% - 3 * var(--s-col-gap)) / 4); }
}
@media (min-width: 78rem) {
  .s-grid > * { flex-basis: calc((100% - 4 * var(--s-col-gap)) / 5); }
}

/* --------------------------------------------------------------------------
   Promotional band between the rails
   -------------------------------------------------------------------------- */

.s-promos { display: grid; gap: var(--s-4); }
@media (min-width: 48rem) { .s-promos { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.s-promo {
  position: relative;
  display: grid;
  align-content: end;
  gap: var(--s-2);
  min-block-size: 11rem;
  padding: var(--s-5);
  overflow: hidden;
  border-radius: var(--s-radius);
  color: var(--s-white);
  background-color: var(--s-maroon-800);
}
.s-promo img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform var(--s-slow) var(--s-ease);
}
.s-promo:hover img { transform: scale(1.06); }
.s-promo::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(to top, rgb(28 0 1 / 0.86), rgb(28 0 1 / 0.25) 60%, transparent);
}
.s-promo > * { position: relative; z-index: 1; }
.s-promo__eyebrow {
  font-size: var(--s-text-2xs);
  font-weight: 700;
  letter-spacing: var(--s-tracking-caps);
  text-transform: uppercase;
  color: var(--s-gold-300);
}
.s-promo__title { font-size: var(--s-text-xl); color: var(--s-white); }
.s-promo__link { font-size: var(--s-text-sm); font-weight: 600; border-block-end: 1px solid currentColor; justify-self: start; padding-block-end: 2px; }

/* ---------------------------------------------------------------------------
   The return promise on a product page

   A quiet line rather than a badge: it is reassurance, not a selling point, and
   a shopper reads it once. It sits on the same tinted ground the page uses for
   its other asides so it reads as the shop speaking, not as a warning.
--------------------------------------------------------------------------- */

.s-pdp__returns {
  padding: var(--s-3) var(--s-4);
  border-inline-start: 3px solid var(--s-gold-500);
  border-radius: var(--s-radius-sm, 6px);
  background-color: var(--s-surface);
}

.s-pdp__returns-line {
  margin: 0;
  font-weight: 600;
  color: var(--s-ink);
}

.s-pdp__returns .s-note { margin-block-start: var(--s-2); }
/* The policy you are reading, in its own list. Marked rather than removed, so
   the panel is the same on every one of them and the reader can see the whole
   set — and still a link, so its address can be copied or opened in a new tab
   like any other. */
.s-aside__list a.s-aside__here {
  font-weight: 700;
  color: var(--s-maroon-800);
}