/** Shopify CDN: Minification failed

Line 2115:39 Unexpected "/"
Line 2116:68 Unterminated string token
Line 2117:71 Unterminated string token
Line 2118:72 Unterminated string token
Line 2119:77 Unterminated string token

**/
/* Culture Nest — theme stylesheet */
:root{
  /* Light theme (default). Core palette also injected from theme settings in theme.liquid. */
  --base:#EDEAE3; --card:#F8F6F1; --elev:#FFFFFF; --deep:#E3DFD5;
  --ivory:#2B2F36; --taupe:#5C5F66; --muted:#5F6269;
  --bronze:#B5703F; --bronze-soft:#D49568; --bronze-tint:rgba(181,112,63,.14);
  /* --bronze/--bronze-soft stay the exact brand swatch — used for borders,
     button fills, tints and icon strokes, all "graphical" contexts that only
     need 3:1 and already clear it. Where the same hue renders as actual TEXT
     (labels, prices, links, star ratings) it needs 4.5:1, and neither brand
     tone reaches that on this light ground: --bronze-soft alone sits at
     ~2.3:1, --bronze at ~3.9:1. --bronze-ink is that hue darkened to ~4.7:1+
     for text use only; the dark theme restores the original soft tone below,
     since that already reads fine against a near-black background. */
  --bronze-ink:#915A32;
  /* --bronze-ink itself is calibrated against --base/--card. Two spots render
     it over a *different* derived surface (bronze-tint-over-card; the hero's
     --deep panel) where it measures under 4.5:1 -- --bronze-ink-deep is the
     same hue, darkened further for exactly those two call sites. Dark mode
     restores a lighter tone than --bronze-soft itself, since both of those
     surfaces are dark there and need a lighter fill than --bronze-ink alone. */
  --bronze-ink-deep:#835029;
  --line:rgba(43,47,54,.12); --line-2:rgba(43,47,54,.07); --line-strong:rgba(43,47,54,.30);
  --on-accent:#FBF7F0;                 /* text on copper — stays light in both modes */
  /* Semantic status colours — darkened from their old dark-background tones so
     text and badge fills clear 4.5:1 on this light ground. rgb triplets let the
     tint variants share one source of truth via rgba(var(--good-rgb),alpha).
     html[data-theme="dark"] below restores the lighter, dark-ground-safe tones. */
  --good:#106B31; --good-rgb:16,107,49;
  --bad:#A93226; --bad-rgb:169,50,38;
  --warn:#8A5A00;
  --header-bg:rgba(237,234,227,.82);   /* sticky header, tokenized so it can flip */
  --chip-bg:rgba(248,246,241,.9);      /* floating glass chips */
  --ph-a:#e6e2d8; --ph-b:#d8d3c6;      /* image placeholder gradient */
  --shadow:0 30px 70px -34px rgba(30,25,15,.18);
  --shadow-sm:0 12px 30px -18px rgba(30,25,15,.14);
  --display:'Inter Tight',system-ui,sans-serif;
  --body:'Inter',system-ui,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,monospace;
  --wrap:1300px; --ease:cubic-bezier(.16,1,.3,1);
}
/* Dark theme — opt-in via the header toggle (or the merchant's "Default
   appearance" setting). Higher specificity than :root, so it also beats the
   settings-driven :root block injected in theme.liquid. Accent stays copper. */
html[data-theme="dark"]{
  --base:#2B2F36; --card:#363B44; --elev:#3E434D; --deep:#22252B;
  --ivory:#EDEAE3; --taupe:#ADB0B5;
  /* Calibrated against --elev (#3E434D), not --card — --elev is the lighter
     of the two "raised surface" tokens (the cart-rewards progress track is
     one real user of it) and is the harder one of the two to clear. A first
     pass tuned only against --card measured 4.20–4.45:1 against --elev,
     still short. --muted measured 4.27:1 against --card originally. */
  --muted:#B0B5BB; --bronze-soft:#DFA57C;
  --line:rgba(237,234,227,.10); --line-2:rgba(237,234,227,.055); --line-strong:rgba(237,234,227,.28);
  /* #7FB98A measured 3.87-4.01:1 against its own rgba(var(--good-rgb),alpha)
     tint (the "X saved"/discount-percent badges) blended over --card/--elev
     -- lightened to clear 4.5:1 against that tint, the same failure shape
     as --bronze-ink/--muted above. --good-rgb intentionally kept pointing at
     this lighter value too, since anything using the tint (cart-saved,
     .share-copy.is-copied, etc.) should get the same fix, not a mismatched
     pair of a light badge background with the old, too-dark text color. */
  --good:#96CBA0; --good-rgb:150,203,160;
  /* Same gap as --good above: #E08A7A measured 4.33:1 against --card and
     3.82:1 against --elev -- checked once the --good pattern turned up,
     rather than waiting to stumble onto a live form-error/sold-out state
     that happened to use it. --warn (#E0A65B) was already fine at 5.24:1 /
     4.62:1 against the same two surfaces and didn't need changing. */
  --bad:#E8A092; --bad-rgb:232,160,146;
  --warn:#E0A65B;
  /* This, not --bronze-soft, is the token actually behind the widespread
     contrast miss: --bronze-ink is what dozens of components (eyebrows,
     "was"/"Save ₹X" prices, star ratings, spec units) use as text color in
     dark mode, and #D49568 -- reused verbatim from --bronze-soft's own
     light-theme literal -- only cleared AA against --card by coincidence,
     not by design, and fell short against --elev entirely. Same value as
     --bronze-soft above, calibrated against --elev. */
  --bronze-ink:#DFA57C;
  --bronze-ink-deep:#E6B27E;
  --header-bg:rgba(43,47,54,.82);
  --chip-bg:rgba(54,59,68,.86);
  --ph-a:#3a3f48; --ph-b:#2a2e35;
  --shadow:0 30px 70px -34px rgba(0,0,0,.7);
  --shadow-sm:0 12px 30px -18px rgba(0,0,0,.6);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:var(--body);background:var(--base);color:var(--ivory);line-height:1.65;-webkit-font-smoothing:antialiased;overflow-x:clip;transition:background .4s ease,color .4s ease}
/* smooth colour crossfade when toggling theme (skipped for reduced-motion users) */
@media(prefers-reduced-motion:no-preference){
  body :where(header,footer,section,a,button,input,.cat,.card,.chip){transition:background-color .4s ease,color .4s ease,border-color .4s ease,box-shadow .4s ease}
}
body::after{content:"";position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.3;mix-blend-mode:multiply;
 background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.05'/%3E%3C/svg%3E")}
html[data-theme="dark"] body::after{opacity:.5;mix-blend-mode:overlay}
h1,h2,h3,h4{font-family:var(--display);font-weight:600;line-height:1.08;letter-spacing:-.025em}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 32px;position:relative;z-index:2}
.label{font-family:var(--mono);font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;font-weight:500;color:var(--bronze-ink)}
.accent{color:var(--bronze-ink)}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.55rem;padding:1rem 2rem;border-radius:100px;font-weight:600;font-size:1rem;background:var(--cta,var(--bronze));color:var(--on-accent);transition:.35s var(--ease);border:none;cursor:pointer}
.btn:hover{background:var(--cta-hover,var(--bronze));transform:translateY(-2px);box-shadow:0 16px 34px -14px rgba(181,112,63,.5)}
.btn:disabled{background:var(--elev);cursor:not-allowed;transform:none;box-shadow:none}
.btn--ghost{background:transparent;color:var(--ivory);border:1px solid var(--line)}
.btn--ghost:hover{background:var(--ivory);color:var(--base);border-color:var(--ivory);box-shadow:none}
.btn--full{width:100%}
:focus-visible{outline:2px solid var(--bronze);outline-offset:3px}
/* Safari didn't support the :focus-visible selector at all until 15.4 (March
   2022) -- still real on an iPad that hasn't been updated past an older
   iPadOS. On an engine that doesn't recognize it, a rule written as plain
   `:focus-visible{...}` (this one, and every component-specific
   `.x:focus-visible` rule throughout this file) fails to parse and is
   dropped entirely -- keyboard focus becomes completely invisible, not just
   less precise, since there's no fallback selector for it to fall back to.
   Gated to fire ONLY when :focus-visible truly isn't supported, so modern
   browsers never see it; @supports not selector(:focus-visible) is false for
   them and this whole block is skipped. Matches :focus instead, which also
   shows on a mouse click in that specific old-browser case -- an accepted
   trade-off, not a regression, since those engines had no ring at all
   before this. Kept unqualified (no class) so it backstops every
   component-specific :focus-visible rule that fails to parse the same way,
   not just this one. */
@supports not selector(:focus-visible){
  :focus{outline:2px solid var(--bronze);outline-offset:3px}
}
.visually-hidden{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip{position:absolute;left:-9999px}
.skip:focus{left:12px;top:12px;z-index:200;background:var(--ivory);color:var(--base);padding:.6rem 1rem;border-radius:6px}
.reveal{opacity:0;transform:translateY(28px);transition:opacity .85s var(--ease),transform .85s var(--ease)}
.reveal.in{opacity:1;transform:none}
.ph{position:relative;overflow:hidden;background:linear-gradient(150deg,var(--ph-a),var(--ph-b))}
.ph img,.ph svg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease),opacity .5s var(--ease)}

/* announcement */
.announce{background:var(--deep);color:var(--taupe);font-size:.8rem;letter-spacing:.14em;text-transform:uppercase;text-align:center;padding:.7rem 1rem;border-bottom:1px solid var(--line-2);position:relative;z-index:3}
.announce b{color:var(--ivory)}
/* the bar is an <a> when a link is configured (section.settings.url) — <div> is
   block by default, but an <a> needs it forced or text-align:center has nothing
   to center within */
a.announce{display:block;text-decoration:none;color:inherit}
a.announce:hover{text-decoration:underline}

/* header */
/* z-index 83 is deliberate and load-bearing. `position:sticky` + z-index +
   backdrop-filter make this a stacking context, so the mobile drawer nested
   inside it cannot escape the header's layer no matter what z-index it
   carries. The scrim is a sibling of the header, so at 60 the scrim (81)
   painted over the whole drawer: the menu looked washed out and every tap
   landed on the scrim, which closed it. Header must therefore outrank the
   scrim. It still sits below the cart drawer (96) and its overlay (90).
   Order here: cookie bar 80 < scrim 81 < header/drawer 83 < overlay 90. */
.header{position:sticky;top:0;z-index:83;background:var(--header-bg);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);border-bottom:1px solid var(--line-2)}
.nav{display:flex;align-items:center;justify-content:space-between;height:78px}
.logo{font-family:var(--display);font-weight:700;font-size:1.4rem;letter-spacing:-.02em;display:flex;align-items:center;gap:.6rem}
.logo img{max-height:40px;width:auto;position:static}
.logo .mark{width:32px;height:32px;flex:none}
.brand-dot{color:var(--bronze-ink)}
.nav-links{display:flex;gap:2.4rem;list-style:none}
/* Every rule in this block is scoped with `> li >` on purpose. The mega panel
   is a descendant of ul#navLinks, so a bare `.nav-links a` also matches every
   link inside the dropdown — that is what painted a bronze ::after bar across
   the middle of the quick-link pills (it read as a strikethrough) and what
   forced the old `.mega a{padding:0}` counter-hack. Child combinators keep
   these styles on the header row where they belong. */
.nav-links > li{opacity:0;animation:navItemIn .5s var(--ease) forwards}
.nav-links > li:nth-child(1){animation-delay:.05s}
.nav-links > li:nth-child(2){animation-delay:.13s}
.nav-links > li:nth-child(3){animation-delay:.21s}
.nav-links > li:nth-child(4){animation-delay:.29s}
@keyframes navItemIn{from{opacity:0;transform:translateY(-9px)}to{opacity:1;transform:none}}
/* The mega-menu item fades without translating. `animation-fill-mode: forwards`
   keeps applying the final keyframe, and an animated transform resolves to an
   identity matrix rather than the keyword `none` — which is still a transform,
   so the <li> became the containing block for its absolutely-positioned panel
   and the dropdown collapsed to the width of the word "Shop". Fading only means
   no transform is ever held, so .mega positions against .nav as intended. */
.nav-links > li.has-mega{animation-name:navItemFade}
@keyframes navItemFade{from{opacity:0}to{opacity:1}}
.nav-links > li > a{font-size:.9rem;font-weight:500;color:var(--taupe);position:relative;padding:1.65rem 0;display:inline-block;transition:color .25s var(--ease),transform .25s var(--ease)}
.nav-links > li > a:hover,.nav-links > li > a[aria-current]{color:var(--ivory)}
.nav-links > li > a:hover{transform:translateY(-1px)}
.nav-links > li > a::after{content:"";position:absolute;left:50%;bottom:1.2rem;height:1.5px;width:0;background:var(--bronze);border-radius:2px;transform:translateX(-50%);transition:width .32s var(--ease)}
.nav-links > li > a:hover::after,.nav-links > li > a[aria-current]::after{width:100%}
@media (prefers-reduced-motion:reduce){.nav-links > li{opacity:1;animation:none}.nav-links > li > a:hover{transform:none}}
.nav-actions{display:flex;align-items:center;gap:1.45rem}
.icon-btn{position:relative;display:grid;place-items:center;width:24px;height:24px}
.icon-btn svg{width:20px;height:20px;stroke:var(--ivory);fill:none;stroke-width:1.6;position:static}
/* Anchored from the icon-btn's centre, not its edges: the glyph inside is
   always centred (place-items:center) regardless of how big the tap target
   is, so a centre-relative offset keeps the badge glued to the visible icon
   whether icon-btn is the base 24px box or the 44px mobile touch target —
   an edge-relative top/right offset drifted away from the glyph on desktop
   once the touch-target fix inflated the box without moving the badge. */
.count{position:absolute;top:50%;left:50%;transform:translate(6px,-11px);background:var(--cta,var(--bronze));color:var(--on-accent);font-size:.6rem;font-weight:700;min-width:16px;height:16px;border-radius:9px;display:grid;place-items:center;padding:0 3px;font-family:var(--body)}
.burger{display:none;flex-direction:column;gap:5px;width:24px}
.burger span{height:1.6px;background:var(--ivory);border-radius:2px;transition:transform .3s var(--ease),opacity .2s}
.burger.is-open span:nth-child(1){transform:translateY(6.6px) rotate(45deg)}
.burger.is-open span:nth-child(2){opacity:0}
.burger.is-open span:nth-child(3){transform:translateY(-6.6px) rotate(-45deg)}
/* Apple-style light/dark switch. Base state = light (the default theme):
   sun shown, knob at rest. html[data-theme="dark"] slides the knob and swaps
   the icon for whichever visitor (or merchant setting) opts into dark. */
.theme-switch{background:none;border:none;padding:0;cursor:pointer;display:inline-flex;align-items:center}
.theme-switch-track{position:relative;width:46px;height:26px;border-radius:100px;background:var(--line);border:1px solid var(--line);transition:background .3s ease;display:inline-block}
.theme-switch-knob{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--bronze);box-shadow:0 1px 3px rgba(0,0,0,.35);transition:transform .3s var(--ease),background .3s ease;transform:translateX(0);display:grid;place-items:center}
html[data-theme="dark"] .theme-switch-knob{transform:translateX(22px)}
.theme-switch-knob svg{width:12px;height:12px;stroke:var(--on-accent);fill:none;stroke-width:2;position:static}
.theme-switch .k-moon{display:none}
html[data-theme="dark"] .theme-switch .k-sun{display:none}
html[data-theme="dark"] .theme-switch .k-moon{display:block}

/* header inline search (visible on big screens) */
.hsearch{display:none;position:relative;align-items:center;gap:.5rem;background:var(--card);border:1px solid var(--line);border-radius:100px;padding:.5rem .9rem;width:220px}
.hsearch:focus-within{border-color:var(--bronze)}
.hsearch-ic{display:inline-flex}
.hsearch-ic svg{width:16px;height:16px;stroke:var(--muted);fill:none;stroke-width:1.8;position:static}
.hsearch input{flex:1;min-width:0;border:none;background:none;outline:none;color:var(--ivory);font-family:inherit;font-size:.84rem}
.hsearch input::placeholder{color:var(--muted)}
.hsearch-results{position:absolute;top:calc(100% + 10px);right:0;width:340px;background:var(--card);border:1px solid var(--line-2);border-radius:12px;box-shadow:var(--shadow);padding:.5rem;display:grid;gap:.2rem;z-index:70;max-height:64vh;overflow:auto}
.hsearch-results[hidden]{display:none}
.hres{display:flex;gap:.7rem;align-items:center;padding:.5rem;border-radius:8px;transition:.15s}
.hres:hover{background:var(--elev)}
.hth{width:40px;height:48px;border-radius:6px;overflow:hidden;background:var(--elev);flex:none}
.hth img{width:100%;height:100%;object-fit:cover;position:static}
.hres b{font-size:.85rem;display:block;color:var(--ivory)}
.hres small{font-size:.78rem;color:var(--bronze-ink)}
@media(min-width:1024px){ .hsearch{display:flex} .nav-actions > .js-search-open{display:none} }

/* Anchored jump target: clear the sticky header instead of landing under it. */
.section--stories[id]{scroll-margin-top:88px}
.chip{position:absolute;background:var(--chip-bg);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--line);border-radius:14px;padding:.9rem 1.1rem;box-shadow:var(--shadow);display:flex;align-items:center;gap:.75rem;z-index:3}
.chip.rating{left:-22px;top:40px;animation:fl 6s ease-in-out infinite}
.chip .stars{color:var(--bronze-ink);font-size:.85rem;letter-spacing:.08em}
.chip strong{font-size:.95rem;display:block;font-family:var(--display)}
.chip small{font-size:.72rem;color:var(--muted)}
.chip.ship{right:-18px;bottom:54px;animation:fl 7s ease-in-out .9s infinite}
.chip .ic{width:40px;height:40px;border-radius:11px;background:var(--bronze-tint);display:grid;place-items:center;flex:none}
.chip .ic svg{width:20px;height:20px;stroke:var(--bronze-soft);fill:none;stroke-width:1.8;position:static}
@keyframes fl{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}

/* sections */
.section{padding:3.4rem 0;position:relative}
.sec-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1.4rem;margin-bottom:1.9rem;flex-wrap:wrap}
.sec-head h2{font-size:clamp(1.9rem,3.9vw,2.9rem)}
.sec-head .label{display:block;margin-bottom:.85rem}
.sec-head p{color:var(--taupe);font-size:.96rem;max-width:34rem;margin-top:.7rem}
.sec-link{font-size:.86rem;font-weight:600;color:var(--bronze-ink);display:inline-flex;align-items:center;gap:.4rem;white-space:nowrap;flex:none;transition:gap .25s var(--ease),color .2s}
.sec-link:hover{gap:.7rem;color:var(--bronze-ink)}
.sec-link svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;flex:none;position:static}
.center .sec-head{flex-direction:column;align-items:center;text-align:center}

/* limited-time deal countdown */
.deal-timer{display:flex;align-items:center;flex-wrap:wrap;gap:.7rem 1rem;margin-top:1rem}
.deal-timer-lbl{display:inline-flex;align-items:center;gap:.4rem;font-family:var(--mono);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:var(--bronze-ink)}
.deal-timer-lbl svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.8;position:static}
.deal-timer-clock{display:inline-flex;align-items:center;gap:.5rem}
.deal-timer .dt-unit{display:inline-flex;flex-direction:column;align-items:center;gap:.15rem;min-width:46px;padding:.4rem .3rem;background:var(--bronze-tint);border:1px solid var(--line-2);border-radius:9px}
.deal-timer .dt-unit b{font-family:var(--display);font-weight:600;font-size:1.3rem;line-height:1;color:var(--ivory);font-variant-numeric:tabular-nums}
.deal-timer .dt-unit i{font-family:var(--mono);font-style:normal;font-size:.55rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
/* No opacity dimming on either rule below: --bronze-ink is already a
   deliberately-darkened, only-just-clears-4.5:1 derivative (see its
   definition) with no headroom left to dim into -- .65/.6 opacity measured
   ~2.55:1 and ~2.33:1, both well under AA. Full opacity is the fix. */
.deal-timer .dt-sep{font-family:var(--display);font-weight:600;font-size:1.2rem;color:var(--bronze-ink);align-self:flex-start;margin-top:.35rem}
.deal-timer .dt-expired{font-family:var(--display);font-size:1rem;font-weight:600;color:var(--bronze-ink)}
@media (max-width:680px){
  .deal-timer .dt-unit{min-width:40px}
  .deal-timer .dt-unit b{font-size:1.1rem}
}

/* stories */
.stories{display:flex;flex-wrap:nowrap;justify-content:safe center;gap:1.05rem;overflow-x:auto;padding:.2rem .1rem .5rem;scroll-snap-type:x mandatory;scrollbar-width:none}
.stories::-webkit-scrollbar{display:none}
.story{flex:0 0 auto;scroll-snap-align:start;text-align:center}
.story .ring{width:72px;height:72px;margin:0 auto;border-radius:50%;padding:2.5px;background:conic-gradient(from 150deg,var(--bronze),var(--bronze-soft),var(--bronze),var(--bronze-soft),var(--bronze));transition:transform .3s var(--ease)}
.story:hover .ring{transform:translateY(-4px)}
.story .inner{width:100%;height:100%;border-radius:50%;overflow:hidden;border:2.5px solid var(--base);position:relative;background:var(--elev)}
.story .inner img{width:100%;height:100%;object-fit:cover;transition:transform .5s var(--ease);position:static}
.story:hover .inner img{transform:scale(1.09)}
.story p{margin:.55rem auto 0;max-width:100px;font-size:.78rem;font-weight:600;color:var(--ivory);line-height:1.25}
.story:hover p{color:var(--ivory)}

/* marquee */
.marq{background:var(--deep);border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2);overflow:hidden;padding:.9rem 0;position:relative;z-index:2}
.marq .track{display:flex;white-space:nowrap;animation:mq 30s linear infinite;width:max-content}
.marq span{font-size:.72rem;letter-spacing:.28em;text-transform:uppercase;color:var(--muted);display:flex;align-items:center;gap:3rem;padding-right:3rem}
.marq i{font-style:normal;color:var(--bronze-ink)}
@keyframes mq{to{transform:translateX(-50%)}}

/* categories — mobile-first: 2-col base, enhanced up */
.catgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.9rem}
@media(min-width:681px){.catgrid{gap:1.3rem}}
/* Column count comes from the section so 3 or 6 cards do not leave an orphan
   on the last row. main-list-collections.liquid sets no property and keeps the
   4-column default it always had. */
@media(min-width:1081px){.catgrid{grid-template-columns:repeat(var(--cat-cols,4),minmax(0,1fr))}}
/* Merchant-set section spacing, capped on phones: a 96px setting chosen on a
   desktop editor would otherwise burn a third of a 390px screen on padding. */
.catsec{padding-block:var(--catsec-pad,3.4rem)}
@media(max-width:680px){.catsec{padding-block:min(var(--catsec-pad,3.4rem),2.6rem)}}
/* Taller on phones only. A 2-up grid at 375px leaves a 160px column, and a
   heading + subtitle + CTA in that width runs to ~7 lines; at 3/4 the text
   scrim covered 94% of the card and the product photo vanished. 5/8 buys the
   height back so the image still reads. Desktop columns are ~250px wide, where
   3/4 was never the problem, so it keeps the original proportion. */
.cat{position:relative;overflow:hidden;aspect-ratio:5/8;display:flex;align-items:flex-end;color:#fff;border-radius:4px}
@media(min-width:681px){.cat{aspect-ratio:3/4}}
.cat::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,rgba(15,16,20,.82) 6%,rgba(15,16,20,.1) 55%,transparent 78%);z-index:2;transition:.4s}
.cat:hover::after{background:linear-gradient(to top,rgba(15,16,20,.9) 6%,rgba(15,16,20,.2) 62%)}
.cat:hover img{transform:scale(1.07)}
.cat .num{position:absolute;top:1.3rem;left:1.4rem;z-index:3;font-family:var(--display);font-weight:700;font-size:.85rem;color:var(--bronze-ink);letter-spacing:.1em}
/* Fluid, not fixed. At 1.35rem in a 160px-wide phone column the headings ran
   to 3-4 lines and the block measured 254-277px inside a 214px card — the card
   is aspect-ratio locked and clips, so 40-64px was being sliced off the TOP of
   every heading (the info is bottom-aligned, so overflow escapes upwards).
   clamp keeps the desktop size intact and scales the phone down to fit. */
/* The text carries its OWN scrim rather than relying on the card-wide gradient.
   That gradient is only .1 alpha at 55% height, and these are product photos on
   white backgrounds — headings in the upper half of the info block were sitting
   on near-white with roughly 2:1 contrast. Anchoring the scrim to .info means it
   grows with the text instead of needing the card gradient re-tuned every time a
   heading wraps to another line. Extra top padding gives the fade somewhere to
   land so there is no hard edge across the photo. */
.cat .info{position:relative;z-index:3;width:100%;
  padding:clamp(.85rem,2.6vw,1.6rem);
  padding-top:clamp(1.6rem,5vw,2.4rem);
  background:linear-gradient(to top,
    rgba(15,16,20,.96) 0%,
    rgba(15,16,20,.92) 55%,
    rgba(15,16,20,.72) 82%,
    rgba(15,16,20,0) 100%)}
.cat h3{font-size:clamp(1rem,2.6vw,1.35rem);line-height:1.2}
.cat small{display:block;font-size:clamp(.72rem,1.8vw,.8rem);color:rgba(243,241,235,.72);margin-top:.25rem}
.cat .go{display:inline-flex;align-items:center;gap:.4rem;margin-top:clamp(.45rem,1.6vw,.8rem);font-size:clamp(.8rem,1.9vw,.9rem);font-weight:700;color:var(--bronze-ink);transition:gap .25s var(--ease)}
.cat .go svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;position:static}
.cat:hover .go{gap:.7rem}
/* The shared transition on `.cat` is already gated behind no-preference, but
   the image zoom, the gradient and the arrow slide are declared outside it and
   were still animating for anyone who asked motion to stop. */
@media(prefers-reduced-motion:reduce){
  .cat::after,.cat .go,.cat img{transition:none}
  .cat:hover img{transform:none}
  .cat:hover .go{gap:.4rem}
}

/* product cards — mobile-first: 2-col base, enhanced up */
/* A 3-up step at tablet: 2-up held all the way to 1081px, which left cards
   oversized and the row sparse through the whole 681–1080 band. */
.prodgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.9rem}
@media(min-width:681px){.prodgrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:1.25rem}}
@media(min-width:1081px){.prodgrid{grid-template-columns:repeat(4,minmax(0,1fr));gap:1.4rem}}
.card{position:relative;background:var(--card);border:1px solid var(--line-2);border-radius:12px;overflow:hidden;display:flex;flex-direction:column;transition:transform .3s var(--ease),box-shadow .3s var(--ease),border-color .3s var(--ease)}
/* Stretched link: the title anchor is the card's single real link, and this
   overlay extends its hit area over the entire card — image, price, padding
   and all — so a tap anywhere but the wishlist opens the product. Keeping one
   anchor (rather than wrapping the card) avoids two tab stops per card and
   never nests the wishlist button inside a link. */
.card h3 a::after{content:"";position:absolute;inset:0;z-index:1}
.card:focus-within{border-color:rgba(176,110,59,.5)}
.card h3 a:focus-visible::after{outline:2px solid var(--bronze-soft);outline-offset:-3px;border-radius:12px}
.card:hover{transform:translateY(-4px);box-shadow:var(--shadow);border-color:rgba(176,110,59,.35)}
.card .frame{aspect-ratio:4/5;position:relative;display:block}
.card:hover .frame .img1{transform:scale(1.03)}
.card .frame .img2{opacity:0}
.card:hover .frame .img2{opacity:1;transform:scale(1.03)}
/* img2 only ever appears on :hover, so on a touch screen it is a second image
   per card that is decoded and composited and never once seen. Taking it out of
   the box tree where hover does not exist costs nothing visually and matters
   most in the orbit carousel, which stacks six cards at once. */
@media (hover: none){
  .card .frame .img2{display:none}
}

/* Badges sit in a row and wrap; the card renders at most two, so they stay on
   one line and never build a column down the front of the product. */
/* pointer-events:none — badges are decoration, and without this a tap that
   lands on one falls on a dead span instead of the card's link. */
.card .pills{position:absolute;top:11px;left:11px;right:52px;z-index:3;pointer-events:none;display:flex;flex-wrap:wrap;gap:.35rem;align-items:flex-start}
.card .pill{font-family:var(--body);font-size:.66rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:.34rem .6rem;border-radius:100px;line-height:1.2;white-space:nowrap;
  background:var(--elev);color:var(--ivory);border:1px solid var(--line)}
/* Discount is the one badge that earns full bronze — it is the strongest
   commercial signal on the card and should read first. */
.card .pill.save{background:var(--cta,var(--bronze));color:var(--on-accent);border-color:var(--cta,var(--bronze))}
.card .pill.new{background:rgba(243,241,235,.94);color:#21242B;border-color:transparent}
.card .pill.best{background:var(--bronze-tint);color:var(--bronze-ink);border-color:rgba(176,110,59,.45)}
.card .pill.low{background:var(--elev);color:var(--bronze-ink);border-color:rgba(176,110,59,.45)}
.card .pill.sold{background:var(--elev);color:var(--taupe)}
.card-media{position:relative;display:block}

.card .wish{position:absolute;top:6px;right:6px;z-index:5;width:44px;height:44px;border-radius:50%;display:grid;place-items:center;background:none;border:0;transition:transform .22s var(--ease)}
/* The 44px button is the touch target; the visible disc is drawn by ::before so
   the control can meet WCAG 2.5.5 without growing into a heavy circle. */
.card .wish::before{content:"";position:absolute;width:34px;height:34px;border-radius:50%;background:var(--chip-bg);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:1px solid var(--line);transition:background .22s ease}
.card .wish svg{width:17px;height:17px;stroke:var(--ivory);fill:none;stroke-width:1.7;position:relative;transition:.2s ease}
.card .wish:hover{transform:scale(1.08)}
.card .wish.on svg{fill:var(--bronze);stroke:var(--bronze)}

/* Same frosted-chip treatment as .wish (--chip-bg + blur), not the old
   design's hardcoded near-white pill — this way it reads as one family with
   the wish button sitting right above it instead of a second, differently
   themed floating control, and it stays correct in both site themes.
   Hover-revealed on devices that have hover; the hover:none query below is
   for touch, where there is no hover state to reveal it from, so it has to
   default to visible or it would never be reachable at all. */
.card .qvbtn{position:absolute;left:11px;right:11px;bottom:11px;z-index:4;display:flex;align-items:center;justify-content:center;gap:.42rem;
  background:var(--chip-bg);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid var(--line);
  color:var(--ivory);border-radius:100px;padding:.68rem;font-family:var(--body);font-size:.78rem;font-weight:700;
  opacity:0;transform:translateY(8px);transition:.25s var(--ease)}
.card .qvbtn svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.8;position:static}
.card:hover .qvbtn{opacity:1;transform:none}
.card .qvbtn:hover{background:var(--elev)}
@media(hover:none){ .card .qvbtn{opacity:1;transform:none} }

.card .meta{padding:.95rem 1rem 1.1rem;display:flex;flex-direction:column;gap:.3rem;flex:1}
.card .meta-top{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;min-height:1rem}
/* Bronze rather than the old #7FB98A green — the only non-brand hue on the card
   and, on a warm dark surface, the thing the eye landed on first. */
.card .stock{font-size:.7rem;color:var(--taupe);display:flex;align-items:center;gap:.38rem}
.card .stock::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--bronze-soft)}
.card .stock.out{color:var(--muted)}
.card .stock.out::before{background:var(--muted)}
.card .cat-lbl{font-family:var(--mono);font-size:.68rem;font-weight:500;color:var(--muted);margin-left:auto}
/* Clamped to two lines so a long title can't make one card taller than its
   neighbours and knock the price row out of alignment across the grid. */
.card h3,.card h4{font-family:var(--display);font-size:.98rem;font-weight:500;line-height:1.32;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.64em}
.card .foot{display:flex;align-items:flex-end;justify-content:space-between;margin-top:auto;padding-top:.55rem;gap:.6rem}
.card .price{display:flex;flex-direction:column;align-items:flex-start;gap:.1rem;min-width:0}
.card .price-row{display:flex;align-items:baseline;gap:.45rem;flex-wrap:wrap}
.card .price b{color:var(--ivory);font-size:clamp(1.25rem,1.7vw,1.45rem);font-weight:700;font-family:var(--display);font-variant-numeric:tabular-nums;white-space:nowrap;line-height:1.15}
.card .price .was{color:var(--muted);text-decoration:line-through;font-size:.8rem;font-weight:400;white-space:nowrap;line-height:1.1}
.card .price-save{font-size:.72rem;font-weight:600;color:var(--bronze-ink);letter-spacing:.01em}
.card .trust-strip{margin-top:.5rem;padding-top:.5rem;border-top:1px solid var(--line-2)}

/* quick view modal */
/* .scrim.qv-scrim (two classes), not .qv-scrim alone: the base .scrim rule
   further down the file also sets z-index (95) at equal single-class
   specificity, so whichever of the two happened to be declared later in
   the file silently won regardless of which value was "intended" here.
   Two classes beats one regardless of source order, so this survives the
   file being reorganised the way the single-class version didn't. */
.scrim.qv-scrim{z-index:96}
.qv-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-46%) scale(.98);width:min(880px,94vw);background:var(--base);border:1px solid var(--line-2);border-radius:12px;z-index:97;opacity:0;visibility:hidden;transition:opacity .3s var(--ease),transform .3s var(--ease),visibility .3s;box-shadow:var(--shadow)}
.qv-modal.open{opacity:1;visibility:visible;transform:translate(-50%,-50%) scale(1)}
.qv-close{position:absolute;top:14px;right:14px;z-index:6;width:34px;height:34px;border-radius:50%;background:var(--card);display:grid;place-items:center;border:1px solid var(--line)}
.qv-close svg{width:16px;height:16px;stroke:var(--ivory);fill:none;stroke-width:1.8;position:static}
.qv-body{max-height:90vh;overflow-y:auto;border-radius:12px}
.qv-loading{padding:4rem 2rem;text-align:center;color:var(--muted);font-size:.9rem}
.qv{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.qv-gallery{padding:1.4rem;background:var(--card)}
.qv-main{aspect-ratio:4/5;border-radius:8px;overflow:hidden;background:var(--elev)}
.qv-main img{width:100%;height:100%;object-fit:cover;position:static}
.qv-thumbs{display:flex;gap:.5rem;margin-top:.7rem}
.qv-thumbs button{width:54px;height:66px;border-radius:6px;overflow:hidden;border:1.5px solid transparent;opacity:.6;transition:.2s;padding:0}
.qv-thumbs button.on{border-color:var(--bronze);opacity:1}
.qv-thumbs img{width:100%;height:100%;object-fit:cover;position:static}
.qv-info{padding:2.2rem 2rem 2.3rem;display:flex;flex-direction:column}
.qv-info h2{font-size:1.5rem;margin:.5rem 0 .7rem}
.qv-price{display:flex;align-items:baseline;gap:.6rem;margin-bottom:1.3rem}
.qv-price b{font-family:var(--display);font-size:1.3rem;color:var(--ivory)}
.qv-price .was{color:var(--muted);text-decoration:line-through;font-size:.9rem}
.qv-stock{font-size:.82rem;margin-bottom:1.1rem;display:flex;align-items:center;gap:.45rem}
.qv-stock::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.qv-stock.in{color:var(--good)}
.qv-stock.out{color:var(--muted)}
.qv-viewfull{margin-top:.95rem;text-align:center;font-size:.84rem;color:var(--bronze-ink);font-weight:500}
@media(max-width:720px){ .qv{grid-template-columns:minmax(0,1fr)} .qv-gallery{padding:1rem} .qv-info{padding:1.5rem} .qv-main{aspect-ratio:16/11} }

/* wishlist page */
.wish-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1.3rem}
@media(max-width:1080px){ .wish-grid{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media(max-width:720px){ .wish-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:.9rem} }
.wish-empty{text-align:center;max-width:26rem;margin:1rem auto 0;display:flex;flex-direction:column;align-items:center;gap:.5rem}
/* Same display:flex-outranks-[hidden] gap already fixed for .cookie-bar,
   .cart-rewards, .cart-saved and .hsearch-results — missed here, so the
   "Nothing saved yet" placeholder stayed on screen underneath real saved
   items instead of disappearing once CN.renderWishlist populated the grid. */
.wish-empty[hidden]{display:none}
.wish-empty .ck{width:52px;height:52px;border-radius:15px;background:var(--bronze-tint);display:grid;place-items:center;margin-bottom:.4rem}
.wish-empty .ck svg{width:24px;height:24px;stroke:var(--bronze-soft);fill:none;stroke-width:1.6;position:static}
.wish-empty h3{font-size:1.2rem}
.wish-empty p{color:var(--muted);font-size:.9rem}
.wish-empty .btn{margin-top:.8rem}

/* cookie bar */
.cookie-bar{position:fixed;left:0;right:0;bottom:0;z-index:80;background:var(--deep);border-top:1px solid var(--line);padding:1.1rem 1.5rem;display:flex;align-items:center;justify-content:center;gap:1.5rem;flex-wrap:wrap;box-shadow:0 -8px 24px rgba(0,0,0,.3)}
/* `hidden` is honoured by the UA sheet's [hidden]{display:none}, which any
   author rule outranks — so display:flex above silently cancelled it and the
   banner stayed on screen (opaque, and still swallowing taps at the bottom of
   the viewport) after Accept/Reject. The choice was saving correctly the whole
   time; only the dismissal was broken. Same explicit re-declaration the theme
   already makes for .cart-rewards, .cart-saved and .hsearch-results. */
.cookie-bar[hidden]{display:none}
.cookie-bar p{font-size:.82rem;line-height:1.6;color:var(--taupe);max-width:34rem;margin:0}
.cookie-bar a{color:var(--bronze-ink);font-weight:500}
.cookie-actions{display:flex;gap:.6rem;flex-wrap:wrap}
.cookie-actions .btn{padding:.7rem 1.3rem;font-size:.8rem}

/* welcome popup */
/* .scrim.welcome-scrim (two classes) — same reasoning as .scrim.qv-scrim
   above: the base .scrim rule fights this one for z-index at equal
   specificity otherwise. */
.scrim.welcome-scrim{z-index:96}
.welcome-pop{position:fixed;top:50%;left:50%;transform:translate(-50%,-46%) scale(.98);width:min(440px,92vw);background:var(--card);border:1px solid var(--line-2);border-radius:14px;z-index:97;padding:2.4rem 2rem 2.2rem;text-align:center;opacity:0;visibility:hidden;transition:opacity .35s var(--ease),transform .35s var(--ease),visibility .35s;box-shadow:var(--shadow)}
.welcome-pop.open{opacity:1;visibility:visible;transform:translate(-50%,-50%) scale(1)}
.welcome-pop .label{display:block;margin-bottom:.7rem}
.welcome-pop h2{font-size:1.5rem;margin-bottom:.6rem}
.welcome-pop p{color:var(--taupe);font-size:.92rem;margin-bottom:1.3rem}
.welcome-close{position:absolute;top:12px;right:12px;width:32px;height:32px;border-radius:50%;background:var(--elev);display:grid;place-items:center;border:1px solid var(--line)}
.welcome-close svg{width:15px;height:15px;stroke:var(--ivory);fill:none;stroke-width:1.8;position:static}
.welcome-form{display:flex;gap:.5rem;flex-wrap:wrap}
.welcome-form input[type=email]{flex:1;min-width:0;padding:.85rem 1rem;border-radius:8px;border:1px solid var(--line);background:var(--base);color:var(--ivory);font-family:inherit;font-size:.9rem}
.welcome-form .btn{flex:none}
.welcome-pop small{display:block;margin-top:.9rem;color:var(--muted);font-size:.72rem}

/* refer a friend */
.refer{background:var(--card);border:1px solid var(--line-2);border-radius:12px;padding:1.8rem 1.6rem;max-width:520px}
.account-refer{margin-top:2.5rem}
.refer .label{display:block;margin-bottom:.7rem}
.refer-title{font-size:1.4rem;margin-bottom:.5rem}
.refer-lead{color:var(--taupe);font-size:.92rem;margin-bottom:1.4rem;max-width:420px}
.refer-code{display:flex;flex-direction:column;gap:.2rem;background:var(--base);border:1px dashed var(--line);border-radius:10px;padding:.9rem 1.1rem;margin-bottom:1rem}
.refer-code-lbl{font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
.refer-code-val{font-family:var(--display);font-size:1.5rem;font-weight:700;letter-spacing:.02em;color:var(--ivory);user-select:all}
.refer-actions{display:flex;flex-direction:column;gap:.7rem}
.refer-wa{gap:.5rem}
.refer-wa svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.7;position:static}
.refer-status{margin-top:1rem;font-size:.85rem;color:var(--bronze-ink)}
.refer-page{padding:1rem 0}
.refer-page .refer{margin:0 auto}
@media(min-width:640px){ .refer-actions{flex-direction:row} .refer-actions .btn{flex:1} }

/* ===== premium product-page storytelling sections ===== */
.pbanner{position:relative;display:flex;align-items:center;min-height:var(--h,480px);overflow:hidden;background:var(--deep)}
.pbanner-media{position:absolute;inset:0}
.pbanner-media img{width:100%;height:100%;object-fit:cover;position:static}
.pbanner-scrim{position:absolute;inset:0;background:linear-gradient(90deg,rgba(10,10,12,.74),rgba(10,10,12,.15))}
.pbanner-inner{position:relative;z-index:2;color:#fff;width:100%;max-width:var(--wrap);margin:0 auto;padding:0 32px}
.pbanner-inner.center{text-align:center;max-width:820px}
.pbanner-inner .label{color:var(--bronze-ink)}
.pbanner-inner h2{font-size:clamp(1.9rem,4.4vw,3.2rem);line-height:1.06;margin:.7rem 0 .55rem;color:#fff;letter-spacing:-.02em}
.pbanner-inner p{color:rgba(255,255,255,.82);max-width:520px;font-size:1.02rem}
.pbanner-inner.center p{margin-left:auto;margin-right:auto}

.pstate{text-align:center;padding:5.5rem 0}
.pstate h2{font-size:clamp(1.6rem,3.6vw,2.7rem);text-transform:uppercase;font-weight:600;letter-spacing:.005em}
.pstate p{color:var(--taupe);max-width:620px;margin:1.1rem auto 0;font-size:1.05rem}

.pcompare{padding:5.5rem 0;background:var(--card)}
.pcompare-head{max-width:640px;margin-bottom:2.6rem}
.pcompare-head .label{display:block;margin-bottom:.7rem}
.pcompare-head h2{font-size:clamp(1.6rem,3.6vw,2.7rem)}
.pcompare-head p{color:var(--taupe);margin-top:.7rem}
.pcompare-bars{display:grid;gap:1rem;max-width:720px}
.pcbar{display:grid;grid-template-columns:120px minmax(0,1fr);align-items:center;gap:1rem}
.pcbar-label{font-size:.92rem;color:var(--taupe);font-weight:500}
.pcbar-track{background:var(--base);border-radius:100px;height:46px;overflow:hidden}
.pcbar-fill{height:100%;width:0;background:var(--elev);border-radius:100px;display:flex;align-items:center;padding:0 1.2rem;gap:.45rem;color:var(--ivory);white-space:nowrap;transition:width 1.05s var(--ease)}
.pcbar.on .pcbar-fill{background:var(--cta,var(--bronze));color:var(--on-accent)}
.pcompare-bars.run .pcbar-fill{width:var(--w)}
.pcbar-fill b{font-family:var(--display);font-size:1.25rem;font-weight:700}
.pcompare-note{color:var(--muted);font-size:.8rem;margin-top:1.5rem;max-width:660px}

.pfeature{padding:4.5rem 0}
.pfeature--tint{background:var(--card)}
.pfeature-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:3.5rem;align-items:center}
.pfeature-grid.rev .pfeature-media{order:2}
.pfeature-media{aspect-ratio:4/3;border-radius:14px;overflow:hidden;background:var(--elev)}
.pfeature-media img{width:100%;height:100%;object-fit:cover;position:static;transition:transform .6s var(--ease)}
.pfeature-media:hover img{transform:scale(1.04)}
/* Video and embeds fill the frame the same way the image does. Shopify wraps
   video_tag/media_tag output in its own div, so the sizing has to reach through
   that wrapper as well as the element itself. */
.pfeature-media video,
.pfeature-media iframe,
.pfeature-media .shopify-video,
.pfeature-media > div{width:100%;height:100%;display:block}
.pfeature-media video,
.pfeature-media iframe{object-fit:cover;border:0}
/* No hover-zoom on video: it fights the moving picture and, with controls
   showing, nudges them out from under the cursor. */
.pfeature-media--video:hover img{transform:none}
.pfeature-text .label{margin-bottom:.8rem;display:block}
.pfeature-text h2{font-size:clamp(1.5rem,3vw,2.3rem);margin-bottom:.95rem;letter-spacing:-.01em}
.pfeature-text p{color:var(--taupe);font-size:1.02rem;max-width:470px}

.pgallery{padding:4.5rem 0}
.pgallery-head{text-align:center;margin-bottom:2.6rem}
.pgallery-head .label{display:block;margin-bottom:.6rem}
.pgallery-head h2{font-size:clamp(1.5rem,3vw,2.3rem)}
.pgallery-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}
.pgtile{aspect-ratio:1;border-radius:14px;overflow:hidden;background:var(--elev)}
.pgtile.wide{grid-column:span 2;aspect-ratio:2.1/1}
.pgtile img{width:100%;height:100%;object-fit:cover;position:static}

@media(max-width:760px){
  .pfeature-grid{grid-template-columns:minmax(0,1fr);gap:1.6rem}
  .pfeature-grid.rev .pfeature-media{order:0}
  .pcbar{grid-template-columns:74px minmax(0,1fr);gap:.7rem}
  .pgallery-grid{grid-template-columns:minmax(0,1fr)}
  .pgtile,.pgtile.wide{aspect-ratio:4/3;grid-column:auto}
  .pbanner-inner{padding:0 24px}
}

/* craft split */
.craft{background:var(--card);border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2)}
.craft-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:4rem;align-items:center;padding:4.2rem 0}
.craft-photo{aspect-ratio:5/4.5;border-radius:8px;box-shadow:var(--shadow);border:1px solid var(--line-2)}
.craft-photo:hover img{transform:scale(1.04)}
.craft h2{font-size:clamp(2rem,3.8vw,2.9rem);margin:1.1rem 0 1.2rem}
.craft .lead{color:var(--taupe);max-width:32rem;margin-bottom:1.9rem}
.checks{display:flex;flex-direction:column;gap:1.05rem;margin-bottom:2.2rem}
.checks div{display:flex;gap:.9rem;align-items:flex-start;color:var(--taupe)}
.checks b{color:var(--ivory);font-weight:700}
.checks .ck{width:23px;height:23px;border-radius:50%;background:var(--bronze-tint);display:grid;place-items:center;flex:none;margin-top:2px}
.checks svg{width:12px;height:12px;stroke:var(--bronze-soft);fill:none;stroke-width:2.6;position:static}

/* features */
/* features — mobile-first: stacked base, 2-up tablet, 4-up desktop */
.feats{display:grid;grid-template-columns:minmax(0,1fr);gap:1.8rem;padding:3.2rem 0;border-bottom:1px solid var(--line-2)}
@media(min-width:681px){.feats{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
@media(min-width:1081px){.feats{grid-template-columns:repeat(4,minmax(0,1fr));gap:1.4rem}}
.feat{display:flex;gap:1rem;align-items:flex-start}
.feat .ic{width:46px;height:46px;border-radius:13px;background:var(--bronze-tint);display:grid;place-items:center;flex:none}
.feat .ic svg{width:22px;height:22px;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;position:static}
.feat h3{font-family:var(--body);font-size:.94rem;font-weight:600;margin-bottom:.15rem}
.feat p{font-size:.8rem;color:var(--muted);line-height:1.45}


/* lookbook */
/* lookbook — mobile-first: 2-up base, 4-up desktop */
.lookgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:150px;gap:1rem}
@media(min-width:681px){.lookgrid{grid-auto-rows:200px}}
@media(min-width:1081px){.lookgrid{grid-template-columns:repeat(4,minmax(0,1fr))}}
.look{position:relative;overflow:hidden;border-radius:6px}
.look:hover img{transform:scale(1.07)}
.look .ov{position:absolute;inset:0;display:grid;place-items:center;background:rgba(15,16,20,.55);color:#fff;font-size:.78rem;letter-spacing:.12em;opacity:0;transition:.3s;z-index:2}
.look:hover .ov{opacity:1}
.look.tall{grid-row:span 2}
.look.wide{grid-column:span 2}

/* instagram feed */
.ig-feed .sec-head{margin-bottom:2rem}
.ig-follow{display:inline-flex;align-items:center;gap:.5rem;margin-top:1.15rem;padding:.6rem 1.25rem;border-radius:100px;font-weight:600;font-size:.85rem;color:#fff;background:linear-gradient(45deg,#FEDA75,#FA7E1E 25%,#D62976 50%,#962FBF 75%,#4F5BD5);box-shadow:0 8px 24px -10px rgba(214,41,118,.6);transition:transform .25s var(--ease),box-shadow .25s var(--ease)}
.ig-follow:hover{transform:translateY(-2px);box-shadow:0 12px 30px -10px rgba(214,41,118,.75)}
.ig-follow svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.8;position:static}
/* mobile-first, full-bleed auto-scrolling reel marquee */
.ig-rail{overflow:hidden;padding:.3rem 0 .5rem;-webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent)}
.ig-rail.is-static{overflow-x:auto;scrollbar-width:none;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scroll-padding-left:.85rem}
.ig-rail.is-static::-webkit-scrollbar{display:none}
.ig-rail.is-static .ig-card{scroll-snap-align:start}
.ig-track{display:flex;width:max-content;padding-inline:.85rem}
.ig-track.is-animated{animation:ig-marquee linear infinite;will-change:transform}
.ig-track.is-paused{animation-play-state:paused}
.ig-rail:hover .ig-track.is-animated{animation-play-state:paused}
@keyframes ig-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.ig-card{flex:0 0 auto;width:min(46vw,190px);margin-right:.85rem;position:relative;border-radius:18px;overflow:hidden;background:var(--elev);display:block;text-decoration:none}
.ig-media{position:relative;aspect-ratio:9/16;overflow:hidden;border-radius:18px}
.ig-media img,.ig-media video,.ig-media svg{width:100%;height:100%;object-fit:cover;position:static;display:block;transition:transform .55s var(--ease)}
.ig-media video{background:var(--deep)}
.ig-card:hover .ig-media img,.ig-card:hover .ig-media video{transform:scale(1.05)}
.ig-card::after{content:"";position:absolute;inset:0;border-radius:18px;padding:2px;background:linear-gradient(45deg,#FEDA75,#FA7E1E 25%,#D62976 50%,#962FBF 75%,#4F5BD5);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:0;transition:opacity .3s var(--ease);pointer-events:none;z-index:3}
.ig-card:active::after,.ig-card:hover::after{opacity:1}
.ig-badge{position:absolute;top:10px;right:10px;width:32px;height:32px;border-radius:50%;background:rgba(12,13,16,.5);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);display:grid;place-items:center;color:#fff;z-index:2}
.ig-badge svg{width:16px;height:16px;fill:currentColor;stroke:none;position:static}
.ig-cap{position:absolute;left:0;right:0;bottom:0;padding:2.6rem .85rem .85rem;font-size:.76rem;line-height:1.35;color:#fff;text-align:left;background:linear-gradient(transparent,rgba(9,10,13,.92));opacity:0;transform:translateY(8px);transition:.3s var(--ease);z-index:2;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.ig-card:hover .ig-cap,.ig-card:active .ig-cap{opacity:1;transform:none}
/* Tap-to-play reels. `.ig-media` is a <button> on video cards, so it needs the
   UA button styling stripped back to the <div> it replaces. */
.ig-tap{display:block;width:100%;padding:0;border:0;background:none;color:inherit;font:inherit;text-align:inherit;cursor:pointer;-webkit-appearance:none;appearance:none}
.ig-tap:focus-visible{outline:2px solid var(--bronze);outline-offset:3px}
/* Beats `.ig-media video` (0,1,1) so the created video can overlay its poster
   image rather than replacing it — the still stays put behind, so there is no
   flash of empty box while the first frame decodes. */
.ig-media video.ig-vid{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:1}
.ig-card.is-playing .ig-badge{opacity:0;transition:opacity .25s var(--ease)}
.ig-card.is-playing:hover .ig-badge,.ig-card.is-playing:focus-within .ig-badge{opacity:1}
/* Sits opposite the play badge: a reel card has two distinct actions and they
   must not be the same target. */
.ig-open{position:absolute;top:10px;left:10px;width:32px;height:32px;border-radius:50%;background:rgba(12,13,16,.5);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);display:grid;place-items:center;color:#fff;z-index:4;opacity:0;transition:opacity .25s var(--ease)}
.ig-card:hover .ig-open,.ig-card:focus-within .ig-open,.ig-rail.is-static .ig-open{opacity:1}
.ig-open svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;position:static}

.ig-empty{text-align:center;padding:2rem 1rem .5rem}
.ig-empty p{color:var(--taupe);font-size:.96rem;margin-bottom:.4rem}
@media (min-width:600px){ .ig-card{width:210px;margin-right:1rem} }
@media (min-width:1000px){ .ig-card{width:236px} }
@media (prefers-reduced-motion:reduce){ .ig-track{animation:none!important} }

/* UGC / video showcase */
/* Geometry is borrowed from the product rail (.rail) rather than invented:
   capped at --wrap, centred, padded to the same 32px gutter, same
   scroll-padding. The rail used to run edge to edge while its own heading sat
   on the content grid, so at 1440 the cards started 93px left of every other
   element on the page and the section read as a stray widget dropped onto the
   homepage rather than part of it. */
.ugc-rail-wrap{position:relative}
.ugc-rail{display:flex;gap:1rem;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;
  max-width:var(--wrap);margin:0 auto;padding:.3rem 32px 1rem;scroll-padding-left:32px}
.ugc-rail::-webkit-scrollbar{display:none}
/* The rail is tabbable (tabindex=0) so keyboard users can scroll it — it needs
   to show that it has focus. Inset so the ring is not clipped by the overflow. */
.ugc-rail:focus-visible{outline:2px solid var(--bronze);outline-offset:-2px;border-radius:14px}
.ugc-item{flex:0 0 auto;scroll-snap-align:start}
.ugc-card{position:relative}
.ugc-media{position:relative;height:clamp(300px,44vh,430px);aspect-ratio:var(--ugc-ratio,9 / 16);border-radius:16px;overflow:hidden;background:var(--elev)}
/* Wider screens get taller cards so four videos fill the grid instead of
   leaving ~300px of dead space at the right of the wrap. Width follows from
   the height and the editor's ratio setting, so this stays shape-agnostic. */
@media (min-width:1200px){ .ugc-media{height:clamp(340px,48vh,470px)} }
/* Direct children only. As a descendant selector this also caught the product
   thumbnail and the arrow icon inside the shoppable tag and stretched them to
   fill the card — and it outranked their own sizing, so the tag rendered as a
   full-bleed product photo. The `>` keeps the fill behaviour for the poster,
   the video and the placeholder while leaving anything nested alone. */
.ugc-media>img,.ugc-media>video,.ugc-media>iframe,.ugc-media>svg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border:0}
.ugc-media>img{transition:transform .55s var(--ease)}
.ugc-card:hover .ugc-media>img{transform:scale(1.05)}
.ugc-play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:62px;height:62px;border-radius:50%;background:rgba(18,19,23,.5);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:1.5px solid rgba(255,255,255,.55);display:grid;place-items:center;cursor:pointer;transition:transform .25s var(--ease),background .25s var(--ease),border-color .25s var(--ease),opacity .25s var(--ease);z-index:3}
.ugc-play:hover{background:var(--bronze);border-color:var(--bronze);transform:translate(-50%,-50%) scale(1.07)}
.ugc-play svg{grid-area:1/1;width:24px;height:24px;fill:#fff;stroke:none;position:static}
.ugc-play .ugc-ic-play{margin-left:3px}
.ugc-play .ugc-ic-pause,.ugc-card.playing .ugc-play .ugc-ic-play{display:none}
.ugc-card.playing .ugc-play .ugc-ic-pause{display:block}
/* While playing the button steps back rather than leaving — it stays in the DOM
   and in the tab order so a keyboard user always has a way to stop the video,
   and returns on hover or focus. display:none would have stranded them. */
.ugc-card.playing .ugc-play{opacity:0}
.ugc-card.playing:hover .ugc-play,.ugc-card.playing .ugc-play:focus-visible{opacity:1}
/* Sound: the one other control worth a button. Hidden until playback starts. */
.ugc-mute{position:absolute;top:10px;right:10px;width:40px;height:40px;border-radius:50%;
  background:rgba(18,19,23,.55);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,.4);
  display:grid;place-items:center;cursor:pointer;z-index:3;
  transition:background .2s var(--ease),border-color .2s var(--ease)}
.ugc-mute:hover{background:var(--bronze);border-color:var(--bronze)}
/* display:grid above outranks the UA [hidden] rule, so the button has to opt
   back out explicitly — otherwise it shows on a card whose video has not been
   built yet, where pressing it does nothing. Same trap as .pr-summary[hidden]. */
.ugc-mute[hidden]{display:none}
.ugc-mute svg{grid-area:1/1;width:17px;height:17px;fill:none;stroke:#fff;stroke-width:1.9;stroke-linecap:round;position:static}
.ugc-mute .ugc-ic-loud{display:none}
.ugc-mute.is-loud .ugc-ic-muted{display:none}
.ugc-mute.is-loud .ugc-ic-loud{display:block}
/* Fixed value, not var(--taupe): same rgba(18,19,23,...) fixed-dark chip as
   .ugc-tag-out right above -- var(--taupe) resolves dark in light mode. */
.ugc-fail{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:4;
  font-size:.8rem;color:#9BA0A6;background:rgba(18,19,23,.7);padding:.5rem .9rem;border-radius:100px}
.ugc-card.is-failed .ugc-play{display:none}
.ugc-card.is-empty .ugc-media{border:1px dashed var(--line-2)}
.ugc-add{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);font-family:var(--mono);font-size:.64rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);white-space:nowrap}
.ugc-meta{padding:.75rem .15rem 0;max-width:100%}
.ugc-cap{display:block;font-family:var(--display);font-size:.94rem;color:var(--ivory);line-height:1.3}

/* The shoppable tag. It sits inside the media, on a scrim, so the card reads as
   one object and the product is understood as the thing in the video rather
   than a recommendation parked underneath it. The whole pill is the link, which
   makes it a single large tap target instead of a small text CTA. */
.ugc-tag{position:absolute;left:10px;right:10px;bottom:10px;z-index:2;
  display:flex;align-items:center;gap:.6rem;padding:.45rem .55rem;
  background:rgba(18,19,23,.62);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  border:1px solid rgba(255,255,255,.14);border-radius:12px;
  transition:background .22s var(--ease),border-color .22s var(--ease),transform .22s var(--ease)}
.ugc-tag:hover,.ugc-tag:focus-visible{background:rgba(18,19,23,.8);border-color:var(--bronze);transform:translateY(-2px)}
.ugc-tag-img{width:40px;height:40px;flex:none;border-radius:8px;object-fit:cover}
.ugc-tag-txt{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}
.ugc-tag-txt strong{font-size:.78rem;font-weight:600;color:#F3F1EC;line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ugc-tag-price{font-size:.76rem;font-weight:700;color:var(--bronze-soft);font-variant-numeric:tabular-nums}
/* Fixed value, not var(--muted): this tag sits on a permanently-dark scrim
   (rgba(18,19,23,...)) regardless of site theme, so it needs the same fixed
   treatment as .ugc-tag-txt strong above it. var(--muted) resolves to a
   mid-gray meant for light backgrounds in light mode -- ~3.1:1 on this scrim,
   failing WCAG AA. #9BA0A6 is the same swatch the dark theme already uses for
   --muted, chosen here as a fixed value since dark-on-dark is what this
   component actually is. */
.ugc-tag-out{color:#9BA0A6;font-weight:600}
.ugc-tag-go{flex:none;width:26px;height:26px;border-radius:50%;background:var(--bronze);
  display:grid;place-items:center;transition:transform .22s var(--ease)}
.ugc-tag:hover .ugc-tag-go{transform:translateX(2px)}
.ugc-tag-go svg{width:13px;height:13px;stroke:var(--on-accent);fill:none;stroke-width:2.2;position:static}
.ugc-tag--plain{justify-content:space-between}
/* Playing shifts the tag back so it never competes with the footage, but it is
   still there — one tap away, and back in full on hover or keyboard focus. */
.ugc-card.playing .ugc-tag{background:rgba(18,19,23,.42);border-color:rgba(255,255,255,.08)}
.ugc-card.playing .ugc-tag:hover,.ugc-card.playing .ugc-tag:focus-visible{background:rgba(18,19,23,.82);border-color:var(--bronze)}
/* Two dead arrows are worse than none. The section script measures the rail
   and sets .ugc-nofit when everything already fits, which is the normal state
   on a wide screen with four videos. */
.ugc-sec.ugc-nofit .rail-nav{display:none}
/* Cards rise in behind the section's own fade. `backwards` holds the from-state
   through the delay, and the whole thing hangs off .in — which theme.js adds
   once and then drops the element from its watch list, so this cannot
   re-trigger while scrolling. Transform and opacity only: no layout work. */
@media (prefers-reduced-motion:no-preference){
  .ugc-sec.in .ugc-item{animation:ugcRise .5s var(--ease) backwards}
  .ugc-sec.in .ugc-item:nth-child(2){animation-delay:.06s}
  .ugc-sec.in .ugc-item:nth-child(3){animation-delay:.12s}
  .ugc-sec.in .ugc-item:nth-child(4){animation-delay:.18s}
  .ugc-sec.in .ugc-item:nth-child(n+5){animation-delay:.24s}
  .ugc-play{will-change:transform}
}
@keyframes ugcRise{from{opacity:0;transform:translateY(16px)}}
@media (max-width:680px){
  /* Phones drop to the 20px page gutter so the first card lines up with the
     heading above it, same as every other section.

     No negative margin here. The -20px trick cancels a .wrap parent's 20px
     padding to go edge-to-edge (which is what .stories does), but this rail's
     parent .ugc-rail-wrap has no padding — so the margins escaped the body and
     pushed the document 20px wide. body{overflow-x:clip} was hiding it, which
     is why it only showed on a real phone as a cut-off strip down the right.
     The padding alone gives the same inset start with no overflow. */
  .ugc-rail{padding-left:20px;padding-right:20px;scroll-padding-left:20px}
  .ugc-media{height:clamp(280px,54vh,390px)}
  /* Rail arrows are a pointer affordance; phones swipe. Hiding them also frees
     the header row so a long heading is not squeezed against them. */
  .ugc-sec .rail-nav{display:none}
}

/* stores */
/* stores — mobile-first: stacked base, 2-up tablet, 3-up desktop */
.stores{display:grid;grid-template-columns:minmax(0,1fr);gap:1.4rem}
@media(min-width:681px){.stores{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
@media(min-width:1081px){.stores{grid-template-columns:repeat(3,minmax(0,1fr))}}
.store{background:var(--card);border:1px solid var(--line-2);border-radius:12px;overflow:hidden;transition:transform .35s var(--ease),border-color .35s var(--ease)}
.store:hover{transform:translateY(-5px);border-color:rgba(176,110,59,.35)}
.store .top{aspect-ratio:16/7;position:relative}
.store:hover .top img{transform:scale(1.06)}
.store .open{position:absolute;top:12px;right:12px;z-index:3;font-size:.66rem;font-weight:700;color:#7FB98A;background:rgba(27,30,36,.85);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);padding:.3rem .62rem;border-radius:100px;display:flex;align-items:center;gap:.35rem}
.store .open::before{content:"";width:6px;height:6px;border-radius:50%;background:#7FB98A}
.store .body{padding:1.3rem}
.store .body h3{font-size:1.1rem;margin-bottom:.35rem}
.store .body p{font-size:.83rem;color:var(--muted);margin-bottom:1rem;min-height:2.6em}
.store .links{display:flex;gap:1.3rem;font-size:.8rem;font-weight:500}
.store .links a{color:var(--bronze-ink)}
.store .links a:hover{color:var(--ivory)}

/* newsletter */
.news .inner{background:linear-gradient(150deg,var(--card),var(--elev));border:1px solid var(--line-2);border-radius:20px;padding:4.6rem 2rem;text-align:center;position:relative;overflow:hidden}
.news .inner::before{content:"";position:absolute;inset:0;background:radial-gradient(60% 90% at 50% 0,var(--bronze-tint),transparent 60%)}
.news h2{font-size:clamp(1.9rem,3.8vw,2.7rem);margin:.9rem auto 1rem;position:relative}
.news p{color:var(--taupe);max-width:42ch;margin:0 auto 2.2rem;position:relative}
.news-form{display:flex;gap:.6rem;max-width:480px;margin:0 auto;flex-wrap:wrap;justify-content:center;position:relative}
.news-form input{flex:1;min-width:230px;padding:1.05rem 1.4rem;border-radius:100px;border:1px solid var(--line);background:var(--elev);font-family:inherit;font-size:.92rem;color:var(--ivory)}
.news-form input::placeholder{color:var(--muted)}
.news-form input:focus{outline:none;border-color:var(--bronze)}
.news-note{font-size:.78rem;color:var(--muted);margin-top:1.1rem;position:relative}
.form-success{color:var(--bronze-ink);font-weight:500;margin-top:1rem;position:relative}
.form-error{color:var(--bad);font-size:.85rem;margin-top:.8rem;position:relative}

/* footer */
.footer{border-top:1px solid var(--line-2);padding:4.8rem 0 2rem;background:var(--deep);position:relative;z-index:2}
.foot-top{text-align:center;padding-bottom:3rem;border-bottom:1px solid var(--line-2);margin-bottom:3rem}
.foot-top .label{display:block;margin-bottom:.6rem}
.foot-top h2{font-size:clamp(1.4rem,2.6vw,1.9rem)}
/* footer columns — mobile-first: stacked base, 2-up on tablet, 4-up on desktop */
.foot-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:2.8rem;padding-bottom:3rem;border-bottom:1px solid var(--line-2)}
@media(min-width:681px){.foot-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
@media(min-width:1081px){.foot-grid{grid-template-columns:minmax(0,1.6fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1.1fr)}}
.foot-brand .logo{margin-bottom:1.1rem}
.foot-brand p{font-size:.9rem;color:var(--taupe);max-width:24rem;margin-bottom:1.5rem}
.socials{display:flex;gap:.8rem}
.socials a{width:38px;height:38px;border-radius:50%;border:1px solid var(--line);display:grid;place-items:center;transition:.25s var(--ease)}
.socials a:hover{background:var(--bronze);border-color:var(--bronze);transform:translateY(-2px)}
.socials svg{width:16px;height:16px;stroke:var(--ivory);fill:none;stroke-width:1.7;position:static}
.foot-connect-socials{margin-top:1.1rem}
.footer h3{font-family:var(--body);font-size:.75rem;letter-spacing:.18em;text-transform:uppercase;margin-bottom:1.25rem;font-weight:700;color:var(--ivory)}
.footer ul{list-style:none;display:flex;flex-direction:column;gap:.8rem}
.footer ul a,.footer ul li{font-size:.9rem;color:var(--taupe);transition:.2s}
.footer ul a:hover{color:var(--bronze-ink)}
.contact li{display:flex;gap:.7rem;align-items:flex-start}
.contact svg{width:16px;height:16px;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;flex:none;margin-top:4px;position:static}
/* No border-top and no margin-top here. .foot-grid already closes itself with
   a border-bottom in the same colour, so this drew a second identical rule
   35px below the first with nothing between them — two stray lines and a band
   of dead space above the payment badges. One divider, and .foot-grid's
   padding-bottom plus this padding-top provide the breathing room. */
.foot-pay{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:.55rem .7rem;padding-top:1.9rem}
.foot-pay .paybadges{margin:0}



.foot-bottom{display:flex;justify-content:space-between;align-items:center;padding-top:1.6rem;font-size:.8rem;color:var(--muted);flex-wrap:wrap;gap:1rem}
.pay-icons{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}
.pay-icons img{height:22px;width:auto;position:static}

/* search overlay */
.overlay{position:fixed;inset:0;z-index:90;background:rgba(12,13,16,.6);-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);opacity:0;visibility:hidden;transition:.3s}
.overlay.open{opacity:1;visibility:visible}
.search-panel{background:var(--card);padding:2.7rem 32px 3rem;transform:translateY(-100%);transition:.28s var(--ease);border-bottom:1px solid var(--line-2)}
.overlay.open .search-panel{transform:translateY(0)}
.search-inner{max-width:800px;margin:0 auto}
/* the padding belongs to the input, not the row — otherwise the gap above
   the underline is dead space that looks like part of the field */
.search-row{display:flex;align-items:stretch;gap:1rem;border-bottom:2px solid var(--bronze);padding-bottom:0}
.search-row svg{width:23px;height:23px;stroke:var(--ivory);fill:none;stroke-width:1.8;position:static;align-self:center;flex:none}
.search-row input{flex:1;min-width:0;min-height:44px;padding:0 0 1rem;border:none;background:none;font-family:var(--display);font-size:1.55rem;font-weight:500;outline:none;color:var(--ivory)}
/* outline:none above dropped the sitewide :focus-visible ring (theme.css:54)
   with nothing to replace it — a keyboard user tabbing to the main search
   field got no visible indication it was focused. Restored, scoped to
   :focus-visible so a mouse click still shows no ring, matching every other
   input's outline:none+replacement pairing in this file. */
.search-row input:focus-visible{outline:2px solid var(--bronze);outline-offset:4px;border-radius:4px}
.search-row input::placeholder{color:var(--muted)}
.search-row button{align-self:center;flex:none;min-width:44px;min-height:44px}
.search-tags{margin-top:1.7rem;display:flex;gap:.6rem;flex-wrap:wrap;align-items:center}
.search-tags span{font-size:.74rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-right:.4rem}
.search-tags a{font-size:.85rem;padding:.55rem 1.1rem;border:1px solid var(--line);border-radius:100px;color:var(--taupe);transition:.2s}
.search-tags a:hover{background:var(--cta,var(--bronze));color:var(--on-accent);border-color:var(--cta,var(--bronze))}
.predict{margin-top:1.6rem;display:grid;gap:.6rem}
.predict a{display:flex;gap:.9rem;align-items:center;padding:.6rem;border-radius:8px;transition:.2s}
.predict a:hover{background:var(--elev)}
.predict .th{width:46px;height:54px;border-radius:6px;overflow:hidden;background:var(--elev);flex:none;position:relative}
.predict .th img{width:100%;height:100%;object-fit:cover;position:static}
.predict b{font-size:.9rem;display:block}
.predict small{font-size:.78rem;color:var(--bronze-ink)}

/* cart drawer */
.scrim{position:fixed;inset:0;z-index:95;background:rgba(12,13,16,.6);opacity:0;visibility:hidden;transition:.3s}
.scrim.open{opacity:1;visibility:visible}
.x{width:34px;height:34px;display:grid;place-items:center;border:1px solid var(--line);border-radius:50%;flex:none}
.x svg{width:15px;height:15px;stroke:var(--ivory);stroke-width:2;fill:none;position:static}
/* .qty is shared with the PDP's own quantity stepper (main-product.liquid)
   and the standalone /cart page (main-cart.liquid) — left exactly as-is.
   The rebuilt cart drawer below has its own stepper (.ccart-qty), so this
   rule is dead weight for the drawer specifically but still load-bearing
   elsewhere; removing it would break those two other places. */
.qty{display:flex;align-items:center;border:1px solid var(--line);border-radius:100px;height:32px;background:var(--elev)}
.qty button{width:30px;height:100%;font-size:1rem;line-height:1;color:var(--ivory)}
.qty span{min-width:22px;text-align:center;font-size:.8rem;font-weight:600}
.is-loading{opacity:.55;pointer-events:none}

/* Value-pulse + line-removal animation for the shared .js-qty delegated
   handler (assets/theme.js) — used by BOTH the rebuilt cart drawer
   (.ccart-item, via q.closest('.ccart-item, tr')) and the standalone
   /cart page's <tr> rows (sections/main-cart.liquid). Kept here as
   generic/shared rather than folded into the drawer's own CSS, since
   removing it (as an earlier pass of this rebuild briefly did) silently
   broke the qty-pulse and remove-animation on the /cart page. */
.val-pulse{display:inline-block;animation:valPulse .42s var(--ease)}
@keyframes valPulse{0%{transform:scale(1)}42%{transform:scale(1.16)}100%{transform:scale(1)}}
.ci-out{animation:ciOut .22s var(--ease) forwards;pointer-events:none;overflow:hidden}
@keyframes ciOut{to{opacity:0;transform:translateX(28px);max-height:0;padding-top:0;padding-bottom:0;margin:0;border:0}}
@media(prefers-reduced-motion:reduce){.val-pulse,.ci-out{animation:none}}

/* =====================================================================
   CART DRAWER — rebuilt from scratch against CultureNest Cart.dc.html,
   not extended from the previous drawer (which is fully removed above).
   Deliberately self-contained: its own custom-property palette scoped to
   .ccart, taken directly from the mock's own oklch design tokens (accent
   #b94224, dark #251d19, discount #db0030, success #21763c, etc. — sampled
   via canvas pixel extraction, not eyeballed) rather than this theme's
   settled bronze/#B5703F system. That's a deliberate one-off for this
   component only: nothing outside `.ccart` reads these variables, so nothing
   else on the site shifts color. The drawer also doesn't invert for
   html[data-theme="dark"] — the mock has no dark variant of its own to draw
   from, so inventing one would be a guess; it keeps one fixed appearance
   like a self-contained overlay, same allowance a page like this can take
   when it deliberately commits to one visual world. Structural values
   (padding, radius, font-size) are copied from the mock's own inline
   styles wherever real data doesn't force a different shape (see the two
   documented exceptions: the rewards card and the trust list, below). ===== */
.ccart{
  --ca-bg:#faf4ec; --ca-card:#fffdfa; --ca-ink:#271d17; --ca-muted:#72665e; --ca-border:#e0dad2;
  --ca-accent:#b94224; --ca-discount:#db0030; --ca-dark:#251d19;
  --ca-success:#21763c; --ca-success-bg:#d4f5da; --ca-error:#ba2b2e;
  --ca-gift-bg:#fbf5ed; --ca-gift-img:#f5dad3;
  position:fixed;top:0;right:0;height:100vh;height:100dvh;width:min(460px,100%);
  background:var(--ca-bg);color:var(--ca-ink);font-family:'Manrope',system-ui,sans-serif;
  z-index:96;transform:translateX(100%);transition:transform .45s var(--ease);
  display:flex;flex-direction:column;box-shadow:0 0 40px rgba(0,0,0,.08);
}
.ccart.open{transform:translateX(0)}
.ccart *{box-sizing:border-box}

/* header — sticky, leading chevron back button + "Cart (N)" */
.ccart-head{position:sticky;top:0;z-index:2;flex:none;background:var(--ca-card);
  border-bottom:1px solid var(--ca-border);display:flex;align-items:center;gap:8px;padding:6px 14px}
.ccart-back{width:40px;height:40px;border:none;background:transparent;font-size:20px;font-weight:700;
  color:var(--ca-ink);display:flex;align-items:center;justify-content:center;border-radius:10px;flex-shrink:0;cursor:pointer}
.ccart-back:hover{background:rgba(0,0,0,.05)}
.ccart-title{font-size:16px;font-weight:700}

/* ticker */
.ccart-ticker{width:100%;border:none;background:var(--ca-accent);color:#fff;font-weight:700;font-size:13px;
  padding:11px 14px;text-align:center;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;cursor:pointer}

/* scroll region — header/ticker/footer stay fixed, everything else scrolls
   as one unit so a short cart sits compact instead of stretching to fill
   the drawer (same reasoning the old drawer-scroll had, carried over as
   the one piece of layout logic that was never about the mock's visuals). */
.ccart-scroll{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain}
.ccart-body{padding:14px;display:flex;flex-direction:column;gap:12px}

/* empty state — mock's exact minimal version: heading, one line, a link */
.ccart-empty{text-align:center;padding:2.4rem 0 1rem}
.ccart-empty h3{font-size:1.05rem;margin:0 0 .4rem;font-family:'Manrope',system-ui,sans-serif}
.ccart-empty p{font-size:.86rem;color:var(--ca-muted);margin:0 auto 1.1rem;max-width:34ch}
.ccart-empty a{display:inline-block;font-size:.86rem;font-weight:700;color:var(--ca-accent)}
.ccart-empty a:hover{opacity:.85}

/* rewards card — mock's shipping-progress module is a single threshold
   (real shipping here is unconditionally free, so that specific claim
   would be false — see rules established earlier this project); reskinned
   to carry this store's real 3-tier gift/discount milestones instead,
   in the mock's own compact card proportions (padding, radius, message
   size, track height) rather than the previous build's taller card. */
/* padding-bottom: the node captions (.ccart-node-cap) are absolutely
   positioned below the track and don't contribute to this flexbox's own
   height, so it has to be reserved explicitly — measured live at ~30px
   needed (captions bottomed out ~7px past a 22px reserve). */
.ccart-rewards{background:var(--ca-card);border:1px solid var(--ca-border);border-radius:12px;
  padding:10px 14px 30px;display:flex;flex-direction:column;gap:8px;position:relative}
.ccart-rewards[hidden]{display:none}
.ccart-rewards-msg{display:block;width:100%;background:none;border:0;padding:0;font:inherit;cursor:pointer;
  font-size:12.5px;font-weight:700;text-align:center;color:var(--ca-ink)}
.ccart-rewards-track{position:relative;height:5px;border-radius:99px;background:var(--ca-border)}
.ccart-rewards-fill{position:absolute;left:0;top:0;height:100%;width:0;border-radius:99px;
  background:var(--ca-success);transition:width .3s ease}
.ccart-rewards-nodes{position:absolute;inset:-8px 0}
.ccart-node{position:absolute;top:0;transform:translateX(-50%);display:flex;flex-direction:column;
  align-items:center;gap:2px;background:none;border:0;padding:2px;cursor:pointer}
.ccart-node-dot{width:16px;height:16px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:var(--ca-border);color:#fff;transition:background .2s ease}
.ccart-node-dot svg{width:9px;height:9px;stroke:currentColor;fill:none;stroke-width:3;position:static}
.ccart-node.is-unlocked .ccart-node-dot{background:var(--ca-success)}
.ccart-node-cap{font-size:8.5px;font-weight:700;color:var(--ca-muted);white-space:nowrap;text-align:center;line-height:1.3}
.ccart-node-cap i{display:block;font-style:normal;font-weight:500;font-size:8px}

/* free gift card */
.ccart-gift{display:flex;gap:14px;padding:14px;background:var(--ca-gift-bg);border:1.5px solid var(--ca-accent);
  border-radius:14px;position:relative;overflow:hidden}
.ccart-gift[hidden]{display:none}
.ccart-gift-img{width:68px;height:68px;flex-shrink:0;border-radius:10px;overflow:hidden;background:var(--ca-gift-img);
  display:flex;align-items:center;justify-content:center}
.ccart-gift-img img{width:100%;height:100%;object-fit:cover;position:static}
.ccart-gift-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px;justify-content:center}
.ccart-gift-name{font-weight:700;font-size:13.5px;line-height:1.3}
.ccart-gift-badge{display:inline-flex;align-items:center;gap:5px;width:fit-content;font-size:11px;font-weight:700;
  color:var(--ca-success);border:1px solid var(--ca-success);padding:3px 10px;border-radius:99px}
.ccart-gift-badge i{width:6px;height:6px;border-radius:99px;background:var(--ca-success);display:inline-block;font-style:normal}
.ccart-gift-price{display:flex;align-items:baseline;gap:8px}
.ccart-gift-price b{font-weight:800;font-size:14px;color:var(--ca-success)}
.ccart-gift-price s{font-size:12px;color:var(--ca-muted);text-decoration:line-through}

/* line items */
.ccart-items{display:flex;flex-direction:column;gap:10px}
.ccart-item{display:flex;gap:14px;padding:14px;background:var(--ca-card);border:1px solid var(--ca-border);
  border-radius:16px;position:relative;box-shadow:0 1px 3px rgba(0,0,0,.04)}
/* overflow:visible, not hidden — the mock's own image container is
   explicitly overflow:visible so the discount ribbon (.ccart-badge,
   left:-8px) can hang off the left edge as designed. hidden here clipped
   it against this container's own boundary. The image itself still gets
   rounded corners, just via its own border-radius instead of relying on
   the parent to clip it. */
.ccart-item-img{width:76px;height:76px;flex-shrink:0;border-radius:10px;overflow:visible;background:var(--ca-border);
  position:relative;display:flex;align-items:center;justify-content:center}
.ccart-item-img img{width:100%;height:100%;object-fit:cover;position:static;border-radius:10px}
.ccart-badge{position:absolute;top:6px;left:-8px;background:var(--ca-discount);color:#fff;font-size:9px;font-weight:800;
  padding:2px 7px;border-radius:2px;transform:rotate(-8deg);box-shadow:0 1px 3px rgba(0,0,0,.25);white-space:nowrap}
.ccart-item-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
.ccart-item-top{display:flex;justify-content:space-between;gap:8px}
.ccart-item-name{font-weight:700;font-size:14.5px;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;font-family:inherit;color:inherit}
.ccart-item-name:hover{color:var(--ca-accent)}
.ccart-item-remove{border:none;background:transparent;color:var(--ca-muted);font-size:16px;width:28px;height:28px;
  flex-shrink:0;border-radius:8px;cursor:pointer;line-height:1}
.ccart-item-remove:hover{background:rgba(0,0,0,.05);color:var(--ca-error)}
.ccart-item-variant{font-size:12px;color:var(--ca-muted)}
.ccart-item-price{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.ccart-item-price b{font-weight:700;font-size:16px}
.ccart-item-price s{font-size:12px;color:var(--ca-muted);text-decoration:line-through}
.ccart-item-bottom{display:flex;align-items:center;justify-content:space-between;margin-top:6px}
.ccart-qty{display:flex;align-items:center;gap:0;border:1px solid var(--ca-border);border-radius:10px;overflow:hidden}
.ccart-qty button{width:36px;height:36px;border:none;background:var(--ca-bg);color:var(--ca-ink);font-size:16px;
  font-weight:700;cursor:pointer;line-height:1}
.ccart-qty button:disabled{opacity:.4;cursor:not-allowed}
.ccart-qty span{width:32px;text-align:center;font-size:14px;font-weight:700}
.ccart-linetotal{font-size:15px;font-weight:700;color:var(--ca-ink)}
/* Item-removal animation reuses the shared .ci-out class (see the "shared"
   comment near .is-loading, above) rather than a separate one — same
   effect the standalone /cart page already uses, so it's already tested. */

/* Gift note (.ccart-giftnote/.ccart-gn-*) was removed on request — the
   toggle+textarea+debounced-save wiring in theme.js went with it. */

/* coupon */
.ccart-coupon{background:var(--ca-card);border:1px solid var(--ca-border);border-radius:14px;padding:14px 16px;
  display:flex;flex-direction:column;gap:10px}
.ccart-coupon[hidden]{display:none}
.ccart-coupon-applied{display:flex;flex-direction:column;gap:10px}
.ccart-coupon-applied[hidden]{display:none}
.ccart-coupon-row2{display:flex;align-items:center;justify-content:space-between;gap:8px}
.ccart-coupon-code{font-size:13px;font-weight:700}
.ccart-coupon-ok{color:var(--ca-success);font-weight:600}
.ccart-coupon-saved{font-size:12px;color:var(--ca-success);margin-top:.15rem}
.ccart-coupon-remove{border:none;background:transparent;color:var(--ca-muted);font-size:12px;font-weight:600;
  text-decoration:underline;padding:6px;cursor:pointer;flex:none}
.ccart-coupon-remove:hover{color:var(--ca-ink)}
.ccart-coupon-form[hidden]{display:none}
.ccart-coupon-row{display:flex;gap:8px}
.ccart-coupon-row input{flex:1;min-width:0;border:1px solid var(--ca-border);border-radius:10px;padding:10px 12px;
  font-size:16px;text-transform:uppercase;background:var(--ca-bg);color:var(--ca-ink);font-family:inherit}
.ccart-coupon-row input::placeholder{color:var(--ca-muted);text-transform:none}
.ccart-coupon-apply{border:none;background:var(--ca-dark);color:#fff;font-weight:700;font-size:13px;
  padding:0 18px;border-radius:10px;white-space:nowrap;min-height:44px;cursor:pointer}
.ccart-coupon-apply:disabled{opacity:.5;cursor:not-allowed}
.ccart-coupon-error{font-size:12px;color:var(--ca-error)}
.ccart-coupon-error[hidden]{display:none}
.ccart-coupon-hint-row{display:flex;align-items:center;justify-content:space-between}
.ccart-coupon-hint{font-size:11.5px;color:var(--ca-muted);text-decoration:underline}
.ccart-offers-toggle{border:none;background:transparent;color:var(--ca-accent);font-size:11.5px;font-weight:700;
  padding:2px;cursor:pointer;display:flex;align-items:center;gap:.2rem}
.ccart-offers-toggle[hidden]{display:none}
.ccart-offers-caret{transition:transform .2s ease}
.ccart-offers-toggle[aria-expanded="true"] .ccart-offers-caret{transform:rotate(90deg)}
.ccart-offers-panel{display:flex;flex-direction:column;gap:8px;padding-top:8px;border-top:1px solid var(--ca-border)}
.ccart-offers-panel[hidden]{display:none}
.ccart-offer-row{display:flex;align-items:center;justify-content:space-between;gap:8px}
.ccart-offer-code{font-size:12px;font-weight:700}
.ccart-offer-label{font-size:11px;color:var(--ca-muted)}
.ccart-offer-apply{border:1px solid var(--ca-border);background:var(--ca-bg);color:var(--ca-ink);font-size:11px;
  font-weight:700;padding:6px 12px;border-radius:8px;cursor:pointer}
.ccart-offer-apply:disabled{opacity:.5;cursor:not-allowed}

/* recommendations */
.ccart-recs{display:flex;flex-direction:column;gap:10px}
.ccart-recs-heading{font-size:15px;font-weight:800;color:var(--ca-accent);margin:0}
.ccart-rec-rail{display:flex;gap:12px;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin}
.ccart-rec{flex:0 0 168px;background:var(--ca-card);border:1px solid var(--ca-border);border-radius:14px;
  padding:12px;display:flex;flex-direction:column;gap:8px;box-shadow:0 1px 3px rgba(0,0,0,.04)}
/* Same overflow:visible fix as .ccart-item-img above — lets the ribbon
   badge (left:-6px) hang off this card's left edge instead of being
   clipped by the image container. */
.ccart-rec-img{height:112px;border-radius:10px;overflow:visible;background:var(--ca-border);position:relative;display:block}
.ccart-rec-img img{width:100%;height:100%;object-fit:cover;position:static;border-radius:10px}
.ccart-rec .ccart-badge{top:6px;left:-6px;font-size:9px;padding:2px 6px}
.ccart-rec-title{font-size:12.5px;font-weight:700;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;min-height:34px;color:inherit;font-family:inherit}
.ccart-rec-price{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.ccart-rec-price b{font-weight:700;font-size:14px}
.ccart-rec-price s{font-size:11.5px;color:var(--ca-muted);text-decoration:line-through}
.ccart-rec-add{border:1.5px solid var(--ca-accent);background:transparent;color:var(--ca-accent);font-weight:700;
  font-size:12.5px;padding:9px;border-radius:9px;min-height:38px;width:100%;cursor:pointer;text-align:center;
  text-decoration:none;display:block;font-family:inherit}
.ccart-rec-add.is-added{background:var(--ca-accent);color:#fff}

/* Trust list (.ccart-trust) removed on request. */

/* sticky footer */
.ccart-stickybar{flex:none;background:var(--ca-bg)}
.ccart-stickybar[hidden]{display:none}
/* Padding lives on .ccart-breakdown-inner, not here: max-height:0 only
   collapses content height, never fixed padding — with padding on this
   element directly, the "closed" state was stuck at ~25px tall (its own
   12px+12px padding + 1px border) instead of 0, showing a sliver of the
   first row (Subtotal) that then visually collided with the savings bar
   sitting right below it. Zero padding on the collapsing element itself
   is what actually lets max-height:0 hide it completely. */
.ccart-breakdown{background:var(--ca-card);border-top:1px solid var(--ca-border);
  max-height:0;overflow:hidden;transition:max-height .3s ease}
.ccart-breakdown.is-open{max-height:260px}
.ccart-breakdown-inner{padding:12px 16px;display:flex;flex-direction:column;gap:7px}
.ccart-breakdown-row{display:flex;justify-content:space-between;font-size:12.5px}
.ccart-breakdown-row span:first-child{color:var(--ca-muted)}
.ccart-breakdown-row.is-pos span:last-child{color:var(--ca-success)}
.ccart-breakdown-row[hidden]{display:none}
.ccart-breakdown-div{height:1px;background:var(--ca-border)}
.ccart-breakdown-total{display:flex;justify-content:space-between;font-size:13.5px;font-weight:800}
.ccart-breakdown-note{text-align:center;font-size:11px;color:var(--ca-muted);margin-top:2px}
.ccart-savingsbar{background:var(--ca-success);color:#fff;text-align:center;font-weight:700;font-size:12.5px;
  padding:7px 12px}
.ccart-savingsbar[hidden]{display:none}
.ccart-cta{background:var(--ca-dark);display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:11px 16px calc(11px + env(safe-area-inset-bottom)) 16px}
.ccart-total-toggle{border:none;background:transparent;display:flex;align-items:center;gap:6px;min-width:0;
  padding:0;cursor:pointer;text-align:left;flex:1}
.ccart-total-label{font-size:10px;color:rgba(255,255,255,.72)}
.ccart-total-amt{display:flex;align-items:baseline;gap:8px}
.ccart-total-amt s{font-size:12px;color:rgba(255,255,255,.58);text-decoration:line-through}
.ccart-total-amt s[hidden]{display:none}
.ccart-total-amt b{font-size:20px;font-weight:800;color:#fff}
.ccart-total-caret{color:rgba(255,255,255,.72);font-size:14px;transition:transform .2s ease;flex-shrink:0}
.ccart-total-toggle[aria-expanded="true"] .ccart-total-caret{transform:rotate(180deg)}
.ccart-checkout{flex-shrink:0;min-width:150px;height:50px;border:none;background:var(--ca-accent);color:#fff;
  font-weight:800;font-size:15px;border-radius:12px;padding:0 14px;box-shadow:0 2px 8px rgba(0,0,0,.2);
  cursor:pointer;transition:background-color .12s ease,transform .12s ease,box-shadow .12s ease;font-family:inherit;
  display:flex;align-items:center;justify-content:center;gap:8px}
.ccart-checkout:hover{filter:brightness(1.08)}
.ccart-checkout-label,.ccart-checkout-arrow{flex:none}
/* UPI-options mark (assets/pay-upi-options.svg, self-hosted — see the
   liquid comment above it) sitting inside the checkout button. Fixed
   height, width auto so it keeps the source's own 42:17 aspect ratio;
   no responsive tiering needed since it's one flat image, not a row of
   separately-collapsing badges the way the old per-provider chip set was. */
.ccart-checkout-pay{height:17px;width:auto;flex:none;display:block}
/* Tap feedback for mobile, where :hover never fires — the fill switches to
   an actual darker shade (not just a brightness filter, which read as too
   subtle to register as "pressed") the instant a finger lands, plus a
   scale-down and flattened shadow, snapping back on release. Registers the
   press itself rather than waiting on the network round-trip to /cart for
   any confirmation. #7d2a15 is --ca-accent darkened ~25% (color-mix, not
   guessed), so it still reads as this same button, just pushed in. */
.ccart-checkout:active{background:#7d2a15;transform:scale(.95);box-shadow:0 1px 3px rgba(0,0,0,.18)}
.ccart-checkout:disabled{opacity:.6;cursor:not-allowed}
@media(prefers-reduced-motion:reduce){.ccart-checkout{transition:background-color .2s ease}.ccart-checkout:active{transform:none}}

/* toast */
.toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,80px);background:var(--ivory);color:var(--base);padding:.9rem 1.5rem;border-radius:100px;font-size:.82rem;font-weight:500;z-index:99;transition:.4s var(--ease);opacity:0;box-shadow:var(--shadow)}
.toast.show{transform:translate(-50%,0);opacity:1}

/* ---- PRODUCT PAGE ---- */
.pdp{padding:3rem 0 5rem}
/* Same auto-minimum trap as the mobile rule below — capped here too so a wide
   gallery can never push the buy column off the grid. Identical layout while
   content fits, which on desktop it always has. */
.pdp-grid{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:3.5rem;align-items:start}
.gallery{display:grid;gap:.8rem}
.gal-main{aspect-ratio:1/1;border-radius:8px;overflow:hidden;background:var(--elev);position:relative;cursor:zoom-in}
.gal-main img{width:100%;height:100%;object-fit:cover;transition:transform .5s var(--ease);position:static}
.gal-main.zoom img{transform:scale(1.7)}
.gal-thumbs{display:flex;gap:.6rem;overflow-x:auto;scrollbar-width:none}
.gal-thumbs::-webkit-scrollbar{display:none}
.gal-thumbs button{flex:0 0 74px;aspect-ratio:1/1;border-radius:6px;overflow:hidden;border:1.5px solid transparent;background:var(--elev);transition:.2s}
.gal-thumbs button.on{border-color:var(--bronze)}
.gal-thumbs img{width:100%;height:100%;object-fit:cover;position:static}
.gal-nav{position:absolute;top:50%;transform:translateY(-50%);width:38px;height:38px;border-radius:50%;background:var(--chip-bg);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:1px solid var(--line);display:grid;place-items:center;z-index:3;cursor:pointer;opacity:0;transition:opacity .25s var(--ease),background .2s}
.gal-main:hover .gal-nav{opacity:1}
.gal-nav.prev{left:12px}
.gal-nav.next{right:12px}
.gal-nav svg{width:18px;height:18px;stroke:var(--ivory);fill:none;stroke-width:2;position:static}
.gal-nav:hover{background:var(--card)}
@media(hover:none){ .gal-main .gal-nav{opacity:1} }
/* video media in the gallery */
.gal-main.showing-video{cursor:default}
.gal-video{position:absolute;inset:0;z-index:2;background:#000}
.gal-video video,.gal-video iframe{width:100%;height:100%;object-fit:contain;display:block;border:0}
.gal-thumbs button.is-video{position:relative}
.thumb-play{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none;background:rgba(0,0,0,.28)}
.thumb-play svg{width:22px;height:22px;color:#fff;fill:#fff;position:static;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))}
.gal-thumbs button.is-video.on .thumb-play{background:rgba(0,0,0,.12)}

/* warranty badge — under Add to Cart (snippets/warranty-badge). Subtle, bronze-outlined, shield. */
/* ---------- warranty box (product page, under Add to Cart) ----------
   Standalone again — briefly lived merged into the offers carousel below as
   an extra rotating slide, but that module is scoped to promotional offers
   only; see snippets/warranty-badge.liquid. */
.pdp-warranty{display:flex;gap:.7rem;align-items:flex-start;margin:1.1rem 0 0;padding:.9rem 1rem;
  background:var(--bronze-tint);border:1px solid var(--bronze);border-radius:12px}
.pdp-warranty-ic{flex:none;display:grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--card)}
.pdp-warranty-ic svg{width:17px;height:17px;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;position:static}
.pdp-warranty-body{min-width:0}
.pdp-warranty-title{margin:0;font-family:var(--display);font-weight:600;color:var(--ivory);font-size:.98rem;line-height:1.25}
.pdp-warranty-points{list-style:none;margin:.35rem 0 0;padding:0;display:flex;flex-wrap:wrap;gap:.2rem .9rem}
.pdp-warranty-points li{position:relative;padding-left:.95rem;color:var(--taupe);font-size:.8rem;line-height:1.5}
.pdp-warranty-points li::before{content:"✓";position:absolute;left:0;color:var(--bronze-ink);font-size:.75rem;top:.05rem}
.pdp-warranty-note{margin:.5rem 0 0;color:var(--muted);font-size:.78rem;line-height:1.5}

/* ---------- Special Offers module (product page) ----------
   Rebuilt per spec: a <culture-offers> custom element (assets/theme.js) drives
   a single flex track that translates as a whole — not individually
   position:absolute cards like the previous build — so the loop-rewind can
   glide back through every slide in one transition instead of snapping.
   Geometry/motion measured from a reference widget; colours are this theme's
   own tokens, not the reference's. Ships as slide 1 static with the full
   segment row rendered (readable with no JS); the custom element upgrades it
   to a moving track only once connected. */
.pdp-offers{display:block;margin:1.1rem 0 0;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:10px}
/* margin-bottom must clear the badge's 12px poke-above-the-slide (see
   .of-badge) with room to spare, or the badge overlaps this row — the
   previous 6px was tuned only against the ≤130px mobile-height target
   and never checked against the badge's own overhang once that stopped
   being clipped off. Priority is correctness over that exact px ceiling. */
.of-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;padding:0 2px}
.of-head-label{font-family:var(--display);font-size:.875rem;font-weight:600;color:var(--bronze-ink)}
.of-head-count{font-size:.72rem;color:var(--taupe)}
/* Reserve the badge's 12px overhang as real padding inside the viewport,
   rather than letting it poke outside a clipped box. Tried overflow-x:hidden
   paired with overflow-y:visible first — mixing them makes the browser
   compute the "visible" axis as auto instead, which does NOT reliably skip
   clipping negative-offset absolutely-positioned content (worked for one
   badge, silently clipped another — an inconsistency not worth depending
   on). Plain overflow:hidden is unambiguous on both axes; this way nothing
   ever needs to render outside it in the first place. */
/* height is set inline by CultureOffers._syncHeight (theme.js), transitioned
   here — the guarantee card and a real offer with a code chip are rarely the
   same natural height (the code row only exists on the latter), and a plain
   flex row stretches every slide to match whichever is tallest by default,
   which is what was leaving a slab of empty space under the shorter card.
   Explicit per-slide height + this transition turns that into a real resize
   instead of permanently reserving the tallest slide's height for all of them. */
.of-viewport{position:relative;overflow:hidden;border-radius:10px;padding-top:14px;
  transition:height .5s var(--ease)}
/* align-items:flex-start, not the flex default (stretch): stretching is
   exactly the "match the tallest slide" behavior _syncHeight needs to
   measure past — each slide has to report its own true content height for
   the resize above to use the right number per slide. */
.of-track{display:flex;align-items:flex-start;will-change:transform}
/* Every slide — the warranty/guarantee card in slot 0, any real offer after
   it — is a plain, non-interactive wrapper (kept only for the badge's
   positioning context and the shared tinted background) around two separate
   real controls: .of-open (opens the drawer) and, when the slide has a
   code, the code row's own copy button — since a <button> can't contain
   another <button>. Used identically whether there's one slide (static) or
   several (rotating); .of-open reproduces the flex/padding a slide used to
   apply directly to itself, scoped to just the icon/title/chevron content. */
.of-slide{flex:0 0 100%;min-width:0;min-height:68px;box-sizing:border-box;position:relative;
  background:var(--bronze-tint);border-radius:10px;cursor:default;padding:0;display:block}
.of-badge{position:absolute;top:-12px;left:40px;height:24px;padding:0 10px;display:flex;align-items:center;
  background:var(--bronze);color:var(--on-accent);font-size:.72rem;font-weight:600;
  border-radius:6px 6px 6px 0;white-space:nowrap}
/* align-items:flex-start + fixed padding-top, not center: centering broke
   the moment a title needed two lines (the guarantee card's "7-Day
   Replacement Guarantee" wraps at narrow widths) — vertically centering a
   taller block sits its top edge closer to .of-open's own top, which ate
   into the badge's -12px overhang above it and the two visibly collided.
   Fixed top/bottom padding keeps the content's top edge a constant
   distance from the badge regardless of how many lines the title wraps
   to, the same "reserve real padding, don't rely on an assumption that
   only held for one specific piece of content" fix as .of-viewport's own
   padding-top above. 18+14 padding against a one-line title's own height
   lands right back on the pre-existing 68px floor, so short single-line
   offers (the common case) render at the same height as before — only a
   wrapped title grows the card. */
.of-open{position:relative;width:100%;min-height:68px;box-sizing:border-box;
  padding:18px 44px 14px 46px;display:flex;align-items:flex-start;gap:.6rem;margin:0;
  background:none;border:0;cursor:pointer;font:inherit;color:inherit;text-align:left}
/* Right margin matches .of-open's own right padding (44px, reserved up there
   for the chevron) — was 12px, which let the code row reach 30-odd px
   further right than the title row above it ever does, so the two rows
   didn't line up on the right and the card read as misaligned. */
.of-slide .of-drawer-code{margin:0 44px 14px 46px}
.of-icon{position:absolute;left:12px;top:18px;flex:none;width:24px;height:24px;
  display:grid;place-items:center}
.of-icon svg{width:20px;height:20px;stroke:var(--bronze-ink);fill:none;stroke-width:1.8;position:static}
.of-body{min-width:0;display:flex;flex-direction:column;gap:.15rem}
.of-title{margin:0;font-size:.9375rem;line-height:1.3;color:var(--ivory);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.of-title b{font-weight:700}
.of-title span{font-weight:400}
.of-sub{font-size:.75rem;color:var(--taupe);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.of-next{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:44px;height:44px;
  display:grid;place-items:center;background:none;border:none;padding:0;cursor:pointer}
.of-next-box{width:26px;height:26px;border-radius:8px;background:var(--elev);display:grid;place-items:center}
.of-next-box svg{width:14px;height:14px;stroke:var(--ivory);fill:none;stroke-width:2;position:static}
.of-progress{display:flex;gap:8px;margin-top:4px;padding:0 2px}
.of-seg{flex:1;height:5px;border-radius:999px;background:var(--deep);overflow:hidden}
.of-seg-fill{height:100%;width:0;background:var(--bronze);border-radius:inherit}
.of-seg.is-done .of-seg-fill{width:100%;transition:none}
.of-seg.is-active .of-seg-fill{transition:width linear}

/* live region for screen readers only — visually hidden */
.of-announce{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

@media (prefers-reduced-motion: reduce){
  .of-track{transition:none !important}
}

/* ---------- offers drawer (bottom sheet / modal) ---------- */
.of-drawer-scrim{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:120;opacity:0;
  pointer-events:none;transition:opacity .25s var(--ease)}
.of-drawer-scrim.is-open{opacity:1;pointer-events:auto}
.of-drawer{position:fixed;left:0;right:0;bottom:0;z-index:121;background:var(--card);
  border-radius:16px 16px 0 0;max-height:85vh;overflow-y:auto;padding:1.1rem 1.2rem 1.6rem;
  transform:translateY(100%);transition:transform .3s var(--ease)}
.of-drawer.is-open{transform:translateY(0)}
.of-drawer-handle{width:36px;height:4px;border-radius:99px;background:var(--line-strong);margin:0 auto .9rem}
.of-drawer-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:.9rem}
.of-drawer-head h3{margin:0;font-family:var(--display);font-size:1.05rem;font-weight:700;color:var(--ivory)}
.of-drawer-close{flex:none;width:32px;height:32px;display:grid;place-items:center;border-radius:50%;
  border:1px solid var(--line);background:var(--elev);cursor:pointer;color:var(--ivory)}
.of-drawer-close svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2;position:static}
.of-drawer-list{display:flex;flex-direction:column;gap:.7rem}
.of-drawer-item{background:var(--bronze-tint);border:1px solid var(--line-2);border-radius:12px;padding:.85rem .9rem}
.of-drawer-item-top{display:flex;align-items:center;gap:.6rem}
.of-drawer-badge{flex:none;font-size:.68rem;font-weight:600;color:var(--on-accent);background:var(--bronze);
  padding:.15rem .5rem;border-radius:6px}
.of-drawer-title{margin:0;font-size:.92rem;color:var(--ivory);flex:1}
.of-drawer-title b{font-weight:700}
.of-drawer-sub{margin:.3rem 0 0;font-size:.78rem;color:var(--taupe)}
.of-drawer-terms{margin:.5rem 0 0;font-size:.72rem;color:var(--muted);line-height:1.5}
.of-drawer-code{display:flex;align-items:center;justify-content:space-between;gap:.6rem;margin-top:.6rem;
  background:var(--elev);border:1px dashed var(--line-strong);border-radius:8px;padding:.5rem .7rem}
.of-drawer-code b{font-family:var(--mono,monospace);letter-spacing:.05em;color:var(--bronze-ink);font-size:.85rem}
.of-drawer-copy{flex:none;font-size:.72rem;font-weight:600;color:var(--bronze-ink);background:none;
  border:1px solid var(--bronze-soft);border-radius:6px;padding:.3rem .6rem;cursor:pointer}
.of-drawer-copy.is-copied{color:var(--good);border-color:var(--good)}

@media (min-width:760px){
  .of-drawer{left:50%;right:auto;bottom:auto;top:50%;width:min(480px,90vw);max-height:80vh;
    border-radius:16px;transform:translate(-50%,-46%);opacity:0;transition:transform .25s var(--ease),opacity .25s var(--ease)}
  .of-drawer.is-open{transform:translate(-50%,-50%);opacity:1}
  .of-drawer-handle{display:none}
}

/* visible placeholder token (policy pages + warranty), impossible to miss in QA */
.cn-placeholder{display:inline-block;font-family:var(--mono);font-size:.85em;font-weight:600;
  color:var(--deep,#22252B);background:var(--bronze-soft);padding:.05em .5em;border-radius:5px;letter-spacing:.01em}

/* trust badges — clean pills that flow evenly (snippets/trust-badges) */
/* Grid, not flex-wrap. As pills of differing text length these wrapped into a
   ragged 2-2-1 with an orphan on the last row, which read as a mistake rather
   than a layout. auto-fit + minmax gives equal-width cells that fill the row
   and drop cleanly to fewer columns as the column narrows — same chips, aligned
   edges. Rendered only by main-product, so the grid cannot affect anything
   else in the theme. */
/* PRODUCT FACTS + SHARE (snippets/trust-badges) -------------------------
   One block with one boundary. The previous version was a bordered fact strip
   with a separately-margined share row under it, which — stacked beneath the
   outlined warranty panel — put three visual containers in a row and made the
   four items read as one flat list of equals.

   Only two rules divide anything now: the top border that separates the block
   from the buy buttons, and one hairline before the share controls. Hierarchy
   is carried by type size and colour instead of by boxes, so the three facts
   fall in the order a customer asks them rather than competing.

   No dividers between the facts themselves. A border-left is only correct
   while a row does not wrap: CSS cannot tell that an item has started a new
   line, so the third item used to pick up a hanging rule and a 16px indent
   that knocked it out of alignment with the first. */
.pfacts{margin:1.1rem 0 1.6rem;padding:.95rem 0 0;border-top:1px solid var(--line-2)}
.pfacts-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
.pfacts-list:empty{display:none}
.pfact{display:flex;align-items:center;gap:.55rem;line-height:1.35;color:var(--taupe);font-weight:500}
.pfact svg{flex:none;width:15px;height:15px;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;position:static}

/* 1 — availability. The only coloured line in the block, and the largest, so
   it is read first and read as a status rather than as another footnote. The
   dot is a ::before because the variant script rewrites this element's
   textContent, which would wipe any real child node. */
.pfacts .stock-line{margin:0;font-size:.92rem;font-weight:600;gap:.5rem}
.pfacts .stock-line.in{color:var(--good)}
.pfacts .stock-line.low{color:var(--bronze-ink)}
.pfacts .stock-line.out{color:var(--muted)}
/* 2 — delivery, the most useful secondary fact: ivory keeps it legible without
   competing with the status line. */
.pfact--ship{font-size:.85rem;color:var(--ivory)}
/* 3 — gateway. Same family, one step quieter in both size and colour. */
.pfact--pay{font-size:.78rem;color:var(--muted)}
.pfact--pay svg{width:14px;height:14px}
/* payment badges (snippets/payment-badges) */
/* payment badges — vector logo chips + optional trust lines (snippets/payment-badges) */
.paywrap{display:flex;flex-direction:column;align-items:center;gap:.75rem;width:100%}
.paybadges{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:.5rem;margin:.9rem 0 0}
.pb{display:inline-flex;align-items:center;height:30px;padding:0 .6rem;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.1)}
.pb svg{height:17px;width:auto;position:static}
.pay-secure{display:inline-flex;align-items:center;gap:.45rem;margin:0;font-size:.84rem;font-weight:600;color:var(--taupe)}
.pay-secure svg{width:16px;height:16px;stroke:var(--bronze-soft);fill:none;stroke-width:1.8;position:static}
.pay-caption{margin:0;font-size:.75rem;letter-spacing:.03em;color:var(--muted)}
.pdp-info{position:sticky;top:100px}
.pdp-info .label{display:block;margin-bottom:.7rem}
.pdp-info h1{font-size:clamp(1.7rem,3.2vw,2.4rem);line-height:1.15;margin-bottom:.6rem;margin-top:-.14em}
.pdp-rating{display:flex;align-items:center;gap:.5rem;font-size:.9rem;color:var(--muted);margin-bottom:1.1rem;text-decoration:none;cursor:pointer;width:fit-content}
.pdp-rating:hover{opacity:.85}
.pdp-rating .stars{color:var(--bronze-ink);letter-spacing:.12em;font-size:1.4rem;line-height:1}
/* ── Server-side star rating (snippets/cn-stars) — Culture Nest reviews, no CLS ── */
.jm-rate{display:inline-flex;align-items:center;gap:.4rem;line-height:1;vertical-align:middle}
.jm-stars{position:relative;display:inline-block;white-space:nowrap;font-size:14px;letter-spacing:1.5px}
.jm-stars-bg{color:var(--line-2)}
.jm-stars-fg{position:absolute;left:0;top:0;overflow:hidden;color:var(--bronze-ink);white-space:nowrap}
.jm-rate-text{font-size:.8rem;color:var(--taupe);font-weight:600;font-variant-numeric:tabular-nums}
.jm-rate-count{color:var(--muted);font-weight:500}
.jm-rate--md .jm-stars{font-size:19px}
.jm-rate--md .jm-rate-text{font-size:.92rem}
.card .jm-rate{margin:.15rem 0 .1rem}
/* Reviews section: match section rhythm + offset the sticky header on scroll-to.
   Targets #reviews directly — the section that anchor points to (main-product's
   star-rating link) carries that id, not a .pdp-reviews class. */
#reviews{scroll-margin-top:90px}
/* Honest trust strip (real delivery/COD/returns signals) — cards, collection, search, PDP */
.trust-strip{display:flex;align-items:center;gap:.4rem;margin:.35rem 0 .1rem;font-size:.72rem;font-weight:500;color:var(--taupe);line-height:1.3}
.trust-strip svg{width:14px;height:14px;flex:none;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;position:static}
@media(max-width:520px){.trust-strip{font-size:.68rem}}
.pdp-price{display:flex;align-items:baseline;gap:.7rem;row-gap:.3rem;flex-wrap:wrap;margin-bottom:.5rem}
.pdp-price .saved{font-family:var(--body);font-size:.82rem;font-weight:700;color:var(--good);background:rgba(var(--good-rgb),.14);border:1px solid rgba(var(--good-rgb),.32);padding:.2rem .6rem;border-radius:100px;font-variant-numeric:tabular-nums;white-space:nowrap}
.pdp-price b{font-size:1.9rem;font-weight:700;font-family:var(--display);color:var(--bronze-ink);font-variant-numeric:tabular-nums}
.pdp-price .was{color:var(--muted);text-decoration:line-through;font-size:1rem}
/* var(--bronze-ink-deep), not var(--bronze-ink) -- the bronze-tint wash
   behind this badge (unlike --base/--card, which --bronze-ink was tuned for)
   measured 4.12:1 in light mode, just under WCAG AA. A fixed hex here would
   have fixed light mode but broken dark mode, since bronze-tint is blended
   over --card, which itself flips -- --bronze-ink-deep flips the other way
   (lighter) in dark mode for exactly this reason. */
.pdp-price .off{background:var(--bronze-tint);color:var(--bronze-ink-deep);font-size:.75rem;font-weight:700;padding:.25rem .6rem;border-radius:100px}
/* One wrapping row in place of three stacked ones. Same three facts, ~44px
   less of the first screen. Separators are generated, not typed, so the row
   still reads correctly when it wraps. */
.pdp-terms{list-style:none;display:flex;flex-wrap:wrap;align-items:center;gap:.45rem .7rem;
  margin:-.6rem 0 1.4rem;font-size:.8rem;font-weight:500;color:var(--taupe)}
.pdp-terms li{display:flex;align-items:center;gap:.32rem}
/* Every fact gets an icon now — the tax line used to be bare text next to
   two icon+text facts, which read as unfinished. All three share one
   color so the row reads as one consistent list rather than a dimmer
   first item next to two brighter ones.

   No separator dot between facts any more. It used to be a generated
   li+li::before "·" — fine when two facts shared a line, but flex-wrap
   decides per viewport width whether they do, and when a fact wrapped onto
   its own line the dot still rendered ahead of it, shoving that fact's
   icon ~15px right of the one above it. Each fact having its own icon
   already marks where it starts, so the dot was both the misalignment bug
   and an unnecessary separator once the icons existed. */
.pdp-terms svg{width:14px;height:14px;flex:none;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;position:static}
/* Two facts now, not three — the old shipping-cost fact and the old
   payment-method fact turned out to describe a ₹49 COD fee that doesn't
   exist in the store's real shipping rates (checked: both payment methods
   price delivery at ₹0), so they merged into one truthful line. That line
   is noticeably longer than the tax note ahead of it; flex-basis:100%
   still forces it onto its own row on purpose at every width, the same
   reasoning as before — leaving the break to whichever width happens to
   wrap it is what read as accidental, not the forced break itself. */
.pdp-terms li:nth-child(2){flex-basis:100%}
/* Benefit line — the answer to "what does this do for me", directly under
   the H1 and above the price. Sized between the H1 and the terms row so it
   reads as a statement rather than fine print. */
.pdp-benefit{font-size:1rem;line-height:1.45;color:var(--ivory);margin:.1rem 0 1rem;max-width:34ch}
/* Change 4 — tabular numerals on transactional numbers */
.card .price,.pdp-price,.qv-price,.ci strong,.drawer-foot .row,.count,.qty span,.qty-big input,.rec-foot small,.sticky-atc .si small,#cartSubtotal,#cartTotal{font-variant-numeric:tabular-nums}
/* Change 2 — cap long-form line length on desktop */
.acc .body{max-width:680px}
.opt{margin-bottom:1.4rem;border:0;padding:0;min-width:0}
.opt-label{font-size:.78rem;letter-spacing:.1em;text-transform:uppercase;font-weight:700;color:var(--taupe);margin-bottom:.7rem;display:flex;justify-content:space-between;width:100%}
.opt-label a{color:var(--bronze-ink);text-transform:none;letter-spacing:0;font-weight:500}
.opt-vals{display:flex;gap:.5rem;flex-wrap:wrap}
.opt-vals label{position:relative}
.opt-vals input{position:absolute;opacity:0;width:0;height:0}
.opt-vals span{display:grid;place-items:center;min-width:48px;height:44px;padding:0 .9rem;border:1px solid var(--line);border-radius:8px;font-size:.85rem;font-weight:500;cursor:pointer;transition:.2s}
.opt-vals input:checked+span{background:var(--cta,var(--bronze));border-color:var(--cta,var(--bronze));color:#fff}
.opt-vals input:focus-visible+span{outline:2px solid var(--bronze);outline-offset:2px}
.opt-vals .soldout span{opacity:.35;text-decoration:line-through;cursor:not-allowed}
/* The status dot. Everything else about the stock line — size, weight, spacing
   and the three state colours — lives with the facts block above, which is the
   only place that renders it. The standalone layout and colour rules that used
   to sit here were left behind when stock moved out of the buy column and were
   being overridden in full. */
.stock-line::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}
.qty-row{display:flex;gap:.8rem;margin-bottom:1rem;align-items:stretch}
.qty-big{display:flex;align-items:center;border:1px solid var(--line);border-radius:100px;height:52px;flex:none}
.qty-big button{width:44px;height:100%;font-size:1.1rem}
.qty-big input{width:40px;text-align:center;background:none;border:none;color:var(--ivory);font-family:inherit;font-size:.95rem;outline:none;-moz-appearance:textfield;appearance:textfield}
.qty-big input::-webkit-outer-spin-button,.qty-big input::-webkit-inner-spin-button{-webkit-appearance:none;appearance:none;margin:0}
.pdp-buy{display:grid;gap:.7rem;margin-bottom:.9rem}
.pdp-buy .btn{height:52px}
/* Share — the closing row of the facts block, divided from it by one hairline.
   The rule is on the adjacent sibling so that hiding the facts (theme setting)
   does not leave a divider with nothing above it. */
.pfacts-share{display:flex;align-items:center;gap:.8rem;flex-wrap:wrap}
.pfacts-list + .pfacts-share{margin-top:.95rem;padding-top:.85rem;border-top:1px solid var(--line-2)}
.pfacts-share-label{font-family:var(--mono);font-size:.62rem;letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
.share-row{display:flex;align-items:center;gap:.4rem}
/* These were full-colour brand logos — a green circle, a blue circle and a
   magenta gradient — which made sharing the loudest thing in the buy box,
   louder than Add to Bag, and the only saturated colour on a charcoal and
   bronze page. Monochrome at rest, brand colour on hover and focus, so the
   association survives without the noise. */
.share-btn{width:40px;height:40px;border-radius:50%;border:1px solid var(--line);
  display:grid;place-items:center;color:var(--muted);background:none;
  transition:border-color .2s var(--ease),color .2s var(--ease),background-color .2s var(--ease)}
.share-btn svg{position:static;width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.7}
/* Buttons sit one step above the dividers (--line vs --line-2) so the controls
   read as controls and the two rules stay hairlines. Fallback hover only —
   each button below sets its own. */
.share-btn:hover{border-color:var(--bronze);color:var(--bronze-ink)}
.share-wa:hover,.share-wa:focus-visible{border-color:#25D366;color:#25D366}
.share-fb:hover,.share-fb:focus-visible{border-color:#1877F2;color:#1877F2}
.share-ig:hover,.share-ig:focus-visible{border-color:#E1306C;color:#E1306C}
.share-copy:hover,.share-copy:focus-visible{border-color:var(--bronze);color:var(--bronze-ink)}
/* Copy confirmation. Both icons are in the markup; only the swap is CSS, so
   confirming costs no reflow. theme.js sets .is-copied only once the clipboard
   write has actually resolved. */
.share-ic{display:none;line-height:0}
.share-ic--idle{display:block}
.share-copy.is-copied{border-color:var(--good);color:var(--good);background:rgba(var(--good-rgb),.12)}
.share-copy.is-copied .share-ic--idle{display:none}
.share-copy.is-copied .share-ic--done{display:block}
/* Shopify dynamic checkout ("Buy it now") — restyled to match the theme */
.shopify-payment-button__button--unbranded{
  background:transparent!important;color:var(--ivory)!important;
  border:1.5px solid var(--line)!important;border-radius:100px!important;
  height:52px!important;min-height:52px!important;line-height:1!important;
  font-family:var(--body)!important;font-weight:700!important;font-size:1rem!important;letter-spacing:0!important;
  transition:background .3s ease,color .3s ease,border-color .3s ease!important;
}
.shopify-payment-button__button--unbranded:hover:not([disabled]){
  background:var(--ivory)!important;color:var(--base)!important;border-color:var(--ivory)!important;
}
.shopify-payment-button__button--unbranded[disabled]{
  background:var(--elev)!important;color:var(--muted)!important;border-color:var(--line-2)!important;opacity:1!important;
}
.shopify-payment-button__more-options{color:var(--muted)!important;font-size:.82rem!important;text-decoration:underline!important;margin-top:.55rem!important}
/* Hierarchy swap: the dynamic checkout button is the one-tap purchase path,
   so it takes the solid fill, and Add to Bag — which adds a step — becomes
   the outline. Uses --cta so it clears WCAG AA like every other filled
   button. Shopify controls this button's LABEL, so the price cannot be put
   inside it; only the treatment is ours. */
.pdp-buy.is-primary-checkout .shopify-payment-button__button--unbranded{
  background:var(--cta,var(--bronze))!important;color:var(--on-accent)!important;
  border-color:transparent!important;
}
.pdp-buy.is-primary-checkout .shopify-payment-button__button--unbranded:hover:not([disabled]){
  background:var(--cta-hover,var(--bronze))!important;color:var(--on-accent)!important;border-color:transparent!important;
}
.btn--outline{background:transparent;color:var(--ivory);border:1.5px solid var(--line-strong)}
.btn--outline:hover{background:var(--ivory);color:var(--base);border-color:var(--ivory);box-shadow:none}
.btn--outline[disabled]{background:var(--elev);color:var(--muted);border-color:var(--line-2)}
.pincode{border:1px solid var(--line);border-radius:12px;padding:1.1rem;margin-bottom:1.5rem}
.pincode h4{font-size:.82rem;letter-spacing:.08em;text-transform:uppercase;margin-bottom:.7rem;font-family:var(--body);color:var(--taupe)}
.pin-row{display:flex;gap:.5rem}
/* min-width:0 because flex items default to min-width:auto and an <input>
   will not shrink below its intrinsic size — roughly 20 characters. At 360px
   that floor pushed the Check button 36px past the panel's right edge. */
.pin-row input{flex:1;min-width:0;background:var(--elev);border:1px solid var(--line);border-radius:100px;padding:.7rem 1rem;color:var(--ivory);font-family:inherit;font-size:.88rem;outline:none}
.pin-row input:focus{border-color:var(--bronze)}
.pin-row button{background:none;border:1px solid var(--line);border-radius:100px;padding:0 1.2rem;font-size:.8rem;font-weight:700;color:var(--bronze-ink);transition:.2s}
.pin-row button:hover{background:var(--cta,var(--bronze));border-color:var(--cta,var(--bronze));color:#fff}
.pin-out{font-size:.82rem;margin-top:.7rem;color:var(--good)}
.pin-out.err{color:var(--bad)}
.trust{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:.9rem;margin-bottom:1.6rem}
.trust div{display:flex;gap:.6rem;align-items:center;font-size:.8rem;color:var(--taupe)}
.trust svg{width:17px;height:17px;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;flex:none;position:static}
.acc details{border-top:1px solid var(--line-2)}
.acc details:last-child{border-bottom:1px solid var(--line-2)}
.acc summary{list-style:none;cursor:pointer;display:flex;justify-content:space-between;align-items:center;padding:1.1rem 0;font-weight:700;font-size:.92rem;font-family:var(--display)}
.acc summary::-webkit-details-marker{display:none}
.acc summary .plus{width:20px;height:20px;position:relative;flex:none}
.acc summary .plus::before,.acc summary .plus::after{content:"";position:absolute;background:var(--bronze-soft);border-radius:2px}
.acc summary .plus::before{top:9px;left:1px;right:1px;height:2px}
.acc summary .plus::after{left:9px;top:1px;bottom:1px;width:2px;transition:opacity .3s}
.acc details[open] summary .plus::after{opacity:0}
.acc .body{padding:0 0 1.1rem;font-size:.88rem;color:var(--taupe);line-height:1.7}
.acc .body ul{padding-left:1.1rem;display:grid;gap:.3rem}
/* hidden bar must clear the banner too: the lift from --cookie-h is on top
   of its own height, so the hide transform has to travel both. */
/* z-index lives at the .sticky-atc{bottom:var(--cookie-h,...);z-index:81}
   rule further down — that's the one actually fixing the cookie-bar
   tap-stealing collision. A stale z-index:70 used to sit here too; it never
   won (the later rule always overrode it) but left a misleading value for
   anyone reading top-to-bottom, so it's gone rather than fixed twice. */
.sticky-atc{position:fixed;left:0;right:0;bottom:0;background:var(--chip-bg);color:var(--ivory);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border-top:1px solid var(--line);padding:.8rem 20px;display:none;align-items:center;gap:1rem;transform:translateY(calc(100% + var(--cookie-h,0px)));transition:.35s var(--ease);pointer-events:none}
.sticky-atc.show{pointer-events:auto}
.sticky-atc.show{transform:none}
.sticky-atc .si{display:flex;gap:.7rem;align-items:center;flex:1;min-width:0}
.sticky-atc .si .th{width:44px;height:44px;border-radius:6px;overflow:hidden;background:var(--elev);flex:none;position:relative}
.sticky-atc .si .th img{width:100%;height:100%;object-fit:cover;position:static}
/* min-width:0 — a flex item defaults to min-width:auto, so this text wrapper
   refused to shrink below its content and rendered ~383px wide inside a 191px
   parent, sliding straight under the Add to Bag button and past the viewport
   edge. The ellipsis on <b> below could never fire because the box grew to fit
   instead of clipping. .si already carried this fix; the nested span did not. */
.sticky-atc .si > span{min-width:0}
.sticky-atc .si b{font-size:.84rem;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sticky-atc .si small{font-size:.8rem;color:var(--bronze-ink);display:block;line-height:1.2}
.sticky-atc .btn{flex:none;white-space:nowrap}

/* ---- COLLECTION ---- */
.coll-head{padding:3rem 0 1.5rem;text-align:center}
.coll-head h1{font-size:clamp(2rem,4vw,3rem);margin:.7rem 0 .6rem}
.coll-head p{color:var(--taupe);max-width:48ch;margin:0 auto;font-size:.95rem}
.coll-bar{display:flex;justify-content:space-between;align-items:center;gap:1rem;padding:1.2rem 0;border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2);margin-bottom:2.2rem;flex-wrap:wrap}
.filter-toggle{display:inline-flex;align-items:center;gap:.5rem;border:1px solid var(--line);border-radius:100px;padding:.6rem 1.2rem;font-size:.82rem;font-weight:500;transition:.2s}
.filter-toggle:hover{border-color:var(--bronze)}
.filter-toggle svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8;position:static}
.coll-count{font-size:.82rem;color:var(--muted)}
/* sort dropdown — appearance reset + custom chevron */
.sortby{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--elev);border:1px solid var(--line);border-radius:100px;padding:.62rem 2.5rem .62rem 1.15rem;color:var(--ivory);font-family:inherit;font-size:.82rem;cursor:pointer;outline:none;transition:border-color .18s var(--ease),box-shadow .18s var(--ease);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235c534a' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 1.05rem center;background-size:12px}
.sortby:hover{border-color:var(--bronze-soft)}
.sortby:focus-visible{border-color:var(--bronze);box-shadow:0 0 0 3px var(--bronze-tint)}
.sortby option{background:var(--card);color:var(--ivory)}
html[data-theme="dark"] .sortby{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239b9184' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E")}
.coll-layout{display:grid;grid-template-columns:250px minmax(0,1fr);gap:2.4rem;align-items:start}
.filters{position:sticky;top:150px}
.filters details{border-bottom:1px solid var(--line-2);padding:1.15rem 0}
.filters details:first-child{padding-top:0}
.filters summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;font-weight:700;font-size:.74rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ivory)}
.filters summary::-webkit-details-marker{display:none}
.filters summary::after{content:"";width:8px;height:8px;border-right:1.6px solid var(--muted);border-bottom:1.6px solid var(--muted);transform:rotate(45deg) translateY(-2px);transition:transform .22s var(--ease),border-color .18s;flex:none}
.filters details[open] summary::after{transform:rotate(-135deg) translateY(-1px)}
.filters summary:hover::after{border-color:var(--bronze-soft)}
.filters .fbody{padding-top:1rem;display:grid;gap:.8rem}
.filters label{display:flex;align-items:center;gap:.65rem;min-height:44px;font-size:.87rem;color:var(--taupe);cursor:pointer;transition:color .15s}
.filters label:hover{color:var(--ivory)}
/* custom checkboxes / radios (Apple-style) */
.filters input[type="checkbox"],.filters input[type="radio"]{appearance:none;-webkit-appearance:none;flex:none;width:19px;height:19px;border:1.5px solid var(--line);border-radius:6px;background:var(--elev);cursor:pointer;position:relative;transition:background .16s var(--ease),border-color .16s var(--ease)}
.filters input[type="radio"]{border-radius:50%}
.filters input[type="checkbox"]:hover,.filters input[type="radio"]:hover{border-color:var(--bronze-soft)}
.filters input[type="checkbox"]:checked,.filters input[type="radio"]:checked{background:var(--bronze);border-color:var(--bronze)}
.filters input[type="checkbox"]:checked::after{content:"";position:absolute;left:6px;top:2.5px;width:5px;height:9px;border:solid var(--on-accent);border-width:0 2px 2px 0;transform:rotate(45deg)}
.filters input:disabled{opacity:.35;cursor:not-allowed}
.filters label:has(input:disabled){color:var(--muted);cursor:not-allowed}
.filters input:focus-visible{outline:none;box-shadow:0 0 0 3px var(--bronze-tint)}
.filters .swatch{width:16px;height:16px;border-radius:50%;border:1px solid var(--line)}
/* price range fields */
.price-range{display:flex;align-items:center;gap:.55rem}
.price-field{display:flex;align-items:stretch;gap:.35rem;flex:1;min-width:0;min-height:44px;background:var(--elev);border:1px solid var(--line);border-radius:10px;padding:0 .7rem;transition:border-color .16s var(--ease),box-shadow .16s var(--ease)}
.price-field:focus-within{border-color:var(--bronze);box-shadow:0 0 0 3px var(--bronze-tint)}
.price-field .cur{color:var(--muted);font-size:.85rem;flex:none;display:flex;align-items:center}
/* filter tap targets: the input fills the pill so there is no dead edge */
.price-field input{width:100%;min-width:0;align-self:stretch;background:none;border:none;outline:none;color:var(--ivory);font-family:inherit;font-size:.85rem;font-variant-numeric:tabular-nums;-moz-appearance:textfield;appearance:textfield}
.price-field input::-webkit-outer-spin-button,.price-field input::-webkit-inner-spin-button{-webkit-appearance:none;appearance:none;margin:0}
.price-sep{color:var(--muted);flex:none}
.active-chips{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1.4rem}
.chip-f{display:inline-flex;align-items:center;gap:.3rem;background:var(--elev);border:1px solid var(--line);border-radius:100px;padding:.35rem .35rem .35rem .8rem;font-size:.78rem}
/* remove-filter target: 32x32 hit area around a small glyph */
.chip-f a{color:var(--muted);font-weight:700;display:inline-flex;align-items:center;justify-content:center;
  min-width:32px;min-height:32px;border-radius:50%;line-height:1}
.chip-f a:hover{color:var(--ivory);background:var(--line-2)}
.pagination{display:flex;justify-content:center;gap:.5rem;margin-top:3rem}
.pagination a,.pagination span{min-width:40px;height:40px;display:grid;place-items:center;border:1px solid var(--line-2);border-radius:50%;font-size:.85rem}
.pagination .current{background:var(--cta,var(--bronze));border-color:var(--cta,var(--bronze));color:#fff}
.empty-state{text-align:center;padding:4rem 0}
.empty-state h2{font-size:1.4rem;margin-bottom:.6rem}
.empty-state p{color:var(--muted);margin-bottom:1.6rem}

/* ---- CART PAGE / PAGE / BLOG / 404 ---- */
.page-wrap{padding:3.5rem 0 5rem;min-height:50vh}
.page-wrap h1{font-size:clamp(2rem,4vw,2.8rem);margin-bottom:1.6rem}
.rte{color:var(--taupe);line-height:1.8;max-width:680px}
.rte h2{font-size:1.5rem;margin:2rem 0 .8rem;color:var(--ivory)}
.rte h3{font-size:1.15rem;margin:1.5rem 0 .6rem;color:var(--ivory)}
.rte p{margin-bottom:1rem}
.rte ul,.rte ol{padding-left:1.3rem;margin-bottom:1rem;display:grid;gap:.4rem}
.rte a{color:var(--bronze-ink);text-decoration:underline}
.cart-table{width:100%;border-collapse:collapse}
.cart-table th{text-align:left;font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);padding-bottom:1rem;border-bottom:1px solid var(--line-2);font-weight:700}
.cart-table td{padding:1.3rem 0;border-bottom:1px solid var(--line-2);vertical-align:middle}
.cart-prod{display:flex;gap:1rem;align-items:center}
.cart-prod .th{width:76px;height:92px;border-radius:8px;overflow:hidden;background:var(--elev);flex:none;position:relative}
.cart-prod .th img{width:100%;height:100%;object-fit:cover;position:static}
.cart-foot{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:2.5rem;margin-top:2.5rem;align-items:start}
.cart-sum{background:var(--card);border:1px solid var(--line-2);border-radius:14px;padding:1.7rem}
.cart-sum .row{display:flex;justify-content:space-between;font-size:.9rem;color:var(--taupe);margin-bottom:.6rem}
.cart-sum .row.total{color:var(--ivory);font-weight:700;font-size:1.15rem;font-family:var(--display);padding-top:.8rem;border-top:1px solid var(--line-2);margin-top:.8rem}
.notes textarea{width:100%;background:var(--elev);border:1px solid var(--line);border-radius:10px;padding:.9rem;color:var(--ivory);font-family:inherit;font-size:.88rem;min-height:90px;outline:none;resize:vertical}
.notes textarea:focus{border-color:var(--bronze)}
.blog-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1.6rem}
.post .ph{aspect-ratio:3/2;border-radius:8px;margin-bottom:1rem}
.post:hover img{transform:scale(1.05)}
.post h2{font-size:1.15rem;margin-bottom:.4rem}
.post .date{font-size:.76rem;color:var(--muted)}
.post p{font-size:.88rem;color:var(--taupe);margin-top:.5rem}
.err-404{text-align:center;padding:5.5rem 0;max-width:620px;margin:0 auto}
.err-mark{margin:0 auto 1.4rem;line-height:0;opacity:.16}
.err-mark svg{width:112px;height:112px}
.err-404 .label{display:inline-block;margin-bottom:1rem}
.err-404 h1{font-size:clamp(1.9rem,5vw,3rem);color:var(--ivory);letter-spacing:-.02em;line-height:1.12}
.err-404 p{color:var(--taupe);margin:.9rem auto 2rem;max-width:440px}
.err-actions{display:flex;gap:.8rem;justify-content:center;flex-wrap:wrap}
.acct-form{max-width:420px;margin:0 auto}
.field{margin-bottom:1.1rem}
.field label{display:block;font-size:.78rem;letter-spacing:.1em;text-transform:uppercase;color:var(--taupe);margin-bottom:.5rem;font-weight:500}
.field input,.field textarea,.field select{width:100%;background:var(--elev);border:1px solid var(--line);border-radius:10px;padding:.9rem 1rem;color:var(--ivory);font-family:inherit;font-size:.92rem;outline:none}
.field input:focus,.field textarea:focus{border-color:var(--bronze)}
.breadcrumb{font-size:.78rem;color:var(--muted);padding:1.4rem 0}
/* Ad traffic lands here directly and has no history to walk back through,
   and the trail repeated the H1 verbatim 500px above it — 64px of the first
   screen for a duplicate. Desktop keeps it: there it costs nothing and does
   help orientation. BreadcrumbList structured data is emitted separately in
   meta-tags and is unaffected. */
@media (max-width:767px){ .pdp-crumb{display:none} }
.breadcrumb a:hover{color:var(--bronze-ink)}

/* responsive */
@media (max-width:1080px){
  /* minmax(0,1fr), not 1fr. `1fr` is shorthand for minmax(auto,1fr), and that
     auto floor refuses to shrink a column below its content's min-content
     width. On the product page the gallery's thumbnail strip set that floor at
     ~375px, so inside a 320px content box the column stayed 375px wide and the
     gallery ran 35px past the right edge of a 360px phone. body{overflow-x:clip}
     then swallowed the evidence: nothing could scroll to reveal it, so it read
     as content simply cut off at the edge.

     minmax(0,…) removes only the floor. Where content already fits — which is
     everywhere else these grids are used — the computed layout is
     unchanged. */
  .craft-grid,.pdp-grid,.cart-foot{grid-template-columns:minmax(0,1fr);gap:2.8rem}
  .pdp-info{position:static}
  .coll-layout{grid-template-columns:minmax(0,1fr)}
  .filters{display:none;position:static}
  .filters.open{display:block;margin-bottom:2rem}
  .blog-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
}
@media (max-width:680px){
  .wrap{padding:0 20px}
  .nav-links{display:none}
  .burger{display:flex}
  .blog-grid{grid-template-columns:minmax(0,1fr)}
  .card .meta{padding:.9rem}
  .card h3,.card h4{font-size:.92rem}
  .stories{gap:1.1rem;margin-inline:-20px;padding-left:20px;padding-right:20px;scroll-padding-left:20px}
  .story{flex:0 0 82px}
  .section{padding:2.6rem 0}
  .chip.rating{left:0;top:14px}
  .chip.ship{right:0;bottom:14px}
  .sticky-atc{display:flex}
  .coll-bar{top:0}
  .trust{grid-template-columns:minmax(0,1fr)}
  body.has-sticky{padding-bottom:64px}
}
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  .reveal{opacity:1;transform:none}
}

/* ---- PASSWORD / COMING SOON ---- */
.pw{min-height:100svh;display:flex;flex-direction:column;position:relative;overflow:hidden;padding:2rem 20px}
.pw-bg{position:absolute;inset:0;z-index:0;background:
  radial-gradient(58% 55% at 78% 12%,var(--bronze-tint),transparent 58%),
  radial-gradient(46% 46% at 8% 92%,rgba(176,110,59,.09),transparent 62%)}
.pw-photo{position:absolute;inset:0;z-index:0;overflow:hidden}
.pw-photo img{width:100%;height:100%;object-fit:cover;opacity:.24;transform:scale(1.03);animation:pwDrift 26s ease-in-out infinite alternate}
.pw-photo::after{content:"";position:absolute;inset:0;background:linear-gradient(to bottom,rgba(27,30,36,.72),rgba(27,30,36,.9))}
@keyframes pwDrift{to{transform:scale(1.1)}}
.pw-inner{position:relative;z-index:2;flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;max-width:660px;margin:0 auto;padding:2.5rem 0}
.pw-logo{font-size:1.5rem;margin-bottom:2.6rem;animation:pwUp .7s var(--ease) both}
.pw-eyebrow{display:block;margin-bottom:1.1rem;animation:pwUp .7s var(--ease) .1s both}
.pw-title{font-size:clamp(2.3rem,6vw,3.9rem);font-weight:700;letter-spacing:-.035em;animation:pwUp .8s var(--ease) .2s both}
.pw-body{color:var(--taupe);font-size:1.02rem;max-width:46ch;margin:1.3rem auto 0;animation:pwUp .8s var(--ease) .3s both}
@keyframes pwUp{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}

.pw-count{display:flex;align-items:flex-start;justify-content:center;gap:.6rem;margin:2.8rem 0 .9rem;animation:pwUp .8s var(--ease) .4s both}
.pw-count .unit{background:rgba(42,46,55,.6);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--line);border-radius:14px;padding:1rem .5rem .7rem;min-width:82px}
.pw-count .unit span{display:block;font-family:var(--display);font-weight:700;font-size:2.1rem;line-height:1;font-variant-numeric:tabular-nums;color:var(--ivory)}
.pw-count .unit small{display:block;margin-top:.45rem;font-size:.62rem;letter-spacing:.22em;text-transform:uppercase;color:var(--muted)}
.pw-count .sep{font-family:var(--display);font-weight:700;font-size:1.6rem;color:var(--bronze-ink);line-height:1;padding-top:1rem}
.pw-count.live .unit{border-color:var(--bronze);background:var(--bronze-tint)}
.pw-date{font-size:.8rem;letter-spacing:.16em;text-transform:uppercase;color:var(--bronze-ink);font-weight:500;animation:pwUp .8s var(--ease) .45s both}

.pw-form-wrap{width:100%;max-width:460px;margin-top:2.6rem;animation:pwUp .8s var(--ease) .55s both}
.pw-form-label{font-size:.75rem;letter-spacing:.2em;text-transform:uppercase;color:var(--taupe);font-weight:500;margin-bottom:.9rem}
.pw-form{display:flex;gap:.55rem;flex-wrap:wrap;justify-content:center}
.pw-form input{flex:1;min-width:220px;padding:1.05rem 1.4rem;border-radius:100px;border:1px solid var(--line);background:rgba(27,30,36,.7);font-family:inherit;font-size:.92rem;color:var(--ivory);outline:none;transition:border-color .25s}
.pw-form input::placeholder{color:var(--muted)}
.pw-form input:focus{border-color:var(--bronze)}
.pw-note{font-size:.76rem;color:var(--muted);margin-top:.9rem}
.pw-msg{flex-basis:100%;font-size:.85rem;margin-top:.7rem;font-weight:500}
.pw-msg.ok{color:var(--bronze-ink)}
.pw-msg.err{color:var(--bad)}

.pw-teasers{list-style:none;display:flex;gap:1.6rem;flex-wrap:wrap;justify-content:center;margin-top:2.6rem;animation:pwUp .8s var(--ease) .65s both}
.pw-teasers li{display:flex;align-items:center;gap:.5rem;font-size:.82rem;color:var(--taupe)}
.pw-teasers .tk{width:22px;height:22px;border-radius:50%;background:var(--bronze-tint);display:grid;place-items:center;flex:none}
.pw-teasers svg{width:11px;height:11px;stroke:var(--bronze-soft);fill:none;stroke-width:2.4;position:static}

.pw-socials{display:flex;gap:.7rem;margin-top:2.4rem;animation:pwUp .8s var(--ease) .7s both}
.pw-socials a{width:38px;height:38px;border-radius:50%;border:1px solid var(--line);display:grid;place-items:center;transition:.25s var(--ease)}
.pw-socials a:hover{background:var(--bronze);border-color:var(--bronze);transform:translateY(-2px)}
.pw-socials svg{width:16px;height:16px;stroke:var(--ivory);fill:none;stroke-width:1.7;position:static}

.pw-enter{margin-top:2.6rem;animation:pwUp .8s var(--ease) .78s both}
.pw-enter-btn{font-size:.76rem;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--line);padding-bottom:.3rem;transition:.25s;font-weight:500}
.pw-enter-btn:hover{color:var(--ivory);border-color:var(--bronze)}
.pw-login{margin-top:1.2rem}
.pw-login-form{display:flex;gap:.5rem;justify-content:center;flex-wrap:wrap}
.pw-login-form input{padding:.85rem 1.2rem;border-radius:100px;border:1px solid var(--line);background:rgba(27,30,36,.7);font-family:inherit;font-size:.88rem;color:var(--ivory);outline:none;min-width:200px}
.pw-login-form input:focus{border-color:var(--bronze)}
.pw-login-form .btn{padding:.85rem 1.6rem}

.pw-foot{position:relative;z-index:2;display:flex;justify-content:space-between;align-items:center;gap:1rem;flex-wrap:wrap;font-size:.74rem;color:var(--muted);padding-top:1.5rem;border-top:1px solid var(--line-2);max-width:1100px;margin:0 auto;width:100%}

@media (max-width:640px){
  .pw-count{gap:.35rem}
  .pw-count .unit{min-width:0;flex:1;padding:.8rem .3rem .6rem}
  .pw-count .unit span{font-size:1.5rem}
  .pw-count .unit small{font-size:.55rem;letter-spacing:.14em}
  .pw-count .sep{font-size:1.1rem;padding-top:.8rem}
  .pw-teasers{gap:.9rem 1.2rem}
  .pw-foot{justify-content:center;text-align:center}
}

/* ---- MEGA MENU ----
   Compact by design: height follows content, no fixed heights. The panel is
   absolutely positioned against .nav (position:relative) — .has-mega stays
   static and must never gain a transform, or it becomes the containing block
   and the panel collapses to the width of the trigger word. */
.nav-side{flex:1;display:flex;align-items:center}
.nav-right{justify-content:flex-end}
.logo--center{position:absolute;left:50%;transform:translateX(-50%)}
.header .nav{position:relative}
.has-mega{position:static}
.mega{position:absolute;top:100%;left:0;right:0;z-index:70;background:var(--card);
  border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2);box-shadow:var(--shadow);
  opacity:0;visibility:hidden;transform:translateY(-6px);pointer-events:none;
  transition:opacity .2s var(--ease),transform .2s var(--ease),visibility .2s}
.has-mega.open > .mega{opacity:1;visibility:visible;transform:none;pointer-events:auto}
/* Bridges the 1px seam between trigger and panel so the pointer never crosses
   dead space on its way down. */
.has-mega.open::after{content:"";position:absolute;left:0;right:0;top:100%;height:10px}
.mega-inner{max-width:1100px;margin:0 auto;padding:1.35rem 32px 1.5rem}

/* Quick links — compact pills. */
.mega-quick{display:flex;gap:.5rem;flex-wrap:wrap;padding-bottom:.95rem;margin-bottom:1.05rem;border-bottom:1px solid var(--line-2)}
.mega-quick-link{display:inline-flex;align-items:center;gap:.4rem;padding:.48rem .9rem;font-size:.82rem;
  font-weight:500;color:var(--taupe);background:var(--elev);border:1px solid var(--line);border-radius:100px;
  transition:color .2s var(--ease),border-color .2s var(--ease),background .2s var(--ease)}
.mega-quick-link svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2;position:static;
  opacity:0;transform:translateX(-3px);transition:opacity .2s var(--ease),transform .2s var(--ease)}
.mega-quick-link:hover{color:var(--ivory);border-color:var(--bronze);background:var(--bronze-tint)}
.mega-quick-link:hover svg{opacity:1;transform:none}

/* Flex, not a fixed grid: category columns hug their content at the left and
   the promo is pushed to the right edge with margin-left:auto. A three-column
   grid of 1fr tracks stretched four links across 750px and left the promo
   marooned in a wide gap — this keeps the panel proportional to whatever the
   catalogue actually has, and wraps instead of squashing when it grows. */
.mega-grid{display:flex;flex-wrap:wrap;align-items:flex-start;gap:1.5rem 2.6rem}
/* Grow to share the row, but cap at 230px. Uncapped 1fr tracks stretched three
   columns across 750px and stranded the promo in the gap; pure content-width
   columns swung the other way and left ~270px of dead space beside them. */
.mega-col{flex:1 1 145px;min-width:145px;max-width:230px}
.mega-col h4{font-family:var(--body);font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--bronze-ink);margin-bottom:.6rem;font-weight:700}
.mega-col ul{list-style:none;display:grid;gap:.1rem;align-content:start}
.mega-col a{display:flex;align-items:center;gap:.5rem;padding:.28rem 0;font-size:.88rem;color:var(--taupe);
  transition:color .18s var(--ease)}
.mega-link-t{position:relative}
.mega-link-t::after{content:"";position:absolute;left:0;bottom:-2px;height:1px;width:0;background:var(--bronze);
  transition:width .22s var(--ease)}
.mega-col a:hover{color:var(--ivory)}
.mega-col a:hover .mega-link-t::after{width:100%}

/* Promo: compact card, image optional, aligned to the top of the columns. */
.mega-promo{flex:0 0 250px;margin-left:auto;border:1px solid var(--line-2);border-radius:12px;overflow:hidden;
  background:var(--elev);transition:border-color .2s var(--ease),background .2s var(--ease)}
.mega-promo:hover{border-color:var(--bronze);background:var(--bronze-tint)}
.mega-promo-img{display:block;aspect-ratio:16/9;overflow:hidden}
.mega-promo-img img{width:100%;height:100%;object-fit:cover;position:static;transition:transform .4s var(--ease)}
.mega-promo:hover .mega-promo-img img{transform:scale(1.05)}
.mega-promo-c{display:block;padding:.8rem .9rem .85rem}
.mega-promo-c strong{display:block;font-family:var(--display);font-size:.92rem;color:var(--ivory);line-height:1.3}
.mega-promo-c small{display:block;margin-top:.2rem;font-size:.75rem;color:var(--muted);line-height:1.4}
.mega-promo-cta{display:inline-flex;align-items:center;gap:.35rem;margin-top:.6rem;font-size:.78rem;
  font-weight:600;color:var(--bronze-ink)}
.mega-promo-cta svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2;position:static;
  transition:transform .2s var(--ease)}
.mega-promo:hover .mega-promo-cta svg{transform:translateX(3px)}

.mega a:focus-visible{outline:2px solid var(--bronze-soft);outline-offset:3px;border-radius:4px}
@media(prefers-reduced-motion:reduce){
  .mega,.mega-quick-link svg,.mega-promo-img img,.mega-link-t::after{transition:none}
}

/* ---- MOBILE NAV ----
   A drawer with its own information architecture: quick pills, then collapsed
   category accordions, then flat links. Height is content-driven (max-height is
   a ceiling, never a floor) and --cookie-h is published by theme.js so the
   drawer stops above the consent bar instead of scrolling underneath it. */
.mnav{display:none}
.mnav-scrim{display:none}
@media (max-width:680px){
  .mnav{display:block;position:fixed;left:0;right:0;top:78px;z-index:82;
    background:var(--card);border-bottom:1px solid var(--line-2);border-radius:0 0 20px 20px;
    box-shadow:0 26px 44px -14px rgba(0,0,0,.5);
    max-height:calc(100dvh - 78px - var(--cookie-h,0px) - 12px);
    opacity:0;visibility:hidden;transform:translateY(-10px);pointer-events:none;
    transition:opacity .22s var(--ease),transform .22s var(--ease),visibility .22s}
  .mnav[hidden]{display:block}          /* [hidden] is the pre-JS state; JS drops it on first open */
  .mnav.open{opacity:1;visibility:visible;transform:none;pointer-events:auto}
  .mnav-scroll{overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
    max-height:inherit;padding:.85rem 14px 1.05rem}

  .mnav-scrim{display:block;position:fixed;inset:0;z-index:81;background:rgba(12,13,16,.5);
    opacity:0;visibility:hidden;transition:opacity .22s var(--ease),visibility .22s}
  .mnav-scrim.open{opacity:1;visibility:visible}

  .mnav-label{font-size:.66rem;letter-spacing:.18em;text-transform:uppercase;color:var(--bronze-ink);
    font-weight:700;margin:.1rem .2rem .55rem}

  /* Quick actions: pills that wrap, not full-width category cards. */
  .mnav-pills{display:flex;flex-wrap:wrap;gap:.45rem;margin-bottom:.9rem}
  .mnav-pill{display:inline-flex;align-items:center;min-height:44px;padding:.5rem 1.05rem;font-size:.86rem;
    font-weight:600;color:var(--ivory);background:var(--elev);border:1px solid var(--line-2);
    border-radius:100px;transition:background-color .18s,border-color .18s,color .18s}
  .mnav-pill:active{background:var(--cta,var(--bronze));border-color:var(--cta,var(--bronze));color:var(--on-accent)}

  .mnav-groups,.mnav-flat{list-style:none;display:block}
  .mnav-groups{border-top:1px solid var(--line-2);padding-top:.35rem}

  /* Real <button>s, so Enter/Space and screen-reader semantics come for free. */
  .mnav-group-btn{display:flex;align-items:center;justify-content:space-between;gap:.75rem;width:100%;
    min-height:48px;padding:.75rem .2rem .75rem .55rem;background:none;border:0;border-radius:12px;
    font-family:inherit;font-size:.99rem;font-weight:600;color:var(--ivory);text-align:left;cursor:pointer;
    transition:background-color .18s,color .18s}
  .mnav-group-btn:active{background:var(--bronze-tint);color:var(--bronze-ink)}
  .mnav-chev{width:16px;height:16px;flex:none;stroke:var(--taupe);fill:none;stroke-width:2;
    stroke-linecap:round;stroke-linejoin:round;position:static;
    transition:transform .2s var(--ease),stroke .18s}
  .mnav-group-btn[aria-expanded="true"]{color:var(--bronze-ink)}
  .mnav-group-btn[aria-expanded="true"] .mnav-chev{transform:rotate(90deg);stroke:var(--bronze-soft)}

  /* Grid-rows 0fr→1fr animates to the panel's real height without hardcoding a
     max-height guess that would clip a longer category later on. */
  .mnav-panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s var(--ease)}
  .mnav-panel > ul{overflow:hidden;list-style:none;min-height:0}
  .mnav-group.open .mnav-panel{grid-template-rows:1fr}
  .mnav-panel[hidden]{display:grid}     /* keep it animatable; JS toggles .open, not display */
  .mnav-panel a{display:flex;align-items:center;min-height:44px;padding:.6rem 1rem .6rem 1.15rem;
    font-size:.93rem;font-weight:500;color:var(--taupe);border-radius:10px;
    transition:background-color .18s,color .18s}
  .mnav-panel a:active{background:var(--bronze-tint);color:var(--bronze-ink)}
  .mnav-panel li:last-child a{margin-bottom:.3rem}

  .mnav-flat{border-top:1px solid var(--line-2);margin-top:.35rem;padding-top:.35rem}
  .mnav-flat a{display:flex;align-items:center;min-height:48px;padding:.75rem .55rem;
    font-size:.99rem;font-weight:600;color:var(--ivory);border-radius:12px;
    transition:background-color .18s,color .18s}
  .mnav-flat a:active,.mnav-flat a[aria-current]{background:var(--bronze-tint);color:var(--bronze-ink)}

  .mnav-foot{display:flex;gap:.55rem;margin-top:.55rem;padding-top:.8rem;border-top:1px solid var(--line-2)}
  .mnav-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:46px;
    padding:.7rem .6rem;font-size:.92rem;font-weight:600;border-radius:100px;
    background:var(--elev);border:1px solid var(--line-2);color:var(--ivory)}
  .mnav-btn--accent{background:var(--cta,var(--bronze));border-color:var(--cta,var(--bronze));color:var(--on-accent)}
  .mnav-btn svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.7;position:static}

  .mnav a:focus-visible,.mnav button:focus-visible{outline:2px solid var(--bronze-soft);outline-offset:2px}
}
@media (prefers-reduced-motion:reduce){
  .mnav,.mnav-scrim,.mnav-panel,.mnav-chev{transition:none}
}

/* ---- PRODUCT RAIL ---- */
.rail-tools{display:flex;align-items:center;gap:1.4rem}
.rail-nav{display:flex;gap:.5rem}
.rail-nav button{width:42px;height:42px;border:1px solid var(--line);border-radius:50%;display:grid;place-items:center;transition:.22s}
.rail-nav button:hover:not(:disabled){background:var(--bronze);border-color:var(--bronze)}
.rail-nav button:disabled{opacity:.3;cursor:not-allowed}
.rail-nav svg{width:16px;height:16px;stroke:var(--ivory);fill:none;stroke-width:1.9;position:static}
.rail-wrap{position:relative}
.rail{display:flex;gap:1.1rem;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;
 padding:.3rem 32px 1rem;max-width:var(--wrap);margin:0 auto;scroll-padding-left:32px}
.rail::-webkit-scrollbar{display:none}
.rail-item{flex:0 0 clamp(200px,23%,290px);scroll-snap-align:start;display:flex;flex-direction:column}
.rail-item>.card{flex:1}
.rail-end-card{height:100%;min-height:340px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.6rem;
 border:1px dashed var(--line);border-radius:8px;text-align:center;padding:1.5rem;transition:.3s var(--ease)}
.rail-end-card:hover{border-color:var(--bronze);background:var(--bronze-tint)}
.rail-end-card .ring{width:52px;height:52px;border-radius:50%;border:1px solid var(--bronze);display:grid;place-items:center;margin-bottom:.4rem}
.rail-end-card .ring svg{width:20px;height:20px;stroke:var(--bronze-soft);fill:none;stroke-width:1.8;position:static}
.rail-end-card strong{font-family:var(--display);font-size:1rem}
.rail-end-card small{font-size:.78rem;color:var(--muted)}

/* ---- DISCOVER ---- */
/* discover — mobile-first: 2-up base, 3-up desktop */
.discover{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem}
@media(min-width:681px){.discover{gap:1.2rem}}
@media(min-width:1081px){.discover{grid-template-columns:repeat(3,minmax(0,1fr))}}
.disc{position:relative;border-radius:8px;overflow:hidden;display:block}
.disc-imgs{aspect-ratio:4/5}
.disc-imgs .d2{opacity:0}
.disc:hover .d1{transform:scale(1.05)}
.disc:hover .d2{opacity:1;transform:scale(1.02)}
.disc::after{content:"";position:absolute;inset:0;z-index:2;background:linear-gradient(to top,rgba(15,16,20,.85) 4%,rgba(15,16,20,.1) 52%,transparent 75%);transition:.35s}
.disc:hover::after{background:linear-gradient(to top,rgba(15,16,20,.9) 4%,rgba(15,16,20,.2) 60%)}
.disc-c{position:absolute;left:0;right:0;bottom:0;z-index:3;padding:1.6rem;text-align:center}
.disc-c h3{font-size:1.3rem;margin-bottom:.6rem}
.disc-cta{display:inline-flex;align-items:center;gap:.4rem;font-size:.76rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
 color:var(--base);background:var(--ivory);padding:.6rem 1.2rem;border-radius:100px;transition:.3s var(--ease);opacity:0;transform:translateY(8px)}
.disc:hover .disc-cta{opacity:1;transform:none}
.disc-cta svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2.2;position:static}

/* ---- SEO + FAQ ---- */
.seo-sec{border-top:1px solid var(--line-2)}
.seo-box{position:relative;overflow:hidden;transition:max-height .5s var(--ease)}
.seo-fade{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;transition:opacity .4s;
 background:linear-gradient(to bottom,transparent,var(--base) 88%)}
.seo-h{font-size:clamp(1.5rem,3vw,2.1rem);margin-bottom:1.2rem}
.seo-intro{margin-bottom:1.6rem}
.seo-body .rte{margin-bottom:1.4rem;max-width:680px}
.seo-body .rte h3{font-size:1.1rem;color:var(--ivory);margin:1.6rem 0 .5rem}
.seo-faq-h{font-size:1.25rem;margin:2.2rem 0 .6rem}
.seo-acc summary{font-size:.95rem}
.seo-more{display:block;margin:1.4rem auto 0;font-size:.76rem;letter-spacing:.16em;text-transform:uppercase;font-weight:700;
 color:var(--bronze-ink);border:1px solid var(--line);border-radius:100px;padding:.7rem 1.6rem;transition:.25s}
.seo-more:hover{background:var(--cta,var(--bronze));border-color:var(--cta,var(--bronze));color:#fff}

/* ---- FOOTER: popular searches ---- */











/* ---- CART DRAWER RECS ----
   Each suggestion is a horizontal tile: thumbnail, name, price, add. It used to
   be a tall vertical card, which cost more of the drawer than the bag itself —
   285px of suggestions against 144px of scrollable cart, so a customer with two
   items could see neither of them fully. The tile form is ~116px and hands the
   difference back to the cart list.

   This is the base style rather than a mobile override because the drawer is
   `width:min(420px,100%)` — a 420px panel at every viewport above that. The
   tall card wasted the same space on a 1920px screen as it did on a phone.

   The markup is unchanged. Grid areas place the existing children directly, and
   .rec-foot becomes display:contents so its price and button can sit in
   different cells without needing a wrapper of their own. */
/* Recommendations rail + saved-for-later wishlist panel used to live here
   (old .drawer-recs/.rec*/.drawer-wish/.dw-* classes) — removed with the
   rest of the previous drawer. The rebuilt recs rail is under "CART
   DRAWER — rebuilt from scratch" earlier in this file (.ccart-rec*).
   The wishlist/"saved for later" panel isn't part of the reference mock
   at all, so it isn't rebuilt — a real feature drop, not a styling change;
   flagged in the implementation summary. */

@media (max-width:1080px){
  .mega-promo{display:none}
}
@media (max-width:680px){
  .logo--center{position:static;transform:none}
  .logo{font-size:1.04rem;white-space:nowrap;gap:.45rem}
  .logo .mark{width:26px;height:26px}
  .nav-actions{gap:.7rem}
  .theme-switch-track{width:40px;height:23px}
  .theme-switch-knob{width:17px;height:17px}
  html[data-theme="dark"] .theme-switch-knob{transform:translateX(19px)}
  .nav-side{flex:none}
  .nav-left{position:absolute;width:0;height:0;top:0;overflow:visible}
  /* The desktop panel is gone below this width — phones get .mnav, which is
     purpose-built navigation rather than this panel reflowed into a column. */
  .mega{display:none}
  .nav-store{display:none}
  .disc-c{padding:1rem}
  .disc-c h3{font-size:1rem}
  .disc-cta{opacity:1;transform:none;font-size:.66rem;padding:.45rem .9rem}
  .rail{padding-left:20px;padding-right:20px;scroll-padding-left:20px}
  .rail-item{flex-basis:64%}
  .rail-nav{display:none}
  .seo-body .rte{max-width:none}
}
@media (max-width:360px){
  .logo{font-size:.95rem;gap:.4rem}
  .logo .mark{width:24px;height:24px}
  .nav-actions{gap:.6rem}
}

/* ===================================================================
   MOBILE-FIRST HARDENING  (appended 2026-08-01)
   Global, additive fixes ordered last so they win on source order.
   Nothing here changes desktop (all inside mobile queries / @supports),
   so it can't regress the published desktop layout.
   =================================================================== */

/* -- 1. iOS focus-zoom: any text-entry control under 16px makes Safari
      zoom on focus and never zoom back, breaking the layout. Force the
      known sub-16px controls to exactly 16px on phones (desktop keeps
      its finer type). These selectors match the originals' specificity
      and come later in the file, so they win without !important. -- */
@media (max-width:699px){
  .field input,.field textarea,.field select,
  .acct-form input,.acct-form textarea,
  .news-form input,.welcome-form input,.pin-row input,.notes textarea,
  .qty-big input,.price-field input,
  .pw-form input,.pw-login-form input{font-size:16px}
}

/* -- 2. Touch targets: WCAG 2.5.5 / Apple HIG want ~44px. Vertical space
      in the 78px header bar is free, so icons get a full-height tap area;
      cards & drawer controls have room to grow their hit box too. -- */
@media (max-width:680px){
  /* Search and Bag were 40px wide against a 44px minimum. Width only — the
     height already passed, and the icon glyphs are unchanged. Scoped to
     mobile: desktop has no touch-target minimum, and applying this
     unconditionally previously inflated the box there too, dragging the
     cart-count badge (positioned off the box edges) away from the glyph. */
  .icon-btn{width:40px;height:44px;min-width:44px;min-height:44px}
  .icon-btn svg{width:21px;height:21px}
  .burger{width:44px;height:44px;flex:none;justify-content:center;align-items:center}
  .burger span{width:24px}   /* empty spans need an explicit width once the row centers them */
  .theme-switch{min-width:44px;min-height:44px;justify-content:center}
  .nav-actions{gap:.35rem}

  /* .card .add rules lived here for a circular add button that no markup has
     rendered for some time. The .card .wish shrink to 40px also went: the
     button is now the 44px touch target with a 34px disc drawn by ::before,
     so shrinking it only broke WCAG 2.5.5. */

  .qty{height:40px}
  .qty button{width:40px}
  .qty span{min-width:30px}
  .x,.qv-close,.welcome-close{width:40px;height:40px}
  /* The old cart drawer's own mobile tap-target/padding overrides
     (.ci .rm, .drawer-head/body/foot, .cart-rewards*) lived here — removed
     with the rest of it. The rebuilt drawer's sizes (.ccart-item-remove,
     .ccart-qty, etc.) are copied directly from the mock's own fixed px
     values everywhere the mock specifies one, so it doesn't need a
     separate mobile-breakpoint override. */

  .pagination a,.pagination span{min-width:44px;height:44px}
  .share-btn,.socials a,.pw-socials a,.rail-nav button{width:44px;height:44px}
  /* The old .mobile-open dvh/overscroll rule lived here. Both concerns moved
     into .mnav itself when the drawer stopped being the restyled <ul>. */
}

/* -- 3. Safe-area insets: with viewport-fit=cover the content goes edge to
      edge, so fixed bottom UI must clear the home indicator and side rails
      must clear the notch in landscape. env() with no fallback is dropped
      by old engines, harmlessly reverting to the base padding above. -- */
.sticky-atc{
  /* max(), not add: do not stack theme padding on top of the safe area. */
  padding-top:.6rem;
  padding-bottom:max(.55rem, env(safe-area-inset-bottom));
  padding-left:calc(20px + env(safe-area-inset-left));
  padding-right:calc(20px + env(safe-area-inset-right));
}
.cookie-bar{padding-bottom:calc(1.1rem + env(safe-area-inset-bottom))}
.toast{bottom:calc(26px + env(safe-area-inset-bottom))}
/* .ccart-cta (rebuilt cart drawer's checkout bar) sets its own safe-area
   padding directly in its base rule instead of a separate override here. */
@media (max-width:680px){
  body.has-sticky{padding-bottom:max(64px, calc(52px + env(safe-area-inset-bottom)))}
  .wrap{
    padding-left:max(20px,env(safe-area-inset-left));
    padding-right:max(20px,env(safe-area-inset-right));
  }
}

/* -- 4. Touch polish: kill the grey iOS tap flash on our custom controls,
      keep horizontal rails from hijacking the browser's back-swipe, and
      contain overscroll on the scroll-locked panels. -- */
a,button,.btn,.icon-btn,.card,summary,label,.chip-f{-webkit-tap-highlight-color:transparent}
.stories,.rail,.ig-rail.is-static,.ugc-rail,.ccart-rec-rail,
.gal-thumbs,.qv-thumbs,.active-chips{overscroll-behavior-x:contain}
.search-panel,.qv-body{overscroll-behavior:contain}
/* .ccart-scroll (rebuilt cart drawer) sets overscroll-behavior:contain
   directly in its own base rule instead of joining this shared list. */

/* ===================================================================
   PHASE 2 — resolved audit issues #6–#9  (appended 2026-08-01)
   =================================================================== */

/* #6 — dense cart-drawer rail controls were below tap size. Grow the hit
   box (visual glyph stays small) so recommendations & saved-item remove
   are comfortable without crowding the tight rails. */
/* The old recs-rail/wishlist mobile tap-target bumps (.rec-add, .dw-x)
   lived here — both classes were removed along with the rest of the
   previous drawer. */

/* #7 — smallest phones: the header is at capacity once icons are 40–44px.
   Account already lives in the mobile menu ("Log in"), so drop the
   standalone header account icon under 380px to give the remaining
   targets breathing room and prevent any edge crowding at 320px. */
@media (max-width:380px){
  .nav-account{display:none}
  .nav-actions{gap:.3rem}
}

/* #8 — lookbook overlay was hover-only (dead on touch). Reveal it
   persistently where hover isn't available, matching .disc-cta's pattern. */
@media (hover:none){
  .look .ov{opacity:1;background:linear-gradient(to top,rgba(15,16,20,.6),rgba(15,16,20,.05))}
}

/* Collection controls & filter rows — comfortable tap sizes on mobile.
   .filter-toggle and the sort <select> were ~36px tall; filter option
   rows were tight to tap accurately. */
@media (max-width:680px){
  .filter-toggle{min-height:44px}
  .sortby{min-height:44px}
  .filters label{min-height:44px;padding:.25rem 0}
  .chip-f{min-height:36px;padding-top:.4rem;padding-bottom:.4rem}
  .chip-f a{min-width:32px;min-height:32px;padding:0;margin:0}
}

/* ===================================================================
   SHOP THE LOOK — shoppable image with hotspot dots
   =================================================================== */
.stl-shop-grid{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);gap:2rem;align-items:start}
.stl-stage{position:relative}
.stl-stage-img{border-radius:16px;overflow:hidden;background:var(--elev);box-shadow:var(--shadow-sm)}
.stl-stage-img img,.stl-stage-img svg{width:100%;height:100%;object-fit:cover;position:static;display:block}
/* hotspot dot */
.stl-dot{position:absolute;transform:translate(-50%,-50%);width:28px;height:28px;border-radius:50%;
  background:rgba(255,255,255,.92);border:2px solid #fff;box-shadow:0 2px 12px rgba(0,0,0,.4);
  cursor:pointer;z-index:3;padding:0;display:grid;place-items:center}
/* Fixed value, not var(--deep): this dot always sits inside a fixed
   near-white pin (rgba(255,255,255,.92)) over a photo, regardless of site
   theme. var(--deep) is a light beige in light mode -- barely distinguishable
   from the near-white pin around it, so the inactive hotspot marker all but
   disappeared on the very theme this site defaults to. */
.stl-dot::before{content:"";width:8px;height:8px;border-radius:50%;background:#4A4D53;transition:background .2s}
.stl-dot-ring{position:absolute;inset:-5px;border-radius:50%;border:2px solid rgba(255,255,255,.7);animation:stlPulse 2.4s ease-out infinite;pointer-events:none}
@keyframes stlPulse{0%{transform:scale(.65);opacity:.9}100%{transform:scale(1.7);opacity:0}}
.stl-dot.is-active{background:var(--bronze);border-color:#fff;transform:translate(-50%,-50%) scale(1.1)}
.stl-dot.is-active::before{background:#fff}
.stl-dot.is-active .stl-dot-ring{border-color:var(--bronze-soft)}
@media(prefers-reduced-motion:reduce){.stl-dot-ring{animation:none}}
/* hover tooltip (desktop) */
.stl-tip{position:absolute;bottom:calc(100% + 12px);left:50%;transform:translateX(-50%) translateY(6px);
  background:var(--card);border:1px solid var(--line-2);border-radius:12px;box-shadow:var(--shadow);
  padding:.5rem;display:flex;gap:.55rem;align-items:center;width:200px;opacity:0;visibility:hidden;
  transition:opacity .25s var(--ease),transform .25s var(--ease),visibility .25s;z-index:6;pointer-events:none}
.stl-tip::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:var(--card)}
.stl-dot:hover .stl-tip,.stl-dot.is-active .stl-tip{opacity:1;visibility:visible;transform:translateX(-50%) translateY(0)}
.stl-tip img{width:44px;height:44px;border-radius:8px;object-fit:cover;flex:none;position:static}
.stl-tip-b{min-width:0;text-align:left}
.stl-tip-t{font-size:.8rem;font-weight:600;color:var(--ivory);line-height:1.25;display:block}
.stl-tip-p{font-size:.84rem;font-weight:700;color:var(--bronze-ink);font-variant-numeric:tabular-nums}
/* product panel */
.stl-panel{position:relative}
.stl-prod{display:none;background:var(--card);border:1px solid var(--line-2);border-radius:16px;padding:1.2rem}
.stl-prod.is-active{display:block}
@media(prefers-reduced-motion:no-preference){.stl-prod.is-active{animation:stlFade .35s var(--ease)}}
@keyframes stlFade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.stl-prod-img{display:block;aspect-ratio:4/3;border-radius:12px;overflow:hidden;background:var(--elev);margin-bottom:1rem}
.stl-prod-img img,.stl-prod-img svg{width:100%;height:100%;object-fit:cover;position:static}
.stl-prod-info h3{font-size:1.15rem;line-height:1.3;margin-bottom:.4rem}
.stl-prod-info .jm-rate{margin-bottom:.6rem}
.stl-prod-price{display:flex;align-items:baseline;gap:.55rem;margin-bottom:1.1rem;flex-wrap:wrap}
.stl-prod-price b{font-family:var(--display);font-size:1.45rem;font-weight:700;color:var(--bronze-ink);font-variant-numeric:tabular-nums}
.stl-prod-price s{color:var(--muted);font-size:.9rem}
.stl-off{font-size:.72rem;font-weight:700;color:var(--good);background:rgba(var(--good-rgb),.14);border:1px solid rgba(var(--good-rgb),.32);padding:.2rem .55rem;border-radius:100px}
.stl-nav{display:flex;justify-content:center;gap:.5rem;margin-top:1.2rem}
.stl-pg{width:9px;height:9px;border-radius:50%;background:var(--line);border:none;cursor:pointer;transition:transform .2s var(--ease),background .2s;padding:0;position:relative}
/* The dot stays small visually, but the touch target meets the 24px minimum. */
.stl-pg::before{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:24px;height:24px;border-radius:50%}
.stl-pg.on{background:var(--bronze);transform:scale(1.25)}
@media(max-width:900px){
  .stl-shop-grid{grid-template-columns:minmax(0,1fr);gap:1.3rem}
  .stl-tip{display:none}
  .stl-prod-img{aspect-ratio:16/9;margin-bottom:.9rem}
  .stl-nav{margin-top:1rem}
}
@media(max-width:680px){
  .stl-dot{width:32px;height:32px}
  .stl-pg{width:11px;height:11px}
}

/* ===================================================================
   FLY TO CART — image clone flies into the cart icon (GPU-only)
   =================================================================== */
.fly-clone{position:fixed;left:0;top:0;z-index:120;border-radius:12px;object-fit:cover;
  pointer-events:none;will-change:transform,opacity;backface-visibility:hidden;
  box-shadow:0 14px 34px -10px rgba(0,0,0,.55)}
/* cart icon bounce when the flight lands */
.cart-bump{animation:cartBump .6s cubic-bezier(.34,1.56,.64,1)}
@keyframes cartBump{
  0%{transform:none}
  30%{transform:scale(1.26) rotate(-7deg)}
  55%{transform:scale(.93) rotate(4deg)}
  100%{transform:none}
}
@media(prefers-reduced-motion:reduce){
  .fly-clone{display:none}
  .cart-bump{animation:none}
}

/* ===================================================================
   The old "PREMIUM CART DRAWER" section lived here — rewards bar (.cart-
   rewards/.crn*), gift line (.ci-gift*), saved banner (.cart-saved),
   Estimated Total (.cart-total-toggle/.cart-summary*), cart offer
   (.cart-offer/.co-*), coupon (.cart-coupon/.cc-*), and the checkout
   button's internals (.cart-checkout/.cc-left/.cc-pay/.cart-assure).
   All removed with the rest of the previous drawer; the rebuilt
   equivalents (.ccart-rewards, .ccart-gift, .ccart-coupon,
   .ccart-checkout, etc.) live under "CART DRAWER — rebuilt from
   scratch" earlier in this file.
   =================================================================== */

/* ===================================================================
   DESKTOP HEADER — logo left, nav links to its right, actions far right.
   Overrides the centered layout on desktop only; mobile (≤680) is
   untouched, so the burger menu keeps all its items.
   =================================================================== */
@media (min-width:681px){
  .header .logo--center{position:static;transform:none;order:0}
  .header .nav-left{order:1;flex:0 0 auto}
  .header .nav-left .nav-links{margin-left:2.4rem}
  .header .nav-right{order:2;flex:1 1 auto;justify-content:flex-end}
}

/* ===================================================================
   MOBILE COLLECTION PAGE  (appended 2026-08-08)
   =================================================================== */

/* ---- Cookie consent: compact bottom sheet on phones ----
   The desktop bar is a centred row of copy + buttons. Below 560px that row
   wrapped into a 128px block pinned over the product grid. Two changes:
   the sheet itself gets tighter, and — more importantly — the page reserves
   its height below, so the last row of products can scroll clear of it
   instead of sitting permanently underneath. --cookie-h is published by
   CN.initCookie and collapses to 0 the moment consent is given. */
body{padding-bottom:var(--cookie-h,0px)}
body.has-sticky{padding-bottom:max(calc(64px + var(--cookie-h,0px)), calc(52px + env(safe-area-inset-bottom) + var(--cookie-h,0px)))}
@media (max-width:560px){
  /* Kept deliberately short: this sits over the tail of the hero on a 390px
     screen, so every row it costs is a row of product the visitor doesn't see
     on arrival. There is no scrim and no dimming — both choices are plain
     buttons of equal weight, which is the consent pattern we want. */
  .cookie-bar{flex-direction:column;align-items:stretch;gap:.5rem;
    padding:.6rem 14px calc(.6rem + env(safe-area-inset-bottom));
    border-radius:16px 16px 0 0;border-top:1px solid var(--line-2)}
  .cookie-bar p{font-size:.72rem;line-height:1.4;max-width:none}
  .cookie-actions{gap:.5rem}
  /* 42px tap target, but .btn's own padding was inflating this to 48 — pin the
     height and let padding sit inside it. */
  .cookie-actions .btn{flex:1;min-height:44px;height:44px;padding:0 .7rem;font-size:.78rem;
    line-height:1.2;display:inline-flex;align-items:center;text-align:center;justify-content:center}
}

/* ---- Collection toolbar: one row on phones ----
   Filters (102px) + count (66px) + the sort select (178px, sized by its
   longest option string) totalled ~378px against 335px of usable width, so
   flex-wrap dropped sort onto a second line and the bar cost 144px — more
   than the cookie banner it sat above. The facade below fixes the sort
   control's width so all three fit one row. */
@media (max-width:680px){
  .coll-bar{flex-wrap:nowrap;gap:.6rem;padding:.75rem 0;margin-bottom:1.1rem}
  .filter-toggle{padding:.55rem .9rem;font-size:.8rem;flex:none}
  .coll-count{font-size:.76rem;text-align:center;flex:1;min-width:0;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  .sort-wrap{position:relative;flex:none;display:inline-flex}
  .sort-facade{display:inline-flex;align-items:center;gap:.4rem;min-height:44px;
    padding:.55rem 2.1rem .55rem .95rem;border:1px solid var(--line);border-radius:100px;
    background:var(--elev);color:var(--ivory);font-size:.8rem;font-weight:500;white-space:nowrap;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235c534a' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat:no-repeat;background-position:right .85rem center;background-size:11px}
  /* The select keeps its full hit area and native picker; only its paint is
     hidden, so nothing about sorting behaviour changes. */
  .sort-wrap .sortby{position:absolute;inset:0;width:100%;height:100%;min-height:44px;
    opacity:0;padding:0;border-radius:100px}
  .sort-wrap:focus-within .sort-facade{border-color:var(--bronze);box-shadow:0 0 0 3px var(--bronze-tint)}

  /* Trim the page header — 154px of eyebrow + title + blurb before any product. */
  .coll-head{padding:1.5rem 0 1rem}
  .coll-head h1{margin:.45rem 0 .4rem}
  .coll-head p{font-size:.86rem;line-height:1.5}
}
html[data-theme="dark"] .sort-facade{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239b9184' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E")}
/* Desktop keeps the labelled select; the facade is phones-only. */
@media (min-width:681px){ .sort-facade{display:none} }

/* ---- Product card on phones: give the image back its share ----
   The image was 198px against 260px of meta on a 160px-wide card. Most of
   that meta was a stock/category row wrapping to two lines and a trust strip
   weighted like primary content. */
@media (max-width:680px){
  .prodgrid{gap:.7rem}
  .card .meta{padding:.7rem .75rem .8rem;gap:.22rem}
  /* The category label wrapped onto its own line, costing 44px for what is
     the least important thing on the card. Stock status stays. */
  .card .cat-lbl{display:none}
  .card .meta-top{min-height:0}
  .card .stock{font-size:.68rem}
  /* Three lines rather than two: at 160px wide, two lines cut most titles
     mid-word. min-height holds the row steady so short titles don't shorten
     the card and break price alignment across the grid. */
  .card h3,.card h4{-webkit-line-clamp:3;font-size:.88rem;line-height:1.3;min-height:3.9em}
  .card .price b{font-size:1.15rem}
  .card .price .was{font-size:.75rem}
  .card .price-save{font-size:.68rem}
  .card .foot{padding-top:.35rem}
  /* Secondary, per the hierarchy: readable but no longer competing with price. */
  .card .trust-strip{margin-top:.4rem;padding-top:.4rem;font-size:.65rem;color:var(--muted)}
  .card .trust-strip svg{width:12px;height:12px}
  /* right:52px keeps the badge row clear of the 44px wishlist button (which
     sits at right:6px); 48px overlapped it by 2px on a 163px card. Padding and
     letter-spacing are pared back so a discount + New pair still lands on one
     line in the 101px that leaves — stacked, the two of them covered a quarter
     of the product image. */
  .card .pills{top:8px;left:8px;right:52px;gap:.25rem}
  .card .pill{font-size:.6rem;padding:.26rem .38rem;letter-spacing:0}
}
@media (max-width:400px){
  .prodgrid{gap:.6rem}
  .card .meta{padding:.6rem .6rem .7rem}
  .card h3,.card h4{font-size:.84rem}
  .card .price b{font-size:1.05rem}
}
/* Below 360px the card is ~135px wide and two badges cannot share a line at
   any sane type size, so they stack and swallow a quarter of the image. Keep
   only the first — the Liquid emits them in priority order (discount, then
   New), so the strongest signal is the one that survives. */
@media (max-width:360px){
  .card .pills .pill ~ .pill{display:none}
}

/* ===================================================================
   HOMEPAGE ABOVE-THE-FOLD — mobile-first  (appended 2026-08-08)

   Measured first, on a 395x856 phone:
     announcement  87px (4 lines)   header 79px   category rail 167px
     = 333px, 39% of the viewport gone before the hero begins.
     hero h1 206px (4 lines @44.8px/1.15), CTA row 135px (buttons wrapped).

   Everything below is authored base-first for the phone, then enhanced at
   768/1024/1440 — the direction the brief requires. It is scoped to the
   header stack and hero only; the rest of the sheet is untouched.
   =================================================================== */

/* --nav-h replaces the 78px that was hardcoded in three places (.nav height,
   .mnav top, .mnav max-height), which is why the drawer had to be edited by
   hand whenever the bar changed. One value, one source. */
:root{--nav-h:60px}

/* ---- Announcement bar ----
   The message is ~80 uppercase characters at .14em tracking, which wrapped to
   four lines on a phone. Tracking is the expensive part, not the type size,
   so that is what gives way first — the copy stays fully readable. */
.announce{font-size:.68rem;letter-spacing:.02em;padding:.4rem 14px;line-height:1.35}

/* ---- Header ---- */
.nav{height:var(--nav-h)}

/* ---- Category rail ----
   Already a snap-scrolling rail, so this is proportion only: smaller rings,
   tighter labels, and a cap on the merchant's section padding. */
.section--stories{padding:min(var(--pad-t,10px),10px) 0 min(var(--pad-b,10px),10px)}
/* padding-top clears the hover lift. Setting overflow-x:auto forces the
   browser to compute overflow-y from `visible` to `auto`, so this rail clips
   vertically whether we asked it to or not — and `.story:hover .ring` lifts
   4px into 2px of headroom, slicing the top off every circle on hover. Reserve
   the lift in padding; overflow-y cannot be opted out of while x scrolls. */
.stories{gap:.8rem;padding:.55rem .1rem .3rem}
.story{flex:0 0 68px}
.story .ring{width:56px;height:56px;padding:2px}
.story .inner{border-width:2px}
/* Two lines is the honest floor here — "Wellness & Recovery" and "Home &
   Cleaning" cannot sit on one line at any readable size in a 68px column, and
   truncating them mid-word would be worse than the height it saves. */
.story p{margin:.3rem auto 0;max-width:72px;font-size:.68rem;line-height:1.15}

/* Keep the drawer pinned to whatever the bar currently is. */
@media (max-width:680px){
  .mnav{top:var(--nav-h);max-height:calc(100dvh - var(--nav-h) - var(--cookie-h,0px) - 12px)}
}

/* ---- Tablet ---- */
@media (min-width:768px){
  :root{--nav-h:64px}
  .announce{font-size:.74rem;letter-spacing:.08em;padding:.55rem 20px}
  /* The rail measures ~98px on its own; the merchant's 24/20 section padding
     is what pushed the band past the target, so cap it rather than shrink
     the rings any further. */
  .section--stories{padding:min(var(--pad-t,8px),8px) 0 min(var(--pad-b,8px),8px)}
  .story{flex:0 0 76px}
  .story .ring{width:60px;height:60px}
  .story p{max-width:80px;font-size:.72rem}
}

/* ---- Desktop: restore the two-column hero ---- */
@media (min-width:1024px){
  :root{--nav-h:68px}
  .announce{font-size:.78rem;letter-spacing:.12em;padding:.7rem 1rem}
  .section--stories{padding:min(var(--pad-t,6px),6px) 0 min(var(--pad-b,6px),6px)}
  .stories{gap:1.05rem}
  .story{flex:0 0 auto}
  .story .ring{width:60px;height:60px;padding:2.5px}
  .story .inner{border-width:2.5px}
  .story p{margin:.5rem auto 0;max-width:100px;font-size:.76rem;line-height:1.25}
}

/* ===================================================================
   MOBILE AUDIT FIXES  (appended 2026-08-08)
   =================================================================== */

/* CRITICAL — the cookie bar (z80, fixed bottom:0) sat directly on top of the
   sticky add-to-cart bar (z70, also bottom:0). They occupied the same strip,
   so on a phone a tap aimed at "Add to Bag" landed on the consent button
   instead: a first-time visitor could not add to cart from the sticky bar at
   all. Lift the ATC by the banner's measured height so both are reachable,
   and raise it above the banner so a partial overlap can never re-steal the
   tap. --cookie-h is published by CN.initCookie and collapses to 0 once
   consent is stored, dropping the bar back to the viewport floor. */
.sticky-atc{bottom:var(--cookie-h,0px);z-index:81}

/* Sticky ATC proportions on phones: the button's 32px side padding made it
   148px wide against 139px for the product it was selling, truncating the
   title after a few words. Trim the padding (height, and so the tap target,
   is unchanged) and tighten the row gap so the name and price get the space.
   The button keeps a floor width so "Add to Bag" never wraps. */
@media (max-width:680px){
  .sticky-atc{padding-left:16px;padding-right:16px;gap:.7rem}
  .sticky-atc .btn{padding-left:18px;padding-right:18px;font-size:.95rem;min-width:118px}
  .sticky-atc .si{gap:.6rem}
  .sticky-atc .si b{font-size:.82rem;line-height:1.25}
}
@media (max-width:360px){
  .sticky-atc{padding-left:12px;padding-right:12px}
  .sticky-atc .btn{padding-left:14px;padding-right:14px;min-width:104px;font-size:.9rem}
  .sticky-atc .si .th{width:40px;height:40px}
}

/* ===================================================================
   PRODUCT PAGE — above-the-fold on phones  (appended 2026-08-08)

   Measured on 395x855 before changing anything: Add to Cart sat at
   docTop 1080 — 1.26 viewports down. The buying decision was a full
   screen of scrolling away. Nothing here shrinks the page; it removes
   spacing that was not earning its height. Desktop already had title,
   rating, price, ATC and Buy Now above the fold at 1366x768 with a
   sticky .pdp-info, so all of this is scoped to phones.
   =================================================================== */

/* Short value proposition — sits between the rating and the price so the
   "what does it do for me" question is answered before the number. */
.pdp-vp{font-size:.95rem;line-height:1.5;color:var(--taupe);margin:0 0 .9rem;max-width:46ch}

@media (max-width:900px){
  /* 3rem of section padding + a 41px breadcrumb before the product even
     starts; the breadcrumb still reads fine at half the padding. */
  .pdp{padding:1.25rem 0 2.5rem}
  .breadcrumb{padding:.7rem 0}
  /* The stacked grid gap was 44.8px of dead space between the gallery and
     the buying panel. */
  .pdp-grid{gap:1.15rem}
  /* 8 thumbnails at 74px cost 74px of height for navigation the swipeable
     main image already provides. Compact, still comfortably tappable. */
  .gal-thumbs button{flex:0 0 54px}
  .gal-thumbs{gap:.45rem}

  .pdp-info .label{margin-bottom:.35rem}
  .pdp-info h1{margin-bottom:.4rem}
  .pdp-vp{font-size:.9rem;margin-bottom:.7rem}
  /* The price was 30px against a 27px title — the brief is explicit that
     price must not outrank the product name. */
  .pdp-price{margin-bottom:.4rem}
  .pdp-price b{font-size:1.5rem}
  .qty-row{margin-bottom:.7rem}
  .opt{margin-bottom:.8rem}
}

/* Desktop buying panel: adding the value proposition cost ~48px and pushed
   Buy Now below the fold at 1366x768, where it had been visible. Reclaim it
   from spacing inside the panel rather than dropping the copy — these gaps
   were the loosest part of the column. Phones already override all of this
   in the block above. */
@media (min-width:901px){
  .pdp{padding:1.6rem 0 4rem}
  .pdp-info .label{margin-bottom:.45rem}
  .pdp-info h1{margin-bottom:.45rem}
  .pdp-vp{margin-bottom:.75rem}
  .pdp-price{margin-bottom:.35rem}
  .qty-row{margin-bottom:.8rem}
  .pdp-buy{gap:.55rem}
  /* Two rows rather than three: status owns the first line, and the two
     supporting facts share the second. Stacking all three cost vertical space
     in a column that is already long, and laying all three out in one row
     (which is what this block used to do) gave them equal weight, which is the
     thing the hierarchy above is for. Wrap is kept as the safety valve — if a
     future delivery string is long enough to collide, it drops to its own line
     instead of overflowing the column. */
  .pfacts-list{flex-direction:row;flex-wrap:wrap;align-items:center;gap:.55rem 1.4rem}
  .pfacts-list .stock-line{flex:0 0 100%}
}

/* The PDP grid stacks at 1080px but the sticky bar only appeared at 680px, so
   every width from 681-1080 (tablets, small laptops) got the stacked layout
   with the buying panel pushed ~1.3 viewports down and no purchase action in
   view at all. Show the bar wherever the layout is stacked. */
@media (max-width:1080px){
  .sticky-atc{display:flex}
}

/* ===================================================================
   MOBILE TAP RESPONSIVENESS + DRAWER MOTION  (appended 2026-08-09)
   =================================================================== */

/* touch-action:manipulation removes the ~300ms iOS Safari holds on every tap
   while it waits to see whether a double-tap-to-zoom is coming. The sheet had
   no touch-action rule at all, which is why the burger felt laggy — the handler
   was firing fine, the browser just wasn't dispatching for a third of a second.
   `manipulation` keeps panning and pinch-zoom, and only drops double-tap-zoom. */
a,button,summary,label,[role="button"],input[type="submit"],
.burger,.icon-btn,.theme-switch,.story,.card,.mnav-group-btn,.mnav-pill{
  touch-action:manipulation;
}

@media (max-width:680px){
  /* The burger is the first thing a thumb reaches for — give it its own
     compositing layer so the first tap never waits on a paint. */
  .burger{will-change:transform}
  .burger span{transition:transform .28s cubic-bezier(.2,.9,.25,1),opacity .16s linear}

  /* Drawer motion: slide down from under the header rather than fading in
     place, on a gentle overshoot-free curve. transform+opacity only, so it
     stays on the compositor. visibility is stepped at the end of the close so
     the panel isn't focusable mid-fade. */
  .mnav{
    transform:translateY(-14px) scaleY(.985);transform-origin:top center;
    transition:opacity .26s cubic-bezier(.22,1,.36,1),
               transform .26s cubic-bezier(.22,1,.36,1),
               visibility 0s linear .26s;
  }
  .mnav.open{
    transform:none;
    transition:opacity .26s cubic-bezier(.22,1,.36,1),
               transform .26s cubic-bezier(.22,1,.36,1),
               visibility 0s linear 0s;
  }
  .mnav-scrim{transition:opacity .26s cubic-bezier(.22,1,.36,1),visibility 0s linear .26s}
  .mnav-scrim.open{transition:opacity .26s cubic-bezier(.22,1,.36,1),visibility 0s linear 0s}

  /* Staggered reveal for the drawer's own rows. Only runs on open, and only
     on the direct children, so expanding an accordion later doesn't re-animate
     the whole panel. */
  .mnav.open .mnav-label,
  .mnav.open .mnav-pills,
  .mnav.open .mnav-groups > li,
  .mnav.open .mnav-flat > li,
  .mnav.open .mnav-foot{
    opacity:0;animation:mnavRowIn .34s cubic-bezier(.22,1,.36,1) forwards;
  }
  .mnav.open .mnav-label{animation-delay:.04s}
  .mnav.open .mnav-pills{animation-delay:.07s}
  .mnav.open .mnav-groups > li:nth-child(1){animation-delay:.10s}
  .mnav.open .mnav-groups > li:nth-child(2){animation-delay:.13s}
  .mnav.open .mnav-groups > li:nth-child(3){animation-delay:.16s}
  .mnav.open .mnav-flat > li{animation-delay:.19s}
  .mnav.open .mnav-foot{animation-delay:.22s}
  @keyframes mnavRowIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
}

/* Motion is decoration here — the drawer must still open instantly for anyone
   who has asked the OS to reduce it. */
@media (prefers-reduced-motion:reduce){
  .mnav,.mnav.open,.mnav-scrim,.mnav-scrim.open{transition:none;transform:none}
  .mnav.open .mnav-label,.mnav.open .mnav-pills,.mnav.open .mnav-groups > li,
  .mnav.open .mnav-flat > li,.mnav.open .mnav-foot{animation:none;opacity:1}
}

/* ===================================================================
   SHOP THE LOOK — product rail + trust row  (appended 2026-08-09)

   Measured before changing anything, on a 390px phone: the stage showed
   1 of 3 products at a time, so two thirds of the look were reachable
   only by finding a 32px dot on a photo. The hotspots stay — they are
   good for exploring the image — but they are no longer the only route
   to the products.
   =================================================================== */

.stl-more{margin-top:1.6rem}
.stl-more-head{margin-bottom:.85rem}
.stl-more-head h3{font-family:var(--display);font-size:1.02rem;font-weight:600;color:var(--ivory);margin:0}
.stl-more-head p{margin:.2rem 0 0;font-size:.82rem;color:var(--muted)}

/* Rail is full-bleed via padding, not negative margins — the .ugc-rail bug
   earlier this session came from -20px margins escaping an unpadded parent. */
.stl-rail{list-style:none;display:flex;gap:.8rem;overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;
  padding:.2rem 20px .6rem;margin:0}
.stl-rail::-webkit-scrollbar{display:none}
/* 74% shows roughly one and a half cards, so the cut-off card is the cue that
   the rail scrolls — no arrows needed on touch. */
.stl-rail-item{flex:0 0 74%;scroll-snap-align:start;min-width:0}
.stl-rail-item .stl-item{height:100%}

.stl-trust{list-style:none;display:flex;gap:.5rem;overflow-x:auto;scrollbar-width:none;
  padding:.9rem 20px 0;margin:.9rem 0 0;border-top:1px solid var(--line-2)}
.stl-trust::-webkit-scrollbar{display:none}
.stl-trust li{flex:0 0 auto;display:flex;align-items:center;gap:.4rem;font-size:.76rem;
  color:var(--taupe);white-space:nowrap}
.stl-trust svg{width:14px;height:14px;flex:none;stroke:var(--bronze-soft);fill:none;stroke-width:1.7;position:static}

/* Hotspots measured 32-35px against a 44px target. Grow the hit area with
   padding and keep the visible dot the same size by drawing it on ::before,
   the same trick the product-card wishlist uses. */
.stl-dot{width:44px;height:44px;background:transparent;border:0;box-shadow:none}
.stl-dot::before{width:26px;height:26px;background:rgba(255,255,255,.92);
  border:2px solid rgba(0,0,0,.15);box-shadow:0 2px 10px rgba(0,0,0,.35)}
.stl-dot.is-active::before{background:var(--bronze);border-color:#fff}
.stl-dot-ring{inset:9px}
.stl-dot:focus-visible{outline:2px solid var(--bronze-soft);outline-offset:2px;border-radius:50%}

@media (min-width:681px){
  .stl-rail{padding-left:0;padding-right:0}
  .stl-rail-item{flex:0 0 44%}
  .stl-trust{padding-left:0;padding-right:0;gap:1.6rem}
  .stl-trust li{font-size:.8rem}
}
@media (min-width:1024px){
  .stl-more{margin-top:2.2rem}
  .stl-rail{overflow:visible;flex-wrap:wrap;gap:1.2rem}
  .stl-rail-item{flex:1 1 0;min-width:180px}
  .stl-more-head h3{font-size:1.15rem}
}

/* The base rule paints .stl-dot.is-active with a solid bronze fill. That was
   fine at 28px, but the dot is now a 44px touch target, so the fill rendered
   as a large disc covering the product beneath it. Keep the target invisible
   and move the colour onto the 26px ::before, which is the dot the eye reads. */
.stl-dot.is-active{background:transparent;border-color:transparent}
.stl-dot.is-active::before{background:var(--bronze);border-color:#fff;box-shadow:0 2px 12px rgba(0,0,0,.45)}

@media (max-width:680px){
  /* The side panel repeated, at full size, whichever product the rail already
     lists — roughly a viewport of duplicate card. On a phone the tooltip is
     the contextual preview (image, title, price, shown on tap) and the rail is
     the product list, which is the split the brief asks for. The panel returns
     at 681px where there is a column to put it in. */
  .stl-panel{display:none}
  .stl-more{margin-top:1.1rem}
}

/* =====================================================================
   FLOATING COUPON BADGE  (snippets/coupon-badge.liquid)

   Three states share one fixed anchor: the loud PROMO card, the dark
   PANEL that holds the code, and the quiet MINI pill. Only one is in the
   DOM flow at a time, so the anchor never jumps between them.

   The offset is arithmetic rather than a guessed constant:

     bottom = 16px + safe-area + --cookie-h + --cb-atc

   --cookie-h is the consent bar's live height (published by CN.initCookie,
   0 once dismissed); --cb-atc is the product page's sticky Add to Cart
   (published by the badge's own script, 0 whenever that bar is hidden).
   Both collapse to 0 through the var() fallback, so on a page with neither
   the badge simply sits at 16px.

   z-index 79 is deliberate: below the cookie bar (80), the sticky ATC (81),
   the search overlay (90), scrims (95), the cart drawer (96), quick view
   (97) and the toast (99). It is the lowest fixed thing on the page.
   ===================================================================== */
.cbadge{
  --cb-accent:var(--bronze);
  --cb-accent-tint:var(--bronze-tint);
  --cb-bg:var(--card);
  --cb-text:var(--ivory);
  --cb-btn:var(--bronze);
  --cb-g1:#D93A22;
  --cb-g2:#F0862F;
  --cb-ok:#1FA463;
  --cb-radius:18px;
  --cb-shadow:0 18px 44px -18px rgba(0,0,0,.45);
  --cb-w-m:268px;
  --cb-w-d:320px;
  position:fixed;z-index:79;
  right:16px;
  bottom:calc(16px + env(safe-area-inset-bottom) + var(--cookie-h,0px) + var(--cb-atc,0px));
  width:max-content;max-width:calc(100% - 32px);
  opacity:0;transform:translateY(10px);
  transition:bottom .3s var(--ease),opacity .25s ease,transform .25s ease}
.cbadge[hidden]{display:none}
.cbadge.is-in{opacity:1;transform:none}
.cbadge--anim-none{transition:none}

/* Out of the way while a drawer, modal or overlay owns the screen. Hidden
   rather than dimmed: it can then never intercept a tap meant for the cart. */
.cbadge.is-hidden{opacity:0;transform:translateY(10px) scale(.96);pointer-events:none}

/* ---- shared close button ---- */
.cb-x{width:30px;height:30px;flex:none;display:grid;place-items:center;
  border-radius:50%;border:0;background:transparent;color:var(--muted);
  cursor:pointer;transition:color .2s,background .2s}
.cb-x:hover{color:var(--ivory);background:var(--elev)}
.cb-x svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2.4;position:static}
/* On the gradient card the close sits half-off the corner, as a solid dark
   disc — on a saturated background a ghost button is close to invisible. */
.cb-x--float{position:absolute;top:-11px;right:-11px;width:30px;height:30px;
  background:var(--deep);color:var(--ivory);border:1px solid rgba(255,255,255,.22);
  box-shadow:0 4px 12px rgba(0,0,0,.45);z-index:2}
.cb-x--float:hover{background:#000;color:#fff}
/* Only the gradient card carries the floating close; the panel and the pill
   have their own, so it is hidden in those states rather than left orphaned
   over a card that is no longer there. */
.cbadge:not(.is-promo) .cb-x--float{display:none}

/* =========== 1. PROMO =========== */
.cb-promo{position:relative;width:var(--cb-w-m);max-width:100%;
  padding:1.15rem 1.05rem 1.05rem;border-radius:var(--cb-radius);
  background:linear-gradient(148deg,var(--cb-g1) 0%,var(--cb-g2) 100%);
  box-shadow:var(--cb-shadow),0 0 0 1px rgba(255,255,255,.09) inset;
  text-align:center;isolation:isolate}
.cb-promo[hidden]{display:none}

/* Sparkle field, drawn as four static radial dots rather than as particles.
   It reads as festive at a glance and costs one extra paint layer — no
   animation loop, no image, nothing to keep the compositor awake. */
.cbadge--sparkle .cb-promo::before{content:"";position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(circle at 12% 18%, rgba(255,255,255,.55) 0 2px, transparent 2px),
    radial-gradient(circle at 88% 26%, rgba(255,255,255,.4) 0 2.5px, transparent 2.5px),
    radial-gradient(circle at 20% 84%, rgba(255,255,255,.35) 0 2px, transparent 2px),
    radial-gradient(circle at 78% 90%, rgba(255,255,255,.3) 0 1.5px, transparent 1.5px),
    radial-gradient(circle at 62% 8%, rgba(255,255,255,.28) 0 1.5px, transparent 1.5px);
  border-radius:inherit;pointer-events:none}
/* A soft warm bloom keeps the flat gradient from looking like a plain block. */
.cb-promo::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(70% 50% at 50% 0%, rgba(255,214,120,.34), transparent 70%)}

.cb-promo-img{display:block;margin:0 auto .5rem;width:var(--cb-img,52px);height:var(--cb-img,52px);
  object-fit:contain;position:static}

.cb-promo-head{display:block;font-family:var(--display);font-weight:700;
  font-size:1.6rem;line-height:1.02;letter-spacing:-.02em;color:#fff;
  text-shadow:0 2px 10px rgba(120,20,0,.4);
  transform:rotate(-2deg);margin-bottom:.7rem}

/* The white ribbon is the number people actually read, so it gets the
   highest contrast pairing on the card and a slight counter-rotation so it
   sits against the headline rather than parallel to it. */
.cb-promo-ribbon{display:block;margin:0 -.15rem;padding:.5rem .6rem;
  background:#fff;color:var(--cb-g1);border-radius:9px;
  font-family:var(--display);font-weight:700;font-size:1.18rem;letter-spacing:-.01em;
  box-shadow:0 6px 16px rgba(90,15,0,.3);transform:rotate(.6deg)}
.cb-promo-sub{display:block;margin-top:.55rem;font-family:var(--display);
  font-weight:600;font-size:.92rem;letter-spacing:.12em;text-transform:uppercase;
  color:#FFD84D}

/* Fixed #22252B, not var(--deep): this button always sits on the fixed
   red/orange .cb-promo gradient (var(--cb-g1)/var(--cb-g2), themeless by
   design), same as every other .cb-promo-* rule here. var(--deep) is dark
   only in dark mode -- in light mode (this site's default) it's a light
   beige, so the white button label measured 1.33:1, effectively invisible.
   #22252B is dark mode's own --deep value, used here as a fixed literal since
   this component was never meant to flip in the first place. */
.cb-promo-cta{display:flex;align-items:center;justify-content:center;gap:.45rem;
  width:100%;min-height:46px;margin-top:.9rem;padding:0 1rem;
  background:#22252B;color:#fff;border:0;border-radius:11px;cursor:pointer;
  font-family:var(--body);font-size:.88rem;font-weight:600;
  transition:transform .2s var(--ease),background .2s}
.cb-promo-cta:hover{background:#000;transform:translateY(-1px)}
.cb-promo-cta svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;position:static}

/* =========== 2. PANEL =========== */
.cb-panel{position:relative;width:var(--cb-w-m);max-width:100%;
  background:var(--cb-bg);color:var(--cb-text);text-align:center;
  border:1px solid var(--line-2);border-radius:var(--cb-radius);
  box-shadow:var(--cb-shadow);padding:.6rem .95rem 1.05rem}
.cb-panel[hidden]{display:none}
.cb-panel-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  margin:0 -.35rem .7rem 0;padding-bottom:.55rem;border-bottom:1px solid var(--line-2)}
.cb-panel-title{display:flex;align-items:center;gap:.4rem;min-width:0;
  font-size:.78rem;font-weight:600;color:var(--taupe);text-align:left}
.cb-panel-title svg{width:14px;height:14px;flex:none;stroke:var(--cb-accent);fill:none;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;position:static}

.cb-panel-off{display:block;font-family:var(--display);font-weight:700;
  font-size:1.5rem;line-height:1.1;letter-spacing:-.02em;color:var(--cb-text)}
.cb-panel-desc{display:block;margin-top:.15rem;font-size:.78rem;color:var(--muted)}

/* Dashed box because that is the universal shorthand for "tear here, this is
   the coupon". user-select:all so the code survives a denied clipboard. */
.cb-code{display:flex;align-items:center;justify-content:center;gap:.5rem;
  margin-top:.85rem;padding:.6rem .8rem;border-radius:11px;
  background:var(--elev);border:1px dashed var(--line);
  transition:border-color .25s,background .25s}
.cb-code-val{font-family:var(--mono);font-size:1.05rem;font-weight:500;letter-spacing:.08em;
  color:var(--cb-text);user-select:all;overflow:hidden;text-overflow:ellipsis}
.cb-code-ok{display:none;place-items:center;width:17px;height:17px;flex:none;
  border-radius:50%;background:var(--cb-ok)}
.cb-code-ok svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:3;position:static}
.cbadge.is-copied .cb-code{border-color:var(--cb-ok);border-style:solid;background:rgba(31,164,99,.12)}
.cbadge.is-copied .cb-code-ok{display:grid}

.cb-copy{display:flex;align-items:center;justify-content:center;
  width:100%;min-height:46px;margin-top:.7rem;padding:0 1rem;
  background:var(--cb-btn);color:var(--on-accent);border:0;border-radius:11px;cursor:pointer;
  font-family:var(--body);font-size:.88rem;font-weight:600;
  transition:background .25s,filter .2s,transform .2s var(--ease)}
.cb-copy:hover{filter:brightness(1.07);transform:translateY(-1px)}
.cbadge.is-copied .cb-copy{background:var(--cb-ok);color:#fff;filter:none}

.cb-fine{margin:.6rem 0 0;font-size:.71rem;line-height:1.45;color:var(--muted)}
.cb-fine span{opacity:.5;margin:0 .1rem}
.cb-live{margin:.4rem 0 0;font-size:.72rem;line-height:1.4;color:var(--cb-ok)}
.cb-live:empty{display:none}

/* =========== 3. MINI =========== */
.cb-mini-wrap{display:flex;align-items:center;gap:.25rem}
.cb-mini-wrap[hidden]{display:none}
.cb-mini{display:inline-flex;align-items:center;gap:.6rem;
  min-height:48px;padding:.45rem .8rem .45rem .55rem;
  background:var(--cb-bg);color:var(--cb-text);text-align:left;
  border:1px solid var(--line-2);border-radius:100px;box-shadow:var(--cb-shadow);
  cursor:pointer;transition:transform .2s var(--ease),border-color .2s}
.cb-mini:hover{transform:translateY(-2px);border-color:var(--cb-accent)}
.cb-mini-ic{width:32px;height:32px;flex:none;border-radius:50%;
  background:var(--cb-accent-tint);display:grid;place-items:center}
.cb-mini-ic svg{width:15px;height:15px;stroke:var(--cb-accent);fill:none;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;position:static}
.cb-mini-txt{display:flex;flex-direction:column;line-height:1.2;min-width:0}
.cb-mini-txt b{font-family:var(--display);font-size:.86rem;font-weight:600;letter-spacing:-.01em}
.cb-mini-txt small{font-size:.7rem;color:var(--muted);white-space:nowrap}
.cb-mini-go svg{width:15px;height:15px;stroke:var(--muted);fill:none;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;position:static}
.cb-x--mini{width:26px;height:26px;align-self:flex-start;margin-top:2px}
.cb-x--mini svg{width:11px;height:11px}

/* Focus has to clear the card's own edge, hence the offset. */
.cb-promo-cta:focus-visible,.cb-copy:focus-visible,.cb-mini:focus-visible,.cb-x:focus-visible{
  outline:2px solid var(--cb-accent);outline-offset:3px}
.cb-x--float:focus-visible{outline-color:#fff}

/* ---- style variants ---- */
/* Compact: same states, less shouting — flat accent instead of the gradient,
   for merchants who want the mechanic without the festival. */
.cbadge--compact .cb-promo{background:var(--cb-accent);padding:1rem}
.cbadge--compact .cb-promo-head{font-size:1.3rem;transform:none}
.cbadge--compact .cb-promo-ribbon{transform:none}
.cbadge--compact .cb-promo::after{display:none}

/* Ticket: notches punched into both edges with radial gradients — no extra
   elements and no image. */
.cbadge--ticket .cb-promo{
  -webkit-mask:radial-gradient(circle at left 50%, transparent 9px, #000 9.5px) left/51% 100% no-repeat,
       radial-gradient(circle at right 50%, transparent 9px, #000 9.5px) right/51% 100% no-repeat;
  mask:radial-gradient(circle at left 50%, transparent 9px, #000 9.5px) left/51% 100% no-repeat,
       radial-gradient(circle at right 50%, transparent 9px, #000 9.5px) right/51% 100% no-repeat}
.cbadge--ticket .cb-panel{border-style:dashed}

/* ---- device targeting ----
   681px is the theme's existing mobile/desktop line (the mobile nav swaps
   there), so the badge agrees with the rest of the site about what "mobile"
   means rather than introducing a second definition. */
@media (max-width:680px){ .cbadge--dev-desktop{display:none} }
@media (min-width:681px){ .cbadge--dev-mobile{display:none} }

/* ---- phones ----
   The card is an overlay on a 390px screen, not a page element: at the base
   sizing it stood 213px tall, a quarter of the viewport, and sat over two
   product cards. Trimming the type and the padding takes it to roughly 165px
   without changing a single colour, radius or shadow — the proportions get
   tighter, the design does not change. Desktop keeps the larger sizing, where
   there is room for it. */
@media (max-width:680px){
  .cb-promo{padding:.85rem .8rem .8rem}
  .cb-promo-head{font-size:1.3rem;margin-bottom:.5rem}
  .cb-promo-ribbon{font-size:1rem;padding:.38rem .5rem;border-radius:8px}
  .cb-promo-sub{margin-top:.4rem;font-size:.76rem;letter-spacing:.1em}
  .cb-promo-cta{min-height:42px;margin-top:.65rem;font-size:.83rem;border-radius:10px}
  .cb-promo-img{margin-bottom:.4rem}
  /* Panel and pill follow, so the three states stay a family. */
  .cb-panel{padding:.5rem .8rem .85rem}
  .cb-panel-off{font-size:1.32rem}
  .cb-code{margin-top:.65rem;padding:.5rem .7rem}
  .cb-copy{min-height:42px;margin-top:.6rem;font-size:.83rem;border-radius:10px}
}

/* ---- desktop ---- */
@media (min-width:681px){
  .cbadge{right:24px;bottom:calc(24px + var(--cookie-h,0px) + var(--cb-atc,0px))}
  .cb-promo,.cb-panel{width:var(--cb-w-d)}
  .cb-promo-head{font-size:1.85rem}
  .cb-promo-ribbon{font-size:1.32rem}
  .cb-panel-off{font-size:1.62rem}
}

/* ---- small phones ----
   At 320px a 268px card plus 16px gutters leaves 20px, so the card takes the
   full column instead and the type steps down one notch. */
@media (max-width:360px){
  .cbadge{right:12px;left:12px;max-width:none;
    bottom:calc(12px + env(safe-area-inset-bottom) + var(--cookie-h,0px) + var(--cb-atc,0px))}
  .cb-promo,.cb-panel{width:100%;max-width:none}
  .cb-promo{padding:.8rem .7rem .75rem}
  .cb-promo-head{font-size:1.2rem}
  .cb-promo-ribbon{font-size:.94rem}
  .cb-panel-off{font-size:1.22rem}
  .cb-mini-txt small{font-size:.66rem}
}

/* One soft pulse on arrival, then never again — an attention cue, not a loop. */
.cbadge--anim-pulse.is-in .cb-promo{animation:cbPulse 2.4s var(--ease) .6s 2}
@keyframes cbPulse{
  0%,100%{box-shadow:var(--cb-shadow),0 0 0 1px rgba(255,255,255,.09) inset}
  50%{box-shadow:var(--cb-shadow),0 0 0 1px rgba(255,255,255,.09) inset,0 0 0 8px rgba(240,134,47,.22)}
}

@media (prefers-reduced-motion:reduce){
  .cbadge,.cb-promo-cta,.cb-copy,.cb-mini{transition:opacity .2s ease}
  .cbadge.is-in{transform:none}
  .cb-promo-cta:hover,.cb-copy:hover,.cb-mini:hover{transform:none}
  .cbadge--anim-pulse.is-in .cb-promo{animation:none}
  .cb-promo-head,.cb-promo-ribbon{transform:none}
}

/* =====================================================================
   CULTURE NEST REVIEWS  (sections/product-reviews-cn.liquid)

   Only the NEW parts live here. The summary, histogram and review card
   reuse the existing .pr-* rules from the Judge.me section above, which is
   what makes the swap invisible: same card, same spacing, same width.

   Mobile first — every rule here is the phone layout, and the two
   min-width blocks at the end add what the extra room allows.
   ===================================================================== */
.cnr{--cnr-accent:var(--bronze);--cnr-radius:14px}
/* The .pr-* card rules this section reuses are compiled from the OLD Judge.me
   section stylesheet, which disappears the day that file is deleted. The two
   that actually carry layout are restated here so the section survives that
   removal. Two-class selectors also beat .wrap, which was overriding the
   900px column and letting reviews run the full 1265px page width. */
/* Review-card styles, recovered from the deleted product-reviews.liquid section
   stylesheet. That file carried every .pr-* rule this section reuses; deleting it
   with Judge.me took the styling with it and left the summary as a bare bullet
   list. Scoped under .cnr so they apply only to the review section. */
.cnr .pr-wrap{max-width:900px}
.cnr .pr-head{margin:0 0 1.6rem}
.cnr .pr-head .label{display:block;margin-bottom:.7rem}
.cnr .pr-head h2{font-family:var(--display);font-weight:600;color:var(--ivory);font-size:clamp(1.5rem,4.4vw,2.1rem);letter-spacing:-.02em;line-height:1.15;margin:0}
.cnr .pr-summary{display:grid;grid-template-columns:auto minmax(0,1fr);gap:1.6rem 2.4rem;align-items:center;
  background:var(--card);border:1px solid var(--line);border-radius:18px;padding:1.6rem clamp(1.2rem,3vw,2rem);margin-bottom:1.6rem}
/* The section ships this block with `hidden` when a product has no approved
   reviews. `.cnr .pr-summary` outweighs the browser's `[hidden]{display:none}`,
   so without this guard a zero-review product renders a "0" average, an empty
   star row and a 0-count histogram right above "No reviews yet" — a rating we
   do not have. Every sibling (.cnr-empty, .cnr-controls, .cnr-status, …) already
   carries the same guard; this one was lost when the .pr-* rules were recovered
   from git and re-scoped under .cnr. */
.cnr .pr-summary[hidden]{display:none}
.cnr .pr-score{text-align:center}
.cnr .pr-avg{display:block;font-family:var(--display);font-weight:600;color:var(--ivory);font-size:3rem;line-height:1;letter-spacing:-.02em}
.cnr .pr-stars{font-size:20px;margin:.4rem 0 .3rem}
.cnr .pr-count{display:block;color:var(--muted);font-size:.82rem}
.cnr .pr-hist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.4rem;min-width:0}
.cnr .pr-hist-row{display:grid;grid-template-columns:34px minmax(0,1fr) 28px;align-items:center;gap:.6rem}
.cnr .pr-hist-label{font-size:.8rem;color:var(--taupe);display:inline-flex;align-items:center;gap:1px;justify-content:flex-end}
.cnr .pr-hist-star{color:var(--bronze-ink)}
.cnr .pr-hist-track{height:8px;background:var(--elev);border-radius:6px;overflow:hidden}
.cnr .pr-hist-fill{display:block;height:100%;background:var(--bronze);border-radius:6px}
.cnr .pr-hist-freq{font-size:.78rem;color:var(--muted);text-align:right;font-variant-numeric:tabular-nums}
.cnr .pr-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1.1rem}
.cnr .pr-item{display:flex;gap:1rem;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:1.2rem}
.cnr .pr-ava{flex:none;width:40px;height:40px;border-radius:50%;background:var(--bronze-tint);color:var(--bronze-ink);
  display:grid;place-items:center;font-weight:700;font-size:1rem}
.cnr .pr-item-body{min-width:0}
.cnr .pr-item-top{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem .7rem;margin-bottom:.3rem}
.cnr .pr-item-stars{font-size:15px}
.cnr .pr-name{color:var(--ivory);font-size:.9rem;font-weight:600}
.cnr .pr-verified{display:inline-flex;align-items:center;gap:.2rem;font-size:.7rem;font-weight:600;color:var(--bronze-ink);background:var(--bronze-tint);border-radius:100px;padding:.15rem .5rem .15rem .35rem;white-space:nowrap}
.cnr .pr-verified svg{width:12px;height:12px;stroke:currentColor;fill:none;stroke-width:2.4;position:static}
.cnr .pr-date{color:var(--muted);font-size:.78rem;margin-left:auto}
.cnr .pr-title{display:block;color:var(--ivory);font-size:.98rem;margin:.15rem 0 .3rem}
.cnr .pr-text{color:var(--taupe);line-height:1.65;font-size:.92rem}
.cnr .pr-text :first-child{margin-top:0}
.cnr .pr-text :last-child{margin-bottom:0}
.cnr .pr-media{list-style:none;display:flex;flex-wrap:wrap;gap:.5rem;margin:.7rem 0 0;padding:0}
.cnr .pr-media img{width:70px;height:70px;object-fit:cover;border-radius:8px;border:1px solid var(--line);display:block;position:static}
.cnr .pr-foot{margin:1.2rem 0 0;color:var(--muted);font-size:.85rem;text-align:center}
.cnr .pr-foot-hint{display:block;margin-top:.3rem;color:var(--bronze-ink)}
.cnr /* Write-a-review + native-widget controls */
.pr-actions{display:flex;justify-content:center;margin:0 0 1.6rem}
.cnr .pr-write{display:inline-flex;align-items:center;gap:.45rem;min-width:220px;justify-content:center}
.cnr .pr-write svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;position:static}
/* Review theming lives in assets/theme.css (prefixed .cnr) so it also reaches
   products on the default template, where the widget renders outside this
   section. The dangling ".cnr" that used to sit before this comment merged
   into the @media rule below as one invalid selector, silently dropping the
   whole block — .pr-summary never actually stacked on phones. */

@media(max-width:560px){
  /* .cnr-prefixed to outweigh the base .cnr .pr-summary/.cnr .pr-date rules —
     a bare .pr-summary here is one class lighter than the two-class base
     rule and loses on specificity regardless of source order or media
     query match, which was the second half of why this never applied. */
  .cnr .pr-summary{grid-template-columns:minmax(0,1fr);text-align:center}
  .cnr .pr-date{margin-left:0}
}
.cnr-desc{margin:.6rem 0 0;color:var(--taupe);font-size:.92rem;line-height:1.6;max-width:46rem}

/* Empty state — a product with no reviews still has to invite the first one. */
.cnr-empty{text-align:center;padding:1.6rem 1rem;margin-bottom:1.2rem;
  background:var(--card);border:1px dashed var(--line);border-radius:var(--cnr-radius)}
.cnr-empty[hidden]{display:none}
.cnr-empty-t{margin:0;color:var(--ivory);font-family:var(--display);font-size:1.05rem}
.cnr-empty-b{margin:.3rem 0 0;color:var(--muted);font-size:.88rem}

/* ---- controls ---- */
.cnr-controls{display:flex;flex-direction:column;gap:.7rem;margin:0 0 1.2rem}
.cnr-controls[hidden]{display:none}
/* The chip row scrolls rather than wrapping to three lines on a phone; the
   negative margin lets it bleed to the screen edge so the last chip is clearly
   cut rather than looking like the end of the list. */
.cnr-chips{display:flex;gap:.4rem;overflow-x:auto;scrollbar-width:none;
  margin:0 -20px;padding:0 20px 2px;-webkit-overflow-scrolling:touch}
.cnr-chips::-webkit-scrollbar{display:none}
.cnr-chip{flex:none;min-height:44px;padding:0 .85rem;border-radius:100px;cursor:pointer;
  background:var(--card);border:1px solid var(--line-2);color:var(--taupe);
  font-family:var(--body);font-size:.82rem;font-weight:500;white-space:nowrap;
  transition:border-color .2s,color .2s,background .2s}
.cnr-chip:hover{border-color:var(--cnr-accent);color:var(--ivory)}
.cnr-chip.is-on{background:var(--bronze-tint);border-color:var(--cnr-accent);color:var(--ivory)}

.cnr-tools{display:flex;gap:.5rem;align-items:center}
.cnr-search{position:relative;flex:1;min-width:0;display:flex;align-items:center}
.cnr-search svg{position:absolute;left:.7rem;width:15px;height:15px;stroke:var(--muted);
  fill:none;stroke-width:2;pointer-events:none}
.cnr-search input{width:100%;min-height:44px;padding:0 .8rem 0 2.1rem;border-radius:10px;
  background:var(--elev);border:1px solid var(--line-2);color:var(--ivory);
  font-family:var(--body);font-size:.86rem}
.cnr-search input::placeholder{color:var(--muted)}
.cnr-sort select{min-height:44px;padding:0 .7rem;border-radius:10px;cursor:pointer;
  background:var(--elev);border:1px solid var(--line-2);color:var(--ivory);
  font-family:var(--body);font-size:.86rem}

.cnr-status{color:var(--muted);font-size:.86rem;padding:.4rem 0;text-align:center}
.cnr-status[hidden]{display:none}
.cnr-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1rem}
.cnr-item{border-radius:var(--cnr-radius)}
.cnr-text{white-space:pre-line}          /* keep the customer's paragraphs */
.cnr-more-wrap{display:flex;justify-content:center;margin-top:1.2rem}
.cnr-more[hidden]{display:none}

/* Shop reply */
.cnr-reply{margin-top:.8rem;padding:.7rem .85rem;border-radius:10px;
  background:var(--elev);border-left:2px solid var(--cnr-accent)}
.cnr-reply b{display:block;color:var(--cnr-accent);font-size:.78rem;margin-bottom:.2rem}
.cnr-reply p{margin:0;color:var(--taupe);font-size:.86rem;line-height:1.55}

/* Media thumbnails */
.cnr-media{gap:.45rem}
.cnr-thumb{position:relative;list-style:none}
.cnr-thumb-btn{display:block;padding:0;border:1px solid var(--line);border-radius:9px;
  overflow:hidden;background:var(--elev);cursor:pointer;line-height:0;position:relative}
.cnr-thumb-btn img{width:66px;height:66px;object-fit:cover;display:block;position:static}
.cnr-play{position:absolute;inset:0;display:grid;place-items:center;background:rgba(0,0,0,.35)}
.cnr-play::before{content:"";border-style:solid;border-width:7px 0 7px 12px;
  border-color:transparent transparent transparent #fff;margin-left:2px}

/* Helpful votes */
.cnr-vote{display:flex;align-items:center;flex-wrap:wrap;gap:.4rem;margin-top:.85rem;
  padding-top:.7rem;border-top:1px solid var(--line-2)}
.cnr-vote-q{color:var(--muted);font-size:.8rem;margin-right:.2rem}
.cnr-vote-btn{min-height:44px;padding:0 .75rem;border-radius:100px;cursor:pointer;
  background:transparent;border:1px solid var(--line-2);color:var(--taupe);
  font-family:var(--body);font-size:.8rem;font-weight:500}
.cnr-vote-btn:hover:not(:disabled){border-color:var(--cnr-accent);color:var(--ivory)}
.cnr-vote-btn:disabled{opacity:.55;cursor:default}
.cnr-vote-msg{color:var(--muted);font-size:.76rem;flex-basis:100%}

/* ---- write-a-review modal ----
   z-index sits just under the cart drawer (96) so a cart opened over it still
   wins, and above the page overlay (90). */
.cnr-scrim{position:fixed;inset:0;z-index:94;background:rgba(12,13,16,.66);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.cnr-scrim[hidden],.cnr-modal[hidden],.cnr-lb[hidden]{display:none}
.cnr-modal{position:fixed;z-index:95;left:0;right:0;bottom:0;top:auto;
  max-height:92vh;overflow-y:auto;overscroll-behavior:contain;
  background:var(--base);border-top:1px solid var(--line);
  border-radius:20px 20px 0 0;box-shadow:var(--shadow);
  padding-bottom:env(safe-area-inset-bottom)}
.cnr-modal-in{position:relative;padding:1.4rem 1.1rem 1.6rem}
.cnr-modal h3{font-family:var(--display);font-weight:600;color:var(--ivory);
  font-size:1.25rem;margin:0;letter-spacing:-.02em;padding-right:2.2rem}
.cnr-form-sub{margin:.2rem 0 1.1rem;color:var(--muted);font-size:.84rem}
.cnr-x{position:absolute;top:0;right:0;width:40px;height:40px;display:grid;place-items:center;
  border:0;border-radius:50%;background:var(--elev);color:var(--taupe);cursor:pointer}
.cnr-x:hover{color:var(--ivory)}
.cnr-x svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2;position:static}

.cnr-form{display:flex;flex-direction:column;gap:.9rem}
.cnr-rate{border:0;padding:0;margin:0}
.cnr-rate legend{color:var(--ivory);font-size:.88rem;font-weight:600;margin-bottom:.35rem;padding:0}
/* Radios in DOM order 5→1 and laid out row-reverse, so the CSS sibling
   selector can light up the hovered star and every one before it — the
   standard trick, and it keeps real radio semantics for the keyboard. */
.cnr-stars-input{display:inline-flex;flex-direction:row-reverse;justify-content:flex-end;gap:.15rem}
.cnr-stars-input input{position:absolute;opacity:0;width:1px;height:1px}
.cnr-stars-input label{font-size:2rem;line-height:1;color:var(--line);cursor:pointer;
  padding:.1rem .05rem;transition:color .15s}
.cnr-stars-input label:hover,
.cnr-stars-input label:hover ~ label,
.cnr-stars-input input:checked ~ label{color:var(--cnr-accent)}
.cnr-stars-input input:focus-visible + label{outline:2px solid var(--cnr-accent);outline-offset:2px;border-radius:4px}

.cnr-field{display:flex;flex-direction:column;gap:.3rem}
.cnr-field > span{color:var(--ivory);font-size:.86rem;font-weight:600}
.cnr-field > span small{color:var(--muted);font-weight:400}
.cnr-field em{color:var(--cnr-accent);font-style:normal}
.cnr-field input[type=text],.cnr-field input[type=email],.cnr-field textarea{
  width:100%;min-height:46px;padding:.7rem .8rem;border-radius:10px;
  background:var(--elev);border:1px solid var(--line-2);color:var(--ivory);
  font-family:var(--body);font-size:.92rem;line-height:1.5}
.cnr-field textarea{resize:vertical;min-height:120px}
.cnr-field input:focus,.cnr-field textarea:focus{outline:none;border-color:var(--cnr-accent)}
.cnr-counter{color:var(--muted);font-size:.72rem;align-self:flex-end;font-variant-numeric:tabular-nums}
.cnr-row{display:flex;flex-direction:column;gap:.9rem}
.cnr-note{margin:0;color:var(--muted);font-size:.75rem;line-height:1.5}

.cnr-drop{position:relative;border:1px dashed var(--line);border-radius:10px;
  padding:.85rem;background:var(--elev);text-align:center}
.cnr-drop input[type=file]{width:100%;color:var(--taupe);font-size:.82rem}
.cnr-drop-hint{display:block;margin-top:.4rem;color:var(--muted);font-size:.72rem;line-height:1.4}
.cnr-previews{list-style:none;display:flex;flex-wrap:wrap;gap:.5rem;margin:.6rem 0 0;padding:0}
.cnr-prev{position:relative;width:64px;height:64px;border-radius:9px;overflow:hidden;
  background:var(--elev);border:1px solid var(--line)}
.cnr-prev img{width:100%;height:100%;object-fit:cover;display:block;position:static}
.cnr-prev-vid{display:grid;place-items:center;width:100%;height:100%;color:var(--muted);font-size:.7rem}
.cnr-prev-x{position:absolute;top:2px;right:2px;width:22px;height:22px;border:0;border-radius:50%;
  background:rgba(0,0,0,.65);color:#fff;font-size:15px;line-height:1;cursor:pointer;display:grid;place-items:center}

/* Honeypot: off-screen and out of the a11y tree, never display:none — some
   bots skip hidden fields, and a real user must never reach it either. */
.cnr-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.cnr-form-msg{margin:0;font-size:.82rem;line-height:1.5;color:var(--taupe)}
.cnr-form-msg:empty{display:none}
.cnr-form-msg.is-err{color:var(--bad)}
.cnr-form-msg.is-warn{color:var(--warn)}
.cnr-submit{min-height:50px}
.cnr-mod-note{margin:0;text-align:center;color:var(--muted);font-size:.75rem}

.cnr-thanks{text-align:center;padding:1.4rem .5rem}
.cnr-thanks[hidden]{display:none}
.cnr-thanks-ic{display:grid;place-items:center;width:48px;height:48px;margin:0 auto .8rem;
  border-radius:50%;background:rgba(var(--good-rgb),.15)}
.cnr-thanks-ic svg{width:22px;height:22px;stroke:var(--good);fill:none;stroke-width:2.6;position:static}
.cnr-thanks p{color:var(--ivory);font-size:.95rem;line-height:1.6;margin:0 0 1.1rem}

/* ---- customer media showcase ----
   The rail pools every approved photo/video on the product. It bleeds to the
   screen edge with the same negative-margin trick as .cnr-chips — same parent,
   same 20px .wrap padding being cancelled, so it is the proven-correct form
   here and not the .ugc-rail mistake.

   Note there is deliberately NO transform lift on hover: `overflow-x:auto`
   forces overflow-y to auto as well, which would slice the top off any tile
   that moved. Hover is carried on the border and image instead. */
.cnr-gallery{margin:0 0 1.4rem}
.cnr-gallery[hidden]{display:none}
.cnr-gallery-head{display:flex;align-items:baseline;gap:.6rem;flex-wrap:wrap;margin:0 0 .65rem}
.cnr-gallery-t{margin:0;font-family:var(--display);font-weight:600;color:var(--ivory);
  font-size:1rem;letter-spacing:-.01em}
.cnr-gallery-n{color:var(--muted);font-size:.78rem}
.cnr-gallery-rail{list-style:none;display:flex;gap:.5rem;margin:0 -20px;padding:0 20px 2px;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
  scroll-snap-type:x proximity;overscroll-behavior-x:contain}
.cnr-gallery-rail::-webkit-scrollbar{display:none}
.cnr-gtile{flex:none;scroll-snap-align:start}
/* 100px, not 92: at 92 the fourth tile landed 2px short of the screen edge, so
   the rail looked like it ended there and nothing invited a swipe. 100 + the
   8px gap puts the fourth tile roughly half off-screen at 390px — the same
   deliberately-cut scroll cue the Shop the Look rail uses. */
.cnr-gtile-btn{position:relative;display:block;padding:0;cursor:pointer;overflow:hidden;
  width:100px;height:100px;border:1px solid var(--line);border-radius:12px;background:var(--card);
  touch-action:manipulation;transition:border-color .18s var(--ease)}
.cnr-gtile-btn img{width:100%;height:100%;object-fit:cover;display:block;position:static;
  transition:opacity .18s var(--ease)}
.cnr-gtile-btn:hover{border-color:var(--cnr-accent)}
.cnr-gtile-btn:hover img{opacity:.86}
/* Overflow tile: the count sits over the last thumbnail rather than replacing
   it, so the rail keeps its rhythm instead of ending on a grey box. */
.cnr-gtile-more{position:absolute;inset:0;display:grid;place-items:center;
  background:rgba(12,13,16,.66);color:#fff;font-family:var(--display);
  font-size:1.05rem;font-weight:600;letter-spacing:-.01em}
.cnr-gtile-btn:focus-visible{outline:2px solid var(--cnr-accent);outline-offset:2px}

/* ---- lightbox ---- */
.cnr-lb{position:fixed;inset:0;z-index:98;background:rgba(8,9,11,.94);
  display:grid;place-items:center;padding:3.2rem .8rem}
.cnr-lb-fig{margin:0;display:flex;flex-direction:column;align-items:center;gap:.75rem;
  max-width:100%;min-width:0}
.cnr-lb-stage{max-width:100%;max-height:100%;display:grid;place-items:center}
.cnr-lb-media{max-width:100%;max-height:64vh;border-radius:10px;display:block;position:static}
/* Attribution under a photo opened from the rail, where the review it belongs
   to is nowhere on screen. Fixed value, not var(--taupe): .cnr-lb is a
   permanently near-black scrim (rgba(8,9,11,.94)) regardless of site theme,
   same reasoning as .cnr-lb-cap-name/.cnr-gtile-more/.ugc-tag-out above --
   var(--taupe) resolves dark in light mode, going dark-on-near-black here. */
.cnr-lb-cap{max-width:min(560px,100%);text-align:center;color:#9BA0A6;
  max-height:22vh;overflow-y:auto;overscroll-behavior:contain}
.cnr-lb-cap[hidden]{display:none}
.cnr-lb-cap-top{display:flex;align-items:center;justify-content:center;gap:.5rem;flex-wrap:wrap}
.cnr-lb-cap-name{color:#fff;font-size:.88rem}
.cnr-lb-cap-v{color:#7FB98A;font-size:.72rem}
.cnr-lb-cap-body{margin:.4rem 0 0;font-size:.85rem;line-height:1.55;white-space:pre-line}
.cnr-lb-x{position:fixed;top:12px;right:12px;background:rgba(255,255,255,.12);color:#fff}
.cnr-lb-nav{position:fixed;top:50%;transform:translateY(-50%);width:44px;height:44px;
  display:grid;place-items:center;border:0;border-radius:50%;cursor:pointer;
  background:rgba(255,255,255,.12);color:#fff}
.cnr-lb-nav[hidden]{display:none}
.cnr-lb-nav svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:2;position:static}
.cnr-lb-prev{left:10px}
.cnr-lb-next{right:10px}

.cnr-chip:focus-visible,.cnr-vote-btn:focus-visible,.cnr-thumb-btn:focus-visible,
.cnr-x:focus-visible,.cnr-lb-nav:focus-visible,.cnr-prev-x:focus-visible{
  outline:2px solid var(--cnr-accent);outline-offset:2px}

/* ---- ≥681px: the modal becomes a centred dialog, controls share a row ---- */
@media(min-width:681px){
  .cnr-controls{flex-direction:row;align-items:center;justify-content:space-between;gap:1rem}
  .cnr-chips{margin:0;padding:0;flex-wrap:wrap;overflow:visible}
  .cnr-tools{flex:none;min-width:300px}
  .cnr-modal{top:50%;left:50%;right:auto;bottom:auto;transform:translate(-50%,-50%);
    width:min(560px,calc(100% - 3rem));border-radius:18px;border:1px solid var(--line);
    max-height:88vh}
  .cnr-modal-in{padding:1.6rem 1.6rem 1.8rem}
  .cnr-row{flex-direction:row}
  .cnr-row .cnr-field{flex:1;min-width:0}
  .cnr-lb-prev{left:24px}
  .cnr-lb-next{right:24px}
  /* On desktop the rail WRAPS instead of scrolling. The review column is a
     fixed 900px, and 7 tiles fill it to within 4px — so a scrolling rail ended
     flush with no partial tile, hiding five tiles and the "+N" badge behind a
     scroll gesture nothing on screen invited. Wrapping shows the whole set and
     puts the overflow count back in view. It also drops the overflow-x:auto
     that was forcing overflow-y to auto. */
  .cnr-gallery-rail{margin:0;padding:0;flex-wrap:wrap;overflow:visible;
    scroll-snap-type:none}
  .cnr-gtile-btn{width:112px;height:112px}
  .cnr-gallery-t{font-size:1.1rem}
}

@media(prefers-reduced-motion:reduce){
  .cnr-chip,.cnr-vote-btn,.cnr-stars-input label{transition:none}
}

/* Post-purchase invite banner inside the review form. */
.cnr-invite-note{margin:0 0 .2rem;padding:.6rem .75rem;border-radius:10px;font-size:.82rem;line-height:1.45;
  color:var(--good);background:rgba(var(--good-rgb),.12);border:1px solid rgba(var(--good-rgb),.32)}

/* --- mobile PDP purchase-first order --- */
@media (max-width:1079px){
  /* display:contents lets the gallery's children become grid items so the
     thumbnail strip can be ordered independently of the main image. */
  .pdp-grid{display:flex;flex-direction:column;gap:1.1rem}
  /* Flex items default to min-width:auto, which lets a child grow past the
     container to fit its content — the same trap that pushed the thumbnail
     strip out. Constrain every direct child once, rather than chasing each.
     max-width:100% also stops the promoted gallery children overshooting. */
  .pdp-grid>*{min-width:0;max-width:100%}
  .pdp-grid .gallery{display:contents}
  .pdp-grid .gal-main{order:1}
  /* Directly under the image it belongs to, not stranded past the accordions. */
  .pdp-grid .gal-thumbs{order:2;margin-top:0;min-width:0;max-width:100%;width:100%}
  .pdp-grid .pdp-info{order:3;display:flex;flex-direction:column}
  /* Smaller thumbs on phones to pay for the height the move costs. 56px is
     still a comfortable target and still legible as a preview. */
  .pdp-grid .gal-thumbs button{flex:0 0 56px}

  /* Within the copy column. Anything without an explicit order defaults to 0
     and would jump to the top, so every direct child is assigned one. */
  .pdp-info>.label{order:1}
  .pdp-info>h1{order:2}
  /* Rating sits with the title, not stranded below the buy block. Tight
     margins because it is a 19px row between two things that belong close
     together. */
  .pdp-info>.pdp-rating{order:3;margin:.1rem 0 .45rem}
  .pdp-info>.pdp-benefit,.pdp-info>.pdp-vp{order:4}
  .pdp-info>.pdp-price{order:5}
  /* Terms sit right under the price, ahead of the buttons: tax-inclusive,
     shipping and COD cost are exactly what a shopper wants settled before
     tapping Buy, not after. This used to follow the buttons instead so it
     wouldn't separate price from the CTA — reversed because burying it
     under the buttons, swatches and warranty panel pushed it far enough
     down the page that it read as an afterthought instead of an answer. */
  .pdp-info>.pdp-terms{order:6}
  .pdp-info>form{order:7}
  /* Both used to be a single .wbadge that lived *inside* the form (order:4,
     right after qty-row) — the Special Offers rebuild pulled the warranty
     box back out to its own element and added the offers module alongside
     it, both now direct .pdp-info children rendered right after the form
     closes. Order 8/9 keeps them landing in the same visual spot as before:
     right under the quantity row, which is the form's last visible row on
     mobile (buy button, then colour options, then qty). */
  .pdp-info>.pdp-warranty{order:8}
  .pdp-info>.pdp-offers{order:9}
  .pdp-info>.pfacts{order:10}
  .pdp-info>.pincode{order:11}
  .pdp-info>.acc{order:12}

  /* Within the form: buy first, then the choices that refine it. */
  .pdp-info form{display:flex;flex-direction:column}
  .pdp-info form>.pdp-buy{order:1}
  .pdp-info form>.opt{order:2;margin-top:1.2rem}
  .pdp-info form>.qty-row{order:3}

  /* Tighter rhythm between the copy rows. Purely spacing — every element is
     still present and full size. */
  /* The 34ch measure is a readability cap meant for a wide desktop column. On
     a 335px phone column it is NARROWER than the available width, so a line
     that would otherwise fit wrapped to two and cost 23px of the fold. */
  .pdp-info>.pdp-price{margin-bottom:.7rem}
  .pdp-info>.pdp-benefit{margin:.1rem 0 .55rem;max-width:none}
  .pdp-info>.pdp-terms{margin:0 0 1rem}
  .pdp-info>h1{margin-bottom:.35rem}

}

/* Phone only: the 1:1 frame is the biggest single block above the button.
   300px still reads clearly at 375px wide. The reserved box stays exact, so
   CLS remains zero, and contain avoids cropping the product. */
@media (max-width:767px){
  /* width:100% is load-bearing. Without it the flex layout resolved the
     width from the height and the card came out narrower than the copy
     column beside it. */
  .pdp-grid .gal-main{width:100%;height:auto;max-height:none;aspect-ratio:1/1}
  /* contain, in a frame that matches the sources: nothing is cropped, and
     because the box is square there is nothing to letterbox either. contain
     rather than cover is the safety net for any product whose media is not
     1:1 — a small band beats a clipped product. */
  .pdp-grid .gal-main img{object-fit:contain}

  /* On short viewports the square frame is what pushes the buy button under
     the fold — 335px of it on a 640px screen. Cap the HEIGHT there rather
     than the ratio: contain keeps the whole image visible, it simply renders
     smaller with a little space either side. Never a crop, which is what the
     ratio change was fixing in the first place. */
  @media (max-height:700px){
    .pdp-grid .gal-main{aspect-ratio:auto;height:294px}
    /* Short screens are the only place the buy button is still tight, so the
       last few pixels come from spacing here rather than from every phone. */
    .pdp-grid{gap:.55rem}
    /* Thumbs to the 44px minimum on the shortest screens — that is exactly the
       height needed to keep the buy button above a 640px fold, and it is still
       a valid target rather than a decoration. */
    .pdp-grid .gal-thumbs button{flex:0 0 44px}
  }
  /* Vertical panning stays with the browser; horizontal is handed to the
     swipe handler, which is what stops a sideways swipe scrolling the page. */
  .pdp-grid .gal-main{touch-action:pan-y}
}

/* Between 768 and 1079 the PDP grid is already single-column but the gallery
   keeps its 1:1 ratio, so at 1002px wide it renders 923px tall and pushes the
   buy button roughly a full screen down — the same defect the mobile audit
   describes, at a width it did not test. Cap the frame; the ratio still
   reserves the box so CLS stays at zero, and contain avoids cropping. */
@media (min-width:768px) and (max-width:1079px){
  .pdp-grid .gal-main{max-height:460px}
  .pdp-grid .gal-main img{object-fit:contain}
}

/* --- cart table -> stacked cards on phones --- */
@media (max-width:767px){
  .cart-table,.cart-table tbody,.cart-table tr,.cart-table td{display:block;width:100%}
  /* The header row labels columns that no longer exist once the row stacks.
     Hidden accessibly rather than removed, so the table still reads as a
     table to assistive tech. */
  .cart-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
  .cart-table tr{
    display:grid;grid-template-columns:76px minmax(0,1fr) auto;
    grid-template-areas:"img info info" "img qty total";
    gap:.6rem .9rem;align-items:start;
    padding:1.1rem 0;border-bottom:1px solid var(--line-2);
  }
  .cart-table td{padding:0;border:0}
  /* display:contents lets the product cell's own children become grid items,
     so the thumbnail and the details sit in separate areas without needing
     another wrapper in the Liquid. */
  .cart-table td:first-child{display:contents}
  .cart-table .cart-prod{display:contents}
  .cart-table .cart-prod .th{grid-area:img;width:76px;height:92px}
  .cart-table .cart-prod>div:last-child{grid-area:info;min-width:0}
  .cart-table td:nth-child(2){grid-area:qty;align-self:end;justify-self:start}
  .cart-table td:last-child{grid-area:total;align-self:end;text-align:right!important;white-space:nowrap}

  /* Titles had six lines to themselves in a squeezed column; with the full
     width back they need a ceiling instead. */
  .cart-table .cart-prod strong{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}

  /* Thumb-sized controls. 40x38 and 44x14 were both under the minimum. */
  .cart-table .qty{height:44px;width:max-content;flex:none}
  .cart-table .qty button{min-width:44px;min-height:44px}
  .cart-table .rm{min-height:44px;display:inline-flex;align-items:center;padding:0 .2rem}
  .cart-foot a[href*="collections"]{display:inline-flex!important;align-items:center;min-height:44px}
}
