/* =================================================================
   V4 ELISHA BAY — Dark Editorial Design System
   Warm parchment light mode · Ink dark mode · Split-word hero
   ================================================================= */

/* =================================================================
   0. KEYFRAMES
   ================================================================= */
@keyframes pageIn      { from{opacity:0;transform:translateY(18px);}  to{opacity:1;transform:none;} }
@keyframes pageOut     { from{opacity:1;transform:translateY(0);}     to{opacity:0;transform:translateY(-12px);} }
@keyframes marqueeRun  { from{transform:translateX(0);}               to{transform:translateX(-50%);} }
@keyframes jarGlowPulse{
  0%,100%{opacity:.7;transform:translate(-50%,-50%) scale(1);}
  50%    {opacity:1; transform:translate(-50%,-50%) scale(1.15);}
}
@keyframes jarGlow2    {
  0%,100%{opacity:.5;transform:translate(-30%,-60%) scale(1);}
  50%    {opacity:.8;transform:translate(-30%,-60%) scale(1.1);}
}
@keyframes countFadeIn { from{opacity:0;transform:translateY(6px);} to{opacity:1;transform:none;} }
@keyframes shimmerSweep{ from{transform:translateX(-100%) skewX(-15deg);} to{transform:translateX(250%) skewX(-15deg);} }
@keyframes toastIn     { to{transform:translateY(0);opacity:1;} }
@keyframes toastOut    { to{transform:translateY(20px);opacity:0;} }
@keyframes pop         { 0%{transform:scale(0);} 60%{transform:scale(1.18);} 100%{transform:scale(1);} }
@keyframes cartBounce  { 0%,100%{transform:none;} 30%{transform:translateY(-7px) rotate(-8deg);} 60%{transform:translateY(2px);} }

/* =================================================================
   1. DESIGN TOKENS
   ================================================================= */
:root {
  /* — Palette — */
  --red:       #d62828;
  --red-deep:  #b01e1e;
  --gold:      #e8a317;
  --gold-soft: #f6c86a;
  --gold-dim:  rgba(232,163,23,.14);
  --gold-line: rgba(232,163,23,.22);

  /* — Light mode (warm parchment) — */
  --bg:        #FAF4E8;
  --bg-soft:   #F4ECDA;
  --bg-tint:   #EDE3CA;
  --surface:   #FFFFFF;
  --surface-2: #F9F3E6;
  --text:      #1E1A0E;
  --text-muted:#6B5E48;
  --border:    rgba(30,20,8,.1);
  --border-lift:rgba(30,20,8,.18);

  /* — Always-dark fixed values (about section stays dark in both themes) — */
  --ink:       #0D0B08;
  --ink-soft:  #161209;
  --ink-card:  #1E1A0E;
  --cream:     #F2E8D0;
  --cream-dim: rgba(242,232,208,.55);

  /* — Hero: follows theme — white + warm gradient in light, dim ink + gradient in dark — */
  --hero-bg: radial-gradient(ellipse 135% 100% at 6% 0%, #FFFFFF 0%, #FFFCF3 26%, #FDF3DD 55%, #F7E9C9 100%);
  --hero-glow-a: rgba(232,163,23,.22);
  --hero-glow-b: rgba(214,40,40,.10);
  --hero-fish-opacity: .18;

  /* — Status — */
  --ok:   #18a957;
  --warn: #e8a317;
  --crit: #ea580c;
  --out:  #dc2626;

  /* — Order status palette —
     One hue per state, and the SAME hue wherever that state appears: the pill
     on an order card, the dot on a tracking step, the tile on the dashboard.

     These were seven hardcoded literals in profile.css (#2563eb, #9333ea,
     #0d9488 …). Two things were wrong with that. They were invisible to the
     dark theme, so every status pill kept its light-mode colour on a near-black
     card. And nothing else could reach them, so the dashboard tiles invented
     their own palette and the Active Orders tile ended up a different blue from
     the Accepted pill sitting six inches below it. */
  --st-pending:   #c8890a;
  --st-accepted:  #2563eb;
  --st-shipping:  #9333ea;
  --st-delivered: #0d9488;
  --st-completed: #16a34a;
  --st-hold:      #ea580c;
  --st-cancelled: #dc2626;

  /* — Traceability promo panel —
     Its own tokens, because the panel used to be a fixed var(--ink) card and
     --ink does not move with the theme: on the dark storefront --bg IS #0D0B08,
     so a #0D0B08 panel sat on an identical page with a shadow nobody can see on
     black — an invisible box holding the one call to action on the page.
     Light keeps exactly what it had. Dark gets the same treatment the rest of
     the dark storefront uses: the lifted surface and a gold hairline. */
  --promo-bg:     var(--ink);
  --promo-border: transparent;
  --promo-ring:   rgba(232,163,23,.1);   /* the big off-corner circle */
  --promo-shadow: 0 20px 48px rgba(0,0,0,.4);

  /* — Elevation — */
  --shadow-sm: 0 1px 3px rgba(30,20,8,.07),0 1px 2px rgba(30,20,8,.05);
  --shadow-md: 0 4px 14px rgba(30,20,8,.1),0 2px 6px rgba(30,20,8,.06);
  --shadow-lg: 0 16px 48px rgba(30,20,8,.14),0 6px 16px rgba(30,20,8,.08);
  --shadow-ink:0 16px 48px rgba(0,0,0,.55),0 4px 12px rgba(0,0,0,.35);

  /* — Shape — */
  --r-sm:   6px;
  --r-md:   12px;
  --r-lg:   20px;
  --r-xl:   28px;
  --r-pill: 999px;

  /* — Type scale — the same eleven steps as portal/portal.css.

     Sizes above 1.6rem are not on the scale on purpose: the hero headings are
     fluid clamp() values set per section. Everything that is body, label or
     meta text uses a token here. See the longer note in portal.css for why
     these exist. */
  --fs-4xs: .55rem;
  --fs-3xs: .62rem;
  --fs-2xs: .68rem;
  --fs-xs:  .74rem;
  --fs-sm:  .8rem;
  --fs-base:.88rem;
  --fs-md:  .95rem;
  --fs-lg:  1.05rem;
  --fs-xl:  1.2rem;
  --fs-2xl: 1.4rem;
  --fs-3xl: 1.55rem;

  /* — Motion — */
  --t-fast: 140ms;
  --t:      220ms;
  --t-slow: 400ms;
  --ease:   cubic-bezier(.22,.61,.36,1);

  /* — Layout — */
  --maxw:  1200px;
  --nav-h: 76px;

  /* — Z-index — */
  --z-nav:    100;
  --z-drawer: 200;
  --z-modal:  300;
  --z-toast:  400;

  color-scheme: light;
}

[data-theme="dark"] {
  --red:       #f04040;
  --red-deep:  #c82020;
  --gold:      #f2b441;
  --gold-soft: #ffd27a;
  --gold-dim:  rgba(242,180,65,.12);
  --gold-line: rgba(242,180,65,.2);

  --bg:        #0D0B08;
  --bg-soft:   #141209;
  --bg-tint:   #1E1A0E;
  --surface:   #1E1A0E;
  --surface-2: #241D0E;
  --text:      #F2E8D0;
  --text-muted:#9A8E72;
  --border:    rgba(232,163,23,.1);
  --border-lift:rgba(232,163,23,.22);

  /* Lifted for a dark ground. The light-mode values are mid-tones chosen to sit
     on white; on #1E1A0E they read as bruises. Same seven hues, same order. */
  --st-pending:   #f2b441;
  --st-accepted:  #60a5fa;
  --st-shipping:  #c084fc;
  --st-delivered: #2dd4bf;
  --st-completed: #4ade80;
  --st-hold:      #fb923c;
  --st-cancelled: #f87171;

  --hero-bg: radial-gradient(ellipse 120% 90% at 15% 0%, #1a1509 0%, #100d07 45%, #0D0B08 100%);
  --hero-glow-a: rgba(232,163,23,.13);
  --hero-glow-b: rgba(214,40,40,.08);
  --hero-fish-opacity: .33;

  /* The promo panel lifts off the page instead of disappearing into it: the
     storefront's dark card surface, the gold hairline every dark card carries,
     and a brighter ring so the corner flourish is still readable. */
  --promo-bg:     var(--surface);
  --promo-border: var(--border-lift);
  --promo-ring:   rgba(242,180,65,.14);
  --promo-shadow: 0 20px 48px rgba(0,0,0,.55);

  --shadow-sm: 0 1px 3px rgba(0,0,0,.4);
  --shadow-md: 0 4px 14px rgba(0,0,0,.5);
  --shadow-lg: 0 16px 48px rgba(0,0,0,.6);

  color-scheme: dark;
}

/* =================================================================
   2. BASE
   ================================================================= */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
main { animation: pageIn .5s var(--ease) both; }
body.page-exit main { animation: pageOut .32s var(--ease) forwards; }

body {
  margin: 0;
  font-family: "Karla","Montserrat",system-ui,-apple-system,sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: var(--fs-md); line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background var(--t-slow) var(--ease), color var(--t-slow) var(--ease);
}

h1,h2,h3,h4 {
  font-family: "Cormorant Garamond",Georgia,serif;
  font-weight: 700; line-height: 1.08; margin: 0; letter-spacing: .1px;
}
h2 { font-size: clamp(2rem,4.2vw,3.2rem); }
h2 em { font-style: italic; }
p   { margin: 0; }
a   { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
ul,ol { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; border-radius: var(--r-sm); }

/* =================================================================
   3. UTILITIES
   ================================================================= */
.container {
  width: 100%; max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: clamp(18px,5vw,48px);
}
.section { padding-block: clamp(64px,9vw,110px); }
.section-head {
  max-width: 620px; margin: 0 auto clamp(32px,5vw,52px);
  text-align: center;
}
.section-head p { color: var(--text-muted); margin-top: 12px; font-size: var(--fs-lg); }

.eyebrow {
  display: inline-block;
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--red); margin-bottom: 14px;
  position: relative; padding-bottom: 6px;
}
.eyebrow::after {
  content: ""; position: absolute;
  bottom: 0; left: 0;
  width: 24px; height: 2px;
  background: var(--gold);
  border-radius: 2px;
}
/* Gold eyebrow variant for dark sections */
.eyebrow-gold { color: var(--gold); }
.eyebrow-gold::after { background: rgba(232,163,23,.4); }

.text-gold { color: var(--gold); }

/* =================================================================
   4. BUTTONS
   ================================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font-family: "Montserrat",inherit; font-weight: 700; font-size: var(--fs-base);
  letter-spacing: .04em; text-transform: uppercase;
  padding: 14px 28px; border-radius: var(--r-pill);
  min-height: 48px; white-space: nowrap; cursor: pointer;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t) var(--ease), background var(--t) var(--ease), color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.btn:active { transform: translateY(1px) scale(.99); }
.btn svg { width: 16px; height: 16px; flex: none; }

.btn-gold {
  background: var(--gold); color: #1E1A0E;
  box-shadow: 0 8px 24px rgba(232,163,23,.32);
}
.btn-gold:hover { background: var(--gold-soft); transform: translateY(-3px); box-shadow: 0 14px 32px rgba(232,163,23,.44); }

.btn-red {
  background: var(--red); color: #fff;
  box-shadow: 0 6px 18px rgba(214,40,40,.26);
}
.btn-red:hover { background: var(--red-deep); transform: translateY(-3px); box-shadow: 0 12px 28px rgba(214,40,40,.38); }

/* .btn-primary — the action INSIDE a card, a drawer or a modal.

   Five controls carry this class (Add on every product card, Add to Cart in
   the product detail, Proceed to Checkout, Place Order, and Done on the
   receipt) and it had no rule at all. They fell through to the bare `.btn`
   base, which sets layout, type and a transition and nothing else — so the
   Add button on twelve cards rendered as plain text with a cart icon, with no
   fill, no hover and no lift. It did not look like a button because nothing
   said it was one.

   Deliberately not a second .btn-gold. Gold is the hero CTA; twelve solid gold
   Add buttons in the grid and nothing on the page reads as the main action any
   more. Red is already the interaction colour on a card — .pc-name:hover and
   .stepper button:hover both go red, and the cart badge is red — so a filled
   red button is the one that says "this is the action here" without arguing
   with the hero. It sits a step below .btn-red in weight: smaller resting
   shadow, smaller lift. */
.btn-primary {
  background: var(--red); color: #fff;
  border: 1.5px solid transparent;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--red) 26%, transparent);
}
.btn-primary:hover {
  background: var(--red-deep);
  transform: translateY(-2px);
  box-shadow: 0 10px 24px color-mix(in srgb, var(--red) 40%, transparent);
}
/* Must come after :hover — same specificity, and a pressed button is usually
   also hovered, so the later rule is the one that decides the transform. */
.btn-primary:active {
  transform: translateY(0) scale(.98);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--red) 30%, transparent);
}
/* The global :focus-visible rule (section 2) already draws a gold outline on
   everything. It is restated here with the gold halo because a 3px outline
   sitting directly on a red fill has very little to separate it from the
   button — the ring reads as part of the shape rather than around it. */
.btn-primary:focus-visible {
  outline: 3px solid var(--gold); outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--gold-dim), 0 4px 14px color-mix(in srgb, var(--red) 26%, transparent);
}

.btn-ghost-ink {
  background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text);
  border: 1.5px solid color-mix(in srgb, var(--text) 18%, transparent);
  backdrop-filter: blur(8px);
  transition: background var(--t), border-color var(--t), color var(--t), transform var(--t-fast);
}
.btn-ghost-ink:hover { background: color-mix(in srgb, var(--text) 11%, transparent); border-color: rgba(232,163,23,.4); color: var(--gold); }

.btn-ghost {
  background: var(--bg); color: var(--text);
  border: 1.5px solid var(--border-lift);
}
.btn-ghost:hover { border-color: var(--gold); color: var(--red); }

.btn-block { width: 100%; }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none !important; box-shadow: none !important; }
/* Sold Out. .btn:disabled above kills the lift and the shadow but not the
   fill, and a half-opacity red button still reads as something you can press.
   Placed after it rather than in the .btn-primary group because the two
   selectors have equal specificity — this one has to be the later rule to win
   the background. */
.btn-primary:disabled {
  background: color-mix(in srgb, var(--text) 10%, var(--surface));
  color: var(--text); border-color: var(--border);
}

/* =================================================================
   5. FORM FIELDS
   ================================================================= */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: var(--fs-sm); font-weight: 700; margin-bottom: 7px; letter-spacing: .02em; }
.field .control {
  width: 100%; padding: 13px 16px; font-size: var(--fs-md); font-family: inherit;
  background: var(--surface); color: var(--text);
  border: 1.5px solid var(--border-lift); border-radius: var(--r-md);
  transition: border-color var(--t), box-shadow var(--t);
}
.field .control:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-dim); }
.field-error { color: var(--out); font-size: var(--fs-xs); margin-top: 5px; min-height: 1em; display: block; }
.sr-only { position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0; }
.icon { width: 22px; height: 22px; flex: none; }
.hide { display: none !important; }

/* Stepper */
.stepper { display: inline-flex; align-items: center; border: 1.5px solid var(--border-lift); border-radius: var(--r-pill); overflow: hidden; }
.stepper button { width: 32px; height: 32px; display: grid; place-items: center; color: var(--text); transition: background var(--t); }
.stepper button:hover { background: var(--bg-tint); color: var(--red); }
.stepper input { width: 36px; text-align: center; border: none; background: transparent; color: var(--text); font-weight: 700; font-family: inherit; font-size: var(--fs-base); }
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; }

/* =================================================================
   6. NAVBAR — minimal editorial
   ================================================================= */
.nav {
  position: fixed; inset: 0 0 auto 0;
  z-index: var(--z-nav);
  padding-block: 16px;
  transition: padding var(--t) var(--ease), background var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.nav::before {
  content: "";
  position: absolute; inset: 0;
  background: var(--surface);
  opacity: 0; transition: opacity var(--t) var(--ease), background var(--t-slow) var(--ease);
  pointer-events: none; z-index: -1;
}
.nav.scrolled::before { opacity: .96; }
.nav.scrolled { padding-block: 12px; box-shadow: 0 1px 0 rgba(232,163,23,.1); }

.nav-inner {
  display: flex; align-items: center; gap: 20px;
  max-width: var(--maxw); margin-inline: auto;
  padding-inline: clamp(18px,5vw,48px);
  position: relative;
}

/* Brand — follows theme (nav sits on the theme-aware hero) */
.brand { display: flex; align-items: center; gap: 11px; flex-shrink: 0; }
.brand .mark { width: 36px; height: 36px; flex: none; transition: transform var(--t) var(--ease); }
.brand:hover .mark { transform: rotate(-8deg) scale(1.06); }
.brand .name {
  font-family: "Cormorant Garamond",serif; font-size: var(--fs-xl); font-weight: 700;
  color: var(--text); line-height: 1;
  transition: color var(--t-slow) var(--ease);
}
.brand .name small {
  display: block; font-family: "Montserrat"; font-size: var(--fs-4xs);
  font-weight: 600; letter-spacing: .26em; color: var(--gold);
  text-transform: uppercase; margin-top: 2px;
}

/* Pill-less centered nav */
.nav-links {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%,-50%);
  display: flex; align-items: center; gap: 2px;
  background: none; border: none; border-radius: 0;
  white-space: nowrap;
}
.nav-links a {
  position: relative; z-index: 1;
  padding: 8px 13px;
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--text);
  transition: color var(--t) var(--ease);
}
.nav-links a:hover  { color: var(--gold); }
.nav-links a.active { color: var(--gold); }
.nav-links a.page-active { color: var(--gold); }

/* Gold underline indicator (not a bg pill) */
.nav-indicator {
  position: absolute;
  bottom: -2px; left: 0; height: 2px;
  background: var(--gold); border-radius: 2px;
  transition: left .38s cubic-bezier(.34,1.56,.64,1), width .38s cubic-bezier(.34,1.56,.64,1);
}
.nav-indicator::before, .nav-indicator::after { display: none; }

/* Nav actions */
.nav-actions { display: flex; align-items: center; gap: 4px; margin-left: auto; flex-shrink: 0; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--r-pill);
  color: var(--text); transition: background var(--t), color var(--t);
}
.icon-btn:hover { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--gold); }

.nav-cart-btn { position: relative; }
.cart-badge {
  position: absolute; top: 1px; right: 1px;
  min-width: 17px; height: 17px; padding: 0 4px;
  background: var(--red); color: #fff; font-size: var(--fs-3xs); font-weight: 700;
  border-radius: var(--r-pill); display: flex; align-items: center; justify-content: center;
  transform: scale(0); transition: transform var(--t) var(--ease);
}
.cart-badge.show { transform: scale(1); }
.cart-icon-anim { animation: cartBounce .5s var(--ease); }

.nav-login-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 8px 18px; min-height: 36px;
  background: var(--gold); color: #1E1A0E;
  border-radius: var(--r-pill); font-family: "Montserrat",inherit;
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  transition: opacity var(--t), transform var(--t), background var(--t);
}
.nav-login-btn:hover { opacity: .88; transform: scale(1.03); }

.theme-toggle .sun  { display: none; }
[data-theme="dark"] .theme-toggle .sun  { display: block; }
[data-theme="dark"] .theme-toggle .moon { display: none; }
.hamburger   { display: none; }
.mob-cart-btn{ display: none; }

/* Account pop */
#account-menu { position: relative; }
.nav-profile-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 10px 3px 3px; border-radius: var(--r-pill); cursor: pointer;
  transition: background var(--t);
}
.nav-profile-btn:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }
.nav-avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--gold); color: #1e1a0e;
  font-size: var(--fs-2xs); font-weight: 700;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.nav-username { font-size: var(--fs-sm); font-weight: 600; color: var(--text); max-width: 80px; overflow: hidden; text-overflow: ellipsis; }
.nav-chev { width: 12px; height: 12px; color: var(--text-muted); flex-shrink: 0; transition: transform var(--t); }
.nav-profile-btn.open .nav-chev { transform: rotate(180deg); }

.account-pop {
  position: absolute; right: 0; top: calc(100% + 10px);
  width: 200px; padding: 8px;
  background: var(--ink-card); border: 1px solid var(--gold-line);
  border-radius: var(--r-md); box-shadow: var(--shadow-ink);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: all var(--t) var(--ease); z-index: 20;
}
.account-pop.open { opacity: 1; visibility: visible; transform: translateY(0); }
.account-pop .ap-head { padding: 10px 12px; border-bottom: 1px solid var(--gold-line); margin-bottom: 6px; color: var(--cream); }
.account-pop .ap-head b { display: block; }
.account-pop button { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 10px 12px; border-radius: var(--r-sm); font-size: var(--fs-base); color: var(--cream); }
.account-pop button:hover { background: rgba(255,255,255,.06); color: var(--gold); }

/* =================================================================
   7. HERO — split typography stage
   ================================================================= */
.hero {
  position: relative;
  background: var(--hero-bg); /* follows theme toggle */
  min-height: 100svh;
  display: flex; flex-direction: column;
  overflow: hidden;
  transition: background var(--t-slow) var(--ease);
}
.hero-canvas {
  position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: hidden;
}
.jar-glow {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%,-50%);
  width: 700px; height: 700px;
  background: radial-gradient(circle at 50% 50%, var(--hero-glow-a) 0%, var(--hero-glow-b) 40%, transparent 70%);
  filter: blur(70px);
  animation: jarGlowPulse 7s ease-in-out infinite;
}
.jar-glow-2 {
  position: absolute; top: 25%; left: 62%;
  transform: translate(-30%,-60%);
  width: 440px; height: 440px;
  background: radial-gradient(circle, var(--hero-glow-b), transparent 70%);
  filter: blur(55px);
  animation: jarGlow2 10s ease-in-out infinite;
}

/* Hero fish — bangus silhouette behind the typography.
   Sized by HEIGHT, not width, and kept within the band above the tile
   strip: at 840px wide the fish ran to y=882 while the strip starts at
   ~y=531, so nearly half the fish was hidden behind the tiles. Anchoring
   to a percentage of the hero keeps it clear as the hero grows. */
.hero-fish-bg {
  position: absolute;
  top: 0%;
  /* 50% is the practical ceiling: at 52% the fish starts colliding with the
     tile strip at 1280x1024 and 1024x700, where the strip sits higher
     relative to the hero than it does on wide screens. */
  /* Flush to the edge, not bled off it: the PNG carries only ~4% transparent
     margin, so a negative offset was cropping the tail rather than empty space. */
  left: 0;
  width: auto;
  height: 50%;
  max-width: 62vw;
  opacity: var(--hero-fish-opacity);
  pointer-events: none;
  user-select: none;
  filter: saturate(0.7) brightness(0.9);
  transition: opacity var(--t-slow) var(--ease);
}

.hero-inner {
  position: relative; z-index: 1; flex: 1;
  display: flex; flex-direction: column; justify-content: center;
  padding-top: calc(var(--nav-h) + clamp(18px,3.4vw,44px));
  padding-bottom: clamp(24px,3.4vw,48px);
  max-width: min(1640px, 100%); /* hero runs wider than the site column */
}

/* Two-column hero: copy left, slider right */
.hero-grid {
  display: grid; grid-template-columns: .88fr 1.12fr;
  gap: clamp(20px,2.6vw,40px); align-items: stretch;
}
.hero-copy { min-width: 0; position: relative; z-index: 2; }

/* Signature split typography */
.hero-split { width: 100%; margin-bottom: clamp(22px,3.4vw,38px); }
.hero-word {
  font-family: "Playfair Display SC","Cormorant Garamond",Georgia,serif;
  font-size: clamp(4rem,11.5vw,164px);
  font-weight: 700; color: var(--text);
  letter-spacing: -.025em; line-height: .88;
  display: block; width: 100%;
  transition: color var(--t-slow) var(--ease);
}
.hero-word.right { text-align: right; }

/* =================================================================
   HERO VISUAL — single image panel + thumbnail strip
   -----------------------------------------------------------------
   One flat panel that cross-fades between products. The thumbnail
   strip in the left column drives it (there are no dot indicators);
   the tagline and craft stats sit over the image, kept legible by
   .hs-scrim regardless of which photo is showing.
   ================================================================= */
.hero-visual { position: relative; min-width: 0; display: flex; }

.hero-slider {
  position: relative;
  flex: 1;                       /* fill the row rather than a fixed box */
  min-height: clamp(500px, 70vh, 840px);
  border-radius: var(--r-xl);

  /* NOTCH — the panel has a tile-shaped bite taken out of its left edge so
     the last tile seats inside the silhouette with an even gap all round,
     rather than sitting on top of a solid rectangle.

     Position and size are measured from the real tile by syncNotch() in
     script.js (they depend on the flex-sized strip, which CSS can't read)
     and written back as the four custom properties below. They default to
     zero, so with JS unavailable the panel is simply an uncut rectangle.

     The cut itself is a second mask layer subtracted from the panel. Its
     shape is a rounded square SVG; the tiles are 1:1 on every viewport that
     shows the notch, so the corner radii stay circular and never distort. */
  --notch-x: 0px; --notch-y: 0px; --notch-w: 0px; --notch-h: 0px;
  --notch-shape: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'><rect width='100' height='100' rx='12' ry='12' fill='black'/></svg>");

  -webkit-mask-image: linear-gradient(#000 0 0), var(--notch-shape);
  -webkit-mask-size: 100% 100%, var(--notch-w) var(--notch-h);
  -webkit-mask-position: 0 0, var(--notch-x) var(--notch-y);
  -webkit-mask-repeat: no-repeat, no-repeat;
  -webkit-mask-composite: xor;
          mask-image: linear-gradient(#000 0 0), var(--notch-shape);
          mask-size: 100% 100%, var(--notch-w) var(--notch-h);
          mask-position: 0 0, var(--notch-x) var(--notch-y);
          mask-repeat: no-repeat, no-repeat;
          mask-composite: exclude;
  overflow: hidden;
  border: 1px solid rgba(232,163,23,.22);
  box-shadow: 0 22px 60px rgba(0,0,0,.42);
  isolation: isolate;

  /* How far the last tile bites into the panel: the strip's overhang minus
     the column gap it first has to cross. The overlay copy is inset by this
     much plus its own padding, so the tagline always clears the tile by the
     same margin instead of colliding with it at wide viewports. */
  --tile-bite: max(0px, calc(clamp(0px, 8.4vw, 140px) - clamp(20px, 2.6vw, 40px)));
}
.hs-track { position: absolute; inset: 0; }

/* Cross-fade, not a stacked deck — the panel reads as one surface. */
.hs-slide {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  opacity: 0;
  /* Runs concurrently with the tile slide — see advance() in script.js.
     Timed so the panel finishes changing exactly as the tile lands. */
  transition: opacity .55s var(--ease);
  pointer-events: none;
}
.hs-slide.active { opacity: 1; pointer-events: auto; }
.hs-slide img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.hs-ph { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.hs-ph .ph-icon  { width: 40px; height: 40px; color: #fff; opacity: .65; }
.hs-ph .ph-label {
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: #fff; opacity: .75;
}

/* Product name moves to the top — the bottom belongs to the tagline. */
.hs-caption {
  position: absolute; left: clamp(20px,2.4vw,30px); top: clamp(18px,2.2vw,26px);
  z-index: 4;
  font-family: "Playfair Display SC",serif;
  font-size: var(--fs-lg); font-weight: 700; color: var(--cream);
  letter-spacing: .02em;
  text-shadow: 0 2px 14px rgba(0,0,0,.6);
}

/* Legibility wash under the overlay copy. */
.hs-scrim {
  position: absolute; left: 0; right: 0; bottom: 0; height: 78%;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(0,0,0,.30) 34%,
    rgba(0,0,0,.66) 62%,
    rgba(0,0,0,.86) 100%
  );
  z-index: 2; pointer-events: none;
}

.hs-overlay {
  position: absolute; z-index: 3;
  left: calc(var(--tile-bite, 0px) + clamp(20px,2.6vw,34px));
  right: clamp(20px,2.6vw,34px);
  bottom: clamp(20px,2.6vw,32px);
  display: flex; flex-direction: column; align-items: flex-start;
}
.hs-overlay .hero-tagline {
  font-family: "Cormorant Garamond",Georgia,serif;
  font-size: clamp(1.45rem,2.5vw,2.1rem); font-weight: 700;
  color: var(--cream); line-height: 1.2; margin-bottom: 10px;
  text-shadow: 0 2px 18px rgba(0,0,0,.55);
}
.hs-overlay .hero-tagline em { font-style: italic; color: var(--gold-soft); }
.hs-overlay .hero-lead {
  font-size: clamp(.95rem,1.15vw,1.06rem);
  line-height: 1.65; max-width: 46ch;
  color: rgba(242,232,208,.86);
  text-shadow: 0 1px 12px rgba(0,0,0,.5);
}

/* Craft stats — right-aligned, stacked above the tagline. Living inside
   .hs-overlay (rather than absolutely placed) means they can never
   collide with the tagline at any viewport width. */
.hero-stats {
  align-self: flex-end;
  display: flex; flex-direction: column; align-items: flex-end;
  gap: clamp(14px,2vw,24px);
  margin-bottom: clamp(20px,3vw,38px);
  text-align: right;
}
.hero-stat b {
  display: block;
  font-family: "Playfair Display SC",serif;
  font-size: clamp(1.5rem,2.4vw,2rem); font-weight: 700;
  color: var(--cream); line-height: 1;
  text-shadow: 0 2px 16px rgba(0,0,0,.6);
}
.hero-stat span {
  display: block; margin-top: 4px;
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-3xs); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--gold-soft);
  text-shadow: 0 1px 10px rgba(0,0,0,.6);
}

/* =================================================================
   HERO STRIP — the "up next" conveyor
   -----------------------------------------------------------------
   Three visible tiles queueing toward the panel. The queue runs
   LEFT to RIGHT: the rightmost tile sits against the panel edge and
   is the one that feeds it next, so on every advance the whole rail
   slides right, the rightmost tile travels into the panel, and a
   fresh tile enters from the left.

   The rail actually holds four tiles and rests one tile-width to the
   left; the fourth is the incoming tile waiting off-screen. Sliding
   the rail back to 0 walks everything one place to the right, after
   which the rail is rebuilt at rest.

   .hero-thumbs clips horizontally (so tiles appear and disappear at
   the edges) but is padded vertically and pulled back with a matching
   negative margin, so tile drop-shadows survive the clip.
   ================================================================= */
.hero-thumbs {
  --ht-gap: clamp(8px,.85vw,12px);
  --ht-w: calc((100% - 2 * var(--ht-gap)) / 3);
  position: relative; z-index: 2;
  width: calc(100% + clamp(0px, 8.4vw, 140px));
  overflow: hidden;
  padding: 34px 0;
  margin: -34px 0;
}
.ht-rail {
  display: flex; gap: var(--ht-gap);
  transform: translateX(calc(-1 * (var(--ht-w) + var(--ht-gap))));
}
.ht-rail.is-moving {
  transform: translateX(0);
  transition: transform .7s cubic-bezier(.4,0,.2,1);
}
/* Incoming tile fades up as it enters; the outgoing one fades away as
   it reaches the panel, rather than being chopped off by the clip. */
.ht-rail .hero-thumb:first-child { opacity: 0; }
.ht-rail.is-moving .hero-thumb:first-child {
  opacity: 1; transition: opacity .7s var(--ease);
}
.ht-rail.is-moving .hero-thumb:last-child {
  opacity: 0; transition: opacity .7s var(--ease);
}

.hero-thumb {
  flex: 0 0 var(--ht-w);
  aspect-ratio: 1 / 1;
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 0; padding: 0;
  cursor: pointer;
  box-shadow: 0 10px 26px rgba(0,0,0,.3);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.hero-thumb img,
.hero-thumb .ht-ph {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.hero-thumb::after {
  content: ""; position: absolute; inset: 0;
  border-radius: inherit;
  background: rgba(0,0,0,.28);
  transition: background var(--t) var(--ease);
}
.hero-thumb:hover { transform: translateY(-4px); }
.hero-thumb:hover::after { background: rgba(0,0,0,.08); }
.hero-thumb:focus-visible { outline: 2px solid var(--gold); outline-offset: -4px; }

/* Rightmost tile is next into the panel. It carried a white ring before the
   notch existed; now the notch itself marks which tile is up next, so the
   ring is redundant. A deeper shadow and a lighter wash keep it reading as
   the foremost tile without outlining it. */
.hero-thumb.next-up { box-shadow: 0 14px 32px rgba(0,0,0,.42); }
.hero-thumb.next-up::after { background: rgba(0,0,0,.06); }

.hero-rule {
  width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 18px;
  margin: clamp(8px,2vw,18px) 0;
}
.hero-rule::before, .hero-rule::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--gold); min-width: 24px;
}
.hero-rule-text {
  flex: none;
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-3xs); font-weight: 600;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--gold); white-space: nowrap;
}

/* Text block stacked full-width, CTA row below it — uses the full
   column width instead of squeezing buttons beside wrapped text */
.hero-bottom {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: clamp(18px,2.6vw,26px);
}
.hero-lead {
  font-size: clamp(1.05rem,1.8vw,1.3rem);
  color: var(--text-muted); line-height: 1.75;
  max-width: 56ch; width: 100%;
}
.hero-tagline {
  font-family: "Cormorant Garamond",Georgia,serif;
  font-size: clamp(1.6rem,3vw,2.3rem); font-weight: 700;
  color: var(--text); line-height: 1.2;
  margin-bottom: 12px;
}
.hero-tagline em { font-style: italic; color: var(--gold); }
.hero-ctas { display: flex; gap: 16px; flex-wrap: wrap; width: 100%; }
.hero-ctas .btn { flex: 1 1 220px; justify-content: center; }

/* Stats strip */
.stats-strip {
  position: relative; z-index: 1;
  border-top: 1px solid rgba(232,163,23,.14);
  background: rgba(255,255,255,.03);
  padding: 28px 0;
  margin-top: clamp(40px,7vw,80px);
}
.stats-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0;
}
.stat-item {
  display: flex; flex-direction: column; align-items: center;
  text-align: center; flex: 1;
}
.stat-row { display: flex; align-items: baseline; gap: 1px; }
.stat-num {
  font-family: "Playfair Display SC",serif;
  font-size: clamp(2rem,4.5vw,3.4rem); font-weight: 700;
  color: var(--cream); line-height: 1;
  animation: countFadeIn .6s var(--ease);
}
.stat-sfx { font-size: .65em; color: var(--gold); font-weight: 700; margin-left: 1px; }
.stat-label {
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-3xs); font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgba(232,163,23,.5); margin-top: 6px;
}
.stat-rule {
  width: 1px; height: 44px; flex-shrink: 0;
  background: rgba(232,163,23,.18);
}

/* Trust bar (rendered by JS) */
.trust-bar {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-top: 28px;
}

/* =================================================================
   8. MARQUEE
   ================================================================= */
.marquee-section {
  background: var(--red); padding: 13px 0; overflow: hidden; position: relative; z-index: 1;
}
.marquee-inner { display: flex; overflow: hidden; user-select: none; }
.marquee-track {
  display: flex; align-items: center; white-space: nowrap;
  animation: marqueeRun 28s linear infinite; flex-shrink: 0;
}
.marquee-section:hover .marquee-track { animation-play-state: paused; }
.mq-item {
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(255,255,255,.92); padding: 0 22px;
}
.mq-sep { color: rgba(255,255,255,.5); font-size: .5rem; flex-shrink: 0; }

/* =================================================================
   9. FEATURED (accordion section)
   ================================================================= */
.featured-section { background: var(--bg); }

.featured-head { margin-bottom: clamp(28px,4vw,44px); }
.featured-sub {
  color: var(--text-muted); font-size: var(--fs-lg); margin-top: 12px; max-width: 50ch;
}
.featured-title {
  font-family: "Playfair Display SC","Cormorant Garamond",Georgia,serif;
  font-size: clamp(2.6rem,6vw,5rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.01em;
  text-transform: uppercase;
  color: var(--text);
  margin: 0;
}
.featured-title .text-gold {
  color: var(--gold);
}

.acc-wrap {
  width: 100%; height: clamp(300px,40vw,440px);
  border: 1px solid var(--border-lift); border-radius: var(--r-xl); overflow: hidden;
  box-shadow: var(--shadow-md);
}
.hero-accordion {
  width: 100%; height: 100%;
  display: flex; gap: 8px; align-items: stretch; padding: 10px;
  background: var(--surface);
}
.acc-panel {
  position: relative; border-radius: var(--r-lg); overflow: hidden; cursor: pointer;
  flex: 1; transition: flex .44s cubic-bezier(.22,.61,.36,1);
}
.acc-panel.active { flex: 5; box-shadow: var(--shadow-md); }
.acc-panel::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top,rgba(0,0,0,.65) 0%,rgba(0,0,0,.12) 45%,transparent 65%);
  pointer-events: none;
}
.acc-label {
  position: absolute; z-index: 2; color: #fff;
  font-family: "Cormorant Garamond",serif; font-size: var(--fs-md); font-weight: 700;
  white-space: nowrap; letter-spacing: .02em;
  transition: all .44s cubic-bezier(.22,.61,.36,1);
}
.acc-panel.active .acc-label      { top: 18px; left: 0; right: 0; text-align: center; transform: none; font-size: var(--fs-lg); }
.acc-panel:not(.active) .acc-label { bottom: auto; top: 50%; left: 24px; transform: translate(-50%,-50%) rotate(90deg); font-size: var(--fs-base); opacity: .88; }
.acc-panel-bg { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.acc-panel-bg .acc-img-holder {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%,-50%) scale(.82);
  width: 50%; max-width: 100px; aspect-ratio: 2/3;
  border-radius: 8px; background: rgba(255,255,255,.12);
  border: 2px dashed rgba(255,255,255,.28);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  opacity: 0; pointer-events: none;
  transition: opacity .44s var(--ease), transform .44s var(--ease);
}
.acc-panel.active .acc-panel-bg .acc-img-holder { opacity: 1; transform: translate(-50%,-50%) scale(1); }
.acc-img-holder .ph-icon  { width: 26px; height: 26px; color: #fff; opacity: .7; }
.acc-img-holder .ph-label { font-size: var(--fs-4xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: #fff; opacity: .6; text-align: center; }

/* =================================================================
   10. BEST SELLERS — carousel
   ================================================================= */
.bestsellers-section {
  background: var(--surface);
  padding-top: clamp(36px,4vw,56px); /* tighter than .section — carousel sits higher */
}
.bestsellers-section .section-head { margin-bottom: clamp(8px,1.5vw,16px); }

.bs-carousel  { position: relative; padding: 0 0 32px; overflow: visible; }
/* WHEEL CAROUSEL
   Cards ride the rim of a large circle whose centre sits far below the
   stage. Each slide pivots about that point (transform-origin below the
   card), so one rotate() both swings it sideways and tilts it with the
   rim — no separate translate needed, and the arc stays exact.

   align-items:flex-start keeps the centre card at the top of the arc with
   the side cards dipping into the space beneath it. */
.bsc-stage {
  position: relative; height: 660px;
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 10px;

  /* The arc runs ~900px deep but the centre card ends at ~598, so the stage
     is cut just below it and the side cards dissolve over the last 56px
     rather than being sliced. Without this the nav sat 320px below the
     cards, far enough that the section had to be zoomed out to see both.

     Unprefixed mask-* only, deliberately. Declaring -webkit-mask-image
     alongside it made Chromium render the stage as a ~200px vertical strip
     with the side cards gone entirely; the two property sets are not
     aliases and compose badly. Unprefixed mask-image is supported by every
     current browser, so the prefix buys nothing here. */
  mask-image: linear-gradient(to bottom, #000 0 calc(100% - 56px), transparent 100%);
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
  /* Pivot distance from each card's top edge. Bigger = wider spacing and a
     shallower arc for the same tilt angle; 1750 spreads the cards far enough
     apart that neighbours don't collide at WHEEL_STEP = 17deg. */
  --wheel-origin: 1750px;
}
.bsc-slide {
  position: absolute; width: 350px;
  transform-origin: 50% var(--wheel-origin, 1500px);
  transition: transform .8s var(--ease), opacity .8s var(--ease);
  will-change: transform, opacity;
}
/* Scale lives on the card, not the slide: scaling the slide would happen
   about the wheel's distant pivot and fling the card across the stage. */
.bsc-slide > .product-card {
  transition: transform .8s var(--ease);
  transform-origin: 50% 50%;
}
/* burst clicking: short transition so cards don't collide mid-glide */
.bsc-stage.fast .bsc-slide,
.bsc-stage.fast .bsc-slide > .product-card { transition-duration: .35s; }

.bsc-nav { display: flex; align-items: center; justify-content: center; gap: 20px; margin-top: 12px; }
.bsc-btn {
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--surface); border: 1.5px solid var(--border-lift);
  display: flex; align-items: center; justify-content: center;
  color: var(--text); cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: all var(--t) var(--ease);
}
.bsc-btn:hover { background: var(--gold); color: #1e1a0e; border-color: var(--gold); box-shadow: 0 6px 18px rgba(232,163,23,.3); }
.bsc-dots { display: flex; gap: 8px; align-items: center; }
.bsc-dot {
  width: 7px; height: 7px; border-radius: 50%;
  border: none; background: var(--border-lift); cursor: pointer; padding: 0;
  transition: background var(--t), transform var(--t);
}
.bsc-dot.active { background: var(--gold); transform: scale(1.5); }
.bsc-slide .product-card { pointer-events: none; }
.bsc-slide[data-active="true"] .product-card {
  pointer-events: auto;
  border-color: var(--gold-line);
  box-shadow: 0 24px 64px rgba(30,20,8,.18), 0 8px 24px rgba(232,163,23,.12);
}

/* Carousel cards run larger than the shop grid */
.bsc-slide .pc-name  { font-size: 1.72rem; }
.bsc-slide .pc-desc  { font-size: var(--fs-md); }
.bsc-slide .pc-body  { padding: 20px 22px 22px; gap: 10px; }
.bsc-slide .price    { font-size: var(--fs-2xl); }
.bsc-slide .pc-meta  { font-size: var(--fs-base); }
.bsc-slide .stars svg { width: 15px; height: 15px; }
.bsc-slide .btn-add  { padding: 12px 18px; font-size: var(--fs-base); }
.bsc-slide .img-holder .ph-icon { width: 54px; height: 54px; }

/* =================================================================
   10b. TRACEABILITY PROMO
   ================================================================= */
.trace-promo-section { background: var(--bg); }
.trace-promo {
  position: relative; overflow: hidden;
  max-width: 900px; margin-inline: auto;
  padding: clamp(40px,6vw,64px) clamp(28px,5vw,56px);
  border-radius: var(--r-xl);
  /* Tokens, not literals. This was `background: var(--ink)` with the comment
     "same always-dark black as About Us" — true, and it is what made the panel
     vanish in dark mode, where --bg is that same black. About Us can stay
     always-dark because it is a full-bleed section and has a cinematic
     background of its own; this is a CARD, and a card has to be distinguishable
     from the page it sits on. See --promo-* in the token blocks. */
  background: var(--promo-bg);
  border: 1px solid var(--promo-border);
  box-shadow: var(--promo-shadow);
  text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.trace-promo::after {
  content: ""; position: absolute; left: -60px; top: -70px;
  width: 220px; height: 220px; border-radius: 50%;
  border: 24px solid var(--promo-ring);
  pointer-events: none;
}
.trace-promo-icon {
  width: 46px; height: 46px; color: var(--gold);
  margin-bottom: 18px; position: relative; z-index: 1;
}
.trace-promo-title {
  position: relative; z-index: 1;
  font-family: "Playfair Display SC","Cormorant Garamond",Georgia,serif;
  font-size: clamp(1.9rem,4vw,2.75rem); font-weight: 700;
  line-height: 1.2; letter-spacing: -.01em;
  color: var(--cream); margin: 0 0 16px; max-width: 34ch;
}
.trace-promo-sub {
  position: relative; z-index: 1;
  font-size: var(--fs-lg); line-height: 1.78; color: var(--cream-dim);
  max-width: 58ch; margin: 0 0 28px;
}
.trace-promo .btn-gold { position: relative; z-index: 1; }

/* =================================================================
   11. PRODUCT CARD — warm editorial
   ================================================================= */
.product-card {
  position: relative; overflow: hidden; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease), border-color var(--t) var(--ease);
}
.product-card::before {
  content: ""; position: absolute; top: 0; left: -100%; width: 55%; height: 100%;
  background: linear-gradient(90deg,transparent,rgba(232,163,23,.15),transparent);
  pointer-events: none; z-index: 10;
}
.product-card:hover::before { animation: shimmerSweep .6s var(--ease) forwards; }
.product-card:hover {
  transform: translateY(-8px) scale(1.01);
  box-shadow: var(--shadow-lg);
  border-color: var(--gold-line);
}

.ribbon {
  position: absolute; top: 12px; left: -4px; z-index: 2;
  background: var(--gold); color: #1e1a0e;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em;
  padding: 5px 12px 5px 10px; border-radius: 0 var(--r-pill) var(--r-pill) 0;
  box-shadow: var(--shadow-sm); display: flex; gap: 5px; align-items: center;
}

.pc-media {
  position: relative; aspect-ratio: 4/3.2;
  background: linear-gradient(160deg,var(--bg-tint),var(--surface-2));
  display: grid; place-items: center; overflow: hidden; cursor: pointer;
}
.pc-media .img-holder {
  width: 100%; height: 100%; position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  transition: transform var(--t-slow) var(--ease);
}
.product-card:hover .pc-media .img-holder { transform: scale(1.06); }
.img-holder .ph-icon  { width: 44px; height: 44px; opacity: .3; color: var(--text-muted); }
.img-holder .ph-label { font-size: var(--fs-2xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); opacity: .55; }
.pc-quickview {
  position: absolute; inset: auto 0 0 0; padding: 10px;
  background: linear-gradient(transparent,rgba(30,20,8,.12));
  opacity: 0; transform: translateY(8px);
  display: flex; justify-content: center;
  transition: all var(--t) var(--ease);
}
.pc-media:hover .pc-quickview { opacity: 1; transform: translateY(0); }
.pc-quickview span {
  background: var(--surface); color: var(--text);
  font-size: var(--fs-xs); font-weight: 600; padding: 6px 14px;
  border-radius: var(--r-pill); box-shadow: var(--shadow-md);
  display: flex; gap: 5px; align-items: center;
}

.pc-body { padding: 16px 17px 18px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.pc-cat  { font-family: "Montserrat",sans-serif; font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--gold); }
.pc-name { font-family: "Cormorant Garamond",serif; font-size: var(--fs-2xl); font-weight: 600; line-height: 1.05; cursor: pointer; }
.pc-name:hover { color: var(--red); }
.pc-desc { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pc-meta { display: flex; align-items: center; justify-content: space-between; font-size: var(--fs-xs); color: var(--text-muted); }
.stars { display: inline-flex; align-items: center; gap: 2px; color: var(--gold); }
.stars svg { width: 13px; height: 13px; }
.stars .rv { color: var(--text-muted); font-size: var(--fs-xs); margin-left: 4px; font-weight: 600; }
/* The review COUNT, beside the average. One five-star review and forty are the
   same "5.0" and are not the same claim, so the average never appears without
   it. Lighter than .rv so the score still leads. */
.stars .rc { color: var(--text-muted); font-size: var(--fs-xs); margin-left: 3px; }
/* NO STARS AT ALL when nothing has been rated. Five hollow stars beside "0.0"
   reads as a product people rated badly, which is a worse lie than the seeded
   4.9 this replaced. Muted and italic so it reads as an absence rather than a
   value — and it says so in words, not by colour alone. */
.stars-none { font-size: var(--fs-xs); font-style: italic; color: var(--text-muted); }
.pc-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; padding-top: 6px; }
.price { font-family: "Montserrat",sans-serif; font-weight: 700; font-size: var(--fs-xl); color: var(--text); }
.price .cur { font-size: var(--fs-sm); color: var(--text-muted); margin-right: 1px; }
.stock-pill { font-size: var(--fs-2xs); font-weight: 700; }
.stock-ok   { color: var(--ok); }
.stock-warn { color: var(--warn); }
.stock-crit { color: var(--crit); }
.stock-out  { color: var(--out); }
.pc-add { display: flex; gap: 8px; align-items: center; }
.btn-add { padding: 10px 14px; font-size: var(--fs-sm); }
/* Names the reason the stepper stops where it does. Only rendered when the
   shelf is what is capping it, so it never appears as unexplained fine print
   on a fully-stocked product. */
.qty-cap { display: block; margin-top: 6px; font-size: var(--fs-2xs); color: var(--text-muted); }

/* =================================================================
   12. ABOUT — always-dark cinematic section
   ================================================================= */
.about-section {
  position: relative; overflow: hidden;
  background: var(--ink); /* always dark */
  padding-block: clamp(80px,11vw,140px);
}
.about-cinema-bg {
  position: absolute; inset: 0; pointer-events: none;
  display: flex; flex-direction: column; justify-content: center; overflow: hidden;
}
.cinema-word {
  font-family: "Playfair Display SC",serif;
  font-size: clamp(8rem,20vw,210px); font-weight: 700; line-height: .82;
  color: var(--gold); opacity: .04;
  display: block; padding-inline: clamp(18px,5vw,48px);
  user-select: none;
}
.cinema-word.right { text-align: right; }

.about-grid {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(40px,6vw,80px); align-items: center;
}

/* Jar card */
.about-jar-card {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 48px 32px;
  background: rgba(255,255,255,.03); border: 1px solid rgba(232,163,23,.15);
  border-radius: var(--r-xl);
  box-shadow: 0 8px 32px rgba(0,0,0,.4);
  position: relative;
}
.jar-svg { width: 120px; height: 160px; margin-bottom: 20px; }

/* About card as location map */
.about-jar-card.about-map-card {
  padding: 0; overflow: hidden;
  height: clamp(300px,30vw,400px);
}
.about-map {
  position: absolute; inset: 0;
  width: 100%; height: 100%; border: 0;
  filter: saturate(.85) contrast(1.02);
}
.about-map-tag {
  position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: var(--r-pill);
  background: rgba(13,11,8,.85); border: 1px solid rgba(232,163,23,.3);
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: .04em;
  color: var(--cream); white-space: nowrap;
  pointer-events: none;
}
.about-map-tag svg { color: var(--gold); flex: none; }
.jar-card-label { text-align: center; }
.jar-brand {
  display: block;
  font-family: "Playfair Display SC",serif; font-size: var(--fs-xl); font-weight: 700;
  color: var(--cream); margin-bottom: 4px;
}
.jar-sub {
  font-family: "Montserrat",sans-serif; font-size: var(--fs-3xs); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: rgba(232,163,23,.6);
}
.about-est-tag {
  margin-top: 20px;
  font-family: "Montserrat",sans-serif; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgba(232,163,23,.45); text-align: center;
}
.about-certs-row {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 14px;
}
.about-certs-row .cert {
  display: flex; align-items: center; gap: 6px;
}
.about-certs-row .cert .ring {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 50%;
  border: 1.5px solid rgba(232,163,23,.5);
  font-family: "Montserrat",sans-serif; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  color: #e8a317; /* hardcoded — always dark bg */
  flex-shrink: 0;
}
.about-certs-row .cert small {
  font-size: var(--fs-xs); color: rgba(242,232,208,.6); /* hardcoded cream — always dark bg */
  line-height: 1.3; max-width: 110px;
}

/* About content (right side, on dark) */
.about-content { display: flex; flex-direction: column; }
.about-h2 {
  font-size: clamp(2rem,4vw,3.2rem); color: var(--cream);
  margin: 8px 0 0;
}
.about-h2 em { font-style: italic; color: var(--gold); }
.about-p {
  color: rgba(242,232,208,.6); font-size: var(--fs-md); line-height: 1.78; margin-top: 16px;
}

.value-list { display: flex; flex-direction: column; gap: 18px; margin-top: 28px; }
.value-row { display: flex; gap: 16px; align-items: flex-start; }
.value-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--gold);
  flex-shrink: 0; margin-top: 7px;
  box-shadow: 0 0 8px rgba(232,163,23,.5);
}
.value-row strong { display: block; color: var(--cream); font-weight: 700; margin-bottom: 3px; }
.value-row p { font-size: var(--fs-base); color: rgba(242,232,208,.5); }

/* =================================================================
   12b. VISION & MISSION
   ================================================================= */
.vm-section { background: var(--bg); }

.section-head-left { text-align: left; margin-inline: 0; max-width: 640px; }
/* leading dash variant — "— ABOUT US" */
.section-head-left .eyebrow { padding-bottom: 0; padding-left: 36px; }
.section-head-left .eyebrow::after {
  bottom: auto; top: 50%; transform: translateY(-50%); left: 0;
}

.vm-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(18px,3vw,28px);
  margin-top: clamp(28px,4vw,44px);
}
.vm-card {
  position: relative; overflow: hidden;
  padding: clamp(24px,3.5vw,36px);
  background: var(--surface); border: 1px solid var(--border-lift);
  border-radius: var(--r-xl);
}
.vm-card::after {
  content: ""; position: absolute; right: -48px; bottom: -64px;
  width: 180px; height: 180px; border-radius: 50%;
  border: 22px solid var(--gold-dim);
  pointer-events: none;
}
.vm-card-vision {
  background: linear-gradient(135deg, var(--red) 0%, var(--red-deep) 100%);
  border-color: transparent;
  box-shadow: 0 12px 32px rgba(176,30,30,.28);
}
.vm-card-vision::after { border-color: rgba(255,255,255,.08); }
.vm-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.vm-icon {
  flex: none; width: 26px; height: 26px; display: grid; place-items: center;
  color: var(--red);
}
.vm-icon svg { width: 24px; height: 24px; }
.vm-head h3 {
  font-size: clamp(1.2rem,2vw,1.45rem); font-weight: 700; color: var(--text);
}
.vm-card p {
  position: relative; z-index: 1;
  font-size: var(--fs-md); line-height: 1.75; color: var(--text-muted);
}
.vm-card-vision .vm-icon,
.vm-card-vision .vm-head h3 { color: #fff; }
.vm-card-vision p { color: rgba(255,255,255,.85); }

/* =================================================================
   13. FAQ + CONTACT (combined, matches About styling)
   ================================================================= */
.faq-section { background: var(--bg); padding-top: 0; }

.faq-contact-grid {
  display: grid; grid-template-columns: 1.35fr 1fr;
  gap: clamp(28px,5vw,56px); align-items: start;
}
.fc-title {
  font-size: clamp(1.3rem,2.2vw,1.6rem); font-weight: 700;
  color: var(--text); margin-bottom: 20px;
}

.faq-list { display: flex; flex-direction: column; gap: 10px; }
.faq-item {
  border: 1px solid var(--border-lift); border-radius: var(--r-md);
  background: var(--surface); overflow: hidden;
  transition: border-color var(--t), box-shadow var(--t);
}
.faq-item.open { border-color: var(--gold-line); box-shadow: 0 4px 16px var(--gold-dim); }
.faq-q {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 20px; text-align: left; font-weight: 600; font-size: var(--fs-md); cursor: pointer;
}
.faq-q:hover { color: var(--red); }
.faq-q .chev { flex: none; width: 20px; height: 20px; transition: transform var(--t) var(--ease); color: var(--red); }
.faq-item.open .chev { transform: rotate(45deg); }
.faq-a { max-height: 0; overflow: hidden; transition: max-height var(--t-slow) var(--ease); }
.faq-a .inner { padding: 0 20px 20px; color: var(--text-muted); font-size: var(--fs-base); }

/* =================================================================
   14. CONTACT — "Get in touch" card
   ================================================================= */
.git-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-xl); padding: clamp(24px,3.5vw,36px);
  box-shadow: var(--shadow-md);
  display: flex; flex-direction: column; gap: 20px;
  position: sticky; top: calc(var(--nav-h) + 24px);
}
.git-card .fc-title { margin-bottom: 0; }
.git-item { display: flex; gap: 13px; align-items: flex-start; }
.git-icon {
  flex: none; width: 22px; height: 22px; margin-top: 2px;
  color: var(--red); display: grid; place-items: center;
}
.git-icon svg { width: 20px; height: 20px; }
.git-item b { display: block; font-size: var(--fs-base); margin-bottom: 3px; color: var(--text); }
.git-item span, .git-item a { font-size: var(--fs-base); color: var(--text-muted); line-height: 1.55; }
.git-item a:hover { color: var(--red); }

.btn-fb {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  margin-top: 4px; padding: 13px 22px; border-radius: var(--r-pill);
  background: #1877f2; color: #fff;
  font-family: "Montserrat",sans-serif; font-size: var(--fs-base); font-weight: 700;
  transition: background var(--t), transform var(--t), box-shadow var(--t);
  align-self: flex-start;
}
.btn-fb svg { width: 18px; height: 18px; }
.btn-fb:hover {
  background: #1466cf; transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(24,119,242,.32);
}

/* =================================================================
   15. FOOTER
   ================================================================= */
.footer {
  background: var(--ink); /* always dark */
  padding-block: clamp(52px,7vw,80px) 32px;
  border-top: 1px solid rgba(232,163,23,.08);
}
.footer-grid {
  display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: 36px;
  padding-bottom: clamp(36px,5vw,56px);
}
.brand-footer .name { color: rgba(255,255,255,.88); }
.brand-footer .name small { color: var(--gold); }
.footer-motto { font-size: var(--fs-base); color: rgba(255,255,255,.36); line-height: 1.72; margin: 14px 0 18px; max-width: 34ch; }
.footer h5 {
  font-family: "Montserrat",sans-serif; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: rgba(255,255,255,.28); margin-bottom: 16px;
}
.footer-links a {
  display: block; padding: 5px 0; font-size: var(--fs-base);
  color: rgba(255,255,255,.44);
  transition: color var(--t), transform var(--t);
}
.footer-links a:hover { color: var(--gold); transform: translateX(4px); }

/* The footer's Facebook / Instagram / Email icons are gone, and their .socials
   rules with them. All three were href="#" — links that went nowhere, wired to
   nothing. The real, administrator-editable contact details (including the
   Facebook page) are in the About Us contact card, which reads site_content and
   is untouched. The motto is now the brand column's last element, so the
   bottom margin that used to space the icons is dropped with them. */
.footer-motto:last-child { margin-bottom: 0; }

.foot-cert { display: flex; gap: 8px; flex-wrap: wrap; }
.foot-cert span {
  font-size: var(--fs-2xs); font-weight: 700;
  color: rgba(255,255,255,.38); border: 1px solid rgba(255,255,255,.1);
  padding: 5px 9px; border-radius: var(--r-sm);
}
.footer-bottom {
  border-top: 1px solid rgba(232,163,23,.08);
  padding-top: 22px;
  display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  font-size: var(--fs-sm); color: rgba(255,255,255,.22);
}

/* =================================================================
   16. CART DRAWER
   ================================================================= */
.scrim { position:fixed;inset:0;background:rgba(20,8,6,.55);backdrop-filter:blur(3px);opacity:0;visibility:hidden;transition:opacity var(--t),visibility var(--t);z-index:var(--z-drawer); }
.scrim.open { opacity:1;visibility:visible; }
.drawer {
  position:fixed;top:0;right:0;height:100%;width:min(420px,100%);
  z-index:calc(var(--z-drawer) + 1);
  background:var(--bg);box-shadow:var(--shadow-ink);
  transform:translateX(100%);transition:transform var(--t-slow) var(--ease);
  display:flex;flex-direction:column;
}
.drawer.open { transform:translateX(0); }
.drawer-head { display:flex;align-items:center;justify-content:space-between;padding:20px 22px;border-bottom:1px solid var(--border); }
.drawer-head h3 { font-size: var(--fs-3xl); }
.drawer-body { flex:1;overflow-y:auto;padding:18px 22px;display:flex;flex-direction:column;gap:14px; }
.drawer-foot { padding:20px 22px;border-top:1px solid var(--border);background:var(--surface); }
.cart-line { display:flex;gap:13px;align-items:center; }
.cart-line .thumb { width:62px;height:62px;border-radius:var(--r-md);background:linear-gradient(160deg,var(--bg-tint),var(--surface-2));display:flex;align-items:center;justify-content:center;flex:none;overflow:hidden; }
/* The thumb is a fixed 62x62 box with overflow:hidden, and .img-holder has no
   intrinsic size of its own — .pc-media and .pd-media each give it one, and
   nothing gave it one here. So the <img> inside (width:100%/height:100% of its
   parent, from .img-holder.has-photo img) had nothing to be 100% OF and
   collapsed. Sized here so a real photo fills the square.

   flex-direction:column keeps the placeholder branch stacking icon over label
   exactly as it did when the holder was a plain block. */
.cart-line .thumb .img-holder { width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px; }
.cart-line .thumb .ph-icon { width:26px;height:26px;color:var(--text-muted);opacity:.35; }
.cart-line .cl-info { flex:1;min-width:0; }
.cart-line .cl-info b { font-family:"Cormorant Garamond",serif;font-size: var(--fs-lg);font-weight:600;display:block;line-height:1.1; }
.cart-line .cl-info .cl-price { font-size: var(--fs-sm);color:var(--text-muted); }
.cart-line .stepper { transform:scale(.85);transform-origin:left; }
.cl-remove { color:var(--text-muted);padding:6px;border-radius:8px;cursor:pointer; }
/* The only svg sizing rule in this stylesheet is `.btn svg`, and .cl-remove is
   not a .btn. There is no global svg rule either, so the trash icon inside it
   computed to 0x0 — measured in the browser, not guessed — and the remove
   control was an invisible 12px of padding that happened to be clickable. */
.cl-remove svg { width:18px;height:18px;display:block;flex:none; }
.cl-remove:hover { color:var(--out);background:var(--bg-tint); }
.cart-empty { text-align:center;color:var(--text-muted);padding:48px 16px;display:flex;flex-direction:column;align-items:center;gap:14px; }
.cart-empty svg { width:60px;height:60px;opacity:.35; }
.summary-row { display:flex;justify-content:space-between;font-size: var(--fs-base);margin-bottom:8px;color:var(--text-muted); }
.summary-row.total { font-size: var(--fs-xl);font-weight:700;color:var(--text);margin:12px 0 16px;padding-top:12px;border-top:1px dashed var(--border); }

/* =================================================================
   17. MODAL
   ================================================================= */
.modal-scrim { position:fixed;inset:0;background:rgba(20,8,6,.6);backdrop-filter:blur(4px);opacity:0;visibility:hidden;transition:opacity var(--t),visibility var(--t);z-index:var(--z-modal);display:grid;place-items:center;padding:20px;overflow-y:auto; }
.modal-scrim.open { opacity:1;visibility:visible; }
.modal { background:var(--bg);border:1px solid var(--border-lift);border-radius:var(--r-xl);width:100%;max-width:560px;max-height:92vh;overflow-y:auto;box-shadow:var(--shadow-lg);transform:translateY(24px) scale(.96);opacity:0;transition:transform var(--t-slow) var(--ease),opacity var(--t) var(--ease);margin:auto; }
.modal-scrim.open .modal { transform:translateY(0) scale(1);opacity:1; }
.modal.wide { max-width:720px; }
.modal-head { display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding:24px 26px 0; }
.modal-head h3 { font-size:1.85rem; }
.modal-close { flex:none;width:38px;height:38px;border-radius:var(--r-pill);display:grid;place-items:center;color:var(--text-muted);cursor:pointer; }
.modal-close:hover { background:var(--bg-tint);color:var(--red); }
.modal-body { padding:18px 26px 26px; }

.pd-grid { display:grid;grid-template-columns:1fr 1fr;gap:22px;align-items:start; }
.pd-media { border-radius:var(--r-md);background:linear-gradient(160deg,var(--bg-tint),var(--surface-2));display:flex;align-items:center;justify-content:center;aspect-ratio:1;overflow:hidden; }
.pd-media .img-holder { width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px; }
.pd-media .ph-icon { width:64px;height:64px;color:var(--text-muted);opacity:.3; }
.pd-media .ph-label { font-size: var(--fs-xs);font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);opacity:.5; }
.pd-info h3 { font-size:1.95rem;margin-bottom:4px; }
.pd-info .pd-desc { color:var(--text-muted);font-size: var(--fs-base);margin:12px 0; }
.pd-nutri { font-size: var(--fs-sm);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r-sm);padding:10px 13px;color:var(--text-muted);margin:12px 0; }
.pd-price { font-size:1.65rem;font-weight:700;font-family:"Montserrat";margin:10px 0; }
.pd-actions { display:flex;gap:12px;align-items:center;margin-top:16px;flex-wrap:wrap; }
.auth-cart-hint { display:flex;align-items:center;gap:10px;background:color-mix(in srgb,var(--red) 7%,var(--bg));border:1px solid color-mix(in srgb,var(--red) 20%,var(--border));border-radius:var(--r-md);padding:12px 15px;margin-bottom:18px;font-size: var(--fs-base);font-weight:500; }
.auth-cart-hint svg { flex-shrink:0;color:var(--red); }

/* =================================================================
   SIGN-IN LOCKOUT NOTICE
   -----------------------------------------------------------------
   Sits above the fields rather than under one of them, because it is
   not about a field: neither the email nor the password is wrong, and
   attaching it to either would be the same misdirection the old
   "Email or password is incorrect" caused.

   The WORD carries it — "Too many failed sign-in attempts" — and the
   tint only reinforces. --warn rather than --red: a wait is not a
   rejection, and painting it as an error invites people to keep
   retrying the thing that is already correct.
   ================================================================= */
.auth-lock {
  margin-bottom: 14px;
  padding: 11px 14px;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--border));
  background: color-mix(in srgb, var(--warn) 8%, var(--surface));
  color: var(--text);
  font-size: var(--fs-base);
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}


/* =================================================================
   PRODUCT REVIEWS — the list under the product detail
   -----------------------------------------------------------------
   Separated from the two-column .pd-grid by a rule rather than by a
   gap: the reviews are a different kind of thing from the buy panel
   and a shopper scrolling past should be able to see where one ends.

   Every colour here is an existing token. The verified badge does NOT
   rely on green alone to say "verified" — it carries the word and a
   tick, because a coloured pill is unreadable to plenty of people and
   invisible to anyone reading it aloud.
   ================================================================= */
.pd-reviews { margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--border); }
.pd-rev-title { font-family: "Cormorant Garamond", serif; font-size: var(--fs-2xl); font-weight: 600; margin-bottom: 12px; }
.pd-rev-empty { font-size: var(--fs-base); color: var(--text-muted); line-height: 1.55; max-width: 62ch; }

.pd-rev-head { display: flex; gap: 26px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
.pd-rev-avg { display: flex; align-items: center; gap: 9px; }
/* color IS SET EXPLICITLY here and on .rev-body rather than inherited.
   `body` carries `transition: color`, and a transition does not advance while
   the tab is in the background — so a theme switched there leaves body frozen
   at the previous theme's text colour, and anything inheriting from it renders
   at ~1:1 against the new background until the tab is looked at. Every other
   component in this file already states its own colour, which is why the
   problem has never shown; these two were the exception. */
.pd-rev-num { font-family: "Montserrat", sans-serif; font-size: 2rem; font-weight: 700; line-height: 1; color: var(--text); }
.pd-rev-count { font-size: var(--fs-sm); color: var(--text-muted); }

/* The 1-5 histogram. Fixed column widths so the bars share a baseline
   and the shape of the distribution is readable at a glance. */
.rev-spread { display: grid; gap: 3px; min-width: 190px; flex: 1 1 190px; }
.rev-spread-row { display: grid; grid-template-columns: 34px 1fr 26px; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--text-muted); }
.rev-spread-n { display: inline-flex; align-items: center; gap: 2px; color: var(--gold); font-weight: 600; }
.rev-spread-n svg { width: 11px; height: 11px; }
.rev-spread-bar { height: 6px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--border); overflow: hidden; }
.rev-spread-bar i { display: block; height: 100%; background: var(--gold); }
.rev-spread-c { text-align: right; font-variant-numeric: tabular-nums; }

.rev-list { list-style: none; display: grid; gap: 14px; }
.rev-item { padding: 13px 15px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-sm); }
.rev-top { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; font-size: var(--fs-xs); color: var(--text-muted); }
.rev-author { font-weight: 700; color: var(--text); }
.rev-date { margin-left: auto; }
.rev-body { margin-top: 7px; font-size: var(--fs-base); line-height: 1.6; color: var(--text); }

/* THE WORD CARRIES THE MEANING, the colour only reinforces it.

   THE LABEL IS --text, NOT --ok. Measured: --ok (#18a957) on the light
   --surface-2 is 2.77:1, which fails AA badly for text this small, and it is
   small precisely because it is a badge. Green on the TICK still reads as
   "good" at a glance while the word itself stays legible — the same fix the
   portal notification chip needed for the same reason. */
.rev-verified { display: inline-flex; align-items: center; gap: 3px; font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text); }
/* Darkened toward --text: bare --ok measures 2.77:1 on the light --surface-2,
   under the 3:1 WCAG asks of a meaningful non-text graphic. Still reads green. */
.rev-verified svg { width: 12px; height: 12px; color: color-mix(in srgb, var(--ok) 76%, var(--text)); }

.pd-rev-more { margin-top: 10px; font-size: var(--fs-sm); color: var(--text-muted); }

/* The customer's own review when it is NOT live. Bordered rather than
   filled so it reads as a note about their submission, not as another
   review in the list. */
.rev-mine { margin-top: 14px; padding: 12px 15px; border-radius: var(--r-sm); font-size: var(--fs-base); line-height: 1.55; border: 1px solid var(--border); background: var(--surface-2); }
.rev-mine b { display: block; margin-bottom: 3px; color: var(--text); }
.rev-mine-pending  { border-color: color-mix(in srgb, var(--warn) 34%, var(--border)); background: color-mix(in srgb, var(--warn) 7%, var(--surface-2)); }
.rev-mine-rejected { border-color: color-mix(in srgb, var(--red) 34%, var(--border));  background: color-mix(in srgb, var(--red) 7%, var(--surface-2)); }

@media (max-width: 640px) {
  .pd-rev-head { gap: 14px; }
  .rev-date { margin-left: 0; width: 100%; }
}


/* =================================================================
   18. AUTH MODAL — split panel
   ================================================================= */
/* NO TRANSITION ON max-width, deliberately. Create Account is wider than Sign
   In, and animating between them looked right until you notice the modal has
   no way to tell "the person switched tabs" from "the modal just opened on
   Create Account" — so it wobbled from 720 to 920 every single time it was
   opened. The width change on a tab switch is instant instead. */
#modal.is-auth { padding:0;overflow:hidden; }
#modal.is-auth .modal-head { position:absolute;top:0;right:0;z-index:10;border:none;background:transparent;padding:8px 10px; }
#modal.is-auth .modal-head h3 { display:none; }
#modal.is-auth #modal-close { color:rgba(255,255,255,.7);border-radius:var(--r-pill); }
#modal.is-auth #modal-close:hover { background:rgba(0,0,0,.2);color:#fff; }
#modal.is-auth .modal-body { padding:0; }

.auth-split { display:grid;grid-template-columns:1fr 1fr;min-height:540px;border-radius:var(--r-lg);overflow:hidden; }

/* CREATE ACCOUNT NEEDS MORE ROOM THAN SIGN IN, because it now carries an
   address. Only the register panel, so signing in does not get a modal sized
   for a form it is not showing.

   THE WIDTH IS DERIVED, NOT PICKED. Region beside Province and City beside
   Barangay means two triggers on a row, and a trigger has to hold "Choose a
   barangay" (130px) plus the 44px icon well, the arrow and its padding — 208px
   of chrome and text, so ~460px of picker. Add this panel's 32px padding each
   side and the 15px its own scrollbar takes, and the form column has to be
   ~540px. At a .8/1.2 split that is a 920px modal.

   Narrower screens need no special case: the picker measures ITSELF (see the
   @container rules in the address-picker section) and drops to one field per
   row the moment the column it is in falls under 460px, whatever the modal
   had to shrink to. */
#modal.is-auth:has(#ap-register.active) { max-width: 920px; }
#modal.is-auth:has(#ap-register.active) .auth-split { grid-template-columns: .8fr 1.2fr; }
.auth-brand {
  position:relative;
  background:linear-gradient(150deg,#161209 0%,#0D0B08 55%,#1E1A0E 100%);
  padding:44px 36px;display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--cream);
}
.auth-brand::before {
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:radial-gradient(rgba(232,163,23,.07) 1px,transparent 1px);
  background-size:22px 22px;
}
.auth-brand::after {
  content:"";position:absolute;right:-70px;bottom:-90px;
  width:240px;height:240px;border-radius:50%;
  border:26px solid rgba(232,163,23,.08);pointer-events:none;
}
.auth-orb { position:absolute;border-radius:50%;pointer-events:none; }
.auth-orb-1 { width:300px;height:300px;top:-80px;right:-60px;background:radial-gradient(circle,rgba(232,163,23,.14),transparent 70%);filter:blur(30px); }
.auth-orb-2 { width:220px;height:220px;bottom:-50px;left:-40px;background:radial-gradient(circle,rgba(214,40,40,.14),transparent 70%);filter:blur(24px); }
.auth-brand-inner { position:relative;z-index:1; }
.auth-logo-row { display:flex;align-items:center;gap:12px;margin-bottom:34px; }
.auth-fish-icon { width:36px;height:36px;flex-shrink:0; }
.auth-brand-name { display:block;font-family:"Playfair Display SC",serif;font-size: var(--fs-lg);font-weight:700;color:#F2E8D0; }
.auth-brand-sub  { display:block;font-size: var(--fs-4xs);font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:rgba(232,163,23,.6);margin-top:2px; }
.auth-headline   { font-family:"Playfair Display SC",serif;font-size:clamp(1.55rem,2.5vw,2.1rem);font-weight:700;line-height:1.2;color:#F2E8D0;margin:0 0 14px; }
.auth-headline em { font-style:italic;color:#e8a317; }
.auth-tagline    { font-size: var(--fs-base);color:rgba(242,232,208,.62);line-height:1.7;margin-bottom:30px; }
.auth-trust-list { list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px;align-items:flex-start; }
.auth-trust-list li {
  display:flex;align-items:center;gap:10px;font-size: var(--fs-sm);color:rgba(242,232,208,.88);
  background:rgba(232,163,23,.08);border:1px solid rgba(232,163,23,.2);
  padding:8px 16px 8px 12px;border-radius:var(--r-pill);
  backdrop-filter:blur(4px);
}
.auth-trust-dot { width:7px;height:7px;border-radius:50%;background:var(--gold);flex-shrink:0;box-shadow:0 0 6px rgba(232,163,23,.6); }
/* 56px of head room, not 36. The close button is absolutely positioned over
   this panel's top-right corner and is 36px tall from 8px down, so at 36px of
   padding the tab row started 8px INSIDE it — "Create Account" ran under the ×
   in the corner. The padding now clears the button with room to spare. */
.auth-form-panel { background:var(--bg);padding:56px 32px 32px;display:flex;flex-direction:column;overflow-y:auto;max-height:600px; }
.auth-tabs { display:flex;position:relative;background:var(--surface-2);border-radius:var(--r-pill);padding:4px;gap:0;margin-bottom:22px; }
.auth-tab  { flex:1;padding:9px 14px;font-size: var(--fs-sm);font-weight:600;font-family:"Montserrat",sans-serif;border-radius:var(--r-pill);color:var(--text-muted);cursor:pointer;border:none;background:transparent;transition:color .2s;position:relative;z-index:1; }
.auth-tab.active { color:var(--red); }
/* THE PILL POSITIONS ITSELF. IT USED TO BE MEASURED, AND THE MEASUREMENT WAS
   TAKEN WHILE THE MODAL WAS STILL ANIMATING.

   moveSlide() read getBoundingClientRect() on the active tab and wrote the
   result into left/width. The modal opens with a `transform: scale(.96)`, and
   getBoundingClientRect returns the TRANSFORMED box — so the pill was given a
   width 4% smaller than the tab and an offset 4% short of it, landing high and
   left of the label it is supposed to sit behind. On a frame where the modal
   had not been laid out at all it measured zero and the pill collapsed to its
   two borders in the corner.

   There is nothing to measure. The two tabs are `flex: 1` inside 4px of
   padding, so each is exactly half the track minus that padding, and CSS can
   say so. No frame timing, no transform to be fooled by, and the same spring
   transition still runs because `left` is what changes. */
.auth-tab-slide  { position:absolute;top:4px;bottom:4px;left:4px;width:calc(50% - 4px);border-radius:var(--r-pill);background:var(--surface);border:1px solid var(--gold-line);box-shadow:0 2px 10px rgba(30,20,8,.1);transition:left .3s cubic-bezier(.34,1.56,.64,1),width .3s cubic-bezier(.34,1.56,.64,1);z-index:0; }
.auth-tabs:has(> .auth-tab:nth-of-type(2).active) .auth-tab-slide { left:50%; }
.auth-panel { display:none; }
.auth-panel.active { display:block;animation:pageIn .26s var(--ease) both; }
.auth-panel-head { margin-bottom:18px; }
.auth-panel-head h3 { font-size: var(--fs-2xl);font-weight:700;color:var(--text);margin:0 0 4px; }
.auth-panel-head p  { font-size: var(--fs-base);color:var(--text-muted);margin:0; }
.auth-field { margin-bottom:13px; }
.auth-field label { display:block;font-size: var(--fs-2xs);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px; }
.auth-input-group { position:relative;display:flex;align-items:center; }
.auth-input-icon { position:absolute;left:13px;pointer-events:none;width:15px;height:15px;color:var(--text-muted);flex-shrink:0;transition:color .2s; }
.auth-input-group:focus-within .auth-input-icon { color:var(--red); }
.auth-input { width:100%;border:1.5px solid var(--border-lift);border-radius:var(--r-md);padding:12px 14px 12px 40px;font-size: var(--fs-base);font-family:inherit;background:var(--surface);color:var(--text);transition:border-color .2s,box-shadow .2s,background .2s; }
.auth-input:hover { border-color:color-mix(in srgb,var(--gold) 45%,var(--border-lift)); }
.auth-input:focus { border-color:var(--gold);box-shadow:0 0 0 3px var(--gold-dim);outline:none; }
.auth-input-pw { padding-right:44px; }
select.auth-input {
  appearance:none; -webkit-appearance:none; cursor:pointer; padding-right:36px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B5E48' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 13px center; background-size:14px;
}
.auth-textarea { resize:vertical;min-height:64px; }
.auth-input-group-ta { align-items:flex-start; }
.auth-icon-ta { top:12px; }
.auth-eye-btn { position:absolute;right:12px;width:28px;height:28px;display:grid;place-items:center;border:none;background:transparent;color:var(--text-muted);cursor:pointer;border-radius:var(--r-sm);transition:color .2s; }
.auth-eye-btn:hover { color:var(--red); }
.auth-eye-btn svg { width:15px;height:15px; }
.auth-strength-wrap { height:4px;border-radius:99px;background:var(--border);margin-top:7px;overflow:hidden; }
.auth-strength-wrap i { display:block;height:100%;width:0;border-radius:99px;transition:width var(--t),background var(--t); }
.auth-row { display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:15px; }
.auth-row .auth-remember { margin-bottom:0; }
.auth-forgot { border:none;background:none;padding:0;font-size: var(--fs-sm);font-weight:600;color:var(--red);cursor:pointer;transition:color .2s; }
.auth-forgot:hover { text-decoration:underline; }
.auth-remember { display:flex;align-items:center;gap:8px;font-size: var(--fs-sm);color:var(--text-muted);margin-bottom:15px;cursor:pointer; }
.auth-remember input { width:16px;height:16px;accent-color:var(--red); }
.auth-submit { width:100%;padding:14px;font-size: var(--fs-base);font-weight:700;font-family:"Montserrat",sans-serif;letter-spacing:.06em;text-transform:uppercase;border-radius:var(--r-pill);border:none;cursor:pointer;background:linear-gradient(90deg,var(--gold) 0%,#c9880f 100%);color:#1e1a0e;position:relative;overflow:hidden;transition:opacity .2s,transform .15s,box-shadow .2s;box-shadow:0 4px 16px rgba(232,163,23,.35);display:flex;align-items:center;justify-content:center;gap:9px; }
.auth-submit svg { width:16px;height:16px;transition:transform .2s var(--ease); }
.auth-submit:hover svg { transform:translateX(3px); }
.auth-submit::after { content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,.16),transparent);transform:translateX(-100%);transition:transform .5s; }
.auth-submit:hover { opacity:.92;transform:translateY(-1px); }
.auth-submit:hover::after { transform:translateX(100%); }
.auth-field .field-error { font-size: var(--fs-xs);color:var(--crit);margin-top:4px;display:block;min-height:1em; }
/* The address group inside Create Account (and the retailer form's business
   address). A real <fieldset> so the six fields are announced as one group,
   with the browser's default border and padding removed — it is a grouping,
   not a box, and a boxed panel in the middle of a form reads as a separate
   step. The legend takes the auth label's styling one size up, so it reads as
   the heading of the fields beneath it rather than as a seventh label. */
.auth-addr { border:0; padding:0; margin:0 0 4px; min-width:0; }
.auth-addr-legend { padding:0; margin-bottom:10px; font-size: var(--fs-xs); font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--text); }
.auth-addr-legend span { text-transform:none; letter-spacing:0; font-weight:500; color:var(--text-muted); }
.auth-switch button { color:var(--red);font-weight:700;cursor:pointer; }
.auth-switch button:hover { text-decoration:underline; }
.strength-label { font-size: var(--fs-xs);margin-top:5px;font-weight:600; }

/* =================================================================
   19. CHECKOUT & RECEIPT
   ================================================================= */
/* Section rhythm. Every section used to be 22px from the next and nothing
   else, so six of them read as one long strip of controls with eyebrows
   scattered through it. A rule between them and a wider gap gives the form
   the same sectioned feel the rest of the storefront has, and the internal
   spacing is now the section's job rather than each field's. */
.co-section { padding-bottom:24px; margin-bottom:24px; border-bottom:1px solid var(--border); }
/* :last-of-type does not work here — .co-footer is a div too, so the last
   .co-section is never the last div among its siblings. Matching on what
   follows it is what actually identifies it, and without this the section rule
   and the footer's own border-top stack into a double line. */
.co-section:has(+ .co-footer) { padding-bottom:0; margin-bottom:0; border-bottom:none; }
.co-section > .co-title { font-family:"Montserrat";font-weight:700;font-size: var(--fs-sm);letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted);margin-bottom:12px; }
.co-section > .co-title::after {
  content:""; display:block; width:22px; height:2px; margin-top:6px;
  background:var(--gold); border-radius:2px;
}
.co-section .field:last-child { margin-bottom:0; }
/* The delivery address inside Order Type. It used to be one field carrying
   `style="margin-top:14px"`; it is now a six-field group, which wants its own
   heading so it reads as one thing rather than six unrelated boxes under
   the Delivery / Pickup toggle. Smaller than .co-title — it is a part of
   that section, not a section of its own. */
.co-address { margin-top:16px; }
.co-address .co-subtitle { font-size: var(--fs-sm); font-weight:700; letter-spacing:.02em; color:var(--text); margin-bottom:10px; }
.toggle-group { display:flex;gap:10px; }
.toggle-group .tg { flex:1;padding:14px;border:1.6px solid var(--border-lift);border-radius:var(--r-md);text-align:center;font-weight:600;font-size: var(--fs-base);transition:all var(--t);display:flex;flex-direction:column;gap:4px;align-items:center;cursor:pointer; }
.toggle-group .tg small { font-weight:500;color:var(--text-muted);font-size: var(--fs-xs); }
.toggle-group .tg:hover { border-color:var(--gold); }
.toggle-group .tg.active { border-color:var(--gold);background:color-mix(in srgb,var(--gold) 8%,var(--bg));color:var(--text); }
/* The summary carries the most weight on the form — it is the only part the
   shopper cannot change from here, and the part they are agreeing to. Gold
   hairline and a lifted surface rather than the flat grey box it was.

   Three columns: what it is, how many at what price, what that comes to. The
   middle column is the one the old two-column layout left the reader to work
   out by dividing. */
.co-summary {
  background:var(--surface); border:1px solid var(--gold-line);
  border-radius:var(--r-md); padding:16px 18px; box-shadow:var(--shadow-sm);
}
.co-summary .li {
  display:grid; grid-template-columns:minmax(0,1fr) auto auto;
  align-items:baseline; gap:6px 14px;
  font-size: var(--fs-base); padding:6px 0;
}
.co-summary .li + .li { border-top:1px solid var(--border); }
.co-summary .li-name { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text); }
.co-summary .li-qty  { font-size: var(--fs-sm); color:var(--text-muted); font-variant-numeric:tabular-nums; }
.co-summary .li-amt  { font-family:"Montserrat",sans-serif; font-weight:600; font-variant-numeric:tabular-nums; text-align:right; }
.co-summary .li.tot {
  font-weight:700; font-size: var(--fs-lg); color:var(--text);
  border-top:1px dashed var(--border-lift); padding-top:11px; margin-top:5px;
}
.co-summary .li.tot .li-qty { font-weight:500; }
.co-summary .li.tot .li-amt { font-size: var(--fs-xl); color:var(--red); }

/* Payment method, as three cards rather than a dropdown. Narrower than the
   two-way Order Type toggle above it, so the labels get less room and the
   sub-line more. */
/* THE METHOD TILES ARE THEIR OWN ROW, AND THE PAYMENT STEP STARTS BELOW THEM.
   Measured before this: the tile row's bottom edge and the QR panel's top edge
   were the same pixel — no margin between two different steps, borders
   touching, which read as the tiles running into the QR. And a retailer's six
   tiles shared one flex row at 96px each, wrapping their sub-lines.

   A three-column grid: the three pay-now methods on the first row, and for a
   retailer the three credit terms on a second row of their own — which is the
   grouping they already had in meaning (pay now vs pay later). The margin is
   the separation between choosing a method and paying by it. */
.toggle-group.co-pay {
  display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:10px;
  margin-bottom:20px;
}
.toggle-group.co-pay .tg { padding:12px 10px; font-size: var(--fs-base); }
.toggle-group.co-pay .tg small { font-size: var(--fs-2xs); line-height:1.25; }
/* Credit terms sit apart from the three immediate methods: they are a retail
   partnership facility, they are only rendered for a retailer, and choosing one
   commits the buyer to a date rather than to a payment now. Gold marks them as
   the account-holder's option without making them louder than the default. */
/* A method this order cannot use. Greyed and inert rather than hidden, with
   its own hint ("Pickup only") saying why — a tile that disappears when the
   customer picks Delivery reads as a bug, and teaches them nothing. Not colour
   alone: the hint text carries the reason, and the button is really disabled,
   so a screen reader announces it. */
.toggle-group.co-pay .tg-unavailable { opacity:.5; cursor:not-allowed; border-style:dashed; }
.toggle-group.co-pay .tg-unavailable:hover { border-color:var(--border-lift); }
.toggle-group.co-pay .tg-unavailable small { color:var(--text-muted); font-style:italic; }
.toggle-group.co-pay .tg-credit { border-color:var(--gold-line); }
.toggle-group.co-pay .tg-credit small { color:var(--gold); font-weight:600; }
.toggle-group.co-pay .tg-credit.active { border-color:var(--gold); background:var(--gold-dim); }

/* The terms a credit order commits to, on the receipt. Set apart from the
   figures above it because it is the only part that describes a future
   obligation rather than what just happened. */
.receipt-box .rb-credit {
  margin-top:12px; padding-top:12px;
  border-top:1px dashed var(--gold-line);
}
.receipt-box .rb-credit b { color:var(--gold); }
.receipt-box .rb-credit-note {
  margin-top:8px; font-size: var(--fs-xs); line-height:1.5; color:var(--text-muted);
}
.receipt-box .rb-credit-note a { color:var(--gold); font-weight:700; text-decoration:underline; }

/* Save to profile. This label carried a five-property inline style attribute
   and a browser-default checkbox — the only control on the form with no
   relationship to anything around it. */
.co-save {
  display:flex; align-items:center; gap:10px;
  margin-top:14px; padding:11px 13px;
  border:1px solid var(--border); border-radius:var(--r-md);
  background:var(--surface-2);
  font-size: var(--fs-base); cursor:pointer;
  transition:border-color var(--t) var(--ease), background var(--t) var(--ease);
}
.co-save:hover { border-color:var(--gold); }
/* Kept in the layer and in the tab order — only the browser's rendering of it
   is replaced. A checkbox removed with display:none is a checkbox no keyboard
   can reach. */
.co-save input { position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }
.co-save .co-save-box {
  flex:none; width:20px; height:20px; border-radius:var(--r-sm);
  border:1.5px solid var(--border-lift); background:var(--surface);
  display:grid; place-items:center;
  color:transparent;
  transition:background var(--t) var(--ease), border-color var(--t) var(--ease), color var(--t) var(--ease);
}
.co-save .co-save-box svg { width:12px; height:12px; display:block; }
.co-save input:checked + .co-save-box { background:var(--gold); border-color:var(--gold); color:#1e1a0e; }
.co-save input:focus-visible + .co-save-box { outline:3px solid var(--gold); outline-offset:2px; }
.co-save .co-save-text { color:var(--text-muted); }
.co-save input:checked ~ .co-save-text { color:var(--text); }

/* The pinned submit.

   .modal is the scroll container (max-height:92vh; overflow-y:auto) and
   .modal-body is an ordinary child of it, so a sticky element inside the body
   sticks to the bottom of the modal's scrollport. That is why this works
   without touching the shared modal markup in seven HTML files.

   The negative inline margins pull it out to the modal's edges so the rule
   above it spans the full width rather than floating inside the body padding;
   the matching padding puts the contents back where they were. */
.co-footer {
  position:sticky; bottom:0; z-index:2;
  display:flex; align-items:center; gap:14px;
  margin:26px -26px -26px; padding:16px 26px;
  border-top:1px solid var(--border);
  background:var(--bg);
}
.co-foot-total { display:flex; flex-direction:column; line-height:1.15; }
.co-foot-total span { font-size: var(--fs-2xs); font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--text-muted); }
.co-foot-total b { font-family:"Montserrat",sans-serif; font-size: var(--fs-xl); font-variant-numeric:tabular-nums; }
.co-submit { flex:1; }
/* Disabled already covers the pointer; .is-busy says the request is in flight
   rather than that the button is unavailable. */
.co-submit.is-busy { opacity:.75; }

/* A field in error, on the input itself and not only in the sentence under it.
   Applied by the submit handler alongside [data-err], removed as soon as the
   shopper edits the field. */
.field.has-error .control { border-color:var(--out); box-shadow:0 0 0 3px color-mix(in srgb, var(--out) 14%, transparent); }
.field.has-error .up-drop { border-color:var(--out); border-style:solid; }

@media (max-width: 560px) {
  /* Three payment cards at 390px are 110px each with a two-word sub-line —
     they wrap rather than squash. Order Type has two and keeps its row. */
  .toggle-group { flex-wrap:wrap; }
  /* One tile per row: the grid above becomes a single column. */
  .toggle-group.co-pay { grid-template-columns:1fr; }
  .toggle-group.co-pay .tg { flex-direction:row; justify-content:space-between; text-align:left; gap:10px; }
  .co-summary .li { grid-template-columns:minmax(0,1fr) auto; }
  .co-summary .li-qty { grid-column:1; grid-row:2; }
  .co-summary .li-amt { grid-column:2; grid-row:1 / span 2; align-self:center; }
  .co-footer { margin-inline:-20px; padding-inline:20px; }
}
/* =================================================================
   UPLOAD FIELD — the payment screenshot on checkout
   -----------------------------------------------------------------
   What was here: `<input type="file" class="control">`. The generic form
   class draws a bordered text field, and the browser draws its own grey
   "Choose File" button inside it — two controls in one box, one of them not
   ours and not themeable. Beside it sat a status line whose colour was set
   from JavaScript with inline styles, and an unframed preview image. There
   was no way to remove an attached file at all.

   The native input is still there and still does the work; it is moved out of
   sight and the label drives it, so the picker, keyboard access and form
   semantics are unchanged while the appearance is ours.
   ================================================================= */

/* Not display:none and not visibility:hidden — either takes the input out of
   the tab order, and the only way to the file picker would then be a mouse. */
.up-input { position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }

.up-drop {
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:6px; text-align:center;
  padding:22px 18px;
  border:1.5px dashed var(--border-lift); border-radius:var(--r-md);
  background:var(--surface-2); color:var(--text-muted);
  cursor:pointer; position:relative; overflow:hidden;
  transition:border-color var(--t) var(--ease), background var(--t) var(--ease), color var(--t) var(--ease);
}
.up-drop:hover { border-color:var(--gold); background:var(--gold-dim); color:var(--text); }
/* The ring belongs on the zone, because the input it describes is invisible.
   Sibling selector: the input precedes the label in the markup for exactly
   this reason. */
.up-input:focus-visible + .up-drop { outline:3px solid var(--gold); outline-offset:3px; }

/* display:block matters. As an inline span its width/height are ignored, the
   svg inside has no intrinsic size, and `width:100%` then resolves against
   the zone — measured at 588px, which made the dropzone 653px tall. */
.up-drop .up-ic  { display:block; width:26px; height:26px; color:var(--gold); }
.up-drop .up-ic svg { width:26px; height:26px; display:block; }
.up-drop .up-cta {
  font-family:"Montserrat",sans-serif; font-size: var(--fs-sm); font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; color:var(--text);
}
.up-drop .up-hint { font-size: var(--fs-xs); line-height:1.4; }

/* Drag-over. A dashed border that only changes colour is easy to miss while
   the pointer is carrying a file, so the fill changes too. */
.up-drop.is-over {
  border-style:solid; border-color:var(--gold);
  background:var(--gold-dim); color:var(--text);
}

/* Busy. The old version wrote the word "Uploading…" into a text line, which
   is the one place the shopper is not looking — their eyes are on the zone
   they just dropped a file into. A sweep across the zone itself is where the
   attention already is. Pointer events go off so a second pick cannot start
   a second upload over the top of the first. */
.up-drop.is-busy { pointer-events:none; border-style:solid; border-color:var(--gold); color:var(--text-muted); }
.up-drop.is-busy::after {
  content:""; position:absolute; inset:0;
  background:linear-gradient(90deg, transparent, var(--gold-dim) 45%, var(--gold-line) 50%, var(--gold-dim) 55%, transparent);
  transform:translateX(-100%);
  animation:upSweep 1.15s var(--ease) infinite;
}
@keyframes upSweep { to { transform:translateX(100%); } }

/* The attached state: a framed thumbnail, what the file is, and the two
   controls that were missing entirely. */
.up-card {
  display:flex; align-items:center; gap:12px;
  padding:10px; border:1.5px solid var(--border-lift); border-radius:var(--r-md);
  background:var(--surface);
}
.up-card .up-thumb {
  width:64px; height:64px; flex:none;
  object-fit:cover; border-radius:var(--r-sm);
  border:1px solid var(--border); background:var(--surface-2);
}
.up-card .up-meta { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
/* The server names the stored file with 32 hex characters; this is the name
   off the shopper's own disk, which is the only one they recognise. It can be
   arbitrarily long, hence the truncation. */
.up-card .up-meta b {
  font-size: var(--fs-base); font-weight:700; color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.up-card .up-meta span { font-size: var(--fs-xs); color:var(--text-muted); }
.up-card .up-acts { display:flex; flex-direction:column; gap:6px; flex:none; }
.up-btn {
  padding:6px 12px; border-radius:var(--r-pill);
  border:1.5px solid var(--border-lift); background:var(--surface); color:var(--text);
  font-family:"Montserrat",sans-serif; font-size: var(--fs-2xs); font-weight:700;
  letter-spacing:.06em; text-transform:uppercase;
  transition:border-color var(--t) var(--ease), color var(--t) var(--ease), background var(--t) var(--ease);
}
.up-btn:hover { border-color:var(--gold); color:var(--gold); }
.up-btn-danger:hover { border-color:var(--red); color:var(--red); background:transparent; }

@media (max-width: 480px) {
  /* Side-by-side under the thumbnail rather than a two-row stack squeezed
     against the right edge. */
  .up-card { flex-wrap:wrap; }
  .up-card .up-meta { flex-basis:calc(100% - 76px); }
  .up-card .up-acts { flex-direction:row; width:100%; }
  .up-btn { flex:1; }
}

.note-mock { font-size: var(--fs-xs);color:var(--warn);background:color-mix(in srgb,var(--warn) 10%,transparent);border-radius:var(--r-sm);padding:8px 11px;margin-top:8px; }
.receipt { text-align:center; }

/* The Sales Invoice inside a storefront modal (assets/js/core/invoice.js).
   The invoice is a white paper document in every theme; this frame gives it a
   paper edge against a dark modal and lets a narrow phone scroll it sideways
   rather than squeeze the four columns until the amounts wrap. */
.receipt-invoice {
  margin: 16px 0 14px; border: 1px solid var(--border-lift); border-radius: var(--r-md);
  background: #fff; overflow-x: auto; text-align: left;
  box-shadow: 0 6px 20px rgba(0,0,0,.08);
}
.receipt-invoice .eb-invoice { min-width: 420px; }
.receipt-actions { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; margin-top: 12px; }
.receipt .receipt-actions .btn { min-width: 140px; }
.receipt .check { width:70px;height:70px;border-radius:50%;background:color-mix(in srgb,var(--ok) 14%,transparent);color:var(--ok);display:grid;place-items:center;margin:0 auto 14px;animation:pop .5s var(--ease); }
.receipt-box { text-align:left;background:var(--surface-2);border:1px dashed var(--border-lift);border-radius:var(--r-md);padding:18px;margin:18px 0;font-size: var(--fs-base); }
.receipt-box .rb-row { display:flex;justify-content:space-between;padding:4px 0;gap:10px; }
.receipt-box .rb-items { border-top:1px dashed var(--border);border-bottom:1px dashed var(--border);margin:10px 0;padding:10px 0; }
.receipt-box .txid { font-family:ui-monospace,monospace;font-weight:700;color:var(--gold); }

/* =================================================================
   20. TOAST
   ================================================================= */
.toast-wrap { position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:var(--z-toast);display:flex;flex-direction:column;gap:10px;align-items:center;width:max-content;max-width:92vw; }
.toast { display:flex;align-items:center;gap:11px;padding:13px 20px;border-radius:var(--r-pill);background:var(--ink-card);color:var(--cream);font-size: var(--fs-base);font-weight:600;box-shadow:var(--shadow-ink);transform:translateY(20px);opacity:0;animation:toastIn .34s var(--ease) forwards; }
.toast.out { animation:toastOut .3s var(--ease) forwards; }
.toast .ic { display:grid;place-items:center;width:22px;height:22px;border-radius:50%;flex:none; }
/* The glyph had no size. There is no global `svg` rule in this stylesheet and
   the only other one is `.btn svg`, so a raw <svg viewBox="0 0 24 24"> dropped
   into a 22px grid cell stretched to fill it corner to corner — the check
   survived that because its path is inset, the old cart mark did not.
   12px inside 22px leaves the ring visible as a ring. */
.toast .ic svg { width:12px;height:12px;display:block; }
.toast.success .ic { background:var(--ok);color:#fff; }

/* Non-success carries a dot, not a glyph — see the note in showToast(). The
   well goes transparent and the dot draws itself, haloed so it holds the same
   visual weight as the filled success disc beside it rather than looking like
   a mark that failed to load. */
.toast.info .ic { background:transparent; }
.toast.info .ic::before {
  content:""; width:9px; height:9px; border-radius:50%;
  background:var(--gold); box-shadow:0 0 0 4px var(--gold-dim);
}
.toast .toast-msg { flex:1;min-width:0; }
/* The Undo affordance on a toast that carries one. Gold on the ink card, so it
   reads as the thing to press rather than as part of the sentence. */
.toast-action {
  flex:none; margin-left:4px; padding:5px 12px;
  border-radius:var(--r-pill);
  background:rgba(255,255,255,.14); color:var(--gold);
  font-family:"Montserrat",inherit; font-size: var(--fs-xs); font-weight:700;
  letter-spacing:.08em; text-transform:uppercase;
  transition:background var(--t) var(--ease);
}
.toast-action:hover { background:rgba(255,255,255,.26); }

/* =================================================================
   21. SCROLL REVEAL
   ================================================================= */
.reveal { opacity:0;transform:translateY(32px);transition:opacity .72s var(--ease),transform .72s var(--ease); }
.reveal.in { opacity:1;transform:none; }
.reveal.d1 { transition-delay:.08s; }
.reveal.d2 { transition-delay:.16s; }
.reveal.d3 { transition-delay:.24s; }
.reveal.d4 { transition-delay:.32s; }

/* =================================================================
   22. SHOP PAGE (shared with shop.html)
   ================================================================= */
.search-box { position:relative;flex:1 1 280px;max-width:420px; }
.search-box svg { position:absolute;left:15px;top:50%;transform:translateY(-50%);width:17px;height:17px;color:var(--text-muted); }
.search-box input { width:100%;padding:13px 16px 13px 44px;border-radius:var(--r-pill);border:1.5px solid var(--border-lift);background:var(--surface);color:var(--text);font-family:inherit;font-size: var(--fs-base);transition:border-color var(--t),box-shadow var(--t); }
.search-box input:focus { outline:none;border-color:var(--gold);box-shadow:0 0 0 3px var(--gold-dim); }
.chips { display:flex;gap:8px;flex-wrap:wrap; }
.chip { padding:9px 16px;border-radius:var(--r-pill);font-size: var(--fs-base);font-weight:600;border:1.5px solid var(--border-lift);background:var(--surface);color:var(--text);transition:all var(--t) var(--ease);cursor:pointer; }
.chip:hover { border-color:var(--gold);color:var(--text); }
.chip.active { background:var(--gold);border-color:var(--gold);color:#1e1a0e;box-shadow:0 4px 12px rgba(232,163,23,.28); }
.sort-select { padding:11px 14px;border-radius:var(--r-pill);border:1.5px solid var(--border-lift);background:var(--surface);color:var(--text);font-family:inherit;font-size: var(--fs-base);font-weight:600;cursor:pointer; }
.sort-select:focus { outline:none;border-color:var(--gold);box-shadow:0 0 0 3px var(--gold-dim); }
.product-grid { display:grid;grid-template-columns:repeat(auto-fill,minmax(252px,1fr));gap:22px; }
.no-results { grid-column:1/-1;text-align:center;padding:60px 20px;color:var(--text-muted); }

/* =================================================================
   23. RESPONSIVE
   ================================================================= */
@media (max-width: 960px) {
  .hero-grid { grid-template-columns: 1fr; }
  /* Single column: nothing to overlap, and the panel gets shorter so the
     hero still fits a phone screen without the copy scrolling away. */
  .hero-slider { flex: none; min-height: 0; height: clamp(360px,64vw,500px);
                 --tile-bite: 0px; }   /* strip no longer overhangs the panel */
  .hero-thumbs { width: 100%; }
  .hero-visual { display: block; }
  .bsc-stage { height: 660px; }
  /* Single column makes the hero much taller, so a percentage height
     overshoots the tile strip. Pin the fish to the band above it. */
  .hero-fish-bg { top: 70px; height: 232px; max-width: 84vw; }
  /* Single column: three square tiles across the full width would be ~265px
     tall each and shove the panel off the screen. Go landscape instead. */
  .hero-thumb  { aspect-ratio: 3 / 2; }
  .about-grid { grid-template-columns: 1fr; }
  .about-jar-card { max-width: 340px; margin-inline: auto; }
  .vm-grid { grid-template-columns: 1fr; }
  .faq-contact-grid { grid-template-columns: 1fr; }
  .git-card { position: static; }
  .footer-grid { grid-template-columns: 1.3fr 1fr 1fr; }
}

@media (max-width: 768px) {
  .hero-word { font-size: clamp(3.6rem,15vw,100px); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  :root { --nav-h: 62px; }

  .nav-links {
    position: fixed; top: var(--nav-h); left: 0; right: 0;
    transform: translate(0,-130%);
    flex-direction: column; align-items: stretch;
    background: var(--ink); border: none;
    border-bottom: 1px solid rgba(232,163,23,.15);
    border-radius: 0; padding: 14px 20px;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    box-shadow: var(--shadow-ink);
    transition: transform var(--t-slow) var(--ease);
    z-index: calc(var(--z-nav) - 1);
  }
  .nav-links.open { transform: translate(0,0); }
  /* panel bg is fixed dark ink regardless of theme — force cream text so it stays legible */
  .nav-links a { padding: 14px; font-size: var(--fs-sm); color: var(--cream); }
  .nav-indicator { display: none; }
  #account-slot { display: none; }
  .mob-cart-btn { display: inline-flex; }
  .hamburger    { display: inline-flex; }

  .hero-word { font-size: clamp(2.8rem,13vw,72px); }
  .hero-rule-text { font-size: var(--fs-4xs); padding: 0 12px; }
  .hero-bottom { flex-direction: column; gap: 20px; }
  .hero-ctas .btn { width: 100%; }
  .hero-thumbs { --ht-gap: 8px; }
  .hero-thumb  { border-radius: var(--r-md); }
  /* Taller panel so the stats and tagline aren't stacked on top of the
     product art on a phone. */
  /* Phone: the strip and arrows now cost real height, so the tiles go
     landscape and the panel gives some back — otherwise the hero runs
     well past the fold and the tagline gets cut mid-sentence. */
  .hero-slider { height: clamp(390px,78vw,470px); }
  .hero-thumb  { border-radius: var(--r-md); aspect-ratio: 4 / 3; }
  .hero-thumbs { --ht-gap: 7px; }
  .hero-bottom { gap: 14px; }
  /* Phones leave only ~135px between the navbar and the tiles. */
  .hero-fish-bg { top: 72px; height: 120px; max-width: 88vw; }
  /* The centred placeholder art collides with the stats in a short panel.
     Lift it and drop its caption — real photography fills the frame and is
     unaffected by this rule. */
  .hs-ph { transform: translateY(-16%); }
  .hs-ph .ph-label { display: none; }
  .hs-overlay  { left: 16px; right: 16px; bottom: 16px; }
  .hs-overlay .hero-lead { max-width: none; }
  /* Stats side by side here — a vertical stack costs ~50px of height the
     tagline needs more. */
  .hero-stats {
    flex-direction: row; align-items: flex-end;
    gap: 22px; margin-bottom: 14px;
  }
  .stats-inner { flex-wrap: wrap; gap: 16px; justify-content: center; }
  .stat-rule { display: none; }

  .acc-wrap { height: clamp(220px,55vw,300px); }
  .section-head h2 { font-size: clamp(1.7rem,6vw,2.4rem); }
  /* The card is ~528px tall at this width; the old 420px stage let it
     overflow onto the nav buttons and the section below. Tighten the wheel
     so the neighbours still peek in at the edges of a narrow screen. */
  .bsc-stage { height: 590px; --wheel-origin: 1200px; }
  .bsc-slide { width: 220px; }
  .product-grid { grid-template-columns: 1fr 1fr; gap: 12px; }

  .footer-grid { grid-template-columns: 1fr; }
  .footer-col-brand { padding-bottom: 20px; border-bottom: 1px solid rgba(232,163,23,.08); }
  .drawer { width: 100%; }
  .auth-split { grid-template-columns: 1fr; }
  .auth-brand  { display: none; }
  .auth-form-panel { padding: 28px 22px 24px; max-height: none; }
  #modal.is-auth #modal-close { color: var(--text-muted); }

  .cinema-word { font-size: clamp(4rem,13vw,100px); }
  .btn-fb { align-self: stretch; }
  .pd-grid { grid-template-columns: 1fr; }

  .chips { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
  .chip  { white-space: nowrap; flex: none; }
}

@media (max-width: 380px) {
  .hero-word { font-size: 2.6rem; }
  .product-grid { grid-template-columns: 1fr; }
}

/* =================================================================
   24. REDUCED MOTION
   ================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
  .jar-glow, .jar-glow-2 { display: none; }
  .marquee-track { animation: none; }
  .up-drop.is-busy::after { animation:none; transform:none; opacity:.5; }
  /* transition-duration above makes the hover lift instantaneous rather than
     absent — the button still jumps 2-3px under the pointer, which is the
     movement a reduced-motion preference is asking not to see. */
  .btn-gold:hover, .btn-red:hover, .btn-primary:hover { transform: none; }
}


/* =================================================================
   ADMIN-DRIVEN CONTENT
   Real product/hero photography uploaded from the Landing Page module
   replaces the camera placeholder; the holder keeps its own aspect so
   swapping a photo in never changes card height.
   ================================================================= */
.img-holder.has-photo { padding: 0; }
.img-holder.has-photo img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  border-radius: inherit;
}

/* Preview mode — the badge that tells the Super Admin this is a
   preview and not a live customer session. */
.eb-preview-chip {
  position: fixed; z-index: 9999;
  left: 50%; bottom: 18px; transform: translateX(-50%);
  padding: 8px 18px; border-radius: 999px;
  background: rgba(30,20,8,.92); color: var(--cream);
  font-family: "Montserrat",sans-serif;
  font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  box-shadow: 0 10px 30px rgba(0,0,0,.35);
  pointer-events: none;
}

/* Where to send a GCash / bank payment — checkout and the retailer Pay form.

   THE QR IS BIG ENOUGH TO SCAN. It was 148px including its padding: fine for a
   laptop screen held at arm's length, marginal for a phone camera, and on a
   phone the customer is usually saving it to scan from their gallery, where a
   small code is the one most likely to fail. 220px on a wide screen, and on a
   phone it takes the card's full width up to 280px. Square by aspect-ratio, so
   a QR uploaded with any proportions never renders as a stretched code.

   Account details sit BESIDE the code (the name and number a person checks
   against their app before sending), then one plain instruction. The reference
   number and screenshot fields follow the card rather than sharing its row. */
/* ONE COLUMN, SO THE CODE GETS THE WHOLE CARD.

   This was a two-column row: the code on the left, the heading and the
   instruction on the right. That handed more than half the card's width to
   text, and the code is the only thing in here that has to survive being
   photographed by a camera across a counter. Details above it, instruction
   below it, code in the middle at whatever width is left over — which is all
   of it.

   Stacking also retires a bug: the two columns used to stack on a
   `max-width: 560px` MEDIA query, which asks how wide the browser is. This
   card lives in a checkout drawer whose width has nothing to do with that, so
   in a 420px drawer on a 1280px screen the row never stacked at all — the text
   column was squeezed to zero and the card overflowed. There is nothing left
   to ask now. */
.pay-qr { display:flex; flex-direction:column; align-items:center; gap:14px;
  padding:16px; margin-bottom:16px;
  border:1px solid var(--border-lift); border-radius:var(--r-md); background:var(--surface-2); }
.pay-qr-head { width:100%; display:flex; flex-direction:column; gap:8px; min-width:0; font-size: var(--fs-base); }

/* AS BIG AS THE CARD ALLOWS, NOT 220px.

   A phone camera has to resolve the individual modules of the code, and what
   gets uploaded here is usually a whole banking-app screenshot — name, number,
   logo and all — so the QR itself is barely half of the picture. At a fixed
   220px that left roughly 120px of actual code, which a camera will not lock
   onto at arm's length.

   It now takes the card's full width, capped at 460 so it does not become
   absurd on a wide drawer, and the image is capped by HEIGHT as well so a tall
   portrait screenshot cannot push the rest of the checkout off the screen.
   Anything beyond that is the "Open full size" link's job. */
.pay-qr-fig { width:100%; max-width:460px; min-width:0; display:block;
  text-decoration:none; color:inherit; }
/* White behind the code whatever the theme: a QR on a dark card scans badly.

   NO FORCED SQUARE. `aspect-ratio: 1/1` assumed the upload is a square QR; the
   one actually in use is a 1080x1311 portrait screenshot of a banking app, and
   letterboxing it into a square box scaled it to fit the HEIGHT — 280px of a
   340px box, throwing away a sixth of the width the code could have had. The
   image keeps its own proportions and is capped by height instead, so a
   portrait upload fills the width and a square one is still square. */
.pay-qr-img { width:100%; height:auto; max-height:560px; object-fit:contain; background:#fff;
  border-radius:var(--r-sm); padding:8px; display:block; }
/* The affordance, said in words. An image that happens to be clickable is not
   discoverable; on a phone nothing hovers to reveal it. */
.pay-qr-zoom { display:flex; align-items:center; justify-content:center; gap:6px;
  margin-top:8px; font-size: var(--fs-sm); font-weight:600; color:var(--text-muted);
  transition:color var(--t); }
.pay-qr-zoom svg { width:14px; height:14px; flex:none; }
.pay-qr-fig:hover .pay-qr-zoom { color:var(--red); }
.pay-qr-fig:focus-visible { outline:3px solid var(--gold); outline-offset:3px; border-radius:var(--r-sm); }
.pay-qr-title { font-weight:700; font-size: var(--fs-md); margin-bottom:2px; }
.pay-qr-row { display:flex; justify-content:space-between; gap:10px; padding-bottom:6px; border-bottom:1px dashed var(--border); }
.pay-qr-row span { color:var(--text-muted); }
.pay-qr-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing:.02em; }
/* Under the code, and the width of the card — it is read after the scan. */
.pay-qr-hint { width:100%; font-size: var(--fs-sm); color:var(--text-muted); line-height:1.5; }
.pay-qr-empty { display:block; font-size: var(--fs-sm); color:var(--text-muted); }

/* =================================================================
   ADDRESS PICKER — assets/js/public/address-picker.js
   -----------------------------------------------------------------
   Mounted into four forms with two different field styles (.field for
   checkout and profile, .auth-field for Create Account and the retailer
   form), so the grid here only arranges cells and never restyles the
   fields themselves — each host keeps looking like itself.

   A six-column grid rather than two: the four dropdowns pair up, but the
   last row wants a wide street and a narrow ZIP, and a two-column grid
   cannot give a four-digit field less room than a street name.
   ================================================================= */
.addr-picker {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  column-gap: 14px;
  /* IT MEASURES ITSELF, NOT THE WINDOW. The picker goes into a checkout
     drawer, a 380px auth modal and a full-width form card, and how much room
     it has has nothing to do with how wide the browser is: in the Create
     Account modal on a 1440px screen these six columns were ~55px each, which
     pushed "Choose a province first" past the modal's edge and put a
     horizontal scrollbar on it. A container query asks the only question that
     matters — how wide is THIS picker. */
  container-type: inline-size;
  container-name: addr;
}
.addr-picker > .addr-cell { grid-column: span 3; min-width: 0; }
.addr-picker > .addr-street { grid-column: span 4; }
.addr-picker > .addr-zip    { grid-column: span 2; }
.addr-picker > .addr-legacy,
.addr-picker > .addr-status { grid-column: 1 / -1; }

/* One dropdown per row once two of them would be under ~250px each. Below
   that a trigger cannot hold "Choose a city or municipality" beside a 44px
   icon well and an arrow, and the label wraps to two lines on one cell and
   not its neighbour — which is what made the modal look broken rather than
   merely tight. Street and ZIP stay paired longer: a four-digit box does not
   need a row of its own until there is really no room. */
/* 460px is where two triggers stop fitting their own placeholders: each gets
   (460 − 14) / 2 = 223px, of which 78px is the icon well, the arrow and the
   padding, leaving 145px for text against a longest string of 130px. Below it
   the four dropdowns take a row each. */
@container addr (max-width: 460px) {
  .addr-picker > .addr-cell   { grid-column: 1 / -1; }
  .addr-picker > .addr-street { grid-column: span 4; }
  .addr-picker > .addr-zip    { grid-column: span 2; }
}
/* An even split once 2-of-6 stops being a usable field. In the auth variant a
   cell also carries a 44px icon well, so a two-column ZIP at this width has
   about 50px left for four digits — which is how "2400" came to render as
   "240". Three and three is still a wide street and a short ZIP by content,
   and both fit what they hold. */
@container addr (max-width: 400px) {
  .addr-picker > .addr-street { grid-column: span 3; }
  .addr-picker > .addr-zip    { grid-column: span 3; }
}
@container addr (max-width: 260px) {
  .addr-picker > .addr-street,
  .addr-picker > .addr-zip { grid-column: 1 / -1; }
}

/* THE ICON WELL BELONGS TO THE TRIGGER TOO.

   In the "auth" variant every cell is .auth-input-group with an absolutely
   positioned .auth-input-icon at the left, and .auth-input is padded 44px to
   clear it. EbSelect replaces the <select> on screen with its own .ebs-trigger,
   which knows nothing about that padding — so the pin was drawn on top of the
   first characters of "Choose a region first". Measured 16px of overlap on the
   retailer form and the same in the Create Account modal.

   Matched to .auth-input rather than the icon being removed, so a dropdown and
   the text field beside it still line their content up on the same axis. */
.addr-picker--auth .ebs .ebs-trigger { padding-left: 44px; }

/* The fallback box exists in the markup from the start (so switching is a
   class flip, not a rebuild), and is shown only when the location data has
   not been loaded on this server. */
.addr-picker > .addr-legacy { display: none; }
.addr-picker.is-legacy > .addr-cell:not(.addr-legacy) { display: none; }
.addr-picker.is-legacy > .addr-legacy { display: block; }

/* Status line: a failed list says so here. Empty and zero-height otherwise,
   so it costs no space in the normal case. */
.addr-status { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); min-height: 0; }
.addr-status:empty { display: none; }

/* A disabled dropdown still has to read as a field, not as a hole in the
   form — it is the next step, waiting for the one above it. */
.addr-picker .ebs-trigger[disabled] { opacity: .6; }

/* Loading. aria-busy is what assistive tech is told; the dimmed label is
   what everyone else sees. Nothing spins — the wait is a fraction of a
   second and motion for that is noise. */
.addr-picker [aria-busy="true"] .ebs-trigger,
.addr-picker [aria-busy="true"] select { opacity: .6; cursor: progress; }

/* PREFILLED FROM THE SAVED PROFILE — the same hint the checkout's own
   fields use, applied here to every page. shop.css and partner.css each
   carried a copy for their own page, so a checkout opened from the home
   page showed no marker at all. On a dropdown the native <select> is hidden
   behind EbSelect's trigger, so the marker has to be carried across to the
   trigger or it is invisible. A hint, never a lock: it goes the moment the
   person changes the field. */
.addr-picker .is-prefilled,
.addr-picker .ebs:has(> select.is-prefilled) .ebs-trigger {
  border-color: var(--gold);
  background-image: linear-gradient(0deg, var(--gold-dim), var(--gold-dim));
}
.addr-picker .is-prefilled:focus,
.addr-picker .ebs:has(> select.is-prefilled) .ebs-trigger:focus-visible { background-image: none; }

/* Errors: the host's own .has-error treatment covers .field; .auth-field has
   none, so the border is set here to match it. */
.addr-picker .auth-field.has-error .auth-input,
.addr-picker .auth-field.has-error .ebs-trigger { border-color: var(--out); }
.addr-picker .field.has-error .ebs-trigger { border-color: var(--out); }

/* ZIP: tabular figures so four digits sit still as they are typed. */
.addr-picker .addr-zip input { font-variant-numeric: tabular-nums; letter-spacing: .04em; }

/* The viewport media query that used to live here is gone. It asked how wide
   the WINDOW was, which told it nothing about the modal the picker was sitting
   in — see the @container rules above. */
