/* GENERATED by build-css.py from fonts.css + tokens.css + main.css + cart.css - edit those, not this file. */
/* ---- fonts.css ---- */
/* ============================================================
   SHIRT ARCHIVE — self-hosted variable fonts
   No third-party requests. Latin subset.
   ============================================================ */

/* Archivo — variable weight 100–900 AND width 62–125.
   The width axis is why this replaced Anton: we can dial in a heavy
   condensed grotesque that matches the design draft, rather than
   accepting whatever single cut a static font ships with. */
@font-face {
  font-family: 'Archivo';
  src: url('../assets/fonts/archivo-var.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}



@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/inter-var.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Geist Mono — catalogue codes (refs, sizes, badges, crumbs). The single
   600 cut is deliberately mapped to EVERY weight: the codes always render
   at the approved boldness, whatever weight a rule asks for. */
@font-face {
  font-family: 'Geist Mono';
  src: url('../assets/fonts/geistmono-600.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---- tokens.css ---- */
/* ============================================================
   SHIRT ARCHIVE — design tokens
   Single source of truth. No hex values anywhere else.
   ============================================================ */

:root {
  /* colour */
  --base:      #F4F1EA;   /* newsprint — never pure white */
  --base-warm: #EDE9DF;   /* recessed panels, image beds */
  --ink:       #14110F;
  --deep:      #1B2A3A;
  --accent:    #E4572E;   /* floodlight orange */
  --gold-hi:   #F4DE8A;   /* trophy gold, highlight edge */
  --gold:      #E0BD48;   /* trophy gold, body */
  --gold-deep: #B08A1E;   /* trophy gold, shadow edge */
  --gold-glow: rgba(224, 189, 72, 0.55);
  --ink-on-gold: #14110F; /* stays dark in dark mode too */
  --green:     #2E5E3A;   /* availability only */
  --muted:     #8C877D;
  --rule-c:    #D6D0C4;   /* hairline rules */

  /* listing tag families — one colour per family, never per tag.
     Kept low-chroma so a row of five chips still reads as newsprint. */
  --tag-era:   #E4572E;   /* Retro / Recent / Current */
  --tag-kit:   #1B2A3A;   /* Home / Away / GK  */
  --tag-fit:   #2F6B6B;   /* Women's / Kids    */
  --tag-team:  #14110F;   /* team, links out   */
  --tag-comp:  #8A6A2F;   /* league / cup      */

  /* fixed pair — panels that stay ink-on-cream in BOTH themes
     (hero panel, footer). Deliberately not theme-swapped. */
  --panel-bg:  #14110F;
  --panel-fg:  #F4F1EA;

  /* turf bands — dark sections backed by black-and-white pitch photography.
     Same fixed pair as the panels: these stay ink-on-cream in both themes,
     because the artwork underneath is always dark. The scrim sits between the
     photograph and the type; raise its alpha if a band ever reads too busy. */
  --band-bg:    #14110F;
  --band-fg:    #F4F1EA;
  --band-scrim: rgba(20, 17, 15, 0.46);
  --band-rule:  rgba(244, 241, 234, 0.18);

  /* type — owner-approved 2026-08-08 off the /international/england/ test:
     Archivo (the display family) carries the UI chrome and the card
     titles/prices; Geist Mono (600 cut mapped to every weight) carries the
     catalogue codes. Body text stays Inter. */
  --font-display: 'Archivo', 'Haettenschweiler', 'Arial Narrow', sans-serif;
  --font-body:    'Inter', system-ui, -apple-system, sans-serif;
  --font-mono:    'Geist Mono', 'Consolas', ui-monospace, monospace;
  --font-ui:      'Archivo', sans-serif;   /* nav, offer strip, dropdown heads */
  --wght-ui:      680;
  --wdth-ui:      80%;
  --font-card:    'Archivo', sans-serif;   /* card titles + prices */

  /* display axes — Archivo is variable in BOTH weight and width.
     These two values are the whole character of the headline type. */
  --wght-display: 800;
  --wdth-display: 74%;

  --fs-hero:   clamp(2.75rem, 5.6vw, 5rem);
  --fs-h2:     1.375rem;
  --fs-body:   1.0625rem;   /* 17px */
  --fs-mono:   0.8125rem;   /* 13px */
  --fs-micro:  0.6875rem;   /* 11px */

  --lh-tight: 0.94;
  --lh-body:  1.65;
  --tr-tight: -0.02em;
  --tr-wide:  0.15em;

  /* space */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-6: 1.5rem;
  --sp-8: 2rem;
  --sp-12: 3rem;
  --sp-16: 4rem;

  --gutter: clamp(1.25rem, 3vw, 3rem);
  --maxw: 1600px;

  /* form */
  --radius: 4px;               /* maximum, anywhere */
  --rule: 1px solid var(--rule-c);
  --rule-ink: 1px solid var(--ink);
  --t: 150ms ease;
}

:root[data-theme="dark"] {
  --base:      #14110F;
  --base-warm: #1C1917;
  --ink:       #F4F1EA;
  --muted:     #9A948A;
  --rule-c:    #35302A;
  --deep:      #0E1620;

  /* tag families, lifted for contrast on ink */
  --tag-era:   #F0784F;
  --tag-kit:   #7FA3C4;
  --tag-fit:   #63A8A8;
  --tag-team:  #F4F1EA;
  --tag-comp:  #C4A059;
}

/* NOTE: dark mode is deliberately OPT-IN via the footer toggle only.
   It is NOT wired to prefers-color-scheme. This design is a printed,
   beige, newsprint object — auto-flipping it to black on a machine set
   to dark mode destroys the entire identity. Do not "fix" this. */

/* ---- main.css ---- */
/* ============================================================
   SHIRT ARCHIVE — homepage
   Every value below references tokens.css. No literals.
   ============================================================ */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--base);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

.wrap { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }

/* ---------- shared type ---------- */
.mono {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
}
.ref {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tr-wide);
  color: var(--muted);
  text-transform: uppercase;
}
.display {
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: var(--lh-tight);
}

/* ============================================================
   HEADER
   ============================================================ */
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  padding: var(--sp-4) var(--gutter);
  border-bottom: var(--rule);
  background: var(--base);
  /* the 1px ink rule does the separating - no shadow, per the design */
}

/* stops in-page anchors landing under the sticky header */
html { scroll-padding-top: 88px; }

.wordmark {
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: clamp(1.5rem, 2.4vw, 2rem);
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: 1;
  white-space: nowrap;
}

.nav {
  display: flex;
  /* wrap rather than overflow. Nav labels in French, Polish and Turkish run
     far longer than the English ones and were painting over the search box
     between the 900px collapse point and ~1450px. Wrapping grows the header
     by a row instead, which no locale can break. */
  flex-wrap: wrap;
  row-gap: var(--sp-2);
  gap: clamp(1rem, 2.4vw, 2.25rem);
  margin-inline: auto;
}
.nav a {
  font-family: var(--font-ui);
  font-weight: var(--wght-ui);
  font-stretch: var(--wdth-ui);
  font-size: 0.9375rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  white-space: nowrap;
  padding-block: var(--sp-1);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t);
}
/* below 1100px the 15px no-wrap nav no longer fits - step back down and let
   the two-word items wrap again (the 900px hamburger takes over from there) */
@media (max-width: 1100px) {
  .nav a { font-size: var(--fs-mono); white-space: normal; }
}
.nav a:hover { border-bottom-color: var(--ink); }

/* min-width:0 lets these flex children shrink instead of forcing the header
   wider than the viewport. Without it a locale with longer nav labels than
   English pushed .utils to 1607px at a 1440px viewport - German runs ~30%
   longer, and every locale after it will too. */
.header > .nav, .header > .utils { min-width: 0; }
.utils { display: flex; align-items: center; gap: var(--sp-6); flex-shrink: 0; }

/* currency selector (2026-08-09). Native <select> on purpose: it is one tap on
   mobile, keyboard accessible for free, and needs no JS to open. */
.ccy select {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--ink);
  background: transparent;
  border: var(--rule);
  border-radius: var(--radius);
  padding: var(--sp-1) var(--sp-2);
  cursor: pointer;
}
.ccy select:hover { border-color: var(--ink); }
/* converted prices carry a hint that the charge is still in GBP */
:root[data-ccy]:not([data-ccy="GBP"]) .money { cursor: help; }
/* currency symbols keep their own casing inside all-caps furniture: the
   Polish zloty is "zł", never "ZŁ", and CHF/kr have fixed forms too */
.offer-strip .money, .buy-label .money, .buy-cta .money,
.money-lit, .badge .money { text-transform: none; }
.search input { min-width: 0; }
.utils button { display: flex; opacity: 0.9; transition: opacity var(--t); }
.utils button:hover { opacity: 1; }
.icon { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.5; }

.bag { position: relative; }
.bag-count {
  position: absolute;
  bottom: -4px; right: -7px;
  min-width: 15px; height: 15px;
  display: grid; place-items: center;
  padding-inline: 3px;
  background: var(--accent);
  color: var(--base);
  border-radius: 50%;
  font-family: var(--font-mono);
  font-size: 9px;
  line-height: 1;
}

.nav-toggle { display: none; }

/* ---- brand lockup ---- */
.brand { display: flex; align-items: center; }
.brand img {
  width: auto;
  height: clamp(30px, 3.4vw, 40px);  /* standard retail header size */
  /* logo ships as pure ink; invert it for dark mode */
}
:root[data-theme="dark"] .brand img { filter: invert(1); }
.brand--footer img { height: 44px; margin-bottom: var(--sp-4); }

/* ============================================================
   HERO
   ============================================================ */
.hero,
.hero-slide { display: grid; grid-template-columns: 34% 1fr; }
/* slide height derives from the media column's 16:9 box (66% wide -> whole
   slide is 2.694:1), so panel and image ALWAYS share one height and the
   image renders full-bleed: zero crop, zero letterbox, at every width. */
.hero-slide { aspect-ratio: 2.694 / 1; }
.hero-panel { min-height: 0; overflow: hidden; }

/* ---- carousel ------------------------------------------------
   Slides are stacked in one grid cell rather than absolutely
   positioned, so the section keeps the height of its tallest slide
   and nothing jumps as they change. Inactive slides are
   visibility:hidden, which also takes their links out of the tab
   order without needing tabindex juggling. */
.hero-carousel { position: relative; }
.hero-track { display: grid; }
.hero-slide {
  grid-area: 1 / 1;
  visibility: hidden;
  opacity: 0;
  transition: opacity 500ms ease, visibility 0s linear 500ms;
}
.hero-slide.is-active {
  visibility: visible;
  opacity: 1;
  transition: opacity 500ms ease, visibility 0s;
}

.hero-ref {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 var(--sp-4);
}

.hero-controls {
  z-index: 20;          /* always above cutouts (2), scanlines (3), spots (4) */
  position: absolute;
  right: var(--gutter);
  bottom: var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2);
  background: var(--panel-bg);
}
.hero-arrow {
  display: grid;
  place-items: center;
  width: 2rem; height: 2rem;
  color: var(--panel-fg);
  background: none;
  border: 0;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity var(--t);
}
.hero-arrow:hover { opacity: 1; }
.hero-dots { display: flex; gap: var(--sp-2); padding: 0 var(--sp-2); }
.hero-dot {
  width: 1.75rem; height: 2px;
  padding: var(--sp-2) 0;
  background: none;
  border: 0;
  cursor: pointer;
  line-height: 0;
}
.hero-dot::before {
  content: "";
  display: block;
  height: 2px;
  background: var(--panel-fg);
  opacity: 0.35;
  transition: opacity var(--t), background-color var(--t);
}
.hero-dot[aria-current="true"]::before { background: var(--accent); opacity: 1; }
.hero-dot:hover::before { opacity: 0.8; }

@media (prefers-reduced-motion: reduce) {
  .hero-slide { transition: none; }
}

.hero-panel {
  background: var(--panel-bg);      /* stays ink in both themes, by design */
  color: var(--panel-fg);
  padding: clamp(2rem, 4.5vw, 4.5rem) clamp(1.5rem, 3vw, 3rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.hero-title { font-size: var(--fs-hero); margin: 0; }
.hero-slash {
  width: 56px; height: 3px;
  background: var(--accent);
  margin: var(--sp-8) 0 var(--sp-6);
}
.hero-sub {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.55;
  margin: 0 0 var(--sp-6);
  max-width: 36ch;
  opacity: 0.92;
}
.hero-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  align-self: flex-start;
  border-bottom: 1px solid transparent;
  transition: border-color var(--t);
}
.hero-cta:hover { border-bottom-color: var(--accent); }
.hero-cta span { transition: transform var(--t); }
.hero-cta:hover span { transform: translateX(4px); }

.hero-media { position: relative; height: 100%; min-height: 0; overflow: hidden; margin: 0; }
/* direct children only - the hover card's thumbnail must NOT be caught */
.hero-media > img:not(.hero-cut) {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
}
.hero-base-mobile { display: none; }
.mobile-hero-shop,
.mobile-hero-search,
.mobile-h1-detail { display: none; }
.hero-card img { position: static; inset: auto; }

/* ============================================================
   LEAGUE INDEX — banner cards
   The index used to be eleven text chips, which wasted the league
   banners entirely. Same card mechanics as the player featured
   grid: the banner does the work, the caption carries the numbers
   that make one league distinguishable from another.
   ============================================================ */
/* One card per row. In two columns each card was ~677px wide and the 3.6:1
   banner had to be cropped hard, so four shirts became two enormous ones and
   the page read as clutter. Full width shows the banner at its own ratio -
   all four shirts, the gradient, and the empty left third the caption sits in. */
.lcard-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  margin-bottom: var(--sp-12);
}
.lcard {
  position: relative;
  display: block;
  overflow: hidden;
  border: var(--rule);
  border-radius: var(--radius);
  background: var(--panel-bg);
}
.lcard img {
  width: 100%;
  /* height:auto is REQUIRED, not tidiness: the img carries height="672" and a
     used height makes the browser ignore aspect-ratio entirely, so the card
     rendered 672px tall instead of following the banner's ratio. */
  height: auto;
  aspect-ratio: 2412 / 672;        /* the banner's own ratio - no crop */
  object-fit: cover;
  object-position: center;
  transition: transform var(--t);
}
.lcard:hover img { transform: scale(1.01); }
/* caption sits in the banner's empty left third rather than across the shirts */
.lcard-t {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-2);
  width: min(34%, 24rem);
  padding: var(--sp-6) var(--sp-4) var(--sp-6) clamp(var(--sp-4), 3vw, var(--sp-12));
  color: var(--panel-fg);
  background: linear-gradient(to right, var(--panel-bg) 55%, transparent);
}
.lcard-n {
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: 1.05;
  font-size: clamp(1.25rem, 2.2vw, 1.75rem);
}
.lcard-m {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  opacity: 0.8;
}
/* on a phone a 3.6:1 strip is ~110px tall and the shirts vanish, so the card
   becomes a taller crop with the caption back along the bottom */
@media (max-width: 720px) {
  .lcard img { aspect-ratio: 16 / 9; object-position: right center; }
  .lcard-t {
    position: static;
    width: auto;
    padding: var(--sp-4);
    background: var(--panel-bg);
  }
}
@media (prefers-reduced-motion: reduce) { .lcard:hover img { transform: none; } }

/* ============================================================
   LISTING ZOOM LENS
   A round lens follows the cursor over the product photo and
   shows the source-resolution image beneath it.

   The honest ceiling is the supplier original: 1080px against a
   643px display, so ~1.7x. background-size is set to the zoom
   asset's own pixel size, which means the lens never magnifies
   past real detail - it just stops getting sharper.

   Pointer-only: enabled in JS behind (hover:hover) and
   (pointer:fine), so touch devices get the plain photo and no
   ghost hover state.
   ============================================================ */
.pdp-frame { position: relative; display: block; }
.pdp-frame img { display: block; width: 100%; height: auto; }

.pdp-lens {
  position: absolute;
  z-index: 3;
  width: 220px;
  height: 220px;
  margin: -110px 0 0 -110px;      /* centre on the cursor */
  border-radius: 50%;
  border: 1px solid var(--rule-c);
  background-color: var(--base);
  background-repeat: no-repeat;
  background-size: 1080px 1080px; /* the zoom asset at 1:1 */
  box-shadow: 0 0 0 1px rgba(20, 17, 15, 0.10);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t);
  pointer-events: none;           /* never eat the cursor */
}
.pdp-frame.zooming .pdp-lens { opacity: 1; visibility: visible; }
.pdp-frame.zooming { cursor: crosshair; }

@media (prefers-reduced-motion: reduce) {
  .pdp-lens { transition: none; }
}

/* ============================================================
   PLAYER INDEX — featured cards + A-Z strip
   93 players used to render as one flat wall of chips. The top
   eight carry 77% of the shirt-intent demand on that page, so
   they get real cards using their career banner art; everyone
   else stays a chip, grouped by era.
   ============================================================ */
.pfeat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-4);
  margin-bottom: var(--sp-12);
}
.pfeat {
  position: relative;
  display: block;
  overflow: hidden;
  border: var(--rule);
  border-radius: var(--radius);
  background: var(--panel-bg);
}
.pfeat img {
  width: 100%;
  height: 100%;
  aspect-ratio: 16 / 7;
  object-fit: cover;
  object-position: right center;   /* the shirts sit right of the pad */
  transition: transform var(--t);
}
.pfeat:hover img { transform: scale(1.02); }
.pfeat-t {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-6) var(--sp-4) var(--sp-3);
  color: var(--panel-fg);
  /* keeps the name legible over whichever shirt lands behind it */
  background: linear-gradient(to top, var(--panel-bg), transparent);
}
.pfeat-n {
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: 1.05;
  font-size: 1.0625rem;
}
.pfeat-c {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  opacity: 0.78;
}

.az {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin-bottom: var(--sp-8);
  padding-bottom: var(--sp-4);
  border-bottom: var(--rule);
}
.az a {
  min-width: 2rem;
  padding: var(--sp-2);
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--muted);
  border: 1px solid transparent;
  transition: color var(--t), border-color var(--t);
}
.az a:hover { color: var(--ink); border-color: var(--rule-c); }

@media (max-width: 1100px) { .pfeat-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 820px)  { .pfeat-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px)  { .pfeat-grid { grid-template-columns: 1fr; } }

/* ============================================================
   TURF BANDS
   Dark full-bleed sections backed by black-and-white pitch
   photography. The page alternates newsprint -> turf band ->
   newsprint so a long page reads as sections rather than one
   flat column.

   Rules of use:
   - turf carries EDITORIAL and TRUST copy only
   - never behind a product grid, a data table or the buy box:
     shirts need a clean ground and numbers need to be read
   - the scrim guarantees contrast, so type never sits directly
     on the photograph
   Three shared assets (gen-turf-assets.py) are reused sitewide
   rather than a different photograph per template.
   ============================================================ */
.band {
  position: relative;
  isolation: isolate;
  background: var(--band-bg);
  color: var(--band-fg);
  padding-block: clamp(var(--sp-8), 5vw, var(--sp-16));
}
.band::before {                       /* the photograph */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: var(--band-img, none);
  background-size: cover;
  background-position: center;
}
.band::after {                        /* the scrim that guarantees contrast */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--band-scrim);
}
.band--line    { --band-img: url("/assets/turf/turf-line.webp"); }
.band--corner  { --band-img: url("/assets/turf/turf-corner.webp");
                 background-position: left center; }
.band--stripes { --band-img: url("/assets/turf/turf-stripes.webp"); }

/* type inside a band inverts; muted greys would disappear */
.band h1, .band h2, .band h3, .band p, .band li, .band td, .band th {
  color: var(--band-fg);
}
.band .ref, .band .meta, .band .hub-standfirst { color: var(--band-fg); opacity: 0.78; }
.band a:not(.btn) { color: var(--band-fg); border-bottom: 1px solid var(--band-rule); }
.band a:not(.btn):hover { border-bottom-color: var(--accent); }
.band .trust-item { border-left-color: var(--band-rule); }
.band .section-head { border-bottom-color: var(--band-rule); }

/* full-bleed out of a .wrap without horizontal scroll. ONLY valid on a block
   whose parent spans the page - inside a narrow grid column the 50vw maths is
   measured off the column and pushes the page sideways. Use .band--inset there. */
.band--bleed {
  margin-inline: calc(50% - 50vw);
  padding-inline: calc(50vw - 50% + var(--gutter));
}

/* contained band: for bands living inside a grid column or a card */
.band--inset {
  padding-inline: clamp(var(--sp-4), 2.5vw, var(--sp-8));
  border-radius: var(--radius);
}

@media (prefers-reduced-motion: no-preference) {
  .band { background-attachment: scroll; }   /* never parallax: uxpilot */
}

/* ============================================================
   TRUST ROW
   ============================================================ */
.trust {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-bottom: var(--rule);
}
/* standalone trust row (not inside a band) needs its own breathing room -
   without it the row sits flush against the chip nav above and reads clipped */
.trust--spaced { margin-top: var(--sp-12); border-top: var(--rule); }
.trust-item {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
  padding: var(--sp-6) var(--sp-8) var(--sp-6) 0;
  border-left: var(--rule);
}
.trust-item:first-child { border-left: 0; padding-left: 0; }
.trust-item:not(:first-child) { padding-left: var(--sp-8); }
.trust-icon { flex: 0 0 auto; width: 34px; height: 34px; stroke: currentColor; fill: none; stroke-width: 1.25; }
.trust h3 {
  margin: 0 0 var(--sp-1);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.trust p {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  line-height: 1.7;
  color: var(--muted);
  max-width: 24ch;
}

/* ============================================================
   NEW ARRIVALS
   ============================================================ */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--sp-8) var(--sp-6);
  border-bottom: var(--rule-ink);
}
.section-head h2 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-h2);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.section-head h2 em { font-style: normal; border-bottom: 2px solid var(--ink); padding-bottom: 2px; }
.section-count {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--muted);
  white-space: nowrap;
}
.view-all {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  white-space: nowrap;
}
.view-all span { transition: transform var(--t); }
.view-all:hover span { transform: translateX(4px); }

.grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  padding-bottom: var(--sp-16);
}
.card { padding: var(--sp-4) var(--sp-4) var(--sp-6); border-left: var(--rule); }
.card:first-child { border-left: 0; padding-left: 0; }
.card:last-child { padding-right: 0; }
.card .ref { display: block; margin-bottom: var(--sp-3); }

.card-media {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--base);   /* newsprint, so specimen shots sit seamlessly */
  border: var(--rule);
  overflow: hidden;
  margin-bottom: var(--sp-4);
}
.card-media img { width: 100%; height: 100%; object-fit: contain; transition: transform var(--t); }
.card:hover .card-media img { transform: scale(1.02); }

.card h3 {
  margin: 0 0 var(--sp-1);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.card .meta { margin: 0 0 var(--sp-3); font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--muted); }
.card .price { margin: 0; font-family: var(--font-mono); font-size: var(--fs-mono); }

/* image placeholder — visible until a real file is dropped in */
.ph::after {
  content: attr(data-ref);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tr-wide);
  color: var(--muted);
  background: var(--base-warm);
  pointer-events: none;
}
.ph.filled::after { display: none; }

/* ============================================================
   FOOTER
   ============================================================ */
.footer {
  background: var(--base);           /* beige, like the rest of the page.
                                        The draft has no dark footer. */
  color: var(--ink);
  border-top: 2px solid var(--ink);
  margin-top: var(--sp-8);
  padding-block: var(--sp-12) var(--sp-8);
}
.footer-grid { display: grid; grid-template-columns: 1.5fr repeat(3, 1fr) auto; gap: var(--sp-8); }
.footer h4 {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  color: var(--muted);
}
.footer ul { margin: 0; padding: 0; list-style: none; }
.footer li { margin-bottom: var(--sp-2); }
.footer li a {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t);
}
.footer li a:hover { border-bottom-color: var(--ink); }
.footer .wordmark { margin-bottom: var(--sp-4); }
.footer-blurb {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  line-height: 1.8;
  color: var(--muted);
  max-width: 32ch;
}
.theme-toggle {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  border: var(--rule-ink);
  border-radius: var(--radius);
  padding: var(--sp-2) var(--sp-3);
  transition: background var(--t), color var(--t);
  white-space: nowrap;
}
.theme-toggle:hover { background: var(--ink); color: var(--base); }
.footer-bottom {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-top: var(--sp-12);
  padding-top: var(--sp-6);
  border-top: var(--rule);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--muted);
}


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

.head-note {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--muted);
  white-space: nowrap;
}

/* ============================================================
   LEDGER — the accession register. Rules, no cards, no stripes.
   ============================================================ */
.ledger-wrap { overflow-x: auto; padding-bottom: var(--sp-16); }
.ledger {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
}
.ledger th {
  text-align: left;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  font-size: var(--fs-micro);
  color: var(--muted);
  padding: var(--sp-4) var(--sp-4) var(--sp-3) 0;
  border-bottom: var(--rule-ink);
  white-space: nowrap;
}
.ledger td {
  padding: var(--sp-3) var(--sp-4) var(--sp-3) 0;
  border-bottom: var(--rule);
  white-space: nowrap;
}
.ledger td:first-child { color: var(--muted); letter-spacing: 0.08em; }
.ledger .num { text-align: right; padding-right: 0; }
.ledger tbody tr { transition: background var(--t); }
.ledger tbody tr:hover { background: var(--base-warm); }

/* ============================================================
   PROVENANCE
   ============================================================ */
.prov {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-8);
  padding-block: var(--sp-8) var(--sp-16);
}
.prov-media {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--base);
  border: var(--rule);
  overflow: hidden;
  margin-bottom: var(--sp-4);
}
.prov-media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t); }
.prov-item:hover .prov-media img { transform: scale(1.02); }
.prov-item .ref { display: block; margin-bottom: var(--sp-2); }
.prov-item h3 {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: 1.05;
}
.prov-item p { margin: 0; font-size: 0.9375rem; line-height: 1.6; color: var(--muted); }

/* ============================================================
   NATIONS
   ============================================================ */
.nations {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border-top: var(--rule);
  margin-bottom: var(--sp-16);
}
.nation {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-8) var(--sp-4) var(--sp-8) 0;
  border-left: var(--rule);
  transition: background var(--t);
}
.nation:first-child { border-left: 0; }
.nation:not(:first-child) { padding-left: var(--sp-6); }
.nation:hover { background: var(--base-warm); }
.nation .display { font-size: clamp(1.5rem, 2.6vw, 2.25rem); }
.nation .count { color: var(--muted); }

/* ============================================================
   JOURNAL — headline is the link, no thumbnails, no buttons
   ============================================================ */
.journal {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  padding-bottom: var(--sp-16);
}
.post { padding: var(--sp-8) var(--sp-8) 0 0; border-left: var(--rule); }
.post:first-child { border-left: 0; }
.post:not(:first-child) { padding-left: var(--sp-8); }
.post-date { display: block; color: var(--muted); margin-bottom: var(--sp-3); }
.post h3 {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: 1.625rem;
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: 1.05;
}
.post h3 a { border-bottom: 2px solid transparent; transition: border-color var(--t); }
.post h3 a:hover { border-bottom-color: var(--accent); }
.post p { margin: 0; font-size: 0.9375rem; line-height: 1.6; color: var(--muted); }

/* ============================================================
   FAQ
   ============================================================ */
.faq { padding-bottom: var(--sp-16); max-width: 900px; }
.faq details { border-bottom: var(--rule); }
.faq summary {
  list-style: none;
  cursor: pointer;
  padding: var(--sp-6) var(--sp-8) var(--sp-6) 0;
  position: relative;
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  transition: color var(--t);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  position: absolute;
  right: 0; top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-size: 1.25rem;
  color: var(--accent);
}
.faq details[open] summary::after { content: "−"; }  /* the character is U+2212 MINUS. Do NOT write it as "\2212" inside a Python string: \221 is a valid OCTAL escape, so Python emits U+0091 (unprintable) followed by '2' - which is exactly the tofu-box-then-2 that shipped on every open FAQ and PDP accordion. */
.faq summary:hover { color: var(--accent); }
.faq details p {
  margin: 0 0 var(--sp-6);
  max-width: 68ch;
  color: var(--muted);
}


/* ---- ledger thumbnails ---- */
.thumb-col { width: 64px; padding-right: var(--sp-4) !important; }
.thumb {
  position: relative;
  display: block;
  width: 52px; height: 52px;
  background: var(--base-warm);
  border: var(--rule);
  overflow: hidden;
}
.thumb img { width: 100%; height: 100%; object-fit: cover; }
.thumb.ph::after { font-size: 7px; letter-spacing: 0.04em; line-height: 1.3; padding: 2px; text-align: center; }
.ledger td a { border-bottom: 1px solid transparent; transition: border-color var(--t); }
.ledger td a:hover { border-bottom-color: var(--ink); }

/* ---- shop by type ---- */
.types {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-top: var(--rule);
  margin-bottom: var(--sp-16);
}
.type {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-8) var(--sp-6) var(--sp-8) 0;
  border-left: var(--rule);
  transition: background var(--t);
}
.type:first-child { border-left: 0; }
.type:not(:first-child) { padding-left: var(--sp-6); }
.type:hover { background: var(--base-warm); }
.type .display { font-size: clamp(1.125rem, 1.7vw, 1.5rem); }
.type .mono { color: var(--muted); }

/* ---- Shop by Type, with photography (2026-08-09) ----
   These were text-only on a page that is otherwise image-led, and the grid was
   4 columns for 5 cards so the last one sat alone on a second row. */
.types--visual {
  grid-template-columns: repeat(5, 1fr);
  gap: 0;
}
.types--visual .type { padding-top: var(--sp-6); }
.type-media {
  display: block;
  margin-bottom: var(--sp-4);
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--base-warm);
  aspect-ratio: 1 / 1;
}
.type-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t);
}
.type:hover .type-media img { transform: scale(1.03); }

@media (max-width: 1100px) {
  .types--visual { grid-template-columns: repeat(3, 1fr); }
  /* the left rule only reads as a divider on a single row */
  .types--visual .type { border-left: 0; padding-left: 0; padding-right: var(--sp-4); }
}
@media (max-width: 640px) {
  .types--visual { grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); }
  .types--visual .type { padding: var(--sp-4) 0 0; }
}

/* ---- journal thumbnails ---- */
.post-media {
  position: relative;
  display: block;
  aspect-ratio: 3 / 2;
  background: var(--base-warm);
  border: var(--rule);
  overflow: hidden;
  margin-bottom: var(--sp-4);
}
.post-media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t); }
.post:hover .post-media img { transform: scale(1.02); }


/* ---- lead / body copy blocks ---- */
.lead { padding-block: var(--sp-8) var(--sp-12); }
.lead-body { margin: 0 0 var(--sp-4); }
.lead-body:last-child { margin-bottom: 0; }
.lead-body strong { font-weight: 500; border-bottom: 1px solid var(--rule-c); }

/* ---- chip navs (clubs, players) ---- */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-6); }
.chips a {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  padding: var(--sp-2) var(--sp-3);
  border: var(--rule);
  border-radius: var(--radius);
  transition: background var(--t), color var(--t), border-color var(--t);
}
.chips a:hover { background: var(--ink); color: var(--base); border-color: var(--ink); }
/* count riding inside a chip (shop-by-player on /new/) */
.chip-n {
  margin-left: var(--sp-2);
  padding-left: var(--sp-2);
  border-left: var(--rule);
  color: var(--muted);
}
.chips a:hover .chip-n { color: var(--base); border-left-color: currentColor; }

/* ---- league count row (/new/, 2026-08-09) ----
   Counts come from the same Counter that builds the facets, so they cannot
   drift. Originally there were three of these rows - fit, kit and league - but
   fit and kit repeated the sidebar facets number for number and were cut. This
   one stays because it is not a facet: it routes off the page to /league/.
   Styled with a visible affordance; as flat boxes it read as static stats. */
.nstrip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}
.nstrip-i {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: var(--rule);
  border-radius: var(--radius);
  transition: background var(--t), color var(--t), border-color var(--t),
              transform var(--t);
}
.nstrip-i::after {
  content: "\2192";
  margin-left: var(--sp-1);
  color: var(--accent);
  transition: transform var(--t);
}
.nstrip-n {
  font-family: var(--font-card);
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1;
}
.nstrip-l { font-size: var(--fs-mono); color: var(--muted); }
.nstrip-i:hover { background: var(--ink); border-color: var(--ink); }
.nstrip-i:hover .nstrip-l,
.nstrip-i:hover .nstrip-n { color: var(--base); }
.nstrip-i:hover::after { transform: translateX(3px); }

/* section head for a row that belongs to the copy above it. .lead already ends
   in sp-12 of padding, and .section-head opens with another sp-8 - together
   that left ~130px of dead space between the intro and this row. */
.section-head--tight { margin-top: 0; padding-top: 0; }

/* ---- in-hub search (/new/, /womens/, /kids/) ----
   These hubs carry 272-701 cards behind a facet sidebar; without a text box
   the only way to reach a known shirt was to scroll. Filters the same card set
   as the facets, in the same pass. */
.shop-search { position: relative; margin-bottom: var(--sp-6); }
.shop-search-i {
  position: absolute;
  left: var(--sp-3);
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  stroke: var(--muted);
  fill: none;
  stroke-width: 1.6;
  pointer-events: none;
}
.shop-search input {
  width: 100%;
  padding: var(--sp-3) var(--sp-8) var(--sp-3) calc(var(--sp-8) + var(--sp-1));
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--ink);
  background: transparent;
  border: var(--rule);
  border-radius: var(--radius);
}
.shop-search input:focus-visible {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px var(--band-rule);
}
.shop-search input::-webkit-search-cancel-button { display: none; }
.shop-search button {
  position: absolute;
  right: var(--sp-2);
  top: 50%;
  transform: translateY(-50%);
  padding: 0 var(--sp-2);
  font-size: 1.1rem;
  line-height: 1;
  color: var(--muted);
  background: none;
  border: 0;
  cursor: pointer;
}
.shop-search button:hover { color: var(--ink); }

.shop-empty {
  padding: var(--sp-16) 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--muted);
  text-align: center;
}
.shop-empty button {
  font: inherit;
  color: var(--accent);
  background: none;
  border: 0;
  border-bottom: 1px solid currentColor;
  cursor: pointer;
}

/* ---- group standfirst on the directory pages (2026-08-09) ----
   Sits between a group heading and its chip row on /club/ and /international/,
   which were a bare stack of headings and counts. Measure is held short so it
   reads as an introduction to the row, not as body copy. */
.group-note {
  max-width: 68ch;
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--muted);
}
.group-note a { color: var(--ink); border-bottom: 1px solid var(--rule-c); }
.group-note a:hover { color: var(--accent); border-bottom-color: currentColor; }

/* ---- team badge chips (directory pages, 2026-08-08) ----
   Crest photo chip + name + count; hover raises the chip and drops a shirt
   preview with a CTA. The generic .chips a rules above are reset here. */
.chips--teams a.tchip-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-3) var(--sp-1) var(--sp-1);
  background: var(--base);
  transition: border-color var(--t), transform var(--t), box-shadow var(--t);
}
.chips--teams a.tchip-link:hover {
  background: var(--base);
  color: inherit;
  border-color: var(--ink);
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(20, 17, 15, 0.12);
  z-index: 6;
}
.tchip {
  width: 42px; height: 42px;
  flex: 0 0 auto;
  border-radius: 50%;
  overflow: hidden;
  background: var(--base-warm);
  border: 1px solid var(--rule-c);
}
.tchip img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tchip img.tchip-ph { object-fit: contain; padding: 7px; opacity: 0.45; }
.tname {
  /* rendered as an H3 since 2026-09-01 (owner: directory entries are
     headings); margin:0 neutralises the heading default, everything else
     was already explicit so the look is unchanged */
  margin: 0;
  font-family: var(--font-ui);
  font-weight: var(--wght-ui);
  font-stretch: var(--wdth-ui);
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.tcount {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--muted);
}
.texp {
  position: absolute;
  top: calc(100% + 6px); left: 0;
  width: 250px;
  display: none;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3);
  background: var(--base);
  border: 1px solid var(--ink);
  box-shadow: 0 14px 30px rgba(20, 17, 15, 0.18);
  z-index: 30;
}
.tchip-link:hover .texp { display: flex; }
.texp .tx { display: flex; flex-direction: column; min-width: 0; }
.texp img {
  width: 84px; height: 84px;
  flex: 0 0 auto;
  object-fit: contain;
  background: var(--base-warm);
}
.texp .tdesc {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--muted);
  letter-spacing: 0.04em;
  margin-bottom: var(--sp-1);
}
.texp .tcta {
  display: block;
  font-family: var(--font-ui);
  font-weight: var(--wght-ui);
  font-stretch: var(--wdth-ui);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
}
.texp .arrow { transition: transform var(--t); display: inline-block; }
.tchip-link:hover .arrow { transform: translateX(3px); }
/* hover previews are pointer-only furniture */
@media (hover: none) { .texp { display: none !important; } }

/* ---- buying guide ---- */
.guide { max-width: 78ch; padding-block: var(--sp-8) var(--sp-16); }
.guide h3 {
  margin: var(--sp-12) 0 var(--sp-4);
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: 1.1;
  padding-top: var(--sp-6);
  border-top: var(--rule);
}
.guide h3:first-child { margin-top: 0; border-top: 0; padding-top: 0; }
.guide p { margin: 0 0 var(--sp-4); }
.guide strong { font-weight: 500; }
.guide em { font-style: italic; }

.nation-note {
  font-family: var(--font-body);
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--muted);
  margin-top: var(--sp-2);
  max-width: 28ch;
}


/* ============================================================
   PRODUCT PAGE
   ============================================================ */
.crumbs { padding-block: var(--sp-6) 0; }
.crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.crumbs li { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; }
.crumbs li + li::before { content: "/"; margin-right: var(--sp-2); opacity: 0.5; }
.crumbs a { border-bottom: 1px solid transparent; transition: border-color var(--t); }
.crumbs a:hover { border-bottom-color: var(--muted); }

.pdp { display: grid; grid-template-columns: 1.15fr 1fr; gap: clamp(1.5rem, 4vw, 4rem); padding-block: var(--sp-8) var(--sp-16); }

.shot { position: relative; margin: 0; aspect-ratio: 1/1; background: var(--base); border: var(--rule); overflow: hidden; }
.shot img { width: 100%; height: 100%; object-fit: contain; }   /* specimen shots: never crop the shirt */
.shot figcaption { position: absolute; left: var(--sp-3); bottom: var(--sp-3); font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: var(--tr-wide); color: var(--muted); text-transform: uppercase; background: var(--base); padding: 2px 6px; }
.shot-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-3); margin-top: var(--sp-3); }

.pdp-buy .ref { display: block; margin-bottom: var(--sp-3); }
.pdp-buy h1 { font-size: clamp(1.75rem, 3.4vw, 2.75rem); margin: 0 0 var(--sp-4); }
.pdp-standfirst { margin: 0 0 var(--sp-6); color: var(--muted); max-width: 46ch; }
.pdp-price { display: flex; align-items: baseline; gap: var(--sp-3); margin: 0 0 var(--sp-8); flex-wrap: wrap; }
.pdp-price .now { font-family: var(--font-mono); font-size: 1.5rem; color: var(--accent); }
.pdp-price .was { font-family: var(--font-mono); font-size: 1rem; color: var(--muted); text-decoration: line-through; }
.pdp-price .save { color: var(--muted); }

.opt { border: 0; padding: 0; margin: 0 0 var(--sp-6); }
.opt-label { display: flex; justify-content: space-between; width: 100%; padding: 0 0 var(--sp-3); font-family: var(--font-mono); font-size: var(--fs-mono); text-transform: uppercase; letter-spacing: 0.1em; }
.opt-aside { color: var(--muted); text-transform: none; letter-spacing: 0; }
.opt-note { margin: var(--sp-3) 0 0; font-family: var(--font-mono); font-size: var(--fs-micro); line-height: 1.7; color: var(--muted); max-width: 52ch; }
.swatches { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.swatches label { cursor: pointer; }
.swatches input { position: absolute; opacity: 0; width: 0; height: 0; }
.swatches span { display: inline-flex; align-items: center; justify-content: center; min-width: 48px; padding: var(--sp-2) var(--sp-4); border: var(--rule-ink); border-radius: var(--radius); font-family: var(--font-mono); font-size: var(--fs-mono); transition: background var(--t), color var(--t); }
.swatches input:checked + span { background: var(--ink); color: var(--base); }
.swatches input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
.swatches .is-out span { color: var(--muted); border-color: var(--rule-c); text-decoration: line-through; cursor: not-allowed; }

.stock { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-4); font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--green); }
.stock .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); }
.btn-buy { width: 100%; padding: var(--sp-4); background: var(--ink); color: var(--base); border-radius: var(--radius); font-family: var(--font-mono); font-size: var(--fs-body); text-transform: uppercase; letter-spacing: 0.1em; transition: background var(--t); }
.btn-buy:hover { background: var(--accent); }
.pay { margin: var(--sp-3) 0 0; color: var(--muted); font-size: var(--fs-micro); }

.pdp-acc { margin-top: var(--sp-8); border-top: var(--rule-ink); }
.pdp-acc details { border-bottom: var(--rule); }
.pdp-acc summary { list-style: none; cursor: pointer; padding: var(--sp-4) var(--sp-8) var(--sp-4) 0; position: relative; font-family: var(--font-mono); font-size: var(--fs-mono); text-transform: uppercase; letter-spacing: 0.08em; }
.pdp-acc summary::-webkit-details-marker { display: none; }
.pdp-acc summary::after { content: "+"; position: absolute; right: 0; top: 50%; transform: translateY(-50%); color: var(--accent); font-size: 1.1rem; }
.pdp-acc details[open] summary::after { content: "−"; }
.pdp-acc p { margin: 0 0 var(--sp-4); font-size: 0.9375rem; color: var(--muted); }

.spec { width: 100%; border-collapse: collapse; margin-bottom: var(--sp-4); font-family: var(--font-mono); font-size: var(--fs-mono); }
.spec th, .spec td { text-align: left; padding: var(--sp-2) var(--sp-4) var(--sp-2) 0; border-bottom: var(--rule); }
.spec th { color: var(--muted); font-weight: 400; white-space: nowrap; }

.pdp-long { max-width: 74ch; padding-bottom: var(--sp-16); }
.pdp-long h2 { font-size: 1.5rem; margin: var(--sp-12) 0 var(--sp-4); padding-top: var(--sp-6); border-top: var(--rule); }
.pdp-long h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.pdp-long p { margin: 0 0 var(--sp-4); }


/* ============================================================
   LEGAL / TRUST PAGES
   ============================================================ */
.legal { max-width: 74ch; padding-block: var(--sp-8) var(--sp-16); }
.legal h1 { font-size: clamp(1.875rem, 4vw, 3rem); margin: 0 0 var(--sp-4); }
.legal-standfirst { font-size: 1.1875rem; line-height: 1.6; margin: 0 0 var(--sp-3); max-width: 56ch; }
.legal-updated { color: var(--muted); margin: 0 0 var(--sp-12); }
.legal h2 {
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: 1.375rem;
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  line-height: 1.1;
  margin: var(--sp-12) 0 var(--sp-4);
  padding-top: var(--sp-6);
  border-top: var(--rule);
}
.legal p { margin: 0 0 var(--sp-4); }
.legal a { border-bottom: 1px solid var(--rule-c); transition: border-color var(--t); }
.legal a:hover { border-bottom-color: var(--ink); }
.legal .spec { margin-bottom: var(--sp-6); }
.legal .spec td { vertical-align: top; }

/* ---- size tables ------------------------------------------------
   .spec is a two-column key/value table; a size chart is 7-8 equal
   columns of numbers. Left as .spec the label column ate the width
   and every figure wrapped mid-range ("73-" / "75"). Fixed layout
   with an even split, and the table scrolls in its own box on
   narrow screens rather than pushing the page sideways. */
.size-table { overflow-x: auto; margin-bottom: var(--sp-8); }
.spec--size {
  table-layout: fixed;
  min-width: 46rem;
  margin-bottom: 0;
}
.spec--size th, .spec--size td {
  padding: var(--sp-2) var(--sp-3);
  text-align: center;
  white-space: nowrap;
  border-bottom: var(--rule);
}
.spec--size tr > :first-child {       /* the row label */
  text-align: left;
  width: 8.5rem;
  color: var(--muted);
  padding-left: 0;
}
.spec--size tr:first-child th { color: var(--ink); font-weight: 600; }
.spec--size tr:nth-child(even) { background: var(--base-warm); }

/* the size guide's own intro band: .legal is a left-aligned max-width
   column, so the 50vw bleed lands off-centre. Contained instead. */
.legal .band { margin-block: var(--sp-8) var(--sp-12); }

.steps { margin: 0 0 var(--sp-6); padding-left: 0; list-style: none; counter-reset: s; }
.steps li {
  counter-increment: s;
  position: relative;
  padding-left: var(--sp-8);
  margin-bottom: var(--sp-3);
}
.steps li::before {
  content: counter(s);
  position: absolute; left: 0; top: 2px;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  width: 20px; height: 20px;
  display: grid; place-items: center;
}

/* placeholder callouts - loud on purpose, must not ship */
.callout {
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  padding: var(--sp-4);
  margin: 0 0 var(--sp-6);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.callout p { margin: 0; color: var(--ink); font-size: var(--fs-mono); line-height: 1.7; }

.footer-legal { margin: var(--sp-3) 0 0; font-size: var(--fs-micro); color: var(--muted); }


/* ============================================================
   HUB PAGES
   ============================================================ */
.hub-head { padding-block: var(--sp-8) var(--sp-6); border-bottom: var(--rule-ink); }
.hub-head h1 { font-size: clamp(2rem, 4.6vw, 3.5rem); margin: 0 0 var(--sp-4); }
.hub-standfirst { margin: 0; font-size: 1.1875rem; line-height: 1.6; color: var(--muted); max-width: 60ch; }

/* personalisation promise - player pages, always above the first grid */
.print-banner {
  margin: var(--sp-6) 0 0;
  padding: var(--sp-4) var(--sp-6);
  background: var(--base-warm);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  max-width: 74ch;
}
.print-banner-kicker {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
}
.print-banner p { margin: 0; color: var(--ink); line-height: var(--lh-body); }
.print-banner a { color: var(--ink); }

/* ---- shirt banner behind the hub headline ----------------------
   The banner art is a fixed dark graphic, so its text stays light in
   both themes - panel-fg, the same token the homepage hero panel uses.
   The image is anchored right: as the viewport narrows the newest shirt
   and the crest stay in view while the empty left third is what gets
   cropped away, and the scrim widens to keep the headline legible. */
.hub-head--banner {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: clamp(190px, 23vw, 320px);
  padding: var(--sp-8) clamp(var(--sp-4), 3.5vw, var(--sp-12));
  margin-block: var(--sp-6);
  border-bottom: 0;
  border-radius: var(--radius);
  overflow: hidden;
}
.hub-banner {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: right center;
}
.hub-head--banner::before {           /* keeps the headline off the shirts */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, var(--panel-bg) 0%,
                              var(--panel-bg) 26%, transparent 64%);
}
/* between desktop and phone the image crops inward and the first shirt
   drifts under the headline, so the scrim has to grow with it */
@media (max-width: 1100px) {
  .hub-head--banner::before {
    background: linear-gradient(90deg, var(--panel-bg) 0%,
                                var(--panel-bg) 40%, transparent 82%);
  }
}

/* the banner H1 is a long keyword string ("Retro & Current X Football Shirts &
   Kits - Men's, Women's and Kids Jerseys"), so it is set much smaller than a
   normal page H1 and given a wider measure. At the old size it wrapped to six
   lines, stretched the banner box and made the image zoom past all four shirts. */
.hub-head-inner { max-width: 44ch; }
.hub-head--banner h1 {
  color: var(--panel-fg);
  font-size: clamp(1.35rem, 2.3vw, 2.15rem);
  margin-bottom: var(--sp-4);
  text-wrap: balance;
}
.hub-head--banner .hub-standfirst {
  color: var(--panel-fg);
  opacity: 0.82;
  font-size: 1rem;
  max-width: 52ch;
}


/* ---- dense product grid + facets (club hubs) ---- */
.grid--dense { grid-template-columns: repeat(6, 1fr); padding-bottom: var(--sp-12); }
.grid--dense .card { padding: var(--sp-3) var(--sp-3) var(--sp-6); }
.grid-note { margin: var(--sp-3) 0 var(--sp-6); font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--muted); max-width: 70ch; }
.tag { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--accent); letter-spacing: 0.06em; }

.facets { display: flex; flex-direction: column; gap: var(--sp-3); padding-block: var(--sp-6); border-bottom: var(--rule); margin-bottom: var(--sp-8); }
.facet { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2); }
.facet-label { font-family: var(--font-mono); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--tr-wide); color: var(--muted); min-width: 56px; }
.facet a { font-family: var(--font-mono); font-size: var(--fs-mono); padding: 2px var(--sp-3); border: var(--rule); border-radius: var(--radius); transition: background var(--t), color var(--t); }
.facet a:hover { background: var(--ink); color: var(--base); border-color: var(--ink); }

.lead h2 { font-family: var(--font-display); font-weight: var(--wght-display); font-stretch: var(--wdth-display); font-size: 1.5rem; text-transform: uppercase; letter-spacing: var(--tr-tight); line-height: 1.1; margin: 0 0 var(--sp-4); padding-top: var(--sp-6); border-top: var(--rule); }

@media (max-width: 1200px) { .grid--dense { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 760px)  { .grid--dense { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 480px)  { .grid--dense { grid-template-columns: repeat(2, 1fr); } }


/* ---- collapsed intro copy (CFS 'Read More' pattern) ---- */
.readmore { max-width: 78ch; padding-block: var(--sp-4) var(--sp-8); }
h2.readmore-sub {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-body);   /* strapline, not a display heading */
  font-size: var(--fs-body);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}
.readmore-body { position: relative; overflow: hidden; }
.readmore:not(.open) .readmore-body { max-height: 3.2em; }   /* line 1 crisp, line 2 fading */
.readmore:not(.open) .readmore-body::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1.8em;
  background: linear-gradient(to bottom, transparent, var(--base));  /* CFS-style fade into page */
}
.readmore-body p { margin: 0 0 var(--sp-4); }
.readmore-btn {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.06em;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: var(--sp-1) 0 0;
  transition: color var(--t);
}
.readmore-btn:hover { color: var(--accent); }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1200px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .card:nth-child(3n+1) { border-left: 0; padding-left: 0; }
  .card:nth-child(n+4) { padding-top: var(--sp-8); }
  .card:last-child { padding-right: var(--sp-4); }
}

@media (max-width: 900px) {
  .header { flex-wrap: wrap; gap: var(--sp-4); }
  .nav-toggle { display: flex; order: 3; margin-left: auto; }
  .utils { order: 2; margin-left: auto; }
  .nav {
    order: 4;
    width: 100%;
    margin: 0;
    display: none;
    flex-direction: column;
    /* the desktop nav wraps; a vertical mobile panel must NOT. With a capped
       height (max-height:76vh below) flex-wrap:wrap spilled an opened dropdown
       into a second column off the right edge - the whole reason a tapped group
       rendered off-screen on phones. Stack and scroll instead. */
    flex-wrap: nowrap;
    gap: var(--sp-3);
    padding-top: var(--sp-4);
    border-top: var(--rule);
  }
  .nav.open { display: flex; }

  .hero,
  .hero-slide { grid-template-columns: 1fr; }
  .hero-media { min-height: 58vw; order: -1; }
  /* on the stacked layout the controls would sit over the panel copy,
     so they move up onto the image instead */
  .hero-controls { bottom: auto; top: calc(58vw - 3.5rem); }

  .trust { grid-template-columns: repeat(2, 1fr); }
  .trust-item { padding: var(--sp-6) var(--sp-4); border-left: var(--rule); border-top: var(--rule); }
  .trust-item:nth-child(2n+1) { border-left: 0; padding-left: 0; }
  .trust-item:nth-child(-n+2) { border-top: 0; }

  .footer-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
  .card { padding-inline: var(--sp-3); }
  .card:nth-child(3n+1) { border-left: var(--rule); padding-left: var(--sp-3); }
  .card:nth-child(2n+1) { border-left: 0; padding-left: 0; }
  .card:nth-child(n+3) { padding-top: var(--sp-6); }
  .trust { grid-template-columns: 1fr; }
  /* A bare `.trust-item` (0,1,0) LOSES to two rules above it:
     `.trust-item:not(:first-child)` sets padding-left, and the 2-column
     `.trust-item:nth-child(-n+2)` clears border-top. Both are (0,2,0), so in
     one column items 2 and 4 kept a 32px indent and item 2 kept no divider -
     the icons stepped in and out and the rules were uneven. These selectors
     match that specificity so the single-column layout actually wins. */
  .trust-item,
  .trust-item:not(:first-child),
  .trust-item:nth-child(2n+1) { border-left: 0; padding-inline: 0; }
  .trust-item:not(:first-child) { border-top: var(--rule); }
  .trust-item:first-child { border-top: 0; }
  .footer-grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

@media (max-width: 1100px) {
  .prov { grid-template-columns: repeat(2, 1fr); }
  .nations { grid-template-columns: repeat(3, 1fr); }
  .nation:nth-child(3n+1) { border-left: 0; padding-left: 0; }
  .nation:nth-child(n+4) { border-top: var(--rule); }
  .journal { grid-template-columns: 1fr; }
  .post { border-left: 0; padding-left: 0 !important; padding-top: var(--sp-6); border-top: var(--rule); }
  .post:first-child { border-top: 0; }
}

@media (max-width: 640px) {
  .prov { grid-template-columns: 1fr; gap: var(--sp-6); }
  .nations { grid-template-columns: 1fr; }
  .nation { border-left: 0 !important; padding-left: 0 !important; border-top: var(--rule); padding-block: var(--sp-6); }
  .nation:first-child { border-top: 0; }
  .head-note { display: none; }
}

@media (max-width: 1100px) {
  .types { grid-template-columns: repeat(2, 1fr); }
  .type:nth-child(2n+1) { border-left: 0; padding-left: 0; }
  .type:nth-child(n+3) { border-top: var(--rule); }
}
@media (max-width: 640px) {
  .types { grid-template-columns: 1fr; }
  .type { border-left: 0 !important; padding-left: 0 !important; border-top: var(--rule); padding-block: var(--sp-6); }
  .type:first-child { border-top: 0; }
}

@media (max-width: 900px) {
  .pdp { grid-template-columns: 1fr; }
  .shot-row { grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 560px) {
  .shot-row { grid-template-columns: repeat(2, 1fr); }
  .swatches span { min-width: 42px; padding: var(--sp-2) var(--sp-3); }
}

/* hub standfirst on mobile: VISIBLE (2026-09-19). It was display:none here
   with the H2 strapline + read-more standing in for it - but the standfirst is
   the researched hub copy, Google indexes the mobile render, and hidden copy
   is copy Google discounts (the 2026-09-10 note below on .grid-note says the
   same). The .hub-head--banner rules below keep it legible over the art. */
@media (max-width: 640px) {
  .hub-head { padding-bottom: var(--sp-4); }
  /* narrow viewport: the shirts are mostly cropped out, so the scrim covers
     more of what is left rather than letting type sit over a shirt */
  .hub-head--banner { min-height: 160px; padding-block: var(--sp-6); }
  .hub-head--banner::before {
    background: linear-gradient(90deg, var(--panel-bg) 0%,
                                var(--panel-bg) 46%, transparent 92%);
  }
}

/* ============================================================
   PRODUCT LISTING
   ============================================================ */
.pdp {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: var(--sp-12);
  padding-block: var(--sp-8) var(--sp-12);
  align-items: start;
}
.pdp-media {
  background: var(--base-warm);
  border: var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.pdp-media img { display: block; width: 100%; height: auto; }

/* --- tag row: colour-coded by family, never by individual tag --- */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-4);
  padding: 0;
  list-style: none;
}
/* ---- tag chips -------------------------------------------------
   Solid blocks, square corners, heavy uppercase - a stamped index
   label, not an outlined pill. Each family owns a colour; the team
   chip overrides --chip-bg/--chip-fg inline with the club's own
   colour (make-team-colours.py), always paired with a text colour
   that clears 4.5:1 against it. The dot is gone: on a filled chip
   it read as a bullet rather than a marker. */
.tag-chip {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  padding: 0.28em 0.62em;
  border: 0;
  border-radius: 0;                       /* square, per the house rule */
  white-space: nowrap;
  text-decoration: none;
  background: var(--chip-bg, var(--ink));
  color: var(--chip-fg, var(--base));
  transition: filter var(--t), transform var(--t);
}
.tag-chip span { color: inherit; }

/* Only the TEAM chip carries colour. Five filled colours fought each other
   and broke the one-accent-per-screen rule in brand.md; with the rest neutral
   the club colour is the single thing the eye lands on, and it happens to be
   the only chip that is a link. Border is drawn inside the existing padding so
   neutral and coloured chips stay exactly the same height. */
.tag-chip:not(.tag-team) {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--rule-c);
  padding: calc(0.28em - 1px) calc(0.62em - 1px);
}
.tag-team { --chip-bg: var(--tag-team); --chip-fg: var(--base); }

a.tag-chip:hover { filter: brightness(1.12); transform: translateY(-1px); }
a.tag-chip:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  a.tag-chip:hover { transform: none; }
}

.pdp h1 { font-size: clamp(1.75rem, 3.4vw, 2.75rem); margin: 0 0 var(--sp-4); }
.pdp-price {
  font-family: var(--font-mono);
  font-size: 1.5rem;
  margin: 0 0 var(--sp-2);
}
.pdp-stock {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--green);
  margin: 0 0 var(--sp-6);
}
.pdp-desc { max-width: 62ch; }
.pdp-desc p { margin: 0 0 var(--sp-4); }

/* spec table — the "info & sizing" block */
.spec {
  width: 100%;
  border-collapse: collapse;
  margin: var(--sp-6) 0;
  font-size: var(--fs-body);
}
.spec th, .spec td {
  text-align: left;
  padding: var(--sp-2) 0;
  border-bottom: var(--rule);
  vertical-align: top;
}
.spec th {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  color: var(--muted);
  width: 40%;
}

@media (max-width: 860px) {
  .pdp { grid-template-columns: 1fr; gap: var(--sp-8); }
}

/* listing prose: section headings - editorial, same voice as the H1 */
.pdp-desc h2 {
  margin: var(--sp-8) 0 var(--sp-3);
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: 1.375rem;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
  color: var(--ink);
}
.pdp-desc h3 {
  margin: var(--sp-4) 0 var(--sp-1);
  font-size: var(--fs-body);
  font-weight: 600;
}
/* internal links in prose must read as links */
.pdp-desc a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.pdp-desc a:hover { text-decoration: none; }

/* collapsible info sections, CFS-style */
.pdp-acc {
  border-top: var(--rule-ink);
}
.pdp-acc:last-of-type { border-bottom: var(--rule-ink); }
.pdp-acc summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-4) 0;
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: 1.375rem;
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
}
.pdp-acc summary::-webkit-details-marker { display: none; }
.pdp-acc summary::after {
  content: "";
  width: 9px; height: 9px;
  border-right: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: rotate(45deg);
  transition: transform var(--t);
  flex: 0 0 auto;
  margin-left: var(--sp-4);
}
.pdp-acc[open] summary::after { transform: rotate(-135deg); }
.pdp-acc > div { padding-bottom: var(--sp-6); }

/* ---- buy panel ---- */
.buy {
  border: var(--rule-ink);
  border-radius: var(--radius);
  padding: var(--sp-6);
  margin: var(--sp-6) 0;
}
.buy-label {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  color: var(--muted);
  margin: 0 0 var(--sp-2);
}
.sizes-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.size-btn {
  min-width: 44px;
  padding: var(--sp-2) var(--sp-3);
  border: var(--rule);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  background: none;
  transition: background var(--t), border-color var(--t);
}
.size-btn:hover { border-color: var(--ink); }
.size-btn.sel { background: var(--ink); color: var(--base); border-color: var(--ink); }
.print-row { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.print-fields { display: none; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.print-fields.open { display: flex; }
.print-fields input {
  border: var(--rule);
  border-radius: var(--radius);
  background: var(--base);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  padding: var(--sp-2) var(--sp-3);
  text-transform: uppercase;
}
.print-fields .f-name { flex: 1; min-width: 0; }
.print-fields .f-num { width: 72px; text-align: center; }
.buy-cta {
  width: 100%;
  padding: var(--sp-3);
  background: var(--ink);
  color: var(--base);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  transition: background var(--t);
}
.buy-cta:hover { background: var(--deep); }
.buy-note {
  margin: var(--sp-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--muted);
  text-align: center;
}
.pdp-desc h2:first-child { margin-top: 0; }
.pdp-terms {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--muted);
}

/* sitewide offer strip */
.offer-strip {
  background: var(--accent);
  color: var(--base);
  text-align: center;
  padding: var(--sp-2) var(--gutter);
  font-family: var(--font-ui);
  font-weight: var(--wght-ui);
  font-stretch: var(--wdth-ui);
  font-size: var(--fs-micro);
  letter-spacing: 0.09em;
}


/* ============================================================
   NAV DROPDOWNS + SEARCH
   ============================================================ */
.nav-dd { position: relative; display: inline-flex; }
.nav-dd > a { display: inline-flex; align-items: center; gap: 5px; }
.dd-caret { width: 9px; height: 6px; stroke: currentColor; fill: none; stroke-width: 1.6; }
.dd-menu {
  position: absolute;
  top: 100%; left: 50%;
  transform: translateX(-50%) translateY(6px);
  min-width: 210px;
  margin: 0; padding: var(--sp-2) 0;
  list-style: none;
  background: var(--base);
  border: var(--rule-ink);
  border-radius: var(--radius);
  opacity: 0; visibility: hidden;
  transition: opacity var(--t), transform var(--t), visibility var(--t);
  z-index: 200;
}
.nav-dd:hover .dd-menu, .nav-dd:focus-within .dd-menu {
  opacity: 1; visibility: visible;
  transform: translateX(-50%) translateY(0);
}
.dd-menu li a {
  display: block;
  padding: var(--sp-2) var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.dd-menu li a:hover { background: var(--base-warm); }
.dd-rule { border-top: var(--rule); margin: var(--sp-2) 0; }

.search { position: relative; display: flex; align-items: center; gap: var(--sp-2); }
.search .icon { flex: 0 0 auto; }
/* pre-existing header overflow in the 900-1150px window (seen at 1024:
   64px of horizontal scroll on every page): the header's gap + search field
   didn't tighten between the desktop layout and the 900px hamburger
   breakpoint. Tighten both in that window only. */
@media (min-width: 901px) and (max-width: 1150px) {
  .header { gap: var(--sp-4); }
  .nav { gap: clamp(0.6rem, 1.4vw, 1.1rem); }
  .search input { width: 110px; }
}

.search input {
  width: clamp(110px, 14vw, 200px);
  border: 0; border-bottom: var(--rule);
  background: none; color: var(--ink);
  font-family: var(--font-mono); font-size: var(--fs-mono);
  padding: var(--sp-1) 0;
  outline: none;
  transition: border-color var(--t);
}
.search input:focus { border-bottom-color: var(--ink); }
.search-results {
  position: absolute;
  top: 100%; right: 0;
  width: 330px; max-height: 380px; overflow-y: auto;
  margin: var(--sp-2) 0 0; padding: var(--sp-2) 0;
  list-style: none;
  background: var(--base);
  border: var(--rule-ink);
  border-radius: var(--radius);
  z-index: 300;
}
.search-results li a {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  font-family: var(--font-mono); font-size: var(--fs-mono);
}
.search-results li a:hover { background: var(--base-warm); }
.search-results li a span { color: var(--muted); }
.search-results .none { padding: var(--sp-2) var(--sp-4); color: var(--muted);
  font-family: var(--font-mono); font-size: var(--fs-mono); }

@media (max-width: 900px) {
  .dd-menu { display: none; }   /* mobile: top-level links only */
  .search input { width: 90px; }
}

/* players index chips with counts */
.chips--players a { display: inline-flex; gap: var(--sp-2); align-items: baseline; }

/* ============================================================
   COLLECTION PAGES: filter sidebar + shop grid
   ============================================================ */
.shop-layout {
  display: grid;
  grid-template-columns: 230px minmax(0, 1fr);
  gap: var(--sp-8);
  align-items: start;
  padding-bottom: var(--sp-16);
}
.filters { position: sticky; top: 96px; }
.facet { display: block; width: 100%; border-top: var(--rule-ink); }
.facet:last-child { border-bottom: var(--rule-ink); }
.facet summary {
  cursor: pointer;
  list-style: none;
  display: flex; width: 100%;
  justify-content: space-between; align-items: center;
  padding: var(--sp-3) 0;
  font-family: var(--font-display);
  font-weight: var(--wght-display);
  font-stretch: var(--wdth-display);
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: var(--tr-tight);
}
.facet summary::-webkit-details-marker { display: none; }
.facet summary::after {
  content: "";
  flex: 0 0 auto;
  width: 7px; height: 7px;
  border-right: 1.6px solid var(--ink);
  border-bottom: 1.6px solid var(--ink);
  transform: rotate(45deg);
  transition: transform var(--t);
}
.facet[open] summary::after { transform: rotate(-135deg); }
.facet-body {
  display: block;
  width: 100%;
  padding: 0 0 var(--sp-4);
  max-height: 300px;
  overflow-y: auto;
}
.facet-body label {
  display: grid;
  grid-template-columns: 15px minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--sp-2);
  width: 100%;
  padding: 3px 0;
  font-family: var(--font-mono); font-size: var(--fs-mono);
  cursor: pointer;
}
.facet-body input { width: 15px; height: 15px; margin: 0; accent-color: var(--accent); }
.facet-body .f-name {
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.facet-body .f-n {
  justify-self: end;
  color: var(--muted); font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums;
}
.shop-bar {
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: var(--sp-4);
}
.sort-sel {
  border: var(--rule); border-radius: var(--radius);
  background: var(--base); color: var(--ink);
  font-family: var(--font-mono); font-size: var(--fs-mono);
  padding: var(--sp-1) var(--sp-2);
}
.grid--shop { grid-template-columns: repeat(4, 1fr); row-gap: var(--sp-8); }
.grid--shop .card:first-child { border-left: var(--rule); padding-left: var(--sp-4); }

/* Desktop keeps the open sidebar; the toggle is a phone-only control. */
.filters-btn { display: none; }

@media (max-width: 1100px) { .grid--shop { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 900px) {
  .shop-layout { grid-template-columns: 1fr; }
  .filters { position: static; }
  /* The stacked sidebar put ~50 checkboxes between the search box and the
     first shirt. Search stays visible; the facets go behind the toggle. */
  .filters-btn {
    display: flex; align-items: center; gap: var(--sp-2);
    width: 100%; margin-top: var(--sp-3);
    padding: var(--sp-3);
    background: var(--base); color: var(--ink);
    border: var(--rule-ink); border-radius: var(--radius);
    font-family: var(--font-display);
    font-weight: var(--wght-display);
    font-stretch: var(--wdth-display);
    font-size: 1rem; text-transform: uppercase;
    letter-spacing: var(--tr-tight);
    cursor: pointer;
  }
  .filters-btn::after {
    content: "";
    flex: 0 0 auto; margin-left: auto;
    width: 7px; height: 7px;
    border-right: 1.6px solid var(--ink);
    border-bottom: 1.6px solid var(--ink);
    transform: rotate(45deg);
    transition: transform var(--t);
  }
  .filters-open .filters-btn::after { transform: rotate(-135deg); }
  .filters-btn-n {
    display: inline-block; min-width: 1.4em;
    padding: 1px var(--sp-1);
    background: var(--accent); color: var(--base);
    border-radius: var(--radius);
    font-family: var(--font-mono); font-size: var(--fs-micro);
    font-variant-numeric: tabular-nums; text-align: center;
  }
  /* an author `display` beats the UA [hidden] rule regardless of specificity */
  .filters-btn-n[hidden] { display: none; }
  .facet-stack { display: none; margin-top: var(--sp-4); }
  .filters-open .facet-stack { display: block; }
  /* Room is not scarce once the stack is opened deliberately - the inner
     300px scroller inside a page scroller is the worst part on touch. */
  .facet-body { max-height: none; overflow-y: visible; }
}
@media (max-width: 620px) { .grid--shop { grid-template-columns: repeat(2, 1fr); } }


/* mega dropdown: league-grouped clubs */
.dd-menu--mega {
  column-count: 2;
  column-gap: var(--sp-6);
  min-width: 430px;
  padding: var(--sp-4) var(--sp-4);
}
.dd-menu--mega li { break-inside: avoid; }
.dd-head {
  font-family: var(--font-ui);
  font-weight: var(--wght-ui);
  font-stretch: var(--wdth-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
  padding: var(--sp-3) var(--sp-4) var(--sp-1);
}
.dd-menu--mega .dd-head:first-child { padding-top: 0; }


/* ============================================================
   HERO: retro-TV hover - hovered shirt stays colour, rest goes
   old-television black & white. Colour window = clip-path on a
   duplicate image; scanlines + vignette + faint flicker overlay.
   ============================================================ */
.hero-base { transition: filter 300ms ease; }
.hero-media.tv .hero-base {
  filter: grayscale(1) contrast(1.18) brightness(0.82) sepia(0.1);
}
.hero-cut {
  position: absolute !important;
  inset: auto;
  height: auto;
  object-fit: fill;
  opacity: 0;
  pointer-events: none;
  transition: opacity 250ms ease;
  z-index: 2;
}
.hero-media.tv .hero-cut.on { opacity: 1; }
.hero-scan {
  position: absolute; inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity 300ms ease;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0)   0px,
      rgba(0, 0, 0, 0)   2px,
      rgba(0, 0, 0, 0.14) 3px,
      rgba(0, 0, 0, 0)   4px),
    radial-gradient(ellipse at center,
      rgba(0, 0, 0, 0) 55%,
      rgba(0, 0, 0, 0.32) 100%);
}
.hero-media.tv .hero-scan { opacity: 1; animation: tv-flicker 2.4s steps(2) infinite; }
@keyframes tv-flicker {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.88; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-media.tv .hero-scan { animation: none; }
}
.hero-spot {
  position: absolute;
  z-index: 4;
  border-radius: 12px;
  cursor: pointer;
}
.hero-spot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* mobile hero: image-led, compact panel */
@media (max-width: 900px) {
  .hero-carousel,
  .hero-track,
  .hero-slide {
    min-height: calc(100svh - 57px);
  }
  .hero-slide:not(:first-child),
  .hero-controls { display: none; }
  /* Mobile is intentionally a single, image-led landing panel. Keep the
     first slide painted even if a stray pointer/swipe event reaches the
     desktop carousel controller after a tap outside the banner. */
  .hero-slide:first-child {
    visibility: visible !important;
    opacity: 1 !important;
    transition: none !important;
  }
  .hero-slide {
    position: relative;
    display: block;
    aspect-ratio: auto;
  }
  .hero-media {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    min-height: 0;
    aspect-ratio: auto;
  }
  .hero-base-desktop { display: none; }
  .hero-media > .hero-base-mobile {
    display: block;
    object-position: center 34%;
  }
  .hero-media .hero-cut,
  .hero-media .hero-card,
  .hero-media .hero-spot { display: none; }
  .mobile-hero-shop {
    display: flex;
    position: absolute;
    z-index: 9;
    inset: auto 0 0;
    min-height: 43%;
    padding: 5rem 0 max(0.75rem, env(safe-area-inset-bottom));
    flex-direction: column;
    justify-content: flex-end;
    /* One long, blended fade keeps the artwork and the card rail feeling
       like a single surface rather than two stacked sections. */
    background:
      radial-gradient(ellipse at 18% 82%, rgba(228, 87, 46, 0.24) 0%, rgba(228, 87, 46, 0) 54%),
      linear-gradient(180deg, rgba(20, 17, 15, 0) 0%, rgba(20, 17, 15, 0.05) 18%, rgba(20, 17, 15, 0.24) 36%, rgba(20, 17, 15, 0.64) 59%, var(--panel-bg) 91%, var(--panel-bg) 100%);
  }
  .hero-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    position: absolute;
    z-index: 10;
    inset: auto clamp(1rem, 7vw, 2rem) clamp(312px, 41svh, 355px);
    min-height: 0;
    padding: 0;
    background: none;
    pointer-events: none;
  }
  .hero-panel > :not(.hero-title):not(.mobile-hero-search) { display: none; }
  .hero-panel .hero-title {
    display: block;
    order: 2;
    width: 100%;
    max-width: none;
    margin: 0;
    text-align: center;
    color: var(--panel-fg);
    font-size: clamp(1.55rem, 8vw, 2.3rem);
    line-height: 0.86;
    text-shadow:
      0 2px 2px rgba(20, 17, 15, 0.9),
      0 0 14px rgba(228, 87, 46, 0.78),
      0 0 30px rgba(228, 87, 46, 0.38);
  }
  .hero-panel .mobile-h1-detail {
    display: block;
    width: fit-content;
    margin: 0.42rem auto 0;
    padding: 0.3rem 0.7rem 0.2rem;
    color: var(--ink);
    background: var(--accent);
    border-radius: 3px;
    font-family: var(--font-display);
    font-size: clamp(0.78rem, 3.8vw, 0.98rem);
    font-weight: var(--wght-display);
    font-stretch: var(--wdth-display);
    letter-spacing: var(--tr-tight);
    line-height: 1;
    text-shadow: none;
    box-shadow: 0 0 0 1px rgba(228, 87, 46, 0.7), 0 0 16px rgba(228, 87, 46, 0.72);
  }
  .hero-panel .mobile-hero-search {
    order: 1;
    display: flex;
    position: relative;
    align-items: center;
    justify-content: flex-start;
    gap: 0.4rem;
    width: min(100%, 290px);
    min-height: 46px;
    padding: 0.32rem 0.35rem 0.32rem 0.75rem;
    border: 2px solid var(--accent);
    border-radius: 8px;
    background:
      repeating-linear-gradient(0deg, rgba(20, 17, 15, 0.025) 0 1px, transparent 1px 4px),
      rgba(255, 255, 255, 0.8);
    color: var(--ink);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.95),
      0 0 0 2px rgba(228, 87, 46, 0.28),
      0 0 18px rgba(228, 87, 46, 0.88),
      0 12px 30px rgba(0, 0, 0, 0.62);
    pointer-events: auto;
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
    transition: background 160ms ease, box-shadow 160ms ease, transform 160ms ease;
  }
  .mobile-hero-search .icon { flex: 0 0 auto; width: 21px; height: 21px; stroke-width: 2; color: var(--accent); }
  .mobile-hero-search input {
    width: 100%;
    min-width: 0;
    padding: 0.45rem 0.2rem;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: 0.76rem;
  }
  .mobile-hero-search input::placeholder { color: rgba(20, 17, 15, 0.58); opacity: 1; }
  .mobile-hero-search button {
    flex: 0 0 auto;
    align-self: stretch;
    padding: 0 0.65rem;
    border-radius: 5px;
    background: var(--accent);
    color: var(--ink);
    font-family: var(--font-display);
    font-size: 0.72rem;
    font-weight: var(--wght-display);
    font-stretch: var(--wdth-display);
    letter-spacing: var(--tr-tight);
  }
  .mobile-hero-search:focus-within {
    transform: translateY(-2px);
    background: #fff;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 1),
      0 0 0 3px rgba(228, 87, 46, 0.38),
      0 0 25px rgba(228, 87, 46, 1),
      0 16px 36px rgba(0, 0, 0, 0.7);
  }
  .mobile-hero-results {
    position: absolute;
    z-index: 30;
    top: calc(100% + 0.35rem);
    left: 0;
    right: 0;
    max-height: min(260px, 36svh);
    margin: 0;
    padding: 0.25rem;
    overflow-y: auto;
    list-style: none;
    border: 1px solid var(--accent);
    border-radius: 5px;
    background: #fff;
    box-shadow: 0 0 24px rgba(228, 87, 46, 0.58), 0 16px 30px rgba(0, 0, 0, 0.62);
  }
  .mobile-hero-results[hidden] { display: none; }
  .mobile-hero-results a {
    display: grid;
    grid-template-columns: 42px 1fr auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem;
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: 0.62rem;
  }
  .mobile-hero-results li + li { border-top: 1px solid rgba(20, 17, 15, 0.12); }
  .mobile-hero-results img { width: 42px; height: 42px; object-fit: contain; background: var(--base); }
  .mobile-hero-results strong { color: var(--accent); font-size: 0.66rem; }
  .mobile-hero-results .none { padding: 0.75rem; color: var(--ink); font-family: var(--font-mono); font-size: 0.68rem; }
  .mobile-shirt-rail {
    display: flex;
    gap: 0.75rem;
    width: 100%;
    padding: 2.25rem calc(var(--gutter) + 0.15rem) 0.9rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    overscroll-behavior-inline: contain;
    transform: translateX(0);
    transition: transform 360ms ease;
  }
  .mobile-shirt-rail.is-peeking { transform: translateX(-12px); }
  .mobile-rail-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--gutter);
    color: var(--panel-fg);
    font-family: var(--font-body);
    font-size: 0.58rem;
    font-weight: 800;
    letter-spacing: 0.08em;
  }
  .mobile-rail-status strong {
    color: var(--accent);
    font-size: 0.68rem;
    text-shadow: 0 0 10px rgba(228, 87, 46, 0.72);
  }
  .mobile-shirt-rail::-webkit-scrollbar { display: none; }
  .mobile-shirt {
    position: relative;
    flex: 0 0 min(46vw, 176px);
    padding: 0.5rem 0.5rem 0.6rem;
    scroll-snap-align: start;
    overflow: hidden;
    border: 0;
    border-radius: 12px;
    background: #fff;
    color: var(--ink);
    box-shadow:
      0 0 0 1px rgba(228, 87, 46, 0.85),
      0 0 12px rgba(228, 87, 46, 0.92),
      0 0 34px rgba(228, 87, 46, 0.62),
      0 14px 30px rgba(0, 0, 0, 0.5);
    opacity: 0.86;
    transform: scale(0.96);
    transition: transform 220ms ease, opacity 220ms ease, box-shadow 220ms ease;
    -webkit-tap-highlight-color: transparent;
  }
  .mobile-shirt::before {
    content: none;
  }
  .mobile-shirt:active,
  .mobile-shirt:focus-visible {
    transform: translateY(-5px) scale(1.015);
    border-color: var(--panel-fg);
    box-shadow:
      0 0 0 2px #9f2f17,
      0 0 20px rgba(228, 87, 46, 1),
      0 0 46px rgba(228, 87, 46, 0.88),
      0 18px 34px rgba(0, 0, 0, 0.58);
    outline: none;
  }
  .mobile-shirt.is-current {
    z-index: 2;
    opacity: 1;
    transform: translateY(-5px) scale(1);
    box-shadow:
      0 0 0 1px rgba(228, 87, 46, 0.92),
      0 0 20px rgba(228, 87, 46, 0.96),
      0 0 44px rgba(228, 87, 46, 0.68),
      0 16px 34px rgba(0, 0, 0, 0.56);
  }
  .mobile-shirt-media {
    position: relative;
    overflow: hidden;
    border-radius: 9px;
    background: #fff;
  }
  .mobile-shirt img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: contain;
    border: 0;
    background:
      radial-gradient(circle at 50% 42%, rgba(228, 87, 46, 0.13), transparent 62%),
      #fff;
    transition: transform 240ms ease;
  }
  .mobile-shirt.is-current img { transform: translateY(-3px) scale(1.055); }
  .mobile-shirt-media em {
    position: absolute;
    left: 0.35rem;
    bottom: 0.35rem;
    padding: 0.28rem 0.46rem;
    background: var(--accent);
    color: #fff;
    font-family: var(--font-body);
    font-size: 0.52rem;
    font-style: normal;
    font-weight: 800;
    letter-spacing: 0.01em;
    line-height: 1;
    border-radius: 999px;
    box-shadow: 0 3px 10px rgba(228, 87, 46, 0.38);
  }
  .mobile-shirt > span {
    display: -webkit-box;
    min-height: 2em;
    margin: 0.5rem 0 0.4rem;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    font-family: var(--font-body);
    font-size: clamp(0.75rem, 3.5vw, 0.9rem);
    font-weight: 750;
    line-height: 1.16;
    letter-spacing: -0.02em;
  }
  .mobile-shirt-buy {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.35rem;
  }
  .mobile-shirt-buy b {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.35rem;
    width: 100%;
    min-height: 38px;
    padding: 0.5rem 0.55rem;
    border-radius: 7px;
    background: linear-gradient(135deg, #ef6840 0%, var(--accent) 58%, #d34823 100%);
    color: #fff;
    font-family: var(--font-body);
    font-size: 0.58rem;
    font-weight: 850;
    letter-spacing: -0.01em;
    text-align: left;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.28),
      0 5px 14px rgba(172, 52, 24, 0.35),
      0 0 18px rgba(228, 87, 46, 0.38);
    transition: transform 120ms ease, filter 120ms ease, box-shadow 120ms ease;
  }
  .mobile-shirt:active .mobile-shirt-buy b { transform: translateY(2px); filter: brightness(1.08); box-shadow: 0 2px 8px rgba(172, 52, 24, 0.38); }
  .mobile-add-label { display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap; }
  .mobile-add-label::before {
    content: '+';
    display: grid;
    place-items: center;
    width: 1rem;
    height: 1rem;
    border: 1.5px solid rgba(255, 255, 255, 0.88);
    border-radius: 50%;
    font-size: 0.72rem;
    line-height: 1;
  }
  .mobile-shirt-buy b .money {
    display: inline;
    min-height: 0;
    margin: 0;
    padding: 0;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-transform: none;
    white-space: nowrap;
    padding-left: 0.35rem;
    border-left: 1px solid rgba(255, 255, 255, 0.38);
    font-weight: 900;
  }
  .mobile-hero-down {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    margin: 0 auto;
    border: 1px solid rgba(244, 241, 234, 0.5);
    border-radius: 50%;
    color: var(--panel-fg);
    animation: mobile-hero-bounce 1.7s ease-in-out infinite;
  }
  .hero-title { font-size: clamp(1.7rem, 8vw, 2.4rem); }
  .hero-slash { margin: var(--sp-4) 0; }
  .hero-sub { font-size: 0.8125rem; max-width: none;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden; }
  .hero-ref { font-size: var(--fs-micro); }
}

/* hero panel type scales with the 2.694:1 slide so it always fits the fixed
   panel height - every size proportional to viewport width above 900px */
@media (min-width: 901px) {
  .hero-panel {
    padding: clamp(1rem, 2.4vw, 3.4rem) clamp(1rem, 2vw, 2.8rem);
    justify-content: center;
  }
  .hero-ref { font-size: clamp(0.55rem, 0.75vw, 0.8125rem); margin-bottom: 0.9vw; }
  .hero-title { font-size: clamp(1.45rem, 2.8vw, 4rem); }
  .hero-slash { margin: 1.4vw 0 1.1vw; width: clamp(32px, 3.5vw, 56px); }
  .hero-sub {
    font-size: clamp(0.66rem, 0.92vw, 0.875rem);
    line-height: 1.6;
    margin: 0 0 1.4vw;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .hero-cta { font-size: clamp(0.6rem, 0.8vw, 0.8125rem); }
}


/* hover listing card - full product card: image, title, price.
   Every part explicitly sized so no browser quirk can collapse it. */
.hero-card {
  position: absolute;
  bottom: 4%;
  transform: translate(-50%, 8px);
  display: block;
  width: 158px;
  padding: var(--sp-2);
  background: var(--base);
  color: var(--ink);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
  text-align: left;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease;
  z-index: 6;
}
.hero-card.on { opacity: 1; transform: translate(-50%, 0); }
.hc-media {
  display: block;
  height: 92px;
  background: var(--base-warm);
  border-radius: var(--radius);
  margin-bottom: var(--sp-2);
}
.hc-media img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
}
/* typography mirrors the site's product cards (.card h3 / .card .price),
   with the accent price kept per the owner's call */
.hc-name {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  line-height: 1.4;
  white-space: normal;
  max-height: 2.9em;
  overflow: hidden;
}
.hc-price {
  display: block;
  margin-top: var(--sp-1);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--accent);
}

/* ---- real product gallery ---- */
.pdp-media--real { background: var(--base-warm); border: var(--rule); border-radius: var(--radius); padding: var(--sp-3); }
.pdp-media--real #pdpMain { width: 100%; height: auto; border-radius: var(--radius); background: var(--base); }
.pdp-thumbs { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.pdp-thumb { padding: 0; border: 1px solid var(--rule-c); border-radius: var(--radius); background: var(--base); cursor: pointer; width: 64px; height: 64px; overflow: hidden; }
.pdp-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pdp-thumb.sel { border-color: var(--accent); }
.pdp-thumb:hover { border-color: var(--ink); }

/* ============================================================
   CARD V2 — editorial card test (2026-08-05, England hub only
   until the owner signs off). Font via --font-card in tokens.
   ============================================================ */
.card--v2 { transition: transform var(--t), box-shadow var(--t); }
.card--v2:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 30px rgba(20, 17, 15, 0.13);
}
.card--v2 .card-media { position: relative; overflow: hidden; }
.card--v2 .card-media img { transition: transform 600ms ease; }
.card--v2:hover .card-media img { transform: scale(1.045); }
/* Best-seller cards: tactile cream stock, a hot orange edge and a gentle
   lift make the product grid feel shoppable rather than archival-flat. */
.grid--wanted .card--v2 {
  position: relative;
  overflow: hidden;
  background: linear-gradient(145deg, #fffdf7 0%, #f5eee2 100%);
  border: 0;
  border-radius: 12px;
  box-shadow: 0 8px 22px rgba(20, 17, 15, 0.13), 0 0 0 1px rgba(228, 87, 46, 0.14);
  transition: transform 220ms ease, box-shadow 220ms ease;
}
.grid--wanted .card--v2::before {
  content: "";
  position: absolute;
  z-index: 3;
  inset: 0 0 auto;
  height: 4px;
  background: linear-gradient(90deg, var(--accent), #ffb15e, var(--accent));
}
.grid--wanted .card--v2:hover {
  transform: translateY(-6px);
  box-shadow: 0 16px 30px rgba(20, 17, 15, 0.2), 0 0 22px rgba(228, 87, 46, 0.3);
}
.grid--wanted .card--v2 > a { display: block; padding: 0.7rem; }
.grid--wanted .card--v2 .ref { color: rgba(20, 17, 15, 0.58); }
.grid--wanted .card--v2 .card-media {
  margin-top: 0.45rem;
  border: 0;
  border-radius: 8px;
  background: #fffaf0;
}
.grid--wanted .card--v2 .card-badges { top: 0.55rem; left: 0.55rem; right: 0.55rem; }
.grid--wanted .card--v2 .badge { box-shadow: 0 2px 7px rgba(20, 17, 15, 0.18); }
.grid--wanted .card--v2 h3 { margin-top: 0.72rem; color: var(--ink); }
.grid--wanted .card--v2 .price { color: var(--accent); }
/* Keep catalogue cards in the same compact proportion as the hero cards. */
.grid--wanted .card--v2::before { display: none; }
.grid--wanted .card--v2 > a { padding: 0.5rem; }
.grid--wanted .card--v2 .card-media { margin-top: 0.3rem; border-radius: 7px; }
.grid--wanted .card--v2 h3 {
  margin-top: 0.55rem;
  font-size: 0.92rem;
  line-height: 1.12;
  min-height: 0;
}
.grid--wanted .card--v2 .price { margin-top: 0.25rem; }
.grid--wanted .card-buy {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.45rem;
  margin-top: 0.55rem;
  padding: 0.42rem 0.55rem 0.38rem 0.65rem;
  border-radius: 5px;
  background: var(--accent);
  color: var(--ink);
  box-shadow: 0 0 12px rgba(228, 87, 46, 0.42);
  font-family: var(--font-display);
  font-size: 0.66rem;
  font-weight: var(--wght-display);
  letter-spacing: var(--tr-tight);
  transition: box-shadow 180ms ease, transform 180ms ease;
}
.grid--wanted .card-buy::before { content: "+"; font-size: 1rem; line-height: 0.7; }
.grid--wanted .card-buy .price {
  display: flex;
  align-items: baseline;
  gap: 0;
  margin: 0;
  color: var(--ink);
  font-family: var(--font-card);
}
.grid--wanted .card-buy .p-cur { font-size: 0.65rem; }
.grid--wanted .card-buy .p-int { font-size: 1rem; }
.grid--wanted .card-buy .p-dec { font-size: 0.62rem; }
.grid--wanted .card--v2:hover .card-buy { transform: translateY(-1px); box-shadow: 0 0 18px rgba(228, 87, 46, 0.7); }

/* The catalogue now uses the exact hero-card component, not a visual
   approximation. These desktop rules mirror the mobile hero declarations. */
.grid--wanted .card--v2 { background: transparent; box-shadow: none; overflow: visible; }
.grid--wanted .card--v2:hover { box-shadow: none; transform: none; }
.grid--wanted .card--v2 > a.mobile-shirt {
  position: relative;
  display: block;
  padding: 0.5rem 0.5rem 0.6rem;
  overflow: hidden;
  border: 0;
  border-radius: 12px;
  background: #fff;
  color: var(--ink);
  box-shadow: 0 0 0 1px rgba(228,87,46,.85), 0 0 12px rgba(228,87,46,.92), 0 0 34px rgba(228,87,46,.62), 0 14px 30px rgba(0,0,0,.5);
  transition: transform 220ms ease, box-shadow 220ms ease;
}
.grid--wanted .card--v2 > a.mobile-shirt:hover { transform: translateY(-5px); box-shadow: 0 0 0 1px rgba(228,87,46,.92), 0 0 20px rgba(228,87,46,.96), 0 0 44px rgba(228,87,46,.68), 0 16px 34px rgba(0,0,0,.56); }
.grid--wanted .mobile-shirt .mobile-shirt-media { position: relative; overflow: hidden; border-radius: 9px; background: #fff; }
.grid--wanted .mobile-shirt .mobile-shirt-media img { width: 100%; aspect-ratio: 1; object-fit: contain; border: 0; background: radial-gradient(circle at 50% 42%, rgba(228,87,46,.13), transparent 62%), #fff; }
.grid--wanted .mobile-shirt > .ref { display: block; margin: 0 0 .18rem; color: var(--ink); font-family: var(--font-body); font-size: .68rem; font-weight: 850; letter-spacing: .01em; line-height: 1.05; }
.grid--wanted .mobile-shirt > .card-badges { position: static; display: flex; flex-wrap: wrap; gap: .25rem; margin: 0 0 .35rem; }
.grid--wanted .mobile-shirt > .card-badges .badge { padding: 2px 5px; font-size: .47rem; line-height: 1.1; }
.grid--wanted .mobile-shirt > span { display: -webkit-box; min-height: 2em; margin: .5rem 0 .4rem; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; font-family: var(--font-body); font-size: .9rem; font-weight: 750; line-height: 1.16; letter-spacing: -.02em; }
.grid--wanted .mobile-shirt .mobile-shirt-buy { display: flex; flex-direction: column; align-items: stretch; gap: .35rem; }
.grid--wanted .mobile-shirt .mobile-shirt-buy b { display: flex; align-items: center; justify-content: flex-start; gap: .25rem; width: 100%; min-height: 38px; padding: .5rem .45rem; border-radius: 7px; background: linear-gradient(135deg,#ef6840 0%,var(--accent) 58%,#d34823 100%); color: #fff; font-family: var(--font-body); font-size: .56rem; font-weight: 850; letter-spacing: -.03em; text-align: left; box-shadow: inset 0 1px 0 rgba(255,255,255,.28),0 4px 8px rgba(172,52,24,.2); white-space: nowrap; }
.grid--wanted .mobile-shirt .mobile-add-label { display: inline-flex; align-items: center; gap: .2rem; min-width: 0; white-space: nowrap; }
.grid--wanted .mobile-shirt .mobile-add-label::before { content: '+'; display: grid; place-items: center; width: 1rem; height: 1rem; border: 1.5px solid rgba(255,255,255,.88); border-radius: 50%; font-size: .72rem; line-height: 1; }
.grid--wanted .mobile-shirt .mobile-shirt-buy b .money { display: inline; min-height: 0; margin: 0 0 0 auto; padding: 0 0 0 .3rem; color: inherit; font: inherit; letter-spacing: inherit; white-space: nowrap; border-left: 1px solid rgba(255,255,255,.38); font-weight: 900; }
/* Calm the catalogue down: broader cards, restrained depth, no orange halo. */
@media (min-width: 901px) {
  .grid--wanted { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .65rem; }
}
@media (max-width: 900px) {
  .grid--wanted { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; }
  .grid--wanted .card--v2 { min-width: 0; padding: 0 !important; border: 0 !important; }
  .grid--wanted .card--v2 > a.mobile-shirt {
    border: 1px solid rgba(228,87,46,.38);
    border-radius: 2px;
    box-shadow: none;
  }
  .grid--wanted .card--v2 > a.mobile-shirt:hover { box-shadow: inset 0 0 0 2px rgba(228,87,46,.55); }
}
.grid--wanted .card--v2 > a.mobile-shirt {
  box-shadow: 0 8px 20px rgba(20,17,15,.16), 0 0 0 1px rgba(228,87,46,.42);
}
.grid--wanted .card--v2 > a.mobile-shirt:hover {
  box-shadow: 0 12px 24px rgba(20,17,15,.22), 0 0 0 1px rgba(228,87,46,.68);
}
.grid--wanted .mobile-shirt .mobile-shirt-buy b { box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 3px 7px rgba(172,52,24,.2); }
.grid--wanted .mobile-shirt:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.grid--wanted .mobile-shirt .mobile-shirt-media img { transition: transform 220ms ease, filter 220ms ease; }
.grid--wanted .mobile-shirt:hover .mobile-shirt-media img { transform: translateY(-3px) scale(1.045); filter: saturate(1.08); }
.grid--wanted .mobile-shirt .mobile-shirt-buy b { cursor: pointer; transition: filter 160ms ease, transform 160ms ease, box-shadow 160ms ease; }
.grid--wanted .mobile-shirt:hover .mobile-shirt-buy b { filter: brightness(1.08); transform: translateY(-1px); box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 5px 11px rgba(172,52,24,.3); }
.grid--wanted .mobile-shirt:active .mobile-shirt-buy b { transform: translateY(1px); filter: brightness(.98); }
.grid--wanted .mobile-shirt > .card-badges .badge {
  border: 0;
  border-radius: 999px;
  background: #25201c;
  color: #fff8ee;
  font-family: var(--font-display);
  font-size: .5rem;
  font-weight: var(--wght-display);
  letter-spacing: .035em;
  line-height: 1;
  text-transform: uppercase;
}
.grid--wanted .mobile-shirt > .card-badges .badge--era { background: var(--accent); color: var(--ink); }

.card--v2 .card-badges {
  position: absolute;
  top: var(--sp-2); left: var(--sp-2);
  right: var(--sp-2);              /* wide chip pairs wrap instead of clipping */
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
}
.card--v2 .badge {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  padding: 3px 7px;
  background: var(--panel-bg);
  color: var(--panel-fg);
}
.card--v2 .badge--era { background: var(--accent); color: var(--base); }

/* HARD ALIGNMENT RULE (owner, 2026-08-08): every card element sits at the
   same height across a row. The card is a full-height flex column; the title
   reserves two lines; size + price are anchored to the bottom. Title length
   can never push the price around again. */
.card--v2 { display: flex; flex-direction: column; }
.card--v2 > a { display: flex; flex-direction: column; flex: 1; }

.card--v2 h3 {
  font-family: var(--font-card);
  font-weight: 740;
  font-stretch: 82%;
  font-size: 1.05rem;
  line-height: 1.22;
  letter-spacing: 0.01em;
  margin: var(--sp-2) 0 var(--sp-1);
  min-height: calc(2 * 1.22em);    /* two-line reservation */
}
.card--v2 .meta,
.card--v2 .price { margin-top: auto; }         /* bottom-anchored */
.card--v2 .meta + .price { margin-top: var(--sp-1); }  /* price follows meta */
.card--v2 .meta {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--muted);
  letter-spacing: 0.06em;
}
/* the deal is in the numerals: big confident pounds, quiet currency/pence */
.card--v2 .price {
  font-family: var(--font-card);
  color: var(--accent);
  display: flex;
  align-items: baseline;
  margin-top: var(--sp-1);
}
.card--v2 .p-cur { font-size: 0.85rem; font-weight: 640; font-stretch: 85%; margin-right: 1px; }
.card--v2 .p-int { font-size: 1.55rem; font-weight: 780; font-stretch: 85%; line-height: 1; }
.card--v2 .p-dec { font-size: 0.85rem; font-weight: 640; font-stretch: 85%; }

/* ============================================================
   JOURNAL POSTS (kit news) — added 2026-08-09
   .journal-post / .journal-hero had NO rules, so the hero image
   rendered at its natural size (source images run 400KB+ and
   1600px wide). Everything below is token-only per rule 4.
   ============================================================ */
/* The prose column is capped for readability, but the ARTICLE ITSELF was left
   flush to the left of a full-width container, so every post had a dead column
   down the right. Centre the readable width; let the shirt grid use the space. */
.journal-post { max-width: 78ch; margin-inline: auto; }
.journal-post > .grid,
.journal-post > h2.archive-head { max-width: none; }
.journal-post .grid {
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-6);
}
/* The sitewide `.card:first-child { border-left:0; padding-left:0 }` makes the
   first card wider than its siblings, which pushed its image and price out of
   line with the rest of the row. .grid--shop already solves this the same way;
   reuse that convention rather than invent another. */
.journal-post .grid .card:first-child {
  border-left: var(--rule);
  padding-left: var(--sp-4);
}
@media (max-width: 900px) {
  .journal-post .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .journal-post .grid { grid-template-columns: 1fr; }
}

.journal-hero { margin: 0 0 var(--sp-6); }
.journal-hero img {
  display: block;
  width: 100%;
  max-height: 340px;          /* was unbounded */
  object-fit: cover;
  border: var(--rule);
  background: var(--base-warm);
}
.journal-hero figcaption {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--muted);
  padding-top: var(--sp-2);
}

.journal-meta { font-family: var(--font-mono); color: var(--muted); }

.journal-post h2 {
  margin: var(--sp-8) 0 var(--sp-3);
  font-family: var(--font-display);
  font-weight: var(--wght-display);
}

/* INTERNAL PROSE links only — orange. Scoped to .lead and the teams line, NOT
   the whole post: every product card is wrapped in an internal <a>, so the
   unscoped version turned all card titles and prices into orange underlined
   text. The outbound source credit stays muted so the eye (and the link equity)
   favours our own pages. */
.journal-post .lead a[href^="/"],
.journal-post .journal-teams a[href^="/"] {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
.journal-post .lead a[href^="/"]:hover,
.journal-post .journal-teams a[href^="/"]:hover { text-decoration-thickness: 2px; }

.journal-source, .journal-teams {
  font-size: 0.875rem;
  color: var(--muted);
  margin-top: var(--sp-6);
}
.journal-source a { color: var(--muted); }

/* News thumbnails are landscape crops, not square product shots, and smaller. */
.journal-grid .card-media { aspect-ratio: 3 / 2; }
.journal-grid .card-media img { object-fit: cover; }
.journal-grid .card-sub {
  font-size: 0.875rem; color: var(--muted); margin: var(--sp-2) 0 0;
}

/* ============================================================
   AUTHORS — /authors/ and /authors/<slug>/   (added 2026-08-09)
   Token-only per rule 4. The byline name is a stamp, so it is a
   link; it stays inherit-coloured so it reads as a byline rather
   than a body link.
   ============================================================ */
.byline-name { color: inherit; text-decoration: none; border-bottom: 1px solid var(--rule-c); }
.byline-name:hover { border-bottom-color: var(--accent); }

.author-page { max-width: 78ch; margin-inline: auto; }
.author-hero { display: flex; gap: var(--sp-6); align-items: center; margin-bottom: var(--sp-8); }
.author-portrait {
  width: 160px; height: 160px; flex: 0 0 160px;
  object-fit: cover; border: var(--rule); background: var(--base-warm);
}
.author-role { font-family: var(--font-mono); color: var(--muted); margin: var(--sp-2) 0 0; }
.author-tagline { margin: var(--sp-2) 0 0; }

.author-tags { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.author-tags li {
  font-family: var(--font-mono); font-size: 0.8125rem;
  border: var(--rule); padding: var(--sp-1) var(--sp-3);
}

.author-stats { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin: var(--sp-4) 0 var(--sp-8); }
.stat { display: flex; flex-direction: column; }
.stat-n { font-family: var(--font-display); font-size: 1.75rem; line-height: 1.1; }
.stat-l { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted); }

.author-articles { list-style: none; padding: 0; }
.author-articles li { padding: var(--sp-3) 0; border-bottom: var(--rule); }

@media (max-width: 560px) {
  .author-hero { flex-direction: column; align-items: flex-start; }
  .author-portrait { width: 120px; height: 120px; flex-basis: 120px; }
}

/* ============================================================
   HOMEPAGE LEDGER — responsive     (added 2026-08-09)
   The archive table overflowed the viewport on mobile (402px of
   content in a 390px window), clipping Season, Kit and Price
   entirely. The ref column already encodes season and kit
   ("ENG · 1990 · H"), so those two are redundant on a narrow
   screen and are the ones to drop.
   ============================================================ */
.ledger { table-layout: auto; width: 100%; }
.ledger .ref-col { font-family: var(--font-mono); white-space: nowrap; }
.ledger .num { white-space: nowrap; padding-right: 0; text-align: right; }
.ledger .thumb-col { width: 56px; }
.ledger .thumb { display: block; width: 44px; height: 44px; overflow: hidden;
                 border: var(--rule); background: var(--base-warm); }
.ledger .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 760px) {
  /* season + kit live inside the ref, so drop the duplicate columns */
  .ledger .opt-col { display: none; }
  .ledger th:nth-child(4), .ledger th:nth-child(5) { display: none; }
  .ledger { font-size: 0.8125rem; }
  .ledger th, .ledger td { padding: var(--sp-2) var(--sp-2) var(--sp-2) 0; }
  .ledger .thumb-col { width: 44px; }
  .ledger .thumb { width: 36px; height: 36px; }
}

/* Hero carousel overflowed the viewport on mobile: figure.hero-media measured
   402px inside a 390px window, which gave the WHOLE page a horizontal scroll.
   Clamp the media and clip at the section, so the carousel can size itself
   without the document inheriting the overflow. */
.hero-media, .hero-media img.hero-base { max-width: 100%; }
.hero, .hero-track, .hero-slide { max-width: 100%; overflow-x: clip; }
@media (max-width: 760px) {
  .hero-media { width: 100%; }
}

@media (max-width: 760px) {
  /* The crest and the three-letter code already identify the team, so the Club
     column is the last redundancy to drop. Ref + price then fit without the
     table scrolling inside its wrapper and clipping the club name mid-word. */
  .ledger th:nth-child(3), .ledger td:nth-child(3) { display: none; }
  .ledger .ref-col { width: 100%; }
}

@media (max-width: 760px) {
  /* The base rule sets min-width:720px so the six-column desktop table can
     scroll rather than crush. With Season, Kit and Club hidden there are only
     three columns left, so the floor has to come off or the table keeps
     scrolling inside its wrapper and clips the content. */
  .ledger { min-width: 0; }
}

/* ============================================================
   CUSTOMER REVIEWS BAND (2026-08-09, upgraded) — orange Trustpilot
   stars, drag-scroll carousel. Sitewide except E-E-A-T / journal.
   ============================================================ */
.reviews-band {
  border-top: var(--rule);
  background: var(--base-warm);
  padding-block: var(--sp-12);
  margin-top: var(--sp-16);
}

/* ---- header: heading, then Excellent x/5 ---- */
.rev-head { margin-bottom: var(--sp-8); }
.rev-heading {
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  margin: 0 0 var(--sp-3);
}
.rev-summary { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); line-height: 1; }
.rev-word {
  font-family: var(--font-ui);
  font-weight: var(--wght-ui); font-stretch: var(--wdth-ui);
  text-transform: uppercase; letter-spacing: 0.08em;
  font-size: 0.9rem;
}
.rev-agg { font-family: var(--font-card); font-size: 0.95rem; color: var(--muted); display: inline-flex; align-items: baseline; gap: 1px; }
.rev-agg strong { color: var(--ink); font-size: 1.25rem; font-weight: 780; }
.rev-count { font-family: var(--font-body); font-size: 0.9rem; color: var(--muted); letter-spacing: 0; }

/* ---- Trustpilot-style boxed stars, orange, small + spaced ---- */
.rev-stars { display: inline-flex; align-items: center; gap: 4px; line-height: 1; white-space: nowrap; }
.rev-star-svg { width: 15px; height: 15px; display: block; border-radius: 2px; }
.rev-stars--lg .rev-star-svg { width: 20px; height: 20px; }

/* ---- carousel: horizontal, drag-to-scroll (JS adds .is-drag) ---- */
.rev-track {
  display: flex;
  gap: var(--sp-4);
  overflow-x: auto;
  padding: var(--sp-1) var(--sp-1) var(--sp-4);
  margin: 0 calc(-1 * var(--sp-1));
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-c) transparent;
  cursor: grab;
}
.rev-track.is-drag { cursor: grabbing; scroll-snap-type: none; }
.rev-track.is-drag .rev-card { pointer-events: none; }
.rev-track::-webkit-scrollbar { height: 6px; }
.rev-track::-webkit-scrollbar-track { background: transparent; }
.rev-track::-webkit-scrollbar-thumb { background: var(--rule-c); border-radius: 3px; }
.rev-track::-webkit-scrollbar-thumb:hover { background: var(--muted); }

.rev-card {
  flex: 0 0 320px;
  scroll-snap-align: start;
  margin: 0;
  padding: var(--sp-6);
  background: var(--base);
  border: var(--rule);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  box-shadow: 0 1px 2px rgba(20, 17, 15, 0.04);
  transition: box-shadow var(--t), transform var(--t), border-color var(--t);
}
.rev-card:hover {
  box-shadow: 0 12px 28px rgba(20, 17, 15, 0.10);
  transform: translateY(-3px);
  border-color: var(--ink);
}
.rev-card .rev-stars { margin-bottom: var(--sp-1); }
.rev-title {
  font-family: var(--font-card);
  font-weight: 740; font-stretch: 82%;
  font-size: 1.2rem;
  line-height: 1.2;
  letter-spacing: 0.01em;
}
.rev-body {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--ink);
}
.rev-author {
  font-family: var(--font-card);
  font-weight: 640;
  font-size: 0.95rem;
  color: var(--ink);
  font-style: normal;
  letter-spacing: 0;
  margin-top: auto;
  padding-top: var(--sp-2);
}
.rev-author::before { content: "\2014\00a0"; color: var(--accent); }

@media (max-width: 600px) {
  .rev-card { flex-basis: 80vw; padding: var(--sp-4); }
  .reviews-band { padding-block: var(--sp-8); }
}

/* Chip rows carry a crest where one exists, so the club row is not a wall of
   plain text. Falls back to text-only cleanly for players and leagues.

   MUST exclude .tchip-link. The badge chips on /club/ and /international/ are
   also inside .chips, and ".chips a img" (0,1,2) outspecifies ".tchip img"
   (0,1,1) whatever the order - so this rule shrank every 42px crest to 20px
   inside its circle and flattened the directory pages. */
.chips a { display: inline-flex; align-items: center; gap: var(--sp-2); }
.chips a:not(.tchip-link) img {
  width: 20px; height: 20px; object-fit: cover; display: block;
  border: 1px solid var(--rule-c); background: var(--base-warm);
}
@media (max-width: 560px) {
  .chips a:not(.tchip-link) img { width: 18px; height: 18px; }
}

/* Ledger thumbs show the listing's own shirt (not a team crest), so they need
   a little more room to read as a garment rather than a colour block. */
.ledger .thumb { width: 56px; height: 56px; }
.ledger .thumb img { object-fit: contain; background: var(--base); }
@media (max-width: 760px) { .ledger .thumb { width: 46px; height: 46px; } }

/* Trending searches: grouped by destination rather than one flat tag dump. */
.trending { display: flex; flex-direction: column; gap: var(--sp-4); }
.trend-group { display: flex; align-items: baseline; gap: var(--sp-4); flex-wrap: wrap; }
.trend-label {
  font-family: var(--font-mono); font-size: 0.75rem; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted); min-width: 84px;
}
.trend-links { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.trend-links a {
  font-family: var(--font-mono); font-size: 0.8125rem;
  border: var(--rule); padding: var(--sp-1) var(--sp-3);
}
.trend-links a:hover { border-color: var(--accent); color: var(--accent); }
@media (max-width: 560px) {
  .trend-group { flex-direction: column; gap: var(--sp-2); }
  .trend-label { min-width: 0; }
}

/* Most-wanted row: 8 cards in the sitewide 6-column grid wrapped as 6 + 2,
   which reads as a mistake. Four-up gives two clean rows and a bigger image,
   which is the point of putting it directly under the hero. */
.grid--wanted { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1000px) { .grid--wanted { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 760px)  { .grid--wanted { grid-template-columns: repeat(2, 1fr); } }

/* ============================================================
   PLAYER TILES — backdrop with the name over it   (2026-08-10)
   ============================================================ */
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4);
         padding-bottom: var(--sp-16); }
.tile { position: relative; display: block; overflow: hidden; border: var(--rule);
        background: var(--panel-bg); }
.tile-media { display: block; aspect-ratio: 3 / 2; }
.tile-media img { width: 100%; height: 100%; object-fit: cover; display: block;
                  transition: transform var(--t); }
.tile:hover .tile-media img { transform: scale(1.03); }
.tile-text { position: absolute; inset: auto 0 0 0; padding: var(--sp-4);
             background: linear-gradient(to top, rgba(20,17,15,.88), rgba(20,17,15,0)); }
.tile-kicker { display: block; font-family: var(--font-mono); font-size: .6875rem;
               text-transform: uppercase; letter-spacing: .1em; color: var(--panel-fg);
               opacity: .75; }
.tile-title { display: block; font-family: var(--font-display);
              font-weight: var(--wght-display); font-size: 1.125rem;
              color: var(--panel-fg); line-height: 1.15; }
@media (max-width: 760px) { .tiles { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 440px) { .tiles { grid-template-columns: 1fr; } }

/* ============================================================
   CARD SIZE CONSISTENCY
   Cards were different heights across rows: a one-line title next to a
   two-line one pushed the image and price out of alignment, and rows with
   badges sat lower than rows without. Reserve two lines for the title and
   bottom-anchor the price so every card in every grid matches.
   ============================================================ */
.card--v2 { display: flex; flex-direction: column; height: 100%; }
.card--v2 > a { display: flex; flex-direction: column; height: 100%; }
.card--v2 h3 {
  min-height: 2.6em; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
.card--v2 .price, .card--v2 .price-lg { margin-top: auto; }
.grid { align-items: stretch; }

/* The chip navs these grids replaced sat INSIDE <section class="lead">, whose
   max-width:78ch is there to keep prose readable. The grid inherited it and
   rendered 837px wide in a 1354px column - the dead space on the right. Let a
   grid or tile row inside a lead go full width while the prose stays capped. */
section.lead:has(> .grid),
section.lead:has(> .tiles) { max-width: none; }
section.lead:has(> .grid) > .lead-body,
section.lead:has(> .tiles) > .lead-body { max-width: none; }

/* ============================================================
   MOBILE SECTION RHYTHM (owner, 2026-08-10)
   ============================================================ */
@media (max-width: 760px) {
  /* Every block is a .section-head followed by a content section, so the gap
     between two blocks is the content's padding-bottom (64px) plus the next
     head's padding-top (32px) = 96px. That reads as considered space on a
     1440px desktop and as dead scroll on a 390px phone: roughly a third of
     each swipe was empty. Tightened to 32 + 24 = 56px HERE rather than in the
     tokens, because the desktop rhythm is correct as it stands. */
  .section-head { padding-block: var(--sp-6) var(--sp-4); }
  .grid, .journal, .faq, .guide { padding-bottom: var(--sp-8); }
  .lead { padding-block: var(--sp-6) var(--sp-8); }
  .prov { padding-block: var(--sp-6) var(--sp-8); }
  .nations { margin-bottom: var(--sp-8); }
}

/* ============================================================
   MOBILE HEADER: ONE LINE (owner, 2026-08-10)
   ============================================================ */
@media (max-width: 760px) {
  /* At 390px the row was brand 111 + utils 304 + burger 32 against 350px of
     usable width, so the header wrapped into THREE stacked lines (logo,
     utils, hamburger) and stood 147px tall before any content. Nothing here
     is hidden - the search box is allowed to shrink into whatever space is
     left, and the currency select is tightened, so every control stays
     reachable on one line.

     A flex container WRAPS BEFORE IT SHRINKS, so `flex-wrap: wrap` plus
     `flex: 1 1 auto` does not fit the row - the line simply breaks and utils
     drops to its own row at full width. The row therefore has to be nowrap,
     which means .nav can no longer rely on wrapping to reach its own line:
     it becomes an absolutely-positioned dropdown panel under the header. */
  .header { flex-wrap: nowrap; gap: var(--sp-3); }
  .header > .brand { flex: 0 0 auto; }
  .utils { flex: 1 1 auto; min-width: 0; gap: var(--sp-3); margin-left: auto; }
  .search { flex: 1 1 auto; min-width: 0; }
  .search input { width: 100%; min-width: 0; }
  .ccy select { padding: 2px 4px; }
  .nav-toggle { flex: 0 0 auto; margin-left: 0; }

  /* .header is position:sticky, so it is the containing block for this. */
  .nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    width: auto;
    padding: var(--sp-4) var(--gutter) var(--sp-6);
    background: var(--base);
    border-bottom: var(--rule);
    max-height: 76vh;
    overflow-y: auto;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
  }
}

/* ============================================================
   MOBILE NAV DROPDOWNS (owner, 2026-08-10)
   ============================================================ */
@media (max-width: 760px) {
  /* `.dd-menu { display: none }` at 900px left the mobile menu as "top-level
     links only", so six of the seven nav groups - International, Clubs,
     Leagues, Women, Kids, By Player - had no way to reach their children:
     64 of the 71 nav links were unreachable on a phone. They now expand in
     place as an accordion. The tap handler is in assets/cart.js, which is the
     only script every page already loads (a build_shell.py change would mark
     all 43,000 pages stale for a nav tweak). */
  .nav-dd { display: block; width: 100%; }
  .nav-dd > a { justify-content: space-between; width: 100%; }
  .dd-caret { transition: transform var(--t); }
  .nav-dd.dd-open > a .dd-caret { transform: rotate(180deg); }

  /* Undo the desktop popover: static flow, no centring transform, no border. */
  .nav-dd.dd-open .dd-menu {
    display: block;
    position: static;
    transform: none;
    min-width: 0;
    opacity: 1;
    visibility: visible;
    border: 0;
    border-left: var(--rule);
    border-radius: 0;
    background: transparent;
    margin: var(--sp-1) 0 var(--sp-2) var(--sp-2);
    padding: 0 0 0 var(--sp-3);
  }
  .nav-dd.dd-open .dd-menu li a { white-space: normal; padding: var(--sp-2) 0; }
}

/* ============================================================
   STACKED HERO: NO BAND UNDER THE PHOTO (owner, 2026-08-10)
   ============================================================ */
@media (max-width: 900px) {
  /* Every slide is sized to the TALLEST slide's panel, so a slide with shorter
     copy has surplus height to place. The rows were `auto` and grid content
     defaults to stretch, so that surplus went into the IMAGE row: the photo
     stayed 278px inside a 286px row and an 8px strip of page background showed
     between the picture and the dark panel. It hit five of the six slides -
     every one except the tallest - which is why it looked like it affected
     "some images" at random.

     `auto 1fr` pins the image row to the picture's own height and gives the
     slack to the panel instead. .hero-media is order:-1 here, so it is the
     item in row 1.

     UPDATE 2026-08-11: `1fr` handed the equal-height slack to the panel, so a
     SHORT slide showed a tall ink panel with the copy centred and a block of
     dead dark space below it. `auto auto` + `align-content: start` pins both
     rows to their content and drops the slack to the BOTTOM of the slide, where
     the light page background shows through instead of the ink panel. */
  .hero-slide { grid-template-rows: none; align-content: normal; }
  /* top-align the copy so a short panel doesn't centre into empty ink */
  .hero-panel { justify-content: flex-end; }
}

@keyframes mobile-hero-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(5px); }
}

@keyframes mobile-card-signal {
  0%, 100% { box-shadow: 0 0 0 1px rgba(228, 87, 46, 0.85), 0 0 12px rgba(228, 87, 46, 0.82), 0 0 30px rgba(228, 87, 46, 0.52), 0 14px 30px rgba(0, 0, 0, 0.5); }
  50% { box-shadow: 0 0 0 2px rgba(159, 47, 23, 0.95), 0 0 22px rgba(228, 87, 46, 1), 0 0 48px rgba(228, 87, 46, 0.82), 0 14px 32px rgba(0, 0, 0, 0.56); }
}

@media (prefers-reduced-motion: reduce) {
  .mobile-hero-down { animation: none; }
  .mobile-shirt,
  .mobile-shirt-rail,
  .mobile-shirt img,
  .mobile-shirt-buy b { transition: none; }
}

/* ============================================================
   CARD COLUMN WIDTH PARITY  (2026-08-11)
   Cards in a grid row did not line up on mobile: measured at 390px the media
   boxes in one row were 162px and 145px tall, with every product image an
   identical 800x800.

   Cause was not the title or the badges, both of which are already normalised.
   The first card of each row had `padding-left: 0` so the divider rule could
   sit flush, which makes that column's CONTENT BOX ~13px wider. A square image
   in a wider box is a TALLER image, so the title and price below it started
   lower on alternate cards. The two-line title reservation cannot correct an
   offset introduced above the title.

   Keep the divider, keep the padding. The far-left card is now inset by one
   step like every other card, which costs nothing visually and makes every
   column the same width - the only way square images can agree on a height.
   ============================================================ */
.card:first-child,
.grid .card:nth-child(3n+1),
.grid .card:nth-child(2n+1) { padding-left: var(--sp-4); }
.card:last-child { padding-right: var(--sp-4); }
.grid--dense .card:first-child,
.grid--dense .card:nth-child(3n+1),
.grid--dense .card:nth-child(2n+1) { padding-left: var(--sp-3); }
.grid--dense .card:last-child { padding-right: var(--sp-3); }
@media (max-width: 560px) {
  .grid .card:nth-child(2n+1),
  .grid .card:nth-child(3n+1) { padding-left: var(--sp-3); }
  .card:last-child { padding-right: var(--sp-3); }
}
/* The media box now sets its own height from its width rather than from the
   image, so a stray non-square photo (7 of the first 400 are 3:4) can no
   longer break the row it sits in. */
.card--v2 .card-media { aspect-ratio: 1 / 1; }
.card--v2 .card-media img { width: 100%; height: 100%; object-fit: cover; }

/* ============================================================
   MOBILE HEADER SEARCH  (2026-08-11)
   The search field rendered 13px wide at 390px - present, focusable in theory,
   unusable in practice. `.search` is `flex: 1 1 auto; min-width: 0`, so it was
   the only element in .utils that could absorb the shortfall, and it absorbed
   all of it: brand 111, currency 54, bag 32, account 20, toggle 32.

   Reclaim the space from decoration rather than from function: drop the
   magnifier glyph (the placeholder already says what the field is) and cap the
   wordmark. Nothing is hidden that a phone user needs - currency, account, bag
   and the menu all stay.
   ============================================================ */
@media (max-width: 700px) {
  .header .search .icon,
  .header .search .shop-search-i { display: none; }
  .header > .brand img { max-width: 84px; height: auto; }
  .search { flex: 1 1 auto; min-width: 96px; }
  .search input { width: 100%; min-width: 96px; font-size: 16px; }
  .ccy select { padding: 2px 2px; max-width: 46px; }
}

/* ============================================================
   HERO SUB-COPY: NEVER TRUNCATE  (2026-08-11)
   `.hero-sub` carried `-webkit-line-clamp: 3` at both breakpoints, so any
   slide whose sentence ran to four lines ended mid-word with an ellipsis
   ("...kids sizes include…"). A clamp is the right tool for a card title of
   unknown length; it is the wrong tool for authored marketing copy, where the
   sentence is known and the fix is to give it room.

   Give the measure a little more width so the existing copy sets in three
   lines, and drop the clamp so a longer line wraps instead of vanishing.
   ============================================================ */
.hero-sub {
  display: block;
  -webkit-line-clamp: none;
  overflow: visible;
  max-width: 46ch;
}
@media (max-width: 900px) {
  .hero-sub { display: block; -webkit-line-clamp: none; overflow: visible;
              max-width: none; }
}
@media (min-width: 901px) {
  .hero-sub { display: block; -webkit-line-clamp: none; overflow: visible;
              max-width: 46ch; }
}

/* ============================================================
   MOBILE: STRAIGHT TO THE SHIRTS  (owner, 2026-08-11)
   On a phone the homepage opened with a four-item trust strip and ~800 words
   of intro prose before the first product. Hide the prose on mobile so the
   grids start directly under the hero; keep every heading.

   TRADE-OFF, RECORDED DELIBERATELY: this is `display: none`, and Google
   indexes the MOBILE document. 804 of the homepage's 3,812 visible words are
   inside these blocks. They stay in the HTML and are still crawlable, but
   hidden text is discounted, so this trades some indexable homepage copy for
   a faster path to product. Reversible in one block. The alternative that
   keeps both - collapsing the prose behind a "Read more" toggle so it is
   present, visible on demand and not hidden by default - needs a DOM change
   in the generators rather than CSS, and is the better answer if rankings dip.
   ============================================================ */
@media (max-width: 700px) {
  /* ...and collapse the turf BAND that wrapped the now-hidden trust row. Left
     standing, its padding-block + ink turf background rendered as a ~64px strip
     of dead dark space between the hero and the next section (owner, 2026-08-11).
     :has scopes it to bands whose only content is the hidden trust row, so a
     band carrying real copy is untouched. */
  /* the tiles/grids live INSIDE section.lead on this page, so the section
     itself must stay - only its prose children are hidden */
  .lead { padding-block: 0; border: 0; }
  .lead:empty { display: none; }

  /* A JOURNAL ARTICLE IS NOT A HUB AND NOT THE HOMEPAGE (owner report,
     2026-08-12: "doesn't show the text on mobile"). Both hides above are
     right for the pages they were written for and catastrophic here:
       .hub-standfirst  (640px, ~line 1676) drops a hub blurb the H2 strapline
                        repeats - but on a post the standfirst IS the article;
       .lead > p        (700px, above) hides homepage prose whose section only
                        survives to hold tiles - but on a post those p's ARE
                        the body copy.
     Result: 4 of 13 paragraphs rendered display:none, so mobile readers got a
     headline, a byline and no story. .journal-post scopes the restore to
     posts, and (0,2,0) beats both bare class hides. Placed after BOTH rules so
     it wins at every width; this block's 700px also covers the 640px one. */
  .journal-post .hub-standfirst,
  .journal-post .lead > p { display: block; }
  .journal-post .lead { padding-block: revert; }

  /* One size for every section heading, and one line each. The longest is
     "Best Selling Football Shirts"; at this size and the condensed cut it
     fits 390px without wrapping. */
  .section-head h2 {
    font-size: 1.15rem;
    line-height: 1.25;
    letter-spacing: 0.005em;
    min-width: 0;
  }
  /* NOT `white-space: nowrap`. One heading - "New Retro In: England 96, Juve,
     Brazil" - measures 423px, so nowrap pushed it and its view-all link 140px
     past a 390px viewport. Truncating it was the other option and was rejected:
     the hero clamp was just removed for exactly that reason, and a heading cut
     mid-phrase is worse than one that wraps. Uniform size is kept; the single
     over-long heading wraps and everything else sets on one line. Shortening
     that heading in the copy is the real fix and is an editorial call. */
  .section-head {
    align-items: baseline;
    gap: var(--sp-2);
    flex-wrap: wrap;
  }
  .section-head .view-all { font-size: var(--fs-micro); white-space: nowrap; }
}

/* ============================================================
   OFFER POPUP (owner, 2026-08-11)
   ------------------------------------------------------------
   Artwork is photographic only - assets/promo/<geo>.webp. Every word is real
   HTML in the brand faces, so the same image serves all eight locales and a
   price can be corrected without a re-render.
   ============================================================ */
.promo-overlay {
  position: fixed;
  inset: 0;
  z-index: 950;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  background: rgba(20, 17, 15, 0.72);
  backdrop-filter: blur(3px);
}
.promo-overlay[hidden] { display: none; }

.promo {
  position: relative;
  width: min(560px, 100%);
  max-height: 92vh;
  overflow: hidden;
  background: #14110F;
  color: #F4F1EA;
  border-radius: var(--radius);
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.5);
}
.promo-media { position: relative; margin: 0; line-height: 0; }
.promo-media img { width: 100%; height: auto; display: block; }
/* the artwork is composed with clear space top and bottom for exactly this */
.promo-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(20,17,15,0.55) 0%,
              rgba(20,17,15,0) 34%, rgba(20,17,15,0.10) 62%, #14110F 100%);
}
.promo-eyebrow {
  position: absolute;
  top: var(--sp-4);
  left: var(--sp-6);
  z-index: 2;
  margin: 0;
  display: inline-block;
  padding: 7px 12px 6px;
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 0.8125rem;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #14110F;
  background: var(--accent);
  border-radius: 2px;
}
.promo-body { padding: 0 var(--sp-6) var(--sp-6); margin-top: -1.6rem; position: relative; z-index: 2; }
.promo-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 7vw, 2.9rem);
  line-height: 0.94;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}
.promo-title em { font-style: normal; color: var(--accent); }
.promo-slash {
  width: 56px; height: 3px;
  margin: var(--sp-4) 0 var(--sp-3);
  background: var(--accent);
}
.promo-sub {
  margin: 0 0 var(--sp-6);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  line-height: 1.7;
  color: #C9C3B8;
  max-width: 42ch;
}
.promo-actions { display: flex; align-items: center; gap: var(--sp-6); flex-wrap: wrap; }
.promo-cta {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 12px 20px;
  font-family: var(--font-ui);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #14110F;
  background: var(--accent);
  border-radius: var(--radius);
  transition: transform var(--t), background var(--t);
}
.promo-cta:hover { background: #F0673D; transform: translateY(-1px); }
.promo-cta span { transition: transform var(--t); }
.promo-cta:hover span { transform: translateX(4px); }
.promo-dismiss {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.08em;
  color: #9A948A;
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  cursor: pointer;
}
.promo-dismiss:hover { color: #F4F1EA; border-bottom-color: #9A948A; }
.promo-x {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1;
  color: #F4F1EA;
  background: rgba(20, 17, 15, 0.5);
  border: 0; border-radius: 50%;
  cursor: pointer;
  transition: background var(--t);
}
.promo-x:hover { background: rgba(20, 17, 15, 0.85); }

@media (max-width: 480px) {
  .promo-body { padding-inline: var(--sp-4); }
  .promo-eyebrow { left: var(--sp-4); }
  .promo-actions { gap: var(--sp-3); }
  .promo-cta { width: 100%; justify-content: center; }
}

/* Language nudge: offers the visitor their own language rather than
   redirecting them into it. Sits above the cart drawer's 900/901. */
.lang-nudge {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 950;
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: var(--sp-3);
  padding: var(--sp-3) var(--gutter);
  background: var(--ink); color: var(--base);
  font-family: var(--font-ui); font-size: 0.875rem;
  box-shadow: 0 -2px 18px rgba(0,0,0,0.22);
}
.lang-nudge-go {
  color: var(--base); text-decoration: underline;
  text-underline-offset: 3px; font-weight: 640;
}
.lang-nudge-no {
  background: none; border: 0; color: var(--base); opacity: 0.72;
  font: inherit; cursor: pointer; text-decoration: underline;
  text-underline-offset: 3px;
}
.lang-nudge-no:hover { opacity: 1; }
@media (max-width: 560px) { .lang-nudge { font-size: 0.8125rem; } }

/* ============================================================
   /new/ FILTER SIDEBAR OVERFLOW  (2026-08-11)
   390px viewport, page scrollWidth 394. The `.filters` aside measured 373px
   starting at x=20, so it ran 3px past the edge and gave the whole page a
   horizontal scrollbar.

   Cause is the CSS grid default `min-width: auto` on a grid item, which
   refuses to shrink below its content's intrinsic width - here the search
   input's default size. `min-width: 0` lets it track the column instead, and
   border-box stops its own padding adding to the total.
   ============================================================ */
.shop-layout > *,
.shop-main,
.filters { min-width: 0; box-sizing: border-box; max-width: 100%; }
.filters input,
.filters select { max-width: 100%; box-sizing: border-box; }
/* The grid ITEM is the one that would not shrink: the container measured a
   correct 350px with two 159px tracks, while each card rendered 187px and
   spilled 3px past the viewport. `min-width: auto` on a grid item again -
   fixing the containers above was not enough because the card is itself the
   item that overflows its track. */
.grid > .card,
.grid--shop > .card { min-width: 0; }

/* ============================================================
   SEARCH SUGGESTIONS: THUMBNAIL + FULL TITLE  (2026-08-11)
   The dropdown was a single flex row with `justify-content: space-between`
   and no image, so a long shirt name competed with the price on one line and
   got squeezed - unreadable on a 390px screen, and giving no visual
   confirmation of what you were about to click on any screen.

   Now: a 44px thumbnail, the full title allowed to wrap to two lines, and the
   price pinned right. Same layout on mobile and desktop - the reason to show
   the shirt is the same on both.
   ============================================================ */
.search-results li a {
  /* FLEX, not grid. A three-column grid assumes the new markup
     (thumb / name / price) and mangles the old one: on any page the
     propagation has not rebuilt yet, the bare product name landed in the 44px
     thumbnail column and wrapped one word per line. Flex treats a stray text
     node as an ordinary item, so old and new markup both read correctly and
     the page simply gains a thumbnail when it is rebuilt. */
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  justify-content: initial;
}
.search-results li a > .sr-thumb { flex: 0 0 44px; }
.search-results li a > .sr-name  { flex: 1 1 auto; min-width: 0; }
.search-results li a > .sr-price { flex: 0 0 auto; margin-left: auto; }
.sr-thumb {
  width: 44px; height: 44px; object-fit: cover;
  background: var(--base-warm); border: var(--rule); display: block;
}
.sr-thumb--none { opacity: 0.35; }
.sr-name {
  font-family: var(--font-ui); font-size: 0.8125rem; line-height: 1.3;
  color: var(--ink);
  /* wrap rather than truncate: the season and kit type are at the END of a
     shirt name, and they are the part that tells two listings apart */
  white-space: normal; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.search-results li a .sr-price {
  font-family: var(--font-mono); font-size: var(--fs-micro);
  color: var(--muted); white-space: nowrap;
}

/* On a phone the dropdown was a fixed 330px box anchored to a 96px input,
   so it hung off the right edge. Pin it to the viewport instead. */
@media (max-width: 700px) {
  .search { position: static; }
  .search-results {
    position: absolute;
    left: var(--gutter); right: var(--gutter);
    width: auto; max-height: 62vh;
  }
  .sr-name { font-size: 0.875rem; -webkit-line-clamp: 3; }
}

/* ============================================================
   MOBILE HEADER: BAG BADGE vs HAMBURGER  (2026-08-11)
   Measured at 390px: the bag ended at x=346 and the hamburger began at x=338,
   so the two overlapped by 8px - and the bag-count badge is absolutely
   positioned at the bag's top-right, which put the number itself on top of
   the menu icon as soon as the cart was non-empty. Empty, it is display:none,
   which is why it looked fine until something was added.

   Root cause is arithmetic, not z-index: brand 84 + search 96 + account 20 +
   currency 46 + bag 32 + toggle 32 + four 12px gaps + 40px of gutter is ~398
   in a 390 viewport, so .utils overflowed its own box. Buy the space back from
   gaps and the search minimum rather than hiding a control, then give the
   toggle a hard separation so the badge can never reach it.
   ============================================================ */
@media (max-width: 700px) {
  .header { gap: var(--sp-2); }
  .utils { gap: var(--sp-2); }
  .search { min-width: 78px; }
  .search input { min-width: 78px; }
  .ccy select { max-width: 42px; }
  /* the badge overhangs the bag box, so the gap has to clear the badge too */
  .utils .bag { margin-right: var(--sp-2); }
  .nav-toggle { margin-left: var(--sp-2); }
}

/* ============================================================
   MOBILE NAV ACCORDION: COLUMNS AND BREAKPOINT  (2026-08-11)
   Two faults in the in-panel accordion, both measurable:

   1. OFF-SCREEN. `.dd-menu--mega` keeps `column-count: 2`, so an opened
      submenu laid itself out in two columns inside a 350px panel and the
      second column flowed past the edge - the panel measured scrollWidth 1114
      against clientWidth 390, and the menu's own rect started at x=390. One
      column is the only sane answer on a phone.

   2. A DEAD BAND. The accordion is scoped to max-width 760px but the hamburger
      appears at 900px, so between 761 and 900 the panel showed top-level links
      whose children were display:none with no way to open them - the same 64
      unreachable links the accordion was written to fix, just in a narrower
      window. Match the breakpoints.
   ============================================================ */
@media (max-width: 900px) {
  .nav-dd { display: block; width: 100%; }
  .nav-dd > a { justify-content: space-between; width: 100%; }
  .dd-caret { transition: transform var(--t); }
  .nav-dd.dd-open > a .dd-caret { transform: rotate(180deg); }

  .nav-dd.dd-open .dd-menu {
    display: block; position: static; transform: none;
    min-width: 0; opacity: 1; visibility: visible;
    border: 0; border-left: var(--rule); border-radius: 0;
    background: transparent;
    margin: var(--sp-1) 0 var(--sp-2) var(--sp-2);
    padding: 0 0 0 var(--sp-3);
  }
  .nav-dd.dd-open .dd-menu li a { white-space: normal; padding: var(--sp-2) 0; }

  /* single column, and never wider than the panel */
  .nav-dd.dd-open .dd-menu--mega {
    column-count: 1; column-gap: 0; min-width: 0; max-width: 100%;
  }
  /* a tap emulates :hover on touch, which would otherwise re-apply the
     desktop popover on top of the accordion */
  .nav-dd:hover .dd-menu,
  .nav-dd:focus-within .dd-menu { display: none; }
  .nav-dd.dd-open:hover .dd-menu,
  .nav-dd.dd-open:focus-within .dd-menu { display: block; }
  /* belt and braces: the panel itself must never scroll sideways */
  .nav { overflow-x: hidden; }
}



/* Lab (owner, 2026-09-06): "BEST SELLERS" tag over the mobile shirt rail.
   Quiet, not a button: dark glass pill, hairline gold edge, gold lettering,
   a whisper of glow. Hidden with the rail on desktop. */
.mobile-shop-h2 { display: none; }
@media (max-width: 900px) {
  .mobile-shop-h2 {
    display: inline-flex; align-items: center; justify-content: center;
    order: 0;
    width: fit-content;
    margin: 0 auto -1.2rem;
    align-self: center;
    padding: 0.38rem 0.9rem 0.34rem;
    text-indent: 0.18em;             /* offsets the trailing letter-spacing so the word sits dead centre */
    color: var(--gold-hi);
    background: rgba(20, 17, 15, 0.62);
    border: 1px solid rgba(232, 200, 110, 0.75);
    border-radius: 999px;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    font-family: var(--font-ui);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    line-height: 1;
    text-transform: uppercase;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.6);
    box-shadow: 0 0 10px rgba(232, 200, 110, 0.28), 0 2px 6px rgba(0, 0, 0, 0.45);
  }
  .mobile-hero-shop { gap: 0; }
  /* lift the search + H1 + badge so the badge clears the H2 and the rail */
  .hero-panel { bottom: calc(clamp(312px, 41svh, 355px) + 76px); }
}

/* Lab (owner, 2026-09-06): hub rows in the hero typeahead */
@media (max-width: 900px) {
  .mobile-hero-results li.hub a { font-family: var(--font-ui); font-size: 0.78rem; font-weight: 800; letter-spacing: 0.02em; text-transform: uppercase; }
  .mobile-hero-results li.hub strong { color: var(--accent); font-size: 1rem; }
  .mobile-hero-results li.hub img { border-radius: 50%; padding: 3px; background: var(--base); }
  .mobile-hero-results li.hub-latest a { padding-left: 1.4rem; font-size: 0.6rem; }
  .mobile-hero-results li.hub-latest a::before { content: "B3"; position: absolute; margin-left: -1rem; color: var(--muted); }
  .mobile-hero-results li.hub-latest a { position: relative; }
  .mobile-hero-results li.hub-latest + li:not(.hub):not(.hub-latest),
  .mobile-hero-results li.hub + li:not(.hub):not(.hub-latest) { border-top: 2px solid var(--accent); }
}


/* Lab (owner, 2026-09-06): card badges match the hero-card labels - small
   orange pills, bottom-left of the photo, on every catalogue card. */
.card--v2 .card-badges {
  top: auto;
  bottom: 0.35rem;
  left: 0.35rem;
  right: 0.35rem;
  gap: 0.25rem;
  align-items: flex-end;
}
.card--v2 .badge,
.card--v2 .badge--era {
  padding: 0.28rem 0.46rem;
  background: var(--accent);
  color: #fff;
  font-family: var(--font-body);
  font-size: 0.52rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1;
  text-transform: uppercase;
  border-radius: 999px;
  box-shadow: 0 3px 10px rgba(228, 87, 46, 0.38);
}
.grid--wanted .card--v2 .card-badges { top: auto; left: 0.35rem; right: 0.35rem; }


/* Lab (owner, 2026-09-06): "Football shirts by club / by country" - crest tiles,
   orange border, crest + name centred, equal heights. No counts. */
.club-logos {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--sp-4);
  padding-block: var(--sp-6) var(--sp-10);
}
.club-logo {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-3);
  min-height: 150px;
  padding: var(--sp-4) var(--sp-3);
  border: 1.5px solid var(--accent); border-radius: 12px;
  background: var(--base);
  text-decoration: none; color: var(--ink);
  text-align: center;
  transition: transform var(--t), box-shadow var(--t);
}
.club-logo:hover { transform: translateY(-2px); box-shadow: 0 0 0 1px var(--accent), 0 10px 24px rgba(228, 87, 46, 0.22); }
.club-logo img { display: block; width: 64px; height: 64px; object-fit: contain; margin: 0 auto; }
.club-logo span { display: block; width: 100%; font-family: var(--font-ui); font-size: 0.78rem; font-weight: 700; line-height: 1.2; letter-spacing: 0.01em; }
@media (max-width: 900px) {
  .club-logos { grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
  .club-logo { min-height: 118px; padding: var(--sp-3) var(--sp-2); }
  .club-logo img { width: 48px; height: 48px; }
  .club-logo span { font-size: 0.68rem; }
}


/* Lab (owner, 2026-09-06): HARD ALIGNMENT across every card row - the link
   is a full-height column, the title reserves two lines, the Add to cart bar
   is anchored to the bottom, so a one-line title never lifts the CTA. */
.grid--wanted .card--v2 { display: flex; flex-direction: column; }
.grid--wanted .card--v2 > a.mobile-shirt { display: flex; flex-direction: column; flex: 1 1 auto; height: 100%; }
.grid--wanted .card--v2 > a.mobile-shirt > span { flex: 0 0 auto; min-height: calc(2 * 1.16em + 0.9rem); }
.grid--wanted .card--v2 .mobile-shirt-buy { margin-top: auto; }
.mobile-shirt-rail .mobile-shirt { display: flex; flex-direction: column; }
.mobile-shirt-rail .mobile-shirt > span { min-height: calc(2 * 1.16em); }
.mobile-shirt-rail .mobile-shirt .mobile-shirt-buy { margin-top: auto; }
/* section head: heading and "view all" share one baseline on desktop */
.section-head { align-items: last baseline; }
.section-head .view-all { align-self: last baseline; }


/* Lab (owner, 2026-09-06): desktop cards - Add to cart + price must carry the card */
@media (min-width: 901px) {
  .grid--wanted .card--v2 .mobile-shirt-buy b {
    min-height: 48px;
    padding: 0.65rem 0.85rem;
    font-size: 0.82rem;
    letter-spacing: 0.01em;
    border-radius: 8px;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.32),
      0 6px 16px rgba(172, 52, 24, 0.42),
      0 0 22px rgba(228, 87, 46, 0.45);
  }
  .grid--wanted .card--v2 .mobile-shirt-buy b .money {
    font-size: 1.05rem;
    font-weight: 900;
    padding-left: 0.7rem;
    border-left: 1px solid rgba(255, 255, 255, 0.45);
  }
  .grid--wanted .card--v2 .mobile-add-label::before { width: 1.2rem; height: 1.2rem; font-size: 0.85rem; }
  .grid--wanted .card--v2 > a.mobile-shirt:hover .mobile-shirt-buy b { filter: brightness(1.06); transform: translateY(-1px); }
}


/* Lab (owner, 2026-09-06): desktop landing - shorter hero so Best Sellers is
   visible on arrival; intro prose hidden on desktop (kept for mobile + SEO).
   The media column stays exactly 16:9 so the person cutouts keep their
   percentage positions - the panel column just takes more of the width. */
@media (min-width: 901px) {
  .hero-slide { grid-template-columns: 46% 1fr; aspect-ratio: 3.292 / 1; }
}


/* Lab (owner, 2026-09-06): desktop card text - bigger title and season line,
   less air between ref / photo / title / CTA */
@media (min-width: 901px) {
  .grid--wanted .card--v2 > a.mobile-shirt { padding: 0.6rem 0.6rem 0.65rem; }
  .grid--wanted .card--v2 .ref { font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em; margin: 0 0 0.4rem; }
  .grid--wanted .card--v2 .card-media { margin-bottom: 0.45rem; }
  .grid--wanted .card--v2 h3 {
    margin: 0 0 0.45rem;
    font-size: 1.02rem;
    line-height: 1.12;
    letter-spacing: -0.005em;
    min-height: calc(2 * 1.12em);
  }
  .grid--wanted .card--v2 > a.mobile-shirt > span { min-height: 0; margin: 0; }
}


/* Lab (owner, 2026-09-06): desktop shirt carousel in the turf band under the hero */
@media (min-width: 901px) {
  .band--rail { padding: 1rem 0 1.1rem; min-height: 0; }
  .band--rail .rail-wrap { position: relative; padding: 0 4.5rem; }
  .band--rail .mobile-hero-shop { display: block; position: static; min-height: 0; padding: 0; background: none; }
  .band--rail .mobile-shop-h2 { display: none; }
  .band--rail .mobile-shirt-rail {
    display: flex; gap: 1rem; padding: 0.4rem 0.25rem 0.6rem;
    overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; scroll-behavior: smooth;
  }
  .band--rail .mobile-shirt-rail::-webkit-scrollbar { display: none; }
  .band--rail .mobile-shirt {
    position: relative; flex: 0 0 172px; scroll-snap-align: start;
    display: flex; flex-direction: column;
    padding: 0.55rem 0.55rem 0.65rem;
    border-radius: 12px; background: #fff; color: var(--ink); text-decoration: none;
    box-shadow: 0 0 0 1px rgba(228, 87, 46, 0.85), 0 0 12px rgba(228, 87, 46, 0.55), 0 10px 22px rgba(0, 0, 0, 0.35);
    transition: transform var(--t);
  }
  .band--rail .mobile-shirt:hover { transform: translateY(-3px); }
  .band--rail .mobile-shirt-media { position: relative; aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden; background: var(--base); }
  .band--rail .mobile-shirt-media img { width: 100%; height: 100%; object-fit: contain; }
  .band--rail .mobile-shirt-media em {
    position: absolute; left: 0.35rem; bottom: 0.35rem; padding: 0.28rem 0.46rem;
    background: var(--accent); color: #fff; font-family: var(--font-body); font-size: 0.52rem; font-style: normal;
    font-weight: 800; line-height: 1; letter-spacing: 0.01em; border-radius: 999px;
  }
  .band--rail .mobile-shirt > span {
    display: block; margin: 0.45rem 0 0.35rem; min-height: calc(2 * 1.15em);
    font-family: var(--font-ui); font-size: 0.78rem; font-weight: 700; line-height: 1.15; color: var(--ink);
  }
  .band--rail .mobile-shirt-buy { margin-top: auto; }
  .band--rail .mobile-shirt-buy b {
    display: flex; align-items: center; justify-content: space-between; gap: 0.35rem; min-height: 40px;
    padding: 0.5rem 0.65rem; border-radius: 7px;
    background: linear-gradient(135deg, #ef6840 0%, var(--accent) 58%, #d34823 100%); color: #fff;
    font-family: var(--font-body); font-size: 0.7rem; font-weight: 850; text-align: left;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.28), 0 5px 14px rgba(172, 52, 24, 0.35);
  }
  .band--rail .mobile-shirt-buy b .money { font-size: 0.9rem; font-weight: 900; padding-left: 0.5rem; border-left: 1px solid rgba(255,255,255,0.45); }
  .band--rail .mobile-add-label { display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap; }
  .band--rail .mobile-add-label::before { content: '+'; display: grid; place-items: center; width: 1.1rem; height: 1.1rem; border: 1.5px solid rgba(255,255,255,.88); border-radius: 50%; font-size: .8rem; line-height: 1; }
  .rail-arrow {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
    width: 44px; height: 44px; border-radius: 50%; border: 1.5px solid var(--accent);
    background: rgba(20, 17, 15, 0.82); color: #fff; cursor: pointer; display: grid; place-items: center;
    box-shadow: 0 0 14px rgba(228, 87, 46, 0.5);
  }
  .rail-arrow svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
  .rail-arrow--prev { left: 0.9rem; } .rail-arrow--next { right: 0.9rem; }
  .rail-arrow:hover { background: var(--accent); }
  .rail-arrow:disabled { opacity: 0.35; cursor: default; }
}


/* Lab (owner, 2026-09-06): no underline on the first word of section headings */
.section-head h2 em { border-bottom: 0; padding-bottom: 0; }


/* Lab (owner, 2026-09-06): mobile cards - the title rule was also catching the
   season line (span.ref) and reserving two lines above the photo; and the
   photo carried a 16px + 9px gap to the title. Closed both. */
@media (max-width: 900px) {
  .grid--wanted .card--v2 > a.mobile-shirt > span.ref {
    display: block; min-height: 0; margin: 0 0 0.3rem; -webkit-line-clamp: unset; overflow: visible;
    font-size: 0.68rem; line-height: 1.2;
  }
  .grid--wanted .card--v2 .card-media { margin-bottom: 0.35rem; }
  .grid--wanted .card--v2 h3 { margin-top: 0.25rem; margin-bottom: 0.3rem; }
  /* the turf band under the hero only hosts the desktop carousel */
}


/* Lab (owner, 2026-09-06): hero rail cards - title sits close to the CTA */
@media (max-width: 900px) {
  .mobile-shirt-rail .mobile-shirt > span { margin: 0.4rem 0 0.35rem; min-height: calc(2 * 1.16em); }
  .mobile-shirt-rail .mobile-shirt .mobile-shirt-buy { margin-top: auto; }
}

/* Lab (owner, 2026-09-06): flame on the Trending heading - emoji glyph, sized to the cap height, no letter-spacing */
.section-head h2 .h2-flame { display: inline-block; width: 1.05em; height: 1.05em; margin-left: 0.25em; vertical-align: -0.12em; object-fit: contain; }


/* Lab (owner, 2026-09-06): desktop card grids - six per row, tighter */
@media (min-width: 901px) {
  .grid--wanted { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 0.75rem; }
  .grid--wanted .card--v2 > a.mobile-shirt { padding: 0.5rem 0.5rem 0.55rem; }
  .grid--wanted .card--v2 .ref { font-size: 0.72rem; margin-bottom: 0.3rem; }
  .grid--wanted .card--v2 h3 { font-size: 0.9rem; line-height: 1.12; min-height: calc(2 * 1.12em); margin-bottom: 0.4rem; }
  .grid--wanted .card--v2 .mobile-shirt-buy b { min-height: 42px; padding: 0.5rem 0.65rem; font-size: 0.72rem; }
  .grid--wanted .card--v2 .mobile-shirt-buy b .money { font-size: 0.95rem; padding-left: 0.5rem; }
  .grid--wanted .card--v2 .mobile-add-label::before { width: 1rem; height: 1rem; font-size: 0.75rem; }
}
@media (min-width: 901px) and (max-width: 1250px) {
  .grid--wanted { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}


/* Lab (owner, 2026-09-06): six-up cards - the CTA bar must hold label + price without overlap */
@media (min-width: 901px) {
  .grid--wanted .card--v2 .mobile-shirt-buy b { gap: 0.3rem; padding: 0.45rem 0.5rem; font-size: 0.62rem; letter-spacing: 0; }
  .grid--wanted .card--v2 .mobile-shirt-buy b .money { font-size: 0.84rem; padding-left: 0.4rem; flex: 0 0 auto; }
  .grid--wanted .card--v2 .mobile-add-label { min-width: 0; overflow: hidden; }
  .grid--wanted .card--v2 .mobile-add-label::before { width: 0.9rem; height: 0.9rem; font-size: 0.7rem; flex: 0 0 auto; }
}
@media (min-width: 1500px) {
  .grid--wanted .card--v2 .mobile-shirt-buy b { font-size: 0.7rem; padding: 0.5rem 0.65rem; }
  .grid--wanted .card--v2 .mobile-shirt-buy b .money { font-size: 0.95rem; }
}


/* Lab (owner, 2026-09-06): the HOMEPAGE grids carry 12 cards for desktop (2 x 6);
   phones show the first 8.
   2026-09-19: scoped to the homepage. cards.js adds .grid--wanted to EVERY grid
   that holds a v2 card (for the add-to-cart bar), so the bare selector hid card
   9+ of every hub, collection and journal grid on phones: /new/ showed 8 of 672
   shirts, /journal/ 8 of 45 posts, each club-hub section 8 of up to 60 - and
   Google indexes the mobile render, so those cards were discounted copy.
   Anchored on the hero carousel: only the eight home pages carry
   `body > section#hero` followed by the `.wrap` that holds their grids. */
@media (max-width: 900px) {
  #hero ~ .wrap .grid--wanted .card--v2:nth-child(n+9) { display: none; }
}

/* Lab: the looping rail manages its own scroll position */
.mobile-shirt-rail { overflow-anchor: none; }


/* Lab (owner, 2026-09-06): desktop - content fills the width, and the first
   section sits close under the carousel */
@media (min-width: 901px) {
  .wrap { max-width: none; padding-inline: 2.5rem; }
  .band--rail { padding-bottom: 0.5rem; }
  .band--rail .mobile-hero-down { display: none; }
  #best-sellers { padding-top: 0.9rem; }
  .band--rail .rail-wrap { padding: 0 3.6rem; }
  .rail-arrow--prev { left: 0.5rem; } .rail-arrow--next { right: 0.5rem; }
}


/* Lab (owner, 2026-09-06): hero text panel - turf texture, floodlight glow,
   ghosted slide index. Panel stays dark; type untouched. Desktop only. */
@media (min-width: 901px) {
  .hero-panel { position: relative; isolation: isolate; }
  .hero-panel::before {
    content: ""; position: absolute; inset: 0; z-index: -2; pointer-events: none;
    background:
      radial-gradient(ellipse 70% 60% at 0% 0%, rgba(228, 87, 46, 0.28) 0%, rgba(228, 87, 46, 0) 60%),
      radial-gradient(ellipse 60% 50% at 100% 100%, rgba(228, 87, 46, 0.12) 0%, rgba(228, 87, 46, 0) 65%),
      url("/assets/turf/turf-line.webp") center / cover no-repeat;
    opacity: 1;
  }
  .hero-panel::after {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background: linear-gradient(90deg, rgba(20, 17, 15, 0.72) 0%, rgba(20, 17, 15, 0.86) 60%, rgba(20, 17, 15, 0.95) 100%);
  }
  /* ghosted index bottom-right of the panel */
  .hero-panel .hero-ghost {
    position: absolute; right: 1.2rem; bottom: -0.35em; z-index: -1; pointer-events: none;
    font-family: var(--font-display); font-weight: var(--wght-display); font-stretch: var(--wdth-display);
    font-size: clamp(6rem, 12vw, 11rem); line-height: 1; letter-spacing: -0.04em;
    color: rgba(244, 241, 234, 0.06);
  }
}

@media (min-width: 901px) {
  /* the intro/lead sections keep 48px of padding even with the prose hidden */
  section.lead { padding-top: 0; padding-bottom: 0; }
  section.lead > .grid--wanted { padding-top: 0.25rem; }
}


/* Lab (owner, 2026-09-06): hero search dropdown - never cropped, card-like
   rows, crest in a disc, orange chevron button instead of a bare arrow */
@media (max-width: 900px) {
  .mobile-hero-results {
    max-height: min(62svh, 480px);
    padding: 0.35rem;
    border: 1px solid rgba(20, 17, 15, 0.12);
    border-radius: 12px;
    background: #fff;
    box-shadow: 0 0 0 1.5px var(--accent), 0 0 22px rgba(228, 87, 46, 0.35), 0 18px 34px rgba(0, 0, 0, 0.5);
  }
  .mobile-hero-results li + li { border-top: 0; }
  .mobile-hero-results li a {
    grid-template-columns: 44px 1fr auto; gap: 0.6rem; padding: 0.45rem 0.5rem; border-radius: 9px;
    font-family: var(--font-body); font-size: 0.74rem; font-weight: 600; line-height: 1.2;
  }
  .mobile-hero-results li a:active { background: rgba(228, 87, 46, 0.08); }
  .mobile-hero-results img { width: 44px; height: 44px; border-radius: 8px; object-fit: cover; background: var(--base); }
  .mobile-hero-results strong { color: var(--accent); font-family: var(--font-body); font-size: 0.76rem; font-weight: 800; }
  /* hub row */
  .mobile-hero-results li.hub a {
    background: linear-gradient(90deg, rgba(228, 87, 46, 0.10), rgba(228, 87, 46, 0));
    font-family: var(--font-ui); font-size: 0.8rem; font-weight: 800; letter-spacing: 0.02em; text-transform: uppercase;
  }
  .mobile-hero-results li.hub img { border-radius: 50%; padding: 4px; background: var(--base); box-shadow: 0 0 0 1px rgba(20, 17, 15, 0.12); object-fit: contain; }
  .mobile-hero-results li.hub strong {
    display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
    background: var(--accent); color: #fff; font-size: 1rem; line-height: 1;
    box-shadow: 0 3px 10px rgba(228, 87, 46, 0.45);
  }
  /* the hub's latest shirt */
  .mobile-hero-results li.hub-latest a { padding-left: 0.5rem; font-size: 0.72rem; }
  .mobile-hero-results li.hub-latest a::before { content: none; }
  .mobile-hero-results li.hub-latest span::after {
    content: "LATEST"; display: inline-block; margin-left: 0.4rem; padding: 0.12rem 0.38rem;
    border-radius: 999px; background: var(--ink); color: #fff; font-size: 0.52rem; font-weight: 800; letter-spacing: 0.06em; vertical-align: middle;
  }
  .mobile-hero-results li.hub-latest + li:not(.hub):not(.hub-latest),
  .mobile-hero-results li.hub + li:not(.hub):not(.hub-latest) { border-top: 1px solid rgba(20, 17, 15, 0.1); margin-top: 0.2rem; padding-top: 0.2rem; }
  .mobile-hero-results .none { padding: 0.8rem; font-family: var(--font-body); font-size: 0.74rem; }
}

@media (max-width: 900px) {
  /* the search dropdown must be able to spill below the panel */
  .hero-panel { overflow: visible; }
  .mobile-hero-search { z-index: 40; }
}


/* Lab (owner, 2026-09-06): hub read-more - the toggle sits at the end of the
   second line, and the next section follows close behind */
.readmore { padding-block: var(--sp-3) var(--sp-2); }
.readmore:not(.open) .readmore-body p { margin-bottom: 0; }
.readmore:not(.open) .readmore-body { max-height: 3.1em; }
.readmore:not(.open) .readmore-btn {
  float: right; position: relative; z-index: 2;
  margin: -1.55em 0 0; padding: 0 0 0 0.75rem;
  background: linear-gradient(90deg, rgba(244, 241, 234, 0) 0%, var(--base) 22%);
  line-height: 1.55;
}
.readmore.open .readmore-btn { display: inline-block; margin-top: var(--sp-2); }
.readmore::after { content: ""; display: table; clear: both; }
.readmore + .section-head { padding-top: var(--sp-4); }


/* Lab (owner, 2026-09-06): hubs on mobile - no dead space where the hidden
   intro sat. 2026-09-19: the .grid-note ("The latest kits - home, away and
   third", "Showing N of M") is no longer hidden either - same reason as the
   intro on 2026-09-10: Google indexes the mobile render, and hidden copy is
   copy Google discounts. Spacing kept. */
@media (max-width: 900px) {
  section.lead { padding-top: 0; padding-bottom: 0; }
  .grid-note { margin-bottom: var(--sp-4); }
  .hub-head { padding-bottom: var(--sp-3); }
  .hub-head + section.lead + .section-head, .hub-head + .section-head { padding-top: var(--sp-4); }
}

/* Lab (owner, 2026-09-06): hub strapline and its blurb sit together */
h2.readmore-sub { margin-bottom: 0.15rem; line-height: 1.3; }
.readmore-body p { line-height: 1.45; }


/* Lab (owner, 2026-09-07): browse hubs - 100 on arrival, Show more button;
   in-hub search styled like the hero search */
/* 2026-09-10: .card.is-more is no longer hidden - every card renders for
   crawlers and visitors alike; the Show more control is retired. */
.card.is-more { content-visibility: auto; contain-intrinsic-size: 0 420px; }
/* 2026-09-20: browse grids are paginated (/page/N/, 96 cards a page) - the
   pager sits under the grid; the range ("97–192 of 671") rides the shop bar */
.shop-range { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--muted); margin-left: var(--sp-3); align-self: center; }
.pager { display: flex; align-items: center; justify-content: center; gap: var(--sp-3); flex-wrap: wrap; padding: var(--sp-8) 0 var(--sp-6); font-family: var(--font-ui); font-size: 0.86rem; font-weight: 700; }
.pager-nums { display: inline-flex; align-items: center; gap: var(--sp-1); }
.pager-n { min-width: 2.4rem; padding: 0.55rem 0.6rem; text-align: center; border: 1.5px solid var(--rule-c); border-radius: 999px; color: var(--ink); text-decoration: none; background: var(--base); }
a.pager-n:hover, .pager-prev:hover, .pager-next:hover { background: var(--ink); color: var(--base); border-color: var(--ink); }
.pager-n[aria-current="page"] { background: var(--ink); color: var(--base); border-color: var(--ink); }
.pager-gap { padding: 0 0.25rem; color: var(--muted); }
.pager-prev, .pager-next { padding: 0.55rem 0.9rem; border: 1.5px solid var(--rule-c); border-radius: 999px; color: var(--ink); text-decoration: none; background: var(--base); white-space: nowrap; }
.pager-prev.is-off, .pager-next.is-off { opacity: 0.35; }
@media (max-width: 640px) { .pager { gap: var(--sp-2); } .pager-n { min-width: 2.1rem; padding: 0.5rem 0.45rem; } .shop-range { display: block; margin: var(--sp-1) 0 0; width: 100%; } }
.show-more-wrap { display: none !important; }
.show-more-wrap-retired { display: flex; justify-content: center; padding: var(--sp-6) 0 var(--sp-8); }
.show-more {
  padding: 0.85rem 1.6rem; border-radius: 999px; border: 1.5px solid var(--accent);
  background: var(--accent); color: #fff; font-family: var(--font-ui); font-size: 0.86rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase;
  cursor: pointer; box-shadow: 0 6px 18px rgba(228, 87, 46, 0.4);
}
.show-more:hover { filter: brightness(1.06); transform: translateY(-1px); }
.shop-search { margin-bottom: var(--sp-5); }
.shop-search input {
  padding: 0.9rem 2.6rem 0.9rem 2.7rem;
  font-family: var(--font-body); font-size: 0.95rem; font-weight: 500;
  background: #fff; border: 2px solid var(--accent); border-radius: 12px;
  box-shadow: 0 0 0 3px rgba(228, 87, 46, 0.14), 0 0 22px rgba(228, 87, 46, 0.22);
}
.shop-search input:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(228, 87, 46, 0.28), 0 0 26px rgba(228, 87, 46, 0.35); }
.shop-search-i { left: 0.95rem; width: 20px; height: 20px; stroke: var(--accent); stroke-width: 2; }
.shop-search button { right: 0.6rem; width: 32px; height: 32px; border-radius: 50%; background: var(--accent); color: #fff; font-size: 1rem; display: grid; place-items: center; padding: 0; }
.shop-search button:hover { color: #fff; filter: brightness(1.08); }

.shop-search button[hidden] { display: none; }

/* Lab (owner, 2026-09-07): guide internal links must read as links */
.guide a { color: var(--accent); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; }
.guide a:hover { text-decoration-thickness: 2px; }

/* Lab (owner, 2026-09-07): Original badges dropdown, one option per badge */
.badge-select { width: 100%; margin: 0 0 var(--sp-4); padding: .7rem 2.4rem .7rem .9rem; font: 600 .95rem/1.2 var(--font-ui); color: var(--ink); background: var(--base) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2314110F' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>") no-repeat right .8rem center/1rem; border: 1.5px solid var(--ink); border-radius: 4px; appearance: none; -webkit-appearance: none; cursor: pointer; }
.badge-select:focus { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Lazy rendering (owner, 2026-09-07): off-screen cards are skipped by layout and
   paint until they scroll near the viewport - the 800-card hubs stop costing a
   full render up front. Images already carry loading="lazy"; this is the DOM side. */
.grid .card, .grid--wanted .card, .journal .post { content-visibility: auto; contain-intrinsic-size: auto 340px; }
.faq details, .guide { content-visibility: auto; contain-intrinsic-size: auto 600px; }

/* Nav one line on laptops (owner, 2026-09-07): between the 900px hamburger and
   ~1500px the nav used to wrap to a second row. Shrink type and gaps with the
   viewport instead, and never wrap. */
@media (min-width: 1101px) and (max-width: 1560px) {
  .nav { flex-wrap: nowrap; gap: clamp(0.4rem, 1.2vw - 0.25rem, 2rem); }
  .nav a { font-size: clamp(0.68rem, 1.25vw - 0.28rem, 0.9375rem); letter-spacing: 0.045em; white-space: nowrap; }
  .brand img { width: clamp(104px, 9vw, 137px); height: auto; }
}
/* laptop header: tighter utils and a narrower search field so the nav keeps its line */
@media (min-width: 901px) and (max-width: 1560px) {
  .utils { gap: clamp(0.6rem, 1.2vw, 1.5rem); }
  .search input { width: clamp(96px, 9vw, 160px); }
  .nav { margin-inline: clamp(0.75rem, 1.5vw, 2rem); }
}
.pdp-details {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  margin: 0 0 1.5rem;
  border-top: var(--rule);
}
.pdp-details > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: .15rem;
  padding: .7rem 0;
  border-bottom: var(--rule);
  min-width: 0;
}
.pdp-details > div:nth-child(odd) { margin-right: 1.5rem; }
.pdp-details dt { font-family: var(--font-ui); font-weight: 700; }
.pdp-details dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 640px) {
  .pdp-details { grid-template-columns: 1fr; }
  .pdp-details > div:nth-child(odd) { margin-right: 0; }
}

/* ---- cart.css ---- */
/* ============================================================
   Cart drawer — Storefront API basket. Colours via tokens only.
   ============================================================ */
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; padding: 0; margin: -1px; }

/* Add-to-cart CTA — orange, glowing, larger + bolder (owner, 2026-08-10) */
.buy-cta {
  background: var(--accent);
  font-family: var(--font-card);
  font-weight: 760;
  font-size: 1.12rem;
  padding: var(--sp-4);
  box-shadow: 0 4px 20px rgba(228, 87, 46, 0.45);
  transition: background var(--t), box-shadow var(--t), filter var(--t);
}
.buy-cta:hover { background: var(--accent); filter: brightness(0.96); box-shadow: 0 6px 26px rgba(228, 87, 46, 0.62); }
/* "Yes" for printing + badges turns orange when selected, not black */
#printYes.sel, #badgeYes.sel { background: var(--accent); border-color: var(--accent); color: var(--base); }

/* Trust row: equal-height items when stacked on mobile so they read uniform */
@media (max-width: 640px) {
  .trust-item { min-height: 84px; align-items: center; }
}

/* Sticky add-to-cart bar (appears when the main CTA scrolls away) */
.sticky-buy { position: fixed; left: 0; right: 0; bottom: 0; z-index: 800; display: none; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--base); border-top: 1px solid var(--rule-c); box-shadow: 0 -6px 22px rgba(20, 17, 15, 0.12); }
.sticky-buy.on { display: flex; }
.sb-img { width: 42px; height: 42px; object-fit: cover; border-radius: var(--radius); background: var(--base-warm); flex: 0 0 auto; }
.sb-info { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.sb-name { font: 680 0.9rem var(--font-card); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sb-price { font: 740 0.9rem var(--font-card); }
.sb-size { position: relative; flex: 0 0 auto; }
.sb-size-btn { min-width: 66px; border: 1px solid var(--rule-c); border-radius: var(--radius); padding: var(--sp-2) var(--sp-3); font: 600 0.85rem var(--font-mono); background: var(--base); color: var(--muted); cursor: pointer; text-align: left; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.sb-size-btn.chosen { color: var(--ink); }
.sb-size-btn::after { content: "\25B2"; font-size: 0.55em; opacity: 0.55; }
.sb-size-menu { position: absolute; bottom: calc(100% + 6px); left: 0; margin: 0; padding: 4px; list-style: none; min-width: 100%; max-height: 46vh; overflow-y: auto; background: var(--base); border: 1px solid var(--rule-c); border-radius: var(--radius); box-shadow: 0 -8px 24px rgba(20, 17, 15, 0.18); z-index: 810; }
.sb-size-menu[hidden] { display: none; }
.sb-size-menu li { padding: var(--sp-2) var(--sp-4); border-radius: var(--radius); cursor: pointer; font: 600 0.9rem var(--font-mono); color: var(--ink); }
.sb-size-menu li:hover, .sb-size-menu li.sel { background: var(--ink); color: var(--base); }
.sb-add { background: var(--accent); color: var(--base); border: 0; border-radius: var(--radius); padding: var(--sp-3) var(--sp-6); font: 740 0.95rem var(--font-card); text-transform: uppercase; letter-spacing: 0.01em; cursor: pointer; flex: 0 0 auto; box-shadow: 0 2px 14px rgba(228, 87, 46, 0.42); }
.sb-add:hover { filter: brightness(0.96); }
@media (max-width: 560px) { .sb-price { display: none; } .sb-add { padding: var(--sp-3) var(--sp-4); font-size: 0.85rem; } .sb-name { font-size: 0.82rem; } }

/* Ships-by estimate under the CTA */
.ship-eta { margin: var(--sp-3) 0 0; font: 500 0.85rem var(--font-ui); color: var(--ink); display: flex; align-items: center; gap: var(--sp-2); }
.ship-eta strong { font-weight: 700; }
.ship-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--green); display: inline-block; flex: 0 0 auto; }

/* Size-guide modal */
.buy-label-row { display: flex; align-items: baseline; justify-content: space-between; }
.size-guide-link { background: none; border: 0; cursor: pointer; font: 600 0.8rem var(--font-ui); color: var(--accent); text-decoration: underline; padding: 0; }
.sg-modal { position: fixed; inset: 0; z-index: 902; display: flex; align-items: center; justify-content: center; }
.sg-modal[hidden] { display: none; }
.sg-overlay { position: absolute; inset: 0; background: rgba(20, 17, 15, 0.5); }
.sg-box { position: relative; z-index: 1; background: var(--base); color: var(--ink); border-radius: var(--radius); max-width: 460px; width: 92vw; max-height: 86vh; overflow-y: auto; padding: var(--sp-6); box-shadow: 0 20px 60px rgba(20, 17, 15, 0.32); }
.sg-close { position: absolute; top: var(--sp-3); right: var(--sp-4); background: none; border: 0; font-size: 1.5rem; line-height: 1; cursor: pointer; color: var(--muted); }
.sg-close:hover { color: var(--ink); }
.sg-box h3 { margin: 0 0 2px; font: 760 1.2rem var(--font-card); }
.sg-fit { font: 600 0.76rem var(--font-ui); text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin: 0 0 var(--sp-4); }
.sg-measure h4 { margin: var(--sp-4) 0 var(--sp-2); font: 700 0.9rem var(--font-card); }
.sg-measure p { font: 400 0.85rem/1.5 var(--font-ui); color: var(--muted); margin: 0; }
.player-intro > summary { cursor: pointer; font: 680 0.95rem var(--font-card); color: var(--accent); list-style: none; padding: var(--sp-2) 0; }
.player-intro > summary::-webkit-details-marker { display: none; }
.account-link { display: flex; align-items: center; color: inherit; opacity: 0.9; transition: opacity var(--t); }
.account-link:hover { opacity: 1; }
.bag { position: relative; }
.bag-count {
  position: absolute; top: -6px; right: -6px;
  min-width: 17px; height: 17px; padding: 0 4px;
  background: var(--accent); color: var(--base);
  font: 700 11px/17px var(--font-ui);
  border-radius: 999px; text-align: center;
  display: none;
}
.bag-count.on { display: block; }

.cart-overlay {
  position: fixed; inset: 0; z-index: 900;
  background: rgba(20, 17, 15, 0.5);
  opacity: 0; transition: opacity .2s ease;
}
.cart-overlay.open { opacity: 1; }

.cart-drawer {
  position: fixed; top: 0; right: 0; z-index: 901;
  width: min(420px, 92vw); height: 100%;
  background: var(--base); color: var(--ink);
  border-left: 1px solid var(--rule-c);
  display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform .24s ease;
  box-shadow: -8px 0 30px rgba(20, 17, 15, 0.18);
}
.cart-drawer.open { transform: translateX(0); }

.cart-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4) var(--sp-6);
  border-bottom: 1px solid var(--rule-c);
}
.cart-head h2 { margin: 0; font: 740 1.15rem/1 var(--font-card); letter-spacing: -0.01em; }
.cart-x {
  background: none; border: 0; cursor: pointer;
  font-size: 1.6rem; line-height: 1; color: var(--muted); padding: 0 4px;
}
.cart-x:hover { color: var(--ink); }

.cart-body { flex: 1; overflow-y: auto; padding: var(--sp-4) var(--sp-6); }
.cart-empty { color: var(--muted); font: 400 .95rem/1.5 var(--font-ui); padding: var(--sp-8) 0; text-align: center; }

.cart-line { display: grid; grid-template-columns: 56px 1fr auto; gap: var(--sp-3); padding: var(--sp-4) 0; border-bottom: 1px solid var(--rule-c); }
.cart-line-img { width: 56px; height: 56px; background: var(--base-warm); border-radius: var(--radius); overflow: hidden; }
.cart-line-img img { width: 100%; height: 100%; object-fit: cover; }
.cart-line-info { min-width: 0; }
.cart-line-name { font: 680 .9rem/1.2 var(--font-card); margin: 0 0 2px; }
.cart-line-meta { font: 400 .78rem/1.35 var(--font-ui); color: var(--muted); }
.cart-line-print { font: 400 .78rem/1.35 var(--font-ui); color: var(--accent); }
.cart-line-right { display: flex; flex-direction: column; align-items: flex-end; justify-content: space-between; }
.cart-line-price { font: 740 .9rem/1 var(--font-card); text-align: right; }
/* the discounted line states its own outcome, so the footer total is a
   confirmation rather than the only place the offer is visible */
.cart-line-price .was { display: block; font-weight: 400; color: var(--muted);
  text-decoration: line-through; margin-bottom: 2px; }
.cart-line-price .cart-free { display: block; color: var(--accent); letter-spacing: .04em; }
.cart-line-offer { font-weight: 600; }
.cart-qty { display: inline-flex; align-items: center; border: 1px solid var(--rule-c); border-radius: var(--radius); }
.cart-qty button { background: none; border: 0; width: 24px; height: 24px; cursor: pointer; color: var(--ink); font-size: .95rem; line-height: 1; }
.cart-qty button:disabled { color: var(--muted); cursor: default; }
.cart-qty span { min-width: 22px; text-align: center; font: 600 .82rem var(--font-mono); }
.cart-remove { background: none; border: 0; cursor: pointer; color: var(--muted); font: 400 .72rem var(--font-ui); text-decoration: underline; padding: 0; margin-top: 4px; }

.cart-foot { border-top: 1px solid var(--rule-c); padding: var(--sp-4) var(--sp-6) var(--sp-6); }
.cart-note { font: 400 .8rem/1.4 var(--font-ui); color: var(--muted); margin: 0 0 var(--sp-3); }
/* discount code: a single row - input + Apply - that collapses to the
   applied code once Shopify accepts it. The drawer shows Shopify's verdict,
   never its own arithmetic, so the saving row below is the real allocation. */
.cart-code { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-4); }
.cart-code input { flex: 1 1 auto; min-width: 0; padding: var(--sp-2) var(--sp-3); border: 1px solid var(--rule-c); border-radius: var(--radius); background: var(--base); color: var(--ink); font: 600 .85rem var(--font-mono); letter-spacing: .04em; text-transform: uppercase; }
.cart-code input::placeholder { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--muted); }
.cart-code input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.cart-code button[type=submit] { flex: 0 0 auto; padding: var(--sp-2) var(--sp-4); border: 1px solid var(--ink); border-radius: var(--radius); background: var(--ink); color: var(--base); font: 740 .8rem var(--font-card); text-transform: uppercase; letter-spacing: .02em; cursor: pointer; }
.cart-code button[type=submit]:hover { background: var(--accent); border-color: var(--accent); }
.cart-code-on { padding: var(--sp-2) var(--sp-3); border: 1px dashed var(--accent); border-radius: var(--radius); background: var(--base-warm); }
.cart-code-tag { font: 600 var(--fs-micro)/1 var(--font-mono); letter-spacing: var(--tr-wide); text-transform: uppercase; color: var(--muted); }
.cart-code-on strong { font: 700 .9rem var(--font-mono); letter-spacing: .06em; color: var(--ink); }
.cart-code-ok { font: 600 .78rem var(--font-ui); color: var(--accent); flex: 1 1 auto; }
.cart-code-x { background: none; border: 0; color: var(--muted); font-size: 1.1rem; line-height: 1; cursor: pointer; padding: 0 var(--sp-1); }
.cart-code-x:hover { color: var(--accent); }
.cart-code-msg { margin: calc(var(--sp-3) * -1) 0 var(--sp-4); font: 400 .78rem/1.4 var(--font-ui); color: var(--accent); }
.cart-subtotal { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: var(--sp-4); }
.cart-subtotal .lab { font: 600 .95rem var(--font-ui); }
.cart-subtotal .val { font: 740 1.35rem/1 var(--font-card); }
/* Subtotal and the saving are the working-out; Total is the number the
   customer is charged, so it keeps the big numeral and the others step down. */
.cart-drawer:has(.cart-saving) .cart-subtotal:not(.cart-total) { margin-bottom: var(--sp-2); }
.cart-drawer:has(.cart-saving) .cart-subtotal:not(.cart-total) .lab { font-weight: 400; color: var(--muted); }
.cart-drawer:has(.cart-saving) .cart-subtotal:not(.cart-total) .val { font-size: 1rem; color: var(--muted); }
/* specificity has to match the :has() rule above, or the muted override wins
   and the saving — the whole point of the row — renders as grey small print */
.cart-drawer:has(.cart-saving) .cart-saving .val { color: var(--accent); font-weight: 740; }
.cart-total { margin-top: var(--sp-3); }
.cart-checkout {
  display: block; width: 100%; text-align: center;
  padding: var(--sp-4); border: 0; border-radius: var(--radius); cursor: pointer;
  background: var(--accent); color: var(--base);
  font: 740 1rem var(--font-card); letter-spacing: 0.01em; text-transform: uppercase;
}
.cart-checkout:hover { filter: brightness(0.94); }
.cart-secure { text-align: center; font: 400 .72rem var(--font-ui); color: var(--muted); margin: var(--sp-3) 0 0; }
.cart-busy { opacity: .55; pointer-events: none; }

/* offer nudge at the top of the drawer: distance to the next free shirt */
.cart-nudge, .cart-pop { position: relative; margin: 0 0 var(--sp-4); padding: var(--sp-4) var(--sp-4) var(--sp-4); background: var(--panel-bg); color: var(--panel-fg); border-radius: var(--radius); overflow: hidden; }
.cart-nudge::before, .cart-pop::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--accent); }
.cart-nudge-tag { display: inline-block; font: 600 var(--fs-micro)/1 var(--font-mono); letter-spacing: var(--tr-wide); text-transform: uppercase; color: var(--accent); margin-bottom: var(--sp-2); }
.cart-nudge-head { margin: 0 0 var(--sp-1); font-family: var(--font-display); font-weight: var(--wght-display); font-stretch: var(--wdth-display); font-size: 1.75rem; line-height: .95; letter-spacing: var(--tr-tight); text-transform: uppercase; color: var(--panel-fg); }
.cart-nudge-sub { margin: 0 0 var(--sp-3); font: 400 .88rem/1.4 var(--font-ui); color: var(--panel-fg); opacity: .8; }
.cart-nudge-track { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-1); }
.cart-nudge-track span { display: block; padding: var(--sp-1) 0; text-align: center; font: 600 var(--fs-micro)/1 var(--font-mono); letter-spacing: var(--tr-wide); color: var(--panel-fg); opacity: .45; border-radius: 2px; background: var(--band-rule); transition: background var(--t), opacity var(--t); }
.cart-nudge-track span.on { background: var(--accent); opacity: 1; }
.cart-nudge-cta { display: inline-block; margin-top: var(--sp-3); font: 600 var(--fs-mono)/1 var(--font-mono); letter-spacing: .04em; color: var(--panel-fg); text-decoration: none; border-bottom: 1px solid var(--accent); padding-bottom: 2px; }
.cart-nudge-cta:hover { color: var(--accent); }
.cart-nudge.is-unlocked::before, .cart-nudge.is-unlocked .cart-nudge-track span.on { background: var(--green); }
.cart-nudge.is-unlocked .cart-nudge-tag { color: var(--panel-fg); opacity: .7; }
.cart-nudge.pulse { animation: cart-nudge-pulse .9s ease-out 1; }
@keyframes cart-nudge-pulse { 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(228, 87, 46, .55); } 40% { transform: scale(1.025); } 100% { transform: scale(1); box-shadow: 0 0 0 14px rgba(228, 87, 46, 0); } }
/* popover over the Add to cart button that was just pressed */
.cart-pop { position: absolute !important; left: 0; right: 0; z-index: 905; margin: 0; box-shadow: 0 18px 44px rgba(20, 17, 15, 0.35); opacity: 0; transform: translateY(8px); transition: opacity 180ms ease, transform 180ms ease; }
.cart-pop.in { opacity: 1; transform: translateY(0); }
.cart-pop::after { content: ""; position: absolute; left: 32px; bottom: -8px; width: 16px; height: 16px; background: var(--panel-bg); transform: rotate(45deg); }
.cart-pop .cart-nudge-head { font-size: 1.5rem; }
.cart-pop-x { position: absolute; top: var(--sp-2); right: var(--sp-2); width: 28px; height: 28px; border: 0; background: none; color: var(--panel-fg); font-size: 1.25rem; line-height: 1; cursor: pointer; opacity: .7; }
.cart-pop-x:hover { opacity: 1; }
.cart-pop-view { display: inline-block; margin: var(--sp-3) 0 0 var(--sp-4); border: 0; background: none; padding: 0 0 2px; font: 600 var(--fs-mono)/1 var(--font-mono); letter-spacing: .04em; color: var(--panel-fg); opacity: .75; border-bottom: 1px solid var(--band-rule); cursor: pointer; }
.cart-pop-view:hover { opacity: 1; }
.cart-pop.is-unlocked::before { background: var(--green); }

/* ---- free mystery shirt offer (cart.js reconcileMystery) ---- */
.cart-mystery { display: flex; gap: var(--sp-3); align-items: center; margin: 0 0 var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--accent); color: var(--base); border-radius: var(--radius); }
.cart-mystery-ico { flex: 0 0 36px; height: 36px; display: grid; place-items: center; font: 800 1.25rem/1 var(--font-display); background: rgba(20, 17, 15, .22); border-radius: 50%; }
.cart-mystery strong { display: block; font: 700 .92rem/1.2 var(--font-card); text-transform: uppercase; letter-spacing: .02em; }
.cart-mystery span { display: block; font: 400 .76rem/1.3 var(--font-ui); opacity: .92; }
.cart-line.is-mystery .cart-mystery-tile { display: grid; place-items: center; font: 800 1.6rem/1 var(--font-display); color: var(--accent); background: var(--band-rule); }
.cart-nudge-mystery { color: var(--accent); opacity: 1; font-weight: 600; }
.buy-mystery { display: flex; align-items: center; gap: var(--sp-2); margin: var(--sp-3) 0 0; padding: var(--sp-2) var(--sp-3); border: 1px dashed var(--accent); border-radius: var(--radius); color: var(--accent); font: 600 .8rem/1.3 var(--font-ui); }
.buy-mystery b { display: inline-grid; place-items: center; flex: 0 0 22px; width: 22px; height: 22px; border-radius: 50%; background: var(--accent); color: var(--base); font: 800 .8rem/1 var(--font-display); }
