/* ==========================================================================
   Mataf Industries - main stylesheet
   Load order: tokens.css, then this file.
   Section padding lives on .section only, so specificity never fights itself.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Base
   -------------------------------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--step-0);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
  /* Last-resort guard against sideways scroll. clip, not hidden, so the
     sticky header keeps working. */
  overflow-x: clip;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol, fieldset { margin: 0; }
ul, ol { padding: 0; list-style: none; }
fieldset { border: 0; padding: 0; min-width: 0; }

img, svg, video { display: block; max-width: 100%; height: auto; }
iframe, embed, object { max-width: 100%; }
a[href^="mailto:"] { overflow-wrap: anywhere; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.18em; }

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

::selection { background: var(--accent); color: var(--white); }

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

.skip-link {
  position: absolute; top: 0; left: var(--gutter);
  transform: translateY(-120%); z-index: 100;
  background: var(--accent); color: var(--white);
  padding: var(--space-2xs) var(--space-s);
  font-size: var(--step--1); font-weight: 500;
  transition: transform 160ms var(--ease);
}
.skip-link:focus-visible { transform: translateY(0); }

/* --------------------------------------------------------------------------
   2. Typography roles
   -------------------------------------------------------------------------- */

.display-xl, .display-l, .display-m, .display-s {
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800;
  line-height: var(--lh-tight);
  /* Condensed type is already tight, so it needs far less negative tracking. */
  letter-spacing: -0.005em;
  text-wrap: balance;
}

.display-xl { font-size: var(--step-7); font-weight: 900; }
.display-l  { font-size: var(--step-5); }
.display-m  { font-size: var(--step-4); line-height: var(--lh-snug); }
.display-s  { font-size: var(--step-2); font-stretch: var(--wd-normal); letter-spacing: -0.01em; line-height: var(--lh-snug); }

.lede {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--ink-60);
  max-width: 46ch;
}

.meta { font-size: var(--step--1); color: var(--ink-60); }

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--space-m); }
.prose h2 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-3); font-weight: 700; letter-spacing: -0.005em; line-height: var(--lh-snug); margin-top: var(--space-xl); }
.prose h3 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-1); font-weight: 600; letter-spacing: -0.005em; margin-top: var(--space-l); }
.prose ul { padding-left: 1.2em; }
.prose ul li { position: relative; }
.prose ul li + li { margin-top: var(--space-2xs); }
.prose ul li::before { content: ''; position: absolute; left: -1em; top: 0.68em; width: 0.5em; height: 2px; background: var(--accent); }
.prose ol { counter-reset: n; padding-left: 1.6em; }
.prose ol li { counter-increment: n; position: relative; }
.prose ol li + li { margin-top: var(--space-2xs); }
.prose ol li::before { content: counter(n) '.'; position: absolute; left: -1.6em; color: var(--accent); font-weight: 600; }
.prose a { text-decoration: underline; }
.prose a:hover { color: var(--accent); }
.prose strong { font-weight: 600; }
.prose blockquote { border-left: 3px solid var(--accent); padding-left: var(--space-m); font-size: var(--step-1); line-height: 1.5; }

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */

.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.container-narrow { max-width: var(--container-narrow); }

.section { padding-block: var(--section-y); }
.section-tight { padding-block: calc(var(--section-y) * 0.6); }

.on-paper { background: var(--paper); }
.on-ink { background-color: var(--ink); background-image: var(--gloss); color: var(--on-dark); }
.on-ink .lede, .on-ink .meta { color: var(--on-dark-60); }

/* --------------------------------------------------------------------------
   Section heads
   Every section opener on the site is styled from here, once. A section only
   ever needs the bare markup:

     <div class="section-head">
       <h2>Twelve sports, one factory</h2>
       <p>We build team uniforms across all of them…</p>
     </div>

   No utility classes on the heading, no lede class on the paragraph, and
   nothing to add to the stylesheet when a new section appears. The heading
   and the paragraph are set by their element, inside this one component.
   -------------------------------------------------------------------------- */

/*
 * Width is set in rem, not ch. A ch on this element resolves against body
 * size, so a `ch` cap here was measuring the paragraph and then applying
 * that same width to a 53px display heading, wrapping headings far earlier
 * than they needed to. The heading gets the full width; the paragraph is
 * held tighter by its own rule below.
 */
.section-head {
  max-width: 42rem;
  margin-bottom: var(--head-gap);
}

/* Spacing lives on the stack, so a section head can carry two elements or
   four without anything needing a bespoke margin. */
.section-head > * + * { margin-top: var(--space-s); }

.section-head h2 {
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800;
  font-size: var(--step-5);
  line-height: 1;
  letter-spacing: -0.005em;
  /* Keeps a two-line heading from dropping a single orphaned word. */
  text-wrap: balance;
}

.section-head p {
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--ink-60);
  max-width: 34rem;
  /* Stops a paragraph ending on a single orphaned word. */
  text-wrap: pretty;
}

.on-ink .section-head p { color: var(--on-dark-60); }

/* Heading on the left, a link or action on the right. */
.section-head-split {
  display: grid;
  gap: var(--space-m);
  align-items: end;
  margin-bottom: var(--head-gap);
}
.section-head-split .section-head { margin-bottom: 0; }
.section-head-split > .link-more { justify-self: start; }
@media (min-width: 64rem) {
  .section-head-split { grid-template-columns: minmax(0, 1fr) auto; }
}

.rule { height: var(--hairline); background: var(--line); border: 0; }

/* Content beside a sidebar. L1-L2 stacked, with the sidebar first so the
   contents list and contact details are not buried under the page; L3 the
   sidebar's blocks sit two across; L4+ a sticky sidebar column. */
.split { display: grid; gap: var(--space-xl); }
/* Only sidebars built from .info-block (contents lists, contact details) move
   first and go two-across; a product's spec panel stays after its copy. */
@media (max-width: 63.999rem) { .split > .info-panel:has(.info-block) { order: -1; } }
@media (min-width: 48rem) {
  .split > .info-panel:has(.info-block) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-l); }
  .split > .info-panel .info-block + .info-block { margin-top: 0; }
}
@media (min-width: 64rem) {
  .split { grid-template-columns: minmax(0, 1fr) 19rem; }
  .split > .info-panel, .split > .info-panel:has(.info-block) { display: block; position: sticky; top: calc(var(--header-stuck) + var(--space-m)); }
  .split > .info-panel .info-block + .info-block { margin-top: var(--space-l); }
}
@media (min-width: 80rem) { .split { grid-template-columns: minmax(0, 1fr) 21rem; gap: var(--space-2xl); } }

.info-panel { background: var(--paper); border-radius: var(--radius-lg); padding: clamp(1.25rem, 0.75rem + 2vw, 2.25rem); align-self: start; }
.info-panel h3 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-0); font-weight: 600; margin-bottom: var(--space-2xs); }
.info-panel + .info-panel, .info-panel .info-block + .info-block { margin-top: var(--space-l); }
.info-panel p, .info-panel address { font-size: var(--step--1); color: var(--ink-60); font-style: normal; line-height: 1.7; }
/* :not(.btn) - an orange button in the panel was being repainted with navy text. */
.info-panel a:not(.btn) { color: var(--ink); }
.info-panel .footer-list a { color: var(--ink); display: inline-block; padding-block: 0.3rem; }
.info-panel .footer-list a:hover { color: var(--accent); }
.info-panel .btn { margin-top: var(--space-xs); }
/* Two blocks across at L3: an odd last block takes the full row. */
@media (min-width: 48rem) and (max-width: 63.999rem) {
  .split > .info-panel .info-block:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* --------------------------------------------------------------------------
   The card wash
   A disc that covers the whole card, anchored at the point the pointer
   crossed the edge. The script writes --wx, --wy and --wr; everything else
   is a transform, so the flood runs on the compositor and never touches
   layout.

   --wr is the measured distance from that entry point to the furthest
   corner. It was a flat 300% of the card's width to begin with, which is
   fine on a square tile but left a visible arc across the bottom of the
   taller category cards, where the diagonal is longer than 1.5 widths.
   -------------------------------------------------------------------------- */

.wash {
  position: absolute;
  top: var(--wy, 50%);
  left: var(--wx, 50%);
  width: calc(var(--wr, 32rem) * 2);
  height: calc(var(--wr, 32rem) * 2);
  border-radius: 50%;
  background: var(--ink);
  /* 20%: a tint that sweeps across, not a cover. At 0.95 it buried the
     photograph entirely, which is what made the tiles read as solid navy
     on hover. */
  opacity: 0.2;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0);
}

.stack-s > * + * { margin-top: var(--space-s); }
.stack-m > * + * { margin-top: var(--space-m); }
.stack-l > * + * { margin-top: var(--space-l); }

/* --------------------------------------------------------------------------
   4. Image placeholders
   Photography is not in yet. These stand in deliberately rather than
   leaving broken images, and disappear the moment a real file is set.
   -------------------------------------------------------------------------- */

.ph {
  position: relative;
  display: grid; place-items: center;
  background: var(--paper-2);
  border: var(--hairline) solid var(--line);
  color: var(--ink-40);
  overflow: hidden;
}
.ph::before {
  content: '';
  position: absolute; inset: 0;
  background-image: repeating-linear-gradient(
    -45deg, transparent 0 11px, rgba(11, 21, 40, 0.028) 11px 22px
  );
}
.ph span {
  position: relative;
  font-size: var(--step--2);
  letter-spacing: 0.04em;
  text-align: center;
  padding: var(--space-s);
  max-width: 22ch;
}
.on-ink .ph { background: var(--ink-raise); border-color: var(--dark-line); color: var(--ink-40); }
.on-ink .ph::before { background-image: repeating-linear-gradient(-45deg, transparent 0 11px, rgba(255,255,255,0.03) 11px 22px); }

.ratio-4x5 { aspect-ratio: 4 / 5; }
.ratio-1x1 { aspect-ratio: 1 / 1; }
.ratio-3x2 { aspect-ratio: 3 / 2; }
.ratio-16x9 { aspect-ratio: 16 / 9; }

.media { overflow: hidden; background: var(--paper-2); }
.media img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); text-align: center;
  gap: var(--space-2xs);
  padding: 0.95em 1.7em;
  font-family: var(--font-text);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.005em;
  border: 1.5px solid transparent;
  border-radius: var(--radius);
  cursor: pointer; text-decoration: none;
  transition: background-color 150ms var(--ease), border-color 150ms var(--ease), color 150ms var(--ease);
}

.btn-primary { background: var(--accent); color: var(--white); border-color: var(--accent); }
.btn-primary:hover { background: var(--accent-deep); border-color: var(--accent-deep); }

.btn-dark { background: var(--ink); color: var(--white); border-color: var(--ink); box-shadow: var(--gloss-edge); }
.btn-dark:hover { background: var(--ink-80); border-color: var(--ink-80); }

.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); }
.btn-ghost:hover { border-color: var(--ink); }

.on-ink .btn-ghost { color: var(--white); border-color: #445069; }
.on-ink .btn-ghost:hover { border-color: var(--white); }

.btn-light { background: var(--white); color: var(--ink); border-color: var(--white); }
.btn-light:hover { background: var(--paper); border-color: var(--paper); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-xs); }
/* L1: buttons stack full width; L2+: side by side at their own width. */
.btn-row > .btn { flex: 1 1 100%; }
@media (min-width: 30rem) { .btn-row > .btn { flex: 0 1 auto; } }

.link-more {
  display: inline-block;
  font-size: var(--step--1); font-weight: 600;
  text-decoration: none;
  border-bottom: 2px solid var(--accent);
  padding-bottom: 2px;
  transition: color 150ms var(--ease);
}
.link-more:hover { color: var(--accent); }
@media (pointer: coarse) { .link-more { padding-top: 0.75rem; } }

/* --------------------------------------------------------------------------
   6. Site header
   Three bands, deliberately unlike each other:

     utility  dark, 36px, small light text at regular weight
     brand    white, roomy, the logo and the one orange button
     sports   white with a hairline, condensed uppercase navy

   The contrast is the point. A slim dark strip reads as service information
   and gets out of the way; the sports bar reads as navigation.
   -------------------------------------------------------------------------- */

/*
 * Sticky with a NEGATIVE offset equal to the utility strip's height. The
 * header scrolls normally until its top edge reaches -2.5rem, at which point
 * it pins with the strip already out of view and the brand row and sports bar
 * still on screen.
 *
 * This replaces an earlier version that animated the header's own height on
 * scroll. Because a sticky element still takes up space in flow, shrinking it
 * pulled the page up, which moved scrollY, which un-set the class, which
 * restored the height: the header visibly shook. Nothing here changes
 * geometry in response to scrolling, so there is no loop to get into.
 */
.site-header { position: sticky; top: -2.5rem; z-index: 50; }

/* --- Band 1: utility strip ---------------------------------------------- */

.header-utility {
  background-color: var(--ink);
  background-image: var(--gloss);
  color: var(--on-dark-60);
  overflow: hidden;
  max-height: 2.5rem;
  box-shadow: var(--gloss-edge);
}

.header-utility-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-m);
  height: 2.5rem;
}

.nav-utility { display: flex; align-items: center; gap: var(--space-m); }
.nav-utility a {
  font-size: var(--step--2);
  font-weight: 400;
  letter-spacing: 0.012em;
  color: var(--on-dark-60);
  text-decoration: none;
  position: relative;
  white-space: nowrap;
}
.nav-utility a:hover,
.nav-utility .current-menu-item > a { color: var(--white); }

.utility-contact {
  display: flex; align-items: center; gap: var(--space-xs);
  font-size: var(--step--2);
  color: var(--on-dark-60);
  white-space: nowrap;
}
.utility-contact a { color: var(--on-dark-60); text-decoration: none; }
.utility-contact a:hover { color: var(--white); }
.utility-sep { flex: none; width: var(--hairline); height: 0.9rem; background: var(--dark-line); }

/* Social icons at the end of the utility strip. Hidden on L1-L2, where the
   strip has room only for the phone and the mailbox. */
.utility-social { display: none; align-items: center; gap: 0.15rem; margin-left: calc(var(--space-xs) * -1); }
.utility-social a { display: grid; place-items: center; width: 2rem; height: 2.5rem; color: var(--on-dark-60); transition: color var(--dur-fast) var(--ease); }
.utility-social a:hover { color: var(--white); }
.utility-social .social-icon { width: 0.95rem; height: 0.95rem; }
@media (min-width: 48rem) { .utility-social { display: flex; } }
/* L3: the strip is centred for the phone and mailbox alone; with the icons
   present they go to the right edge instead of trailing the email. */
/* Two classes, so it outranks the later L1-L3 rule that centres the strip. */
@media (min-width: 48rem) and (max-width: 63.999rem) { .header-utility .header-utility-inner { justify-content: space-between; align-items: center; } }

/* The strapline carries its own divider, so hiding it on a narrow screen
   takes the divider with it and leaves the phone and the mailbox joined by
   the one that belongs to them. */
.utility-note { display: flex; align-items: center; gap: var(--space-xs); color: #828CA0; }
@media (max-width: 29.999rem) { .utility-contact { gap: 0.5rem; font-size: 0.75rem; } }
@media (pointer: coarse) { .utility-contact a { display: inline-flex; align-items: center; min-height: 2.5rem; } }

/* --- Band 2: brand row --------------------------------------------------- */

.header-brand {
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: saturate(160%) blur(10px);
}
.header-brand-inner { display: flex; align-items: center; gap: var(--space-m); min-height: 4.5rem; }

.brand {
  display: flex; align-items: center; gap: 0.55rem;
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800; font-size: var(--step-3);
  letter-spacing: 0.005em; text-transform: uppercase;
  text-decoration: none; margin-right: auto; line-height: 1;
}
.brand img { max-height: 2.75rem; width: auto; }
.brand-mark { width: 0.55rem; height: 1.4rem; background: var(--accent); border-radius: 1px; }

/* --- Band 3: sports bar -------------------------------------------------- */

.header-nav {
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: saturate(160%) blur(10px);
  border-top: var(--hairline) solid var(--line);
  border-bottom: var(--hairline) solid var(--line);
}

.header-nav-inner {
  /* Safety valve: a longer sport name added later scrolls the bar rather
     than wrapping it into a broken second line. */
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.header-nav-inner::-webkit-scrollbar { display: none; }

.sports-list {
  display: flex; align-items: stretch; justify-content: space-between;
  gap: clamp(0.125rem, 0.9vw, 1rem);
}

.sports-list a {
  display: block; position: relative;
  padding: 0.85rem 0.35rem;
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 700;
  font-size: var(--step--2);
  letter-spacing: 0.035em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--ink);
}
.sports-list .current-menu-item > a { color: var(--accent); }

.sports-list .menu-item-has-children { position: relative; }
.sports-list .sub-menu {
  position: absolute; top: 100%; left: 0;
  min-width: 12rem; padding: var(--space-2xs);
  background: var(--white);
  border: var(--hairline) solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 48px -20px rgba(11, 21, 40, 0.28);
}
.sports-list .sub-menu a { padding: 0.45rem 0.6rem; font-size: var(--step--2); border-radius: var(--radius); text-transform: none; letter-spacing: 0; }
.sports-list .sub-menu a:hover { background: var(--paper); color: var(--accent); }

/* --- Shared -------------------------------------------------------------- */

.nav-toggle {
  display: none;
  background: transparent; border: var(--hairline) solid var(--line-strong);
  color: var(--ink); border-radius: var(--radius);
  padding: 0.55rem 0.85rem;
  font-family: var(--font-text); font-size: var(--step--1); font-weight: 500;
  cursor: pointer;
}

.header-cta { padding: 0.75em 1.4em; }

.nav-panel-extra { display: none; }

/* Footer reuses the plain list layout. */
.nav-list { display: flex; align-items: center; gap: var(--space-m); }
.nav-list a { font-size: var(--step--1); font-weight: 500; text-decoration: none; position: relative; }

/* L1-L3: the sports bar becomes a drop-down panel. L4+: the full bar. */
@media (max-width: 63.999rem) {
  .nav-toggle { display: inline-flex; align-items: center; justify-content: center; min-height: var(--tap); min-width: var(--tap); }
  .sports-list .sub-menu a { display: block; padding-block: 0.75rem; font-size: var(--step--1); }
  .header-cta { display: none; }

  /* The utility strip keeps only the phone and the mailbox, which is the
     part a visitor on a phone actually wants. The strapline goes, and its
     divider goes with it. */
  .nav-utility { display: none; }
  .header-utility-inner { justify-content: center; }
  .utility-note { display: none; }

  .header-brand-inner { min-height: 3.75rem; }
  .brand { font-size: var(--step-2); }

  .header-nav {
    position: absolute; inset-inline: 0; top: 100%;
    border-top: 0;
    box-shadow: var(--shadow-lift);
    display: none;
    max-height: calc(100vh - var(--header-h));
    max-height: calc(100dvh - var(--header-h));
    overscroll-behavior: contain;
    overflow-y: auto;
  }
  .header-nav[data-open='true'] { display: block; }

  .header-nav-inner { overflow-x: visible; padding-block: var(--space-2xs) var(--space-m); }

  .sports-list { flex-direction: column; gap: 0; }
  .sports-list > li { border-bottom: var(--hairline) solid var(--line); }
  .sports-list a { padding: var(--space-s) 0; font-size: var(--step-0); letter-spacing: 0.02em; }

  .sports-list .sub-menu {
    position: static; min-width: 0; padding: 0 0 var(--space-2xs) var(--space-s);
    background: transparent; border: 0; box-shadow: none;
  }

  .nav-panel-extra { display: block; padding-top: var(--space-m); }
  .nav-panel-extra .nav-list { flex-direction: column; align-items: stretch; gap: 0; margin-bottom: var(--space-m); }
  .nav-panel-extra .nav-list li { border-bottom: var(--hairline) solid var(--line); }
  .nav-panel-extra .nav-list a { display: block; padding-block: var(--space-s); font-size: var(--step-0); }
  .nav-panel-extra .btn { width: 100%; }
}
/* L3: there is room for the quote button beside the menu toggle again. */
@media (min-width: 48rem) { .header-cta { display: inline-flex; } }

/* --------------------------------------------------------------------------
   7. Footer
   -------------------------------------------------------------------------- */

.site-footer { background-color: var(--ink); background-image: var(--gloss); color: var(--on-dark); padding-block: clamp(2.5rem, 1.75rem + 3vw, 4rem) var(--space-l); }

/* Closing prompt: an orange-ruled band at the head of the footer. Stacked on
   L1-L2, copy beside the buttons from L3. */
.footer-cta {
  display: grid; gap: var(--space-m); align-items: center;
  padding-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
  margin-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
  border-bottom: var(--hairline) solid var(--dark-line);
}
@media (min-width: 48rem) { .footer-cta { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-xl); } }
.footer-cta-title { font-family: var(--font-display); font-stretch: var(--wd-tight); font-weight: 800; font-size: var(--step-4); line-height: 1.05; text-wrap: balance; }
.footer-cta-title::before { content: ''; display: block; width: 2.75rem; height: 3px; background: var(--accent); margin-bottom: var(--space-s); }
.footer-cta-text { margin-top: var(--space-xs); font-size: var(--step-0); color: var(--on-dark-60); max-width: 44ch; }
.footer-cta .btn-ghost { color: var(--white); border-color: #445069; }
.footer-cta .btn-ghost:hover { border-color: var(--white); }

/* L1 one column; L2 brand full width over two columns. L3-L4: brand full
   width with the map beside it, the twelve sports full width in three
   columns (as one narrow column every name wrapped to two lines), then
   company / help / contact three across. L5: brand beside four columns. */
.footer-grid { display: grid; gap: var(--space-xl); }
@media (min-width: 30rem) {
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-xl) var(--space-l); }
  .footer-grid > .footer-brand { grid-column: 1 / -1; }
}
/* L3+: the brand block is a full-width row of its own, text left and the
   map right. Beside the link columns it grew taller than all of them once
   the map was added, so it never shares a row with them. */
@media (min-width: 48rem) {
  .footer-brand { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-xl); align-content: start; }
  .footer-brand > :not(.footer-map) { grid-column: 1; }
  .footer-brand > .footer-map { grid-column: 2; grid-row: 1 / span 3; margin-top: 0; max-width: none; }
}
@media (min-width: 48rem) and (max-width: 79.999rem) {
  .footer-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .footer-grid > .footer-col:has(.footer-list-sports) { grid-column: 1 / -1; }
  .footer-list-sports { columns: 3; column-gap: var(--space-l); }
  .footer-list-sports li { break-inside: avoid; }
}
/* L2: the twelve sports span the row in two columns rather than one long
   column beside a short one. */
@media (min-width: 30rem) and (max-width: 47.999rem) {
  .footer-grid > .footer-col:has(.footer-list-sports) { grid-column: 1 / -1; }
  .footer-list-sports { columns: 2; column-gap: var(--space-l); }
  .footer-list-sports li { break-inside: avoid; }
}
/* L5: brand row on top, then four link columns in one row. Sports gets a
   double-width track split into two columns (about 470px, so no name
   wraps); contact gets a little extra for the email. */
@media (min-width: 80rem) {
  .footer-grid { grid-template-columns: minmax(0, 2.4fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.15fr); gap: var(--space-xl) var(--space-l); }
  .footer-list-sports { columns: 2; column-gap: var(--space-m); }
  .footer-list-sports li { break-inside: avoid; }
  .footer-list-sports a { white-space: nowrap; }
}

.footer-brand .brand { color: var(--white); font-size: var(--step-2); margin-right: 0; }
.footer-tagline { margin-top: var(--space-s); font-size: var(--step--1); color: var(--on-dark-60); max-width: 40ch; line-height: 1.65; }

.footer-social { display: flex; flex-wrap: wrap; gap: var(--space-2xs); margin-top: var(--space-m); }
.footer-social a {
  display: grid; place-items: center;
  width: var(--tap); height: var(--tap);
  border: var(--hairline) solid var(--dark-line); border-radius: 50%;
  color: var(--on-dark-60);
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.footer-social a:hover { color: var(--white); border-color: var(--accent); background: var(--accent); }
.social-icon { width: 1.15rem; height: 1.15rem; }

/* Sialkot map under the brand block. The light OSM tiles are toned down to
   sit in the navy footer, and come back to full colour on hover. */
.footer-map { margin-top: var(--space-l); max-width: 26rem; }
.footer-map iframe {
  /* 4:3 and at least 240px tall: OpenStreetMap's credit line (required by
     its licence, so never hidden) wraps on a small map and covered a third
     of a 200px one. */
  display: block; width: 100%; aspect-ratio: 4 / 3; min-height: 15rem; border: 0;
  border-radius: var(--radius-lg); background: var(--ink-raise);
  box-shadow: 0 0 0 var(--hairline) var(--dark-line);
  filter: grayscale(1) invert(0.9) contrast(0.85) brightness(0.95);
  transition: filter var(--dur) var(--ease);
}
.footer-map:hover iframe, .footer-map:focus-within iframe { filter: none; }
.footer-map figcaption {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-2xs) var(--space-s);
  margin-top: var(--space-2xs); font-size: var(--step--2); color: var(--on-dark-60);
}
.footer-map figcaption a { color: var(--on-dark-60); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--accent); }
.footer-map figcaption a:hover { color: var(--white); }
@media (pointer: coarse) { .footer-map figcaption a { display: inline-block; padding-block: 0.6rem; } }

.footer-head { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step--1); font-weight: 600; margin-bottom: var(--space-s); letter-spacing: -0.01em; color: var(--white); }
.footer-head::after { content: ''; display: block; width: 1.5rem; height: 2px; background: var(--accent); margin-top: 0.45rem; }

.footer-contact-label { display: block; margin-top: var(--space-s); font-size: var(--step--2); letter-spacing: 0.06em; text-transform: uppercase; color: #828CA0; }
.footer-contact-label:first-child { margin-top: 0; }

/* The four confirmed terms, as a quiet row of orange-dotted items. */
.footer-trust {
  display: flex; flex-wrap: wrap; gap: var(--space-2xs) var(--space-l);
  margin-top: var(--space-xl); padding-top: var(--space-m);
  border-top: var(--hairline) solid var(--dark-line);
  font-size: var(--step--1); font-weight: 500; color: var(--white);
}
.footer-trust li { display: inline-flex; align-items: center; gap: 0.5rem; }
/* Two by two until there is room for all four on one line, so the last item
   is never left alone on a row. */
@media (min-width: 30rem) and (max-width: 63.999rem) {
  .footer-trust { display: grid; grid-template-columns: repeat(2, max-content); gap: 0.75rem var(--space-xl); }
}
.footer-trust li::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }

.footer-top { color: var(--on-dark-60); text-decoration: none; font-weight: 600; }
.footer-top::after { content: ' \2191'; }
.footer-top:hover { color: var(--white); }
@media (pointer: coarse) { .footer-top { display: inline-block; padding-block: 0.6rem; } }
/* Tight line height and a wider gap between items, so a link that wraps
   reads as one link rather than two. */
.footer-list li + li { margin-top: 0.75rem; }
.footer-list a { font-size: var(--step--1); line-height: 1.35; color: var(--on-dark-60); text-decoration: none; }
.footer-list a:hover { color: var(--white); }
@media (pointer: coarse) {
  .footer-list li + li { margin-top: 0; }
  .footer-list a { display: inline-block; padding-block: 0.6rem; min-height: var(--tap); }
}
.footer-address { font-size: var(--step--1); color: var(--on-dark-60); line-height: 1.75; font-style: normal; }
.footer-address a { color: var(--on-dark-60); display: inline-block; padding-block: 0.65rem; margin-block: -0.65rem; }
.footer-address a:hover { color: var(--white); }
/* The site-wide mailto rule breaks anywhere; here the address has room, so
   it stays whole. */
.footer-address a[href^="mailto:"] { overflow-wrap: normal; word-break: keep-all; white-space: nowrap; }
.footer-base {
  margin-top: var(--space-xl); padding-top: var(--space-m);
  border-top: var(--hairline) solid var(--dark-line);
  display: flex; flex-wrap: wrap; gap: var(--space-s) var(--space-m);
  justify-content: space-between;
  font-size: var(--step--2); color: var(--on-dark-60);
}
/* Room on the right for the fixed WhatsApp button (56px + offset + gap), so
   it never sits on top of "Back to top" or the legal links. */
.footer-base { align-items: center; padding-right: 5.25rem; }
.footer-base .nav-list { flex-wrap: wrap; gap: var(--space-2xs) var(--space-m); }
.footer-base .nav-list a { color: var(--on-dark-60); font-size: var(--step--2); }
@media (pointer: coarse) { .footer-base .nav-list a { display: inline-block; padding-block: 0.6rem; } }
.footer-base .nav-list a:hover { color: var(--white); border-bottom-color: var(--accent); }

/* --------------------------------------------------------------------------
   7b. WhatsApp chat widget (footer.php, initWhatsApp in main.js)
   WhatsApp's teal rather than its bright green: white on the bright green is
   under 2:1, the teal is 4.1:1 for the icon and the darker teal 7.6:1 for
   button text.
   -------------------------------------------------------------------------- */

.wa-widget {
  --wa: #128C7E; --wa-deep: #075E54; --wa-paper: #ECE5DD;
  position: fixed; z-index: 60;
  right: max(var(--gutter), env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-s);
  pointer-events: none;
}
.wa-widget > * { pointer-events: auto; }

.wa-button {
  display: grid; place-items: center;
  width: 3.5rem; height: 3.5rem; border-radius: 50%;
  background: var(--wa); color: var(--white);
  box-shadow: 0 10px 28px -8px rgba(11, 21, 40, 0.45);
  transition: background-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.wa-button:hover { background: var(--wa-deep); transform: translateY(-2px); }
.wa-button .social-icon { width: 1.75rem; height: 1.75rem; }
.wa-button[aria-expanded="true"] { background: var(--wa-deep); }

.wa-teaser {
  position: relative; max-width: 15rem;
  padding: var(--space-s) 2.25rem var(--space-s) var(--space-m);
  background: var(--white); color: var(--ink);
  border-radius: var(--radius-lg) var(--radius-lg) 4px var(--radius-lg);
  box-shadow: 0 12px 32px -10px rgba(11, 21, 40, 0.35);
  font-size: var(--step--1); line-height: 1.45;
  animation: wa-in 320ms var(--ease-out) both;
}
.wa-teaser-close, .wa-card-close {
  position: absolute; top: 0.25rem; right: 0.25rem;
  display: grid; place-items: center; width: 2rem; height: 2rem;
  border: 0; border-radius: 50%; background: transparent; color: inherit;
  font-size: 1.25rem; line-height: 1; cursor: pointer; opacity: 0.7;
}
.wa-teaser-close:hover, .wa-card-close:hover { opacity: 1; background: rgba(11, 21, 40, 0.08); }

.wa-card {
  width: min(21rem, calc(100vw - 2 * var(--gutter)));
  background: var(--white); color: var(--ink);
  border-radius: var(--radius-lg); overflow: hidden;
  box-shadow: 0 24px 60px -16px rgba(11, 21, 40, 0.45);
  animation: wa-in 260ms var(--ease-out) both;
}
.wa-card[hidden], .wa-teaser[hidden] { display: none; }
.wa-card-head { position: relative; display: flex; align-items: center; gap: var(--space-s); padding: var(--space-m) 3rem var(--space-m) var(--space-m); background: var(--wa-deep); color: var(--white); }
.wa-card-avatar { display: grid; place-items: center; flex: none; width: 2.75rem; height: 2.75rem; border-radius: 50%; background: var(--wa); }
.wa-card-avatar .social-icon { width: 1.4rem; height: 1.4rem; }
.wa-card-title { font-family: var(--font-display); font-stretch: var(--wd-normal); font-weight: 700; font-size: var(--step-0); }
.wa-card-sub { font-size: var(--step--2); opacity: 0.85; }
.wa-card-close { top: 50%; transform: translateY(-50%); right: var(--space-xs); }
.wa-card-close:hover { background: rgba(255, 255, 255, 0.14); }
.wa-card-body { padding: var(--space-m); background: var(--wa-paper); }
.wa-bubble {
  position: relative; max-width: 92%;
  padding: var(--space-s) var(--space-m);
  background: var(--white); border-radius: 0 var(--radius-lg) var(--radius-lg) var(--radius-lg);
  font-size: var(--step--1); line-height: 1.5; box-shadow: 0 1px 1px rgba(11, 21, 40, 0.08);
}
.wa-card-cta {
  display: flex; width: calc(100% - 2 * var(--space-m)); margin: var(--space-m);
  background: var(--wa-deep); border-color: var(--wa-deep); color: var(--white);
}
.wa-card-cta:hover { background: var(--wa); border-color: var(--wa); }
.wa-card-cta .social-icon { width: 1.15rem; height: 1.15rem; }

@keyframes wa-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }

/* Kept clear of the page on print. */
@media print { .wa-widget { display: none; } }

/* --------------------------------------------------------------------------
   8. Banner - full-bleed photograph with overlaid headline
   -------------------------------------------------------------------------- */

.banner {
  position: relative;
  display: grid; align-items: end;
  min-height: clamp(28rem, 76vh, 46rem);
  min-height: clamp(28rem, 76svh, 46rem);
  background-color: var(--ink);
  color: var(--white);
  overflow: hidden;
}

.banner-media { position: absolute; inset: 0; }
.banner-media img { width: 100%; height: 100%; object-fit: cover; }
.banner-media .ph { width: 100%; height: 100%; border: 0; }

/* Slideshow of the sport banners. Deliberately slow: the incoming photograph
   fades in over nearly three seconds on top of the outgoing one, which holds
   still at full strength underneath, so the scene never dips to navy
   halfway. Each photograph also drifts a few percent sideways while it is up,
   which reads as a slide without anything visibly moving across the screen.
   The athlete sits right of centre in every one, so crops keep the right. */
/* isolate: the slides' z-index stays inside here, under the scrim. */
.banner-slides { --fade: 2.8s; --drift: 9.8s; isolation: isolate; }
.banner-slides .banner-slide {
  position: absolute; inset: 0;
  object-position: 100% 35%;
  opacity: 0;
  transform: scale(1.08) translateX(2%);
  transition: opacity var(--fade) cubic-bezier(0.45, 0, 0.55, 1), transform 0s linear var(--fade);
  will-change: opacity, transform;
}
.banner-slides .banner-slide.is-active,
.banner-slides .banner-slide.is-prev {
  transform: scale(1.04) translateX(0);
  transition: opacity var(--fade) cubic-bezier(0.45, 0, 0.55, 1), transform var(--drift) cubic-bezier(0.33, 0.02, 0.2, 1);
}
.banner-slides .banner-slide.is-active { opacity: 1; z-index: 2; }
.banner-slides .banner-slide.is-prev { opacity: 1; z-index: 1; }

.banner-controls {
  position: absolute; z-index: 2;
  right: max(var(--gutter), calc((100% - var(--container)) / 2 + var(--gutter)));
  top: var(--space-m);
  display: flex; align-items: center; gap: var(--space-s);
}
@media (min-width: 48rem) { .banner-controls { top: auto; bottom: clamp(3rem, 6vw, 5.5rem); } }
.banner-controls[hidden] { display: none; }

/* L1 keeps only the pause button; the dots return from L2 with full-height
   hit areas. */
.banner-dots { display: none; align-items: center; gap: 0; }
@media (min-width: 30rem) { .banner-dots { display: flex; } }
.banner-dot, .banner-pause {
  -webkit-appearance: none; appearance: none;
  border: 0; padding: 0; cursor: pointer;
  background: transparent; color: var(--white);
}
/* A 24px hit area around a 6px mark. */
.banner-dot { width: 1.5rem; height: 2.75rem; display: grid; place-items: center; transition: width var(--dur-slow) var(--ease); }
.banner-dot::before {
  content: ''; width: 6px; height: 6px; border-radius: 3px;
  background: rgba(255, 255, 255, 0.45);
  transition: width var(--dur-slow) var(--ease), background-color var(--dur-slow) var(--ease);
}
.banner-dot:hover::before { background: rgba(255, 255, 255, 0.8); }
.banner-dot.is-active { width: 2rem; }
.banner-dot.is-active::before { width: 1.375rem; background: var(--white); }

.banner-pause {
  width: var(--tap); height: var(--tap); border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.45);
  display: grid; place-items: center;
  transition: border-color var(--dur-fast) var(--ease);
}
.banner-pause:hover { border-color: var(--white); }
/* Two bars while playing, a triangle once paused. */
.banner-pause::before {
  content: ''; width: 8px; height: 10px;
  border-inline: 3px solid currentColor;
  box-sizing: border-box;
}
.banner-pause[aria-pressed="true"]::before {
  width: 0; height: 0;
  border-inline: 0;
  border-block: 5px solid transparent;
  border-left: 8px solid currentColor;
  margin-left: 2px;
}
.banner-dot:focus-visible, .banner-pause:focus-visible { outline: 2px solid var(--white); outline-offset: 2px; }

/* Scrim. Without it, white type over an unknown photograph is a gamble. */
.banner::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(
    to top,
    rgba(11, 21, 40, 0.84) 0%,
    rgba(11, 21, 40, 0.54) 42%,
    rgba(11, 21, 40, 0.18) 78%,
    rgba(11, 21, 40, 0.30) 100%
  );
}

.banner-inner { position: relative; z-index: 1; padding-block: clamp(3rem, 6vw, 5.5rem); }
/* L1-L2: the slideshow controls sit at the top of the banner, so the copy is
   held clear of them rather than running up underneath. */
@media (max-width: 47.999rem) { .banner-inner { padding-top: calc(var(--tap) + var(--space-l) * 2); } }
.banner h1 { max-width: 18ch; margin-bottom: var(--space-m); }
.banner .lede { color: rgba(255, 255, 255, 0.86); max-width: 48ch; margin-bottom: var(--space-l); }

.banner-eyebrow {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-size: var(--step--1); font-weight: 500;
  color: rgba(255, 255, 255, 0.82);
  margin-bottom: var(--space-m);
}
.banner-eyebrow::before { content: ''; width: 2rem; height: 2px; background: var(--accent); }

/* Slideshow copy. The h1 is the fixed eyebrow line; the blocks below it
   change with the photograph. All blocks share one grid cell, so the banner
   is as tall as the longest and never jumps between slides.

   Leaving: the outgoing block fades in half a second without moving.
   Arriving: once it has gone, the new block's lines come in one after
   another from the side named in data-dir, slowly and without overshoot. */
.banner h1.banner-eyebrow { max-width: none; font-family: var(--font-text); font-size: var(--step--1); font-weight: 500; letter-spacing: 0; line-height: var(--lh-snug); }
.banner-title { max-width: 18ch; margin-bottom: var(--space-m); }

/* initSlides() sets the height to the showing block's, so the eyebrow above
   glides to sit on each new title instead of floating over a gap. */
/* minmax(0, 1fr): the one row follows that height. An auto row would size
   to the tallest block and hang below the box, pushing the active block
   down past the banner. Without JS the box is auto height and the row fits
   the tallest block as before. */
.banner-copies { display: grid; grid-template-rows: minmax(0, 1fr); transition: height 1.2s var(--ease-in-out); }
/* align-self: end keeps the buttons on one line from slide to slide, with a
   shorter block growing upward rather than leaving a gap beneath it. */
.banner-copy { grid-area: 1 / 1; align-self: end; visibility: hidden; transition: visibility 0s linear 0.6s; }
.banner-copy.is-active { visibility: visible; transition-delay: 0s; }

.banner-copy[data-dir="ltr"] { --from: translate3d(-3.5rem, 0, 0); }
.banner-copy[data-dir="rtl"] { --from: translate3d(3.5rem, 0, 0); }
.banner-copy[data-dir="ttb"] { --from: translate3d(0, -2.25rem, 0); }
.banner-copy[data-dir="btt"] { --from: translate3d(0, 2.25rem, 0); }

.banner-copy > * {
  opacity: 0;
  transform: var(--from);
  transition: opacity 0.5s var(--ease), transform 0s linear 0.6s;
}
.banner-copy.is-active > * {
  opacity: 1;
  transform: none;
  transition:
    opacity 1.1s var(--ease) var(--delay, 0.5s),
    transform 1.4s var(--ease-out) var(--delay, 0.5s);
}
.banner-copy.is-active > :nth-child(2) { --delay: 0.68s; }
.banner-copy.is-active > :nth-child(3) { --delay: 0.86s; }

/* --------------------------------------------------------------------------
   8b. Key terms band
   The four numbers a buyer checks first, as a slim band of its own between
   the banner and the first section.

   It is orange, not navy. The banner above it is navy and the section below
   is white, so a navy band here read as more of the same. Orange is the one
   accent the site owns, and this is the place to spend it: the page's first
   proof point, in the colour nothing else on the page uses at this scale.
   -------------------------------------------------------------------------- */

/*
 * Flat, true --accent. No gloss layer and no gradient.
 *
 * An earlier version put the white sheen over the top of this band and a 17%
 * navy gradient across the bottom, which meant almost none of it was
 * actually the true accent: it read lighter at the top and darker at the bottom than
 * the buttons, so the band looked like a second, different orange. The accent
 * only reads as one colour if it is used as one colour.
 */
.facts {
  position: relative;
  background-color: var(--accent);
  color: var(--white);
  overflow: hidden;
  isolation: isolate;
}

.facts-slab {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 64rem) {
  .facts-slab { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.fact {
  position: relative;
  padding: clamp(1rem, 1.6vw, 1.35rem) clamp(0.9rem, 1.6vw, 1.5rem);
}
/* Cells on the container edge align with it, not with its padding: the left
   column in the two-across layout, the first and last cells in four-across. */
.fact:nth-child(odd) { padding-left: 0; }
@media (min-width: 64rem) {
  .fact:nth-child(odd) { padding-left: clamp(0.9rem, 1.6vw, 1.5rem); }
  .fact:first-child { padding-left: 0; }
  .fact:last-child { padding-right: 0; }
}

/* Dividers are white at low opacity, not the dark hairline used elsewhere:
   a near-navy rule on orange goes muddy rather than reading as a line. */
.facts { --fact-divider: rgba(255, 255, 255, 0.24); }

/* Two columns: rules between, never around the outside. */
.fact:nth-child(n+3) { border-top: var(--hairline) solid var(--fact-divider); }
.fact:nth-child(even) { border-left: var(--hairline) solid var(--fact-divider); }

/* Four columns: one rule between each pair, no rows to divide. */
@media (min-width: 64rem) {
  .fact { border-top: 0; }
  .fact + .fact { border-left: var(--hairline) solid var(--fact-divider); }
}

/* Secondary text on this band is white held back, not grey. --on-dark-60 is
   tuned against navy and drops to about 2:1 on orange, which is unreadable.
   White at 88% gives 4.7:1 on the #B93E0C accent, which clears AA at this small size. */
.facts { --fact-quiet: rgba(255, 255, 255, 0.88); }

.fact-label {
  font-size: var(--step--2);
  color: var(--fact-quiet);
  letter-spacing: 0.015em;
  margin-bottom: 0.2rem;
}

/*
 * Inline rather than flex on purpose. A flex row puts its gap between every
 * child, which pushed the two halves of a range apart ("15 - 25"). Inline
 * children sit on the baseline with no gap, and only the unit is spaced.
 */
.fact-value {
  margin: 0;
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800;
  font-size: clamp(1.35rem, 1.05rem + 1.1vw, 1.85rem);
  line-height: 1.08;
  letter-spacing: 0;
  color: var(--white);
}

.fact-num { font-variant-numeric: tabular-nums; }
.fact-num-text { font-size: 0.78em; }
/* The dash was orange to stand out on navy. On orange it would vanish, so it
   steps back to a soft white instead of trying to compete with the figures. */
.fact-dash { color: rgba(255, 255, 255, 0.62); margin-inline: 0.02em; }

.fact-unit {
  font-family: var(--font-text);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0;
  color: var(--fact-quiet);
  /* No margin: the newline between the figure and the unit in the template
     already renders one space, in the parent's display font. Adding margin
     on top of it spaced them twice. */
  margin-left: 0;
}

/* The rule under each figure draws itself on reveal and runs out across the
   cell on hover. It is navy rather than orange now: an orange rule on an orange band
   is invisible, and navy ties the band back to the rest of the site.
   Kept thin and close, so it costs the band almost no height. */
.fact-rule {
  display: block;
  height: 2px;
  width: 1.75rem;
  margin-top: 0.5rem;
  background: var(--ink);
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   9. Category cards
   -------------------------------------------------------------------------- */

/* .cards:   1 / 2 / 3 / 3 / 3
   .cards-4: 1 / 2 / 2 / 4 / 4 - four-up grids hold 4 or 8 items, so they skip
   three columns, which would always strand a lone card on the last row. */
.cards { display: grid; gap: var(--space-m); }
@media (min-width: 30rem) { .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-s); } }
@media (min-width: 48rem) { .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-m); } }
@media (min-width: 48rem) { .cards-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .cards-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.card {
  display: flex; flex-direction: column;
  background: var(--white);
  border: var(--hairline) solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  isolation: isolate;
  text-decoration: none;
}
.card:focus-within { border-color: var(--ink); }

.card-media { position: relative; }
.card-media .ph, .card-media .media { border: 0; border-radius: 0; }

/* The body sits above the wash; the picture and the border sit under it. */
.card-body { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--space-2xs); padding: clamp(1rem, 0.75rem + 0.8vw, 1.5rem); flex: 1; }
.card-body h3 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-1); font-weight: 600; letter-spacing: -0.02em; line-height: var(--lh-snug); }
.card-body h3 a { text-decoration: none; }
.card-body h3 a::after { content: ''; position: absolute; inset: 0; }
.card-body p { font-size: var(--step--1); color: var(--ink-60); }

.card-spec {
  margin-top: auto; padding-top: var(--space-s);
  border-top: var(--hairline) solid var(--line);
  font-size: var(--step--2); color: var(--ink-60);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-2xs) var(--space-s);
}
.card-spec b { font-weight: 600; color: var(--ink); }

/* Product cards on sport pages. The photographs are shot on white, so the
   media well is white too and the square reads as part of the card. The back
   view sits over the front and fades in on hover; touch screens keep the
   front, which is the one that names the garment. */
.product-group + .product-group { margin-top: var(--space-xl); }
.product-group > h3 {
  font-family: var(--font-display); font-stretch: var(--wd-normal);
  font-size: var(--step-1); font-weight: 600; letter-spacing: -0.02em;
  padding-bottom: var(--space-s); margin-bottom: var(--space-m);
  border-bottom: var(--hairline) solid var(--line);
}
.product-media { aspect-ratio: 1 / 1; background: var(--white); overflow: hidden; }
.product-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; transition: opacity var(--dur) var(--ease), transform var(--dur-slow) var(--ease-out); }
.product-media .product-back { opacity: 0; }
@media (hover: hover) {
  .product-card:hover .has-back .product-back { opacity: 1; }
  .product-card:hover .has-back .product-front { opacity: 0; }
  .product-card:hover .product-media img { transform: scale(1.03); }
}
.product-card .card-body h4 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-1); font-weight: 600; letter-spacing: -0.02em; line-height: var(--lh-snug); }
.product-card .card-body .product-code { font-size: var(--step--2); letter-spacing: 0.08em; color: var(--ink-60); font-variant-numeric: tabular-nums; }
/* Once product pages are live the name links the whole card; the quote link
   sits above that stretched link so it stays its own action. */
.product-card .card-body h4 a { text-decoration: none; display: inline-block; padding-block: 0.7rem; margin-block: -0.7rem; }
/* L4 four-across cards are at their narrowest (about 230px), where the price
   and "Quote this" wrapped differently card to card. Stacking them there
   keeps every card's footer on the same two lines. */
@media (min-width: 64rem) and (max-width: 79.999rem) {
  .product-card .card-spec { flex-direction: column; align-items: flex-start; }
}
/* The whole card is the link, photograph included: the body steps out of the
   positioning chain so the stretched link measures against the card, not just
   the text area under the photo (owner's request, 2026-10-11). */
.product-card { position: relative; }
.product-card .card-body { position: static; }
.product-card .card-body h4 a::after,
.product-card .card-body h3 a::after { content: ''; position: absolute; inset: 0; z-index: 1; }
.product-card .product-quote { position: relative; z-index: 2; display: inline-block; padding-block: 0.6rem; margin-block: -0.6rem; }

/* --------------------------------------------------------------------------
   Single product page: gallery beside the buying summary, then the copy.
   -------------------------------------------------------------------------- */

.product-hero { padding-block: clamp(1.5rem, 1rem + 3vw, 3.5rem) var(--section-y); border-bottom: var(--hairline) solid var(--line); }
/* L1-L2 stacked; L3 gallery and summary side by side; L4+ gallery wider. */
.product-hero-grid { display: grid; gap: var(--space-l); align-items: start; }
@media (min-width: 48rem) { .product-hero-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .product-hero-grid { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--space-xl); } }
@media (min-width: 80rem) { .product-hero-grid { gap: var(--space-2xl); } }

.product-gallery-main { position: relative; border: var(--hairline) solid var(--line); border-radius: var(--radius-lg); }
.product-gallery-view { position: absolute; inset: 0; opacity: 0; transition: opacity var(--dur) var(--ease); }
.product-gallery-view.is-active { opacity: 1; }

/* Magnifier (initProductZoom in main.js). The layer carries the 2000px master
   at 2.5x and only shows while zoomed; the well clips it to its rounded box. */
.product-gallery-main.has-zoom { overflow: hidden; cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.product-gallery-main.is-zoomed { cursor: crosshair; }
.product-zoom {
  position: absolute; inset: 0; z-index: 2;
  background-color: var(--white); background-repeat: no-repeat;
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease);
}
.product-gallery-main.is-zoomed .product-zoom { opacity: 1; }
.product-zoom-hint {
  position: absolute; z-index: 3; right: var(--space-xs); bottom: var(--space-xs);
  padding: 0.3rem 0.65rem; border-radius: 999px;
  background: rgba(11, 21, 40, 0.72); color: var(--white);
  font-size: var(--step--2); font-weight: 600; letter-spacing: 0.01em;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease);
}
.product-zoom-hint::before { content: '\2295'; margin-right: 0.35rem; }
.product-gallery-main.is-zoomed .product-zoom-hint { opacity: 0; }
.product-gallery-thumbs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-xs); margin-top: var(--space-xs); }
.product-thumb {
  position: relative; display: block; padding: 0; cursor: pointer;
  background: var(--white); border: var(--hairline) solid var(--line); border-radius: var(--radius-lg);
  overflow: hidden; aspect-ratio: 1 / 1;
  transition: border-color var(--dur) var(--ease-out);
}
.product-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.product-thumb:hover, .product-thumb.is-active { border-color: var(--ink); }
.product-thumb:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The view name stays the button's accessible name at every width, but is
   only drawn from L3, where a thumbnail is wide enough that it no longer
   covers the garment. */
.product-thumb-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@media (min-width: 48rem) {
  .product-thumb-label {
    width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal;
    inset-inline: 0; bottom: 0; padding: 0.15rem; line-height: 1.3;
    font-size: var(--step--2); color: var(--ink-60); background: rgba(255, 255, 255, 0.85);
  }
}

.product-summary .breadcrumb { margin-bottom: var(--space-s); }
.product-kicker { font-size: var(--step--1); color: var(--ink-60); margin-bottom: var(--space-2xs); }
.product-kicker .product-code { letter-spacing: 0.08em; font-variant-numeric: tabular-nums; }
.product-summary h1 { margin-bottom: var(--space-s); }
.product-summary .lede { margin-bottom: var(--space-l); }

.product-terms { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-s) var(--space-m); margin-bottom: var(--space-l); padding-block: var(--space-m); border-block: var(--hairline) solid var(--line); }
.product-terms dt { font-size: var(--step--2); color: var(--ink-60); }
.product-terms dd { margin: 0; font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-0); font-weight: 600; }
@media (min-width: 64rem) { .product-terms dd { font-size: var(--step-1); } }

.product-specs { margin-bottom: var(--space-m); }
.product-specs > div { padding-block: 0.55rem; border-top: var(--hairline) dotted var(--line-strong); }
.product-specs dt { font-size: var(--step--2); color: var(--ink-60); }
.product-specs dd { margin: 0; font-size: var(--step--1); color: var(--ink); font-weight: 600; }

/* Product price table. L1-L2: one row per tier, bracket on the left and
   price on the right, so all six prices are visible with nothing to scroll.
   L3+: the six tiers across in one row. The border comes from .table-scroll.
   The cells carry data-label and ARIA roles (product-page.php), so the table
   keeps its semantics while it is displayed as blocks. */
.price-table { width: 100%; border-collapse: collapse; background: var(--white); }
.price-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.price-table tbody, .price-table tr { display: block; }
.price-table th { padding: var(--space-s) var(--space-xs); font-size: var(--step--2); font-weight: 600; color: var(--ink-60); text-align: center; border-bottom: var(--hairline) solid var(--line); font-variant-numeric: tabular-nums; }
.price-table td { display: flex; align-items: baseline; gap: 0.25rem; padding: var(--space-s) var(--space-m); text-align: left; border-top: var(--hairline) solid var(--line); }
.price-table td:first-child { border-top: 0; }
.price-table td::before { content: attr(data-label); margin-right: auto; padding-right: var(--space-s); font-size: var(--step--1); font-weight: 600; color: var(--ink-60); font-variant-numeric: tabular-nums; }
.price-table .price-amount { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-1); font-weight: 700; font-variant-numeric: tabular-nums; }
.price-table .price-unit, .price-table .price-quote { font-size: var(--step--2); color: var(--ink-60); }
@media (min-width: 48rem) {
  .price-table thead { position: static; width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal; display: table-header-group; }
  .price-table tbody { display: table-row-group; }
  .price-table tr { display: table-row; }
  .price-table td { display: table-cell; padding: var(--space-m) var(--space-xs); text-align: center; border-top: 0; border-left: var(--hairline) solid var(--line); }
  .price-table td:first-child { border-left: 0; }
  .price-table td::before { content: none; }
  .price-table .price-amount { display: block; font-size: var(--step-2); }
}
.product-quote { font-weight: 600; color: var(--ink); text-underline-offset: 0.2em; }
.product-quote:hover { color: var(--accent); }

.sport-hero { position: relative; display: grid; align-items: end; min-height: clamp(20rem, 46vh, 30rem); background-color: var(--ink); color: var(--white); overflow: hidden; }
.sport-hero > .ph, .sport-hero > .media { position: absolute; inset: 0; height: 100%; border: 0; border-radius: 0; }

/* The real photograph, now that every sport has one. Square source cropped
   to a wide hero, anchored high so heads are not cut off. */
.sport-hero-media {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 32%;
}
/* The wide banners put the athlete right of centre, clear of the headline.
   Where the banner is narrower than the photograph - tablets and phones - the
   crop keeps the right-hand end, where the athlete is. */
.sport-hero-media.is-wide { object-position: 100% 30%; }
.sport-hero::after { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgba(11, 21, 40, 0.88) 0%, rgba(11, 21, 40, 0.55) 45%, rgba(11, 21, 40, 0.2) 100%); }
.sport-hero-inner { position: relative; z-index: 1; padding-block: clamp(2rem, 4vw, 3.5rem); }
.sport-hero h1 { margin-bottom: var(--space-s); }
.sport-hero .lede { color: rgba(255,255,255,0.86); margin-bottom: var(--space-l); }
.sport-hero .breadcrumb { color: rgba(255,255,255,0.7); }
.sport-hero .breadcrumb span { color: rgba(255,255,255,0.45); }

/* --------------------------------------------------------------------------
   9b. Sport tiles
   -------------------------------------------------------------------------- */

/*
 * Four across on desktop, so twelve sports read as three even rows.
 *
 * The tile IS the photograph: square, edge to edge, nothing beside it. At
 * rest it shows only the sport's name over the picture. Bringing a pointer
 * to a tile opens the kit list and the call to action over the image, so the
 * grid stays calm until someone is actually looking at one of them.
 *
 * Everything sits in one stacking context on top of the picture, painted in
 * document order:
 *   .sport-media    the photograph, absolutely filling the tile
 *   .sport-veil     the gradient that keeps white type legible on any image
 *   .wash           the orange flood, above both, below the words
 *   .sport-content  the name, and the panel that opens under it (z-index 1)
 */

/* 2 / 2 / 3 / 4 / 4 - twelve sports divide evenly at every step. */
.sports { display: grid; gap: var(--space-xs); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 30rem) { .sports { gap: var(--space-s); } }
@media (min-width: 48rem) { .sports { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-m); } }
@media (min-width: 64rem) { .sports { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.sport {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  overflow: hidden;
  isolation: isolate;
  background: var(--ink);
  text-decoration: none;
  color: var(--white);
}

.sport-media { position: absolute; inset: 0; overflow: hidden; background: var(--paper-2); }
.sport-media .ph, .sport-media .media {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0; border-radius: 0;
}
.sport-media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Without this, white type on a pale photograph is a gamble. */
.sport-veil {
  position: absolute; inset: 0;
  background: linear-gradient(
    to top,
    rgba(11, 21, 40, 0.88) 0%,
    rgba(11, 21, 40, 0.55) 30%,
    rgba(11, 21, 40, 0.12) 62%,
    rgba(11, 21, 40, 0.3) 100%
  );
}

.sport-content {
  position: absolute; inset-inline: 0; bottom: 0; z-index: 1;
  padding: var(--space-s);
}
@media (min-width: 48rem) { .sport-content { padding: var(--space-m); } }

.sport-name {
  display: block;
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800;
  font-size: var(--step-1);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.05;
  color: var(--white);
}
@media (min-width: 48rem) { .sport-name { font-size: var(--step-2); } }

/* The panel. Collapsed by rows rather than by height, so it opens to whatever
   the content actually measures without anything being hard-coded. */
.sport-detail {
  display: grid;
  grid-template-rows: 0fr;
}
.sport-detail-inner { overflow: hidden; min-height: 0; }

.sport-kit {
  display: flex; flex-wrap: wrap; gap: 0.3rem;
  padding-top: var(--space-s);
}
/*
 * Orange chips on the navy wash.
 *
 * These began as white at 10% over the photograph, so their contrast was
 * whatever the picture behind them happened to be. A solid fill fixed that.
 * The colour then has to follow the wash, because the chips are only ever
 * visible while it is up: against an orange wash they had to be navy, and now
 * the wash is navy they go back to orange, which puts the accent into the
 * open state. White on orange is 5.6:1.
 */
.sport-kit li {
  font-size: var(--step--1);
  font-weight: 500;
  line-height: 1.25;
  padding: 0.25rem 0.55rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--white);
}

/* Underlined in orange for the same reason the chips are orange: it only ever
   shows while the navy wash is up. */
/* L1 tiles are about 140px square: the name alone fits, and the whole tile
   is the link, so the call to action waits for L2. */
.sport-go {
  display: none;
  margin-top: var(--space-xs);
  font-size: var(--step--2);
  font-weight: 600;
  padding-bottom: 2px;
  border-bottom: 2px solid var(--accent);
}
@media (min-width: 30rem) { .sport-go { display: inline-block; } }
@media (min-width: 48rem) { .sport-go { font-size: var(--step--1); margin-top: var(--space-s); } }

/* An orange rule seals the bottom edge of the tile on hover. */
.sport::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  height: 4px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}

/* --------------------------------------------------------------------------
   10. Trust
   -------------------------------------------------------------------------- */

/*
 * Four claims, each closing on a fact. The items stretch to equal height and
 * the fact line is pushed to the bottom with margin-top:auto, so the four
 * facts sit on one line across the row however long the copy above them runs.
 * That alignment is what makes the block read as evidence rather than as four
 * paragraphs that happen to be side by side.
 */

/* 1 / 2 / 2 / 4 / 4 */
.trust-points { display: grid; gap: var(--space-l); align-items: stretch; }
@media (min-width: 30rem) { .trust-points { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-l) var(--space-m); } }
@media (min-width: 48rem) { .trust-points { gap: var(--space-l) var(--space-xl); } }
@media (min-width: 64rem) { .trust-points { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.trust-item {
  position: relative;
  display: flex;
  flex-direction: column;
  padding-top: var(--space-m);
  border-top: var(--hairline) solid var(--line);
}

/* The orange index rule, drawn in on scroll and run out on hover. */
.trust-item::before {
  content: '';
  position: absolute; top: -1px; left: 0;
  width: 2.75rem; height: 3px;
  background: var(--accent);
  transform-origin: left;
}

.trust-item h3 {
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800;
  font-size: var(--step-1);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.15;
  margin-bottom: var(--space-2xs);
}

.trust-item p { font-size: var(--step--1); color: var(--ink-60); }

.trust-fact {
  margin-top: auto;
  padding-top: var(--space-s);
  font-size: var(--step--2);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.01em;
}
.trust-fact::before {
  content: '';
  display: block;
  width: 100%; height: var(--hairline);
  background: var(--line);
  margin-bottom: var(--space-s);
}

/* On navy */
.on-ink .trust-item { border-top-color: var(--dark-line); }
.on-ink .trust-item p { color: var(--on-dark-60); }
.on-ink .trust-fact { color: var(--white); }
.on-ink .trust-fact::before { background: var(--dark-line); }

/* The logo strip gets a label, so a row of marks reads as a claim someone is
   making rather than as decoration that failed to load. */
.logo-strip { margin-top: var(--space-2xl); }

.logo-strip-label {
  font-size: var(--step--2);
  color: var(--ink-60);
  margin-bottom: var(--space-m);
}
.on-ink .logo-strip-label { color: var(--on-dark-60); }

/* --------------------------------------------------------------------------
   11. How it works - a real sequence, so it is genuinely numbered
   -------------------------------------------------------------------------- */

/*
 * Each stage is photographed, with its number set into the bottom corner of
 * the picture and an orange rule opening the text beneath it.
 *
 * Numbering is legitimate here: this genuinely is a sequence, brief through
 * to shipping, and the order is the information.
 */

/* 1 / 2 / 2 / 3 / 3 - six steps divide evenly at every step. */
.process { display: grid; gap: var(--space-l) var(--space-m); align-items: stretch; }
@media (min-width: 30rem) { .process { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-l) var(--space-s); } }
@media (min-width: 48rem) { .process { gap: var(--space-xl) var(--space-m); } }
@media (min-width: 64rem) { .process { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.step { position: relative; display: flex; flex-direction: column; }

.step-media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--paper-2);
  margin-bottom: var(--space-m);
}
.step-media .ph, .step-media .media { border: 0; border-radius: 0; }
.step-media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Keeps the number readable whatever the photograph turns out to be. */
.step-media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(11, 21, 40, 0.72) 0%, rgba(11, 21, 40, 0.18) 34%, transparent 62%);
}

.step-num {
  position: absolute; left: var(--space-s); bottom: 0.35rem; z-index: 1;
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 900;
  font-size: var(--step-5);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--white);
}

.step-body {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  border-top: 2px solid var(--line);
  padding-top: var(--space-m);
}

/* The orange mark that opens each stage. Drawn in as the step scrolls up. */
.step-body::after {
  content: '';
  position: absolute; top: -2px; left: 0;
  width: 3rem; height: 2px;
  background: var(--accent);
  transform-origin: left;
}

.step h3 {
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800;
  font-size: var(--step-1);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.15;
  margin-bottom: var(--space-2xs);
}

.step p { font-size: var(--step--1); color: var(--ink-60); }

/* Pushed to the bottom, so all six lead times sit on one line across a row
   however long the copy above them runs. Same device as the trust facts. */
.step .step-time {
  display: block;
  margin-top: auto;
  padding-top: var(--space-s);
  font-size: var(--step--2);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.01em;
}
.step .step-time::before {
  content: '';
  display: block;
  width: 100%; height: var(--hairline);
  background: var(--line);
  margin-bottom: var(--space-s);
}

/* On navy. The rule moved onto .step-body when the photographs went in, so
   the dark override has to follow it. */
.on-ink .step-body { border-top-color: var(--dark-line); }
.on-ink .step p { color: var(--on-dark-60); }
.on-ink .step .step-time { color: var(--white); }
.on-ink .step .step-time::before { background: var(--dark-line); }

/* --------------------------------------------------------------------------
   11b. Supporting page components
   Used by the fabrics, FAQ, size guide, terms and sport pages.
   -------------------------------------------------------------------------- */

/* A closing line under a section, linking on to the page that owns the
   subject in full. */
.section-aside {
  margin-top: var(--space-l);
  padding-top: var(--space-m);
  border-top: var(--hairline) solid var(--line);
  font-size: var(--step--1);
  color: var(--ink-60);
  max-width: 52rem;
}
.section-aside a { color: var(--ink); transition: color var(--dur-fast) var(--ease); }
.section-aside a:hover { color: var(--accent); }
.on-ink .section-aside { border-top-color: var(--dark-line); color: var(--on-dark-60); }
.on-ink .section-aside a { color: var(--white); }
.on-ink .section-aside a:hover { color: var(--accent); }

/* One decoration method, set out in full on /capabilities/. A rule on the left
   rather than a card: six cards in a column would read as a repeat of the six
   summary cards higher up the same page. */
.method-detail {
  border-left: 3px solid var(--line);
  padding-left: clamp(1rem, 0.4rem + 2vw, 2rem);
  max-width: 60rem;
  /* Deep links arrive here from the sport pages, and the header is sticky. */
  scroll-margin-top: calc(var(--header-stuck) + 1rem);
}
.method-detail + .method-detail { margin-top: var(--space-2xl); }
.method-detail:hover { border-left-color: var(--accent); }
.method-detail { transition: border-color var(--dur) var(--ease-out); }

.method-detail h3 {
  font-family: var(--font-display);
  font-stretch: var(--wd-normal);
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: -0.005em;
}
.method-lead { margin-top: var(--space-xs); max-width: var(--measure); }

.method-specs { margin-top: var(--space-m); }
.method-spec {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3xs);
  padding-block: var(--space-xs);
  border-top: var(--hairline) solid var(--line);
}
.method-spec dt { font-size: var(--step--1); font-weight: 600; color: var(--ink-60); }
.method-spec dd { margin: 0; font-size: var(--step--1); }

.method-sports { margin-top: var(--space-m); font-size: var(--step--1); color: var(--ink-60); }
.method-sports a { color: var(--ink); transition: color var(--dur-fast) var(--ease); }
.method-sports a:hover { color: var(--accent); }

/* L1 label over value; L2 a narrow label column; L3+ the full one. */
@media (min-width: 30rem) { .method-spec { grid-template-columns: 9rem minmax(0, 1fr); gap: var(--space-s); } }
@media (min-width: 48rem) { .method-spec { grid-template-columns: 11rem minmax(0, 1fr); gap: var(--space-m); } }

/* A subject heading plus its questions, on the FAQ and terms pages. */
.faq-group + .faq-group { margin-top: var(--space-2xl); }
.faq-group .section-head { margin-bottom: var(--space-m); }

/* The fabric library: a colour chip beside its specification. */
.fabric-row {
  display: grid;
  gap: var(--space-m);
  align-items: start;
  padding-bottom: var(--space-l);
  border-bottom: var(--hairline) solid var(--line);
}
@media (min-width: 48rem) {
  .fabric-row { grid-template-columns: 12rem minmax(0, 1fr); gap: var(--space-xl); }
  .fabric-chip { aspect-ratio: 3 / 2; }
}

/* A short wide strip while stacked (L1-L2), the 3:2 chip beside the copy
   from L3. */
.fabric-chip {
  position: relative;
  aspect-ratio: 21 / 9;
  border-radius: var(--radius-lg);
  border: var(--hairline) solid var(--line);
  overflow: hidden;
}
/* The same woven texture the home page swatches use, so a fabric reads as
   fabric rather than as a flat colour block. */
.fabric-chip::after {
  content: '';
  position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.10) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(0deg, rgba(11, 21, 40, 0.07) 0 1px, transparent 1px 3px);
}

.fabric-detail h3 {
  font-family: var(--font-display);
  font-stretch: var(--wd-tight);
  font-weight: 800;
  font-size: var(--step-2);
  text-transform: uppercase;
  letter-spacing: 0.015em;
  line-height: 1.1;
  margin-bottom: var(--space-2xs);
}
.fabric-detail > p { font-size: var(--step-0); color: var(--ink-60); max-width: 54ch; }

.fabric-specs {
  display: grid;
  gap: var(--space-2xs) var(--space-l);
  margin-top: var(--space-m);
}
@media (min-width: 30rem) {
  .fabric-specs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.fabric-specs > div { border-top: 2px solid var(--ink); padding-top: var(--space-2xs); }
.fabric-specs dt { font-size: var(--step--2); color: var(--ink-60); }
.fabric-specs dd { margin: 0; font-size: var(--step--1); font-weight: 600; }

.fabric-uses { margin-top: var(--space-m); font-size: var(--step--1); color: var(--ink-60); }
.fabric-uses a { color: var(--ink); text-decoration: underline; text-underline-offset: 0.18em; }
.fabric-uses a:hover { color: var(--accent); }

/* --------------------------------------------------------------------------
   12. Fabric swatches
   -------------------------------------------------------------------------- */

/* 1 / 2 / 2 / 4 / 4 - eight fabrics, never three across. */
.swatches { display: grid; gap: var(--space-m); }
@media (min-width: 30rem) { .swatches { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-s); } }
@media (min-width: 48rem) { .swatches { gap: var(--space-m); } }
@media (min-width: 64rem) { .swatches { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Column flex with the spec list pushed to the foot, so the spec rows line up
   across a row of swatches however long each title and description runs. */
.swatch { background: var(--white); border: var(--hairline) solid var(--line); border-radius: var(--radius-lg); overflow: hidden; isolation: isolate; display: flex; flex-direction: column; }
.swatch-body { display: flex; flex-direction: column; flex: 1; }
.swatch-body > dl { margin-top: auto; }
.swatch-chip {
  aspect-ratio: 3 / 2;
  position: relative;
  border-bottom: var(--hairline) solid var(--line);
}
/* A woven texture drawn in CSS, so a swatch reads as fabric before any
   photography exists. The chip colour comes from an inline custom property. */
.swatch-chip::after {
  content: '';
  position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.10) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(0deg, rgba(11, 21, 40, 0.07) 0 1px, transparent 1px 3px);
}
/* Swatch photographs fill the chip, and the drawn weave steps aside for them. */
.swatch-chip img, .fabric-chip img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.swatch-chip.has-photo::after, .fabric-chip.has-photo::after { content: none; }
/* Positioned so it paints above the wash, which is absolutely placed and
   would otherwise cover it. */
.swatch-body { position: relative; z-index: 1; padding: var(--space-m); }
.swatch-body h3 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-0); font-weight: 600; letter-spacing: -0.005em; margin-bottom: var(--space-2xs); }
.swatch-body > p { font-size: var(--step--2); color: var(--ink-60); margin-bottom: var(--space-s); }
.swatch-spec { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; gap: var(--space-s); font-size: var(--step--2); padding-block: 0.4rem; border-top: var(--hairline) dotted var(--line-strong); }
.swatch-spec dt { color: var(--ink-60); }
.swatch-spec dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
/* Same narrow L4 range: label over value on every row, so rows line up
   across the four swatches instead of wrapping at different points. */
@media (min-width: 64rem) and (max-width: 79.999rem) {
  .swatch-spec { grid-template-columns: 1fr; gap: 0.1rem; }
  .swatch-spec dd { text-align: left; }
}
/* L5: a long composition ("88% poly / 12% elastane") wraps to two lines, so
   the first row always reserves two; every card's specs then start level. */
@media (min-width: 80rem) {
  .swatch-body dl > .swatch-spec:first-child { min-height: calc(2 * 1.65em + 0.8rem); }
}

/* --------------------------------------------------------------------------
   13. Decoration methods
   -------------------------------------------------------------------------- */

/* 1 / 2 / 3 / 3 / 3. Sport pages show three methods, so in the two-across
   layout an odd last card spans the row instead of standing alone. */
.methods { display: grid; gap: var(--space-m); }
@media (min-width: 30rem) {
  .methods { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-s); }
  .methods > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (min-width: 48rem) {
  .methods { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-m); }
  .methods > :last-child:nth-child(odd) { grid-column: auto; }
}

.method { background: var(--white); border: var(--hairline) solid var(--line); border-radius: var(--radius-lg); overflow: hidden; isolation: isolate; display: flex; flex-direction: column; }
/* Positioned so it paints above the wash. */
.method-body { position: relative; z-index: 1; padding: var(--space-m); display: flex; flex-direction: column; gap: var(--space-2xs); flex: 1; }
.method-body h3 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-1); font-weight: 600; letter-spacing: -0.005em; }
.method-body p { font-size: var(--step--1); color: var(--ink-60); }
.method-note { margin-top: auto; padding-top: var(--space-s); border-top: var(--hairline) solid var(--line); font-size: var(--step--2); font-weight: 600; color: var(--accent); }

/* --------------------------------------------------------------------------
   14. Sizing
   -------------------------------------------------------------------------- */

/* Scroll with a hint: shadows at either edge appear only while there is more
   table to scroll to in that direction. The row labels stay pinned. */
.table-scroll {
  overflow-x: auto; overscroll-behavior-x: contain;
  border: var(--hairline) solid var(--line); border-radius: var(--radius-lg);
  background:
    linear-gradient(to right, var(--white) 30%, rgba(255, 255, 255, 0)) left / 2.5rem 100% no-repeat local,
    linear-gradient(to left, var(--white) 30%, rgba(255, 255, 255, 0)) right / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(11, 21, 40, 0.16), transparent) left / 0.875rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(11, 21, 40, 0.16), transparent) right / 0.875rem 100% no-repeat scroll,
    var(--white);
}
.table-scroll:focus-visible { outline-offset: 2px; }
.table-note { margin-bottom: var(--space-s); max-width: var(--measure); }
.size-table { width: 100%; border-collapse: collapse; min-width: 34rem; }
@media (min-width: 48rem) { .size-table { min-width: 40rem; } }
.size-table th[scope='row'], .size-table thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--white); box-shadow: inset -1px 0 0 var(--line); }
.size-table tbody tr:nth-child(even) th[scope='row'] { background: var(--paper); }
.size-table caption { text-align: left; padding: var(--space-m) var(--space-m) 0; font-size: var(--step--1); color: var(--ink-60); }
.size-table th, .size-table td { padding: 0.7rem var(--space-s); text-align: left; font-size: var(--step--1); border-bottom: var(--hairline) solid var(--line); }
@media (min-width: 48rem) { .size-table th, .size-table td { padding: 0.85rem var(--space-m); } }
.size-table thead th { font-family: var(--font-display); font-stretch: var(--wd-normal); font-weight: 600; font-size: var(--step--1); border-bottom: 2px solid var(--ink); white-space: nowrap; }
.size-table tbody th { font-weight: 600; }
.size-table tbody tr:nth-child(even) { background: var(--paper); }
.size-table tbody tr:last-child td, .size-table tbody tr:last-child th { border-bottom: 0; }
.size-table td { font-variant-numeric: tabular-nums; color: var(--ink-60); }

.sizing-notes { display: grid; gap: var(--space-m); margin-top: var(--space-l); }
/* 1 / 1 / 3 / 3 / 3 - three notes, so no two-across step to orphan one. */
@media (min-width: 48rem) { .sizing-notes { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.sizing-note h3 { font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-0); font-weight: 600; margin-bottom: var(--space-3xs); }
.sizing-note p { font-size: var(--step--1); color: var(--ink-60); }

/* --------------------------------------------------------------------------
   15. Capacity figures
   -------------------------------------------------------------------------- */

/* 2 / 2 / 2 / 4 / 4 */
.figures { display: grid; gap: var(--space-l) var(--space-m); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 64rem) { .figures { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-l); } }

.figure-item { border-top: 2px solid var(--accent); padding-top: var(--space-s); }
.figure-value {
  display: block;
  font-family: var(--font-display); font-stretch: var(--wd-tight); font-weight: 900;
  font-size: var(--step-5); line-height: 1; letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--space-2xs);
}
.figure-label { font-size: var(--step--1); color: var(--ink-60); }
.on-ink .figure-label { color: var(--on-dark-60); }

/* --------------------------------------------------------------------------
   16. Portfolio gallery
   -------------------------------------------------------------------------- */

/* Nine tiles with one lead. L1-L2: two across, lead full width (1 + 8).
   L3+: three across, lead 2x2 (4 cells + 8 tiles fills four rows exactly). */
.gallery { display: grid; gap: var(--space-2xs); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 48rem) { .gallery { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-s); } }
@media (min-width: 64rem) { .gallery { gap: var(--space-m); } }

.gallery-item { position: relative; overflow: hidden; isolation: isolate; border-radius: var(--radius-lg); }
.gallery-item .ph, .gallery-item .media { height: 100%; border-radius: 0; }
/* Catalogue photographs on the home page: white well, whole garment shown. */
.gallery-link { display: block; height: 100%; text-decoration: none; }
.gallery-item .product-media { position: relative; }
.gallery-caption { position: relative; z-index: 1; }

/* One tile leads, so the grid is not a wall of identical squares. */
.gallery-item-lead { grid-column: span 2; }
@media (min-width: 48rem) { .gallery-item-lead { grid-row: span 2; } }

.gallery-caption {
  position: absolute; inset-inline: 0; bottom: 0;
  padding: var(--space-s);
  font-size: var(--step--2); color: var(--white);
  background: linear-gradient(to top, rgba(11, 21, 40, 0.78), transparent);
}

/* --------------------------------------------------------------------------
   17. FAQ - native details/summary, so it works without JavaScript
   -------------------------------------------------------------------------- */

.faq { max-width: 58rem; border-top: var(--hairline) solid var(--line); }
.faq-item { border-bottom: var(--hairline) solid var(--line); }

.faq-item summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-m);
  padding-block: var(--space-m);
  cursor: pointer; list-style: none;
  font-family: var(--font-display); font-stretch: var(--wd-normal); font-size: var(--step-1); font-weight: 600;
  letter-spacing: -0.005em; line-height: var(--lh-snug);
  transition: color 150ms var(--ease);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--accent); }
.faq-item summary::after {
  content: '+';
  font-family: var(--font-text); font-weight: 400;
  font-size: var(--step-2); line-height: 1; color: var(--accent);
  flex: none; transition: transform 200ms var(--ease);
}

.faq-answer { padding-bottom: var(--space-m); max-width: 62ch; color: var(--ink-60); font-size: var(--step-0); }
.faq-answer > * + * { margin-top: var(--space-s); }
.faq-answer a { color: var(--ink); text-decoration: underline; }
.faq-answer a:hover { color: var(--accent); }

/* --------------------------------------------------------------------------
   18. Forms
   -------------------------------------------------------------------------- */

.form-grid { display: grid; gap: var(--space-m); }
/* L1-L2 one column; L3+ fields pair up. Submit is full width on L1. */
@media (min-width: 48rem) { .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.field-wide { grid-column: 1 / -1; }
.form-grid [type='submit'] { width: 100%; }
@media (min-width: 30rem) { .form-grid [type='submit'] { width: auto; } }

/* The privacy line under the submit button. Quiet, but not hidden: it sits
   where the decision to send is actually made. */
.form-legal {
  font-size: var(--step--2);
  color: var(--ink-60);
  max-width: 44rem;
  margin-top: calc(var(--space-s) * -1);
}
.form-legal a { color: var(--ink); transition: color var(--dur-fast) var(--ease); }
.form-legal a:hover { color: var(--accent); }

.field { display: flex; flex-direction: column; gap: var(--space-3xs); }
.field label, .field legend { font-size: var(--step--1); font-weight: 500; }
.field .hint { font-size: var(--step--2); color: var(--ink-60); }
.field .req { color: var(--accent); }

.field input, .field select, .field textarea {
  font-family: var(--font-text); font-size: var(--step-0);
  color: var(--ink); background: var(--white);
  border: var(--hairline) solid var(--line-strong);
  border-radius: var(--radius);
  padding: 0.75em 0.9em; width: 100%;
  transition: border-color 150ms var(--ease), box-shadow 150ms var(--ease);
}
.field textarea { min-height: 9.5rem; resize: vertical; line-height: 1.55; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--ink-40); }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--ink); box-shadow: 0 0 0 3px rgba(11, 21, 40, 0.06); }
.field input[type='file'] { padding: 0.6em; background: var(--paper); border-style: dashed; }

/* --------------------------------------------------------------------------
   Artwork upload

   The browser's own file input is the most generic control on the form, and
   this is the field that decides whether a quote can be costed at all, so it
   is worth the surface area.

   Without JS the native input above is what you get. Everything below is
   gated on .js, because a drop zone that cannot report which file you picked
   is worse than the plain control.
   -------------------------------------------------------------------------- */

.filefield-drop { display: none; }

.js .filefield-input {
  /* Clipped, not hidden: it must stay in the tab order and stay the control
     the label points at. display:none would remove both. */
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.js .filefield-drop {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-s);
  padding: var(--space-m);
  background: var(--paper);
  border: 2px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  cursor: pointer;
  position: relative;
  isolation: isolate;
  transition:
    border-color var(--dur) var(--ease-out),
    background-color var(--dur) var(--ease-out),
    transform var(--dur) var(--ease-out);
}

.js .filefield-drop:hover { border-color: var(--ink-40); background: var(--white); }

/* The drop surface is aria-hidden, so the hint stays as the input's described-by
   text. With JS on it would be the same sentence printed twice, so it is
   clipped rather than removed. */
.js .filefield .hint {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Dragging a file over it, and keyboard focus on the real input, are the same
   state as far as the eye is concerned. */
.js .filefield-input:focus-visible ~ .filefield-drop,
.js .filefield.is-dragging .filefield-drop {
  border-color: var(--accent);
  border-style: solid;
  background: var(--accent-wash);
}
.js .filefield.is-dragging .filefield-drop { transform: scale(1.01); }

.filefield-copy { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.filefield-prompt { font-size: var(--step-0); font-weight: 600; }
.filefield-formats { font-size: var(--step--2); color: var(--ink-60); max-width: 46ch; }

/* A registration mark, not a cloud. It is what the floor actually aligns
   artwork to, and it is the one thing on this form that could only belong to
   a printer. The brackets open out when a file is dragged over. */
.filefield-mark {
  position: relative;
  flex: none;
  width: 3rem;
  height: 3rem;
  background:
    linear-gradient(var(--ink-40) 0 0) center / 2px 1rem no-repeat,
    linear-gradient(var(--ink-40) 0 0) center / 1rem 2px no-repeat;
  transition: background-size var(--dur) var(--ease-out);
}
.filefield-mark::before,
.filefield-mark::after {
  content: '';
  position: absolute;
  width: 0.9rem;
  height: 0.9rem;
  border: 2px solid var(--accent);
  transition: inset var(--dur) var(--ease-out), width var(--dur) var(--ease-out), height var(--dur) var(--ease-out);
}
.filefield-mark::before { top: 0; left: 0; border-right: 0; border-bottom: 0; }
.filefield-mark::after { bottom: 0; right: 0; border-left: 0; border-top: 0; }

.js .filefield-drop:hover .filefield-mark::before,
.js .filefield.is-dragging .filefield-mark::before { width: 1.25rem; height: 1.25rem; }
.js .filefield-drop:hover .filefield-mark::after,
.js .filefield.is-dragging .filefield-mark::after { width: 1.25rem; height: 1.25rem; }

/* The chosen file, once there is one. */
.filefield-chosen {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  margin-top: var(--space-2xs);
  padding: var(--space-xs) var(--space-s);
  background: var(--white);
  border: var(--hairline) solid var(--line-strong);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.filefield-chosen[hidden] { display: none; }

.filefield-file { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.filefield-name {
  font-size: var(--step--1);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.filefield-size { font-size: var(--step--2); color: var(--ink-60); font-variant-numeric: tabular-nums; }

.filefield-clear {
  flex: none;
  font-family: var(--font-text);
  font-size: var(--step--2);
  color: var(--ink-60);
  background: none;
  border: 0;
  padding: 0.35rem 0.5rem;
  min-height: var(--tap);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  transition: color var(--dur-fast) var(--ease);
}
.filefield-clear:hover { color: var(--accent); }

/* An oversized file, caught before the upload is attempted. */
.filefield.is-toobig .filefield-chosen { border-left-color: var(--accent); background: var(--accent-wash); }
.filefield-error { font-size: var(--step--2); color: var(--accent); margin-top: var(--space-3xs); }

/* Stacked on L1, mark beside the copy from L2. */
@media (min-width: 30rem) {
  .js .filefield-drop { flex-direction: row; align-items: center; gap: var(--space-m); padding: var(--space-m) var(--space-l); }
}

/* Six decoration methods: 1 / 2 / 3 / 3 / 3, never the 5 + 1 auto-fit gave. */
.check-grid { display: grid; gap: var(--space-2xs) var(--space-m); grid-template-columns: 1fr; }
@media (min-width: 30rem) { .check-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 48rem) { .check-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.check { display: flex; align-items: flex-start; gap: 0.55rem; font-size: var(--step--1); cursor: pointer; padding-block: 0.3rem; }
@media (pointer: coarse) { .check { padding-block: 0.65rem; } }
.check input { width: 1.05rem; height: 1.05rem; margin-top: 0.22rem; accent-color: var(--accent); flex: none; }

.form-notice { padding: var(--space-m); border-left: 3px solid var(--accent); background: var(--accent-wash); font-size: var(--step--1); margin-bottom: var(--space-l); border-radius: 0 var(--radius) var(--radius) 0; }
.form-notice-ok { border-left-color: var(--ok); background: var(--ok-wash); }

.form-errors { margin-bottom: var(--space-l); padding: var(--space-m); border-left: 3px solid var(--accent); background: var(--accent-wash); border-radius: 0 var(--radius) var(--radius) 0; }
.form-errors li { font-size: var(--step--1); }
.form-errors li + li { margin-top: var(--space-3xs); }

.form-panel { background: var(--white); border: var(--hairline) solid var(--line); border-radius: var(--radius-lg); padding: clamp(1rem, 0.5rem + 2.5vw, 2.5rem); }

/* --------------------------------------------------------------------------
   19. Inner pages, listings, 404
   -------------------------------------------------------------------------- */

.page-hero { border-bottom: var(--hairline) solid var(--line); padding-block: clamp(2.5rem, 1.5rem + 4vw, 4.5rem); }
.page-hero h1 { margin-bottom: var(--space-s); }
.page-hero .lede { margin-bottom: 0; }

.breadcrumb { font-size: var(--step--2); color: var(--ink-60); margin-bottom: var(--space-m); }
.breadcrumb a { text-decoration: none; padding-block: 0.6rem; }
.breadcrumb a:hover { color: var(--accent); text-decoration: underline; }
.breadcrumb span { color: var(--ink-40); padding-inline: 0.4rem; }

.index-list { border-top: var(--hairline) solid var(--line); }
.index-row { display: grid; gap: var(--space-2xs) var(--space-m); padding-block: var(--space-m); border-bottom: var(--hairline) solid var(--line); align-items: baseline; }
@media (min-width: 48rem) { .index-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) auto; } }
.index-name { font-family: var(--font-display); font-stretch: var(--wd-normal); font-weight: 600; font-size: var(--step-2); letter-spacing: -0.005em; line-height: var(--lh-snug); }
.index-desc { font-size: var(--step--1); color: var(--ink-60); max-width: 44ch; }
.index-spec { font-size: var(--step--2); color: var(--ink-60); white-space: nowrap; }

.error-404 { padding-block: var(--space-3xl); }

.wp-caption, figure.wp-block-image { margin-block: var(--space-l); }
.wp-caption-text, figcaption { font-size: var(--step--2); color: var(--ink-60); margin-top: var(--space-2xs); }
/* Floated images only float from L2; on L1 they would leave a sliver of text. */
.alignleft, .alignright { float: none; margin: 0 0 var(--space-s); }
@media (min-width: 30rem) {
  .alignleft { float: left; max-width: 50%; margin: 0 var(--space-m) var(--space-s) 0; }
  .alignright { float: right; max-width: 50%; margin: 0 0 var(--space-s) var(--space-m); }
}
.prose table { display: block; max-width: 100%; overflow-x: auto; }
.prose pre { overflow-x: auto; }
.aligncenter { margin-inline: auto; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}
