/* Aaradesigner storefront — design tokens.
   Identity: deep wine + dusty rose on blush. It's a tonal palette — everything light on the page is a
   tint of the same rose the brand signs with, so the page reads as one fabric rather than a neutral
   shell with a colour dropped on it. Wine is the primary (CTAs, active states, the footer plane); dusty
   rose is the single accent (eyebrows, rules, the secondary CTA, the best-seller tag) and stays scarce.
   There is no third brand hue — the only non-rose colours on the page are status signals (sale red,
   in-stock green, low-stock amber, star amber), and they're deliberately foreign so they read as
   information rather than decoration. */
:root {
  /* Brand */
  --maroon: #87143c;        /* primary wine */
  --maroon-dark: #650e2c;   /* hover + the dark footer plane */
  --maroon-light: #a02a50;
  --accent: #debec6;        /* dusty rose */
  --accent-dark: #8d495a;   /* the readable-as-text rose: eyebrows, hover fills */
  --accent-light: #ebd6dc;
  /* Dusty rose is a light-mid tone (L* ~79) — white on it is 1.7:1. Anything sitting ON --accent takes
     this near-black wine instead, which clears 9:1. */
  --on-accent: #3a1622;

  /* Surfaces — blush tints, lightest to deepest */
  --cream: #f5e8ed;         /* page background */
  --peach: #f2e1e8;         /* tinted band (price strip, CTA panel) */
  --warm: #faf0f4;          /* hover fills, chips, quiet panels — sits on white, so lighter than --cream */
  --line: #e7d5dc;

  /* Type — warmed a few degrees toward the wine so neutral grey never reads as dingy on the blush */
  --heading: #21141a;       /* display + headings */
  --ink: #3a2e33;           /* body copy */
  --muted: #735c64;         /* secondary copy — 4.8:1 on --peach, the tightest surface it lands on */

  /* Status */
  --sale: #c0392b;
  --new-arrival: #2e7d5b;
  --best-seller: #82590f;   /* low-stock warning TEXT — needs 4.5:1, so a deep amber, not the badge tint */
  --featured: #87143c;
  /* Stars stay amber. A rose star would disappear into the palette and a wine one would compete with the
     sale price directly under it; amber is also the one shape on a product card customers read without
     looking. Deepened from the old gold so it clears 3:1 as a graphical object on both white and blush. */
  --star: #a8721f;

  /* A single wine-tinted shadow hue, so elevation never goes cold-grey against the blush. */
  --shadow: 62, 26, 40;

  /* Editorial, not rounded: panels get a soft 8px, controls a near-square 3px. */
  --radius: 8px;
  --radius-sm: 3px;

  /* Heights of the fixed mobile chrome. Named because up to two bars can stack at the bottom of a phone
     viewport — the tab nav always, plus the PDP's buy bar above it — and four separate rules have to
     agree on the total: each bar's own `bottom` offset, the page's bottom padding, and the WhatsApp
     button's clearance. A literal 56px repeated across them is a bug waiting for someone to change one
     of them. Both bars set `height` explicitly to exactly these values, so the arithmetic is a fact
     rather than an estimate of what padding and font metrics happen to add up to. */
  --sf-bottomnav-h: 56px;
  --sf-pdpbar-h: 64px;

  --font-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --font-body: 'Nunito Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-accent: 'Raleway', -apple-system, BlinkMacSystemFont, sans-serif;
}

* { box-sizing: border-box; }

body.storefront {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  animation: sf-fade-in .35s ease both;
}

@keyframes sf-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Solid wine, not a translucent tint: a 16%-alpha maroon over this site's blush surfaces resolved to
   almost the same pink as the page itself, so selected text barely looked selected. Dark planes (footer,
   closing CTA, announce bar, maroon buttons) flip to cream-on-wine — wine-on-wine with dark text made a
   selection there literally unreadable. */
::selection { background: var(--maroon); color: #fff; }
.sf-announce ::selection, .sf-footer ::selection, .sf-cta-band ::selection,
.sf-btn-maroon ::selection, .sf-hero-slide-overlay ::selection {
  background: var(--cream); color: var(--maroon-dark);
}
*:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }

/* Playfair is a high-contrast serif: it needs a little weight and tighter tracking to hold up at
   display sizes, and never sits at the default 1.5 line-height a sans would. */
.sf-display {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.2;
}

/* Small uppercase label that sits above a section heading. Raleway, not the serif — Playfair at 12px
   with wide tracking loses its thick/thin contrast and just reads as a weak sans. */
.sf-eyebrow {
  font-family: var(--font-accent);
  font-size: .7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .22em;
  color: var(--accent-dark);
  text-align: center;
  margin: 0 0 .6rem;
}

/* "View All →" — the reference's one recurring link treatment. The arrow steps forward on hover and a
   hairline wipes in under the label. */
.sf-section-more { text-align: center; margin-top: 2rem; }
.sf-view-all {
  display: inline-flex; align-items: center; gap: .5rem; position: relative;
  font-family: var(--font-accent); font-size: .76rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .16em; color: var(--maroon);
  padding-bottom: .3rem;
}
.sf-view-all::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: left; transition: transform .28s cubic-bezier(.16,1,.3,1);
}
.sf-view-all:hover { color: var(--maroon-dark); }
.sf-view-all:hover::after { transform: scaleX(1); }
.sf-view-all span { transition: transform .28s cubic-bezier(.16,1,.3,1); }
.sf-view-all:hover span { transform: translateX(4px); }

a { color: inherit; text-decoration: none; }

/* ---- Announcement ticker — a seamless-loop marquee: the message list is rendered twice back to back,
   and the whole strip animates by exactly -50% (one full copy's width), so the loop point is invisible. */
.sf-announce {
  background: var(--maroon);
  color: #fff;
  font-family: var(--font-accent);
  font-size: .72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .16em;
  padding: .6rem 0;
  display: flex;
  align-items: center;
  gap: 1rem;
  position: relative;
  overflow: hidden;
}
.sf-announce-track {
  flex: 1;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 24px, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 24px, #000 calc(100% - 24px), transparent);
}
.sf-announce-track-inner {
  display: inline-flex;
  white-space: nowrap;
  animation: sf-marquee linear infinite;
}
.sf-announce-item { padding: 0 2rem; }
.sf-announce-item a, .sf-announce-item span { color: inherit; text-decoration: none; }
.sf-announce-item a:hover { text-decoration: underline; }
@keyframes sf-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.sf-announce-close {
  flex: 0 0 auto;
  margin-right: 1rem;
  background: transparent;
  border: 0;
  color: #fff;
  opacity: .8;
  cursor: pointer;
  font-size: .95rem;
  line-height: 1;
  transition: opacity .15s;
}
.sf-announce-close:hover { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .sf-announce-track-inner { animation: none; } }

/* ---- Header ---- */
.sf-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 1.1rem clamp(1rem, 4vw, 2.5rem);
  border-bottom: 1px solid var(--line);
  background: #fff;
  position: relative;
}
.sf-nav {
  display: flex; align-items: center; gap: 2rem;
  font-family: var(--font-accent); font-size: .76rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .16em;
}
.sf-nav .sf-dropdown { position: relative; }
.sf-nav a:hover, .sf-nav button:hover { color: var(--maroon); }
/* text-transform/letter-spacing are restated explicitly: the `font: inherit` shorthand resets the
   font-* longhands but Chrome's UA button style still wins on casing without these. */
.sf-nav button {
  background: none; border: 0; font: inherit; cursor: pointer; color: inherit;
  text-transform: uppercase; letter-spacing: .16em;
  display: flex; align-items: center; gap: .4rem;
}
/* Animated underline — wipes in from the left on hover/focus. Desktop only: below 860px the nav is a
   stacked panel where a per-item underline would fight the row dividers. */
@media (min-width: 861px) {
  .sf-nav > a, .sf-nav > .sf-dropdown > button { position: relative; padding-bottom: .3rem; }
  .sf-nav > a::after, .sf-nav > .sf-dropdown > button::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--maroon);
    transform: scaleX(0); transform-origin: left; transition: transform .28s cubic-bezier(.16,1,.3,1);
  }
  .sf-nav > a:hover::after, .sf-nav > a:focus-visible::after,
  .sf-nav > .sf-dropdown > button:hover::after,
  .sf-nav > .sf-dropdown:hover > button::after,
  .sf-nav > .sf-dropdown:focus-within > button::after { transform: scaleX(1); }
}
/* The "gap" between the trigger and the menu used to be a real margin (top: calc(100% + .9rem)) — empty
   space that belongs to neither element, so the mouse briefly left .sf-dropdown's hover subtree crossing
   it and the menu closed before it could be reached. Now the menu sits flush (top: 100%, zero gap) and
   the same visual space is padding-top *inside* .sf-dropdown-menu instead — still part of its box, so
   :hover never lapses while the cursor crosses it. The visible card (background/border/shadow) moved to
   .sf-dropdown-menu-inner, which starts only after that padding, so nothing looks different. */
/* left:0, not centered under the trigger — "Category" sits early in the nav (left column of the
   header's 3-col grid), close to the page's left edge. A 360px-wide menu centered under it would
   overhang further left than the trigger itself and run into (or past) the viewport edge. Left-aligning
   means it only ever extends right of the trigger, staying inside the header's own left inset. */
.sf-dropdown-menu {
  position: absolute; top: 100%; left: 0;
  padding-top: .9rem; min-width: 360px; display: none; z-index: 40;
}
.sf-dropdown:hover .sf-dropdown-menu, .sf-dropdown:focus-within .sf-dropdown-menu { display: block; }
.sf-dropdown-menu-inner {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: 0 18px 40px rgba(var(--shadow),.14);
  padding: .7rem;
  /* Two columns once there's enough categories to make one long column look ungainly — with under 5
     items this just leaves the second column empty, which is fine (the menu still isn't taller than it
     needs to be, unlike a fixed-height scroll container would risk). */
  display: grid; grid-template-columns: repeat(2, 1fr); gap: .1rem .4rem;
}
.sf-dropdown-menu a {
  display: block; padding: .6rem .8rem; border-radius: var(--radius-sm); font-family: var(--font-body);
  font-size: .87rem; font-weight: 400; text-transform: none; letter-spacing: normal; transition: background .15s, color .15s;
  white-space: nowrap;
}
.sf-dropdown-menu a:hover { color: var(--maroon); }
.sf-dropdown-menu a:hover { background: var(--warm); }

/* One seamless pill instead of a rounded input next to a separately-shaped button (the old version had
   the input at border-radius:999px and the button at --radius-sm — the shape mismatch read as two
   unrelated controls stuck together). overflow:hidden on the pill itself clips the button's square
   corners to match, so there's exactly one continuous outline. */
.sf-search-bar {
  max-width: 420px; margin: 1.5rem auto 0; display: flex; align-items: stretch;
  border: 1.5px solid var(--line); border-radius: 999px; overflow: hidden; background: #fff;
  transition: border-color .15s, box-shadow .15s;
}
.sf-search-bar:focus-within { border-color: var(--maroon); box-shadow: 0 0 0 3px rgba(var(--shadow),.1); }
.sf-search-bar input {
  flex: 1; min-width: 0; border: 0; background: none; padding: .8rem 0 .8rem 1.2rem; font: inherit; color: var(--ink);
}
.sf-search-bar input:focus { outline: none; }
.sf-search-bar button {
  border: 0; background: var(--maroon); color: #fff; width: 3rem; flex-shrink: 0; cursor: pointer;
  font-size: .95rem; transition: background .15s;
}
.sf-search-bar button:hover { background: var(--maroon-dark); }

/* PDP quantity stepper — was three inline-styled elements with --radius-sm (3px, near-square) corners
   and no hover feedback, easy to miss against the reskinned blush background. Rounder to match the
   softer pill language used elsewhere (search bar, buttons), and the −/+ buttons now tint on hover so
   they read as clickable rather than static labels either side of the number. */
.sf-qty-stepper {
  display: flex; align-items: center; border: 1.5px solid var(--line); border-radius: var(--radius); overflow: hidden; background: #fff;
}
.sf-qty-stepper button {
  border: 0; background: none; width: 40px; height: 44px; cursor: pointer; font-size: 1.15rem; color: var(--ink);
  transition: background .15s, color .15s;
}
.sf-qty-stepper button:hover { background: var(--warm); color: var(--maroon); }
.sf-qty-stepper input {
  width: 46px; border: 0; border-left: 1.5px solid var(--line); border-right: 1.5px solid var(--line);
  height: 44px; text-align: center; font: inherit; font-weight: 600; color: var(--ink);
}
.sf-qty-stepper input:focus { outline: none; background: var(--warm); }
/* Hide the native number-input spinner arrows — the −/+ buttons are the only stepper UI. */
.sf-qty-stepper input::-webkit-outer-spin-button, .sf-qty-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.sf-qty-stepper input[type=number] { -moz-appearance: textfield; }

.sf-logo { display: flex; flex-direction: column; align-items: center; justify-self: center; line-height: 1; }
.sf-logo-img { height: 46px; width: auto; object-fit: contain; }
@media (max-width: 640px) { .sf-logo-img { height: 36px; } }

.sf-icons { display: flex; align-items: center; justify-content: flex-end; gap: 1.1rem; }

.sf-nav-toggle { display: none; background: none; border: 0; font-size: 1.25rem; color: var(--ink); cursor: pointer; padding: .2rem .4rem; justify-self: start; }

/* ---- Header: mobile nav (hamburger + tap-open category submenu) ---- */
@media (max-width: 860px) {
  .sf-header { grid-template-columns: auto 1fr auto; }
  .sf-nav-toggle { display: inline-flex; }

  .sf-nav {
    position: absolute; top: 100%; left: 0; right: 0; z-index: 50; flex-direction: column; align-items: stretch; gap: 0;
    background: #fff; border-bottom: 1px solid var(--line); box-shadow: 0 16px 32px rgba(var(--shadow),.1);
    max-height: 0; overflow: hidden; transition: max-height .25s ease;
  }
  .sf-nav.sf-nav-open { max-height: 360px; overflow-y: auto; }
  .sf-nav a, .sf-nav > .sf-dropdown > button { padding: .9rem 1.4rem; width: 100%; text-align: left; border-top: 1px solid var(--line); }
  .sf-nav > a:first-child { border-top: 0; }

  /* Below this breakpoint there's no hover, so the dropdown is JS-driven via .sf-dropdown-open. */
  .sf-dropdown:hover .sf-dropdown-menu, .sf-dropdown:focus-within .sf-dropdown-menu { display: none; }
  .sf-dropdown-menu {
    position: static; transform: none; padding-top: 0; min-width: 0; display: none;
  }
  .sf-dropdown.sf-dropdown-open .sf-dropdown-menu { display: block; }
  .sf-dropdown-menu-inner {
    background: var(--warm); border: 0; border-radius: 0; box-shadow: none; padding: 0;
    display: block; /* single column — the 2-up grid is a desktop-only space-saving trick */
  }
  .sf-dropdown-menu a { padding: .75rem 1.4rem .75rem 2.2rem; border-top: 1px solid var(--line); border-radius: 0; white-space: normal; }
}
.sf-icon-btn { position: relative; display: inline-flex; background: none; border: 0; cursor: pointer; color: var(--ink); font-size: 1.05rem; padding: .2rem; transition: color .15s, transform .15s; }
.sf-icon-btn:hover { color: var(--maroon); transform: translateY(-1px); }
.sf-badge {
  position: absolute; top: -6px; right: -8px; background: var(--maroon); color: #fff;
  font-size: .62rem; font-weight: 700; min-width: 16px; height: 16px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center; padding: 0 3px;
  transition: transform .18s;
}
.sf-badge.sf-pop { animation: sf-pop .35s ease; }
@keyframes sf-pop { 0% { transform: scale(1); } 40% { transform: scale(1.5); } 100% { transform: scale(1); } }
/* The templates and storefront.js both hide an empty (count == 0) badge with `d-none` — a Bootstrap
   class name that only exists in the admin panel's stylesheet, never here, so until this rule every
   empty cart/favorites badge rendered a literal "0". Scoped to .sf-badge rather than declared as a
   global utility: this stylesheet's vocabulary is sf-prefixed, and a bare .d-none invites more of the
   admin's Bootstrap vocabulary to drift in. */
.sf-badge.d-none { display: none; }

/* ---- Buttons — near-square corners, Raleway small caps, wide tracking. Boutique, not app-store. ---- */
.sf-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  border: 1.5px solid transparent; border-radius: var(--radius-sm); padding: .85rem 1.7rem;
  font-family: var(--font-accent); font-weight: 700; font-size: .76rem;
  text-transform: uppercase; letter-spacing: .14em; line-height: 1.2;
  cursor: pointer; transition: transform .15s, box-shadow .15s, background .2s, border-color .2s, color .2s, opacity .15s;
}
.sf-btn:active { transform: translateY(1px); }
.sf-btn-maroon { background: var(--maroon); border-color: var(--maroon); color: #fff; }
.sf-btn-maroon:hover { background: var(--maroon-dark); border-color: var(--maroon-dark); box-shadow: 0 10px 22px rgba(135,20,60,.28); }
/* Dusty rose takes near-black wine text, not white — white on #debec6 is a 1.7:1 contrast failure.
   The hover deepens the rose only as far as it can go while still holding that same dark label (7.5:1);
   dropping to --accent-dark here would force the text to flip to white mid-hover, which reads as a
   different button rather than the same one responding. */
.sf-btn-rose { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.sf-btn-rose:hover { background: #d0a8b3; border-color: #d0a8b3; box-shadow: 0 10px 22px rgba(141,73,90,.3); }
/* Wine outline that fills on hover — the reference's secondary CTA. */
.sf-btn-outline { background: transparent; border-color: var(--maroon); color: var(--maroon); }
.sf-btn-outline:hover { background: var(--maroon); color: #fff; }
/* Quiet utility button (Cancel, Back, Refresh) — stays neutral so it never competes with a real CTA. */
.sf-btn-ghost { background: #fff; color: var(--ink); border-color: var(--line); }
.sf-btn-ghost:hover { border-color: var(--maroon); color: var(--maroon); }
/* A <select> wearing .sf-btn: keep the chrome, drop the small-caps — option text isn't a button label. */
select.sf-btn { font-family: var(--font-body); font-weight: 600; font-size: .85rem; text-transform: none; letter-spacing: .01em; }
.sf-btn[disabled] { opacity: .45; cursor: not-allowed; }
.sf-btn .sf-spinner { display: none; }
.sf-btn.sf-loading .sf-spinner, .sf-btn.htmx-request .sf-spinner { display: inline-block; }
.sf-btn.sf-loading .sf-btn-label, .sf-btn.htmx-request .sf-btn-label { opacity: .6; }
.sf-spinner {
  width: 14px; height: 14px; border-radius: 50%; border: 2px solid rgba(255,255,255,.4); border-top-color: #fff;
  animation: sf-spin .6s linear infinite;
}
.sf-btn-rose .sf-spinner { border-color: rgba(58,22,34,.3); border-top-color: var(--on-accent); }
.sf-btn-ghost .sf-spinner, .sf-btn-outline .sf-spinner { border-color: rgba(135,20,60,.25); border-top-color: var(--maroon); }
@keyframes sf-spin { to { transform: rotate(360deg); } }

/* ---- Sections ---- */
.sf-section { padding: clamp(2.5rem, 5vw, 4.5rem) clamp(1rem, 4vw, 2.5rem); }
/* Playfair at 500, not 700 — the face already carries plenty of stroke contrast, and the heavier cut
   turns blobby at display sizes. Tracking pulls in slightly to close the serif's natural gaps. */
.sf-section-title {
  font-family: var(--font-display); font-weight: 500; font-size: clamp(1.75rem, 3vw, 2.4rem);
  line-height: 1.18; letter-spacing: -.01em; text-align: center; color: var(--heading); margin: 0 0 .6rem;
}
.sf-section-sub { text-align: center; color: var(--muted); max-width: 560px; margin: 0 auto 2.5rem; font-size: .93rem; line-height: 1.7; }

/* One tier down, for the homepage's repeated per-category browse sections. There are nine of them in a
   row, and at the full section size each one announced itself as loudly as "New Arrivals" — nine chapter
   headings where the page only has three chapters. Smaller type and tighter padding make them read as
   what they are: shelves under the Shop by Category grid, not equals of the curated rows above it. The
   heading block alone was costing ~300px nine times over. */
.sf-section.sf-catsec { padding: clamp(2rem, 3.6vw, 3rem) clamp(1rem, 4vw, 2.5rem); }
.sf-catsec .sf-section-title { font-size: clamp(1.45rem, 2.2vw, 1.85rem); margin-bottom: .45rem; }
.sf-catsec .sf-section-sub { margin-bottom: 0; font-size: .88rem; }
.sf-catsec .sf-eyebrow { margin-bottom: .45rem; }
/* The gap above the grid lives here rather than under the heading above it, because the sub-heading is
   the category's optional admin description — most categories don't have one, and hanging the spacing
   off an element that may not exist is how a section ends up with its grid jammed against its title. */
.sf-catsec .sf-home-cat-results { margin-top: 1.7rem; }
.sf-catsec .sf-section-more { margin-top: 1.4rem; }

/* ---- Hero 2: text + real product photo ---- */
@keyframes sf-rise { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: translateY(0); } }

.sf-hero2 {
  display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: clamp(2rem, 5vw, 4rem);
  padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.2rem, 5vw, 3rem);
  background: radial-gradient(120% 160% at 100% 0%, rgba(222,190,198,.85), transparent 58%),
              radial-gradient(120% 160% at 0% 100%, rgba(135,20,60,.09), transparent 55%),
              var(--cream);
}
.sf-hero2-text { animation: sf-rise .7s cubic-bezier(.16,1,.3,1) both; }
.sf-hero2-eyebrow {
  font-family: var(--font-accent); text-transform: uppercase; letter-spacing: .24em;
  font-size: .72rem; font-weight: 600; color: var(--accent-dark); margin: 0 0 .9rem;
}
.sf-hero2-title { font-family: var(--font-display); font-weight: 600; font-size: clamp(2.1rem, 4.4vw, 3.4rem); line-height: 1.14; letter-spacing: -.015em; color: var(--heading); margin: 0 0 1.1rem; }
.sf-hero2-sub { color: var(--ink); opacity: .78; font-size: clamp(.95rem, 1.4vw, 1.05rem); line-height: 1.65; max-width: 460px; margin: 0 0 1.8rem; }
.sf-hero2-cta { display: flex; flex-wrap: wrap; gap: .9rem; margin-bottom: 1.8rem; }
.sf-hero2-chips { display: flex; flex-wrap: wrap; gap: 1.4rem .9rem; }
.sf-hero2-chips span { display: inline-flex; align-items: center; gap: .5rem; font-size: .82rem; color: var(--muted); font-weight: 500; }
.sf-hero2-chips i { color: var(--maroon); font-size: .85rem; }

.sf-hero2-art { position: relative; display: flex; justify-content: center; animation: sf-rise .85s cubic-bezier(.16,1,.3,1) both; }
.sf-hero2-photo-link {
  position: relative; display: block; width: min(100%, 380px); aspect-ratio: 3/4; border-radius: var(--radius);
  overflow: hidden; box-shadow: 0 34px 70px rgba(var(--shadow),.25); transform: rotate(1.2deg); transition: transform .3s ease;
}
.sf-hero2-photo-link:hover { transform: rotate(0deg) scale(1.015); }
.sf-hero2-photo { width: 100%; height: 100%; object-fit: cover; display: block; }
.sf-hero2-photo-tag {
  position: absolute; left: 1rem; right: 1rem; bottom: 1rem; background: rgba(255,255,255,.92); backdrop-filter: blur(4px);
  border-radius: var(--radius); padding: .7rem .9rem; display: flex; flex-direction: column; gap: .1rem; box-shadow: 0 10px 24px rgba(0,0,0,.12);
}
.sf-hero2-photo-tag-label { font-family: var(--font-accent); font-size: .64rem; text-transform: uppercase; letter-spacing: .18em; color: var(--maroon); font-weight: 700; }
.sf-hero2-photo-tag span:last-child { font-size: .86rem; font-weight: 600; color: var(--heading); }
.sf-hero2-motif {
  width: min(100%, 380px); aspect-ratio: 3/4; border-radius: var(--radius); overflow: hidden; position: relative;
  box-shadow: 0 34px 70px rgba(var(--shadow),.2);
}

@media (max-width: 860px) {
  .sf-hero2 { grid-template-columns: 1fr; text-align: center; }
  .sf-hero2-sub { margin-left: auto; margin-right: auto; }
  .sf-hero2-cta, .sf-hero2-chips { justify-content: center; }
  .sf-hero2-art { order: -1; }
  .sf-hero2-photo-link, .sf-hero2-motif { width: min(100%, 300px); }
}

/* ---- Hero slider — admin-managed banner carousel. Slides are stacked (position:absolute) and
   crossfaded by JS toggling .active (see storefront.js "Hero slider"); there's no scrollable/draggable
   surface at all, on purpose — customers only ever scroll this page vertically, so advancing slides is
   autoplay + tapping the dots/arrows, never a horizontal swipe gesture. */
.sf-hero-slider { position: relative; }
.sf-hero-slider-viewport { overflow: hidden; }
/* height via clamp(), not aspect-ratio + max-height — on a block box that's stretching to fill a wide
   parent, some browsers resolve a conflict between "fill available width" and "max-height" by shrinking
   the WIDTH to satisfy the ratio instead (560px * 16/7 = 1280px), leaving a blank gap beside a narrower-
   than-expected slider on wide screens. An explicit width + a plain height clamp can't fight like that. */
.sf-hero-slider-track { position: relative; width: 100%; height: clamp(320px, 32vw, 560px); }
.sf-hero-slide {
  position: absolute; inset: 0; opacity: 0; pointer-events: none; transition: opacity .6s ease;
}
.sf-hero-slide.active { opacity: 1; pointer-events: auto; }
.sf-hero-slide-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sf-hero-slide-overlay {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
  padding: clamp(1.5rem, 6vw, 4rem); gap: .6rem; max-width: 560px; color: #fff;
  background: linear-gradient(90deg, rgba(var(--shadow),.6) 0%, rgba(var(--shadow),.2) 55%, transparent 80%);
}
/* Over photography, Playfair needs 600 — its hairline strokes disappear into a busy image at 400/500. */
.sf-hero-slide-title {
  font-family: var(--font-display); font-weight: 600; font-size: clamp(1.7rem, 4vw, 2.8rem);
  line-height: 1.16; letter-spacing: -.01em; margin: 0; text-shadow: 0 2px 12px rgba(0,0,0,.35);
}
.sf-hero-slide-subtitle { font-size: clamp(.9rem, 1.4vw, 1.05rem); opacity: .95; margin: 0 0 .4rem; max-width: 420px; text-shadow: 0 1px 8px rgba(0,0,0,.3); }
.sf-hero-slider-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; width: 42px; height: 42px; border-radius: 50%;
  background: rgba(255,255,255,.85); border: 0; color: var(--maroon); cursor: pointer; display: flex; align-items: center;
  justify-content: center; box-shadow: 0 6px 18px rgba(0,0,0,.15); transition: background .15s;
}
.sf-hero-slider-arrow:hover { background: #fff; }
.sf-hero-slider-prev { left: 1rem; }
.sf-hero-slider-next { right: 1rem; }
.sf-hero-slider-dots { position: absolute; bottom: 1.1rem; left: 50%; transform: translateX(-50%); display: flex; gap: .5rem; z-index: 2; }
.sf-hero-slider-dot { width: 9px; height: 9px; border-radius: 50%; border: 0; background: rgba(255,255,255,.55); cursor: pointer; padding: 0; transition: background .15s, width .15s; }
.sf-hero-slider-dot.active { background: #fff; width: 22px; border-radius: 5px; }

@media (max-width: 860px) {
  .sf-hero-slider-track { height: clamp(380px, 125vw, 480px); }
  .sf-hero-slide-overlay {
    max-width: 100%; text-align: center; align-items: center; justify-content: flex-end; padding-bottom: 2.4rem;
    background: linear-gradient(180deg, rgba(var(--shadow),.1) 0%, rgba(var(--shadow),.7) 78%);
  }
  .sf-hero-slider-arrow { width: 36px; height: 36px; }
}
@media (prefers-reduced-motion: reduce) { .sf-hero-slide { transition: none; } }

/* ---- Trust band ----
   Sits directly under the hero and is the page's confidence anchor — the slot a bigger store fills with
   "10 lakh+ customers". This is a new studio with a handful of real orders, so there is no honest number
   to put here; instead the four icons get a title that frames them as a promise the customer can hold us
   to. It costs one heading and claims nothing that isn't already true elsewhere on the site. */
/* Not .sf-section: this is the head of the icon grid below it, so it owns only its own top padding and
   lets .sf-trust's padding supply the gap between the heading and the icons. */
.sf-trust-band { padding: clamp(2.2rem, 4.5vw, 3.2rem) clamp(1rem, 4vw, 2.5rem) 0; }
.sf-trust-head {
  font-family: var(--font-display); font-weight: 500; font-size: clamp(1.35rem, 2.4vw, 1.7rem);
  line-height: 1.2; letter-spacing: -.01em; text-align: center; color: var(--heading); margin: 0;
}
.sf-trust {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.6rem; max-width: 1200px; margin: 0 auto;
  padding: clamp(2rem, 4vw, 2.8rem) clamp(1rem, 4vw, 2.5rem);
}
.sf-trust-item { display: flex; align-items: flex-start; gap: .9rem; }
.sf-trust-item i {
  width: 44px; height: 44px; border-radius: 50%; background: var(--accent); color: var(--maroon);
  display: flex; align-items: center; justify-content: center; font-size: 1.05rem; flex-shrink: 0;
}
.sf-trust-item strong { display: block; font-family: var(--font-display); font-weight: 600; font-size: .98rem; color: var(--heading); margin-bottom: .25rem; }
.sf-trust-item span { display: block; font-size: .8rem; color: var(--muted); line-height: 1.4; }
@media (max-width: 860px) { .sf-trust { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px) { .sf-trust { grid-template-columns: 1fr; } }

/* ---- "Find yours" band — the catalog-wide colour/size/budget filter, on the homepage ----

   The problem it solves is placement, not filtering: /search already answers "show me everything in
   green, in an XL, under two thousand", and until now the only way to ask was to guess that a nav link
   called "Shop" hid a sidebar. This band puts the three questions on the page every customer lands on.

   The form is a tailor's docket, which is the one object this brand's own positioning earns — a
   made-to-order studio takes your colour, your size and your budget on a slip before it cuts anything.
   So: a white slip on the deeper blush band, ruled into three labelled fields, with the label set in the
   left gutter and right-aligned so the three rows share one hard vertical edge. The dashed stitch is
   inherited from the "Shop by Price" tickets this band replaced — the same single line of dashes, moved
   onto the component that now does that job, so the page still has exactly one stitch on it.

   No rules between the rows, deliberately. The gutter and the alignment already say "form"; hairlines
   on top of that would say "table", and the card would start reading as data rather than as a choice. */
.sf-shopby-section { background: var(--peach); padding: clamp(2rem, 4vw, 3.2rem) clamp(1rem, 4vw, 2.5rem); }
.sf-shopby {
  /* Deliberately narrower than the 1200px measure the product grids use — this is a slip laid on the
     page, not a section of it, and it should not span the same width as the catalog underneath. The
     number is set by the content: 24 short chips laid against an 88px label gutter fill about 880px, and
     at the grids' full width all three rows ended well short of the right edge, a form with a column of
     blank paper beside it. At 960 the colour row breaks 7 + 5 rather than 10 + 2, and the size row very
     nearly fills its track. */
  position: relative; max-width: 960px; margin: 0 auto;
  background: #fff; border-radius: var(--radius);
  padding: clamp(1.5rem, 3vw, 2rem) clamp(1.2rem, 3vw, 2.2rem) clamp(1.6rem, 3vw, 2.1rem);
  box-shadow: 0 14px 34px rgba(var(--shadow), .08);
}
/* The stitch — inset pseudo-element, not a border on the card, so the dash sits inside the padding box
   and the card's own corner radius stays crisp behind it. */
.sf-shopby::before {
  content: ""; position: absolute; inset: 8px; border: 1px dashed var(--accent);
  border-radius: calc(var(--radius) - 6px); pointer-events: none;
}
/* Above the stitch, and the padding is what keeps the content clear of it. */
.sf-shopby > * { position: relative; }

/* Baseline, not flex-end: the escape hatch for the customer who doesn't want to filter at all belongs on
   the same line as the heading, reading as "Find yours … or browse all 121 pieces". Aligned to the
   bottom of the block it sat level with the second line of the sub-heading instead, attached to nothing. */
.sf-shopby-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: .5rem 2rem;
  flex-wrap: wrap; margin-bottom: clamp(1.1rem, 2.2vw, 1.4rem);
}
.sf-shopby-head-copy { min-width: 0; }
/* Left-aligned, unlike every .sf-section-title on the page, and a size down. This heading belongs to the
   card it sits inside — a centred display title would turn a control into a section and cost the
   vertical space the band exists to save. */
.sf-shopby-title {
  font-family: var(--font-display); font-weight: 500; font-size: clamp(1.4rem, 2.4vw, 1.85rem);
  line-height: 1.15; letter-spacing: -.01em; color: var(--heading); margin: 0 0 .35rem;
}
.sf-shopby-sub { color: var(--muted); font-size: .88rem; line-height: 1.6; margin: 0; max-width: 46ch; }
.sf-shopby-all { flex-shrink: 0; }

/* Label gutter + options. min-width:0 on the options track is load-bearing: without it a grid column
   sized 1fr takes its max-content width from the chips inside, the row grows past the card, and the
   whole page gets a horizontal scrollbar on a phone instead of the row scrolling inside itself. */
.sf-shopby-row {
  display: grid; grid-template-columns: 5.5rem minmax(0, 1fr); align-items: start;
  gap: .9rem; padding: .55rem 0;
}
.sf-shopby-label {
  font-family: var(--font-accent); font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .18em; color: var(--accent-dark);
  text-align: right; margin: 0; padding-top: .95rem; line-height: 1;
}
.sf-shopby-opts { min-width: 0; display: flex; flex-wrap: wrap; gap: .5rem; }

.sf-shopby-chip {
  display: inline-flex; align-items: center; gap: .5rem; flex: 0 0 auto; min-height: 42px;
  padding: .35rem .85rem; background: #fff; border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-family: var(--font-body); font-size: .84rem; font-weight: 600; color: var(--ink);
  text-decoration: none; white-space: nowrap;
  transition: border-color .2s, background-color .2s, color .2s, box-shadow .2s;
}
.sf-shopby-chip:hover, .sf-shopby-chip:focus-visible {
  border-color: var(--maroon); background: var(--warm); color: var(--maroon);
  box-shadow: 0 6px 14px rgba(var(--shadow), .1);
}
/* Ring rather than a plain circle: several catalog colours (White, Peach, Gold) are lighter than the
   chip they sit on and would otherwise read as a hole in the border. */
.sf-shopby-dot {
  width: 15px; height: 15px; border-radius: 50%; flex: 0 0 auto;
  box-shadow: inset 0 0 0 1px rgba(var(--shadow), .22);
}
/* Sizes are codes, not words — the accent face at letterspacing keeps XS/M/XXXL legible and stops the
   short ones from looking like typos next to the colour names. */
.sf-shopby-chip-size {
  font-family: var(--font-accent); font-weight: 700; letter-spacing: .06em;
  justify-content: center; min-width: 3.1rem;
}
/* The budget chips keep the price ticket's setting — "Under" small and tracked, the amount in Playfair
   with the rupee sign lifted — at chip scale. It is the one typographic voice worth carrying over from
   the section this band replaced, and it stops the shortest row on the card from reading as an
   afterthought. */
.sf-shopby-chip-price { gap: .55rem; padding-right: 1rem; }
.sf-shopby-under {
  font-family: var(--font-accent); font-size: .62rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .16em; color: var(--muted); transition: color .2s;
}
.sf-shopby-amount {
  font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; line-height: 1;
  letter-spacing: -.01em; color: var(--maroon);
}
.sf-shopby-chip-price:hover .sf-shopby-under { color: var(--accent-dark); }

/* Phone: the label moves above its row.
 *
 * Only the colour row turns into a swiper, and the split is about what the customer is doing, not about
 * saving space. Colour is a browse: twelve named swatches wrapped would be four lines of chips and the
 * card would outgrow the hero above it, and a shopper scanning colours will happily swipe. Size is the
 * opposite — nobody browses sizes, they look for *theirs*, and a row that hides six of ten behind a
 * gesture tells a customer hunting for XXXL that this studio doesn't make it. Sizes wrap and every one
 * of them stays on screen. Budget is two chips; it never needed a gesture either.
 *
 * That split is also why the trailing edge-mask lives on the scrolling row alone. Applied to all three
 * it dimmed the last chip of rows that fit perfectly well — the "there's more this way" signal pointing
 * at nothing, over a ₹2,000 chip a customer could already see. The colour row's content is ~1,170px
 * against a track that is never wider than ~740px here, so on this row the fade is always telling the
 * truth. The overflow lives on the row itself, never a parent, so the page can't scroll sideways. */
@media (max-width: 860px) {
  .sf-shopby-row { grid-template-columns: 1fr; gap: .45rem; padding: .5rem 0; }
  .sf-shopby-label { text-align: left; padding-top: 0; }
  .sf-shopby-opts-scroll {
    flex-wrap: nowrap; overflow-x: auto; padding-bottom: .15rem;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 1.8rem), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 1.8rem), transparent 100%);
  }
  .sf-shopby-opts-scroll::-webkit-scrollbar { display: none; }
  .sf-shopby-head { align-items: flex-start; flex-direction: column; gap: .8rem; }
}
@media (prefers-reduced-motion: reduce) { .sf-shopby-chip { transition: none; } }

/* ---- Closing CTA band ---- */
/* Its own section padding, taller than the default .sf-section — this is the page's closing signature
   moment, so the surrounding cream/peach breathing room is deliberately more generous than a regular
   content section's. */
.sf-cta-section { padding-top: clamp(3.2rem, 7vw, 6rem); padding-bottom: clamp(3.2rem, 7vw, 6rem); background: var(--peach); }
.sf-cta-band {
  position: relative; overflow: hidden; max-width: 1200px; margin: 0 auto;
  background: linear-gradient(120deg, var(--maroon-dark) 0%, var(--maroon) 100%);
  border-radius: var(--radius); padding: clamp(2rem, 4.5vw, 2.9rem) clamp(1.6rem, 4vw, 3.2rem);
  display: flex; align-items: center; justify-content: space-between; gap: 1.8rem; flex-wrap: wrap;
  box-shadow: 0 18px 40px -18px rgba(101, 14, 44, .55);
}
.sf-cta-band-mark {
  position: absolute; top: 50%; right: clamp(1rem, 6vw, 4rem); transform: translateY(-50%);
  font-size: clamp(4rem, 9vw, 7rem); color: rgba(255,255,255,.08); pointer-events: none;
}
.sf-cta-band-copy { position: relative; z-index: 1; }
.sf-cta-band-copy .sf-eyebrow { margin-bottom: .5rem; }
.sf-cta-band h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.3rem, 2.5vw, 1.65rem); color: #fff; margin: 0 0 .5rem; }
.sf-cta-band-copy p { color: rgba(255,255,255,.82); font-size: .9rem; line-height: 1.65; margin: 0; max-width: 460px; }
.sf-cta-band-btn { position: relative; z-index: 1; background: #fff; border-color: #fff; color: var(--maroon-dark); flex-shrink: 0; }
.sf-cta-band-btn:hover { background: var(--cream); border-color: var(--cream); box-shadow: 0 10px 24px rgba(0,0,0,.22); }

/* ---- Category grid: image-forward tiles, dense on desktop, horizontal-scroll on mobile ---- */
/* A vertical-wrapping grid at every width — customers scroll down to see more tiles, never sideways.
   auto-fill naturally drops to fewer columns as the viewport narrows (2 columns around phone widths). */
.sf-cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1.1rem; max-width: 1200px; margin: 0 auto; }
@media (max-width: 640px) { .sf-cat-grid { grid-template-columns: repeat(2, 1fr); gap: .8rem; } }
.sf-cat-card {
  position: relative; display: block; border-radius: var(--radius); overflow: hidden; aspect-ratio: 3/4;
  box-shadow: 0 1px 2px rgba(var(--shadow),.06); transition: box-shadow .25s ease, transform .25s ease;
}
.sf-cat-card:hover { transform: translateY(-4px); box-shadow: 0 18px 34px rgba(var(--shadow),.20); }
.sf-cat-img, .sf-cat-card .sf-art { transition: transform .5s cubic-bezier(.16,1,.3,1); }
.sf-cat-card:hover .sf-cat-img, .sf-cat-card:hover .sf-art { transform: scale(1.08); }
.sf-cat-scrim { position: absolute; inset: 0; background: linear-gradient(to top, rgba(32,12,20,.78) 0%, rgba(32,12,20,.05) 65%); }
.sf-cat-label {
  position: absolute; left: 0; right: 0; bottom: 0; padding: .9rem .95rem .85rem;
  transform: translateY(2px); transition: transform .25s ease;
}
.sf-cat-card:hover .sf-cat-label { transform: translateY(-2px); }
.sf-cat-label strong { display: block; color: #fff; font-family: var(--font-accent); font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .12em; text-shadow: 0 1px 3px rgba(0,0,0,.3); }

/* ---- Category rail — the quick way into a collection, near the top of the page ----
   Two forms of one component: .sf-catrail-item (homepage — arch thumb, name beneath) and
   .sf-catswitch-item (category page — the same arch at chip scale, name beside it, so the row reads as
   a tab strip between sibling collections).

   The arch is the shape decision. This pattern is almost always drawn as a circle, but a circle crops a
   full-length kurti or saree into an unreadable middle; a 3:4 portrait with a semicircular top keeps the
   drape and the hemline, and reads as a lookbook frame rather than an avatar. Its square-ish foot uses
   the same 3px control radius as every button on the site, so it belongs to this palette's editorial
   geometry rather than importing an app-store one.

   This is the one place on the storefront where content scrolls sideways, and it is a deliberate
   exception rather than a walking-back of the rule that governs the product and category grids: a rail
   of ten small labelled links is navigation, and a swipeable strip is how it is read everywhere. The
   overflow lives on .sf-catrail itself, never on a parent, so the page can't scroll horizontally — and
   above the 860px nav breakpoint the row wraps and centres instead, so there is no sideways scroll on a
   desktop at all. Verify both by checking documentElement.scrollWidth against clientWidth. */
.sf-catrail-band {
  background: #fff;
  border-bottom: 1px solid var(--line);
  padding: 1.4rem clamp(1rem, 4vw, 2.5rem);
}
.sf-catrail-wrap { max-width: 1200px; margin: 0 auto; }
.sf-catrail {
  display: flex;
  align-items: flex-start;
  gap: clamp(.85rem, 2.4vw, 1.4rem);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* The strip is masked to nothing at the trailing edge, so a partly-visible item fades out instead of
     being cut — the standard, wordless "there's more this way". Removed once the row wraps. */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.2rem), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 2.2rem), transparent 100%);
}
.sf-catrail::-webkit-scrollbar { display: none; }
.sf-catrail-item {
  flex: 0 0 auto; width: 78px; scroll-snap-align: start;
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
  text-decoration: none;
}
.sf-catrail-art {
  position: relative; display: block; width: 100%; aspect-ratio: 3 / 4; overflow: hidden;
  background: var(--warm);
  border-radius: 999px 999px var(--radius-sm) var(--radius-sm);
  box-shadow: 0 0 0 1px var(--line);
  transition: box-shadow .25s ease, transform .25s ease;
}
.sf-catrail-item:hover .sf-catrail-art {
  transform: translateY(-3px);
  box-shadow: 0 0 0 1.5px var(--maroon), 0 12px 22px rgba(var(--shadow), .18);
}
.sf-catrail-name {
  font-family: var(--font-accent); font-size: .63rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .07em; line-height: 1.3;
  color: var(--ink); text-align: center;
  transition: color .2s;
}
.sf-catrail-item:hover .sf-catrail-name { color: var(--maroon); }

/* Category-page variant: thumb and name on one line, so the switcher costs ~52px above the products
   the customer actually came for rather than the ~140px the homepage rail spends. */
/* Not the rail's 1200px measure: this row has to start on the same vertical as the filter sidebar and
   product grid directly beneath it, and .sf-listing takes the full section width. */
.sf-catswitch-wrap { max-width: none; margin-top: 1.8rem; }
.sf-catswitch-label {
  font-family: var(--font-accent); font-size: .64rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .18em; color: var(--muted);
  margin: 0 0 .6rem;
}
.sf-catswitch { gap: .55rem; align-items: stretch; }
.sf-catswitch-item {
  flex: 0 0 auto; scroll-snap-align: start;
  display: inline-flex; align-items: center; gap: .6rem;
  padding: .3rem .85rem .3rem .3rem;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius-sm);
  text-decoration: none;
  transition: border-color .2s, box-shadow .2s;
}
.sf-catswitch-item:hover { border-color: var(--maroon); box-shadow: 0 6px 14px rgba(var(--shadow), .12); }
.sf-catswitch-item .sf-catrail-art {
  width: 30px; box-shadow: none;
  border-radius: 999px 999px 2px 2px;
}
.sf-catswitch-item:hover .sf-catrail-art { transform: none; box-shadow: none; }
.sf-catswitch-item .sf-catrail-name { font-size: .66rem; white-space: nowrap; }

/* Desktop: ten collections fit on one centred line inside the 1200px measure, so the rail stops being a
   scroller entirely — no sideways scrolling with a mouse, and no edge fade implying one. */
@media (min-width: 861px) {
  .sf-catrail {
    flex-wrap: wrap; justify-content: center; overflow-x: visible;
    -webkit-mask-image: none; mask-image: none;
  }
  .sf-catrail-item { width: 92px; }
  /* The switcher stays left-flush at every width so it lines up with its own label, rather than
     centring on desktop and hanging under a left-aligned caption. */
  .sf-catswitch { justify-content: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
  .sf-catrail-art, .sf-catrail-name, .sf-catswitch-item { transition: none; }
  .sf-catrail-item:hover .sf-catrail-art { transform: none; }
}

/* ---- Placeholder art (no product photography yet) ---- */
.sf-art {
  position: absolute; inset: 0; overflow: hidden; display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(120% 120% at 15% 10%, rgba(255,255,255,.28), transparent 55%),
    linear-gradient(135deg, var(--maroon-dark) 0%, var(--maroon) 55%, var(--accent) 135%);
}
.sf-art::before {
  content: ""; position: absolute; inset: 0; opacity: .5;
  background-image:
    repeating-linear-gradient(135deg, rgba(255,255,255,.16) 0 2px, transparent 2px 14px);
}
.sf-art-motif { position: relative; width: 38%; opacity: .92; }

/* ---- Real product photo (once uploaded) — fills the same box .sf-art does ---- */
.sf-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* ---- Product cards ---- */
.sf-product-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.6rem; }
@media (max-width: 980px) { .sf-product-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px) { .sf-product-grid { grid-template-columns: 1fr 1fr; gap: 1rem; } }
.sf-card { display: flex; flex-direction: column; position: relative; }
.sf-card-art {
  aspect-ratio: 3/4; border-radius: var(--radius); position: relative; overflow: hidden;
  transition: transform .25s ease, box-shadow .25s ease;
}
.sf-card:hover .sf-card-art { transform: translateY(-4px); box-shadow: 0 20px 40px rgba(var(--shadow),.18); }
.sf-badge-pill {
  position: absolute; top: .7rem; left: .7rem; z-index: 2; color: #fff;
  font-family: var(--font-accent); font-size: .62rem; font-weight: 700;
  padding: .32rem .6rem; border-radius: var(--radius-sm); letter-spacing: .14em; text-transform: uppercase;
}
.sf-badge-new-arrival { background: var(--new-arrival); }
/* Dusty rose is light — the best-seller tag takes the dark wine ink so it stays readable at 10px. */
.sf-badge-best-seller { background: var(--accent); color: var(--on-accent); }
.sf-badge-featured { background: var(--featured); }
.sf-badge-discount { background: var(--sale); }
.sf-soldout-overlay {
  position: absolute; inset: 0; background: rgba(245,232,237,.75); display: flex; align-items: center; justify-content: center; z-index: 2;
}
.sf-soldout-pill {
  background: #fff; border-radius: var(--radius-sm); padding: .55rem 1.1rem; box-shadow: 0 8px 18px rgba(var(--shadow),.18);
  font-family: var(--font-accent); font-weight: 700; font-size: .7rem; text-transform: uppercase; letter-spacing: .14em; color: var(--heading);
}
.sf-fav-btn {
  position: absolute; top: .7rem; right: .7rem; z-index: 3; width: 34px; height: 34px; border-radius: 50%;
  background: #fff; border: 0; display: flex; align-items: center; justify-content: center; cursor: pointer;
  box-shadow: 0 6px 14px rgba(0,0,0,.12); color: var(--muted); transition: color .15s, transform .15s;
}
.sf-fav-btn:hover { transform: scale(1.08); }
.sf-fav-btn.is-fav { color: var(--maroon); }
/* The heart itself gets the same pop the header badge does, so the optimistic fill on click reads as a
   deliberate confirmation rather than a static icon quietly changing colour. */
.sf-fav-btn.is-fav i { animation: sf-pop .35s ease; }
/* Un-hearting on the favorites page collapses the card out of the grid (storefront.js). A class rather
   than a DOM removal, so a failed request can put the card straight back. The final keyframe takes it
   out of layout too — a faded-but-still-there card leaves a hole in the grid; browsers that can't
   animate `display` just leave the hole, which is the lesser failure. */
.sf-card.sf-fav-removed { pointer-events: none; animation: sf-card-remove .22s ease forwards; }
@keyframes sf-card-remove {
  from { opacity: 1; transform: scale(1); }
  99%  { opacity: 0; transform: scale(.94); }
  to   { opacity: 0; transform: scale(.94); display: none; }
}
@media (prefers-reduced-motion: reduce) { .sf-fav-btn.is-fav i { animation: none; } }
.sf-card-body { padding-top: .85rem; }
/* Empty stars stay visibly quieter than filled ones, but not the old #dcc7cf — that was 1.35:1 against
   the blush page background, which made the row (and especially the count beside it) read as missing
   rather than empty. The count gets --muted, the same guaranteed-readable tone as all secondary copy. */
.sf-card-rating { color: #c4a2af; font-size: .72rem; letter-spacing: 1px; }
.sf-card-rating .filled { color: var(--star); }
.sf-card-rating span { color: var(--muted); }
/* Serif product names — the strongest, cheapest boutique cue on a grid of photographs. Prices stay in
   the sans: numerals need to be unambiguous, and the contrast separates name from price at a glance. */
.sf-card-name { font-family: var(--font-display); font-weight: 500; font-size: 1rem; line-height: 1.35; color: var(--heading); margin: .35rem 0 .3rem; }
.sf-price { font-weight: 700; font-size: .95rem; color: var(--heading); }
.sf-price-was { color: var(--muted); text-decoration: line-through; font-weight: 400; font-size: .84rem; margin-right: .4rem; }
.sf-price-sale { color: var(--sale); }

/* ---- Skeleton shimmer (reused pattern for async swaps) ---- */
.sk { position: relative; overflow: hidden; background: #ecdce3; border-radius: var(--radius-sm); }
.sk::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.75), transparent);
  animation: sk-shimmer 1.2s infinite;
}
@keyframes sk-shimmer { 100% { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .sk::after { animation: none; } body.storefront { animation: none; } }

/* ---- Footer ---- */
.sf-footer {
  position: relative; overflow: hidden; background: var(--maroon-dark); color: rgba(255,255,255,.82);
  padding: 3.5rem clamp(1rem, 4vw, 2.5rem) 2.4rem; margin-top: 3rem;
}
/* The seal — the brand's six-petal motif doubled into a rosette (markup in layout.html), sunk behind
   the closing rows and clipped by the footer's own overflow so it reads as a watermark pressed into the
   wine, not a logo sitting on it. overflow:hidden above is what crops it; don't remove one without the
   other. It's the single decorative move down here — everything else in the footer stays flat. */
.sf-footer-seal {
  position: absolute; left: 50%; bottom: -64px; transform: translateX(-50%);
  width: 280px; height: 280px; color: #fff; opacity: .13; pointer-events: none;
}
@media (max-width: 560px) { .sf-footer-seal { width: 200px; height: 200px; bottom: -46px; } }
/* A thin rose seam where the blush page meets the wine footer, instead of a hard flat edge. */
.sf-footer::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--accent-dark), var(--accent-light) 50%, var(--accent-dark));
}
/* The three footer rows are positioned so they paint above the absolutely-positioned seal — an
   in-flow sibling would otherwise sit *under* it in the paint order regardless of DOM order. */
.sf-footer-grid, .sf-footer-pay, .sf-footer-bottom { position: relative; }
.sf-footer-grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr 1fr; gap: 2.5rem; max-width: 1200px; margin: 0 auto; }
@media (max-width: 860px) { .sf-footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .sf-footer-grid { grid-template-columns: 1fr; } .sf-footer-brand { text-align: center; } }
.sf-footer h4 {
  color: #fff; font-family: var(--font-accent); font-weight: 700; font-size: .76rem;
  text-transform: uppercase; letter-spacing: .18em; margin: 0 0 1.2rem;
}
/* A short rose rule under each column heading. It earns its place on mobile, where the four columns
   stack into one tall list and this is the only thing telling a reader where one section ends. */
.sf-footer h4::after {
  content: ""; display: block; width: 26px; height: 2px; margin-top: .55rem;
  background: var(--accent); opacity: .75;
}
.sf-footer h4.sf-footer-logo::after { display: none; }
/* Selector matches `.sf-footer h4`'s specificity plus one, so the wordmark can override the column-
   heading styling without a pile of !important. */
.sf-footer h4.sf-footer-logo {
  font-family: var(--font-display); font-weight: 500; font-size: 1.55rem;
  text-transform: none; letter-spacing: .01em;
}
.sf-footer-tagline { opacity: .72; max-width: 320px; font-size: .88rem; line-height: 1.7; margin: 0 0 1.1rem; }
@media (max-width: 560px) { .sf-footer-tagline { margin-left: auto; margin-right: auto; } }
.sf-footer a { opacity: .82; transition: opacity .15s, color .15s; }
.sf-footer a:hover { opacity: 1; color: var(--accent-light); }
.sf-footer-links { display: flex; flex-direction: column; gap: .7rem; font-size: .88rem; }
.sf-footer-links a { display: flex; align-items: center; gap: .55rem; }
.sf-footer-links a i { font-size: .8rem; width: 1em; color: var(--accent); opacity: .9; flex-shrink: 0; }
/* "Our Promise" footer badges — informational, not links, so they get their own icon+label rule rather
   than piggybacking on `.sf-footer-links a` (no hover state, nothing to click). */
.sf-footer-badges { gap: .85rem; }
.sf-footer-badges span { display: flex; align-items: center; gap: .6rem; opacity: .88; }
/* The promise icons get a tinted disc so the column carries some weight of its own next to the two
   link columns — it's four short lines of text otherwise, and it reads as the thinnest thing here. */
.sf-footer-badges span i {
  width: 26px; height: 26px; border-radius: 50%; background: rgba(222,190,198,.14);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .74rem; color: var(--accent); opacity: 1; flex-shrink: 0;
}

/* ---- Social ----
   White discs with each platform's own mark in its own colour. Against the wine plane these are the
   only saturated things in the footer, which is the point: they're the one row down here that's meant
   to be clicked, and the ghost-outline treatment they replaced disappeared into the background. */
.sf-footer .sf-social { display: flex; gap: .65rem; margin-top: 1.1rem; flex-wrap: wrap; }
@media (max-width: 560px) { .sf-footer .sf-social { justify-content: center; } }
.sf-footer .sf-social a {
  width: 40px; height: 40px; border-radius: 50%; background: #fff; opacity: 1;
  display: flex; align-items: center; justify-content: center; font-size: 1.05rem;
  box-shadow: 0 2px 10px rgba(0,0,0,.18);
  transition: transform .16s, box-shadow .16s;
}
.sf-footer .sf-social a:hover { opacity: 1; transform: translateY(-3px); box-shadow: 0 9px 20px rgba(0,0,0,.3); }
/* Colours live on the <i>, not the <a>: `.sf-footer a:hover` sets a colour on the anchor, and putting
   the brand colour there too would mean every icon turned rose on hover. */
.sf-footer .sf-so-facebook i { color: #1877f2; }
.sf-footer .sf-so-threads i { color: #101010; }
.sf-footer .sf-so-whatsapp i { color: #25d366; }
/* Instagram's mark is a gradient, not a flat colour — painted through the glyph. The `color` line is
   the fallback for anything without background-clip:text, so the icon is never invisible. */
.sf-footer .sf-so-instagram i {
  color: #dc2743;
  background: linear-gradient(45deg, #f9ce34 5%, #ee2a7b 50%, #6228d7 95%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ---- Payment methods ----
   Its own labelled row rather than three grey chips squeezed against the copyright: on a made-to-order
   store the "how do I pay, and is it safe" question is a real hesitation, so it gets real estate. */
.sf-footer-pay {
  max-width: 1200px; margin: 2.6rem auto 0; padding-top: 1.7rem;
  border-top: 1px solid rgba(255,255,255,.12);
  display: flex; align-items: center; flex-wrap: wrap; gap: .85rem;
}
.sf-footer-pay-label {
  font-family: var(--font-accent); font-size: .66rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .18em; opacity: .62;
}
.sf-footer-payments { display: flex; gap: .45rem; align-items: center; flex-wrap: wrap; }
.sf-footer-payments span {
  height: 28px; padding: 0 .55rem; border-radius: 5px; background: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 1.2rem; line-height: 1;
  box-shadow: 0 1px 4px rgba(0,0,0,.18);
}
/* UPI / RuPay / Netbanking have no mark in the bundled icon font, so they're set as type in the utility
   face — a deliberate wordmark chip, not a placeholder for a logo that never arrives. */
.sf-footer-payments .sf-pay-text {
  font-family: var(--font-accent); font-size: .7rem; font-weight: 700;
  letter-spacing: .06em; color: var(--maroon-dark);
}
.sf-footer-payments .sf-pay-visa i { color: #1a1f71; }
.sf-footer-payments .sf-pay-mc i { color: #eb001b; }
.sf-footer-secure {
  margin-left: auto; display: inline-flex; align-items: center; gap: .45rem;
  font-size: .76rem; opacity: .68;
}
.sf-footer-secure i { color: var(--accent); font-size: .72rem; }
@media (max-width: 640px) { .sf-footer-secure { margin-left: 0; } }

.sf-footer-bottom {
  max-width: 1200px; margin: 1.8rem auto 0; padding-top: 1.4rem; border-top: 1px solid rgba(255,255,255,.12);
  display: flex; justify-content: center; align-items: center; flex-wrap: wrap; gap: 1rem;
  font-size: .8rem; opacity: .7; text-align: center;
}

/* ---- Empty states ---- */
.sf-empty { text-align: center; padding: 5rem 1rem; color: var(--muted); }
.sf-empty i { font-size: 2.4rem; opacity: .4; margin-bottom: 1rem; display: block; }

/* ---- Listing layout: filter sidebar + product grid (category/search pages) ---- */
.sf-listing { display: grid; grid-template-columns: 240px 1fr; gap: 2.2rem; align-items: start; }
@media (max-width: 860px) { .sf-listing { grid-template-columns: 1fr; } }
/* Set on category.html/search.html when the filter sidebar has nothing to filter by (see
   fragments.html :: filterSidebar's th:if) — without this the 240px column stays reserved as a blank
   gutter even once the empty "Filter By" card inside it is gone. */
.sf-listing.sf-listing-no-filters { grid-template-columns: 1fr; }

.sf-filters {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem;
  position: sticky; top: 1.5rem;
}
.sf-filters-summary {
  display: none; list-style: none; cursor: pointer; align-items: center; justify-content: space-between;
  font-weight: 600; font-family: var(--font-display); color: var(--heading); font-size: 1.05rem;
}
.sf-filters-summary::-webkit-details-marker { display: none; }
.sf-filters-caret { font-size: .75rem; transition: transform .2s; }
.sf-filters[open] .sf-filters-caret { transform: rotate(180deg); }
.sf-filters-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem; }
.sf-filters-title { font-weight: 600; font-family: var(--font-display); color: var(--heading); font-size: 1.05rem; }
.sf-filters-clear { font-family: var(--font-accent); font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: var(--maroon); }
.sf-filters-clear:hover { text-decoration: underline; }
/* Each filter axis (Price, Colour, Size) is its own collapsible <details> — same open/close chevron
   pattern as the outer .sf-filters shell, not a JS toggle. */
.sf-filter-section { padding: 1rem 0; border-top: 1px solid var(--line); }
.sf-filter-section:first-of-type { border-top: 0; padding-top: 0; }
.sf-filter-section summary {
  display: flex; align-items: center; justify-content: space-between; cursor: pointer; list-style: none;
  font-family: var(--font-accent); font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .16em; color: var(--heading);
}
.sf-filter-section summary::-webkit-details-marker { display: none; }
.sf-filter-section summary i { font-size: .7rem; color: var(--muted); transition: transform .2s; }
.sf-filter-section[open] summary i { transform: rotate(180deg); }
.sf-filter-section-body { margin-top: .9rem; }

/* Active-filter chips, shown above the collapsible sections when at least one filter is applied. */
.sf-filter-chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.1rem; }
.sf-filter-chip {
  display: inline-flex; align-items: center; gap: .45rem; background: var(--warm); color: var(--ink);
  border-radius: var(--radius-sm); padding: .42rem .8rem; font-size: .78rem; font-weight: 600; opacity: 1;
  transition: background .15s;
}
.sf-filter-chip:hover { background: #f0dfe7; }
.sf-filter-chip i { font-size: .65rem; color: var(--muted); }

/* ---- "Under ₹X" quick-filter chips (category + search listing pages) ----
   Distinct from .sf-filter-chip above on purpose, because they say opposite things: a filter chip is a
   *removal* control describing a filter already on (quiet warm fill, × always showing), a price chip is
   an *offer* (white card, wine only once it's the one in effect). They're the listing-page relative of
   the homepage's Shop by Price tiles and borrow that component's small tracked "Under" over a heavy
   amount, so the same idea reads the same way in both places.

   width:fit-content + margin-inline:auto rather than justify-content:center — a centred flex row that
   overflows clips its own first item on a phone, and these have to stay reachable from the left edge. */
.sf-pricechips {
  display: flex; gap: .55rem;
  width: fit-content; max-width: 100%; margin: 1.5rem auto 0;
  overflow-x: auto; scrollbar-width: none;
}
.sf-pricechips::-webkit-scrollbar { display: none; }
.sf-pricechip {
  flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: .35rem;
  padding: .48rem .9rem; background: #fff;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  text-decoration: none;
  transition: border-color .18s, background .18s, box-shadow .18s;
}
.sf-pricechip:hover { border-color: var(--maroon); box-shadow: 0 6px 14px rgba(var(--shadow), .12); }
.sf-pricechip-under {
  font-family: var(--font-accent); font-size: .58rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .14em; color: var(--muted);
}
.sf-pricechip-amount { font-weight: 700; font-size: .9rem; color: var(--heading); }
.sf-pricechip:hover .sf-pricechip-amount { color: var(--maroon); }
.sf-pricechip.is-active { background: var(--maroon); border-color: var(--maroon); }
.sf-pricechip.is-active .sf-pricechip-under { color: rgba(255, 255, 255, .78); }
.sf-pricechip.is-active .sf-pricechip-amount,
.sf-pricechip.is-active:hover .sf-pricechip-amount { color: #fff; }
.sf-pricechip.is-active i { font-size: .62rem; color: rgba(255, 255, 255, .8); }
@media (prefers-reduced-motion: reduce) { .sf-pricechip { transition: none; } }

.sf-filter-swatch-row { display: flex; flex-wrap: wrap; gap: .55rem; }
.sf-filter-swatch {
  width: 30px; height: 30px; border-radius: 50%; box-shadow: 0 0 0 1px var(--line) inset;
  display: flex; align-items: center; justify-content: center; color: #fff; font-size: .7rem;
  border: 2px solid transparent; transition: transform .15s, border-color .15s;
}
.sf-filter-swatch:hover { transform: translateY(-1px); }
.sf-filter-swatch.active { border-color: var(--maroon); box-shadow: 0 0 0 1px var(--maroon) inset; }

.sf-filter-size-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.sf-filter-size {
  min-width: 2.6rem; height: 2.3rem; padding: 0 .6rem; border-radius: var(--radius-sm); border: 1.5px solid var(--line);
  display: inline-flex; align-items: center; justify-content: center; font-size: .82rem; font-weight: 600;
  transition: border-color .15s, background .15s, color .15s;
}
.sf-filter-size:hover { border-color: var(--maroon); color: var(--maroon); }
.sf-filter-size.active { border-color: var(--maroon); background: var(--maroon); color: #fff; }

/* Dual-handle price slider — two native <input type="range"> stacked on the same track. Both stay
   independently draggable (each only intercepts pointer events on its own thumb, via -webkit/-moz
   ::-thumb pointer-events; the track itself passes clicks through), with a colored fill bar between them
   drawn by JS setting --sf-price-min-pct/--sf-price-max-pct (see storefront.js "Price range slider"). */
.sf-price-inputs { display: flex; align-items: center; gap: .6rem; margin-bottom: 1.1rem; }
.sf-price-number {
  width: 0; flex: 1; padding: .5rem .6rem; border: 1px solid var(--line); border-radius: var(--radius-sm); font: inherit; font-size: .85rem;
  -moz-appearance: textfield;
}
.sf-price-number::-webkit-outer-spin-button, .sf-price-number::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.sf-price-slider {
  position: relative; height: 20px;
  --sf-price-min-pct: 0%; --sf-price-max-pct: 100%;
}
.sf-price-slider-track { position: absolute; top: 50%; left: 0; right: 0; height: 4px; margin-top: -2px; border-radius: 999px; background: var(--line); }
.sf-price-slider-fill {
  position: absolute; top: 0; height: 100%; border-radius: 999px; background: var(--maroon);
  left: var(--sf-price-min-pct); right: calc(100% - var(--sf-price-max-pct));
}
.sf-price-range {
  position: absolute; top: 0; left: 0; width: 100%; height: 20px; margin: 0; background: none;
  pointer-events: none; -webkit-appearance: none; appearance: none;
}
.sf-price-range::-webkit-slider-runnable-track { background: none; }
.sf-price-range::-moz-range-track { background: none; }
.sf-price-range::-webkit-slider-thumb {
  -webkit-appearance: none; pointer-events: auto; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; border: 2px solid var(--maroon); box-shadow: 0 2px 6px rgba(var(--shadow),.25); cursor: grab; margin-top: 0;
}
.sf-price-range::-moz-range-thumb {
  pointer-events: auto; width: 18px; height: 18px; border-radius: 50%; background: #fff;
  border: 2px solid var(--maroon); box-shadow: 0 2px 6px rgba(var(--shadow),.25); cursor: grab;
}
.sf-price-range:active::-webkit-slider-thumb, .sf-price-range:active::-moz-range-thumb { cursor: grabbing; }
.sf-filter-price-apply { width: 100%; padding: .6rem; font-size: .85rem; margin-top: .9rem; }

@media (max-width: 860px) {
  .sf-filters { position: static; padding: 1rem 1.2rem; }
  .sf-filters-summary { display: flex; }
  .sf-filters-body { margin-top: 1rem; }
  .sf-filters:not([open]) .sf-filters-summary { margin: 0; }
}

/* ---- PDP: layout ----
   Amazon-style compact gallery. The old layout gave the photo half the page width at 3:4, which on a
   desktop meant an ~850px-tall image the customer had to scroll past before reaching the buy box. Now
   the main frame is HEIGHT-capped (min(72vh, 540px)) and derives its width from the 3:4 ratio, with a
   vertical thumbnail rail on its left — so photo, price, options and both buy buttons all land in one
   viewport. The media column is sticky (same 1.2rem offset as the cart/checkout rails): the photo stays
   in view as a reference while the customer reads the description below. The grid is width-capped and
   centred so the info column doesn't stretch into an unreadable ribbon on wide screens. */
.sf-pdp-grid {
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start;
  max-width: 1160px; margin: 0 auto;
}
.sf-pdp-media { display: flex; gap: .7rem; position: sticky; top: 1.2rem; }
.sf-pdp-frame {
  border-radius: var(--radius); overflow: hidden; position: relative;
  aspect-ratio: 3 / 4; height: min(72vh, 540px);
}
.sf-pdp-thumbs {
  display: flex; flex-direction: column; gap: .55rem; flex-shrink: 0;
  max-height: min(72vh, 540px); overflow-y: auto;
  scrollbar-width: none; /* the rail scrolls if a product has many photos, without growing the layout */
}
.sf-pdp-thumbs::-webkit-scrollbar { display: none; }
.pdp-thumb {
  width: 54px; height: 68px; flex-shrink: 0;
  border-radius: var(--radius-sm); overflow: hidden; position: relative;
  border: 2px solid transparent; padding: 0; cursor: pointer; background: none;
  transition: border-color .15s;
}
.pdp-thumb:hover { border-color: var(--accent-dark); }
.pdp-thumb.selected { border-color: var(--maroon); }
/* Small laptops/tablets: step the frame down so the info column keeps a readable width — a 540px-tall
   frame plus the thumb rail would eat more than half of a ~900px viewport. */
@media (max-width: 1024px) and (min-width: 761px) {
  .sf-pdp-frame { height: min(64vh, 420px); }
  .sf-pdp-thumbs { max-height: min(64vh, 420px); }
}
@media (max-width: 760px) {
  .sf-pdp-grid { grid-template-columns: 1fr; }
  /* Stacked: photo first, thumbnails as a swipeable row under it. Sticky off — on a phone the media
     would otherwise sit on top of the info column it now shares a single track with. */
  .sf-pdp-media { position: static; flex-direction: column-reverse; }
  .sf-pdp-frame { height: auto; width: 100%; max-height: 68vh; }
  .sf-pdp-thumbs { flex-direction: row; max-height: none; overflow-x: auto; overflow-y: hidden; }
}

/* ---- PDP: image zoom + lightbox ---- */
.sf-zoom-frame { cursor: zoom-in; }
.sf-zoom-frame .sf-photo { transition: transform .06s linear; }
.sf-zoom-hint {
  position: absolute; bottom: .7rem; right: .7rem; z-index: 2; background: rgba(var(--shadow),.68); color: #fff;
  font-family: var(--font-accent); font-size: .64rem; font-weight: 600; text-transform: uppercase; letter-spacing: .1em; padding: .32rem .6rem; border-radius: var(--radius-sm); display: flex; align-items: center; gap: .35rem;
  pointer-events: none; opacity: 0; transition: opacity .15s;
}
.sf-zoom-frame:hover .sf-zoom-hint { opacity: 1; }
@media (max-width: 760px) { .sf-zoom-hint { display: none; } }

/* Rating chip on the product photo. Top-right is the only free corner of the PDP frame — the
   New Arrival / Best Seller pills own top-left, the zoom hint bottom-right — and it happens to be the
   right one: it balances the badge diagonally and never collides with the hint on hover. Sits above the
   image's zoom transform (which scales the <img>, not this) and stops its own click from reaching the
   frame's lightbox handler, so it goes to the reviews it summarises. */
.sf-photo-rating {
  position: absolute; top: .7rem; right: .7rem; z-index: 3; cursor: pointer;
  display: inline-flex; align-items: center; gap: .32rem;
  padding: .32rem .58rem;
  background: rgba(255, 255, 255, .94);
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 12px rgba(var(--shadow), .18);
  font-size: .78rem; font-weight: 700; color: var(--heading); text-decoration: none;
  transition: background .18s;
}
.sf-photo-rating:hover { background: #fff; }
.sf-photo-rating i { color: var(--star); font-size: .72rem; }
.sf-photo-rating-count { font-weight: 600; font-size: .7rem; color: var(--muted); }

/* ---- Product video (product page only) ----
   `contain` on black, not `cover` like a photo: a garment clip is shot in whatever aspect the phone was
   held at, and cropping a video to the frame's 3:4 cuts the hem off the dress it exists to show. The
   frame stops advertising zoom while a clip is on screen — there is nothing to zoom, and the pointer
   belongs to the video's own controls. */
.sf-photo-video { object-fit: contain; background: #000; }
.sf-zoom-frame:has(video.sf-photo) { cursor: default; }
.sf-zoom-frame:has(video.sf-photo) .sf-zoom-hint { display: none; }

/* Play badge on a video thumbnail — the one thing that distinguishes it from the photos beside it. */
.pdp-thumb-play {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(var(--shadow), .32); color: #fff; font-size: .7rem; pointer-events: none;
}
.pdp-thumb-play i {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; background: rgba(255, 255, 255, .92); color: var(--maroon);
  padding-left: 2px; /* an equilateral play glyph reads off-centre unless it is nudged right */
}

.sf-lightbox {
  position: fixed; inset: 0; z-index: 200; background: rgba(32,12,20,.95);
  display: flex; align-items: center; justify-content: center; padding: 2rem;
  opacity: 0; visibility: hidden; transition: opacity .2s ease;
}
.sf-lightbox.open { opacity: 1; visibility: visible; }
.sf-lightbox img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 6px; }
.sf-lightbox-close {
  position: absolute; top: 1.2rem; right: 1.4rem; width: 42px; height: 42px; border-radius: 50%;
  background: rgba(255,255,255,.12); border: 0; color: #fff; font-size: 1.2rem; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: background .15s;
}
.sf-lightbox-close:hover { background: rgba(255,255,255,.22); }

/* ---- PDP: detail accordions (fabric / wash care / shipping) ----
   Native <details>: no JS to keep alive across htmx swaps, keyboard- and screen-reader-correct for
   free. Collapsed by default so the buy column stays one clean view; the chevron flips on open. */
.sf-pdp-detail-acc { border-top: 1px solid var(--line); margin-bottom: 1.6rem; }
.sf-pdp-acc { border-bottom: 1px solid var(--line); }
.sf-pdp-acc summary {
  display: flex; align-items: center; gap: .7rem; cursor: pointer; list-style: none;
  padding: .95rem .2rem; font-family: var(--font-accent); font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .14em; color: var(--heading);
}
.sf-pdp-acc summary::-webkit-details-marker { display: none; }
.sf-pdp-acc summary > i:first-child { color: var(--maroon); font-size: .9rem; width: 1.2rem; text-align: center; }
.sf-pdp-acc-chev { margin-left: auto; font-size: .7rem; color: var(--muted); transition: transform .2s; }
.sf-pdp-acc[open] .sf-pdp-acc-chev { transform: rotate(180deg); }
.sf-pdp-acc-body { padding: 0 .2rem 1.1rem; font-size: .9rem; color: var(--ink); line-height: 1.7; }
.sf-pdp-acc-body p { margin: 0 0 .6rem; }
.sf-pdp-acc-body ul, .sf-pdp-acc-body ol { margin: 0; padding-left: 1.2rem; }
.sf-pdp-acc-body li { margin-bottom: .35rem; }
.sf-pdp-acc-body li:last-child { margin-bottom: 0; }

/* ---- PDP: size chart ----
   The brand's printed chart, rebuilt as HTML in the same maroon-and-gold look: deep gradient ground,
   gold rules and headings, a gold header band with dark text. Native markup instead of the PNG so it
   stays crisp on any screen, is readable by screen readers, and weighs nothing. */
.sf-sizechart-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: .4rem;
  font-family: var(--font-accent); font-size: .74rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em; color: var(--maroon);
  text-decoration: underline; text-underline-offset: 3px;
}
.sf-sizechart-link:hover { color: var(--heading); }
.sf-sizechart-link i { font-size: .8rem; text-decoration: none; }
.sf-sizechart {
  position: fixed; inset: 0; z-index: 200; background: rgba(32, 12, 20, .62);
  display: flex; align-items: center; justify-content: center; padding: 1.2rem;
  opacity: 0; visibility: hidden; transition: opacity .2s ease;
}
.sf-sizechart.open { opacity: 1; visibility: visible; }
.sf-sizechart-card {
  position: relative; width: min(540px, 100%); max-height: 92vh; overflow-y: auto;
  background: radial-gradient(130% 100% at 50% 0%, #8d1240 0%, #5c0c2a 60%, #47081f 100%);
  border: 1px solid rgba(226, 167, 92, .5); border-radius: var(--radius);
  padding: 1.8rem 1.6rem 1.5rem; text-align: center; color: #f6e7cd;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .45);
}
.sf-sizechart-close {
  position: absolute; top: .8rem; right: .9rem; width: 34px; height: 34px; border-radius: 50%;
  background: rgba(255, 255, 255, .1); border: 0; color: #f6e7cd; font-size: .95rem; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: background .15s;
}
.sf-sizechart-close:hover { background: rgba(255, 255, 255, .22); }
.sf-sizechart-brand {
  font-family: var(--font-display); font-size: 1.5rem; letter-spacing: .3em; color: #e8b96b;
  margin: 0 0 1rem; line-height: 1.3;
}
.sf-sizechart-brand span {
  display: block; font-family: var(--font-accent); font-size: .62rem; font-weight: 600;
  letter-spacing: .28em; text-transform: uppercase; color: #d9a75f; margin-top: .2rem;
}
.sf-sizechart-title {
  font-family: var(--font-display); font-size: clamp(1.3rem, 4vw, 1.7rem); letter-spacing: .08em;
  color: #ecc27a; margin: 0 0 .3rem; text-transform: uppercase;
}
.sf-sizechart-sub { font-size: .85rem; color: #f6e7cd; margin: 0 0 1.2rem; }
.sf-sizechart-scroll { overflow-x: auto; }
.sf-sizechart table { width: 100%; border-collapse: collapse; min-width: 400px; }
.sf-sizechart th, .sf-sizechart td { border: 1px solid rgba(226, 167, 92, .55); padding: .55rem .4rem; }
.sf-sizechart thead th {
  background: #e0a557; color: #2b1408; font-family: var(--font-accent); font-weight: 700;
  font-size: .82rem; letter-spacing: .02em;
}
.sf-sizechart thead th small { display: block; font-weight: 600; font-size: .68rem; }
.sf-sizechart tbody th { color: #ecc27a; font-weight: 700; font-size: .95rem; letter-spacing: .06em; }
.sf-sizechart tbody td { color: #fdf6ea; font-size: .95rem; }
.sf-sizechart-note {
  display: inline-flex; align-items: center; gap: .5rem; margin: 1.1rem 0 .6rem;
  border: 1px solid rgba(226, 167, 92, .6); border-radius: 999px; padding: .45rem 1rem;
  font-size: .82rem; color: #fdf6ea;
}
.sf-sizechart-note i { color: #e8b96b; }
.sf-sizechart-tip { font-size: .84rem; color: #e8b96b; margin: 0; line-height: 1.6; }

/* ---- PDP: color swatches + size selector ---- */
.sf-option-label { font-family: var(--font-accent); font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .16em; color: var(--heading); margin: 0 0 .7rem; }
.sf-swatch-row { display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 1.4rem; }
.sf-swatch {
  width: 38px; height: 38px; border-radius: 50%; border: 2px solid transparent; padding: 2px;
  background-clip: content-box, border-box; cursor: pointer; position: relative;
  box-shadow: 0 0 0 1px var(--line) inset; transition: transform .15s, box-shadow .15s;
}
.sf-swatch:hover { transform: translateY(-2px); }
.sf-swatch.selected { border-color: var(--maroon); box-shadow: 0 0 0 1px var(--maroon) inset; }
.sf-swatch-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; box-shadow: 0 0 0 1px var(--line) inset; flex-shrink: 0; }

/* ---- PDP: reviews ---- */
/* Moved off the page's inline <style> so the PDP owns no colors of its own. */
.sf-star-input { font-size: 1.5rem; color: var(--star); display: flex; gap: .3rem; }
.sf-star-input i { cursor: pointer; }
.sf-stars { color: var(--star); letter-spacing: .06em; }

/* A single oversized Playfair quotation mark behind the heading — customer words are the one thing on
   this page we didn't write, so they get the flourish. Decorative only, hidden from screen readers. */
.sf-quote-head { position: relative; }
.sf-quote-head::before {
  content: "\201C"; position: absolute; left: -.14em; top: -.52em; z-index: 0;
  font-family: var(--font-display); font-size: 7rem; line-height: 1; color: var(--accent-dark);
  opacity: .3; pointer-events: none;
}
.sf-quote-head > * { position: relative; z-index: 1; }
@media (max-width: 560px) { .sf-quote-head::before { font-size: 5rem; left: -.1em; } }

/* ---- Cart ---- */
.sf-cart { max-width: 820px; margin: 0 auto; }
.sf-cart-line { display: flex; align-items: center; gap: 1.2rem; padding: 1.2rem 0; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.sf-cart-thumb { width: 88px; height: 110px; border-radius: var(--radius); overflow: hidden; flex-shrink: 0; position: relative; }
.sf-cart-info { flex: 1; min-width: 160px; }
.sf-cart-name { font-weight: 600; }
.sf-cart-variant { color: var(--muted); font-size: .85rem; margin-top: .3rem; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.sf-cart-qty-total { display: flex; align-items: center; gap: 1rem; }
.sf-cart-qty { width: 56px; padding: .5rem; border: 1px solid var(--line); border-radius: var(--radius-sm); text-align: center; font: inherit; }
.sf-cart-line-total { min-width: 80px; text-align: right; font-weight: 700; }
.sf-cart-summary { display: flex; justify-content: space-between; align-items: center; padding: 1.6rem 0; }

@media (max-width: 560px) {
  .sf-cart-line { position: relative; padding-right: 2.6rem; }
  .sf-cart-qty-total { width: 100%; margin-left: calc(88px + 1.2rem); justify-content: space-between; margin-top: -.3rem; }
  .sf-cart-remove { position: absolute; top: 1.2rem; right: 0; }
}
@media (max-width: 400px) {
  .sf-cart-thumb { width: 68px; height: 86px; }
  .sf-cart-qty-total { margin-left: calc(68px + .9rem); }
}

.sf-size-row { display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 1.2rem; }
.sf-size-btn {
  min-width: 3rem; height: 2.7rem; padding: 0 .9rem; border-radius: var(--radius-sm); border: 1.5px solid var(--line);
  background: #fff; font-family: var(--font-accent); font-weight: 600; font-size: .82rem; letter-spacing: .06em; cursor: pointer; transition: border-color .15s, color .15s, background .15s;
}
.sf-size-btn:hover:not([disabled]) { border-color: var(--maroon); color: var(--maroon); }
.sf-size-btn.selected { border-color: var(--maroon); background: var(--maroon); color: #fff; }
.sf-size-btn[disabled] { opacity: .4; cursor: not-allowed; text-decoration: line-through; }

.sf-stock-msg { font-size: .84rem; font-weight: 600; margin-bottom: 1.2rem; display: flex; align-items: center; gap: .45rem; }
.sf-stock-msg.ok { color: var(--new-arrival); }
.sf-stock-msg.low { color: var(--best-seller); }
.sf-stock-msg.out { color: var(--sale); }
.sf-stock-msg.pick { color: var(--muted); }

/* ---- PDP: buy controls ----
   .sf-pdp-aux is the adjustment row (quantity, favorite, share) — decisions made once, next to the
   colour and size they belong with, in the page flow at every width.
   .sf-pdp-actions holds the two commitments (Add to cart, Buy it now) and is the element that becomes
   the fixed bar on a phone. It contains the real #pdp-add-btn / #pdp-buy-btn, not copies: the PDP's
   variant script resolves those by id and drives their disabled state, data-add-to-cart variant id and
   spinner, so a duplicated pair would have to be kept in sync and would eventually drift. */
.sf-pdp-aux { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.1rem; }
.sf-pdp-actions { display: flex; flex-direction: column; gap: .7rem; margin-bottom: 1.6rem; }

@media (max-width: 860px) {
  /* Pinned above the bottom tab bar, not over it — the two stack, they never overlap. `bottom` is the
     tab bar's own height plus the same safe-area inset the tab bar reserves for the home indicator, so
     the buy bar's foot lands exactly on the tab bar's head on a notched phone as well as a flat one.
     z-index sits one below .sf-bottom-nav's 45 so the tab bar's upward shadow stays on top of the seam,
     and above .sf-whatsapp-fab's 40. */
  .sf-pdp-actions {
    position: fixed; left: 0; right: 0; z-index: 44;
    bottom: calc(var(--sf-bottomnav-h) + env(safe-area-inset-bottom, 0px));
    flex-direction: row; gap: .6rem; margin-bottom: 0;
    height: var(--sf-pdpbar-h);
    padding: .5rem .9rem;
    background: #fff; border-top: 1px solid var(--line);
    box-shadow: 0 -6px 18px rgba(var(--shadow), .12);
  }
  .sf-pdp-actions .sf-btn { flex: 1; height: 100%; padding: 0 .8rem; font-size: .7rem; letter-spacing: .1em; }

  /* Clearance for BOTH fixed bars, replacing the tab-bar-only padding set further down for every other
     page. :has() rather than a body class because the bar is conditional on the product being in stock
     — a sold-out PDP renders no .sf-pdp-actions and correctly keeps the ordinary one-bar padding — and
     because it re-evaluates on its own across htmx-boosted navigation, with no init hook to re-run and
     no stale class to clean up when the customer navigates away. */
  body.storefront:has(.sf-pdp-actions) {
    padding-bottom: calc(var(--sf-bottomnav-h) + var(--sf-pdpbar-h) + env(safe-area-inset-bottom, 0px));
  }
  body.storefront:has(.sf-pdp-actions) .sf-whatsapp-fab {
    bottom: calc(var(--sf-bottomnav-h) + var(--sf-pdpbar-h) + env(safe-area-inset-bottom, 0px) + 1rem);
  }
  /* The buy bar owns its own view-transition group for the same reason the tab bar does: fixed chrome
     that fades through itself on every navigation reads as a flicker. */
  .sf-pdp-actions { view-transition-name: sf-pdp-actions; }
}

/* ---- Pagination ---- */
.sf-pagination { display: flex; justify-content: center; align-items: center; gap: .4rem; margin: 2.5rem 0 1rem; flex-wrap: wrap; }
.sf-page-btn {
  display: inline-flex; align-items: center; justify-content: center; min-width: 2.2rem; height: 2.2rem;
  padding: 0 .6rem; border-radius: var(--radius-sm); border: 1px solid var(--line); color: var(--ink); font-size: .85rem;
  text-decoration: none; transition: background .15s, color .15s, border-color .15s;
}
.sf-page-btn:hover { border-color: var(--maroon); color: var(--maroon); }

/* ---- Sign-in popup ---- */
/* .sf-modal-overlay toggles the [hidden] attribute via JS (storefront.js). An author stylesheet's
   `display` always wins over the UA stylesheet's `[hidden] { display: none }`, regardless of specificity
   (origin beats specificity in the cascade) — so `display` must stay `none` here by default and only
   switch to `flex` via :not([hidden]), or every guest page gets an invisible full-viewport overlay
   sitting over everything, catching every click site-wide. */
.sf-modal-overlay {
  position: fixed; inset: 0; z-index: 200; display: none; align-items: center; justify-content: center;
  padding: 1.2rem; background: rgba(58,22,34,.42); backdrop-filter: blur(2px);
  opacity: 0; transition: opacity .2s ease;
}
.sf-modal-overlay:not([hidden]) { display: flex; }
.sf-modal-overlay.sf-modal-open { opacity: 1; }
.sf-modal {
  position: relative; width: 100%; max-width: 420px; max-height: calc(100vh - 2.4rem); overflow-y: auto;
  transform: translateY(10px) scale(.97); transition: transform .2s ease;
}
.sf-modal-overlay.sf-modal-open .sf-modal { transform: translateY(0) scale(1); }
.sf-modal-close {
  position: absolute; top: .7rem; right: .7rem; z-index: 1; width: 2.1rem; height: 2.1rem; border-radius: 999px;
  background: var(--cream); border: 1px solid var(--line); color: var(--muted); display: flex; align-items: center;
  justify-content: center; cursor: pointer; transition: background .15s, color .15s;
}
.sf-modal-close:hover { background: var(--maroon); color: #fff; border-color: var(--maroon); }
.sf-auth-card-modal { box-shadow: 0 24px 60px -12px rgba(58,22,34,.35); }
@media (prefers-reduced-motion: reduce) {
  .sf-modal-overlay, .sf-modal { transition: none; }
}

/* ---- Account: sign-in + dashboard ---- */
.sf-auth-wrap { max-width: 420px; margin: 0 auto; }
.sf-auth-card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(1.6rem, 4vw, 2.4rem); box-shadow: 0 10px 30px rgba(var(--shadow),.06); }
.sf-auth-icon { width: 3rem; height: 3rem; border-radius: 999px; background: var(--cream); border: 1px solid var(--line); display: flex; align-items: center; justify-content: center; margin: 0 auto 1.2rem; color: var(--maroon); font-size: 1.2rem; }
.sf-auth-title { font-family: var(--font-display); font-weight: 600; font-size: 1.4rem; color: var(--heading); text-align: center; margin: 0 0 .4rem; }
.sf-auth-sub { color: var(--muted); font-size: .88rem; text-align: center; margin: 0 0 1.6rem; line-height: 1.6; }
.sf-auth-field { margin-bottom: 1.1rem; }
.sf-auth-field label { display: block; font-size: .78rem; font-weight: 600; color: var(--ink); margin-bottom: .4rem; }
.sf-auth-field input { width: 100%; padding: .8rem .9rem; border: 1.5px solid var(--line); border-radius: var(--radius-sm); font: inherit; font-size: .95rem; transition: border-color .15s; }
.sf-auth-field input:focus { outline: none; border-color: var(--maroon); }
.sf-phone-input { display: flex; align-items: stretch; border: 1.5px solid var(--line); border-radius: var(--radius-sm); transition: border-color .15s; overflow: hidden; }
.sf-phone-input:focus-within { border-color: var(--maroon); }
.sf-phone-prefix { display: flex; align-items: center; padding: 0 .7rem; background: var(--cream); color: var(--muted); font-weight: 600; font-size: .95rem; border-right: 1.5px solid var(--line); }
.sf-phone-input input { flex: 1; min-width: 0; border: 0; border-radius: 0; padding: .75rem .9rem; font: inherit; font-size: .95rem; }
.sf-phone-input input:focus { outline: none; }
.sf-auth-error { color: var(--sale); font-size: .82rem; font-weight: 600; margin: -.4rem 0 1rem; min-height: 1.1em; }

/* ---- Inline alert — errors that deserve more than a bare red line (checkout, payment) ---- */
.sf-alert {
  display: flex; gap: .75rem; align-items: flex-start;
  padding: .9rem 1rem; margin: .9rem 0;
  background: #fdf3f1; border: 1px solid #eecfc9; border-left: 3px solid var(--sale);
  border-radius: var(--radius-sm);
  animation: sf-alert-in .28s ease;
}
.sf-alert i { color: var(--sale); font-size: .95rem; margin-top: .14rem; flex-shrink: 0; }
.sf-alert-body { flex: 1; min-width: 0; font-size: .84rem; line-height: 1.5; color: #7c2d21; }
.sf-alert-title { display: block; font-weight: 700; font-size: .86rem; color: #5f2016; margin-bottom: .12rem; }
@keyframes sf-alert-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.sf-auth-submit { width: 100%; justify-content: center; padding: .85rem; font-size: .92rem; }
.sf-auth-links { display: flex; justify-content: space-between; align-items: center; margin-top: 1.2rem; font-size: .82rem; }
.sf-auth-links button { background: none; border: 0; padding: 0; color: var(--maroon); font-weight: 600; cursor: pointer; font: inherit; }
.sf-auth-links button:disabled { color: var(--muted); cursor: not-allowed; }
.sf-auth-step { display: none; }
.sf-auth-step.active { display: block; }

.sf-dash-head { display: flex; align-items: center; gap: 1rem; margin-bottom: 2rem; }
.sf-dash-avatar { width: 3.4rem; height: 3.4rem; border-radius: 999px; background: var(--maroon); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 1.3rem; flex-shrink: 0; }
.sf-dash-name { font-family: var(--font-display); font-weight: 600; font-size: 1.25rem; color: var(--heading); margin: 0; }
.sf-dash-phone { color: var(--muted); font-size: .88rem; margin: .15rem 0 0; }
.sf-dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 1rem; }
.sf-dash-tile { display: flex; align-items: center; gap: .9rem; padding: 1.3rem; border: 1px solid var(--line); border-radius: var(--radius); background: #fff; transition: border-color .15s, transform .15s; }
.sf-dash-tile:hover { border-color: var(--maroon); transform: translateY(-2px); }
.sf-dash-tile i { font-size: 1.15rem; color: var(--maroon); width: 1.6rem; text-align: center; }
.sf-dash-tile-label { font-weight: 600; font-size: .9rem; }
.sf-dash-tile-sub { color: var(--muted); font-size: .78rem; margin-top: .1rem; }
.sf-dash-signout { margin-top: 2rem; text-align: center; }

/* ---- Account: address book ---- */
.sf-addr-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1.1rem; }
.sf-addr-card { position: relative; border: 1px solid var(--line); border-radius: var(--radius); padding: 1.3rem 1.4rem; background: #fff; }
.sf-addr-card.is-default { border-color: var(--maroon); }
.sf-addr-badge { display: inline-block; background: var(--maroon); color: #fff; font-family: var(--font-accent); font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; padding: .24rem .55rem; border-radius: var(--radius-sm); margin-bottom: .6rem; }
.sf-addr-name { font-weight: 700; margin: 0 0 .2rem; }
.sf-addr-lines { color: var(--muted); font-size: .87rem; line-height: 1.6; margin: 0 0 1rem; }
.sf-addr-actions { display: flex; gap: 1rem; font-size: .82rem; font-weight: 600; flex-wrap: wrap; }
.sf-addr-actions button { background: none; border: 0; padding: 0; color: var(--maroon); cursor: pointer; font: inherit; font-weight: 600; }
.sf-addr-actions button:hover { text-decoration: underline; }
.sf-addr-actions .muted { color: var(--muted); }
.sf-addr-add-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .6rem;
  border: 1.5px dashed var(--line); border-radius: var(--radius); min-height: 160px; background: none; cursor: pointer;
  color: var(--muted); font-weight: 600; font-size: .9rem; transition: border-color .15s, color .15s;
}
.sf-addr-add-tile:hover { border-color: var(--maroon); color: var(--maroon); }
.sf-addr-add-tile i { font-size: 1.4rem; }

.sf-addr-form-wrap { max-width: 640px; margin: 0 auto; }
.sf-addr-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.2rem; }
.sf-addr-form-grid .sf-auth-field.span-2 { grid-column: 1 / -1; }
.sf-addr-form-grid select { width: 100%; padding: .8rem .9rem; border: 1.5px solid var(--line); border-radius: var(--radius-sm); font: inherit; font-size: .95rem; background: #fff; }
.sf-addr-form-grid select:focus { outline: none; border-color: var(--maroon); }
.sf-addr-checkbox { display: flex; align-items: center; gap: .55rem; font-size: .88rem; margin: .3rem 0 1.3rem; }
.sf-addr-checkbox input { width: 1.05rem; height: 1.05rem; }
.sf-addr-form-actions { display: flex; gap: .8rem; }
.sf-addr-form-actions .sf-btn { flex: 1; justify-content: center; }
@media (max-width: 560px) { .sf-addr-form-grid { grid-template-columns: 1fr; } }
.sf-page-btn.active { background: var(--maroon); border-color: var(--maroon); color: #fff; }

/* ---- Checkout ---- */
.sf-checkout { display: grid; grid-template-columns: 1fr 340px; gap: 1.6rem; align-items: start; }
.sf-checkout-block { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem 1.5rem; margin-bottom: 1.2rem; }
.sf-checkout-block-title { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; color: var(--heading); margin: 0 0 1rem; }
.sf-checkout-radio-list { display: flex; flex-direction: column; gap: .7rem; }
.sf-checkout-radio-card {
  display: flex; gap: .8rem; align-items: flex-start; padding: .9rem 1rem; border: 1.5px solid var(--line);
  border-radius: var(--radius-sm); cursor: pointer; transition: border-color .15s, background .15s;
}
.sf-checkout-radio-card:has(input:checked) { border-color: var(--maroon); background: rgba(135,20,60,.06); }
.sf-checkout-radio-card input { margin-top: .3rem; width: 1.05rem; height: 1.05rem; flex-shrink: 0; }
.sf-pay-body { flex: 1; min-width: 0; }
/* Gateway sub-choice ("Pay via Razorpay / Cashfree") — rendered only when >1 gateway is enabled, and
   shown only while its method tile directly above it is the selected one. */
.sf-pay-gateways { display: none; align-items: center; flex-wrap: wrap; gap: .9rem; padding: .55rem 1rem .55rem 2.7rem; margin-top: -.4rem; border: 1.5px solid var(--line); border-top: 0; border-radius: 0 0 var(--radius-sm) var(--radius-sm); background: var(--warm); font-size: .85rem; }
.sf-checkout-radio-card:has(input:checked) + .sf-pay-gateways { display: flex; }
.sf-pay-gateways label { display: flex; align-items: center; gap: .4rem; cursor: pointer; font-weight: 600; }
.sf-pay-gateways input { width: .95rem; height: .95rem; margin: 0; }
.sf-pay-gateways-label { color: var(--muted); font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; }
.sf-pay-now { text-align: right; flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; gap: .1rem; }
.sf-pay-now-amt { font-weight: 700; font-size: .98rem; }
.sf-pay-now-note { font-size: .68rem; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.sf-checkout-add-address { font-size: .85rem; font-weight: 600; color: var(--maroon); margin-top: .2rem; }
.sf-checkout-add-address:hover { text-decoration: underline; }
.sf-checkout-summary { position: sticky; top: 1.2rem; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem 1.5rem; }
.sf-checkout-summary-line { display: flex; justify-content: space-between; font-size: .87rem; color: var(--muted); padding: .35rem 0; gap: 1rem; }
.sf-checkout-summary-total { display: flex; justify-content: space-between; font-weight: 700; font-size: 1.1rem; border-top: 1px solid var(--line); margin-top: .6rem; padding-top: .8rem; }
@media (max-width: 860px) { .sf-checkout { grid-template-columns: 1fr; } .sf-checkout-summary { position: static; } }

/* ---- Orders ---- */
/* Two-column page: order cards left, the marketing rail (cart resume, coupons) right. */
.sf-orders-layout { display: grid; grid-template-columns: 1fr 280px; gap: 1.6rem; align-items: start; }
.sf-orders-main { min-width: 0; }
.sf-orders-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.sf-orders-tabs { display: flex; gap: .3rem; flex-wrap: wrap; }
.sf-orders-tabs button {
  background: none; border: 1px solid var(--line); border-radius: 999px; padding: .42rem 1rem;
  font-size: .8rem; font-weight: 600; color: var(--muted); cursor: pointer;
}
.sf-orders-tabs button.active { background: var(--maroon); border-color: var(--maroon); color: #fff; }
#sf-orders-search {
  border: 1px solid var(--line); border-radius: 999px; padding: .5rem 1.1rem; font-size: .85rem;
  min-width: 200px; background: #fff;
}
#sf-orders-search:focus { outline: none; border-color: var(--maroon); }
.sf-orders-noresults { color: var(--muted); padding: 1.5rem 0; }
.sf-orders-rail { display: flex; flex-direction: column; gap: 1rem; position: sticky; top: 1.2rem; }
.sf-rail-card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 1.1rem 1.2rem; }
.sf-rail-title { font-weight: 700; font-size: .9rem; margin: 0 0 .7rem; }
.sf-rail-title i { color: var(--maroon); margin-right: .35rem; }
.sf-rail-cart-thumbs { display: flex; gap: .4rem; margin-bottom: .7rem; }
.sf-rail-cart-thumbs img { width: 52px; height: 64px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--line); }
.sf-rail-cart-sum { display: flex; justify-content: space-between; align-items: baseline; font-size: .85rem; color: var(--muted); margin: 0 0 .8rem; }
.sf-rail-cart-sum strong { color: var(--ink); font-size: 1rem; }
.sf-rail-cart-link { display: block; text-align: center; font-size: .8rem; font-weight: 600; color: var(--maroon); margin-top: .55rem; }
.sf-rail-cart-link:hover { text-decoration: underline; }
.sf-rail-coupon { background: #faf5ec; border-color: #e0d3bd; }
.sf-rail-coupon-code { font-weight: 800; letter-spacing: .12em; font-size: 1.05rem; color: #7a5c2e; margin: 0 0 .25rem; }
.sf-rail-coupon-label { font-size: .8rem; color: var(--muted); margin: 0; }
.sf-rail-quiet-text { font-size: .8rem; color: var(--muted); margin: 0; line-height: 1.5; }
.sf-rail-quiet-text a { color: var(--maroon); font-weight: 600; }
/* Mini product rows for the recommendation cards. */
.sf-rail-prod { display: flex; gap: .7rem; align-items: center; padding: .45rem 0; border-top: 1px solid var(--warm); }
.sf-rail-prod:first-of-type { border-top: 0; }
.sf-rail-prod img { width: 48px; height: 60px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--line); flex-shrink: 0; }
.sf-rail-prod-body { min-width: 0; }
.sf-rail-prod-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: .8rem; color: var(--ink); line-height: 1.35; }
.sf-rail-prod:hover .sf-rail-prod-name { color: var(--maroon); }
.sf-rail-prod-price { display: flex; gap: .4rem; align-items: baseline; margin-top: .15rem; }
.sf-rail-prod-price strong { font-size: .85rem; }
.sf-rail-prod-price del { font-size: .72rem; color: var(--muted); }
.sf-rail-prod-price em { font-style: normal; font-size: .68rem; font-weight: 700; color: var(--sale); }
.sf-order-fav { position: static; width: 26px; height: 26px; font-size: .72rem; flex-shrink: 0; }
@media (max-width: 900px) { .sf-orders-layout { grid-template-columns: 1fr; } .sf-orders-rail { position: static; } }

/* Marketplace-style order cards: thumbnails + item links left, actions right. */
.sf-order-cards { display: flex; flex-direction: column; gap: 1rem; }
.sf-order-card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.sf-order-card-head {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: .75rem 1.2rem; background: var(--warm); border-bottom: 1px solid var(--line);
}
.sf-order-card-num { font-weight: 700; color: var(--maroon); font-size: .92rem; }
.sf-order-card-num:hover { text-decoration: underline; }
.sf-order-card-date { color: var(--muted); font-size: .8rem; margin-left: .6rem; }
.sf-order-card-headr { display: flex; align-items: center; gap: .8rem; }
.sf-order-card-total { font-weight: 700; font-size: .95rem; }
.sf-order-card-body { display: flex; gap: 1.1rem; padding: 1rem 1.2rem; align-items: flex-start; }
.sf-order-thumbs { display: flex; gap: .4rem; align-items: center; flex-shrink: 0; }
.sf-order-thumbs img { width: 64px; height: 80px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--warm); }
.sf-order-thumbs-more {
  display: flex; align-items: center; justify-content: center; width: 34px; height: 80px;
  border-radius: var(--radius-sm); border: 1px dashed var(--line); color: var(--muted); font-size: .8rem; font-weight: 600;
}
.sf-order-card-lines { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .35rem; }
.sf-order-card-line { font-size: .88rem; display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.sf-order-card-line a { color: var(--ink); }
.sf-order-card-line a:hover { color: var(--maroon); text-decoration: underline; }
.sf-order-rate { font-size: .76rem; font-weight: 700; color: #b08d57; white-space: nowrap; }
.sf-order-rate:hover { text-decoration: underline; }
.sf-order-card-actions { display: flex; flex-direction: column; gap: .5rem; flex-shrink: 0; min-width: 132px; }
.sf-order-action-btn { padding: .5rem .9rem; font-size: .8rem; text-align: center; white-space: nowrap; }
@media (max-width: 640px) {
  .sf-order-card-body { flex-wrap: wrap; }
  .sf-order-card-actions { flex-direction: row; flex-wrap: wrap; width: 100%; min-width: 0; }
}

.sf-order-list { display: flex; flex-direction: column; gap: .8rem; }
.sf-order-row {
  display: flex; align-items: center; gap: 1rem;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 1.1rem 1.3rem; transition: border-color .15s;
}
.sf-order-row:hover { border-color: var(--maroon); }
.sf-order-row-link { flex: 1; min-width: 0; display: grid; grid-template-columns: 1fr auto auto; gap: 1.2rem; align-items: center; }
.sf-order-row-pay { flex-shrink: 0; padding: .55rem 1.1rem; font-size: .82rem; white-space: nowrap; }
.sf-order-badge { display: inline-block; font-family: var(--font-accent); font-size: .66rem; font-weight: 700; padding: .32rem .7rem; border-radius: var(--radius-sm); text-transform: uppercase; letter-spacing: .14em; }
.sf-order-badge-pending_payment { background: #f9ebda; color: var(--best-seller); }
.sf-order-badge-paid, .sf-order-badge-delivered { background: #e7f2ea; color: var(--new-arrival); }
.sf-order-badge-packed, .sf-order-badge-shipped { background: #f3e2e9; color: var(--maroon); }
.sf-order-badge-cancelled { background: #fbeae8; color: var(--sale); }
.sf-order-confirm-head { text-align: center; margin-bottom: 1.6rem; }
.sf-order-confirm-head i { font-size: 2.4rem; }
.sf-order-confirm-success i { color: var(--new-arrival); }
.sf-order-confirm-verifying i { color: var(--maroon); }
.sf-order-confirm-pending i { color: var(--best-seller); }
@media (max-width: 560px) {
  .sf-order-row { flex-wrap: wrap; }
  .sf-order-row-link { grid-template-columns: 1fr; text-align: left; gap: .5rem; }
}

/* ---- Invoice ---- */
.sf-invoice-wrap { max-width: 820px; margin: 0 auto; }
.sf-invoice-actions { display: flex; justify-content: space-between; margin-bottom: 1.2rem; }
.sf-invoice-paper { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(1.6rem, 4vw, 2.8rem); }
.sf-invoice-head { display: flex; justify-content: space-between; gap: 1.5rem; padding-bottom: 1.4rem; border-bottom: 2px solid var(--ink); margin-bottom: 1.4rem; flex-wrap: wrap; }
.sf-invoice-company { font-family: var(--font-display); font-weight: 600; font-size: 1.4rem; color: var(--heading); margin: 0 0 .4rem; }
.sf-invoice-addr { font-size: .84rem; color: var(--muted); line-height: 1.6; margin: 0 0 .5rem; }
.sf-invoice-meta { text-align: right; }
.sf-invoice-meta h1 { font-family: var(--font-accent); font-weight: 700; font-size: 1rem; color: var(--maroon); margin: 0 0 .4rem; text-transform: uppercase; letter-spacing: .16em; }
.sf-invoice-meta p { margin: .15rem 0; font-size: .87rem; }
.sf-invoice-bill-to { margin-bottom: 1.6rem; }
.sf-invoice-bill-to h4 { font-family: var(--font-accent); font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .16em; color: var(--muted); margin: 0 0 .5rem; }
.sf-invoice-bill-to p { font-size: .88rem; line-height: 1.7; margin: 0; }
.sf-invoice-table { width: 100%; border-collapse: collapse; margin-bottom: 1.4rem; font-size: .87rem; }
.sf-invoice-table th, .sf-invoice-table td { padding: .6rem .5rem; border-bottom: 1px solid var(--line); text-align: left; }
.sf-invoice-table th { font-family: var(--font-accent); font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: var(--muted); }
.sf-invoice-table .num { text-align: right; }
.sf-invoice-totals { max-width: 320px; margin-left: auto; }
.sf-invoice-totals-row { display: flex; justify-content: space-between; padding: .35rem 0; font-size: .88rem; color: var(--muted); }
.sf-invoice-totals-row.total { font-weight: 700; font-size: 1.05rem; color: var(--ink); border-top: 1px solid var(--line); margin-top: .4rem; padding-top: .7rem; }
.sf-invoice-footnote { font-size: .76rem; color: var(--muted); margin-top: 1.8rem; padding-top: 1rem; border-top: 1px dashed var(--line); }
/* Scoped to :has(.sf-invoice-paper) — without it, this hides body.storefront's entire subtree on EVERY
   print, on every page, and only unhides an element (.sf-invoice-paper) that only exists on the invoice
   page, so printing anything else (Ctrl+P on the homepage, a product page, etc.) produced a blank page. */
@media print {
  body.storefront:has(.sf-invoice-paper) * { visibility: hidden; }
  body.storefront:has(.sf-invoice-paper) .sf-invoice-paper,
  body.storefront:has(.sf-invoice-paper) .sf-invoice-paper * { visibility: visible; }
  .sf-invoice-paper { position: absolute; left: 0; top: 0; width: 100%; border: none; padding: 0; }
  body.storefront:has(.sf-invoice-paper) .sf-invoice-actions,
  body.storefront:has(.sf-invoice-paper) .sf-announce,
  body.storefront:has(.sf-invoice-paper) .sf-header,
  body.storefront:has(.sf-invoice-paper) .sf-footer { display: none !important; }
}
@media (max-width: 560px) { .sf-invoice-head { flex-direction: column; } .sf-invoice-meta { text-align: left; } }

/* ---- WhatsApp floating button ---- */
.sf-whatsapp-fab {
  position: fixed; right: 1.3rem; bottom: 1.3rem; z-index: 40;
  width: 3.4rem; height: 3.4rem; border-radius: 999px; background: #25d366; color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 1.6rem;
  box-shadow: 0 8px 20px rgba(37,211,102,.4); transition: transform .15s;
}
.sf-whatsapp-fab:hover { transform: scale(1.08); color: #fff; }
@media print { .sf-whatsapp-fab { display: none !important; } }

/* ---- Policy pages / FAQ ---- */
.sf-policy-wrap { max-width: 760px; margin: 0 auto; }
.sf-policy-body { font-size: .94rem; line-height: 1.8; color: var(--ink); }
.sf-policy-body h3 { font-family: var(--font-display); font-weight: 600; color: var(--heading); font-size: 1.2rem; margin: 1.6rem 0 .6rem; }
.sf-policy-body h3:first-child { margin-top: 0; }
.sf-policy-body ul { padding-left: 1.3rem; }
.sf-policy-body a { color: var(--maroon); text-decoration: underline; }
.sf-faq-list { display: flex; flex-direction: column; gap: .7rem; }
.sf-faq-item { border: 1px solid var(--line); border-radius: var(--radius); padding: 1.1rem 1.3rem; background: #fff; }
.sf-faq-item summary { cursor: pointer; font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; color: var(--heading); list-style: none; display: flex; justify-content: space-between; align-items: center; }
.sf-faq-item summary::-webkit-details-marker { display: none; }
.sf-faq-item summary::after { content: '+'; font-size: 1.3rem; color: var(--maroon); font-weight: 400; margin-left: 1rem; transition: transform .2s; }
.sf-faq-item[open] summary::after { transform: rotate(45deg); }
.sf-faq-item p { margin: .8rem 0 0; color: var(--muted); font-size: .9rem; line-height: 1.7; }

/* ---- Bottom tab bar — mobile-only primary navigation, always in thumb reach, the single biggest
   thing that makes this feel like a native app rather than a scaled-down desktop site. Hidden above the
   tablet breakpoint, where the header nav already covers the same destinations. .active is set by JS
   (storefront.js) from the current path, not server-rendered — see the note on the markup in layout.html. */
.sf-bottom-nav {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
  background: #fff; border-top: 1px solid var(--line); box-shadow: 0 -4px 16px rgba(var(--shadow),.08);
  padding: .35rem .25rem calc(.35rem + env(safe-area-inset-bottom, 0px));
}
@media (max-width: 860px) {
  .sf-bottom-nav {
    display: flex; align-items: stretch; justify-content: space-around;
    /* Fixed rather than derived from its contents: --sf-bottomnav-h is what every other rule offsets
       against (page padding, the WhatsApp button, the PDP buy bar), so the bar has to actually be that
       tall rather than approximately so. */
    height: calc(var(--sf-bottomnav-h) + env(safe-area-inset-bottom, 0px));
  }
  /* Room for the fixed bar so it never covers the last bit of page content. The PDP, which stacks a
     second bar above this one, overrides this — see body.storefront:has(.sf-pdp-actions). */
  body.storefront { padding-bottom: calc(var(--sf-bottomnav-h) + env(safe-area-inset-bottom, 0px)); }
  .sf-whatsapp-fab { bottom: calc(var(--sf-bottomnav-h) + env(safe-area-inset-bottom, 0px) + 1rem); }
}
.sf-bottom-nav-item {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .2rem;
  padding: .35rem .2rem; border-radius: var(--radius-sm); color: var(--muted); font-size: .66rem; font-weight: 600;
  text-decoration: none; transition: color .15s, background .15s;
}
.sf-bottom-nav-item i { font-size: 1.15rem; }
.sf-bottom-nav-item.active { color: var(--maroon); background: var(--warm); }
.sf-bottom-nav-icon-wrap { position: relative; display: inline-flex; }
.sf-bottom-nav-badge { position: absolute; top: -5px; right: -9px; }

/* ---- Skeleton / shimmer loading states ----
   .sk (existing) is the shimmer surface itself. The classes below are ready-made shapes so htmx-loading
   placeholders (hx-indicator targets shown while a fragment request is in flight) don't need bespoke CSS
   per page — a skeleton card/row looks like the real product grid it's about to become. */
.sk-text { height: .9em; margin: .3em 0; }
.sk-text.w-40 { width: 40%; }
.sk-text.w-80 { width: 80%; }
.sk-card { border-radius: var(--radius); overflow: hidden; }
.sk-card-art { aspect-ratio: 3/4; }
.sk-card-body { padding: .7rem .2rem; }
.sk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1.4rem; }
@media (max-width: 640px) { .sk-grid { grid-template-columns: repeat(2, 1fr); gap: .9rem; } }
/* Shown/hidden by htmx itself via hx-indicator — htmx toggles .htmx-request on the indicator element for
   the duration of the request, no manual JS needed.

   ...but NOT immediately. Every loading state below is held back by SF_LOADING_DELAY (160ms). Most
   filter/pagination/cart responses land well inside that window, and a skeleton that flashes up and
   vanishes in 80ms reads as a stutter — it makes a fast interaction *feel slower* than showing nothing
   at all. Past 160ms the request is genuinely slow enough that silence would read as a dead click, so
   the indicator appears. This is the same "don't show a spinner for a fast response" rule React apps
   get from a Suspense/useTransition delay; here it's pure CSS timing, no JS bookkeeping.

   The delay is expressed as a 0s-duration animation with a delay and `fill-mode: both`: during the
   delay the browser holds the `from` keyframe, then jumps to `to`. Nothing interpolates, so animating
   the discrete `display` property is safe — and on a browser too old to animate `display` the whole
   keyframe is simply ignored and the indicator appears instantly, i.e. the previous behaviour. */
.sf-hx-indicator { display: none; }
.htmx-request.sf-hx-indicator, .htmx-request .sf-hx-indicator {
  display: block;
  animation: sf-delayed-show 0s linear .16s both;
}
@keyframes sf-delayed-show { from { display: none; } to { display: block; } }
/* The other half of the skeleton swap, which the fragment's own comment has always described but which
   was never actually written: once the skeleton is showing, the stale grid underneath has to go, or the
   page doubles in height and collapses back the moment the response lands. Same delay, so the two
   switch over in the same frame. */
@keyframes sf-delayed-hide { from { display: block; } to { display: none; } }
#results-skeleton.htmx-request ~ #results { animation: sf-delayed-hide 0s linear .16s both; }
/* For small in-place updates (cart quantity/remove) that don't warrant a full skeleton reveal — dim the
   existing content in place instead of replacing it with a placeholder. The delay lives only on the
   .htmx-request rule, so dimming waits 160ms but *un*-dimming (the class coming off when the response
   lands) is instant — a delayed recovery would leave the fresh content greyed out after it had already
   arrived. */
#cart-content, .sf-home-cat-results { transition: opacity .15s; }
#cart-content.htmx-request { opacity: .45; pointer-events: none; transition-delay: .16s; }
/* Homepage per-category browse sections (see StorefrontController.homeCategorySection) — same
   dim-in-place pattern while a pagination click's htmx request is in flight, no per-section skeleton. */
.sf-home-cat-results.htmx-request { opacity: .45; pointer-events: none; transition-delay: .16s; }

/* ---- Navigation progress bar ----
   htmx already swaps without a full reload, but between the click and the swap there is no feedback at
   all: on a slow connection the page just sits there looking like the tap missed. This is the bar every
   SPA router ships for exactly that reason — a 2px hairline that starts the instant the request leaves
   and eases toward (never reaching) the right edge, so "still working" is always legible without
   claiming to know the actual progress. Fixed to the very top of the viewport, above the header, wine
   into rose so it reads as brand chrome rather than a browser artifact.

   --sf-progress (0–1) is written by storefront.js; the element scales rather than animating `width`, so
   the whole thing stays on the compositor and can't jank the page it's reporting on. */
.sf-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 120; pointer-events: none;
  background: linear-gradient(90deg, var(--maroon), var(--accent));
  transform: scaleX(var(--sf-progress, 0)); transform-origin: 0 50%;
  opacity: 0; visibility: hidden;
}
.sf-progress.active { opacity: 1; visibility: visible; transition: transform .24s cubic-bezier(.4,0,.2,1); }
/* Finished: run to full width, then fade out — the fade is delayed past the fill so the bar is visibly
   *completed* rather than just disappearing mid-track. */
.sf-progress.done { opacity: 0; transition: transform .16s ease-out, opacity .3s ease .14s; }
@media (prefers-reduced-motion: reduce) { .sf-progress { transition: none !important; } }

/* ---- View transitions ----
   Enabled globally from storefront.js (htmx.config.globalViewTransitions), so every htmx swap — a
   boosted page navigation, a filtered product grid, a cart line removal — cross-fades instead of
   popping. Chrome/Edge only today; every other browser ignores the whole mechanism and swaps exactly as
   it does now, which is why this is safe to turn on unconditionally.

   The default UA cross-fade is 250ms. That is too slow here: the point of the transition is to soften
   the seam, not to make the customer wait for it, and anything past ~200ms starts to read as latency
   the site is adding on top of the network. 170ms is long enough to perceive as a fade and short enough
   to still feel instant. */
::view-transition-old(root), ::view-transition-new(root) {
  animation-duration: .17s; animation-timing-function: cubic-bezier(.4, 0, .2, 1);
}
/* The fixed mobile chrome opts out of the page cross-fade entirely by owning its own transition group.
   Without this the bottom tab bar and the WhatsApp button fade through themselves on every navigation —
   a flicker on precisely the two elements that are supposed to feel like they're *outside* the page.
   Only ever applied to position:fixed elements: a named element animates from its old box to its new
   one, so naming a statically-positioned header would make it visibly slide whenever a navigation also
   changed the scroll position. */
.sf-bottom-nav { view-transition-name: sf-bottom-nav; }
.sf-whatsapp-fab { view-transition-name: sf-whatsapp-fab; }
/* Set on the product photo of whichever card was clicked (see storefront.js) and permanently on the
   product page's own hero image, so the two are the same named element across the swap and Chrome
   morphs the thumbnail into the full-size photo instead of cross-fading them. This is the shared-element
   transition a React app would reach for framer-motion's `layoutId` to get. */
#pdp-main img.sf-photo { view-transition-name: sf-pdp-hero; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* ---- "Added to cart" slide-in panel ---- */
/* Confirmation where the eye already is (right side, near the cart icon), not a corner badge blink.
   Non-blocking by design: the scrim only dims, it never traps. */
.sf-cadd-scrim {
  position: fixed; inset: 0; background: rgba(33, 20, 26, .28); opacity: 0; z-index: 1200;
  transition: opacity .25s ease;
}
.sf-cadd-scrim.open { opacity: 1; }
.sf-cadd {
  position: fixed; top: 0; right: 0; z-index: 1201;
  width: min(370px, 92vw); height: 100dvh; overflow-y: auto;
  background: #fff; border-left: 1px solid var(--line); box-shadow: -18px 0 48px rgba(var(--shadow), .16);
  padding: 1.2rem 1.3rem 2rem;
  transform: translateX(100%); transition: transform .26s cubic-bezier(.32, .72, 0, 1);
}
.sf-cadd.open { transform: none; }
.sf-cadd-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; }
.sf-cadd-ok { margin: 0; font-weight: 700; font-size: 1rem; color: var(--new-arrival); }
.sf-cadd-ok i { margin-right: .4rem; }
.sf-cadd-close {
  background: none; border: 0; font-size: 1.6rem; line-height: 1; color: var(--muted); cursor: pointer; padding: 0 .2rem;
}
.sf-cadd-close:hover { color: var(--ink); }
.sf-cadd-item { display: flex; gap: .8rem; padding-bottom: 1rem; border-bottom: 1px solid var(--line); }
.sf-cadd-item img { width: 72px; height: 90px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--line); }
.sf-cadd-item-name { margin: 0; font-weight: 600; font-size: .9rem; line-height: 1.35; }
.sf-cadd-item-meta { margin: .2rem 0 0; font-size: .78rem; color: var(--muted); }
.sf-cadd-item-price { margin: .3rem 0 0; font-weight: 700; }
.sf-cadd-sub { display: flex; justify-content: space-between; align-items: baseline; margin: 1rem 0; font-size: .88rem; color: var(--muted); }
.sf-cadd-sub strong { font-size: 1.05rem; color: var(--ink); }
.sf-cadd-btn { display: block; width: 100%; text-align: center; margin-bottom: .55rem; }
.sf-cadd-keep {
  display: block; width: 100%; background: none; border: 0; padding: .5rem 0;
  font-size: .82rem; font-weight: 600; color: var(--muted); cursor: pointer;
}
.sf-cadd-keep:hover { color: var(--maroon); text-decoration: underline; }
.sf-cadd-also { margin-top: 1.4rem; border-top: 1px solid var(--line); padding-top: 1.1rem; }
.sf-cadd-also-title { margin: 0 0 .8rem; font-weight: 700; font-size: .9rem; }
.sf-cadd-also-row { display: flex; gap: .7rem; align-items: center; margin-bottom: .8rem; }
.sf-cadd-also-row img { width: 48px; height: 60px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--line); }
.sf-cadd-also-name {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: .82rem; color: var(--ink); line-height: 1.35;
}
.sf-cadd-also-name:hover { color: var(--maroon); }
.sf-cadd-also-price { margin: .15rem 0 0; display: flex; gap: .4rem; align-items: baseline; }
.sf-cadd-also-price strong { font-size: .85rem; }
.sf-cadd-also-price del { font-size: .72rem; color: var(--muted); }
@media (prefers-reduced-motion: reduce) {
  .sf-cadd, .sf-cadd-scrim { transition: none; }
}

/* ---- Shipment tracking (shared by the order page and the public /track/{token} page) ---- */
/* Two layers, one rendering each: a compact horizontal milestone stepper for "how far along is it?",
   and the vertical station route below for "where exactly is it?". */
.sf-trk-status{margin:0 0 .9rem;font-weight:600}
.sf-trk-steps{display:flex;max-width:560px;margin:1.1rem 0 .3rem}
.sf-trk-step{flex:1;text-align:center;position:relative;padding:0 .2rem;min-width:0}
.sf-trk-step::before{content:"";position:absolute;top:9px;left:-50%;width:100%;height:2px;background:#e6ded1}
.sf-trk-step:first-child::before{display:none}
.sf-trk-step.done::before{background:#7a5c2e}
.sf-trk-step-dot{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;border-radius:50%;background:#fff;border:2px solid #ded4c6;color:transparent;font-size:9px}
.sf-trk-step.done .sf-trk-step-dot{background:#7a5c2e;border-color:#7a5c2e;color:#fff}
.sf-trk-step-label{display:block;font-size:.72rem;color:#9a9086;margin-top:.35rem;line-height:1.25}
.sf-trk-step.done .sf-trk-step-label{color:#3a332c;font-weight:600}
.sf-trk-step-at{display:block;font-size:.66rem;color:#b3a99d;margin-top:.1rem}
@media(max-width:560px){
  .sf-trk-step-at{display:none}
  .sf-trk-step-label{font-size:.6rem}
}
/* The journey as a route: one stop per location, origin at the top, delivery (or current position) at
   the bottom. Every marker is FILLED with a white icon — mixing outlined and filled reads as a
   mismatch. */
.sf-route{margin-top:1.5rem;max-width:520px}
.sf-route-title{font-weight:600;margin:0 0 .8rem}
.sf-route-stop{position:relative;display:flex;gap:.7rem;padding-bottom:1.1rem}
.sf-route-stop::before{content:"";position:absolute;left:12px;top:28px;bottom:-2px;width:2px;background:#e6ded1}
.sf-route-stop:last-child::before{display:none}
.sf-route-dot{width:26px;height:26px;border-radius:50%;background:#f0e7db;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;position:relative;z-index:1}
.sf-route-dot::after{content:"";width:7px;height:7px;border-radius:50%;background:#c4b6a2}
.sf-route-dot i{font-size:11px;line-height:1;color:#fff !important}
.sf-route-stop.start .sf-route-dot{background:#7a5c2e}
.sf-route-stop.end .sf-route-dot{background:var(--maroon)}
.sf-route-stop.end.delivered .sf-route-dot{background:#3e7d54}
.sf-route-stop.start .sf-route-dot::after,.sf-route-stop.end .sf-route-dot::after{display:none}
.sf-route-loc{font-weight:600;color:#3a332c;font-size:.88rem}
.sf-route-tag{display:inline-block;font-size:.62rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  border-radius:999px;padding:.14rem .5rem;margin-left:.45rem;vertical-align:1px}
.sf-route-tag.origin{background:#f4ead9;color:#7a5c2e}
.sf-route-tag.delivered{background:#e7f2ea;color:#3e7d54}
.sf-route-tag.current{background:#f3e2e9;color:var(--maroon)}
.sf-route-ev{font-size:.78rem;color:#8c8177;margin-top:.15rem}
.sf-awb-copy{background:none;border:1px solid var(--line);border-radius:999px;padding:.1rem .6rem;
  font-size:.7rem;font-weight:700;color:#7a5c2e;cursor:pointer;margin-left:.35rem;vertical-align:1px}
.sf-awb-copy:hover{background:#faf5ec}

/* ---- Product share fallback menu (desktop, no navigator.share) ---- */
#sf-share-menu {
  position: fixed; z-index: 1300; background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: 0 14px 34px rgba(var(--shadow), .16);
  padding: .4rem; display: flex; flex-direction: column; min-width: 170px;
  animation: sf-alert-in .18s ease;
}
#sf-share-menu a, #sf-share-menu button {
  display: flex; align-items: center; gap: .6rem; padding: .55rem .8rem; border: 0; background: none;
  font-size: .86rem; font-weight: 600; color: var(--ink); cursor: pointer; text-align: left;
  border-radius: var(--radius-sm); font-family: inherit;
}
#sf-share-menu a:hover, #sf-share-menu button:hover { background: var(--warm); color: var(--maroon); }
#sf-share-menu i { width: 18px; text-align: center; color: var(--maroon); }


/* ---- UPI pay page ----
   One centred card. The amount is the headline, the QR the hero on desktop; on a phone the QR is
   useless (you can't scan your own screen) so the app buttons take over and "Open UPI app" leads. */
.sf-upi-section { display: flex; justify-content: center; }
.sf-upi-card {
  width: min(460px, 100%); background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.8rem 1.6rem 1.4rem; text-align: center; box-shadow: 0 10px 30px rgba(var(--shadow), .08);
}
.sf-upi-badge {
  display: inline-flex; align-items: center; gap: .4rem; padding: .3rem .7rem; border-radius: 999px;
  background: #fcf3dc; color: #8a5a00; font-family: var(--font-accent); font-size: .66rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
}
.sf-upi-amount { font-family: var(--font-display); font-size: 2.4rem; color: var(--heading); margin: .8rem 0 .1rem; line-height: 1; }
.sf-upi-order { color: var(--muted); font-size: .86rem; margin: 0 0 1.2rem; }
.sf-upi-order strong { color: var(--ink); }
.sf-upi-qr-wrap {
  display: inline-flex; padding: .7rem; background: #fff; border: 1.5px solid var(--line); border-radius: var(--radius-sm);
}
.sf-upi-qr-wrap canvas { display: block; width: 240px; height: 240px; }
.sf-upi-hint { font-size: .8rem; color: var(--muted); margin: .6rem 0 1rem; }
.sf-upi-apps { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; margin-bottom: 1.1rem; }
.sf-upi-app {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem; min-height: 46px;
  padding: .55rem .8rem; border: 1.5px solid var(--line); border-radius: var(--radius-sm); background: #fff;
  color: var(--ink); font: inherit; font-size: .86rem; font-weight: 600; text-decoration: none; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.sf-upi-app:hover { border-color: var(--maroon); background: var(--warm); }
.sf-upi-app i { color: var(--maroon); }
.sf-upi-paytm-logo { font-weight: 800; font-size: 1.05rem; letter-spacing: -.02em; }
.sf-upi-paytm-logo b { color: #002970; } .sf-upi-paytm-logo i { color: #00b9f1; font-style: normal; }
.sf-upi-mobile-only { display: none; }
.sf-upi-vpa {
  display: flex; flex-direction: column; gap: .35rem; align-items: center; padding: .9rem; margin-bottom: 1rem;
  background: var(--warm); border-radius: var(--radius-sm); font-size: .82rem; color: var(--muted);
}
.sf-upi-vpa-label { font-family: var(--font-accent); font-size: .66rem; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; }
.sf-upi-vpa-row { display: inline-flex; align-items: center; gap: .5rem; }
.sf-upi-vpa code { font-size: 1rem; font-weight: 700; color: var(--heading); background: #fff; padding: .25rem .6rem; border-radius: 6px; border: 1px solid var(--line); }
.sf-upi-copy { background: none; border: 1px solid var(--line); border-radius: 6px; padding: .3rem .6rem; font: inherit; font-size: .76rem; font-weight: 600; color: var(--maroon); cursor: pointer; }
.sf-upi-copy:hover { background: #fff; }
.sf-upi-vpa-note { line-height: 1.5; }
.sf-upi-vpa-note strong { color: var(--ink); }
.sf-upi-paid { width: 100%; }
.sf-upi-status { font-size: .82rem; color: var(--muted); margin: .8rem 0 .5rem; }
.sf-upi-status.is-paid { color: var(--new-arrival); font-weight: 600; }
.sf-upi-later { font-size: .8rem; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 760px) {
  .sf-upi-mobile-only { display: inline-flex; }
  /* The phone can't scan itself: shrink the QR to a "save/share me" thumbnail and let the buttons lead. */
  .sf-upi-qr-wrap canvas { width: 168px; height: 168px; }
  .sf-upi-card { padding: 1.4rem 1.1rem 1.2rem; }
}

/* ---- Account wallet ---- */
.sf-dash-tile-wallet i { color: var(--maroon); }
.sf-wallet-hero {
  background: linear-gradient(135deg, var(--maroon) 0%, #6d0f30 100%); color: #fff;
  border-radius: var(--radius); padding: 1.6rem 1.7rem; box-shadow: 0 12px 30px rgba(var(--shadow), .18);
}
.sf-wallet-hero-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: .5rem; }
.sf-wallet-hero-label { font-family: var(--font-accent); font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; display: inline-flex; align-items: center; gap: .5rem; opacity: .92; }
.sf-wallet-hero-credit { font-size: .66rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; background: rgba(255,255,255,.16); padding: .28rem .6rem; border-radius: 999px; }
.sf-wallet-hero-amt { font-family: var(--font-display); font-size: 2.7rem; line-height: 1; margin: .4rem 0 .5rem; }
.sf-wallet-hero-note { font-size: .84rem; opacity: .85; margin: 0; line-height: 1.55; }

.sf-wallet-list { display: flex; flex-direction: column; }
.sf-wallet-row { display: flex; align-items: center; gap: 1rem; padding: 1rem .2rem; border-bottom: 1px solid var(--line); }
.sf-wallet-row-icon { flex-shrink: 0; width: 42px; height: 42px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: .95rem; }
.sf-wallet-row-icon.is-credit { background: #e7f2ea; color: #1e7145; }
.sf-wallet-row-icon.is-debit { background: #fbe9ec; color: #b0234a; }
.sf-wallet-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
.sf-wallet-row-title { font-weight: 600; color: var(--heading); font-size: .95rem; }
.sf-wallet-row-sub { font-size: .82rem; color: var(--ink); }
.sf-wallet-row-date { font-size: .74rem; color: var(--muted); }
.sf-wallet-row-amt { text-align: right; flex-shrink: 0; display: flex; flex-direction: column; gap: .15rem; }
.sf-wallet-row-amt > span:first-child { font-weight: 700; font-size: 1rem; }
.sf-wallet-row-amt .is-credit { color: #1e7145; }
.sf-wallet-row-amt .is-debit { color: #b0234a; }
.sf-wallet-row-bal { font-size: .72rem; color: var(--muted); }

/* ---- Order page: returns ---- */
.sf-return-existing { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: .8rem 1rem; margin-bottom: .7rem; }
.sf-return-existing-top { display: flex; justify-content: space-between; align-items: center; }
.sf-return-badge { font-family: var(--font-accent); font-size: .64rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; padding: .28rem .6rem; border-radius: 999px; }
.sf-return-badge.is-requested { background: #fcf3dc; color: #8a5a00; }
.sf-return-badge.is-approved { background: #e3effb; color: #1c4e80; }
.sf-return-badge.is-refunded { background: #e7f2ea; color: #1e7145; }
.sf-return-badge.is-rejected { background: #fbe5e4; color: #b0234a; }
.sf-return-amt { font-weight: 700; color: var(--heading); }
.sf-return-lines { font-size: .86rem; color: var(--ink); margin: .4rem 0 .2rem; }
.sf-return-meta { font-size: .76rem; color: var(--muted); margin: 0; }

.sf-return-items { display: flex; flex-direction: column; gap: .6rem; }
.sf-return-item { border: 1.5px solid var(--line); border-radius: var(--radius-sm); padding: .75rem .9rem; transition: border-color .15s, background .15s; }
.sf-return-item.is-picked { border-color: var(--maroon); background: var(--warm); }
.sf-return-item-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
.sf-return-check { display: flex; align-items: flex-start; gap: .6rem; cursor: pointer; margin: 0; }
.sf-return-check input { margin-top: .25rem; width: 1.05rem; height: 1.05rem; }
.sf-return-item-name { display: block; font-weight: 600; color: var(--heading); font-size: .92rem; }
.sf-return-item-meta { display: block; font-size: .78rem; color: var(--muted); }
.sf-return-qty { display: flex; align-items: center; gap: .4rem; flex-shrink: 0; }
.sf-return-qty-label { font-size: .72rem; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.sf-return-qty-input { width: 52px; border: 1px solid var(--line); border-radius: 6px; padding: .3rem .4rem; font: inherit; font-size: .85rem; text-align: center; }
.sf-return-qty-input:disabled { background: #f4f4f6; color: var(--muted); }
.sf-return-reason { width: 100%; margin-top: .6rem; border: 1px solid var(--line); border-radius: 6px; padding: .45rem .7rem; font: inherit; font-size: .84rem; }
.sf-return-reason:disabled { background: #f4f4f6; }
.sf-return-radio { display: flex; align-items: center; gap: .55rem; padding: .5rem 0; cursor: pointer; font-size: .88rem; color: var(--ink); }
.sf-return-radio input { width: 1.05rem; height: 1.05rem; }
.sf-return-summary { font-weight: 600; color: var(--maroon); font-size: .9rem; margin-top: .6rem; }

/* ---- Checkout: wallet toggle ---- */
.sf-checkout-wallet { display: flex; justify-content: space-between; align-items: center; padding: .6rem 0; border-top: 1px dashed var(--line); }
.sf-checkout-wallet-toggle { display: flex; align-items: center; gap: .5rem; cursor: pointer; font-size: .9rem; color: var(--ink); margin: 0; }
.sf-checkout-wallet-toggle input { width: 1.05rem; height: 1.05rem; }
.sf-checkout-wallet-toggle i { color: var(--maroon); }
.sf-checkout-wallet #sf-wallet-applied { font-weight: 700; color: #1e7145; }

/* ---- Wallet: add money (top-up) ---- */
.sf-wallet-topup { margin-top: 1.2rem; border: 1px solid var(--line); border-radius: var(--radius); padding: 1.2rem 1.3rem; background: #fff; }
.sf-wallet-topup-title { font-family: var(--font-accent); font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: var(--heading); margin: 0 0 .8rem; display: flex; align-items: center; gap: .45rem; }
.sf-wallet-topup-title i { color: var(--maroon); }
.sf-topup-amounts { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: .9rem; }
.sf-topup-chip { border: 1.5px solid var(--line); background: #fff; border-radius: 999px; padding: .5rem 1rem; font: inherit; font-weight: 600; font-size: .9rem; cursor: pointer; transition: border-color .15s, background .15s, color .15s; }
.sf-topup-chip:hover { border-color: var(--maroon); }
.sf-topup-chip.is-active { background: var(--maroon); color: #fff; border-color: var(--maroon); }
.sf-topup-input { border: 1.5px solid var(--line); border-radius: 999px; padding: .5rem 1rem; font: inherit; font-size: .9rem; width: 140px; }
.sf-topup-methods { display: flex; flex-wrap: wrap; gap: 1rem; margin-bottom: .8rem; }
.sf-topup-method { display: flex; align-items: center; gap: .45rem; cursor: pointer; font-size: .9rem; font-weight: 600; color: var(--ink); }
.sf-topup-method input { width: 1rem; height: 1rem; }

/* ---- Account: WhatsApp opt-in ---- */
.sf-wa-optin { border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem 1.2rem; margin: 1.4rem 0; }
.sf-wa-optin-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; cursor: pointer; margin: 0; }
.sf-wa-optin-title { display: block; font-weight: 600; color: var(--heading); font-size: .95rem; }
.sf-wa-optin-title i { color: #25d366; }
.sf-wa-optin-sub { display: block; font-size: .8rem; color: var(--muted); margin-top: .15rem; line-height: 1.5; }
.sf-switch { position: relative; width: 46px; height: 26px; flex-shrink: 0; }
.sf-switch input { opacity: 0; width: 0; height: 0; }
.sf-switch-slider { position: absolute; inset: 0; background: #d8d5dd; border-radius: 999px; transition: background .18s; }
.sf-switch-slider::before { content: ""; position: absolute; height: 20px; width: 20px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform .18s; box-shadow: 0 1px 3px rgba(0,0,0,.2); }
.sf-switch input:checked + .sf-switch-slider { background: #25d366; }
.sf-switch input:checked + .sf-switch-slider::before { transform: translateX(20px); }

/* ---- Delivery estimate ("Arrives by …") ---------------------------------------------------------
   A calm green delivery cue — the one place green reads as "on its way / good news" without fighting
   the wine palette. Shown on the order page, public tracking page (.sf-eta) and product page (.sf-pdp-eta). */
.sf-eta {
  display: flex; align-items: center; gap: .85rem;
  background: #f0f8f2; border: 1px solid #cfe8d6; border-radius: 12px;
  padding: .85rem 1.05rem; margin: 0 0 1.2rem;
}
.sf-eta-ico { font-size: 1.35rem; color: #1a8a4f; flex-shrink: 0; }
.sf-eta-body { min-width: 0; }
.sf-eta-lead { color: var(--ink); font-size: .98rem; line-height: 1.4; }
.sf-eta-lead strong { color: #166b3d; }
.sf-eta-sub { color: var(--muted); font-size: .84rem; margin-top: .1rem; }

.sf-pdp-eta {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .1rem .5rem;
  color: var(--ink); font-size: .98rem; margin: 0 0 1.5rem;
}
.sf-pdp-eta i { color: #1a8a4f; margin-right: .35rem; }
.sf-pdp-eta strong { color: #166b3d; }
.sf-pdp-eta-sub { color: var(--muted); font-size: .86rem; }

.sf-cart-eta {
  display: flex; align-items: flex-start; gap: .5rem;
  background: #f0f8f2; border: 1px solid #cfe8d6; border-radius: 10px;
  padding: .6rem .8rem; margin: 0 0 .9rem; font-size: .86rem; color: var(--ink); line-height: 1.4;
}
.sf-cart-eta i { color: #1a8a4f; margin-top: .15rem; }
.sf-cart-eta strong { color: #166b3d; }
