/* ============================================================
   LAKUSH SUPPLY — Design System
   Baby-blue streetwear e-commerce aesthetic

   Flipped from the original all-black theme to baby blue. Because the page
   went light, the ink had to invert too: --text is now near-black and the
   greys were rebuilt as *darker* muted tones, otherwise every label on the
   site would have been white-on-pale-blue and unreadable.
   ============================================================ */

:root {
  --bg: #a9dcf5;
  --surface: #bde6f8;
  --surface-2: #d2eefb;
  --border: #57a0c7;
  --border-light: #3f8cb7;
  --text: #0c1a22;
  --text-muted: #35596b;
  /* Deliberately darker than a normal "faint" grey: this colour carries small
     copy (SKUs, breadcrumbs, legal, price strikethroughs) and the lighter tone
     the black theme used measured 2.7:1 on baby blue, well under the 4.5:1
     minimum for body text. */
  --text-faint: #3b6173;
  --red: #d81f2a;
  --radius: 0px;
  --radius-sm: 0px;
  --radius-lg: 0px;
  --shadow: 0 12px 28px rgba(12,26,34,.22);
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --container: 1280px;
}

* { box-sizing: border-box; }
/* No global scroll-behavior: smooth — it makes window.scrollTo()'s default
 * ('auto') animate too, and that animation is exactly what a still-decelerating
 * touch-momentum scroll can interrupt (reads as "works, then doesn't,
 * alternating"). The couple of spots that want a smooth glide (main.js) pass
 * behavior: 'smooth' explicitly on the call, which animates regardless of
 * this rule being gone. */
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
ul { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, h4 { font-family: var(--font-body); margin: 0; font-weight: 800; letter-spacing: -.01em; }
.container { max-width: var(--container); margin: 0 auto; padding: 0 24px; }
.section { padding: 56px 0; }
/* Used by the homepage category grid, where 56px top and bottom was eating the
   height the tiles needed to fit on one screen. */
/* Two class selectors deliberately: the 860px breakpoint further down restyles
   `.section` to 40px padding, and with equal specificity that later rule would
   win and undo this on every phone. */
.section.section--tight { padding: 16px 0; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--text-muted);
}
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 24px; flex-wrap: wrap; border-bottom: 1px solid var(--border); padding-bottom: 16px; }
.section-head h2 { font-size: 20px; letter-spacing: 1px; text-transform: uppercase; color: var(--text); }
.section-head .view-all { font-size: 12px; font-weight: 600; letter-spacing: .5px; text-transform: uppercase; color: var(--text-muted); white-space: nowrap; }
.section-head .view-all:hover { color: var(--text); }

/* ---------- Buttons (invert-on-hover, sharp corners) ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px; padding: 12px 26px; border-radius: 0; border: 1px solid var(--text);
  font-size: 12.5px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
  transition: background .15s ease, color .15s ease; white-space: nowrap;
}
/* Filled buttons are dark-on-blue now, so the label has to be the page colour
   rather than the hard #000 it used when the button itself was white. */
.btn-primary { background: var(--text); color: var(--bg); }
.btn-primary:hover { background: transparent; color: var(--text); }
.btn-outline { background: transparent; color: var(--text); }
.btn-outline:hover { background: var(--text); color: var(--bg); }
.btn-sm { min-height: 38px; padding: 8px 16px; font-size: 11px; }
.btn-block { width: 100%; }

/* ---------- Marquee / ticker strip ---------- */
.ticker { border-bottom: 1px solid var(--border); background: var(--bg); overflow: hidden; }
.ticker .container { display: flex; align-items: center; justify-content: center; height: 38px; }
.ticker-text {
  font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- Utility bar (search / login / cart) ---------- */
.utility-bar { border-bottom: 1px solid var(--border); }
.utility-bar .container { display: flex; align-items: center; justify-content: flex-end; gap: 20px; height: 38px; }
.utility-link { font-size: 11px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--text-muted); display: flex; align-items: center; gap: 6px; }
.utility-link:hover { color: var(--text); }
.utility-link svg { width: 14px; height: 14px; }

/* ---------- Header ---------- */
.header {
  position: sticky; top: 0; z-index: 50; background: var(--bg); border-bottom: 1px solid var(--border);
}
.header-logo-row { display: flex; align-items: center; justify-content: center; position: relative; padding: 16px 24px; }
.logo { font-size: clamp(24px, 4.5vw, 38px); font-weight: 900; letter-spacing: 2px; color: var(--text); text-transform: uppercase; }
/*
 * Left cluster: menu button + the three contact icons.
 *
 * The burger used to be absolutely positioned on its own. It now lives in this
 * flex group so the contact icons can queue up next to it without the two
 * overlapping on narrow screens.
 */
.header-left { position: absolute; left: 24px; top: 50%; transform: translateY(-50%); display: flex; align-items: center; gap: 2px; }
.burger { display: none; background: none; border: none; color: var(--text); width: 40px; height: 40px; align-items: center; justify-content: center; }
.header-icons { position: absolute; right: 24px; top: 50%; transform: translateY(-50%); display: flex; align-items: center; gap: 14px; }
.icon-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; color: var(--text); }
.icon-btn svg { width: 19px; height: 19px; }
/* Contact icons — a touch smaller than search/cart so they read as secondary. */
.icon-btn--chat svg { width: 17px; height: 17px; }
.icon-btn--chat { color: var(--text-muted); }
.icon-btn--chat:hover { color: var(--text); }
.badge { position: absolute; top: 0; right: 0; background: var(--text); color: var(--bg); font-size: 10px; font-weight: 800; width: 15px; height: 15px; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.mobile-only { display: none; }

.main-nav-row { border-top: 1px solid var(--border); }
.main-nav { display: flex; align-items: center; justify-content: center; gap: 0; flex-wrap: wrap; }
.main-nav > li > a {
  display: block; padding: 16px 18px; font-size: 12.5px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
  color: var(--text-muted); transition: color .15s;
}
.main-nav > li > a:hover { color: var(--text); }

/* ---------- Header logo image (LaKush Supply wordmark) ---------- */
/*
 * Bigger than it was — 46px max became 66px, 30px floor became 40px.
 *
 * The row padding came down at the same time (20px → 16px desktop, 16px → 12px
 * mobile). A taller header pushes the category grid down, and the homepage is
 * built to fit one screen; without the trim, a 1280x800 laptop went 2px over.
 */
.header-logo-row .logo { display: inline-flex; align-items: center; }
.header-logo-img { height: clamp(40px, 5.6vw, 66px); width: auto; display: block; }

/* ---------- Search / mobile drawer ---------- */
.drawer { position: fixed; inset: 0; z-index: 100; display: none; }
.drawer.open { display: block; }
.drawer-backdrop { position: absolute; inset: 0; background: rgba(8,26,36,.55); }
.drawer-panel { position: absolute; top: 0; left: 0; bottom: 0; width: 82%; max-width: 320px; background: var(--surface); border-right: 1px solid var(--border); padding: 24px; overflow-y: auto; }
.drawer-panel .logo { margin-bottom: 24px; font-size: 22px; display: block; }
/* Real wordmark in the drawer, matching the header — it used to be the plain
   text brand name. */
.drawer-logo-img { width: 100%; max-width: 190px; height: auto; display: block; margin-bottom: 22px; }
.drawer-panel li a { display: block; padding: 14px 0; font-weight: 700; text-transform: uppercase; font-size: 13px; letter-spacing: .5px; border-bottom: 1px solid var(--border); }

/* ---------- Product grid & card ---------- */
.grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); }
/* A shade lighter than the page so cards still read as cards — on the old black
   theme they matched the background and the 1px grid gap did all the work. */
.card { background: var(--surface-2); display: flex; flex-direction: column; }
.card-media { position: relative; aspect-ratio: 1/1; overflow: hidden; }
.card-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Only cards with a real matched photo open the lightbox — plain placeholder
   swatches have nothing to preview, so they stay inert (see wireCardMediaLightbox). */
.card-media--clickable { cursor: zoom-in; }
.card-tags { position: absolute; top: 10px; left: 10px; display: flex; flex-direction: column; gap: 6px; }
.tag { font-size: 10px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; padding: 4px 8px; }
.tag-out { background: #000; color: #fff; border: 1px solid #000; }
/* Same red-ring urgency language as the Fire Sale category tile, so "running
   low" reads as the same kind of signal site-wide rather than a one-off. */
.tag-low {
  background: #000; color: var(--red); border: 1px solid var(--red);
  animation: tag-low-pulse 1.8s ease-in-out infinite;
}
@keyframes tag-low-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(216,31,42,.5); }
  50% { box-shadow: 0 0 0 4px rgba(216,31,42,0); }
}
@media (prefers-reduced-motion: reduce) {
  .tag-low { animation: none; }
}
.card-quick { position: absolute; top: 10px; right: 10px; display: flex; flex-direction: column; gap: 6px; opacity: 0; transition: opacity .15s; }
.card:hover .card-quick { opacity: 1; }
.qbtn { width: 30px; height: 30px; background: #fff; border: 1px solid #000; display: flex; align-items: center; justify-content: center; color: #000; }
/* These sit on the near-white product tile, not the page, so they stay
   black-on-white. The hover border stays dark — white would disappear. */
.qbtn:hover { background: #000; color: #fff; border-color: #000; }
.qbtn svg { width: 13px; height: 13px; }
.card-body { padding: 14px 16px 20px; display: flex; flex-direction: column; gap: 4px; flex: 1; }
.card-cat { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .5px; color: var(--text-faint); }
.card-title { font-size: 12.5px; font-weight: 700; letter-spacing: .2px; text-transform: uppercase; color: var(--text); }
.card-title a:hover { color: var(--text-muted); }
.card-price { font-size: 13px; font-weight: 600; margin-top: 2px; }
.card-price .was { color: var(--text-faint); text-decoration: line-through; font-weight: 500; font-size: 12px; margin-right: 6px; }
.card-price .now { color: var(--text); }
.card-add { margin-top: auto; padding-top: 12px; }

/* flat near-white placeholder tones (photography stand-in) */
.p1 { background: #ececec; }
.p2 { background: #e6e6e2; }
.p3 { background: #e3e6e6; }
.p4 { background: #e8e4e6; }
.p5 { background: #e5e8e2; }
.p6 { background: #e8e2df; }

/* ---------- Shop-by-category tiles ---------- */
/* White rounded cards on the baby-blue page, one photo tile per category — the
   product shots aren't in yet, so `.category-blob` is a stand-in; swap each
   for a real `<img>` inside `.category-media` when photography is ready. */
/*
 * Two columns at every screen size — seven tiles, so four rows.
 *
 * Capped at 560px and centred: stretched across a 1280px container, a 2-column
 * grid gives 610px-wide tiles holding a ~100px image, which reads as letterboxed
 * strips rather than tiles. Narrow keeps them close to square.
 *
 * Height comes from viewport height (`10.5vh`) rather than fixed pixels, because
 * four rows have to fit the screen — with a `max-width` cap for narrow screens,
 * where tile width runs out before height does.
 */
.category-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;
  max-width: 560px; margin-left: auto; margin-right: auto;
}
.category-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  background: #ececec; border-radius: 16px; padding: 14px 10px 12px; gap: 10px;
  transition: transform .15s ease, box-shadow .15s ease;
}
.category-card:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(12,26,34,.25); }
.category-media {
  height: clamp(48px, 10.5vh, 150px); width: auto; max-width: 62%; aspect-ratio: 1/1;
  display: flex; align-items: center; justify-content: center;
}
/*
 * dvh, not vh, wherever this height is set.
 *
 * On phones `100vh` means the viewport with the browser's address and tab bars
 * *ignored* — about 135px more than you can actually see on an iPhone. Sizing
 * against it pushed the bottom row under the browser chrome. `dvh` tracks the
 * genuinely visible height. The vh line above stays as the fallback for older
 * browsers.
 */
@supports (height: 1dvh) {
  .category-media { height: clamp(48px, 10.5dvh, 150px); }
}
.category-media img { width: 100%; height: 100%; object-fit: contain; }
.category-blob { width: 100%; height: 100%; border-radius: 50%; filter: blur(1px); opacity: .9; }
/* Scales with width so "Concentrates" still fits a narrow tile on one line. */
.category-name {
  font-size: clamp(9px, 1vw + 4px, 13px); font-weight: 800; letter-spacing: .2px;
  color: #111; text-transform: none; line-height: 1.2;
}

/* Fire Sale: hotter than the rest and given a warm ring so it reads as the
   promo tile rather than just another category. */
.cat-firesale { background: radial-gradient(circle at 40% 25%, #ffd54a, #ff7a18 45%, #d81f2a); }
.category-card--fire { box-shadow: inset 0 0 0 2px #d81f2a; }
.category-card--fire .category-name { color: #d81f2a; }

.cat-flower { background: radial-gradient(circle at 35% 30%, #7c9a5e, #3f5a2c); }
.cat-wax { background: radial-gradient(circle at 35% 30%, #f2b23a, #c97f0e); }
.cat-snowballs { background: radial-gradient(circle at 35% 30%, #d8d4c8, #a29c8a); }
.cat-moonrocks { background: radial-gradient(circle at 35% 30%, #cfc7a8, #8f8664); }
.cat-vapes { background: radial-gradient(circle at 35% 30%, #6fb3c4, #2f7183); }
.cat-prerolls { background: radial-gradient(circle at 35% 30%, #d99a6c, #9c5b2e); }
.cat-edibles { background: radial-gradient(circle at 35% 30%, #d67a8a, #a13a52); }
.cat-mushies { background: radial-gradient(circle at 35% 30%, #b79ad6, #6c4a94); }
.cat-merch { background: radial-gradient(circle at 35% 30%, #9a9a9a, #4a4a4a); }

/*
 * Phones: all seven categories, two columns, no scrolling.
 *
 * Everything here is shaved to buy vertical room — the desktop paddings put an
 * iPhone SE 122px over its visible height. Measured to fit portrait on SE through
 * 14 Pro Max, Pixel 7 and Galaxy S21.
 */
@media (max-width: 680px) {
  .category-grid { gap: 8px; }
  .category-card { padding: 8px 6px; gap: 6px; border-radius: 12px; }
  .category-media { height: clamp(36px, 9.5vh, 130px); max-width: 72%; }
  .category-name { font-size: clamp(9px, 3vw, 12px); }
  .section.section--tight { padding: 10px 0; }
}
@supports (height: 1dvh) {
  @media (max-width: 680px) {
    .category-media { height: clamp(36px, 9.5dvh, 130px); }
  }
}
/*
 * Short windows.
 *
 * Four rows is the tight case: at 700px tall the standard sizing overflowed by
 * ~30px. Trimming padding and easing the media brings it back inside. Two-class
 * selector again, to survive the later `.section` rule at the 860px breakpoint.
 */
@media (max-height: 760px) {
  .section.section--tight { padding: 10px 0; }
  .category-media { height: clamp(44px, 9vh, 150px); }
}

/* ---------- CTA band ---------- */
.cta-band { border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.cta-band .container { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 40px 24px; flex-wrap: wrap; }
.cta-band h3 { font-size: 18px; letter-spacing: 1px; text-transform: uppercase; margin-bottom: 4px; }
.cta-band p { color: var(--text-muted); font-size: 13.5px; }
.cta-band .actions { display: flex; gap: 10px; flex-wrap: wrap; }
/* Buttons-only variant: with the heading and blurb gone there's nothing to sit
   opposite, so centre them instead of leaving them pushed to the right edge. */
.cta-band.cta-band--links .container { justify-content: center; align-items: center; padding: 16px 24px; }
.cta-band.cta-band--links .actions { justify-content: center; }

/* ---------- Footer ---------- */
.footer { border-top: 1px solid var(--border); padding-top: 44px; font-size: 14px; }
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: 32px; padding-bottom: 32px; border-bottom: 1px solid var(--border); }
.footer h4 { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--text); margin-bottom: 16px; font-weight: 800; }
.footer-grid p { color: var(--text-muted); font-size: 13px; line-height: 1.7; max-width: 320px; }
.footer-grid li { margin-bottom: 9px; }
.footer-grid a { color: var(--text-muted); font-size: 13px; }
.footer-grid a:hover { color: var(--text); }
.footer-contact { display: flex; flex-direction: column; gap: 10px; }
.footer-contact a { display: inline-flex; align-items: center; gap: 8px; color: var(--text-muted); font-weight: 600; font-size: 13px; text-transform: uppercase; letter-spacing: .3px; }
.footer-contact a:hover { color: var(--text); }
.footer-contact .dot { width: 5px; height: 5px; background: var(--text); flex-shrink: 0; }
.pay-row { font-size: 11px; letter-spacing: .5px; text-transform: uppercase; color: var(--text-faint); margin-top: 14px; }
.footer-legal { padding: 22px 0 26px; color: var(--text-faint); font-size: 11px; line-height: 1.8; }
.footer-legal p { margin: 0 0 10px; }
.footer-bottom { display: flex; justify-content: space-between; align-items: center; padding: 18px 0; border-top: 1px solid var(--border); color: var(--text-faint); font-size: 11.5px; text-transform: uppercase; letter-spacing: .3px; flex-wrap: wrap; gap: 10px; }
.footer-bottom .links { display: flex; gap: 18px; }
.footer-bottom .links a:hover { color: var(--text); }

/* ---------- Breadcrumb ---------- */
.breadcrumb { padding: 16px 0; font-size: 11.5px; text-transform: uppercase; letter-spacing: .3px; color: var(--text-faint); border-bottom: 1px solid var(--border); }
.breadcrumb .container { display: flex; flex-wrap: wrap; row-gap: 4px; }
.breadcrumb a:hover { color: var(--text); }
.breadcrumb .sep { margin: 0 8px; }
.breadcrumb .current { color: var(--text-muted); overflow-wrap: anywhere; }
/* A full three-part crumb ("Home / Prerolls / Boutique Snack Pack Prerolls
   Preroll Cart") is long — shrink the type and tighten the separators so it
   wraps to a clean second line instead of crowding/overflowing on a phone. */
@media (max-width: 520px) {
  .breadcrumb { font-size: 10.5px; letter-spacing: .2px; }
  .breadcrumb .sep { margin: 0 5px; }
}

/* ---------- Shop layout ---------- */
.shop-layout { display: grid; grid-template-columns: 230px 1fr; gap: 32px; align-items: start; }
.filter-box { border: 1px solid var(--border); padding: 18px; margin-bottom: 14px; }
.filter-box h4 { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 14px; color: var(--text-muted); }
.filter-row { display: flex; align-items: center; justify-content: space-between; padding: 7px 0; font-size: 13px; color: var(--text-muted); min-height: 32px; }
.filter-row:hover { color: var(--text); }
.filter-row input { accent-color: var(--text); width: 15px; height: 15px; }
.filter-row .count { font-size: 11px; color: var(--text-faint); }
.range-slider { width: 100%; accent-color: var(--text); margin: 10px 0; }
.shop-toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 22px; flex-wrap: wrap; gap: 12px; border-bottom: 1px solid var(--border); padding-bottom: 18px; }
.shop-toolbar .count-txt { color: var(--text-muted); font-size: 12.5px; text-transform: uppercase; letter-spacing: .3px; }
.select {
  background: transparent; border: 1px solid var(--border-light); color: var(--text);
  padding: 10px 14px; border-radius: 0; font-size: 12px; font-weight: 700; min-height: 40px;
  text-transform: uppercase; letter-spacing: .5px;
}
.pagination { display: flex; gap: 0; justify-content: center; margin-top: 36px; border: 1px solid var(--border); width: fit-content; margin-left: auto; margin-right: auto; }
.pagination a, .pagination span { min-width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; border-right: 1px solid var(--border); font-size: 12px; font-weight: 700; padding: 0 6px; }
.pagination a:last-child, .pagination span:last-child { border-right: none; }
.pagination .active { background: var(--text); color: var(--bg); }
.pagination a:hover { color: var(--text); background: var(--surface-2); }

/* ---------- Product detail ---------- */
.product-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; }
.gallery-main { aspect-ratio: 1/1; margin-bottom: 10px; border: 1px solid var(--border); }
/* Real-photo variant: main.js swaps this in once assets/image-map.json has a
   match for the item; height is driven by .gallery-frame instead of the
   placeholder's own aspect-ratio, since a thumb row sits below it. */
.gallery-main--photo { aspect-ratio: auto; border: none; }
.gallery-frame { position: relative; aspect-ratio: 1/1; border: 1px solid var(--border); overflow: hidden; }
.gallery-frame img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.gallery-thumbs { display: flex; gap: 8px; margin-top: 8px; }
.gallery-thumb { width: 64px; height: 64px; flex-shrink: 0; padding: 0; border: 1px solid var(--border); background: none; opacity: .6; }
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-thumb:hover { opacity: .85; }
.gallery-thumb.active { opacity: 1; border-color: var(--text); }

/* Prev/next arrows sitting directly on the hero photo — always visible (no
   hover-reveal) since touch devices have no hover state to reveal them with. */
.gallery-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px; border-radius: 50%;
  background: rgba(255,255,255,.85); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1; color: var(--text); cursor: pointer;
}
.gallery-nav:hover { background: #fff; }
.gallery-nav--prev { left: 10px; }
.gallery-nav--next { right: 10px; }

/* ---------- Lightbox (full-screen photo viewer) ----------
   One shared overlay built lazily by ensureLightbox() in main.js and reused
   across whichever product opens it; state (images/index) lives in JS. */
.lightbox { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; }
.lightbox[hidden] { display: none; }
.lightbox:not([hidden]) { animation: lightbox-fade .18s ease; }
@keyframes lightbox-fade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .lightbox:not([hidden]) { animation: none; } }
body.lightbox-open { overflow: hidden; }
.lightbox-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.9); }
.lightbox-img { position: relative; z-index: 1; max-width: 90vw; max-height: 88vh; object-fit: contain; }
.lightbox-close {
  position: absolute; top: 16px; right: 16px; z-index: 2;
  width: 44px; height: 44px; background: transparent; border: none;
  color: #fff; font-size: 30px; line-height: 1; cursor: pointer;
}
.lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 52px; height: 52px; border-radius: 50%;
  background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.35);
  color: #fff; font-size: 28px; line-height: 1;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.lightbox-nav:hover { background: rgba(255,255,255,.24); }
.lightbox-nav--prev { left: 12px; }
.lightbox-nav--next { right: 12px; }
@media (max-width: 520px) {
  .lightbox-nav { width: 44px; height: 44px; font-size: 24px; }
  .lightbox-nav--prev { left: 6px; }
  .lightbox-nav--next { right: 6px; }
}
.product-info .card-cat { font-size: 11px; }
.product-title { font-size: 20px; font-weight: 800; margin: 8px 0 12px; letter-spacing: .3px; text-transform: uppercase; }
.product-price { font-size: 18px; font-weight: 700; color: var(--text); margin-bottom: 14px; }

/* ---------- Stock meter (product page) ----------
   Fill width and label are set in JS (initProductPage) from real qty against
   SalesBinder's own reorder threshold, falling back to DEFAULT_LOW_STOCK_THRESHOLD
   while that field's unconfigured. Plain dark fill when stock is unremarkable;
   red + a slow pulse once it's genuinely low, echoing the same red-ring
   urgency language as the Fire Sale tile and the .tag-low card badge. */
.stock-meter { margin-bottom: 20px; max-width: 280px; }
.stock-meter-track { height: 6px; background: var(--surface-2); border: 1px solid var(--border); overflow: hidden; }
.stock-meter-fill { height: 100%; width: 0%; background: var(--text); transition: width .5s ease; }
.stock-meter-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px; color: var(--text-muted); margin-top: 7px; }
.stock-meter--low .stock-meter-fill { background: var(--red); animation: stock-fill-pulse 1.8s ease-in-out infinite; }
.stock-meter--low .stock-meter-label { color: var(--red); }
.stock-meter--out .stock-meter-fill { background: var(--text-faint); }
.stock-meter--out .stock-meter-label { color: var(--text-faint); }
@keyframes stock-fill-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .5; }
}
@media (prefers-reduced-motion: reduce) {
  .stock-meter--low .stock-meter-fill { animation: none; }
}

.qty-add { display: flex; gap: 10px; align-items: center; margin-bottom: 22px; }
.qty-box { display: flex; align-items: center; border: 1px solid var(--border-light); }
.qty-box button { width: 40px; height: 46px; background: transparent; border: none; color: var(--text); font-size: 16px; }
.qty-box button:hover { color: var(--text-muted); }
.qty-box input { width: 40px; text-align: center; background: transparent; border: none; color: var(--text); font-size: 14px; }
.product-meta-row { display: flex; gap: 20px; font-size: 12px; text-transform: uppercase; letter-spacing: .3px; color: var(--text-muted); border-top: 1px solid var(--border); padding-top: 16px; flex-wrap: wrap; }

/* ---------- Cart page ---------- */
.cart-layout { display: grid; grid-template-columns: 1fr 360px; gap: 40px; align-items: start; }
.cart-row { display: grid; grid-template-columns: 80px 1fr auto auto auto; gap: 16px; align-items: center; padding: 18px 0; border-bottom: 1px solid var(--border); }
.cart-thumb { width: 72px; height: 72px; position: relative; overflow: hidden; }
.cart-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cart-remove { display: inline-flex; padding: 8px; color: var(--text-faint); }
.cart-remove:hover { color: var(--text); }
.summary-box { border: 1px solid var(--border); padding: 24px; }
.summary-box h3 { font-size: 14px; letter-spacing: 1px; text-transform: uppercase; margin-bottom: 18px; font-weight: 800; }
.summary-row { display: flex; justify-content: space-between; padding: 10px 0; font-size: 13px; text-transform: uppercase; letter-spacing: .3px; color: var(--text-muted); border-bottom: 1px solid var(--border); }
.summary-row.total { color: var(--text); font-weight: 800; font-size: 15px; border-bottom: none; padding-top: 14px; }
.coupon-row { display: flex; gap: 8px; margin: 16px 0; }
.coupon-row input { flex: 1; background: transparent; border: 1px solid var(--border-light); padding: 11px 14px; color: var(--text); font-size: 12.5px; min-height: 40px; text-transform: uppercase; letter-spacing: .3px; }
.empty-cart { text-align: center; padding: 72px 24px; color: var(--text-muted); }

/* ---------- Checkout: order note + invoice send panel ---------- */
.order-note-label {
  display: block; margin-top: 16px; margin-bottom: 6px;
  font-size: 10px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase;
  color: var(--text-muted);
}
.order-note {
  width: 100%; background: transparent; border: 1px solid var(--border-light);
  padding: 10px 12px; color: var(--text); font-family: inherit; font-size: 13px;
  resize: vertical;
}
.order-note:focus { outline: none; border-color: var(--text); }

.send-panel { margin-top: 18px; border-top: 1px solid var(--border); padding-top: 16px; }
.send-panel[hidden] { display: none; }
.send-panel h4 {
  font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
  margin-bottom: 8px; color: var(--text);
}
.send-hint { font-size: 12px; line-height: 1.6; color: var(--text-muted); margin: 0 0 12px; }
.send-actions { display: flex; flex-direction: column; gap: 8px; }
/* Buttons are stacked and full-width in a 360px sidebar; side by side they'd
   wrap mid-label. */
.send-actions .btn { width: 100%; }

#checkout-btn[disabled] { opacity: .45; cursor: not-allowed; }

/* ---------- Responsive ---------- */
/* Base/desktop state — hidden here so the 860px media query below can turn it
   back on for mobile. Declaring it after that query instead (as it was) wins
   the cascade on source order alone, regardless of viewport, and hides the
   button everywhere: see the cta-band note further down for the same trap. */
.filter-toggle-btn { display: none; }
@media (max-width: 1080px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .product-layout { grid-template-columns: 1fr; }
  .cart-layout { grid-template-columns: 1fr; }
}
@media (max-width: 860px) {
  .main-nav-row { display: none; }
  .burger { display: flex; }
  .mobile-only { display: inline-flex !important; }
  /*
   * Phones: lay the header out with flex instead of absolute positioning.
   *
   * Absolutely positioned side clusters don't know the centred logo exists — at
   * 360px the left cluster (burger + 3 contact icons) ran straight under it.
   * space-between keeps all three apart, tighter side padding buys the width
   * back, and flex-wrap is the safety net on anything narrower still.
   */
  .header-logo-row { padding: 12px 16px; justify-content: space-between; gap: 6px; flex-wrap: wrap; }
  .header-left,
  .header-icons { position: static; transform: none; }
  .header-icons { gap: 6px; }
  .header-logo-img { height: clamp(30px, 9vw, 40px); }
  .icon-btn--chat { width: 30px; }
  .utility-bar .container { justify-content: center; gap: 16px; }
  .grid { grid-template-columns: repeat(2, 1fr); }
  .shop-layout { grid-template-columns: 1fr; }
  .cta-band .container { flex-direction: column; align-items: flex-start; }
  .filter-toggle-btn { display: inline-flex; }
  .filters-col { display: none; }
  .filters-col.open { display: block; }
  .section { padding: 40px 0; }
  .product-title { font-size: 17px; }
}
@media (max-width: 520px) {
  .footer-grid { grid-template-columns: 1fr; }
  .container { padding: 0 16px; }
  .cart-row { grid-template-columns: 60px 1fr; row-gap: 10px; }
  .cart-row > *:nth-child(3) { grid-column: 2; }
  .cart-row > *:nth-child(4) { grid-column: 2; }
  .cart-row > *:nth-child(5) { grid-column: 2; justify-self: start; }
  .qty-add { flex-wrap: wrap; }
  .qty-add .btn { width: 100%; order: 3; }
}

/*
 * Join-button band padding — last in the file on purpose.
 *
 * The base `.cta-band--links` rule is declared further up, near the CTA band.
 * Media queries carry no extra specificity, so an equally specific base rule
 * declared *after* a media query still wins; putting these at the end is what
 * makes them stick instead of quietly losing the height they're meant to save.
 */
@media (max-width: 680px) {
  .cta-band.cta-band--links .container { padding: 8px 16px; align-items: center; }
}
@media (max-height: 760px) {
  .cta-band.cta-band--links .container { padding: 10px 24px; }
}

/*
 * Touch targets.
 *
 * Apple and Android both put the minimum tappable size at ~44px. Several
 * controls were sized for a mouse cursor and came in under that — the burger at
 * 40, the header icons at 36, the cart's remove "x" at 32. Padded out rather
 * than visually enlarged, so nothing about the layout changes.
 */
@media (hover: none) and (pointer: coarse) {
  .burger { width: 44px; height: 44px; }
  /* Contact icons excluded: three of them at 44px alongside the burger, logo and
     cart overflows a 360px header. They stay 30px wide with full height, which
     keeps a 30x44 hit area — narrow but tall enough to hit reliably. */
  .icon-btn:not(.icon-btn--chat) { width: 44px; height: 44px; }
  .icon-btn--chat { height: 44px; }
  .cart-remove { padding: 14px; }
  .btn-sm { min-height: 44px; }
  /* Pagination and category-filter rows weren't in scope for the original pass
     below — both were static/decorative back then. Real pagination (up to 54
     pages) and real per-category filtering made them genuinely tap-heavy, so
     they get the same treatment now: padded out, not resized, so the layout
     doesn't shift. */
  .pagination a, .pagination span { min-width: 44px; min-height: 44px; }
  .filter-row { min-height: 44px; }
  .filter-row input { width: 20px; height: 20px; }
  /* Stops iOS zooming the page when a text field is focused, which happens on
     any input under 16px and leaves the layout scrolled sideways. */
  .order-note,
  .coupon-row input,
  .qty-box input,
  .select { font-size: 16px; }
}
