:root {
  /* Layout + spacing system */
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 48px;
  --space-10: 64px;
  --space-11: 76px;
  --space-12: 90px;

  /* Radius system */
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 18px;
  --radius-pill: 999px;

  /* Typography system */
  --font-sans: "Inter", sans-serif;
  --font-serif: "Playfair Display", serif;
  --text-xs: 0.75rem;
  --text-sm: 0.84rem;
  --text-md: 0.95rem;
  --text-base: 0.875rem;
  --text-lg: 1.08rem;
  --text-xl: 1.14rem;
  --display-1: clamp(2rem, 6vw, 4rem);
  --display-2: 1.6rem;

  /* Icon system */
  --icon-sm: 14px;
  --icon-md: 16px;
  --icon-lg: 20px;
  --icon-xl: 22px;

  /* Button system */
  --btn-height-sm: 40px;
  --btn-height-md: 44px;
  --btn-height-lg: 48px;
  --btn-pad-x: 16px;
  --btn-pad-y: 11px;
  --btn-font-weight: 600;

  --bg-main: #0F2A23;
  --bg-deep: #0B1F1A;
  --gold: #C6A55C;
  --gold-light: #E0C27A;
  --text-main: #F5F5F5;
  --text-muted: #A8B3AE;
  --light-bg: #F4F4F1;
  /* CS2a: promoted from inline hex literals in styles-products.css
     where each was repeated 4–13 times. Naming follows the existing
     bg-/text-/gold- convention so consumers grep one prefix. */
  --card-deep: #18342d;   /* dark panel green (was 13× inline) */
  --cream: #fff0c4;       /* warm parchment text (was 7× inline) */
  --cream-soft: #f5e5b8;  /* lighter cream / accent text (was 4×) */
  --radius: var(--radius-sm);
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.22);
  --motion-fast: 0.18s;
  --motion-base: 0.24s;
  --motion-slow: 0.38s;
  --ease-premium: cubic-bezier(0.22, 1, 0.36, 1);
  --liquid-bg: transparent;
  --liquid-bg-strong: transparent;
  --liquid-bg-soft: transparent;
  --liquid-border: rgba(198, 165, 92, 0.22);
  --liquid-border-hover: rgba(198, 165, 92, 0.55);
  --liquid-shadow: none;
  --liquid-shadow-hover: 0 8px 20px rgba(0, 0, 0, 0.2);
  --liquid-highlight: transparent;
}

* { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  overscroll-behavior-y: none;
}
body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--text-main);
  background: var(--bg-main);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  padding-bottom: 0;
  overscroll-behavior-y: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

input,
textarea,
select,
[contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

.container {
  width: min(1180px, 92vw);
  margin: 0 auto;
}

h1, h2, h3 {
  font-family: var(--font-serif);
  letter-spacing: 0.02em;
  margin: 0 0 var(--space-3);
}

p { margin: 0 0 var(--space-2); color: var(--text-muted); font-size: var(--text-base); }

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

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(8px);
  background:
    linear-gradient(180deg, rgba(8, 23, 19, 0.94), rgba(8, 23, 19, 0.88)),
    radial-gradient(circle at 18% 0%, rgba(198, 165, 92, 0.08), transparent 28%);
  border-bottom: 1px solid rgba(198, 165, 92, 0.16);
  box-shadow: 0 10px 26px rgba(4, 15, 11, 0.16);
}

.tg-browser-banner {
  position: sticky;
  top: 74px;
  z-index: 99;
  background: rgba(11, 31, 26, 0.94);
  border-bottom: 1px solid rgba(198, 165, 92, 0.24);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.tg-browser-banner-inner {
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) 0;
}

.tg-browser-banner-text {
  margin: 0;
  color: #f2e5bf;
  font-size: var(--text-sm);
}

.tg-browser-banner-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.tg-browser-banner-actions .btn {
  min-height: 36px;
  padding: 7px 12px;
}


.header-inner {
  min-height: 78px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-5);
}

.logo {
  color: var(--gold);
  font-family: "Playfair Display", serif;
  font-size: 1.7rem;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.logo-mark {
  width: 118px;
  height: 62px;
  object-fit: contain;
  object-position: left center;
  padding: 0;
  flex: 0 0 auto;
  filter: brightness(0) saturate(100%) invert(79%) sepia(24%) saturate(553%) hue-rotate(356deg) brightness(90%) contrast(91%);
}

.logo-wordmark {
  display: inline-block;
  line-height: 1;
}

.site-nav {
  justify-self: center;
  display: flex;
  gap: 34px;
  position: relative;
  padding-bottom: 10px;
}

.site-nav a {
  color: var(--text-main);
  opacity: 0.92;
  transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
  position: relative;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.site-nav a:hover {
  color: var(--gold-light);
  transform: translateY(-1px);
}

.site-nav a.active {
  color: var(--gold-light);
  opacity: 1;
}

.nav-underline {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--gold), var(--gold-light));
  transform: translateX(0);
  opacity: 0;
  /* Longer, gentler ease so the scroll-spy underline glides
     between items instead of snapping. */
  transition: transform 0.42s cubic-bezier(0.4, 0, 0.2, 1), width 0.42s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.25s ease;
}

.nav-underline.ready {
  opacity: 1;
}

.social-nav-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.social-nav-btn {
  border: 0;
  background: transparent;
  color: var(--text-main);
  opacity: 0.92;
  font: inherit;
  cursor: pointer;
  padding: 0;
  transition: color 0.2s ease;
}

.social-nav-btn:hover {
  color: var(--gold-light);
}

.social-nav-icon {
  width: var(--btn-height-md);
  height: var(--btn-height-md);
  border-radius: var(--radius-pill);
  border: 1px solid rgba(198, 165, 92, 0.22);
  background: rgba(11, 31, 26, 0.72);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  overflow: hidden;
}

.social-btn-image {
  width: 100%;
  height: 100%;
  border-radius: 999px;
  object-fit: cover;
  object-position: center;
  display: block;
  border: 0;
  filter: saturate(1.02) contrast(1.04);
  transform: scale(1.28);
}

.social-btn-svg {
  width: 22px;
  height: 22px;
  color: rgba(245, 229, 184, 0.82);
  transition: color 0.18s ease, transform 0.18s ease;
}

.social-nav-btn:hover .social-btn-svg,
.social-nav-btn:focus-visible .social-btn-svg {
  color: var(--gold-light, #f5e5b8);
  transform: scale(1.06);
}

.social-nav-icon:hover {
  border-color: rgba(224, 194, 122, 0.48);
}

.social-nav-icon:hover .social-btn-image {
  border-color: rgba(224, 194, 122, 0.48);
}

.social-nav-menu {
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  min-width: 188px;
  display: none;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-2);
  border-radius: var(--radius-lg);
  background: rgba(11, 31, 26, 0.98);
  border: 1px solid rgba(198, 165, 92, 0.3);
  box-shadow: var(--shadow);
  z-index: 130;
}

.social-nav-menu.open {
  display: flex;
}

.social-nav-menu a {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid rgba(198, 165, 92, 0.25);
  color: var(--gold-light);
  white-space: nowrap;
}

.social-link-icon {
  display: inline-flex;
  width: var(--icon-md);
  height: var(--icon-md);
  margin-right: var(--space-2);
  justify-content: center;
  align-items: center;
}

.social-link-icon svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  fill: currentColor;
}

.social-nav-menu a:hover {
  border-color: var(--gold-light);
  background: rgba(198, 165, 92, 0.12);
}

.nav-toggle {
  display: none;
  border: 1px solid rgba(198, 165, 92, 0.22);
  background: rgba(11, 31, 26, 0.72);
  color: #f8e5b0;
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
}

.header-inner > .btn { justify-self: end; }

.header-right {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 10px;
}

.lang-select {
  position: relative;
}

.lang-current,
.lang-option {
  border-radius: var(--radius);
  border: 1px solid rgba(198, 165, 92, 0.22);
  background: rgba(11, 31, 26, 0.72);
  color: #f8e5b0;
  min-height: 44px;
  padding: 10px 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.lang-current:hover,
.lang-option:hover {
  border-color: rgba(198, 165, 92, 0.55);
  color: #fff0c4;
}

.lang-current::after {
  content: "▾";
  margin-left: var(--space-2);
  font-size: var(--text-xs);
}

.lang-menu {
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  min-width: 100%;
  display: none;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-2);
  border-radius: var(--radius-lg);
  border: 1px solid rgba(198, 165, 92, 0.28);
  background: rgba(11, 31, 26, 0.97);
  box-shadow: var(--shadow);
  z-index: 120;
}

.lang-menu.open {
  display: flex;
}

.btn {
  border-radius: var(--radius-lg);
  padding: var(--btn-pad-y) var(--btn-pad-x);
  min-height: var(--btn-height-md);
  font-weight: var(--btn-font-weight);
  transition: transform var(--motion-fast) var(--ease-premium), box-shadow var(--motion-fast) var(--ease-premium), background-color var(--motion-fast) var(--ease-premium), color var(--motion-fast) var(--ease-premium), border-color var(--motion-fast) var(--ease-premium);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(198, 165, 92, 0.22);
  cursor: pointer;
  will-change: transform;
  box-shadow: none;
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.btn-solid {
  background: var(--gold);
  color: #0b211b;
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.btn-solid:hover {
  background: var(--gold-light);
  border-color: transparent;
  transform: translateY(-1px) scale(1.01);
  box-shadow: 0 4px 15px rgba(212, 175, 55, 0.4);
}

.btn-outline {
  border-color: rgba(198, 165, 92, 0.45);
  color: var(--gold-light);
  background: transparent;
}

.btn-outline:hover {
  border-color: var(--gold-light);
  color: #fff0c4;
  transform: translateY(-1px) scale(1.01);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
}

.btn:active {
  transform: translateY(0) scale(0.97);
}

/* CS2d — canonical .card: 18px radius, neutral ivory shell, soft shadow.
   landing.css overrides bg/border/radius for its dark-green theme.
   styles-products.css .product-card inherits the 18px radius. */
.card {
  border-radius: 18px;
  padding: 16px;
  background: var(--cream, #fffaf0);
  border: 1px solid rgba(198, 165, 92, 0.15);
  box-shadow: 0 8px 24px rgba(4, 14, 10, 0.08);
}

/* CS2d — canonical secondary button. landing.css uses .btn-muted for the
   same role; keeping both names so existing markup doesn't change. */
.btn-secondary {
  background: transparent;
  border: 1px solid rgba(198, 165, 92, 0.4);
  color: var(--text-main, #f5f5f5);
}
.btn-secondary:hover {
  background: rgba(198, 165, 92, 0.1);
  border-color: var(--gold, #c6a55c);
}

.liquid-pressable {
  position: relative;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}

.liquid-pressable::after {
  content: "";
  position: absolute;
  left: var(--press-x, 50%);
  top: var(--press-y, 50%);
  width: 20px;
  height: 20px;
  border-radius: 999px;
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.25);
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.74) 0%,
    rgba(224, 194, 122, 0.52) 42%,
    rgba(224, 194, 122, 0.08) 64%,
    rgba(224, 194, 122, 0) 76%
  );
  filter: blur(0.2px);
}

.liquid-pressable.liquid-press-hold::after {
  opacity: 0.58;
  animation: liquidPressHold 760ms cubic-bezier(0.22, 0.72, 0.26, 1) infinite;
}

.liquid-pressable:active::after {
  opacity: 0.52;
  animation: liquidPressHold 520ms cubic-bezier(0.22, 0.72, 0.26, 1) 1;
}

.liquid-pressable.liquid-press-release::after {
  animation: liquidPressRelease 540ms cubic-bezier(0.2, 0.74, 0.22, 1) forwards;
}

@keyframes liquidPressHold {
  0% {
    transform: translate(-50%, -50%) scaleX(1.9) scaleY(2.8) rotate(-4deg);
    border-radius: 62% 38% 56% 44% / 48% 60% 40% 52%;
  }
  25% {
    transform: translate(-50%, -50%) scaleX(2.8) scaleY(2.0) rotate(3deg);
    border-radius: 44% 56% 36% 64% / 58% 42% 58% 42%;
  }
  50% {
    transform: translate(-50%, -50%) scaleX(2.0) scaleY(3.0) rotate(-3deg);
    border-radius: 58% 42% 62% 38% / 40% 62% 38% 60%;
  }
  75% {
    transform: translate(-50%, -50%) scaleX(3.0) scaleY(2.0) rotate(3deg);
    border-radius: 40% 60% 48% 52% / 60% 40% 60% 40%;
  }
  100% {
    transform: translate(-50%, -50%) scaleX(1.9) scaleY(2.8) rotate(-4deg);
    border-radius: 62% 38% 56% 44% / 48% 60% 40% 52%;
  }
}

@keyframes liquidPressRelease {
  0% {
    opacity: 0.52;
    transform: translate(-50%, -50%) scaleX(2.5) scaleY(1.9) rotate(2deg);
    border-radius: 42% 58% 38% 62% / 56% 44% 58% 42%;
  }
  45% {
    opacity: 0.24;
    transform: translate(-50%, -50%) scaleX(5.8) scaleY(4.1) rotate(-2deg);
    border-radius: 55% 45% 64% 36% / 42% 58% 42% 58%;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scaleX(8.3) scaleY(5.9) rotate(0deg);
    border-radius: 50%;
  }
}

/* Guaranteed fallback for environments where JS pointer effects are blocked. */
.btn:active::after,
.icon-action:active::after,
.lang-current:active::after,
.lang-option:active::after,
.subcategory-chip:active::after,
.quick-nav:active::after,
.qty-btn:active::after,
.cart-qty button:active::after,
.category-tile-btn:active::after,
.add-btn:active::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 16px;
  border-radius: 999px;
  transform: translate(-50%, -50%) scale(0.2);
  opacity: 0.58;
  pointer-events: none;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.68) 0%, rgba(224, 194, 122, 0.34) 52%, rgba(224, 194, 122, 0) 78%);
  animation: liquidPressRelease 420ms cubic-bezier(0.2, 0.74, 0.22, 1) 1;
}

@media (prefers-reduced-motion: reduce) {
  .liquid-pressable.liquid-press-hold::after,
  .liquid-pressable.liquid-press-release::after,
  .liquid-pressable:active::after,
  .btn:active::after,
  .icon-action:active::after,
  .lang-current:active::after,
  .lang-option:active::after,
  .subcategory-chip:active::after,
  .quick-nav:active::after,
  .qty-btn:active::after,
  .cart-qty button:active::after,
  .category-tile-btn:active::after,
  .add-btn:active::after {
    animation: none;
    opacity: 0.18;
    transform: translate(-50%, -50%) scale(2.2);
  }
}

.hero {
  /* DZ5: 60vh still centred the content inside tall empty bands
     (big gap navbar→headline in the review). 54vh keeps the
     dominant-art feel while tightening the dead air further. */
  min-height: 54vh;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  background-image:
    linear-gradient(180deg, rgba(11, 31, 26, 0.88), rgba(11, 31, 26, 0.54));
  background-size: cover;
  background-position: center;
}

.hero-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(5, 14, 11, 0.32), rgba(5, 14, 11, 0.06) 45%, rgba(5, 14, 11, 0.36)),
    radial-gradient(ellipse at 10% 85%, rgba(198, 165, 92, 0.09), rgba(198, 165, 92, 0) 62%);
}

.hero-content {
  position: relative;
  z-index: 1;
  /* DZ5: trimmed 48→36px — combined with the lower min-height
     this pulls the headline up so the navbar→eyebrow gap reads
     intentional, not empty. */
  padding: 36px 0;
}

.hero-layout {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--space-8);
  align-items: center;
}

.hero-copy {
  position: relative;
  max-width: 640px;
  /* Was 22 18 22 0 — vertical padding stacked on top of
     .hero-content's 48 px, doubling air. Drop to 8 18 8 0. */
  padding: 8px 18px 8px 0;
}

.eyebrow {
  color: var(--gold-light);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: var(--text-sm);
}

.hero h1 {
  max-width: 660px;
  font-size: var(--display-1);
  line-height: 1.06;
  text-wrap: balance;
}

/* Gold-accent keyword inside the hero headline. The whole h1 is
   white on dark green; one focal word in gold gives the headline
   visual rhythm without overpowering the rest. The italic adds
   a tiny editorial flourish that matches the Playfair body. */
.hero-title-accent {
  color: var(--gold-light, #f5e5b8);
  font-style: italic;
  font-weight: 600;
}

.hero-sub {
  max-width: 520px;
  font-size: var(--text-lg);
  font-weight: 500;
  line-height: 1.6;
}

.hero-visual {
  display: flex;
  justify-content: center;
  align-items: center;
  padding-left: var(--space-5);
  /* Was clamp(420, 44vw, 680) — image area was 680 px tall on
     wide desktops, which forced the whole hero up to 78vh+.
     Tightened to clamp(360, 36vw, 540) to match the trimmed
     .hero min-height; image still reads as a dominant feature. */
  min-height: clamp(360px, 36vw, 540px);
}

.hero-image-wrap {
  position: relative;
  width: min(590px, 100%);
  /* Was 0 46px 34px — 46 px lateral padding around the image
     was visible as wide dark-green bars. Reduced to 0 20px 16px. */
  padding: 0 20px 16px;
  overflow: visible;
  min-height: clamp(360px, 36vw, 540px);
}

.hero-image-wrap::before {
  content: "";
  position: absolute;
  inset: 24px 10px 0;
  border-radius: 34% 34% 24% 24% / 16% 16% 22% 22%;
  background:
    radial-gradient(circle at 50% 40%, rgba(198, 165, 92, 0.12), transparent 58%),
    radial-gradient(circle at 48% 74%, rgba(15, 42, 35, 0.5), transparent 72%);
  filter: blur(10px);
  opacity: 0.82;
  pointer-events: none;
}

.hero-image-shell {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: 140px 140px 34px 34px / 52px 52px 34px 34px;
  overflow: hidden;
  border: 1px solid rgba(198, 165, 92, 0.18);
  box-shadow:
    0 28px 56px rgba(0, 0, 0, 0.34),
    0 0 0 1px rgba(255, 255, 255, 0.04) inset;
  background:
    radial-gradient(circle at 50% 45%, rgba(42, 72, 61, 0.92), rgba(11, 31, 26, 0.98) 78%),
    linear-gradient(135deg, rgba(198, 165, 92, 0.08), rgba(255, 255, 255, 0.03));
}

.hero-image-shell::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0) 16%),
    radial-gradient(circle at 26% 22%, rgba(198, 165, 92, 0.14), transparent 52%);
  pointer-events: none;
  z-index: 2;
}

.hero-image-shell::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(120deg, rgba(11, 31, 26, 0.2), rgba(11, 31, 26, 0.03)),
    radial-gradient(circle at 85% 8%, rgba(198, 165, 92, 0.12), transparent 44%);
  pointer-events: none;
  z-index: 2;
}

.hero-image {
  /* Stack both image layers (+ video) in the same box so the
     front can crossfade over the behind-buffer without exposing
     the shell background. Shell is position:relative + overflow
     hidden with a fixed aspect-ratio, so absolute is safe. The
     decorative ::before/::after frame is z-index:2 and stays on
     top of both. */
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  /* User: the photo sat inside the rounded frame with a dark
     letterbox border. `contain` + scale(0.96) caused both — it
     fit-with-bars and then shrank, leaving a gap. `cover` +
     scale(1) makes the image fill the 3:4 shell edge-to-edge
     (cropped, no bars), so the frame looks "fully put". */
  object-fit: cover;
  object-position: center;
  display: block;
  filter: saturate(0.9) contrast(1.05);
  transform: scale(1);
  transform-origin: center;
  opacity: 1;
  /* Duration MUST match HERO_FADE_MS in script.js (700ms) so the
     JS-driven slide never jumps mid-transition. Eased like a
     catalogue swipe; GPU-composited for a stable, jank-free move. */
  transition: transform 700ms cubic-bezier(0.4, 0, 0.2, 1),
    opacity 700ms ease;
  will-change: transform;
  backface-visibility: hidden;
}

/* Behind-buffer: always opaque, sits under the front layer so
   when the front fades out it reveals this (next) image with no
   background flash. */
.hero-image--back {
  z-index: 0;
}

.hero-image.is-fading {
  opacity: 0;
}

.hero-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  /* DZ5: were heavy 46px dark (rgba(11,31,26,.7)) discs that sat
     on the photo like UI bolted on. Lighter: smaller frosted-
     glass pills, semi-transparent at rest, fully solid + gold on
     hover so they recede until wanted. */
  width: 40px;
  height: 40px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  color: #fff8e9;
  font-size: 1.25rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
  opacity: 0.7;
  transition: transform 180ms ease, background 180ms ease, border-color 180ms ease, opacity 180ms ease;
}

.hero-nav:hover,
.hero-nav:focus-visible {
  background: rgba(198, 165, 92, 0.42);
  border-color: rgba(198, 165, 92, 0.8);
  color: #fff;
  opacity: 1;
}

.hero-nav:active {
  transform: translateY(-50%) scale(0.96);
}

/* Move the arrows ON the photo edges (was 10px which left them
   floating in the dark green gutter, hard to spot). The wrap
   has padding: 0 46px on the sides; setting left/right to 56px
   tucks the buttons just inside the photo's left/right edges. */
.hero-nav-prev {
  left: 56px;
}

.hero-nav-next {
  right: 56px;
}

/* On narrow viewports the gutter shrinks, keep the arrows in
   line with the image edges. */
@media (max-width: 768px) {
  .hero-nav-prev { left: 24px; }
  .hero-nav-next { right: 24px; }
}

.hero-dots {
  /* Anchored to .hero-image-shell (dots now live inside it) so
     they sit over the image's bottom edge, not in the dark
     padding below the frame. z-index 4 keeps them above the
     decorative ::after vignette (z-index 2). */
  position: absolute;
  left: 50%;
  bottom: 14px;
  z-index: 4;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  /* Slots reserve their own spacing — tight gap keeps the dots
     close like a real page indicator. */
  gap: 2px;
}

/* Each dot is a FIXED-WIDTH slot (= active pill width). The
   visible dot is the ::before, which grows inside its slot when
   active. Because the slot never changes size, the other dots
   never get pushed / the row never re-centres — that reflow was
   the "wrong alignment / not smooth" jiggle. The pill itself
   eases open like a real carousel indicator. */
.hero-dot {
  width: 24px;
  height: 14px;
  padding: 0;
  border: 0;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.hero-dot::before {
  content: "";
  display: block;
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.26);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
  /* Duration + easing match the hero slide (HERO_FADE_MS / the
     .hero-image transform) so the dot and the picture move in
     sync, not at different speeds. */
  transition: width 700ms cubic-bezier(0.4, 0, 0.2, 1),
    background 700ms ease, box-shadow 700ms ease;
}

.hero-dot.is-active::before {
  width: 22px;
  background: rgba(198, 165, 92, 0.96);
  box-shadow: 0 0 0 1px rgba(198, 165, 92, 0.24);
}

.hero-dot:hover::before,
.hero-dot:focus-visible::before {
  background: rgba(255, 255, 255, 0.52);
}

.hero-actions {
  margin-top: var(--space-5);
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}

/* Clear primary vs secondary hierarchy in the hero. Primary
   (Katalogga o'tish / Перейти в каталог) stays the solid gold
   button and gets a soft glow so it visually dominates; the
   Telegram CTA is demoted to a quiet ghost (muted white, thin
   border, no hover lift) so it reads as the secondary action.
   Scoped to .hero-actions so the site-wide .btn-outline (filters,
   etc.) is unaffected. */
.hero-actions .btn-solid {
  box-shadow: 0 8px 22px rgba(198, 165, 92, 0.34);
}

.hero-actions .btn-outline {
  border-color: rgba(255, 255, 255, 0.26);
  color: rgba(255, 255, 255, 0.78);
  background: transparent;
  font-weight: 500;
  box-shadow: none;
}

.hero-actions .btn-outline:hover {
  border-color: rgba(255, 255, 255, 0.5);
  color: #ffffff;
  transform: none;
  box-shadow: none;
}

.hero-actions .btn {
  min-width: 216px;
  padding-inline: 22px;
}

/* Hero quick-cat chips — top 4 popular categories surfaced
   directly in the hero so users don't have to scroll to discover
   the catalog. Compact pill style; clear gold-tint hover; wraps
   to a second line on narrow viewports. */
.hero-quick-cats {
  margin-top: var(--space-3);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.hero-quick-cat {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid rgba(198, 165, 92, 0.32);
  background: rgba(11, 31, 26, 0.55);
  color: rgba(245, 229, 184, 0.92);
  font-size: 0.88rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  transition: background 160ms ease, border-color 160ms ease, color 160ms ease, transform 140ms ease;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.hero-quick-cat:hover,
.hero-quick-cat:focus-visible {
  background: rgba(198, 165, 92, 0.18);
  border-color: rgba(198, 165, 92, 0.6);
  color: #fff8e9;
  transform: translateY(-1px);
  outline: none;
}

.hero-quick-cat:active {
  transform: translateY(0);
}

@media (max-width: 768px) {
  .hero-quick-cats {
    margin-top: var(--space-2);
  }
  .hero-quick-cat {
    height: 32px;
    padding: 0 12px;
    font-size: 0.84rem;
  }
}

/* Scroll cue: a small chevron pinned to the bottom-center of the
   hero. Pulses gently to invite a scroll, then fades out the
   first time the user actually scrolls (driven by JS toggling
   .is-hidden). Hidden entirely on phones — there's much less
   above-the-fold confusion at narrower widths. */
.hero-scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 6;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(11, 31, 26, 0.55);
  color: rgba(245, 229, 184, 0.85);
  text-decoration: none;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  animation: heroScrollCueFloat 2.4s ease-in-out infinite;
  transition: opacity 320ms ease, transform 320ms ease;
}

.hero-scroll-cue:hover,
.hero-scroll-cue:focus-visible {
  background: rgba(198, 165, 92, 0.24);
  border-color: rgba(198, 165, 92, 0.6);
  color: #fff8e9;
  outline: none;
}

.hero-scroll-cue.is-hidden {
  opacity: 0;
  pointer-events: none;
  transform: translateX(-50%) translateY(8px);
}

@keyframes heroScrollCueFloat {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(4px); }
}

@media (max-width: 768px) {
  .hero-scroll-cue {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-scroll-cue {
    animation: none;
  }
}

.section { padding: 32px 0; }

/* Mahsulotlar section — compact spacing so the product grid lands
   close to the section title once a category is chosen.
   DZ2: was pure #fff — the only white block among the dark +
   cream sections, which made the page jump dark→cream→dark→
   white→cream→dark. Unified to the shared light tone so every
   light section reads as one deliberate surface. */
#new.section { padding: 18px 0; background: var(--light-bg); }
#new .section-head { margin-bottom: 8px; }
#new .section-head h2 { font-size: clamp(1.4rem, 2.2vw, 1.75rem); }
#new .filter-feedback { min-height: 18px; margin-top: 2px; font-size: 0.85rem; }
#new .sort-filter-toolbar { margin-bottom: 12px; }
.section-light {
  background: var(--light-bg);
  color: #1b2822;
}
.section-light p { color: #4f5f59; }
.section-light h2, .section-light h3 { color: #15231f; font-weight: 800; letter-spacing: -0.02em; }

.section-dark { background: var(--bg-main); }
.section-deep { background: var(--bg-deep); }

.section-head { margin-bottom: 20px; }
.section-head h2 { font-size: var(--display-2); }

.filter-feedback {
  min-height: 22px;
  margin-top: var(--space-2);
  font-size: var(--text-md);
  color: #51625c;
}

.results-summary {
  margin-top: 2px;
  font-size: 0.85rem;
  color: #6b7c75;
  font-weight: 600;
}

/* DZ6: the .catalog-loading-status text pill ("Mahsulotlar
   yuklanmoqda…") was dead — it shipped `hidden` and nothing ever
   un-hid it; the skeleton-card grid in renderProducts() is the
   real (and better) loading state. Removed the pill css, markup
   and JS refs so the skeleton is the single source of truth. */

.products-flash {
  animation: productsFlash 0.55s ease-out;
}

@keyframes productsFlash {
  0% {
    box-shadow: 0 0 0 0 rgba(198, 165, 92, 0.0);
    transform: translateY(0);
  }
  35% {
    box-shadow: 0 0 0 2px rgba(198, 165, 92, 0.42);
    transform: translateY(-1px);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(198, 165, 92, 0.0);
    transform: translateY(0);
  }
}

.sort-filter-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.sort-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.sort-wrap label {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
}

.sort-wrap select {
  background: rgba(7, 20, 16, 0.85);
  border: 1px solid rgba(198, 165, 92, 0.3);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: 0.875rem;
  padding: 6px 10px;
  cursor: pointer;
}

/* Sticky filter/sort toolbar. The bg MUST be opaque: with a
   transparent bg the product cards scrolled *behind* the stuck
   toolbar and bled through its text (looked broken). Solid
   light surface + hairline divider + padding so it reads as a
   real toolbar and fully occludes scrolled content. */
.sticky-tools {
  position: sticky;
  top: 86px;
  z-index: 70;
  margin-bottom: var(--space-4);
  padding: 12px 0;
  border: 0;
  border-bottom: 1px solid rgba(20, 35, 31, 0.1);
  border-radius: 0;
  background: var(--light-bg);
  backdrop-filter: none;
}

/* Always-visible search bar above the sticky filter/sort toolbar.
   On mobile the search field used to live inside the filter
   drawer which forced a 2-tap path to type — open drawer, then
   focus input. Now it's a sibling of the toolbar so the input
   is reachable in 1 tap regardless of scroll position. */
.search-sticky {
  position: sticky;
  top: 86px;
  z-index: 71;
  margin: 0 0 var(--space-3);
  padding: 6px 0;
  background: linear-gradient(180deg, rgba(11, 33, 27, 0.95) 0%, rgba(11, 33, 27, 0.85) 100%);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* Toolbar sits directly under the search bar — bump its top so
   they don't visually fight. */
.search-sticky + .sticky-tools {
  top: 152px;
}

/* The search bar is currently visually-hidden (single search lives
   in the catalog-entry card). visually-hidden is position:absolute
   so it occupies no space — without this the adjacency rule above
   still stuck the toolbar at 152px, leaving a tall gap where
   scrolled cards showed ABOVE the toolbar. Pin it back under the
   header. */
.search-sticky.visually-hidden + .sticky-tools {
  top: 86px;
}

.search-sticky-shell {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 0 12px;
  border: 1px solid rgba(198, 165, 92, 0.32);
  border-radius: 999px;
  background: rgba(15, 42, 35, 0.92);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.search-sticky-shell:focus-within {
  border-color: rgba(224, 194, 122, 0.65);
  box-shadow: 0 0 0 3px rgba(198, 165, 92, 0.18);
}
.search-sticky-shell .search-icon {
  font-size: 0.95rem;
  color: rgba(245, 229, 184, 0.65);
  flex: 0 0 auto;
}
.search-sticky-shell .search-icon-svg {
  width: 18px;
  height: 18px;
  display: block;
  flex: 0 0 auto;
  color: rgba(245, 229, 184, 0.65);
  transition: color 0.18s ease;
}
.search-sticky-shell:focus-within .search-icon-svg {
  color: var(--gold-light, #f5e5b8);
}
.search-sticky-shell input[type="search"] {
  flex: 1 1 auto;
  border: 0;
  background: transparent;
  color: var(--text);
  padding: 10px 0;
  font-size: 0.95rem;
  min-width: 0;
}
.search-sticky-shell input[type="search"]:focus {
  outline: none;
}
.search-sticky-shell input[type="search"]::placeholder {
  color: rgba(245, 229, 184, 0.5);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* SEARCH DROPDOWN — replaces the native <datalist> so we can show
   product thumbs, prices, and recent-search history. The native
   <datalist> stays in the DOM as a no-CSS fallback. */
.search-dropdown {
  position: absolute;
  left: 0;
  right: 0;
  margin-top: 6px;
  z-index: 80;
  max-height: min(420px, 70vh);
  overflow-y: auto;
  border: 1px solid rgba(198, 165, 92, 0.32);
  border-radius: 12px;
  background: rgba(13, 36, 30, 0.98);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.search-sticky {
  position: sticky;
}
.search-sticky > .search-dropdown {
  top: 100%;
}

.search-dropdown-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 14px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(198, 165, 92, 0.08);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  font-size: 0.95rem;
  transition: background 0.12s ease;
}
.search-dropdown-item:last-child {
  border-bottom: 0;
}
.search-dropdown-item:hover,
.search-dropdown-item.is-active {
  background: rgba(198, 165, 92, 0.12);
}
.search-dropdown-item-recent {
  color: rgba(245, 229, 184, 0.85);
}
.search-dropdown-icon {
  flex: 0 0 auto;
  width: 20px;
  text-align: center;
  font-size: 0.95rem;
  opacity: 0.7;
}
.search-dropdown-thumb {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid rgba(198, 165, 92, 0.2);
  background: #0d1f1a;
}
.search-dropdown-thumb-placeholder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
}
.search-dropdown-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}
.search-dropdown-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}
.search-dropdown-sub {
  font-size: 0.78rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-dropdown-price {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--gold-light, #f5e5b8);
  white-space: nowrap;
}

@media (max-width: 768px) {
  .search-dropdown {
    max-height: min(360px, 60vh);
  }
  .search-dropdown-thumb {
    width: 40px;
    height: 40px;
  }
}

/* On phones, the header is shorter so the sticky offsets need
   to come down. Also ensure the search bar feels chunky enough
   for thumb tapping. */
@media (max-width: 768px) {
  .search-sticky {
    top: 64px;
  }
  .search-sticky + .sticky-tools {
    top: 124px;
  }
  .search-sticky.visually-hidden + .sticky-tools {
    top: 64px;
  }
  .search-sticky-shell input[type="search"] {
    padding: 12px 0;
    font-size: 1rem;
  }
}

.filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: var(--btn-height-lg);
  min-height: var(--btn-height-lg);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-4);
  background: #18342d;
  color: #f5e5b8;
  border-color: rgba(168, 134, 66, 0.3);
  font-weight: 600;
  transition: all 0.2s ease;
}

.filter-toggle-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  color: rgba(245, 229, 184, 0.85);
  transition: transform 0.18s ease;
}

.filter-toggle:hover .filter-toggle-icon {
  transform: translateY(-1px);
}

.filter-toggle:hover {
  background: #1f4238;
  border-color: rgba(168, 134, 66, 0.5);
  box-shadow: 0 4px 12px rgba(24, 52, 45, 0.18);
}

.filter-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 199;
  background: rgba(0, 0, 0, 0.5);
}

.filter-backdrop.open {
  display: block;
}

.filter-panel {
  position: fixed;
  top: 0;
  right: 0;
  /* Keyboard-open guard: 100vh stays the visual viewport even when
     the soft keyboard slides up; the panel then extends below the
     keyboard and the close button sits behind it. 100dvh shrinks to
     the visible region (when supported), but the legacy 100vh below
     it still won the cascade. Drop the legacy fallback so dvh wins
     where supported, and add safe-area-inset-bottom + a bounded
     min-height so the trailing buttons stay reachable on phones.
     env(safe-area-inset-bottom) prevents the close button from
     sitting under the iPhone home indicator. */
  height: 100dvh;
  max-height: 100dvh;
  width: min(380px, 100vw);
  padding: var(--space-4);
  padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
  border-left: 1px solid rgba(198, 165, 92, 0.22);
  background: rgba(11, 33, 27, 0.99);
  box-shadow: -8px 0 32px rgba(0, 0, 0, 0.4);
  z-index: 200;
  transform: translateX(110%);
  transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
/* Browsers without 100dvh support fall back to 100vh — better than
   nothing, and the user can still scroll the panel content. */
@supports not (height: 100dvh) {
  .filter-panel { height: 100vh; max-height: 100vh; }
}

.filter-panel.open {
  transform: translateX(0);
}

/* MOBILE BOTTOM-SHEET MODE
   On phones (≤768px), the right-side drawer is awkward — the user
   has to reach with their thumb to a 380px-wide panel that doesn't
   feel like a phone-native UI. Convert it to a bottom-sheet: full
   width, rounded top, anchored to the bottom, slides up from
   below. The same JS toggle (.open class) drives the animation —
   no script changes needed. The visible drag-handle pill at the
   top is a familiar bottom-sheet affordance. */
@media (max-width: 768px) {
  .filter-panel {
    top: auto;
    right: 0;
    left: 0;
    bottom: 0;
    width: 100vw;
    height: auto;
    max-height: 85vh;
    max-height: 85dvh;
    border-left: 0;
    border-top: 1px solid rgba(198, 165, 92, 0.22);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.45);
    transform: translateY(110%);
    padding-top: calc(var(--space-4) + 14px);
    padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
  }
  .filter-panel.open {
    transform: translateY(0);
  }
  /* Drag-handle pill — pure decoration that signals "this slides
     down to dismiss" without needing a label. */
  .filter-panel::before {
    content: "";
    position: absolute;
    top: 8px;
    left: 50%;
    transform: translateX(-50%);
    width: 44px;
    height: 4px;
    border-radius: 999px;
    background: rgba(198, 165, 92, 0.45);
  }
}

.filter-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid rgba(198, 165, 92, 0.15);
  flex-shrink: 0;
}

.filter-panel-head span {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
}

.filter-panel-head .btn {
  min-height: 32px;
  padding: 4px 12px;
  font-size: 1rem;
}

.field-wrap label {
  display: inline-block;
  margin-bottom: var(--space-2);
  color: #d6d8d5;
  font-weight: 600;
}

.field-wrap.inline-controls {
  display: flex;
  flex-direction: column;
}

.range-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}

.toggle-row {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.toggle-row .btn {
  min-height: var(--btn-height-sm);
  padding: 9px var(--space-3);
}

.stock-filter-row .btn.active {
  border-color: rgba(198, 165, 92, 0.78);
  background: rgba(198, 165, 92, 0.16);
  color: var(--gold-light);
}

.active-filter-bar {
  margin: 0 0 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}

.active-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.active-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid rgba(24, 52, 45, 0.18);
  background: #18342d;
  color: #f5e5b8;
  font-size: 0.88rem;
  font-weight: 600;
}

.active-filter-chip button {
  border: 0;
  background: transparent;
  color: rgba(245, 229, 184, 0.5);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 0;
}

.active-filter-chip button:hover {
  color: #f5e5b8;
}

.btn.active {
  background: rgba(198, 165, 92, 0.18);
  border-color: var(--gold-light);
  color: var(--gold-light);
}

.section-light .field-wrap select,
.section-light .field-wrap input {
  border-color: rgba(15, 42, 35, 0.22);
  background: #ffffff;
  color: #1c2b26;
}

.sort-wrap select {
  background: #18342d !important;
  border: 1px solid rgba(198, 165, 92, 0.35) !important;
  color: #f4f4f2 !important;
  border-radius: 999px !important;
  padding: 8px 16px !important;
  font-weight: 600 !important;
  cursor: pointer !important;
  transition: border-color 0.2s ease !important;
}

.sort-wrap select:hover {
  border-color: rgba(198, 165, 92, 0.55) !important;
}

.filter-panel .field-wrap select,
.filter-panel .field-wrap input {
  background: rgba(7, 20, 16, 0.7);
  border-color: rgba(198, 165, 92, 0.22);
  color: #f4f4f2;
}

/* DZ3: 150px min packed 7-8 cramped cards per row on desktop —
   bathroom fixtures sell on imagery, so go ~4/row with a much
   bigger product image. The "Ixcham" toggle adds .cards-compact;
   it previously had NO css (dead toggle), so wiring the dense
   variant here both fixes density AND makes that control mean
   something for users who want more per screen. */
.cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 22px;
  align-items: stretch;
  align-content: start;
  grid-auto-rows: max-content;
}

.cards-grid.cards-compact {
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 14px;
}
