/* ==========================================================================
   LACED GLOBAL — shared stylesheet
   Aesthetic: "Shopfloor". Warm-neutral paper and sand, near-black ink, a
   serif display face over a quiet grotesk workhorse. Colour comes from the
   product photography; the UI stays neutral. One signal colour, one job:
   it marks the bag.
   Mobile-first. Verified at 375 / 768 / 1440.
   --------------------------------------------------------------------------
   00 Tokens
   01 Reset & base
   02 Typography
   03 Layout primitives
   04 Buttons & links
   05 Badges, pills, rules
   06 Header / nav
   07 Hero & editorial blocks
   08 Product card & grid
   09 Product detail (PDP)
   10 Forms
   11 Cart drawer
   12 Prose / legal
   13 Footer
   14 Motion & reveal
   15 Utilities
   16 Breakpoints
   17 Trust strip
   18 Shop filter & sort
   ========================================================================== */

/* ==========================================================================
   00 TOKENS
   ========================================================================== */

:root {
  /* --- Ink: near-black, warm. Never pure #000. --- */
  --ink:            #141516;
  --ink-2:          #2E2E2C;
  /* Measured against the darkest ground it is ever set on (--sand), not just
     --paper: at #6C6A64 it was 4.47:1 on sand and failed AA for small text. */
  --ink-muted:      #696761;   /* 5.24:1 on --paper, 4.67:1 on --sand, 5.66:1 on --white */
  --ink-faint:      #8F8C84;   /* 3.11:1 on --paper — decorative / disabled only, never text */

  /* --- Paper & sand: the whole palette is warm neutral. --- */
  --paper:          #F8F6F2;   /* page ground */
  --sand:           #EDE9E2;   /* the ground every photograph sits on */
  --white:          #FFFFFF;   /* raised panels only */

  /* --- Signal. ONE JOB: it marks the bag. The count on the header cart
         button, and the notice inside the drawer. It appears nowhere else —
         not on nav, not on links, not on focus rings, not on errors. --- */
  --bag:            #B03A1A;   /* 6.1:1 with white text */

  /* --- Focus. Ink, not signal: the highest-contrast ring we have, and it
         inverts automatically inside .section--ink. --- */
  --focus:          #141516;

  /* --- Lines. Two decorative weights, plus one that is load-bearing.
         --line / --line-strong draw rules and dividers: decoration, exempt
         from contrast minimums. --line-control draws the *boundary of an
         interactive control* (chip, input, checkbox, size swatch) and the
         underline that is a link's only affordance, so it has to clear the
         3:1 floor in WCAG 1.4.11. At --line-strong's 0.30 those boundaries
         measured 1.96:1 on paper; 0.50 puts them at 3.38:1. --- */
  --line:           rgba(20, 21, 22, 0.13);
  --line-strong:    rgba(20, 21, 22, 0.30);
  --line-control:   rgba(20, 21, 22, 0.50);
  --line-inv:       rgba(248, 246, 242, 0.16);
  --line-inv-strong:rgba(248, 246, 242, 0.34);

  /* --- Two type families. One decisive display serif, one workhorse
         grotesk that does every label, price, control and paragraph. --- */
  --font-display: "Instrument Serif", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-ui:      "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* Aliases kept so nothing downstream breaks. Both resolve to the workhorse
     or the display face — there is no third family. */
  --font-label:     var(--font-ui);
  --font-mono:      var(--font-ui);
  --font-editorial: var(--font-display);

  /* --- Type scale (fluid). The display caps at 68px: a shop headline that
         wraps past three lines is a layout failure, not a statement. --- */
  --t-display: clamp(2.25rem, 1.35rem + 3.8vw, 4.25rem);
  --t-h1:      clamp(2rem,    1.5rem + 2.1vw, 3.25rem);
  --t-h2:      clamp(1.625rem, 1.35rem + 1.2vw, 2.375rem);
  --t-h3:      clamp(1.25rem, 1.12rem + 0.55vw, 1.625rem);
  --t-h4:      clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  --t-lede:    clamp(1.0625rem, 0.99rem + 0.4vw, 1.25rem);
  --t-body:    1rem;
  --t-sm:      0.875rem;
  --t-xs:      0.8125rem;
  --t-micro:   0.6875rem;

  /* Label tracking — one value, used by every uppercase micro-label. */
  --track-label: 0.14em;

  /* --- Spacing: 4pt-derived, single scale. --- */
  --s-1:  0.25rem;
  --s-2:  0.5rem;
  --s-3:  0.75rem;
  --s-4:  1rem;
  --s-5:  1.5rem;
  --s-6:  2rem;
  --s-7:  2.5rem;
  --s-8:  3.5rem;
  --s-9:  5rem;

  /* --- Vertical rhythm. Every section derives from this one value, so the
         page has one spacing rhythm rather than per-section guesses. --- */
  --section-y: 3.5rem;

  /* --- Structure --- */
  --wrap:       1440px;
  --wrap-text:  68ch;
  --gutter:     1.25rem;
  --header-h:   60px;

  /* --- Radii. Three values, each with one job:
         0    buttons, badges — square, per the category.
         4px  anything that frames content: media, inputs, panels, chips.
         full the cart count dot, and nothing else. --- */
  --r-0:    0;
  --r-1:    4px;
  --r-full: 999px;

  /* --- Shadow: only where an element genuinely floats above the page. --- */
  --shadow-drawer: -20px 0 70px rgba(20, 21, 22, 0.20);

  /* --- Motion --- */
  --ease:      cubic-bezier(0.22, 0.75, 0.18, 1);
  --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
  --dur-1: 160ms;
  --dur-2: 320ms;
  --dur-3: 560ms;

  --z-header: 60;
  --z-drawer: 90;
  --z-scrim:  85;

  color-scheme: light;
}

/* ==========================================================================
   01 RESET & BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: -0.004em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-variant-ligatures: common-ligatures;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; }
ul[class], ol[class] { list-style: none; }

img, picture, video, canvas, svg { display: block; max-width: 100%; }
img { height: auto; border-style: none; }

input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }

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

/* The hidden attribute must win over any display rule below. */
[hidden] { display: none !important; }

hr { border: 0; border-top: 1px solid var(--line); margin: 0; }

::selection { background: #141516; color: #F8F6F2; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--r-1);
}
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: var(--s-4);
  z-index: 200;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0.75rem 1rem;
  background: var(--ink);
  color: var(--paper);
  font: 500 var(--t-micro)/1 var(--font-ui);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  transform: translateY(-180%);
  transition: transform var(--dur-2) var(--ease);
}
.skip-link:focus { transform: translateY(0); }

/* ==========================================================================
   02 TYPOGRAPHY
   Two faces. Instrument Serif carries display, headings and the pull quote;
   Archivo carries every label, price, control and paragraph.
   ========================================================================== */

.display,
.h1, .h2, .h3 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

.display {
  font-size: var(--t-display);
  line-height: 0.98;
  letter-spacing: -0.018em;
  text-transform: none;
}

.h1 { font-size: var(--t-h1); }
.h2 { font-size: var(--t-h2); }
.h3 { font-size: var(--t-h3); line-height: 1.12; }

/* h4 is a UI heading, not a display one — it lives inside cards and panels. */
.h4 {
  font-family: var(--font-ui);
  font-size: var(--t-h4);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.012em;
}

/* Eyebrow — the quiet uppercase micro-label above a heading. This is the
   category's section label: small, wide-tracked, sans. It sits above the
   grid rather than shouting. */
.eyebrow {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
/* Same label, full ink. Used where the kicker has to carry weight. */
.eyebrow--accent { color: var(--ink); }

.lede {
  font-size: var(--t-lede);
  line-height: 1.5;
  letter-spacing: -0.008em;
  color: var(--ink-2);
  max-width: 46ch;
  text-wrap: pretty;
}

/* Serif italic pull quote — one per page at most. */
.editorial {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.05rem + 1.9vw, 2.5rem);
  font-weight: 400;
  font-style: italic;
  line-height: 1.22;
  letter-spacing: -0.01em;
  color: var(--ink);
  max-width: 26ch;
}

/* Photography provenance. Deliberately not .meta: it is a disclosure a buyer
   has to be able to read, so it stays at body colour and body size. */
.photo-note {
  font-size: var(--t-sm);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 62ch;
  padding-left: var(--s-4);
  border-left: 2px solid var(--line-strong);
}

/* Small metadata: colourway, SKU, dates, counts. */
.meta {
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  letter-spacing: 0;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.meta--upper {
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  font-size: var(--t-micro);
  font-weight: 500;
}

.price {
  font-family: var(--font-ui);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.price--strike { text-decoration: line-through; color: var(--ink-muted); font-weight: 400; }

.muted  { color: var(--ink-muted); }
.accent { color: var(--ink); font-weight: 600; }

/* Oversized figure for stat blocks. */
.numeral {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.5rem, 1.6rem + 3.4vw, 4rem);
  line-height: 0.92;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   03 LAYOUT PRIMITIVES
   ========================================================================== */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--narrow { max-width: 900px; }
.wrap--text   { max-width: var(--wrap-text); }
.wrap--flush  { padding-inline: 0; }

/* Every section derives from --section-y, which is the only value that moves
   across breakpoints. There are no per-section padding overrides below. */
.section        { padding-block: var(--section-y); }
.section--tight { padding-block: calc(var(--section-y) * 0.6); }
.section--roomy { padding-block: calc(var(--section-y) * 1.4); }
.section--flush-top    { padding-top: 0; }
.section--flush-bottom { padding-bottom: 0; }

/* Inverted full-bleed block. Everything inside flips to paper-on-ink.
   Values are literal, not var() references — a custom property that points at
   another property redefined in the same scope resolves to the NEW value, so
   `--ink: var(--paper)` here would silently render ink-on-ink. */
.section--ink {
  --ink:            #F8F6F2;
  --ink-2:          #E8E4DC;
  --ink-muted:      rgba(248, 246, 242, 0.66);
  --ink-faint:      rgba(248, 246, 242, 0.42);
  --paper:          #141516;
  --sand:           #212220;
  --white:          #212220;
  --line:           rgba(248, 246, 242, 0.16);
  --line-strong:    rgba(248, 246, 242, 0.34);
  --line-control:   rgba(248, 246, 242, 0.50);  /* 5.01:1 on #141516 */
  --focus:          #F8F6F2;
  --bag:            #E4714E;
  background: #141516;
  color: #F8F6F2;
}

/* Slightly recessed warm band for alternating rhythm on a light page. */
.section--sunk { background: var(--sand); }

/* When the page ends on an ink band, it runs straight into the ink footer as
   one continuous dark base instead of leaving a stranded paper gap. */
main:has(> .section--ink:last-child) + .site-footer { margin-top: 0; }

/* Section header: label + title left, optional link right. */
.section-head {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding-bottom: var(--s-4);
  margin-bottom: var(--s-5);
  border-bottom: 1px solid var(--line);
}
.section-head__title { display: grid; gap: var(--s-2); }
.section-head__aside { display: flex; align-items: center; gap: var(--s-4); }

.rule { height: 1px; background: var(--line); border: 0; }
.rule--strong { background: var(--line-strong); }

/* Generic responsive column grids. */
.grid-2, .grid-3, .grid-4 {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
}

/* Split layout: text column + media column. */
.split { display: grid; gap: var(--s-6); align-items: start; }

/* Stat row — hairline-separated figures. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}
.stat {
  background: var(--paper);
  padding: var(--s-5) var(--s-4);
  display: grid;
  gap: var(--s-2);
  align-content: start;
}
.stat__label {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* Feature block — icon-free, numbered, hairline-led. */
.feature {
  display: grid;
  gap: var(--s-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line-strong);
}
.feature__index {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.feature__title {
  font-family: var(--font-ui);
  font-size: var(--t-h4);
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.3;
}
.feature__body { color: var(--ink-muted); font-size: var(--t-sm); line-height: 1.6; max-width: 42ch; }

/* Callout — bordered notice for policy pages and delivery notes. */
.callout {
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink);
  border-radius: var(--r-1);
  padding: var(--s-5);
  background: var(--white);
  display: grid;
  gap: var(--s-2);
}
.callout__title { font-weight: 600; letter-spacing: -0.012em; }

/* ==========================================================================
   04 BUTTONS & LINKS
   Square, ink-filled, small wide-tracked label. Hover inverts — no colour is
   involved anywhere in the button system.
   ========================================================================== */

.btn {
  --btn-bg: var(--ink);
  --btn-fg: var(--paper);
  --btn-bd: var(--ink);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: 0.9rem 1.5rem;
  min-height: 48px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  border-radius: var(--r-0);
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-align: center;
  cursor: pointer;
  touch-action: manipulation;
  transition: background var(--dur-1) var(--ease),
              color var(--dur-1) var(--ease),
              border-color var(--dur-1) var(--ease);
}
.btn:hover { background: var(--paper); color: var(--ink); border-color: var(--ink); }
.btn:active { background: var(--ink-2); color: var(--paper); border-color: var(--ink-2); }

.btn--ghost { --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--line-strong); }
.btn--ghost:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.btn--ghost:active { background: var(--ink-2); border-color: var(--ink-2); color: var(--paper); }

/* Kept as an alias so existing markup keeps working. There is no coloured
   button in this system — the primary action is ink. */
.btn--accent { --btn-bg: var(--ink); --btn-bd: var(--ink); --btn-fg: var(--paper); }

.btn--quiet {
  --btn-bg: transparent; --btn-fg: var(--ink-muted); --btn-bd: transparent;
  padding-inline: 0.5rem; min-height: 44px;
}
.btn--quiet:hover { background: transparent; border-color: transparent; color: var(--ink); }

.btn--sm { padding: 0.7rem 1rem; min-height: 44px; }
.btn--lg { padding: 1.15rem 2rem; min-height: 56px; }
.btn--block { display: flex; width: 100%; }

.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.4;
  pointer-events: none;
  cursor: not-allowed;
}

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* Text link inside prose. It inherits the surrounding colour, so the underline
   is the whole of the distinction — and it has to be there at rest, for
   everyone, without a hover.

   A real text-decoration rather than a background-image rule: the gradient
   trick drew at --line-strong (1.96:1 against paper, barely a smudge), sat at
   a fixed 1px under the descenders, and vanished entirely in forced-colors
   mode. currentColor ties the underline to the text, so it is always exactly
   as legible as the sentence it sits in — 5.24:1 in muted copy, 12.61:1 in
   body copy — and hover thickens it rather than introducing it. */
.link {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-decoration-thickness: 1px;
  text-decoration-skip-ink: auto;
  text-underline-offset: 3px;
  transition: text-decoration-thickness var(--dur-1) var(--ease);
}
.link:hover,
.link:focus-visible { text-decoration-thickness: 2px; }
.link--static { text-decoration-thickness: 2px; }

/* "→" link for section headers and card footers. Box is 44px tall for touch;
   the rule still sits tight under the label. */
.link-arrow {
  display: inline-flex;
  align-items: flex-end;
  gap: 0.6rem;
  min-height: 44px;
  padding-bottom: 0.5rem;
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 1px solid var(--line-control);
  transition: border-color var(--dur-1) var(--ease);
}
.link-arrow::after {
  content: "\2192";
  transition: transform var(--dur-2) var(--ease);
}
.link-arrow:hover { border-color: var(--ink); }
.link-arrow:hover::after { transform: translateX(5px); }

/* ==========================================================================
   05 BADGES, PILLS, RULES
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.55rem;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: 0.625rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  border-radius: var(--r-0);
  white-space: nowrap;
}
.badge--accent  { background: var(--ink); color: var(--paper); }
.badge--paper   { background: var(--paper); color: var(--ink); }
.badge--outline { background: transparent; color: var(--ink); border: 1px solid var(--line-strong); }
.badge--sold    { background: transparent; color: var(--ink-muted); border: 1px solid var(--line-strong); }

.badge-row { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* Chips — filters and tags. Square-cornered like everything else. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.9rem;
  min-height: 44px;
  border: 1px solid var(--line-control);
  border-radius: var(--r-1);
  background: transparent;
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  touch-action: manipulation;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.pill:hover { border-color: var(--ink); color: var(--ink); }
.pill.is-active, .pill[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }

.pill-row { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* Horizontally scrollable chip row for mobile filter bars.

   overflow-x: auto makes overflow-y compute to auto too, so this row is a
   scroll container on BOTH axes and clips to its padding box. With 0 top and
   2px bottom padding it sliced the top and bottom off every chip's focus ring
   (2px outline + 3px offset = 5px needed per side), leaving two stubs at the
   sides. The padding buys the ring its 5px; the matching negative margin gives
   the space straight back so nothing moves. */
.pill-row--scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  margin-block: -5px;
  padding-block: 5px;
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
  /* Scrolling a chip into view has to bring its focus ring too, not stop flush
     against the chip's own edge and leave the ring hanging over the fold. */
  scroll-padding-inline: 6px;   /* 5px of ring + 1px for sub-pixel chip widths */
}
.pill-row--scroll::-webkit-scrollbar { display: none; }

/* ==========================================================================
   06 HEADER / NAV
   ========================================================================== */

/* Thin ink strip above the header. */
.announce {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-align: center;
  padding: 0.65rem var(--gutter);
}
/* Not aria-hidden, so it is exposed as text and measured as text:
   0.45 was 4.27:1 on the ink strip, 0.50 is 5.01:1. */
.announce__dot { color: rgba(248, 246, 242, 0.50); padding-inline: 0.6rem; }

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: color-mix(in srgb, var(--paper) 90%, transparent);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: var(--header-h);
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* --- Wordmark: serif name, tracked sans qualifier. --- */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 44px;
  flex-shrink: 0;
}
.brand__mark { width: 21px; height: 21px; flex: none; color: var(--ink); }
.brand__mark .brand__lace { stroke: currentColor; }
.brand__mark .brand__eyelet { fill: currentColor; }
.brand__word {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  line-height: 1;
  white-space: nowrap;
  text-transform: none;
}
.brand__word b {
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 400;
  letter-spacing: -0.01em;
}
.brand__word span {
  font-family: var(--font-ui);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* --- Desktop nav --- */
.nav { display: none; }
.nav__list { display: flex; align-items: center; gap: var(--s-6); }
.nav__link {
  position: relative;
  display: inline-block;
  padding-block: 1rem;
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  transition: color var(--dur-1) var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0.55rem;
  height: 1px;
  width: 100%;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-2) var(--ease);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover::after,
.nav__link.is-active::after { transform: scaleX(1); }
.nav__link.is-active { color: var(--ink); font-weight: 600; }

/* --- Header actions --- */
.header-actions { display: flex; align-items: center; gap: var(--s-2); }

.cart-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.8rem;
  min-height: 44px;
  border: 1px solid var(--ink);
  border-radius: var(--r-0);
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  touch-action: manipulation;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.cart-btn:hover { background: var(--ink); color: var(--paper); }
.cart-btn__label { display: none; }
.cart-btn__icon { width: 17px; height: 17px; }

/* The one place the signal colour appears: the bag has something in it. */
.cart-btn__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 19px;
  height: 19px;
  padding-inline: 5px;
  border-radius: var(--r-full);
  background: var(--bag);
  color: #FFFFFF;
  font-size: 0.625rem;
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.cart-btn__count[hidden] { display: none; }
.cart-btn__count.is-bumped { animation: countBump var(--dur-3) var(--ease-out); }

@keyframes countBump {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.42); }
  100% { transform: scale(1); }
}

/* --- Mobile toggle --- */
.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding-inline: 11px;
  border: 1px solid var(--ink);
  border-radius: var(--r-0);
  touch-action: manipulation;
}
.nav-toggle__bar {
  display: block;
  height: 1.5px;
  width: 100%;
  background: var(--ink);
  transition: transform var(--dur-2) var(--ease), opacity var(--dur-1) var(--ease);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* --- Mobile nav panel --- */
.mobile-nav {
  display: grid;
  grid-template-rows: 0fr;
  background: var(--paper);
  border-bottom: 1px solid transparent;
  visibility: hidden;
  transition: grid-template-rows var(--dur-3) var(--ease), visibility var(--dur-3) var(--ease), border-color var(--dur-2) var(--ease);
}
.mobile-nav.is-open { grid-template-rows: 1fr; visibility: visible; border-bottom-color: var(--line); }
.mobile-nav__inner { overflow: hidden; }
.mobile-nav__list {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--s-2) var(--gutter) var(--s-5);
}
.mobile-nav__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 56px;
  padding: var(--s-4) 0 var(--s-3);
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 400;
  letter-spacing: -0.012em;
  text-transform: none;
}
.mobile-nav__link::after {
  content: attr(data-index);
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  color: var(--ink-muted);
}
.mobile-nav__link.is-active::before {
  content: "";
  align-self: center;
  width: 7px;
  height: 7px;
  margin-right: -0.35rem;
  background: var(--ink);
}
.mobile-nav__foot {
  padding-top: var(--s-3);
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.mobile-nav__foot a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ==========================================================================
   07 HERO & EDITORIAL BLOCKS
   The hero is deliberately short. On a shop, product has to be near the fold.
   ========================================================================== */

.hero {
  position: relative;
  padding-block: var(--s-5) var(--s-6);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
.hero__inner { display: grid; gap: var(--s-5); }
.hero__title { margin-block: var(--s-3) var(--s-4); }
.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}
/* On a phone the shop window comes first: the photograph sits directly under
   the header and the headline reads beneath it. At 900px the two columns sit
   side by side and DOM order applies again. */
.hero__media { order: -1; }
@media (min-width: 900px) { .hero__media { order: 0; } }

/* --- Media frames -------------------------------------------------------
   Two ratios site-wide, each with one job:
     1 / 1  every product photograph (cards, PDP, cart lines, editorial)
     3 / 2  the single lifestyle hero
   Every frame is a warm sand ground with object-fit: cover, so nothing is
   ever distorted and nothing is ever letterboxed.

   The frames carry no border. They carry one shared inset hairline instead:
   invisible against dark photography, but enough to hold the square when a
   shot is nearly white and would otherwise dissolve into the paper. It is
   drawn as ::after so it sits above the image rather than behind it.
   ---------------------------------------------------------------------- */
.product-card__media::after,
.pdp__hero::after,
.pdp__thumb::after,
.hero__media::after,
.media::after,
.cart-line__media::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(20, 21, 22, 0.07);
  pointer-events: none;
}
.hero__media {
  position: relative;
  aspect-ratio: 3 / 2;
  background: var(--sand);
  border-radius: var(--r-1);
  overflow: hidden;
}
.hero__media img,
.hero__media picture { width: 100%; height: 100%; }
.hero__media img { object-fit: cover; object-position: center; }

/* Ticker — a slow marquee of small caps. Pure CSS, pauses on hover. */
.marquee {
  display: flex;
  overflow: hidden;
  border-block: 1px solid var(--line);
  padding-block: 0.85rem;
  user-select: none;
}
.marquee__track {
  display: flex;
  flex: none;
  gap: var(--s-6);
  padding-right: var(--s-6);
  min-width: 100%;
  animation: marquee 38s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__item {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}
.marquee__item::before { content: "\2022"; color: var(--ink-faint); padding-right: var(--s-6); }

@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}

/* ==========================================================================
   08 PRODUCT CARD & GRID
   The card has to feel buyable: photograph on sand, brand, name, colourway,
   then a hairline foot carrying the price and the sizes in stock, then a
   full-width add-to-bag. No border, no shadow — alignment does the work.
   ========================================================================== */

.product-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-6) var(--s-3);
}

.product-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  isolation: isolate;
}

.product-card__media {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--sand);
  border-radius: var(--r-1);
}
.product-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: transform var(--dur-3) var(--ease-out), opacity var(--dur-2) var(--ease);
}
/* Retained so existing markup cannot break, but the frame stays square: one
   ratio for every product photograph on the site. */
.product-card__media--portrait { aspect-ratio: 1 / 1; }

/* For cut-out product shots on a white background. Unused by this catalogue. */
.product-card__img--contain { object-fit: contain; padding: 8%; mix-blend-mode: multiply; }

.product-card__img--alt { position: absolute; inset: 0; opacity: 0; }
.product-card:hover .product-card__img--alt { opacity: 1; }
.product-card:hover .product-card__img { transform: scale(1.03); }

.product-card__badges {
  position: absolute;
  inset: var(--s-2) var(--s-2) auto var(--s-2);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1);
  z-index: 2;
  pointer-events: none;
}
/* A badge on top of photography must stay legible whatever the image does. */
.product-card__badges .badge--outline {
  background: var(--paper);
  color: var(--ink);
  border-color: transparent;
}
.product-card__badges .badge {
  max-width: 100%;
  white-space: normal;
  text-align: left;
  line-height: 1.2;
}

.product-card__body { display: grid; gap: 0.25rem; }

.product-card__brand {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.product-card__name {
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.012em;
  /* two-line clamp keeps every card the same height */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Whole-card click target without nesting interactive elements. */
.product-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
/* The link sits inside .product-card__name, which is line-clamped and so
   overflow: hidden — a ring on the link itself gets sliced off top and bottom.
   It is drawn around the photograph instead, which nothing clips.

   Scoped to the link's own :focus-visible rather than the card's :focus-within:
   focus-within also matched the add-to-bag button nested in the same card, so
   tabbing to Add lit up two rings at once and pointed at the wrong control. */
.product-card__link:focus-visible { outline: none; }
.product-card:has(.product-card__link:focus-visible) .product-card__media {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* Price left, sizes in stock right. Both are load-bearing on a shop. */
.product-card__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  margin-top: auto;
}
.product-card__price {
  font-family: var(--font-ui);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.product-card__size {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* The add-to-bag. The card's link overlay sits at z-index 1, so the button
   has to be lifted above it or the click navigates instead of adding. */
.product-card__add { position: relative; z-index: 2; }

.product-card.is-sold { opacity: 0.55; }
.product-card.is-sold .product-card__add { display: none; }

/* Empty / no-results state for the shop grid. */
.empty-state {
  grid-column: 1 / -1;
  display: grid;
  gap: var(--s-4);
  justify-items: center;
  text-align: center;
  padding: var(--s-9) var(--s-4);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-1);
}
.empty-state__body { color: var(--ink-muted); font-size: var(--t-sm); line-height: 1.6; max-width: 46ch; }

/* ==========================================================================
   09 PRODUCT DETAIL (PDP)
   ========================================================================== */

.pdp { display: grid; gap: var(--s-6); padding-block: var(--s-5) var(--s-8); }

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-block: var(--s-2);
}
.breadcrumb a,
.breadcrumb > span {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.breadcrumb a:hover { color: var(--ink); }
.breadcrumb__sep { color: var(--ink-faint); }

.pdp__gallery { display: grid; gap: var(--s-4); }
.pdp__hero {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--sand);
  border-radius: var(--r-1);
  overflow: hidden;
}
.pdp__hero img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.pdp__hero img.is-contain { object-fit: contain; padding: 6%; mix-blend-mode: multiply; }

.pdp__thumbs {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  scrollbar-width: none;
}
.pdp__thumbs::-webkit-scrollbar { display: none; }
.pdp__thumb {
  position: relative;
  flex: none;
  width: 72px;
  aspect-ratio: 1 / 1;
  background: var(--sand);
  border: 1px solid transparent;
  border-radius: var(--r-1);
  overflow: hidden;
}
.pdp__thumb img { width: 100%; height: 100%; object-fit: cover; }
.pdp__thumb.is-active { border-color: var(--ink); }

.pdp__panel { display: grid; gap: var(--s-4); align-content: start; }
.pdp__brand {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.pdp__title {
  font-family: var(--font-display);
  font-size: var(--t-h1);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.014em;
  text-wrap: balance;
}
.pdp__price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s-3);
  font-family: var(--font-ui);
  font-size: 1.625rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.pdp__row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }
.pdp__note { font-size: var(--t-xs); color: var(--ink-muted); line-height: 1.6; }

/* Size selector — accessible radio grid, no JS required for the visuals. */
.size-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: var(--s-2);
}
.size-option { position: relative; }
.size-option input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
.size-option span {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 52px;
  padding: 0.4rem;
  border: 1px solid var(--line-control);
  border-radius: var(--r-1);
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  text-align: center;
  transition: border-color var(--dur-1) var(--ease), background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.size-option small { font-size: 0.625rem; color: var(--ink-muted); letter-spacing: 0.02em; }
.size-option input:hover + span { border-color: var(--ink); }
.size-option input:checked + span { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.size-option input:checked + span small { color: rgba(248, 246, 242, 0.7); }
.size-option input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }
.size-option input:disabled + span {
  opacity: 0.4;
  cursor: not-allowed;
  text-decoration: line-through;
}

/* Specification table. */
.spec-list { display: grid; border-top: 1px solid var(--line-strong); }
.spec-list__row {
  display: grid;
  grid-template-columns: 40% 1fr;
  gap: var(--s-3);
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--t-sm);
}
.spec-list__key {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.spec-list__val { font-variant-numeric: tabular-nums; }

/* Disclosure — <details> for delivery, sizing, returns on the PDP. */
.disclosure { border-bottom: 1px solid var(--line); }
.disclosure > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  min-height: 48px;
  padding-block: var(--s-4);
  cursor: pointer;
  list-style: none;
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::after {
  content: "+";
  font-size: 1.05rem;
  line-height: 1;
  color: var(--ink);
  transition: transform var(--dur-2) var(--ease);
}
.disclosure[open] > summary::after { transform: rotate(45deg); }
.disclosure__body { padding-bottom: var(--s-4); font-size: var(--t-sm); color: var(--ink-muted); line-height: 1.65; }
.disclosure__body p + p { margin-top: var(--s-3); }

/* ==========================================================================
   10 FORMS
   ========================================================================== */

.field { display: grid; gap: var(--s-2); }
.field__label {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-2);
}

.input, .select, .textarea {
  width: 100%;
  padding: 0.85rem 0.95rem;
  min-height: 48px;
  background: var(--white);
  border: 1px solid var(--line-control);
  border-radius: var(--r-1);
  font-size: var(--t-body);
  line-height: 1.4;
  color: var(--ink);
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--ink-muted); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--ink-2); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(20, 21, 22, 0.12);
}
.textarea { min-height: 140px; resize: vertical; }

.select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.5rem;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%),
                    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 20px) 52%, calc(100% - 14px) 52%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.checkbox { display: flex; align-items: flex-start; gap: var(--s-3); font-size: var(--t-sm); cursor: pointer; min-height: 44px; }
.checkbox input {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  border: 1px solid var(--line-control);
  border-radius: var(--r-1);
  background: var(--white);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.checkbox input:checked { background: var(--ink); border-color: var(--ink); }
.checkbox input:checked::after {
  content: "";
  display: block;
  width: 4px;
  height: 8px;
  margin: 2px auto 0;
  border: solid var(--paper);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}

.form-note { font-size: var(--t-xs); color: var(--ink-muted); line-height: 1.55; }
/* Errors are ink, bold and rule-marked, not coloured — the signal colour has
   one job and this is not it. Colour was never the only cue here anyway. */
.form-note--error {
  color: var(--ink);
  font-weight: 600;
  font-size: var(--t-xs);
  letter-spacing: 0;
  padding-left: var(--s-3);
  border-left: 2px solid var(--ink);
}

/* Contact panel — mailto block that replaces a form. No POST anywhere. */
.contact-card {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-6) var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  background: var(--white);
}
.contact-card__address {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1rem + 2.2vw, 2.5rem);
  font-weight: 400;
  letter-spacing: -0.014em;
  word-break: break-word;
}
.contact-card__address a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  border-bottom: 1px solid var(--line-control);
}
.contact-card__address a:hover { border-color: var(--ink); }

/* ==========================================================================
   11 CART DRAWER
   ========================================================================== */

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-scrim);
  background: rgba(20, 21, 22, 0.5);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-2) var(--ease), visibility var(--dur-2) var(--ease);
}
.drawer-scrim.is-open { opacity: 1; visibility: visible; }

.cart-drawer {
  position: fixed;
  top: 0;
  right: 0;
  z-index: var(--z-drawer);
  display: flex;
  flex-direction: column;
  width: min(100%, 430px);
  height: 100dvh;
  background: var(--paper);
  border-left: 1px solid var(--line-strong);
  box-shadow: var(--shadow-drawer);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--dur-3) var(--ease-out), visibility var(--dur-3) var(--ease-out);
}
.cart-drawer.is-open { transform: translateX(0); visibility: visible; }

.cart-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4) var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--line-strong);
  flex: none;
}
.cart-drawer__title {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.cart-drawer__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-0);
  font-size: 1.05rem;
  line-height: 1;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.cart-drawer__close:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }

.cart-drawer__items {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-inline: var(--s-5);
  -webkit-overflow-scrolling: touch;
}

.cart-line {
  display: grid;
  grid-template-columns: 76px 1fr auto;
  gap: var(--s-3);
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--line);
  align-items: start;
}
.cart-line__media {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--sand);
  border-radius: var(--r-1);
  overflow: hidden;
}
.cart-line__media img { width: 100%; height: 100%; object-fit: cover; }
.cart-line__body { display: grid; gap: 0.25rem; min-width: 0; }
.cart-line__brand {
  font-family: var(--font-ui);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.cart-line__name {
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.012em;
}
.cart-line__meta {
  font-family: var(--font-ui);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.cart-line__side { display: grid; gap: var(--s-2); justify-items: end; }
.cart-line__price { font-family: var(--font-ui); font-size: var(--t-xs); font-weight: 600; font-variant-numeric: tabular-nums; }
.cart-line__remove {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-ui);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  border-bottom: 1px solid transparent;
  transition: color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.cart-line__remove:hover { color: var(--ink); border-bottom-color: var(--ink); }

.cart-empty {
  display: grid;
  gap: var(--s-4);
  justify-items: start;
  padding-block: var(--s-8);
}
.cart-empty__title { font-family: var(--font-display); font-size: var(--t-h3); font-weight: 400; letter-spacing: -0.012em; }

.cart-drawer__foot {
  flex: none;
  display: grid;
  gap: var(--s-4);
  padding: var(--s-5);
  border-top: 1px solid var(--line-strong);
  background: var(--sand);
}
.cart-subtotal {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}
.cart-subtotal__label {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.cart-subtotal__value {
  font-family: var(--font-ui);
  font-size: 1.375rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* "Checkout not live yet" state, swapped in by site.js. The second and last
   place the signal colour appears — it is still marking the bag. */
.cart-notice {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--bag);
  border-radius: var(--r-1);
  background: var(--paper);
  animation: noticeIn var(--dur-2) var(--ease-out) both;
}
.cart-notice__title {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.cart-notice__body { font-size: var(--t-xs); color: var(--ink-muted); line-height: 1.6; }

@keyframes noticeIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   12 PROSE / LEGAL
   ========================================================================== */

.legal-head {
  display: grid;
  gap: var(--s-3);
  padding-block: var(--s-7) var(--s-5);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-6);
}
.legal-head__title {
  font-family: var(--font-display);
  font-size: var(--t-h1);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.014em;
  text-transform: none;
}
.updated {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.prose { max-width: var(--wrap-text); font-size: 1.0625rem; line-height: 1.72; color: var(--ink-2); }
.prose > * + * { margin-top: var(--s-4); }
.prose h2 {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin-top: var(--s-7);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}
.prose h3 {
  font-family: var(--font-ui);
  font-size: var(--t-h4);
  font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin-top: var(--s-5);
}
.prose ul, .prose ol { padding-left: 1.25rem; display: grid; gap: var(--s-2); }
.prose ul { list-style: none; padding-left: 0; }
.prose ul > li { position: relative; padding-left: 1.35rem; }
.prose ul > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 8px;
  height: 1px;
  background: var(--ink);
}
.prose ol { list-style: decimal; }
.prose ol > li::marker { font-size: 0.85em; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
/* Same reasoning as .link: --ink against .prose's --ink-2 is not a colour
   difference anyone can see, so the underline is the only cue and it cannot be
   a 1.96:1 hairline. currentColor makes it 16.94:1 at rest. */
.prose a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-decoration-thickness: 1px;
  text-decoration-skip-ink: auto;
  text-underline-offset: 3px;
  transition: text-decoration-thickness var(--dur-1) var(--ease);
}
.prose a:hover { text-decoration-thickness: 2px; }
.prose strong { font-weight: 600; color: var(--ink); }
.prose small { font-size: var(--t-xs); color: var(--ink-muted); }

/* Table of contents for long legal pages. */
.toc {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  background: var(--sand);
}
.toc__title {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.toc a { font-size: var(--t-sm); display: inline-flex; align-items: center; min-height: 44px; }
.toc a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ==========================================================================
   13 FOOTER
   ========================================================================== */

/* The footer paints an ink ground but, unlike .section--ink, it used to leave
   the tokens alone — so --focus stayed #141516 and every focus ring down here
   was ink drawn on ink, 1.00:1 and literally invisible. The ground is dark, so
   the ring, the control boundary and the muted text all have to invert with
   it. Values are literal for the same reason .section--ink's are. */
.site-footer {
  --focus:        #F8F6F2;                    /* 16.94:1 on #141516 (was 1.00:1) */
  --line-control: rgba(248, 246, 242, 0.50);  /* 5.01:1 on #141516 */
  --ink-muted:    rgba(248, 246, 242, 0.66);
  background: var(--ink);
  color: var(--paper);
  margin-top: var(--s-9);
  overflow: hidden;
}
.site-footer__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
  /* lets .footer-wordmark size against the real content width, not vw
     (vw includes the scrollbar, which clipped the last letter) */
  container-type: inline-size;
}

.site-footer__top {
  display: grid;
  gap: var(--s-6);
  padding-block: var(--s-7) var(--s-6);
}

.footer-brand { display: grid; gap: var(--s-4); max-width: 42ch; }
.footer-brand .brand__mark { color: var(--paper); }
.footer-brand .brand__word span { color: rgba(248, 246, 242, 0.55); }
.footer-blurb { font-size: var(--t-sm); line-height: 1.65; color: rgba(248, 246, 242, 0.68); }

.footer-cols { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-6) var(--s-4); }
.footer-col { display: grid; gap: var(--s-3); align-content: start; }
.footer-col__title {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: rgba(248, 246, 242, 0.50);   /* 5.01:1 on #141516 (0.45 was 4.27:1) */
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--line-inv);
}
.footer-links { display: grid; }
.footer-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-sm);
  color: rgba(248, 246, 242, 0.82);
  width: fit-content;
  transition: color var(--dur-1) var(--ease);
}
.footer-links a:hover { color: #F8F6F2; text-decoration: underline; text-underline-offset: 4px; }

.footer-contact { display: grid; gap: var(--s-2); }
.footer-contact a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  border-bottom: 1px solid var(--line-control);
  width: fit-content;
  transition: border-color var(--dur-1) var(--ease);
}
.footer-contact a:hover { border-color: #F8F6F2; }

.footer-bottom {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding-block: var(--s-4) var(--s-5);
  border-top: 1px solid var(--line-inv);
}
.footer-legal {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 400;
  letter-spacing: 0.04em;
  color: rgba(248, 246, 242, 0.5);
  line-height: 1.7;
}

/* Oversized clipped wordmark — the footer signature. Decorative only. */
.footer-wordmark {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.5rem, 12vw, 12rem); /* fallback */
  font-size: clamp(2.5rem, 13cqw, 13rem);
  line-height: 0.8;
  letter-spacing: -0.02em;
  color: transparent;
  -webkit-text-stroke: 1px rgba(248, 246, 242, 0.3);
  white-space: nowrap;
  user-select: none;
  padding-bottom: 0.08em;
  margin-bottom: -0.16em;
}

/* ==========================================================================
   14 MOTION & REVEAL
   ========================================================================== */

/* Add data-reveal to any block; site.js adds .is-visible when it scrolls in.
   Use style="--i:1" ... on siblings for a stagger. */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 60ms);
}
[data-reveal].is-visible { opacity: 1; transform: none; }

/* If JS never runs, nothing should stay invisible. */
.no-js [data-reveal] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
  .marquee__track { animation: none; }
}

/* ==========================================================================
   15 UTILITIES
   ========================================================================== */

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.text-center { text-align: center; }
.text-right  { text-align: right; }
.flex-between { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }
.flex-wrap { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.stack-2 { display: grid; gap: var(--s-2); }
.stack-3 { display: grid; gap: var(--s-3); }
.stack-4 { display: grid; gap: var(--s-4); }
.stack-5 { display: grid; gap: var(--s-5); }
.mt-4 { margin-top: var(--s-4); }
.mt-5 { margin-top: var(--s-5); }
.mt-6 { margin-top: var(--s-6); }
.mb-4 { margin-bottom: var(--s-4); }
.mb-5 { margin-bottom: var(--s-5); }
.mb-6 { margin-bottom: var(--s-6); }
.max-46 { max-width: 46ch; }
.hide-mobile { display: none; }
.full-bleed { width: 100vw; margin-inline: calc(50% - 50vw); }

/* Editorial media frames. Same two ratios as everything else: 1/1 for a
   product photograph, 3/2 for a lifestyle shot. Sand ground, no border. */
.media {
  position: relative;
  overflow: hidden;
  background: var(--sand);
  border-radius: var(--r-1);
}
.media img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.media--square   { aspect-ratio: 1 / 1; }
.media--portrait { aspect-ratio: 1 / 1; }
.media--wide     { aspect-ratio: 3 / 2; }
.media--multiply img { object-fit: contain; padding: 7%; mix-blend-mode: multiply; }

/* ==========================================================================
   16 BREAKPOINTS
   --section-y is the only spacing value that changes across breakpoints.
   ========================================================================== */

/* --- 600px: roomier gutters, 2-up content --- */
@media (min-width: 600px) {
  :root { --gutter: 2rem; --header-h: 68px; --section-y: 4.5rem; }

  .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .product-grid { gap: var(--s-6) var(--s-4); }
  .stat-row { grid-template-columns: repeat(4, 1fr); }
  .stat { padding: var(--s-6) var(--s-5); }
  .cart-btn__label { display: inline; }
  .footer-bottom { flex-direction: row; align-items: center; justify-content: space-between; }
  .section-head { flex-direction: row; align-items: flex-end; justify-content: space-between; }
  .contact-card { padding: var(--s-7) var(--s-6); }
}

/* --- 768px: tablet --- */
@media (min-width: 768px) {
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* 3-up from tablet upward and never wider. The catalogue is 12 pairs and
     each rail holds 6, so three columns is the only count that leaves no
     ragged final row anywhere on the site — and it buys a bigger tile. */
  .product-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hero { padding-block: var(--s-7) var(--s-8); }
  .split { grid-template-columns: 1fr 1fr; gap: var(--s-7); }
  .footer-cols { grid-template-columns: repeat(3, 1fr); }
  .site-footer__top { grid-template-columns: 1fr 1.35fr; gap: var(--s-8); padding-block: var(--s-8) var(--s-7); }
  .legal-head { padding-block: var(--s-8) var(--s-6); }
}

/* --- 900px: desktop nav takes over, PDP goes two-column --- */
@media (min-width: 900px) {
  :root { --gutter: 2.5rem; --header-h: 76px; --section-y: 6rem; }

  .nav { display: block; }
  .nav-toggle { display: none; }
  .mobile-nav { display: none; }

  .hero__inner { grid-template-columns: 1fr 1.1fr; align-items: center; gap: var(--s-7); }

  .pdp {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: var(--s-7);
    align-items: start;
  }
  .pdp__panel {
    position: sticky;
    top: calc(var(--header-h) + var(--s-5));
    gap: var(--s-5);
  }
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .hide-mobile { display: block; }
  .feature { padding-top: var(--s-5); }
}

/* --- 1200px: 4-up product grid --- */
@media (min-width: 1200px) {
  :root { --gutter: 3rem; }

  .product-grid { gap: var(--s-7) var(--s-5); }
  .split--wide { grid-template-columns: 0.9fr 1.35fr; gap: var(--s-8); }
  .site-footer__top { grid-template-columns: 1fr 1.6fr; }
  .footer-cols { grid-template-columns: repeat(3, 1fr); gap: var(--s-7); }
}

/* --- 1440px+: cap the gutter growth, keep the measure honest --- */
@media (min-width: 1440px) {
  :root { --gutter: 3.5rem; }
  .product-grid { gap: var(--s-7) var(--s-6); }
  .hero__inner { gap: var(--s-9); }
}

/* Very small phones (<=360px) — keep the grid from crushing. */
@media (max-width: 360px) {
  .product-grid { grid-template-columns: 1fr; }
  .cart-line { grid-template-columns: 64px 1fr auto; }
}

/* ==========================================================================
   17 TRUST STRIP
   Hairline lattice of short factual assurances, each led by a small inline
   SVG. Same construction as .stat-row — 1px gaps over a --line ground — so it
   sits in the existing rhythm. Icons are ink: the strip must never become the
   loudest thing on a page whose job is to sell product.
   ========================================================================== */

.trust-strip {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}

.trust-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--s-2) var(--s-3);
  background: var(--paper);
  padding: var(--s-5) var(--s-4);
}

.trust-item__icon {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--ink);
  margin-top: 1px;
}

.trust-item__title {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
  align-self: center;
}

.trust-item__body {
  grid-column: 2;
  font-size: var(--t-xs);
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: 36ch;
}

@media (min-width: 600px) {
  .trust-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .trust-item { padding: var(--s-6) var(--s-5); }
}

@media (min-width: 900px) {
  .trust-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ==========================================================================
   18 SHOP FILTER & SORT (shop.html)
   No page script is allowed, so the shop controls are real <input> elements
   and the rules below read them with :has(). Two rules of the game:
     - every filter rule HIDES; nothing re-shows across dimensions, so the
       dimensions compose as AND;
     - shoe size is multi-valued per product, so it is filtered on the wrapping
       .product-cell (display: contents) rather than on the card itself. That
       keeps its show/hide pair independent of the card-level hides.
   Hidden cards generate no box, so they do not increment the results counter.
   ========================================================================== */

.shop-layout { display: grid; gap: var(--s-6); align-items: start; }

/* --- Filter panel: a scrolling chip bar on mobile, a sidebar at 900px --- */
.filters {
  display: grid;
  gap: var(--s-5);
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--line);
}
.filters__group { display: grid; gap: var(--s-3); margin: 0; padding: 0; border: 0; min-width: 0; }
.filters__legend { padding: 0; }
/* Chips keep their natural width so labels never wrap mid-word. */
.filters .pill { flex: none; white-space: nowrap; }

/* A .pill that wraps a checkbox or radio becomes the control itself. */
.pill:has(input) { position: relative; }
.pill input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.pill:has(input:checked) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.pill:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 3px; }

/* --- Results column --- */
.shop-results { display: flex; flex-direction: column; gap: var(--s-5); counter-reset: results; }
.shop-results .product-card { counter-increment: results; }

/* The bar sits after the grid in the DOM so the counter can read the final
   value, and is pulled above it visually. */
.shop-bar {
  order: -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}
/* The count is written as real text by site.js (so it can be read out, copied
   and survives a stylesheet failure). This counter is the no-script fallback
   and is suppressed as soon as that text is present. */
.shop-count__num:empty::after { content: "Showing " counter(results) " of 12"; }

/* Wrapper for the size filter. Generates no box of its own. */
.product-cell { display: contents; }

/* --- Brand: one card has exactly one brand, so hide per unchecked option --- */
.shop-layout:has(.f-brand:checked):not(:has(#f-nike:checked))   .product-card[data-brand="Nike"]   { display: none; }
.shop-layout:has(.f-brand:checked):not(:has(#f-jordan:checked)) .product-card[data-brand="Jordan"] { display: none; }
.shop-layout:has(.f-brand:checked):not(:has(#f-adidas:checked)) .product-card[data-brand="adidas"] { display: none; }
.shop-layout:has(.f-brand:checked):not(:has(#f-vans:checked))   .product-card[data-brand="Vans"]   { display: none; }

/* --- Price band (radios; "Any" is the default and declares no rule) --- */
.shop-layout:has(#f-price-u100:checked) .product-card:not([data-band="u100"]) { display: none; }
.shop-layout:has(#f-price-100:checked)  .product-card:not([data-band="100"])  { display: none; }
.shop-layout:has(#f-price-150:checked)  .product-card:not([data-band="150"])  { display: none; }
.shop-layout:has(#f-price-250:checked)  .product-card:not([data-band="250"])  { display: none; }

/* --- Shoe size: hide every cell, then show back any cell holding a checked
       size. The show rules carry an id, so they always out-specify the hide. */
.shop-layout:has(.f-size:checked) .product-cell { display: none; }
.shop-layout:has(#f-size-5:checked)  .product-cell[data-sizes~="5"]  { display: contents; }
.shop-layout:has(#f-size-6:checked)  .product-cell[data-sizes~="6"]  { display: contents; }
.shop-layout:has(#f-size-7:checked)  .product-cell[data-sizes~="7"]  { display: contents; }
.shop-layout:has(#f-size-8:checked)  .product-cell[data-sizes~="8"]  { display: contents; }
.shop-layout:has(#f-size-9:checked)  .product-cell[data-sizes~="9"]  { display: contents; }
.shop-layout:has(#f-size-10:checked) .product-cell[data-sizes~="10"] { display: contents; }
.shop-layout:has(#f-size-11:checked) .product-cell[data-sizes~="11"] { display: contents; }
.shop-layout:has(#f-size-12:checked) .product-cell[data-sizes~="12"] { display: contents; }

/* --- Sort. data-rank is the product's position by price, cheapest first.
       "Newest" leaves order at 0, which is DOM order. --- */
.product-card[data-rank="1"]  { --rank: 1; }
.product-card[data-rank="2"]  { --rank: 2; }
.product-card[data-rank="3"]  { --rank: 3; }
.product-card[data-rank="4"]  { --rank: 4; }
.product-card[data-rank="5"]  { --rank: 5; }
.product-card[data-rank="6"]  { --rank: 6; }
.product-card[data-rank="7"]  { --rank: 7; }
.product-card[data-rank="8"]  { --rank: 8; }
.product-card[data-rank="9"]  { --rank: 9; }
.product-card[data-rank="10"] { --rank: 10; }
.product-card[data-rank="11"] { --rank: 11; }
.product-card[data-rank="12"] { --rank: 12; }

.shop-layout:has(#sort-low:checked)  .product-card { order: var(--rank, 0); }
.shop-layout:has(#sort-high:checked) .product-card { order: calc(var(--rank, 0) * -1); }

@media (min-width: 900px) {
  .shop-layout { grid-template-columns: 232px minmax(0, 1fr); gap: var(--s-7); }

  /* Same clipping trap one level up: overflow-y: auto makes the sidebar a
     scroll container on both axes, and with padding-left: 0 every chip sat
     flush against the clip edge, so the left side of its focus ring was cut
     off. 5px of left padding, given back as negative margin. */
  .filters {
    position: sticky;
    top: calc(var(--header-h) + var(--s-5));
    max-height: calc(100dvh - var(--header-h) - var(--s-7));
    overflow-y: auto;
    margin-left: -5px;
    padding-left: 5px;
    padding-right: var(--s-2);
    padding-bottom: 5px;   /* was 0: the last chip's ring was cut off at the fold */
    border-bottom: 0;
  }
  /* In the sidebar the chip rows wrap instead of scrolling sideways. */
  .filters .pill-row--scroll {
    flex-wrap: wrap;
    overflow: visible;
    margin-inline: 0;
    padding-inline: 0;
  }
}

/* --- No results. The .empty-state block in shop.html is visible by default;
       each rule below hides it when one specific product survives the current
       filter combination, so the disjunction across all twelve rules means
       "at least one card is showing". Conditions per dimension use :is() as an
       OR: "this dimension is unfiltered" OR "this product's own option is
       checked". No script is involved. --- */
/* nike-air-force-1-shadow-pastel */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-nike:checked)):is(:has(#f-price-any:checked), :has(#f-price-100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-5:checked), :has(#f-size-6:checked), :has(#f-size-7:checked), :has(#f-size-8:checked)) .empty-state { display: none; }
/* nike-air-force-1-lv8-utility-black */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-nike:checked)):is(:has(#f-price-any:checked), :has(#f-price-100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked), :has(#f-size-11:checked)) .empty-state { display: none; }
/* carhartt-wip-nike-air-force-1-low-ale-brown */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-nike:checked)):is(:has(#f-price-any:checked), :has(#f-price-250:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked)) .empty-state { display: none; }
/* air-jordan-1-low-black-varsity-red */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-jordan:checked)):is(:has(#f-price-any:checked), :has(#f-price-150:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-6:checked), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked), :has(#f-size-11:checked)) .empty-state { display: none; }
/* nike-air-max-1-ultra-moire-total-orange */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-nike:checked)):is(:has(#f-price-any:checked), :has(#f-price-100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-6:checked), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked)) .empty-state { display: none; }
/* nike-zoom-fly-triple-black */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-nike:checked)):is(:has(#f-price-any:checked), :has(#f-price-100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked), :has(#f-size-11:checked), :has(#f-size-12:checked)) .empty-state { display: none; }
/* nike-free-rn-flyknit-university-red */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-nike:checked)):is(:has(#f-price-any:checked), :has(#f-price-u100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked)) .empty-state { display: none; }
/* nike-kyrie-7-black-white */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-nike:checked)):is(:has(#f-price-any:checked), :has(#f-price-100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked), :has(#f-size-11:checked), :has(#f-size-12:checked)) .empty-state { display: none; }
/* adidas-superstar-cloud-white */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-adidas:checked)):is(:has(#f-price-any:checked), :has(#f-price-u100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-5:checked), :has(#f-size-6:checked), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked), :has(#f-size-11:checked)) .empty-state { display: none; }
/* adidas-forum-low-white-royal-blue */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-adidas:checked)):is(:has(#f-price-any:checked), :has(#f-price-u100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-6:checked), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked)) .empty-state { display: none; }
/* adidas-campus-burgundy */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-adidas:checked)):is(:has(#f-price-any:checked), :has(#f-price-100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-6:checked), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked), :has(#f-size-11:checked)) .empty-state { display: none; }
/* vans-old-skool-port-royale */
.shop-layout:is(:not(:has(.f-brand:checked)), :has(#f-vans:checked)):is(:has(#f-price-any:checked), :has(#f-price-u100:checked)):is(:not(:has(.f-size:checked)), :has(#f-size-5:checked), :has(#f-size-6:checked), :has(#f-size-7:checked), :has(#f-size-8:checked), :has(#f-size-9:checked), :has(#f-size-10:checked)) .empty-state { display: none; }
