/* =========================================================================
   DESIGN TOKENS
   Sleeker pass: thin light borders instead of thick black ones, soft
   blurred shadows instead of hard flat offsets, and an actual radius
   scale (there wasn't one before — every corner was square). Brand reds
   and navy are softened a shade too. Everything below keeps the exact
   same selectors as before — only the token *values* and the odd
   `border-radius`/`overflow` addition changed, so nothing that reads
   these classes elsewhere needs to change to pick this up.
   ========================================================================= */
:root{
  --bg:#FFFFFF;
  --surface:#FFFFFF;
  --ink:#14171C;
  --ink-soft:#565B66;
  --line:#DCE1E8;
  --red:#D8455C;
  --accent:#2D6CDF;
  --accent-light:#8FB8FF;
  --navy:#2C4A85;
  --navy-soft:#4A6BA8;
  --green:#2F7D53;
  --font-display:'Archivo Black', sans-serif;
  --font-body:'IBM Plex Sans', sans-serif;
  --font-mono:'IBM Plex Mono', monospace;

  /* New: border/radius/shadow scale — didn't exist before (everything was
     a flat 2px black border with a hard offset shadow and 0 radius). */
  --border-w:1.5px;
  --radius-sm:0px;
  --radius:0px;
  --radius-lg:0px;
  --radius-pill:0px;
  --shadow-sm:0 2px 8px rgba(20,23,28,0.08);
  --shadow:0 4px 16px rgba(20,23,28,0.10);
  --shadow-lg:0 10px 30px rgba(20,23,28,0.14);
}
*{box-sizing:border-box; margin:0; padding:0;}
html{scroll-behavior:smooth;}
body{
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font-body);
  -webkit-font-smoothing:antialiased;
}
a{color:inherit; text-decoration:none;}
button{font-family:inherit; cursor:pointer;}
img,svg{display:block; max-width:100%;}
ul{list-style:none;}
.wrap{max-width:1240px; margin:0 auto; padding:0 28px;}

/* Sitewide form-field base — anywhere a plain <input>/<select>/<textarea>
   shows up (product variation dropdowns, comment forms, checkout, account
   forms), it should look deliberate, not like unstyled browser defaults. */
input[type="text"], input[type="email"], input[type="tel"], input[type="number"],
input[type="password"], input[type="url"], input[type="search"], input.input-text,
select, textarea{
  width:100%; border:var(--border-w) solid var(--line); border-radius:var(--radius-sm);
  padding:12px 14px; font-family:var(--font-body);
  font-size:14px; background:var(--bg); color:var(--ink);
}
input:focus, select:focus, textarea:focus{outline:none; border-color:var(--red);}

:focus-visible{outline:3px solid var(--red); outline-offset:2px;}

@media (prefers-reduced-motion: reduce){
  *{animation-duration:0.001ms !important; animation-iteration-count:1 !important; transition-duration:0.001ms !important;}
}

/* ---------- NAV ---------- */

/* position:sticky (not fixed) deliberately kept — it still reserves its
   own space in normal flow, so nothing below needs compensating padding.
   The .nav--hidden translate is added/removed by assets/js/header-scroll.js
   based on scroll direction: slides up out of view on scroll down, slides
   back in on scroll up (or near the very top of the page) — see that file
   for the exact thresholds. */
header.nav{
  position:sticky; top:0; z-index:50;
  background:var(--bg);
  border-bottom:1px solid var(--line);
  transform:translateY(0);
  transition:transform 0.25s ease;
}
header.nav.nav--hidden{transform:translateY(-100%);}
.nav-inner{
  display:flex; align-items:center; justify-content:space-between;
  padding:16px 28px; max-width:1240px; margin:0 auto;
  gap:16px;
}
.logo-block{display:flex; align-items:center; flex-shrink:0;}
.site-logo-img{height:38px; width:auto; max-width:220px; object-fit:contain; display:block;}
.footer-brand .site-logo-img{height:34px;}
/* Header logo only — 1.5x the shared base size (38px → 57px,
   220px → 330px max-width). Scoped to .nav specifically so the footer's
   own logo (still the shared base size via .footer-brand above) isn't
   affected. */
.nav .site-logo-img{height:57px; max-width:330px;}
nav.links{display:flex; align-items:center; font-size:13px; font-weight:500; flex-wrap:nowrap;}
/* wp_nav_menu() always wraps the actual menu items in a <ul>, one level
   inside the <nav class="links"> container — so the flex row needs to be
   set on that inner <ul>, not just the outer <nav>, or the items stack
   vertically like an ordinary list. (Only relevant if nav.links is used
   directly somewhere again — header.php now renders the primary menu
   inside the browse drawer instead, see header-nav.css.) */
nav.links ul{display:flex; align-items:center; gap:16px; list-style:none; flex-wrap:nowrap;}
nav.links li{list-style:none;}
nav.links a{position:relative; padding:4px 0; white-space:nowrap;}
nav.links a:hover{color:var(--red);}
.nav-actions{display:flex; align-items:center; gap:14px; flex-shrink:0;}
.icon-btn{
  width:34px; height:34px; border:var(--border-w) solid var(--line); border-radius:var(--radius-sm);
  background:var(--surface);
  display:flex; align-items:center; justify-content:center; position:relative;
  flex-shrink:0; transition:border-color 0.15s ease, background 0.15s ease;
}
.icon-btn:hover{border-color:var(--accent);}
.icon-btn svg{width:16px; height:16px;}
.icon-btn .badge{
  position:absolute; top:-8px; right:-8px; background:var(--red); color:#fff;
  font-family:var(--font-mono); font-size:10px; font-weight:600;
  width:18px; height:18px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  border:2px solid var(--bg);
}
.icon-btn.is-member{background:var(--navy); border-color:var(--navy); color:#fff;}

/* ---------- Icon button tooltips ----------
   Sitewide (header.php's nav-actions icons render on every page) — a
   plain aria-label tells a screen reader what each icon does, but a
   sighted mouse user got nothing until they clicked. data-tooltip="..."
   on any element (currently just the nav-actions icons) shows a small
   label on hover/focus via ::after — no JS needed. Hidden entirely on
   touch devices: :hover has no clean touch equivalent and can otherwise
   leave a tooltip "stuck" open after a tap until the next one elsewhere. */
[data-tooltip]{position:relative;}
[data-tooltip]::after{
  content:attr(data-tooltip);
  position:absolute; top:calc(100% + 10px); left:50%; transform:translateX(-50%) translateY(-4px);
  background:var(--ink); color:#fff; font-family:var(--font-mono); font-size:11px; font-weight:600; letter-spacing:0.02em;
  padding:6px 10px; border-radius:var(--radius-sm); white-space:nowrap;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity 0.15s ease, transform 0.15s ease;
  z-index:60;
}
[data-tooltip]::before{
  content:''; position:absolute; top:100%; left:50%; transform:translateX(-50%);
  border:5px solid transparent; border-bottom-color:var(--ink);
  opacity:0; visibility:hidden; pointer-events:none; transition:opacity 0.15s ease;
  z-index:60;
}
[data-tooltip]:hover::after, [data-tooltip]:focus-visible::after{ opacity:1; visibility:visible; transform:translateX(-50%) translateY(0); }
[data-tooltip]:hover::before, [data-tooltip]:focus-visible::before{ opacity:1; visibility:visible; }
@media (hover:none){
  [data-tooltip]::after, [data-tooltip]::before{ display:none; }
}

/* ---------- SECTION HEADS / GRID / CARDS (shared: home, shop, quick-view) ---------- */
/* padding-top/bottom only (not the padding:56px 0 shorthand) — that
   shorthand explicitly sets left/right to 0, and since .section is
   declared after .wrap at equal specificity, it was winning the cascade
   and wiping out .wrap's 28px side padding on every element that carries
   both classes (My Account, cart, checkout, blog, 404, generic pages,
   etc.) — content ran edge-to-edge on any viewport narrower than the
   1240px .wrap max-width. Longhand here leaves left/right unset so
   .wrap's padding applies normally. */
.section{padding-top:56px; padding-bottom:56px;}
.section-head{
  display:flex; align-items:baseline; justify-content:space-between; gap:20px;
  margin-bottom:26px; flex-wrap:wrap;
}
.section-head h1,.section-head h2{font-family:var(--font-body); font-weight:700; font-size:26px; letter-spacing:-0.01em;}
.section-head .meta{font-family:var(--font-mono); font-size:12px; color:var(--ink-soft);}

.grid:not([hidden]){display:flex; flex-wrap:wrap; gap:22px;}
.grid > *{flex:0 1 auto; width:calc(25% - 16.5px);}
.grid > .empty-state{width:100%;}
@media (max-width:980px){ .grid > *{width:calc(33.333% - 14.67px);} }
@media (max-width:680px){ .grid > *{width:calc(50% - 11px);} }
@media (max-width:460px){ .grid > *{width:100%;} }

/* Deliberately its own (lighter) shadow values rather than the shared
   --shadow-sm/--shadow variables (used elsewhere for buttons, tooltips,
   filter pills, etc.) — keeps this change scoped to product cards
   specifically rather than rippling into unrelated components. Just
   enough depth to read as a card, not enough to look like it's floating
   — the border is doing most of the definition work here. */
.card{
  background:var(--surface); border:var(--border-w) solid var(--line); border-radius:var(--radius);
  box-shadow:0 1px 3px rgba(20,23,28,0.05);
  display:flex; flex-direction:column;
  opacity:0; transform:translateY(10px);
  animation:reveal 0.45s ease forwards;
  transition:box-shadow 0.2s ease, transform 0.2s ease;
}
.card:hover{box-shadow:0 4px 10px rgba(20,23,28,0.08); transform:translateY(-2px);}
@keyframes reveal{to{opacity:1; transform:translateY(0);}}

/* ---------- REVEAL ON SCROLL (generic, opt-in utility) ----------
   Fade+slide-up entrance for any element marked with .js-reveal — a
   template opts an element into this by adding the class, so nothing
   gets this treatment just by existing on the page. Lives here (not
   home.css or pages.css) because main.css is the one stylesheet loaded
   on every template, and this utility is used across several of them
   (homepage sections, Warehouse Picks cards, etc.) — see assets/js/
   main.js's initReveal()/window.dwcInitReveal for the matching JS, which
   also re-scans for .js-reveal elements added later via AJAX (search
   results, "load more" on Warehouse Picks) the same way the shimmer
   system just above already does for .shimmer-img/.shimmer-block.

   Stagger within a row/grid is via nth-child delay steps below. Covers
   up to 8 siblings; a 9th+ just shares the last delay bucket, which
   isn't noticeable in practice since the stagger has already read by
   then. */
.js-reveal{
  opacity:0; transform:translateY(24px);
  transition:opacity 0.5s ease, transform 0.5s ease;
}
.js-reveal.is-revealed{ opacity:1; transform:translateY(0); }
.js-reveal:nth-child(1){ transition-delay:0s; }
.js-reveal:nth-child(2){ transition-delay:0.1s; }
.js-reveal:nth-child(3){ transition-delay:0.2s; }
.js-reveal:nth-child(4){ transition-delay:0.3s; }
.js-reveal:nth-child(5){ transition-delay:0.4s; }
.js-reveal:nth-child(6){ transition-delay:0.5s; }
.js-reveal:nth-child(7){ transition-delay:0.6s; }
.js-reveal:nth-child(8){ transition-delay:0.7s; }
@media (prefers-reduced-motion: reduce){
  .js-reveal{ opacity:1; transform:none; transition:none; }
}
.card-swatch{
  aspect-ratio:1/1; position:relative; border-bottom:var(--border-w) solid var(--line);
  border-radius:var(--radius) var(--radius) 0 0;
  display:flex; align-items:flex-end; justify-content:space-between; padding:10px;
  overflow:hidden;
}
.card-swatch .card-swatch-img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0;}
.card-swatch .bin, .card-swatch .stock-flag, .club-pick-flag{position:relative; z-index:1;}
.card-swatch .bin{
  font-family:var(--font-mono); font-size:10px; color:rgba(0,0,0,0.55); font-weight:600;
  background:rgba(255,255,255,0.8); padding:2px 6px; border-radius:var(--radius-sm);
}
.card-swatch .stock-flag{
  font-family:var(--font-mono); font-size:10px; font-weight:700; color:#fff;
  background:var(--navy); padding:3px 7px; border-radius:var(--radius-sm);
  white-space:nowrap;
}
.club-pick-flag{
  position:absolute; top:10px; right:10px;
  font-family:var(--font-mono); font-size:10px; font-weight:700; color:#fff;
  background:var(--red); padding:3px 8px; border-radius:var(--radius-sm);
  white-space:nowrap;
}
.one-of-a-kind-flag{
  position:absolute; top:10px; left:10px; z-index:1;
  font-family:var(--font-mono); font-size:10px; font-weight:700; color:var(--ink);
  background:#fff; border:var(--border-w) solid var(--ink); padding:3px 8px; border-radius:var(--radius-sm);
  white-space:nowrap;
}
.card-body{padding:14px 14px 16px; display:flex; flex-direction:column; gap:8px; flex:1;}
.card-cat{font-family:var(--font-mono); font-size:10px; letter-spacing:0.1em; color:var(--ink-soft); text-transform:uppercase;}
.card-name{font-size:14.5px; font-weight:600; line-height:1.3;}
a.card-name:hover{color:var(--red);}

.price-ladder{margin-top:auto; border-top:1px dashed var(--line); padding-top:8px; display:flex; flex-direction:column; gap:3px;}
.price-tier{display:flex; justify-content:space-between; align-items:baseline; font-family:var(--font-mono);}
.price-tier .t-label{font-size:9.5px; letter-spacing:0.08em; color:var(--ink-soft);}
.price-tier .t-val{font-size:11px; color:var(--ink-soft);}
.t-approx{font-style:italic; opacity:0.75; font-size:0.95em;}
.price-tier.warehouse .t-val{font-size:19px; font-weight:600; color:var(--ink);}
.price-tier.warehouse .t-label{font-size:9.5px;}
.price-tier.club{background:var(--accent); margin:5px -14px -16px; padding:8px 14px; border-top:var(--border-w) solid var(--line); border-radius:0 0 var(--radius) var(--radius);}
.price-tier.club .t-label{color:#fff; font-weight:700;}
.price-tier.club .t-val{font-size:13px; font-weight:700; color:#fff;}
.price-tier.club.locked{background:var(--bg);}
.price-tier.club.locked .t-label{color:var(--ink-soft); font-weight:600;}
.price-tier.club.locked .t-val{color:var(--ink-soft); font-weight:500;}
.club-val-wrap{position:relative; display:inline-flex; align-items:center; gap:7px;}
.club-val-wrap .t-val.blurred{filter:blur(3px); user-select:none; pointer-events:none; color:var(--ink); opacity:0.85;}
.signin-overlay{
  background:var(--ink); color:#fff; font-family:var(--font-mono); font-size:9px; font-weight:700;
  letter-spacing:0.03em; padding:3px 7px; border-radius:var(--radius-sm); white-space:nowrap; cursor:pointer;
  display:inline-flex; align-items:center; gap:4px;
}
.signin-overlay:hover{background:var(--red);}
.t-label-wrap{display:inline-flex; align-items:center; gap:4px;}
.t-info{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  width:12px; height:12px; border-radius:50%; border:1px solid var(--ink-soft);
  font-family:var(--font-body); font-size:8px; font-weight:700; color:var(--ink-soft);
  cursor:help; flex-shrink:0;
}
.price-tier.club .t-info{border-color:#fff; color:#fff;}
.t-tooltip{
  position:absolute; left:0; bottom:135%;
  width:160px; background:var(--ink); color:#fff; border-radius:var(--radius-sm);
  font-family:var(--font-body); font-size:11px; font-weight:400; line-height:1.4;
  padding:8px 10px; box-shadow:var(--shadow);
  opacity:0; visibility:hidden; transition:opacity 0.15s ease;
  z-index:20; pointer-events:none;
}
.t-info:hover .t-tooltip, .t-info:focus .t-tooltip{opacity:1; visibility:visible;}

.card-actions{display:flex; gap:6px; margin-top:10px;}
/* Both buttons are flex:1 in a shared row that can get narrow (quarter-
   width cards at desktop, this product page's outfit-pairing context,
   etc). Flex items default to min-width:auto, which lets their text
   content force the button wider than its share of the row — the text
   then visually overflows past the button's own border. min-width:0
   lets the button actually shrink to the space it's given, and
   text-overflow keeps long labels from spilling out rather than wrapping
   or bleeding past the edge. */
.quick-view-btn{
  flex:1; min-width:0; border:var(--border-w) solid var(--line); border-radius:var(--radius-sm); background:var(--surface); color:var(--ink);
  font-family:var(--font-mono); font-size:10px; font-weight:600; letter-spacing:0.02em;
  padding:9px 4px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.quick-view-btn:hover{background:var(--accent); color:#fff; border-color:var(--accent);}
.add-btn{
  flex:1; min-width:0; border:var(--border-w) solid var(--ink); border-radius:var(--radius-sm); background:var(--ink); color:#fff;
  font-family:var(--font-mono); font-size:10.5px; font-weight:600; letter-spacing:0.02em;
  padding:9px 4px; text-align:center; display:block; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:background 0.15s ease, border-color 0.15s ease;
}
.add-btn:hover{background:var(--red); border-color:var(--red);}
.add-btn:disabled{opacity:0.5; cursor:not-allowed;}

/* Inline add-to-cart failure message (replaces a browser alert() — see
   cart.js) — sits directly under whichever button failed, wherever that
   button happens to be (card, quick-view modal, single product page). */
.add-to-cart-inline-error{
  font-size:12px; color:var(--red); background:#FBEAEC; border:var(--border-w) solid var(--red);
  border-radius:var(--radius-sm); padding:7px 10px; margin-top:8px; line-height:1.4;
}

.empty-state{
  border:var(--border-w) dashed var(--ink-soft); border-radius:var(--radius); padding:34px; text-align:center; font-family:var(--font-mono);
  font-size:13px; color:var(--ink-soft);
}

/* ---------- CART DRAWER ---------- */
.drawer-overlay, .modal-overlay{
  position:fixed; inset:0; background:rgba(20,23,28,0.5); z-index:90;
  opacity:0; visibility:hidden; transition:opacity 0.2s ease;
}
.drawer-overlay.open, .modal-overlay.open{opacity:1; visibility:visible;}

.cart-drawer{
  position:fixed; top:0; right:0; bottom:0; width:min(420px, 100vw); z-index:95;
  background:var(--surface); border-left:var(--border-w) solid var(--line);
  border-radius:var(--radius-lg) 0 0 var(--radius-lg); overflow:hidden;
  box-shadow:var(--shadow-lg);
  display:flex; flex-direction:column;
  transform:translateX(100%); transition:transform 0.25s ease;
}
.cart-drawer.open{transform:translateX(0);}
.cart-drawer-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:16px 20px; background:var(--ink); color:#fff;
  font-family:var(--font-mono); font-size:12px; letter-spacing:0.1em; flex-shrink:0;
}
.drawer-close{background:none; border:none; color:inherit; width:24px; height:24px;}
.drawer-close svg{width:16px; height:16px;}
.cart-drawer-body{flex:1; overflow-y:auto; padding:16px 20px;}

/* ---------- Size guide — shared between template-size-guide.php and
   the product-page modal (template-parts/size-tables.php is the one
   source for both). ---------- */
.size-guide-caveat{
  font-size:13px; color:var(--ink-soft); line-height:1.6; max-width:640px;
  border:var(--border-w) solid var(--line); padding:12px 14px; margin-bottom:28px;
}
.size-guide-block{margin-bottom:32px;}
.size-guide-block h3{font-size:16px; margin-bottom:12px;}
.size-table-wrap{overflow-x:auto;}
.size-table{border-collapse:collapse; width:100%; min-width:340px; font-size:13.5px;}
.size-table th, .size-table td{
  border:1px solid var(--line); padding:8px 12px; text-align:left; white-space:nowrap;
}
.size-table th{background:var(--bg); font-family:var(--font-mono); font-size:11px; letter-spacing:0.03em; color:var(--ink-soft);}
.size-guide-tips{padding-left:18px;}
.size-guide-tips li{font-size:13.5px; color:var(--ink-soft); line-height:1.6; margin-bottom:6px;}

/* The product-page version — same table content, in a modal rather than
   a full page. Wider than the login/join modals since it holds tables. */
.size-guide-modal{
  position:fixed; top:50%; left:50%; transform:translate(-50%,-48%); z-index:96;
  width:min(680px, 94vw); max-height:85vh; overflow-y:auto;
  background:var(--surface); border:var(--border-w) solid var(--line); border-radius:var(--radius-lg); box-shadow:var(--shadow-lg);
  opacity:0; visibility:hidden; transition:opacity 0.2s ease, transform 0.2s ease;
}
.size-guide-modal.open{opacity:1; visibility:visible; transform:translate(-50%,-50%);}
.size-guide-modal .modal-close{position:sticky; top:12px; left:100%; margin-right:12px; z-index:2;}
.size-guide-modal-body{padding:8px 28px 28px; margin-top:-32px;}
.size-guide-modal-body h2{font-family:var(--font-body); font-weight:700; font-size:21px; margin:8px 0 16px; line-height:1.1;}
.size-guide-trigger{
  display:inline-flex; align-items:center; gap:6px; background:none; border:none;
  font-family:var(--font-mono); font-size:12px; color:var(--ink-soft); text-decoration:underline; text-underline-offset:2px;
  padding:0; margin:10px 0 4px;
}
.size-guide-trigger:hover{color:var(--ink);}
.product-enquiry-sub{font-size:13.5px; color:var(--ink-soft); line-height:1.5; margin:-8px 0 18px;}

.mini-cart-item{display:flex; gap:12px; padding:14px 0; border-bottom:1px solid var(--line);}
.mini-cart-item-media{width:56px; height:56px; border:var(--border-w) solid var(--line); border-radius:var(--radius-sm); flex-shrink:0; overflow:hidden;}
.mini-cart-item-media img{width:100%; height:100%; object-fit:cover;}
.mini-cart-item-body{flex:1; display:flex; flex-direction:column; gap:4px;}
.mini-cart-item-name{font-size:13px; font-weight:600;}
.mini-cart-item-stock-note{font-family:var(--font-mono); font-size:10.5px; color:var(--ink-soft);}
.mini-cart-item-price{font-family:var(--font-mono); font-size:12px; color:var(--ink-soft);}
.mini-cart-qty-row{display:flex; align-items:center; gap:8px; margin-top:2px;}
.qty-step{
  width:22px; height:22px; border:var(--border-w) solid var(--line); border-radius:var(--radius-sm); background:var(--surface);
  font-family:var(--font-mono); font-size:14px; line-height:1; display:flex; align-items:center; justify-content:center;
}
.qty-step:disabled{opacity:0.5; cursor:not-allowed; background:var(--surface);}
.qty-step:disabled:hover{background:var(--surface); color:inherit; border-color:var(--line);}
.qty-step:hover{background:var(--accent); color:#fff; border-color:var(--accent);}
.qty-value{font-family:var(--font-mono); font-size:12px; min-width:16px; text-align:center;}
.mini-cart-remove{margin-left:auto; background:none; border:none; color:var(--ink-soft); width:18px; height:18px;}
.mini-cart-remove:hover{color:var(--red);}
.mini-cart-remove svg{width:12px; height:12px;}
.mini-cart-footer{padding-top:16px; margin-top:6px; border-top:1px solid var(--line); display:flex; flex-direction:column; gap:10px;}
.mini-cart-subtotal{display:flex; justify-content:space-between; font-family:var(--font-mono); font-size:13px; font-weight:700;}
.mini-cart-checkout-btn{text-align:center;}
.mini-cart-view-basket{text-align:center; font-family:var(--font-mono); font-size:11px; color:var(--ink-soft); text-decoration:underline;}
.mini-cart-empty{margin-top:20px;}

/* ---------- QUICK VIEW MODAL ---------- */
.quick-view-modal{
  position:fixed; top:50%; left:50%; transform:translate(-50%,-48%); z-index:96;
  width:min(760px, 92vw); max-height:88vh; overflow-y:auto;
  background:var(--surface); border:var(--border-w) solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow-lg);
  opacity:0; visibility:hidden; transition:opacity 0.2s ease, transform 0.2s ease;
}
.quick-view-modal.open{opacity:1; visibility:visible; transform:translate(-50%,-50%);}
.modal-close{position:sticky; top:12px; left:100%; margin-right:12px; z-index:2;}
.quick-view-body{display:flex; gap:0; margin-top:-40px;}
.qv-media{aspect-ratio:1/1; border-right:var(--border-w) solid var(--line); border-radius:var(--radius-lg) 0 0 var(--radius-lg); overflow:hidden; flex:1 1 50%; width:50%;}
.qv-media img{width:100%; height:100%; object-fit:cover;}
.qv-details{padding:28px; flex:1 1 50%; width:50%;}
.qv-name{font-family:var(--font-body); font-weight:700; font-size:22px; margin:6px 0 12px; line-height:1.1;}
.qv-desc{font-size:15px; color:var(--ink-soft); line-height:1.65; margin-bottom:10px;}
/* .price-tier.club's base rule (above, in the price-ladder block) has
   a negative bottom margin so the banner bleeds flush to a product
   card's bottom edge — right when it's the card's last element. In
   the quick-view modal it isn't: .qv-qty-row comes right after it, so
   that same negative margin was pulling the qty row up and
   overlapping the banner. Horizontal bleed is still worth keeping
   here (flush to .qv-details' own 28px padding, same idea as the
   card version just matched to this container's padding instead of
   .card-body's), but the bottom margin needs to push, not pull, or
   there's nothing separating the two. */
.qv-details .price-tier.club{margin:5px -28px 0; padding:8px 28px;}
.qv-qty-row{display:flex; align-items:center; gap:10px; margin:14px 0 10px;}
.qv-qty-row label{font-family:var(--font-mono); font-size:11px; color:var(--ink-soft);}
.qv-qty-row input{width:64px; border:var(--border-w) solid var(--line); border-radius:var(--radius-sm); padding:8px; font-family:var(--font-body); font-size:14px; background:var(--bg);}
.qv-add-btn{width:100%;}
.qv-full-link{display:block; text-align:center; margin-top:12px; font-family:var(--font-mono); font-size:11px; color:var(--ink-soft); text-decoration:underline;}
/* Loading state — see #quickViewBody in assets/js/quick-view.js. Same
   .skeleton-bar shimmer bars as the result-card skeleton further up
   this file, just sized/arranged to match .qv-media/.qv-details
   instead of .card/.card-body. Matching the real layout's shape (not
   just reusing .empty-state's small dashed box, which is what this
   replaced) is what stops the modal visibly resizing/"popping" once
   the real content swaps in — the skeleton already occupies the same
   50/50 footprint the loaded content will. .skeleton-bar is already
   display:block (see the shimmer system above), so these just stack
   in normal flow inside .qv-details — no extra flex needed. */
.qv-media .skeleton-image{width:100%; height:100%; border-radius:0;}
.qv-skeleton-cat{width:70px; height:10px; margin:6px 0 16px;}
.qv-skeleton-name{width:80%; height:24px; margin-bottom:18px;}
.qv-skeleton-desc-line{width:100%; height:13px; margin-bottom:8px;}
.qv-skeleton-desc-line.short{width:55%; margin-bottom:20px;}
.qv-skeleton-price{width:130px; height:26px; margin-bottom:24px;}
.qv-skeleton-btn{width:100%; height:46px;}
@media (max-width:700px){
  .quick-view-body{flex-direction:column;}
  .qv-media, .qv-details{width:100%;}
  .qv-media{border-right:none; border-bottom:var(--border-w) solid var(--line); border-radius:var(--radius-lg) var(--radius-lg) 0 0;}
}

/* ---------- FOOTER ----------
   Brand + 4 columns (SHOP, HELP & INFORMATION, COMPANY, newsletter). */
.site-footer{border-top:1px solid var(--line); background:var(--surface); margin-top:0;}
.footer-top{
  display:flex; flex-wrap:wrap; gap:32px;
  padding:52px 28px 40px;
}
.footer-brand{flex:1 1 auto; width:calc(26% - 24px);}
.footer-col{flex:1 1 auto; width:calc(18.5% - 24px);}
.footer-col.footer-news{width:calc(18.5% - 24px);}
.footer-brand p{font-size:13px; color:var(--ink-soft); margin-top:14px; line-height:1.6; max-width:280px;}
.footer-social{display:flex; gap:8px; margin-top:16px;}
.footer-social a{
  width:34px; height:34px; border:var(--border-w) solid var(--line); border-radius:50%;
  background:var(--surface); color:var(--ink-soft);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  font-size:14px; transition:border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.footer-social a:hover{background:var(--ink); border-color:var(--ink); color:#fff;}
.footer-col h4{font-family:var(--font-mono); font-size:11px; letter-spacing:0.1em; margin-bottom:14px;}
.footer-col ul li{margin-bottom:9px;}
.footer-col ul a{font-size:13px; color:var(--ink-soft);}
.footer-col ul a:hover{color:var(--red);}
.news-row{display:flex; gap:8px; margin-top:12px;}
.news-row input{flex:1; border:var(--border-w) solid var(--line); border-radius:var(--radius-sm); padding:10px 12px; font-size:13px; background:var(--bg); min-width:0;}
.news-row button{border:var(--border-w) solid var(--ink); border-radius:var(--radius-sm); background:var(--ink); color:#fff; font-family:var(--font-mono); font-size:11px; font-weight:700; padding:0 16px;}
.news-row button:hover{background:var(--red); border-color:var(--red);}
.footer-bottom{
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px;
  padding:16px 28px; border-top:1px solid var(--line);
  font-family:var(--font-mono); font-size:10.5px; color:var(--ink-soft);
}
.footer-legal-links a{color:var(--ink-soft);}
.footer-legal-links a:hover{color:var(--red);}
.footer-legal-sep{color:var(--line); padding:0 2px;}
@media (max-width:1100px){ .footer-brand{width:calc(40% - 24px);} .footer-col{width:calc(28% - 24px);} }
@media (max-width:900px){ .footer-brand, .footer-col{width:calc(50% - 20px);} }
@media (max-width:560px){ .footer-brand, .footer-col{width:100%;} }

/* ---------- PHOTO PLACEHOLDER (swap for a real image — see brief in chat) ---------- */
.photo-placeholder{
  position:relative; overflow:hidden; min-height:200px; border-radius:var(--radius);
  background:repeating-linear-gradient(115deg, var(--line) 0 3px, var(--bg) 3px 16px);
  display:flex; align-items:center; justify-content:center; border:var(--border-w) solid var(--line);
}
.photo-placeholder-label{
  background:var(--surface); border:var(--border-w) solid var(--line); border-radius:var(--radius-sm); box-shadow:var(--shadow-sm);
  padding:10px 16px; font-family:var(--font-mono); font-size:11px; color:var(--ink-soft);
  text-align:center; max-width:240px; line-height:1.5;
}
.photo-placeholder-label strong{display:block; color:var(--ink); font-size:12px; margin-bottom:4px;}

/* ---------- MISC SHARED ---------- */
.product-breadcrumb{font-family:var(--font-mono); font-size:11px; color:var(--ink-soft); display:flex; gap:8px; margin-bottom:20px; flex-wrap:wrap;}
.product-breadcrumb a:hover{color:var(--red);}

/* ---------- Star ratings (WooCommerce's own .star-rating markup,
   restyled since we dequeued its default stylesheet) — sitewide, since
   both product-page reviews and homepage testimonials use it. ---------- */
.star-rating{
  overflow:hidden; position:relative; height:1.1em; line-height:1.1em;
  width:5.5em; font-size:14px; letter-spacing:2px;
}
.star-rating::before{
  content:"☆☆☆☆☆"; position:absolute; top:0; left:0; color:var(--ink-soft);
}
.star-rating span{overflow:hidden; position:absolute; top:0; left:0; height:100%; padding-top:1.5em;}
.star-rating span::before{content:"★★★★★"; position:absolute; top:0; left:0; color:var(--accent);}
.comment-form-rating select{width:auto; display:inline-block;}
.woocommerce-review__author{font-weight:600; font-size:13px;}
.woocommerce-review__published-date{font-family:var(--font-mono); font-size:11px; color:var(--ink-soft); margin-left:6px;}
.review .description{font-size:13.5px; color:var(--ink-soft); margin-top:6px; line-height:1.6;}
#reviews #comments{list-style:none;}
#reviews .comment_container{display:flex; gap:12px; padding:16px 0; border-bottom:1px solid var(--line);}
#reviews .avatar{width:40px; height:40px; border:var(--border-w) solid var(--line); border-radius:50%; flex-shrink:0;}
/* =========================================================================
   SHIMMER LOADING EFFECTS
   Applied to images and content areas before they've loaded.
   ========================================================================= */

/* ---- Base shimmer animation ---- */
@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

.shimmer-base {
  position: relative;
  background: var(--bg);
  background-image: linear-gradient(
    90deg,
    var(--bg) 0%,
    #e8ecf0 20%,
    var(--bg) 40%,
    var(--bg) 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: shimmer 1.8s ease-in-out infinite;
}

/* ---- Shimmer overlay for images ---- */
.shimmer-img {
  position: relative;
  overflow: hidden;
}

.shimmer-img::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--bg);
  background-image: linear-gradient(
    90deg,
    var(--bg) 0%,
    #e8ecf0 20%,
    var(--bg) 40%,
    var(--bg) 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: shimmer 1.8s ease-in-out infinite;
  transition: opacity 0.4s ease;
}

.shimmer-img.loaded::before {
  opacity: 0;
  pointer-events: none;
}

.shimmer-img img {
  position: relative;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.shimmer-img.loaded img {
  opacity: 1;
}

/* ---- Content block shimmer (for non-image content) ---- */
.shimmer-block {
  position: relative;
  min-height: 60px;
}

.shimmer-block::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--bg);
  background-image: linear-gradient(
    90deg,
    var(--bg) 0%,
    #e8ecf0 20%,
    var(--bg) 40%,
    var(--bg) 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: shimmer 1.8s ease-in-out infinite;
  transition: opacity 0.4s ease;
  border-radius: var(--radius-sm);
}

.shimmer-block.loaded::before {
  opacity: 0;
  pointer-events: none;
}

.shimmer-block .shimmer-content {
  position: relative;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.shimmer-block.loaded .shimmer-content {
  opacity: 1;
}

/* ---- Specific sizes for different card elements ---- */
.shimmer-text-line {
  min-height: 14px;
  margin-bottom: 6px;
  width: 100%;
}

.shimmer-text-line.short {
  width: 60%;
}

.shimmer-text-line.medium {
  width: 80%;
}

/* ---- Result skeleton cards ----
   Placeholder product cards shown while a search (or outfit-pairing) call
   is in flight — see search-render.js's skeletonCardHtml(), used by the
   homepage scanner (ai-search.js), the sitewide search results page
   (search-results.js), and single-product "Complete the look"
   (outfit-pairing.js). Sitewide rather than scoped to any one of those
   templates, since all three load this markup. Sized to match
   .card/.card-swatch/.card-body above so the grid doesn't jump when real
   cards swap in. Uses its own shimmer class (not .shimmer-img/.shimmer-block)
   since those are marked "loaded" — animation stopped — a frame after they
   appear, which is wrong here where the wait is the whole point. */
.skeleton-card{pointer-events:none;}
.skeleton-bar{
  display:block; border-radius:var(--radius-sm);
  background-image:linear-gradient(90deg, var(--bg) 0%, #e8ecf0 20%, var(--bg) 40%, var(--bg) 100%);
  background-size:200% 100%; background-repeat:no-repeat;
  animation:shimmer 1.8s ease-in-out infinite;
}
.skeleton-card .card-swatch{background:var(--bg);}
.skeleton-bar.skeleton-image{width:100%; height:100%;}
.skeleton-card .card-body{gap:10px;}
.skeleton-bar.text-short{width:45%; height:10px;}
.skeleton-bar.text-medium{width:85%; height:14px;}
.skeleton-bar.price{width:100%; height:20px; margin-top:auto;}
@media (prefers-reduced-motion: reduce){
  .skeleton-bar{animation:none;}
}

/* ---- Reduce shimmer on mobile for performance ---- */
@media (prefers-reduced-motion: reduce) {
  .shimmer-base,
  .shimmer-img::before,
  .shimmer-block::before {
    animation: none;
    background-image: none;
    background-color: var(--bg);
  }
}
/* LOT badge for warehouse lots */
.lot-flag{
  position:absolute; top:10px; left:10px;
  font-family:var(--font-mono); font-size:10px; font-weight:700; color:#fff;
  background:var(--navy); padding:3px 8px; border-radius:var(--radius-sm);
  white-space:nowrap;
  letter-spacing:0.05em;
}