/* ============================================================
   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-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 { max-width: 78ch; 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 {
  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;
    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: hidden on mobile - the H2 strapline + read-more carry it there */
@media (max-width: 640px) {
  .hub-standfirst { display: none; }
  .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); }

@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; }
}
@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-slide { aspect-ratio: auto; }
  .hero-media { aspect-ratio: 16 / 9; height: auto; }
  .hero-panel { padding: var(--sp-6) var(--gutter) var(--sp-8); }
  .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); }

.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: 78ch; }

/* ============================================================
   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. */
  .hero-slide { grid-template-rows: auto 1fr; }
}

/* ============================================================
   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) {
  .trust,
  .trust--spaced { display: none; }
  .lead > .lead-body,
  .lead > p:not(.grid-note) { display: none; }
  /* 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; }

  /* 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; }
}
