/* ==========================================================================
   Satya Since 1973 — Storefront components
   Header · navigation · hero · product card · grid · product page ·
   quick view · cart drawer · bottom navigation · footer · toasts
   ========================================================================== */

/* --------------------------------------------------------------------------
   Announcement bar
   -------------------------------------------------------------------------- */

.s-announce {
  background-color: var(--s-maroon-800);
  color: var(--s-white);
  font-size: var(--s-text-xs);
  letter-spacing: var(--s-tracking-wide);
}
.s-announce__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-4);
  min-block-size: 2.25rem;
  text-align: center;
}
.s-announce strong { color: var(--s-gold-300); font-weight: 700; }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.s-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--s-z-header);
  background-color: var(--s-surface);
  border-block-end: 1px solid var(--s-line);
}

.s-header__main {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding-block: var(--s-3);
}
@media (min-width: 62rem) {
  .s-header__main { grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--s-8); padding-block: var(--s-4); }
}

.s-header__burger { display: grid; }
@media (min-width: 62rem) { .s-header__burger { display: none; } }

.s-header__brand { display: inline-flex; align-items: center; }
.s-brand-logo { block-size: 3.25rem; inline-size: auto; object-fit: contain; }
@media (min-width: 62rem) { .s-brand-logo { block-size: 4.25rem; } }

.s-header__actions { display: flex; align-items: center; gap: 0.1rem; justify-self: end; }

/* ---- Search ------------------------------------------------------------- */

/* On a phone the search bar moves to its own row rather than being squeezed
   into a 90px column between the logo and the icons. */
.s-search { position: relative; grid-column: 1 / -1; grid-row: 2; }
@media (min-width: 62rem) { .s-search { grid-column: 2; grid-row: 1; } }

.s-search__form { display: flex; }

.s-search__input {
  inline-size: 100%;
  min-block-size: 2.75rem;
  padding: 0.55rem 3rem 0.55rem 1.1rem;
  border: 1px solid var(--s-line);
  border-radius: var(--s-radius-pill);
  background-color: var(--s-cream);
  font-size: var(--s-text-md);
  transition: border-color var(--s-fast) var(--s-ease), background-color var(--s-fast) var(--s-ease);
}
.s-search__input:focus {
  outline: none;
  background-color: var(--s-surface);
  border-color: var(--s-maroon-700);
  box-shadow: 0 0 0 3px rgb(93 0 3 / 0.10);
}

.s-search__go {
  position: absolute;
  inset-inline-end: 4px;
  inset-block-start: 50%;
  translate: 0 -50%;
  display: grid;
  place-items: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  border-radius: 50%;
  background-color: var(--s-maroon-700);
  color: var(--s-white);
}
.s-search__go:hover { background-color: var(--s-maroon-600); }
.s-search__go svg { inline-size: 1.05rem; block-size: 1.05rem; }

/* ---- Predictive results ------------------------------------------------- */

.s-suggest {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100% + 0.5rem);
  z-index: 20;
  max-block-size: 26rem;
  overflow-y: auto;
  padding: var(--s-2);
  border: 1px solid var(--s-line);
  border-radius: var(--s-radius);
  background-color: var(--s-surface);
  box-shadow: var(--s-shadow-lg);
}
.s-suggest__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2);
  border-radius: var(--s-radius-sm);
}
.s-suggest__item:hover, .s-suggest__item.is-active { background-color: var(--s-cream); }
.s-suggest__thumb {
  inline-size: 3rem; block-size: 3rem;
  flex: none;
  border-radius: var(--s-radius-sm);
  object-fit: cover;
  background-color: var(--s-line-soft);
}
.s-suggest__name { font-size: var(--s-text-sm); font-weight: 600; }
.s-suggest__meta { font-size: var(--s-text-xs); color: var(--s-muted); }
.s-suggest__price { margin-inline-start: auto; font-weight: 700; font-size: var(--s-text-sm); color: var(--s-maroon-700); }
.s-suggest__empty { padding: var(--s-4); text-align: center; color: var(--s-muted); font-size: var(--s-text-sm); }

/* ---- Category bar ------------------------------------------------------- */

.s-catbar {
  display: none;
  background-color: var(--s-sage-200);
  border-block-start: 1px solid rgb(255 255 255 / 0.5);
}
@media (min-width: 62rem) { .s-catbar { display: block; } }

.s-catbar__list {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  overflow-x: auto;
  scrollbar-width: none;
}
.s-catbar__list::-webkit-scrollbar { display: none; }

.s-catbar__link {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.75rem;
  padding-inline: var(--s-4);
  border-radius: var(--s-radius-sm);
  font-size: var(--s-text-sm);
  font-weight: 600;
  color: var(--s-maroon-900);
  white-space: nowrap;
  transition: background-color var(--s-fast) var(--s-ease);
}
.s-catbar__link:hover { background-color: rgb(255 255 255 / 0.55); }
.s-catbar__link.is-active { background-color: var(--s-maroon-700); color: var(--s-white); }

/* --------------------------------------------------------------------------
   Mobile menu drawer
   -------------------------------------------------------------------------- */

.s-menu {
  position: fixed;
  inset-block: 0;
  inset-inline-start: 0;
  z-index: var(--s-z-drawer);
  inline-size: min(20rem, 86vw);
  display: flex;
  flex-direction: column;
  background-color: var(--s-surface);
  box-shadow: var(--s-shadow-xl);
  transform: translateX(-100%);
  /* Hidden as well as moved while it is closed, so its links are not in the
     tab order. Pressing Tab on the home page went through all seventeen links
     of a menu nobody could see (14 September 2026). On the way out the change
     waits for the slide to finish; on the way in it is immediate, so the first
     link can take focus as the menu opens. */
  visibility: hidden;
  transition: transform var(--s-base) var(--s-ease-out), visibility 0s linear var(--s-base);
}
.s-menu.is-open {
  transform: none;
  visibility: visible;
  transition: transform var(--s-base) var(--s-ease-out), visibility 0s;
}

.s-menu__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4);
  border-block-end: 1px solid var(--s-line);
}
/* The menu's list scrolls inside the drawer on every phone browser.

   `min-block-size: 0` lets the drawer's flex column give the list only the
   space that is left, which Firefox and Safari need before they will scroll
   it; `overscroll-behavior: contain` keeps a swipe that reaches the end from
   dragging the page behind; `touch-action: pan-y` tells the browser the
   vertical swipe belongs to the list (client, 15 September 2026: the open
   menu would not scroll on a phone). */
.s-menu__body {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  padding: var(--s-3);
}
.s-menu__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-block-size: 2.875rem;
  padding-inline: var(--s-3);
  border-radius: var(--s-radius-sm);
  font-size: var(--s-text-md);
  font-weight: 500;
}
.s-menu__link:hover { background-color: var(--s-cream); }
.s-menu__group-label {
  padding: var(--s-4) var(--s-3) var(--s-2);
  font-size: var(--s-text-2xs);
  font-weight: 700;
  letter-spacing: var(--s-tracking-caps);
  text-transform: uppercase;
  color: var(--s-muted);
}

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

.s-hero {
  position: relative;
  overflow: hidden;
  background-color: var(--s-maroon-900);
  color: var(--s-white);
}

.s-hero__inner {
  display: grid;
  gap: var(--s-8);
  align-items: center;
  padding-block: var(--s-12);
}
@media (min-width: 62rem) {
  .s-hero__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); padding-block: var(--s-16); gap: var(--s-16); }
}

.s-hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--s-text-2xs);
  font-weight: 700;
  letter-spacing: var(--s-tracking-caps);
  text-transform: uppercase;
  color: var(--s-gold-300);
}
.s-hero__eyebrow::before {
  content: "";
  inline-size: 1.75rem;
  block-size: 1px;
  background-color: currentColor;
}

.s-hero__title {
  margin-block: var(--s-4) var(--s-4);
  font-size: var(--s-text-4xl);
  line-height: 1.05;
  color: var(--s-white);
}
@media (min-width: 62rem) { .s-hero__title { font-size: var(--s-text-5xl); } }
.s-hero__title em { font-style: normal; color: var(--s-gold-400); }

.s-hero__lede {
  max-inline-size: 34rem;
  color: rgb(255 255 255 / 0.82);
  font-size: var(--s-text-lg);
}

.s-hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-block-start: var(--s-8); }

/* A collage rather than one flat banner: three of the client's own
   photographs, which say more about the shop than a stock hero would. */
.s-hero__art {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  grid-template-rows: repeat(2, 1fr);
  gap: var(--s-3);
  aspect-ratio: 4 / 3;
}
.s-hero__art img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  border-radius: var(--s-radius);
  box-shadow: var(--s-shadow-lg);
}
.s-hero__art img:first-child { grid-row: span 2; }

.s-hero__glow {
  position: absolute;
  inset-block-start: -30%;
  inset-inline-start: -10%;
  inline-size: 55%;
  aspect-ratio: 1;
  border-radius: 50%;
  background-image: radial-gradient(circle, rgb(214 166 46 / 0.20), transparent 68%);
  pointer-events: none;
}

/* ---- Trust strip -------------------------------------------------------- */

.s-trust {
  background-color: var(--s-surface);
  border-block-end: 1px solid var(--s-line);
}
.s-trust__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-4);
  padding-block: var(--s-6);
}
@media (min-width: 48rem) { .s-trust__list { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.s-trust__item { display: flex; align-items: center; gap: var(--s-3); }
.s-trust__icon {
  display: grid;
  place-items: center;
  inline-size: 2.5rem; block-size: 2.5rem;
  flex: none;
  border-radius: 50%;
  background-color: var(--s-gold-100);
  color: var(--s-gold-700);
}
.s-trust__icon svg { inline-size: 1.25rem; block-size: 1.25rem; }
.s-trust__title { font-size: var(--s-text-sm); font-weight: 700; }
.s-trust__note { font-size: var(--s-text-xs); color: var(--s-muted); }

/* --------------------------------------------------------------------------
   Category tiles
   -------------------------------------------------------------------------- */

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

.s-cat {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--s-radius);
  background-color: var(--s-surface);
  border: 1px solid var(--s-line);
  transition: transform var(--s-base) var(--s-ease), box-shadow var(--s-base) var(--s-ease), border-color var(--s-base) var(--s-ease);
}
.s-cat:hover { transform: translateY(-3px); box-shadow: var(--s-shadow); border-color: var(--s-gold-400); }

.s-cat__figure { aspect-ratio: 1; background-color: var(--s-line-soft); }
.s-cat__figure img { inline-size: 100%; block-size: 100%; object-fit: cover; }

.s-cat__empty {
  display: grid;
  place-items: center;
  block-size: 100%;
  background-image: linear-gradient(135deg, var(--s-sage-100), var(--s-gold-100));
  color: var(--s-maroon-600);
  font-family: var(--s-font-display);
  font-size: var(--s-text-3xl);
}

.s-cat__body { padding: var(--s-3); text-align: center; }
.s-cat__name { font-size: var(--s-text-sm); font-weight: 600; line-height: 1.3; }
.s-cat__count { margin-block-start: 2px; font-size: var(--s-text-xs); color: var(--s-muted); }

/* --------------------------------------------------------------------------
   Product grid and card
   -------------------------------------------------------------------------- */

.s-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3);
}
@media (min-width: 40rem) { .s-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); } }
@media (min-width: 62rem) { .s-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-5); } }
@media (min-width: 78rem) { .s-grid, .s-grid--wide { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* The horizontal rail used on the home page. On a phone it is a swipe; from
   the tablet breakpoint up it becomes the same grid, because a rail on a wide
   screen hides most of what is in it. */
.s-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(11.5rem, 68vw);
  gap: var(--s-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--s-gutter);
  padding-block-end: var(--s-2);
  margin-inline: calc(var(--s-gutter) * -1);
  padding-inline: var(--s-gutter);
  scrollbar-width: none;
}
.s-rail::-webkit-scrollbar { display: none; }
.s-rail > * { scroll-snap-align: start; }

@media (min-width: 40rem) {
  .s-rail {
    grid-auto-flow: row;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-columns: auto;
    overflow: visible;
    margin-inline: 0;
    padding-inline: 0;
    gap: var(--s-4);
  }
}
@media (min-width: 62rem) { .s-rail { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-5); } }

.s-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--s-line);
  border-radius: var(--s-radius);
  background-color: var(--s-surface);
  transition: transform var(--s-base) var(--s-ease),
              box-shadow var(--s-base) var(--s-ease),
              border-color var(--s-base) var(--s-ease);
}
@media (hover: hover) {
  .s-card:hover { transform: translateY(-4px); box-shadow: var(--s-shadow-lg); border-color: var(--s-gold-400); }
}

.s-card__figure {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  background-color: var(--s-line-soft);
}
.s-card__img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform var(--s-slow) var(--s-ease);
}
@media (hover: hover) { .s-card:hover .s-card__img { transform: scale(1.06); } }

.s-card__tags {
  position: absolute;
  inset-block-start: var(--s-2);
  inset-inline-start: var(--s-2);
  display: grid;
  gap: var(--s-1);
  justify-items: start;
}

/* The wishlist toggle sits over the picture; on touch it is always visible,
   because there is no hover to reveal it with. */
.s-card__wish {
  position: absolute;
  inset-block-start: var(--s-2);
  inset-inline-end: var(--s-2);
  display: grid;
  place-items: center;
  inline-size: 2.25rem; block-size: 2.25rem;
  border-radius: 50%;
  background-color: rgb(255 255 255 / 0.92);
  color: var(--s-ink-soft);
  box-shadow: var(--s-shadow-sm);
  transition: color var(--s-fast) var(--s-ease), transform var(--s-fast) var(--s-ease), opacity var(--s-fast) var(--s-ease);
}
.s-card__wish svg { inline-size: 1.1rem; block-size: 1.1rem; }
.s-card__wish:hover { color: var(--s-maroon-700); transform: scale(1.08); }
.s-card__wish.is-on { color: var(--s-maroon-700); }
.s-card__wish.is-on svg { fill: currentColor; }

@media (hover: hover) {
  .s-card__wish { opacity: 0; }
  .s-card:hover .s-card__wish, .s-card__wish:focus-visible, .s-card__wish.is-on { opacity: 1; }
}

/* Quick view — a hover affordance on a pointer, and a real row on touch. */
.s-card__quick {
  position: absolute;
  inset-inline: var(--s-2);
  inset-block-end: var(--s-2);
  min-block-size: 2.25rem;
  border-radius: var(--s-radius-pill);
  background-color: rgb(255 255 255 / 0.95);
  color: var(--s-maroon-800);
  font-size: var(--s-text-xs);
  font-weight: 700;
  letter-spacing: var(--s-tracking-wide);
  box-shadow: var(--s-shadow);
  display: grid;
  place-items: center;
}
.s-card__quick:hover { background-color: var(--s-maroon-700); color: var(--s-white); }
@media (hover: hover) {
  .s-card__quick { opacity: 0; translate: 0 0.5rem; transition: opacity var(--s-base) var(--s-ease), translate var(--s-base) var(--s-ease), background-color var(--s-fast) var(--s-ease); }
  .s-card:hover .s-card__quick, .s-card__quick:focus-visible { opacity: 1; translate: 0; }
}

.s-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  flex: 1 1 auto;
  padding: var(--s-3);
}
@media (min-width: 48rem) { .s-card__body { padding: var(--s-4); } }

.s-card__cat {
  font-size: var(--s-text-2xs);
  font-weight: 600;
  letter-spacing: var(--s-tracking-wide);
  text-transform: uppercase;
  color: var(--s-gold-700);
}

.s-card__name {
  font-family: var(--s-font-body);
  font-size: var(--s-text-sm);
  font-weight: 600;
  line-height: 1.35;
  /* Two lines, always: a ragged grid where one card is a line taller than its
     neighbours is the difference between a shop and a spreadsheet. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-block-size: 2.4em;
}
.s-card__name:hover { color: var(--s-maroon-700); }

.s-card__price-row { display: flex; align-items: baseline; gap: var(--s-2); margin-block-start: auto; padding-block-start: var(--s-2); }
.s-card__price { font-size: var(--s-text-lg); font-weight: 700; color: var(--s-maroon-800); }
.s-card__mrp { font-size: var(--s-text-xs); color: var(--s-muted); text-decoration: line-through; }
.s-card__off { font-size: var(--s-text-xs); font-weight: 700; color: var(--s-success); }

.s-card__stock { font-size: var(--s-text-xs); color: var(--s-muted); }
.s-card__stock--out { color: var(--s-danger); font-weight: 600; }
.s-card__stock--low { color: var(--s-warn); font-weight: 600; }

.s-card__cta { margin-block-start: var(--s-3); }

/* The whole card is clickable, but the controls on top of it still work: the
   link is stretched behind them rather than wrapping them.

   The two controls that sit over the picture keep their own `position:
   absolute` — lumping them in with `.s-card__cta` here set them to `relative`
   and dropped both out of the image into normal flow, which is why the heart
   and Quick view were invisible however hard you hovered. Only the button in
   the card body needs a stacking context of its own. */
.s-card__link::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.s-card__wish, .s-card__quick { z-index: 2; }
.s-card__cta { position: relative; z-index: 2; }

/* --------------------------------------------------------------------------
   Listing layout — filters beside the grid
   -------------------------------------------------------------------------- */

/* One column at every width — `filters.css` carries the note. The two-column
   rule and the sticky `.s-filters` column that used to be here went with the
   desktop filter panel in session 7. */
.s-listing { display: grid; gap: var(--s-6); align-items: start; }

.s-filters__group + .s-filters__group { margin-block-start: var(--s-6); padding-block-start: var(--s-6); border-block-start: 1px solid var(--s-line-soft); }
.s-filters__title { font-family: var(--s-font-body); font-size: var(--s-text-xs); font-weight: 700; letter-spacing: var(--s-tracking-caps); text-transform: uppercase; color: var(--s-muted); margin-block-end: var(--s-3); }

.s-check { display: flex; align-items: center; gap: var(--s-2); min-block-size: 2.25rem; font-size: var(--s-text-sm); cursor: pointer; }
.s-check input { inline-size: 1.05rem; block-size: 1.05rem; accent-color: var(--s-maroon-700); flex: none; }
.s-check__count { margin-inline-start: auto; font-size: var(--s-text-xs); color: var(--s-muted); }

.s-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-block-end: var(--s-5);
}
.s-toolbar__count { font-size: var(--s-text-sm); color: var(--s-muted); }
.s-toolbar__right { display: flex; align-items: center; gap: var(--s-2); margin-inline-start: auto; }
.s-toolbar__filter { display: inline-flex; }
@media (min-width: 62rem) { .s-toolbar__filter { display: none; } }

.s-chipbar { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-block-end: var(--s-4); }
.s-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 0.3rem 0.4rem 0.3rem 0.75rem;
  border: 1px solid var(--s-line);
  border-radius: var(--s-radius-pill);
  background-color: var(--s-surface);
  font-size: var(--s-text-xs);
  font-weight: 600;
}
.s-chip__x { display: grid; place-items: center; inline-size: 1.25rem; block-size: 1.25rem; border-radius: 50%; background-color: var(--s-line-soft); }
.s-chip__x:hover { background-color: var(--s-maroon-700); color: var(--s-white); }

/* --------------------------------------------------------------------------
   Product page
   -------------------------------------------------------------------------- */

.s-pdp { display: grid; gap: var(--s-8); align-items: start; }
@media (min-width: 62rem) { .s-pdp { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--s-12); } }

.s-gallery { display: grid; gap: var(--s-3); }
@media (min-width: 62rem) {
  .s-gallery { position: sticky; inset-block-start: calc(var(--s-4) + 5.5rem); grid-template-columns: 5rem minmax(0, 1fr); }
  .s-gallery__thumbs { grid-row: 1; grid-column: 1; grid-auto-flow: row; }
  .s-gallery__stage { grid-row: 1; grid-column: 2; }

  /* One picture, no thumbnail rail — so no empty column to sit beside.
     Left in, it indented the picture by 5rem while the breadcrumb, the
     title and everything below stayed on the page margin. */
  .s-gallery--single { grid-template-columns: minmax(0, 1fr); }
  .s-gallery--single .s-gallery__stage { grid-column: 1; }
}

/* The photograph is matted, not bled: an ivory mat inside a gold hairline,
   the same framing the product cards use (MASTER_PROMPT.md §7a). `contain`
   rather than `cover`, so a photograph the client composed is never cropped
   to fill a square. */
.s-gallery__stage {
  position: relative;
  overflow: hidden;
  aspect-ratio: 1;
  padding: var(--s-4);
  border: 1px solid var(--s-gold-300, var(--s-line));
  border-radius: var(--s-radius);
  background-color: var(--s-white);
  box-shadow: var(--s-shadow-sm);
  cursor: zoom-in;
  touch-action: manipulation;
}

.s-gallery__photo {
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;

  /* The magnifier moves the picture, not the frame. */
  transform-origin: center;
  transition: transform var(--s-fast) var(--s-ease-out);
  will-change: transform;

  /* Nothing to select, nothing to drag away. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

/* While the magnifier is following the cursor the movement must be immediate,
   or the picture lags a frame behind the pointer and feels broken. */
.s-gallery__stage.is-zooming .s-gallery__photo { transition: none; }

/* The shield covers the photograph so a right-click, a drag or a long press
   lands here. It stops the casual copy, which is what the client asked for;
   it is not protection against anyone reading the network tab, and it is not
   described to them as if it were. */
.s-gallery__shield {
  position: absolute;
  inset: 0;
  z-index: 1;
  -webkit-touch-callout: none;
  user-select: none;
}

.s-gallery__stage img { inline-size: 100%; block-size: 100%; object-fit: contain; }

/* A hint that the picture does more than sit there — shown only where there is
   a real pointer to hover with. */
@media (hover: hover) and (pointer: fine) {
  .s-gallery__stage::after {
    content: "Hover to zoom";
    position: absolute;
    inset-block-end: var(--s-3);
    inset-inline-end: var(--s-3);
    z-index: 2;
    padding: 0.25rem 0.6rem;
    border-radius: var(--s-radius-pill);
    background-color: color-mix(in srgb, var(--s-maroon-700) 82%, transparent);
    color: var(--s-white);
    font-size: var(--s-text-2xs);
    letter-spacing: var(--s-tracking-caps);
    text-transform: uppercase;
    opacity: 0;
    transition: opacity var(--s-fast) var(--s-ease-out);
    pointer-events: none;
  }
  .s-gallery__stage:hover::after { opacity: 1; }
  .s-gallery__stage.is-zooming::after { opacity: 0; }
}

.s-gallery__thumbs { display: grid; grid-auto-flow: column; grid-auto-columns: 4.5rem; gap: var(--s-2); overflow-x: auto; scrollbar-width: none; }
.s-gallery__thumbs::-webkit-scrollbar { display: none; }

/* On a wide screen the thumbnails are a column beside the photograph, not a
   row under it.

   That was already said, six hundred lines up, inside the `62rem` block — and
   then undone by the rule directly above this one, which comes later in the
   file and wins on source order however narrow its selector's media query is.
   The result: three thumbnails laid out left to right at x=40, 120 and 200
   inside a strip 80px wide, so the second and third were clipped away and a
   product with three pictures looked like a product with one.

   Repeated here, after the rule that broke it, rather than moved — the block
   up there also places the grid rows and columns, and splitting that apart
   would leave two half-statements of the same layout. */
@media (min-width: 62rem) {
  .s-gallery__thumbs {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-auto-rows: 4.5rem;
    overflow-x: visible;
    overflow-y: auto;
  }
}
.s-gallery__thumb {
  aspect-ratio: 1;
  overflow: hidden;
  border: 2px solid transparent;
  border-radius: var(--s-radius-sm);
  background-color: var(--s-line-soft);
}
.s-gallery__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.s-gallery__thumb.is-active { border-color: var(--s-maroon-700); }

.s-pdp__cat { font-size: var(--s-text-2xs); font-weight: 700; letter-spacing: var(--s-tracking-caps); text-transform: uppercase; color: var(--s-gold-700); }
.s-pdp__title { margin-block: var(--s-2) var(--s-3); font-size: var(--s-text-3xl); color: var(--s-maroon-900); }
@media (min-width: 62rem) { .s-pdp__title { font-size: var(--s-text-4xl); } }

.s-pdp__price-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s-3); margin-block: var(--s-4); }
.s-pdp__price { font-size: var(--s-text-3xl); font-weight: 700; color: var(--s-maroon-800); }
.s-pdp__mrp { font-size: var(--s-text-lg); color: var(--s-muted); text-decoration: line-through; }
.s-pdp__off { font-size: var(--s-text-sm); font-weight: 700; color: var(--s-success); }
.s-pdp__tax { inline-size: 100%; font-size: var(--s-text-xs); color: var(--s-muted); }

.s-pdp__block { padding-block: var(--s-5); border-block-start: 1px solid var(--s-line); }
.s-pdp__block-title { font-family: var(--s-font-body); font-size: var(--s-text-xs); font-weight: 700; letter-spacing: var(--s-tracking-caps); text-transform: uppercase; color: var(--s-muted); margin-block-end: var(--s-3); }

/* ---- Version choosers --------------------------------------------------- */

.s-choices { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.s-choice {
  min-inline-size: 3rem;
  min-block-size: 2.75rem;
  padding-inline: var(--s-4);
  display: grid;
  place-items: center;
  border: 1px solid var(--s-line);
  border-radius: var(--s-radius-sm);
  background-color: var(--s-surface);
  font-size: var(--s-text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--s-fast) var(--s-ease), background-color var(--s-fast) var(--s-ease), color var(--s-fast) var(--s-ease);
}
.s-choice:hover { border-color: var(--s-maroon-500); }
.s-choice.is-selected { border-color: var(--s-maroon-700); background-color: var(--s-maroon-700); color: var(--s-white); }
/* A combination that does not exist is shown and struck through rather than
   removed, so the shopper can see it is a real option that happens to be
   unavailable with what they have already picked. */
.s-choice.is-unavailable { opacity: 0.42; text-decoration: line-through; cursor: not-allowed; }

.s-qty { display: inline-flex; align-items: center; border: 1px solid var(--s-line); border-radius: var(--s-radius-pill); overflow: hidden; }
.s-qty__btn { inline-size: 2.75rem; block-size: 2.75rem; display: grid; place-items: center; font-size: var(--s-text-lg); }
.s-qty__btn:hover:not(:disabled) { background-color: var(--s-cream); color: var(--s-maroon-700); }
.s-qty__btn:disabled { opacity: 0.35; cursor: not-allowed; }
.s-qty__value { inline-size: 2.75rem; text-align: center; border: 0; font-weight: 700; -moz-appearance: textfield; }
.s-qty__value::-webkit-outer-spin-button, .s-qty__value::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.s-pdp__buy { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }
.s-pdp__buy .s-btn { flex: 1 1 12rem; }

/* The quick view's "Add to bag" and "Save" row. Its spacing between the two is
   settled in premium.css, beside the rule it overrides. */
.s-qv__buy { align-items: center; }

.s-stockline { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--s-text-sm); font-weight: 600; }
.s-stockline::before { content: ""; inline-size: 0.5rem; block-size: 0.5rem; border-radius: 50%; background-color: currentColor; }
.s-stockline--in { color: var(--s-success); }
.s-stockline--low { color: var(--s-warn); }
.s-stockline--out { color: var(--s-danger); }

/* Merchant-written description HTML.

   The admin editor can produce headings, lists, quotes and links, so every one
   of them needs a rule here — an unstyled <h3> inside a description is how a
   product page starts looking like a plain-text dump. Serif headings, because
   product names and prices are serif too (MASTER_PROMPT.md §7a). */
.s-prose { font-size: var(--s-text-md); line-height: 1.7; color: var(--s-ink-soft); }
.s-prose > :first-child { margin-block-start: 0; }
.s-prose > :last-child { margin-block-end: 0; }
.s-prose p + p { margin-block-start: var(--s-4); }

.s-prose h2, .s-prose h3, .s-prose h4 {
  font-family: var(--s-font-display);
  color: var(--s-ink);
  line-height: 1.25;
  margin-block: var(--s-6) var(--s-2);
}
.s-prose h2 { font-size: var(--s-text-xl); }
.s-prose h3 { font-size: var(--s-text-lg); }
.s-prose h4 { font-size: var(--s-text-md); }

.s-prose ul, .s-prose ol { padding-inline-start: 1.25rem; margin-block: var(--s-3); }
.s-prose li + li { margin-block-start: var(--s-2); }
.s-prose ul { list-style: disc; }
.s-prose ol { list-style: decimal; }

.s-prose strong, .s-prose b { color: var(--s-ink); font-weight: 600; }
.s-prose a { color: var(--s-maroon-700); text-underline-offset: 0.15em; }

/* A gold rule rather than a grey bar: the same device the card uses above its
   price, so a quote reads as part of the same shop. */
.s-prose blockquote {
  margin-block: var(--s-4);
  padding-inline-start: var(--s-4);
  border-inline-start: 2px solid var(--s-gold-500);
  color: var(--s-ink);
  font-family: var(--s-font-display);
}

.s-prose .ql-align-center { text-align: center; }
.s-prose .ql-align-right { text-align: end; }
.s-prose .ql-align-justify { text-align: justify; }

/* The collection's own writing at the foot of a category page. Held to a
   readable measure and centred, so it does not stretch to 1900px — the one
   place a capped width is right, because a 200-character line is unreadable. */
.s-prose--section {
  margin-block-start: var(--s-10);
  padding-block-start: var(--s-6);
  border-block-start: 1px solid var(--s-line-soft);
  max-inline-size: 52rem;
}

.s-specs { inline-size: 100%; border-collapse: collapse; font-size: var(--s-text-sm); }
.s-specs th, .s-specs td { padding: var(--s-3) 0; text-align: start; border-block-end: 1px solid var(--s-line-soft); vertical-align: top; }
.s-specs th { inline-size: 40%; font-weight: 600; color: var(--s-muted); }

/* Sticky buy bar on a phone — the single most valuable thing on the page
   should never be scrolled past. */
.s-stickybuy {
  position: fixed;
  inset-inline: 0;
  inset-block-end: var(--s-bottomnav-height);
  z-index: calc(var(--s-z-bottomnav) - 1);
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-gutter);
  background-color: var(--s-surface);
  border-block-start: 1px solid var(--s-line);
  box-shadow: 0 -6px 20px rgb(29 23 22 / 0.09);
  translate: 0 110%;
  transition: translate var(--s-base) var(--s-ease-out);
}
.s-stickybuy.is-shown { translate: 0; }
.s-stickybuy__price { font-weight: 700; font-size: var(--s-text-lg); color: var(--s-maroon-800); }
.s-stickybuy .s-btn { margin-inline-start: auto; flex: 1 1 auto; max-inline-size: 14rem; }
@media (min-width: 62rem) { .s-stickybuy { display: none; } }

/* --------------------------------------------------------------------------
   Quick view + lightbox
   -------------------------------------------------------------------------- */

.s-modal {
  position: fixed;
  inset: 0;
  z-index: var(--s-z-modal);
  display: grid;
  place-items: end center;
  padding: 0;
  pointer-events: none;
}
@media (min-width: 48rem) { .s-modal { place-items: center; padding: var(--s-6); } }

.s-modal__panel {
  pointer-events: auto;
  inline-size: 100%;
  max-inline-size: 56rem;
  max-block-size: 92vh;
  overflow-y: auto;
  background-color: var(--s-surface);
  border-radius: var(--s-radius-lg) var(--s-radius-lg) 0 0;
  box-shadow: var(--s-shadow-xl);
  /* A bottom sheet on a phone, a centred dialog from the tablet up. */
  translate: 0 100%;
  transition: translate var(--s-base) var(--s-ease-out), opacity var(--s-base) var(--s-ease);
  opacity: 0;
}
.s-modal.is-open .s-modal__panel { translate: 0; opacity: 1; }

@media (min-width: 48rem) {
  .s-modal__panel { border-radius: var(--s-radius-lg); translate: 0; scale: 0.96; }
  .s-modal.is-open .s-modal__panel { scale: 1; }
}

.s-modal__close {
  position: absolute;
  inset-block-start: var(--s-3);
  inset-inline-end: var(--s-3);
  z-index: 3;
  display: grid;
  place-items: center;
  inline-size: 2.5rem; block-size: 2.5rem;
  border-radius: 50%;
  background-color: rgb(255 255 255 / 0.92);
  box-shadow: var(--s-shadow-sm);
}
.s-modal__close:hover { background-color: var(--s-maroon-700); color: var(--s-white); }

/* The grab handle that tells a thumb this sheet can be dismissed. */
.s-modal__grip {
  inline-size: 2.5rem; block-size: 4px;
  margin: var(--s-3) auto 0;
  border-radius: var(--s-radius-pill);
  background-color: var(--s-line);
}
@media (min-width: 48rem) { .s-modal__grip { display: none; } }

.s-quick { display: grid; gap: var(--s-5); padding: var(--s-5); }
@media (min-width: 48rem) { .s-quick { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-8); padding: var(--s-8); } }
/* Matted, not bled — the same framing as the gallery stage and the cards
   (MASTER_PROMPT.md §7d). It was `cover`, which cropped the top and the bottom
   off every photograph the client composed; on a phone, where the sheet is
   narrow and the figure is still a square, that is most of the picture. */
.s-quick__figure {
  aspect-ratio: 1;
  overflow: hidden;
  padding: var(--s-3);
  border: 1px solid var(--s-gold-300, var(--s-line));
  border-radius: var(--s-radius);
  background-color: var(--s-white);
}
.s-quick__figure img { inline-size: 100%; block-size: 100%; object-fit: contain; }
.s-quick__title { font-size: var(--s-text-2xl); color: var(--s-maroon-900); }

.s-lightbox { display: grid; place-items: center; padding: var(--s-4); overflow: auto; }
.s-lightbox img {
  max-inline-size: min(92vw, 60rem);
  max-block-size: 88vh;
  border-radius: var(--s-radius);
  object-fit: contain;
  cursor: zoom-in;
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  transition: max-inline-size var(--s-fast) var(--s-ease-out), max-block-size var(--s-fast) var(--s-ease-out);
}

/* Filled rather than fitted. A phone cannot pinch a picture that is already
   scaled to fit the screen, so the tap has to be what enlarges it — and the
   overflow above is what then lets it be panned. */
.s-lightbox.is-zoomed img { max-inline-size: none; max-block-size: none; inline-size: 200%; cursor: zoom-out; }

/* --------------------------------------------------------------------------
   Cart drawer
   -------------------------------------------------------------------------- */

.s-cart {
  position: fixed;
  inset-block: 0;
  inset-inline-end: 0;
  z-index: var(--s-z-drawer);
  inline-size: min(26rem, 100vw);
  display: flex;
  flex-direction: column;
  background-color: var(--s-surface);
  box-shadow: var(--s-shadow-xl);
  translate: 100% 0;
  /* Out of the tab order while closed, the same way as the menu. */
  visibility: hidden;
  transition: translate var(--s-base) var(--s-ease-out), visibility 0s linear var(--s-base);
}
.s-cart.is-open {
  translate: 0;
  visibility: visible;
  transition: translate var(--s-base) var(--s-ease-out), visibility 0s;
}

.s-cart__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: var(--s-5); border-block-end: 1px solid var(--s-line); }
.s-cart__title { font-size: var(--s-text-xl); }
.s-cart__body { flex: 1 1 auto; overflow-y: auto; padding: var(--s-4); }
.s-cart__foot { padding: var(--s-5); border-block-start: 1px solid var(--s-line); background-color: var(--s-cream); }
.s-cart__total { display: flex; justify-content: space-between; align-items: baseline; margin-block-end: var(--s-4); font-weight: 700; }

/* The bag's second way out, under "Buy now" and quieter than it. */
.s-cart__second { margin-block-start: var(--s-3); }
.s-cart__total span:last-child { font-size: var(--s-text-xl); color: var(--s-maroon-800); }

/* A line with a photograph reserves a column for it. A line without one must
   not.

   The 4.5rem column used to be unconditional, so any `.s-line` with no
   thumbnail — every row on "Your orders" and on the account summary, and any
   order line whose product has no picture — had its words squeezed into 72px
   while the whole content column sat empty beside them. Same family as the
   single-picture gallery already recorded in PROJECT_HANDOFF.md §5: a column
   left behind by an element that is not there still takes its space. */
.s-line { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-3); padding-block: var(--s-3); }
.s-line:has(.s-line__thumb) { grid-template-columns: 4.5rem minmax(0, 1fr); }
.s-line + .s-line { border-block-start: 1px solid var(--s-line-soft); }
.s-line__thumb { aspect-ratio: 1; border-radius: var(--s-radius-sm); object-fit: cover; background-color: var(--s-line-soft); }
.s-line__name { font-size: var(--s-text-sm); font-weight: 600; line-height: 1.3; }
.s-line__meta { font-size: var(--s-text-xs); color: var(--s-muted); }
.s-line__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); margin-block-start: var(--s-2); }
.s-line__price { font-weight: 700; color: var(--s-maroon-800); }

/* The price belongs beside the words, never under the photograph.

   `.s-line` is a two-column grid and the price is its third child, so it was
   landing on the second row of the **first** column — the 4.5rem one reserved
   for the picture. "₹1,500.00" needs 74px and that column is 72px, so it was
   clipped at 320. `-2` is the last column whether the line has a picture or
   not, which is why it is written that way rather than as `2`.

   Scoped with `>` on purpose: the bag nests its price inside `.s-line__foot`,
   which is a flex row and has no business being told about grid columns. */
.s-line > .s-line__price { grid-column: -2; justify-self: end; }

/* One return or exchange, on the customer's own order page.

   Deliberately not `.s-line`: that grid reserves a 4.5rem column for a
   photograph, and a return has no photograph — so its words were being squeezed
   into the thumbnail's 72px column and clipped at 320. Same rhythm, same
   separator, no column for a picture that does not exist. */
.s-request { display: grid; gap: var(--s-2); padding-block: var(--s-3); }
.s-request + .s-request { border-block-start: 1px solid var(--s-line-soft); }
.s-request__actions { justify-self: start; }

/* --------------------------------------------------------------------------
   Empty states — designed, never faked
   -------------------------------------------------------------------------- */

.s-empty { display: grid; justify-items: center; gap: var(--s-3); padding: var(--s-12) var(--s-4); text-align: center; }
.s-empty__mark { display: grid; place-items: center; inline-size: 4rem; block-size: 4rem; border-radius: 50%; background-color: var(--s-gold-100); color: var(--s-gold-700); }
.s-empty__mark svg { inline-size: 1.75rem; block-size: 1.75rem; }
.s-empty__title { font-size: var(--s-text-xl); color: var(--s-maroon-900); }
.s-empty__body { max-inline-size: 30rem; color: var(--s-muted); font-size: var(--s-text-sm); }

/* --------------------------------------------------------------------------
   Bottom navigation — phones only
   -------------------------------------------------------------------------- */

.s-bottomnav {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--s-z-bottomnav);
  display: grid;
  /* `minmax(0, 1fr)`, never a bare `1fr`.

     A `1fr` track has an automatic minimum of its own min-content, so five
     items whose widest word does not fit a fifth of the screen push the bar
     wider than the phone — and because the bar is fixed and full-bleed, that
     scrolls the **whole document** sideways. At 356 the fifth item, Account,
     was cut off the end and the bag page dragged. Same family as everywhere
     else in this file; see PROJECT_HANDOFF.md §5. */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  block-size: var(--s-bottomnav-height);
  background-color: var(--s-surface);
  border-block-start: 1px solid var(--s-line);
  padding-block-end: env(safe-area-inset-bottom, 0);
}
@media (min-width: 62rem) { .s-bottomnav { display: none; } }

.s-bottomnav__item {
  position: relative;
  display: grid;
  place-items: center;
  gap: 2px;
  min-inline-size: 0;
  padding-inline: 2px;
  font-size: 0.625rem;
  font-weight: 600;
  color: var(--s-muted);
  text-align: center;
}

/* The word under the icon is one line and gives ground rather than taking it —
   a label that wraps makes its own item taller than its four neighbours. */
.s-bottomnav__item > span {
  max-inline-size: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.s-bottomnav__item svg { inline-size: 1.375rem; block-size: 1.375rem; }
.s-bottomnav__item.is-active { color: var(--s-maroon-700); }
.s-bottomnav__item.is-active::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inline-size: 1.75rem;
  block-size: 3px;
  border-radius: 0 0 3px 3px;
  background-color: var(--s-maroon-700);
}
.s-bottomnav__count {
  position: absolute;
  inset-block-start: 0.35rem;
  inset-inline-start: 55%;
  min-inline-size: 1.05rem;
  block-size: 1.05rem;
  padding-inline: 0.2rem;
  display: grid;
  place-items: center;
  border-radius: var(--s-radius-pill);
  background-color: var(--s-maroon-700);
  color: var(--s-white);
  font-size: 0.6rem;
  font-weight: 700;
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.s-footer { background-color: var(--s-maroon-900); color: rgb(255 255 255 / 0.78); }

.s-footer__top {
  display: grid;
  gap: var(--s-8);
  padding-block: var(--s-12);
}
@media (min-width: 48rem) { .s-footer__top { grid-template-columns: 1.4fr repeat(3, 1fr); gap: var(--s-8); } }

.s-footer__logo { block-size: 6rem; inline-size: auto; margin-block-end: var(--s-4); }
.s-footer__blurb { font-size: var(--s-text-sm); max-inline-size: 24rem; }

.s-footer__title {
  font-family: var(--s-font-body);
  font-size: var(--s-text-xs);
  font-weight: 700;
  letter-spacing: var(--s-tracking-caps);
  text-transform: uppercase;
  color: var(--s-gold-400);
  margin-block-end: var(--s-4);
}
.s-footer__list { display: grid; gap: var(--s-2); font-size: var(--s-text-sm); }
.s-footer__list a:hover { color: var(--s-gold-300); }

.s-footer__contact { display: grid; gap: var(--s-3); font-size: var(--s-text-sm); }
.s-footer__contact a { display: inline-flex; align-items: center; gap: var(--s-2); }
.s-footer__contact a:hover { color: var(--s-gold-300); }

.s-social { display: flex; gap: var(--s-2); margin-block-start: var(--s-5); }
.s-social a {
  display: grid;
  place-items: center;
  inline-size: 2.25rem; block-size: 2.25rem;
  border-radius: 50%;
  border: 1px solid rgb(255 255 255 / 0.22);
  transition: background-color var(--s-fast) var(--s-ease), color var(--s-fast) var(--s-ease);
}
.s-social a:hover { background-color: var(--s-gold-500); color: var(--s-maroon-900); border-color: transparent; }
.s-social svg { inline-size: 1.05rem; block-size: 1.05rem; }

.s-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding-block: var(--s-5);
  border-block-start: 1px solid rgb(255 255 255 / 0.14);
  font-size: var(--s-text-xs);
}

/* --------------------------------------------------------------------------
   Breadcrumbs
   -------------------------------------------------------------------------- */

.s-crumbs { padding-block: var(--s-4); font-size: var(--s-text-xs); color: var(--s-muted); }
.s-crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); list-style: none; padding: 0; }
.s-crumbs li + li::before { content: "/"; margin-inline-end: var(--s-2); opacity: 0.5; }
.s-crumbs a:hover { color: var(--s-maroon-700); }

/* --------------------------------------------------------------------------
   Toasts
   -------------------------------------------------------------------------- */

/* On a phone the message arrives at the TOP, not the bottom.

   It used to sit just above the bottom navigation — which is exactly where the
   "Add to bag" and "Save" buttons are on a product page and inside the quick
   view. The client filmed it: "Saved for later" landed squarely across both
   buttons, and the second message landed across the first. Anchoring it to the
   buttons would only move the collision; the top of the screen is the one band
   on a phone that no action row ever occupies.

   On a desktop there is no bottom bar and plenty of room, so it stays where it
   was, bottom right. */
.s-toasts {
  position: fixed;
  inset-block-start: calc(var(--s-3) + env(safe-area-inset-top, 0px));
  inset-block-end: auto;
  inset-inline: var(--s-gutter);
  z-index: var(--s-z-toast);
  display: grid;
  gap: var(--s-2);
  justify-items: center;
  pointer-events: none;
}
@media (min-width: 62rem) {
  .s-toasts {
    inset-block-start: auto;
    inset-block-end: var(--s-6);
    inset-inline: auto var(--s-6);
    justify-items: end;
  }

  /*
   * With the bag open, messages move to the left of it.
   *
   * The bag is a panel down the right-hand side and its "Go to bag" button sits
   * at the bottom of it — the same corner a message appears in. "Added to your
   * bag" therefore landed on top of the button that acts on it, which is what
   * the client photographed on 9 September 2026.
   *
   * Shifted by the panel's own width so the message sits beside the bag rather
   * than on it. `26rem` is `.s-cart`'s width; the two must stay in step.
   */
  .s-cart.is-open ~ .s-toasts {
    inset-inline-end: calc(min(26rem, 100vw) + var(--s-6));
  }
}

.s-toast {
  /*
   * A message, and nothing to press.
   *
   * This was `auto`, which let a message that is only ever read take every
   * click that landed on it — and the bag's own "Go to bag" button sits exactly
   * where a message appears on a desktop, so for the three seconds a message
   * was up that button could not be pressed at all. Reported by the client on
   * 9 September 2026 as the two overlapping each other.
   *
   * There is nothing in a message to click: no close control, no link, and it
   * takes itself off screen after a few seconds. So it lets presses through to
   * whatever it is covering.
   */
  pointer-events: none;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  max-inline-size: 24rem;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--s-radius);
  background-color: var(--s-ink);
  color: var(--s-white);
  font-size: var(--s-text-sm);
  box-shadow: var(--s-shadow-lg);
  animation: s-toast-in var(--s-base) var(--s-ease-out);
}
/* The shop's own colour, not a system green.

   The client asked for it in as many words: a brown in the brand's family. A
   confirmation on this shop should look like it came from this shop. Failures
   keep the red, because a warning that matches the furniture is a warning
   nobody reads. */
.s-toast--ok { background-color: var(--s-maroon-700); }
.s-toast--bad { background-color: var(--s-danger); }
.s-toast a { text-decoration: underline; font-weight: 600; }

/* Coming down from the top on a phone, up from the bottom on a desktop. */
@keyframes s-toast-in { from { opacity: 0; translate: 0 -0.75rem; } to { opacity: 1; translate: 0; } }
@media (min-width: 62rem) {
  @keyframes s-toast-in { from { opacity: 0; translate: 0 0.75rem; } to { opacity: 1; translate: 0; } }
}

/* --------------------------------------------------------------------------
   Pagination
   -------------------------------------------------------------------------- */

.s-pager { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); margin-block-start: var(--s-8); }
.s-pager a, .s-pager span {
  min-inline-size: 2.5rem;
  min-block-size: 2.5rem;
  padding-inline: var(--s-3);
  display: grid;
  place-items: center;
  border: 1px solid var(--s-line);
  border-radius: var(--s-radius-sm);
  background-color: var(--s-surface);
  font-size: var(--s-text-sm);
  font-weight: 600;
}
.s-pager a:hover { border-color: var(--s-maroon-700); color: var(--s-maroon-700); }
.s-pager .is-current { background-color: var(--s-maroon-700); border-color: var(--s-maroon-700); color: var(--s-white); }
.s-pager .is-disabled { opacity: 0.4; }

/* --------------------------------------------------------------------------
   Bag page
   -------------------------------------------------------------------------- */

.s-cartpage { display: grid; gap: var(--s-6); align-items: start; }
@media (min-width: 62rem) { .s-cartpage { grid-template-columns: minmax(0, 1fr) 22rem; gap: var(--s-8); } }

/* A grid item will not shrink below its min-content unless it is told it may,
   and both panels on the bag page are grid items. The bag's own line — thumbnail,
   name, quantity stepper, price — has a min-content around 375px, so on a 356px
   phone the panel stayed 375 wide inside a 324px column and the whole document
   scrolled sideways: the subtotal and the Apply button were both cut off at the
   right. Reported by the client from a 356 × 620 phone. Sixth appearance of this
   family; see PROJECT_HANDOFF.md §5. */
.s-cartpage > * { min-inline-size: 0; }

.s-panel {
  min-inline-size: 0;
  padding: var(--s-5);
  border: 1px solid var(--s-line);
  border-radius: var(--s-radius);
  background-color: var(--s-surface);
}
@media (min-width: 62rem) { .s-summary { position: sticky; inset-block-start: calc(var(--s-4) + 5.5rem); } }

.s-line__meta--warn { color: var(--s-warn); font-weight: 600; }
.s-line__remove { margin-block-start: 0.4rem; font-size: var(--s-text-xs); color: var(--s-muted); text-decoration: underline; }
.s-line__remove:hover { color: var(--s-danger); }

.s-note { font-size: var(--s-text-xs); color: var(--s-muted); }

.s-callout {
  margin-block-start: var(--s-4);
  padding: var(--s-4);
  border-radius: var(--s-radius-sm);
  background-color: var(--s-gold-100);
  font-size: var(--s-text-sm);
  line-height: 1.55;
}

/* The mobile filter sheet borrows the cart drawer's shell but is its own
   dialog, so both can be open-and-closed independently. */
.s-filtersheet { translate: 100% 0; }
.s-filtersheet.is-open { translate: 0; }

/* ---- the "page not found" page ----------------------------------------- */

/* One panel, centred, generous. It replaces Laravel's black "404 | NOT FOUND"
   screen, which had no header and no way back (live, 2026-09-05). */
.s-notfound {
  max-width: 40rem;
  margin: 3rem auto;
  padding: 2.5rem 2rem;
  text-align: center;
}

.s-notfound__body { color: var(--s-muted); margin: 0.75rem 0 1.5rem; }

.s-notfound__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
  align-items: center;
}
