/* ==========================================================================
   Precision Tennis Restring
   Visual language modelled on trunktailors.com — measured from the live site:
     · Helvetica Neue / Arial throughout (no serif)
     · Headings uppercase, 700, letter-spacing ~0.1em, deliberately small
     · Pure white ground, near-black text
     · Buttons: 1px border, square corners, transparent, uppercase
     · Tall portrait imagery, full-bleed, two-up
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  --ink: #121212;
  --ink-2: #222222;
  --muted: #6b6b6b;
  --muted-2: #8e8e8e;
  --line: #e3e3e3;
  --line-2: #f0f0f0;
  --paper: #ffffff;
  --wash: #f4f4f2;
  --wash-2: #ebebe8;

  /* Navy — the wordmark colour, as on the reference site */
  --navy: #1b3a5c;
  --accent: #1b3a5c;

  /* Archivo is a Helvetica-lineage grotesque with REAL 400/500/600/700 cuts.
     The previous stack fell back to Arial on Windows, and Arial ships only
     Regular and Bold — so any weight between 400 and 600 silently rendered as
     Regular. That is why asking for a heavier body text changed nothing. */
  --f-sans: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --f-ui: "Archivo", "Karla", "Helvetica Neue", Arial, sans-serif;
  --f-logo: "Libre Baskerville", Georgia, "Times New Roman", serif;

  /* Weight scale — one place to dial the whole site up or down */
  --w-body: 500;
  --w-ui: 600;
  --w-head: 700;

  /* Measured from the reference: 24px side gutters, no max-width container,
     ~11px gap between grid cells. */
  --gutter: clamp(16px, 2vw, 24px);
  --grid-gap: clamp(8px, 0.8vw, 11px);
  --section-y: clamp(3.5rem, 8vw, 7rem);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* No overflow-x here. The reference leaves both html and body visible; any
     horizontal overflow is contained on the element that causes it, which
     keeps the scrollbar flush to the viewport edge and avoids turning either
     element into a scroll container. */
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-sans);
  font-size: 0.9375rem; /* 15px, as the reference */
  line-height: 1.55;
  letter-spacing: 0.04em;
  font-weight: var(--w-body);
  /* Deliberately NOT antialiased. `-webkit-font-smoothing: antialiased`
     thins every stroke; the reference uses the default subpixel rendering,
     which is what gives its type the heavier, denser look. */
}

img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 3px;
}

::selection { background: var(--ink); color: #fff; }

/* ---------- Layout ----------
   Full-bleed by default: no max-width, 24px gutters, exactly like the
   reference. `--narrow` / `--mid` cap only long-form reading columns. */
.wrap {
  width: 100%;
  padding-inline: var(--gutter);
}

/* Reading column: capped for line length but still anchored to the same
   left gutter as everything else, so nothing steps in and out down the page. */
.wrap--narrow { max-width: calc(820px + var(--gutter) * 2); }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 4rem); }
.section--flush-top { padding-top: 0; }
.section--wash { background: var(--wash); }

/* Last tinted band before the footer: a little extra room underneath so the
   change of colour reads as the section ending rather than being cut off. */
.section--capped { padding-bottom: clamp(4rem, 9vw, 7.5rem); }

.bleed {
  width: 100%;
  padding-inline: var(--gutter);
}

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

/* ==========================================================================
   Type — uppercase, bold, letterspaced. Sizes stay small on purpose.
   ========================================================================== */
.h-xl,
.h-lg,
.h-md,
.h-sm {
  font-family: var(--f-sans);
  font-weight: var(--w-head);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  line-height: 1.3;
  color: var(--ink);
}

.h-xl { font-size: clamp(1.25rem, 2.3vw, 1.95rem); line-height: 1.25; }
.h-lg { font-size: clamp(1.0625rem, 1.8vw, 1.5rem); }
.h-md { font-size: clamp(0.9375rem, 1.3vw, 1.125rem); }
.h-sm { font-size: 0.8125rem; letter-spacing: 0.12em; }

/* Small uppercase label */
.label {
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.label--ink { color: var(--ink); }

/* Body copy — slightly looser than the 1.5 base, since these paragraphs run
   longer than the reference's short captions. */
.body-text {
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ink-2);
  max-width: 62ch;
}
.body-text + .body-text { margin-top: 1.2em; }

.lede {
  font-size: clamp(0.9375rem, 1.1vw, 1.0625rem);
  line-height: 1.65;
  color: var(--ink-2);
  max-width: 58ch;
}

.dim { color: var(--muted); }

/* Centred intro statement — the reference's signature device */
.statement {
  font-family: var(--f-sans);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: clamp(0.9375rem, 1.5vw, 1.1875rem);
  line-height: 1.75;
  text-align: center;
  max-width: 46ch;
  margin-inline: auto;
  color: var(--ink);
}

/* Supporting line under the centred hero statement */
.statement__note {
  margin-top: 0.9rem;
  text-align: center;
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Section head — left-anchored to the page gutter, as the reference is.
   Closing CTA bands centre themselves via .cta-band instead. */
.sec-head { max-width: 52rem; }
.sec-head__title { margin-top: 0.9rem; }
.sec-head__lede { margin-top: 1.1rem; }

/* ==========================================================================
   Buttons — 1px border, square, transparent, uppercase
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  font-family: var(--f-ui);
  font-size: 0.75rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.85rem 1.5rem;
  border: 1px solid var(--ink-2);
  border-radius: 0;
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease),
    border-color 0.35s var(--ease);
}

.btn:hover { background: var(--ink); border-color: var(--ink); color: #fff; }

.btn--solid { background: var(--ink); border-color: var(--ink); color: #fff; }
.btn--solid:hover { background: transparent; color: var(--ink); }

.btn--sm { padding: 0.5rem 0.85rem; font-size: 0.6875rem; letter-spacing: 0.12em; }
.btn--wide { padding-inline: 2.25rem; }

.btn__icon { width: 0.95em; height: 0.95em; flex: none; }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.btn-row--center { justify-content: center; }

/* Once a centred row wraps, buttons of very different label lengths — "Book a
   Restring Online" over "SMS" — read as a ragged stack. Matching their width
   keeps the column aligned. */
@media (max-width: 520px) {
  .btn-row--center > .btn,
  .cta-band__cta > .btn { flex: 1 1 100%; }
}

/* Underline link */
.tlink {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--ink);
  transition: opacity 0.3s var(--ease);
}
.tlink:hover { opacity: 0.55; }

/* ==========================================================================
   Header — nav left, wordmark centred, actions right
   ========================================================================== */
.hdr {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  border-bottom: 1px solid transparent;
  transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease);
}

/* Solid by default: without backdrop-filter a translucent bar lets page
   content bleed through the nav. Frosted only where it can actually blur. */
.hdr.is-stuck {
  background: var(--paper);
  border-bottom-color: var(--line);
}

@supports (backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px)) {
  .hdr.is-stuck {
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: blur(12px) saturate(1.3);
    -webkit-backdrop-filter: blur(12px) saturate(1.3);
  }
}

.hdr__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  height: 68px;
}

/* Pin each item to its own column explicitly.
   Without this, hiding .nav on mobile removes it from the grid entirely and
   auto-placement slides the wordmark into column 1 — which is exactly why the
   logo sat off-centre on phones. Explicit columns keep it centred at every
   breakpoint, whether or not the nav is present. */
.hdr__inner > .nav { grid-column: 1; justify-self: start; }
.hdr__inner > .brand { grid-column: 2; justify-self: center; }
.hdr__inner > .hdr__actions { grid-column: 3; justify-self: end; }

.nav {
  display: flex;
  align-items: center;
  gap: clamp(0.7rem, 1.3vw, 1.4rem);
}

.nav__link {
  font-family: var(--f-sans);
  font-size: 0.6875rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease), opacity 0.3s var(--ease);
}

.nav__link:hover { opacity: 0.55; }
.nav__link.is-active { border-bottom-color: var(--ink); }

/* Wordmark — modelled on the reference's logo treatment: a wide, short,
   centred serif wordmark in navy, set in caps with open letter-spacing. */
.brand {
  display: grid;
  justify-items: center;
  gap: 0.28rem;
  text-align: center;
  white-space: nowrap;
}

.brand__name {
  font-family: var(--f-logo);
  font-weight: 700;
  font-size: clamp(0.9375rem, 1.4vw, 1.1875rem);
  letter-spacing: 0.2em;
  /* open tracking pushes the word right; pull the trailing space back so the
     wordmark stays optically centred */
  text-indent: 0.2em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--navy);
}

.brand__sub {
  font-family: var(--f-logo);
  font-size: 0.5625rem;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  color: var(--navy);
  opacity: 0.62;
  line-height: 1;
}

.hdr__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.9rem;
}

.hdr__phone {
  font-family: var(--f-sans);
  font-size: 0.7188rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
  transition: opacity 0.3s var(--ease);
}
.hdr__phone:hover { opacity: 0.55; }

/* Burger */
.burger {
  display: none;
  width: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--line);
  border-radius: 0;
  cursor: pointer;
}

.burger__bars { width: 15px; height: 9px; position: relative; }
.burger__bars::before,
.burger__bars::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 1px;
  background: var(--ink);
  transition: transform 0.35s var(--ease-out), opacity 0.25s;
}
.burger__bars::before { top: 0; }
.burger__bars::after { bottom: 0; }
.burger[aria-expanded="true"] .burger__bars::before { transform: translateY(4px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__bars::after { transform: translateY(-4px) rotate(-45deg); }

.mobile-nav {
  position: fixed;
  inset: 68px 0 0 0;
  z-index: 99;
  background: var(--paper);
  padding: 1.5rem var(--gutter) 2.5rem;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease-out), visibility 0.3s;
  overflow-y: auto;
}

.mobile-nav.is-open { opacity: 1; visibility: visible; transform: none; }

.mobile-nav__link {
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding-block: 1rem;
  border-bottom: 1px solid var(--line-2);
}

.mobile-nav__foot { margin-top: auto; padding-top: 2rem; display: grid; gap: 0.6rem; }

/* Keep the left-hand nav visible down to small laptops — hide the phone
   number first, since it buys width and is repeated in the footer. */
@media (max-width: 1120px) {
  .hdr__phone { display: none; }
}

@media (max-width: 900px) {
  .nav { display: none; }
  .burger { display: flex; }
  .hdr__actions { gap: 0.6rem; }
}

@media (max-width: 560px) {
  .hdr__cta { display: none; }
}

/* ==========================================================================
   Plates — tall portrait blocks standing in for photography
   Swap the inner content for <img> when real photos exist; the ratio and
   rhythm are already correct.
   ========================================================================== */
.plate {
  position: relative;
  background: var(--wash);
  aspect-ratio: 5 / 7;
  overflow: hidden;
  display: grid;
  place-items: center;
}

.plate--wide { aspect-ratio: 4 / 3; }

/* A cut-out product shot rather than a scene: show the whole object instead
   of cropping it, and blend its white studio background into the tile so it
   sits alongside full-bleed photography without looking pasted on. */
.plate--product { background: var(--wash); }

/* A wide product shot gets a landscape frame rather than the portrait one, so
   it isn't marooned in a tall tile. */
.plate--product.plate--fit { aspect-ratio: 4 / 3; min-height: 0; }

/* ---------------------------------------------------------------------------
   ONE IMAGE TREATMENT FOR THE WHOLE SITE
   Every product and service photo is shot on white. They all get the same
   handling — contained so nothing is cropped, inset so nothing touches the
   edge, and multiplied so the white studio ground melts into the tile. That
   shared treatment is what makes a mixed set of supplier photos read as one
   consistent system.
   Scene photography (the hero plates) still fills its frame.

   The media is positioned against the tile rather than laid out inside it.
   These tiles get their height from `aspect-ratio`, and a percentage height on
   a grid item does not resolve against that — the image fell back to its own
   intrinsic height, overflowed a landscape tile and was clipped by
   `overflow: hidden`. That is what cropped the string photo in the tension
   panel. `inset: 0` resolves against the padding box, which is always definite,
   so the image is contained in the frame it is actually given.
   --------------------------------------------------------------------------- */
.scard__media,
.acard__media,
.svc__media,
.tension__swatch-img { position: relative; }

.scard__media > .media-photo,
.acard__media > .media-photo,
.tension__swatch-img > .media-photo,
.plate--product > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  padding: 7%;
  mix-blend-mode: multiply;
}

/* Service photos are a mix of scene shots and packshots, so the inset
   treatment above cannot make them agree — each one showed its own rectangle
   at its own size. They fill the frame instead, which is the one treatment
   every photo can share. The two packshots are supplied on a 5:6 canvas so
   filling crops nothing off them. */
.svc__media > .media-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  padding: 0;
  mix-blend-mode: normal;
}

/* Photos already cut out to transparency carry no white ground to blend away,
   and multiplying them only muddies the highlights. */
.media-photo.cutout,
.plate--product > img.cutout { mix-blend-mode: normal; }

/* Scene photos fill their slot and crop from the centre.
   `.plate--product` is excluded explicitly: it has the same specificity as
   `.plate`, so without :not() whichever rule came last would win. */
.plate:not(.plate--product) > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Drawing kept behind the photo, shown only if the file fails to load */
.media-fallback { display: none; position: absolute; inset: 0; place-items: center; }
.media-fallback svg { width: 76%; height: 76%; }
.media-photo.is-broken { display: none; }
.media-photo.is-broken + .media-fallback { display: grid; }

.plate > svg { width: 78%; height: 78%; }
/* The machine drawing is wider and lighter than the racquet — give it more
   room so the two plates carry equal visual weight. */
.plate > .mach { width: 94%; height: 94%; }

.plate__cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 1.1rem 1.25rem;
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Two-up bleed grid — 11px gutter between cells, as measured */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--grid-gap);
}

@media (max-width: 520px) {
  .grid-2 { grid-template-columns: 1fr; }
}

/* Split: image one side, copy the other */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: center;
}

.split--reverse .split__media { order: 2; }

.split__copy { max-width: 34rem; }

@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; }
  .split--reverse .split__media { order: 0; }
}

/* ==========================================================================
   Reveal — hidden state scoped to .js so the page still renders if
   scripting fails. Motion is an enhancement, never a prerequisite.
   ========================================================================== */
.js .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
  transition-delay: var(--d, 0ms);
}

.js .reveal.is-in { opacity: 1; transform: none; }

/* ---------- String bed ---------- */
.bed { width: 100%; height: auto; overflow: visible; }

.bed__frame,
.bed__throat {
  fill: none;
  stroke: var(--ink);
  stroke-width: 4.5;
  opacity: 0.9;
}

.bed__string {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.05;
  stroke-linecap: butt;
  opacity: 0.42;
}

.bed__mains, .bed__crosses { clip-path: inset(0 0 0 0); }

.bed.is-animating .bed__mains { animation: wipe-down 0.9s var(--ease-out) 0.15s both; }
.bed.is-animating .bed__crosses { animation: wipe-right 1.1s var(--ease-out) 0.85s both; }

@keyframes wipe-down {
  from { clip-path: inset(0 0 100% 0); }
  to { clip-path: inset(0 0 0 0); }
}

@keyframes wipe-right {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}

/* ==========================================================================
   Services
   ========================================================================== */
.svc-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem) clamp(1rem, 2vw, 2rem);
  align-items: stretch;
}

@media (max-width: 900px) { .svc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .svc-grid { grid-template-columns: 1fr; } }

/* The service photos come from six different sources and their colour casts
   fight each other — and fight the black-and-white hero above them. Desaturating
   the grid makes a mixed set of supplier photos read as one. */
.svc-grid--mono .svc__media { filter: grayscale(1); }

/* Flex column so the description absorbs the slack and every "Read more"
   lands on the same baseline, regardless of how long the copy runs. */
.svc {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  height: 100%;
}

.svc__body { flex: 1 1 auto; }
.svc > .tlink { align-self: flex-start; margin-top: auto; }

/* Every service tile is the same frame: identical ratio, identical 1px edge,
   square corners, no shadow. The photo fills it edge to edge (see the
   `cover` rule below) so a picture never sits inside the tile as a smaller
   rectangle — which is what made some cards look bordered and others not. */
.svc__media {
  position: relative;
  background: var(--wash);
  aspect-ratio: 5 / 6;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
  transition: border-color 0.4s var(--ease);
}

.svc:hover .svc__media { border-color: var(--muted-2); }

/* Services not yet running: still shown, clearly marked, still enquirable */
.svc__badge {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 2;
  background: var(--ink);
  color: #fff;
  font-family: var(--f-ui);
  font-size: 0.5625rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.3rem 0.5rem;
}

.svc--soon .svc__media svg { opacity: 0.45; }
.svc--soon .svc__from { color: var(--muted-2); }

.svc:hover .svc__media { background: var(--wash-2); }
.svc__media svg { width: 72%; height: 72%; }

.svc__title { margin-top: 0.15rem; }
.svc__body { font-size: 0.875rem; line-height: 1.75; color: var(--muted); }
.svc__from {
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
}

/* ==========================================================================
   Strings & pricing
   ========================================================================== */
.ptable { border-top: 1px solid var(--ink); }

.prow {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.4fr) auto;
  gap: clamp(0.75rem, 2.5vw, 2rem);
  align-items: center;
  padding: 1.15rem 0;
  border-bottom: 1px solid var(--line-2);
}

.prow__name {
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
}

.prow__meta {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-top: 0.3rem;
}

/* Colour on a price row: the swatch sits on the text baseline beside its name,
   so the row still reads as one line of meta rather than sprouting a column. */
.prow__colour {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  white-space: nowrap;
}

/* Multi-colour strings sit their swatches in a tight run, then the names. */
.prow__colour .swatch { flex: none; margin-right: -0.2em; }
.prow__colour .swatch:last-of-type { margin-right: 0; }

.prow__desc { font-size: 0.8438rem; color: var(--muted); line-height: 1.7; }

.prow__price {
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

@media (max-width: 780px) {
  .prow { grid-template-columns: 1fr auto; }
  .prow__desc { grid-column: 1 / -1; }
}

/* String cards */
.string-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: clamp(1.5rem, 3vw, 2.25rem) clamp(1rem, 2vw, 1.75rem);
}

.scard { display: grid; gap: 0.9rem; align-content: start; position: relative; }

.scard__media {
  background: var(--wash);
  aspect-ratio: 5 / 6;
  display: grid;
  place-items: center;
  overflow: hidden;
  transition: background-color 0.4s var(--ease);
}

.scard:hover .scard__media { background: var(--wash-2); }
.scard__media svg { width: 76%; height: 76%; }

.scard__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}

.scard__name {
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
}

.scard__price {
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.8125rem;
  flex: none;
}

.scard__type {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-top: 0.3rem;
}

.scard__desc { font-size: 0.8438rem; line-height: 1.7; color: var(--muted); }

.scard__tag {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-ui);
  font-size: 0.5625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.3rem 0.5rem;
  z-index: 2;
}

/* Accessories */
.acc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem) clamp(1rem, 2vw, 1.5rem);
}

.acard { display: grid; gap: 0.75rem; align-content: start; }

.acard__media {
  background: var(--wash);
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  overflow: hidden;
  transition: background-color 0.4s var(--ease);
}

.acard:hover .acard__media { background: var(--wash-2); }
.acard__media svg { width: 74%; height: 74%; }

.acard__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}

.acard__name {
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
}

.acard__price { font-weight: 700; font-size: 0.75rem; flex: none; }

.acard__meta {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
}

/* Multi-buy line on an accessory — the deal reads as part of the item.
   `.acard` is a grid, so the badge needs `justify-self` to shrink to its text
   rather than stretching the full column width. */
.acard__bundle {
  margin-top: 0.4rem;
  justify-self: start;
  display: inline-block;
  padding: 0.25rem 0.45rem;
  border: 1px solid var(--line);
  font-family: var(--f-ui);
  font-size: 0.5938rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* "Updated as of …" stamp, used under every block that quotes a price */
.pricestamp {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-top: 0.9rem;
}

.pricestamp--tight { margin-top: 0.5rem; }

.swatches { display: flex; gap: 4px; flex-wrap: wrap; }
.swatch { width: 12px; height: 12px; border: 1px solid var(--line); }

/* ==========================================================================
   Steps / numbered sequences
   ========================================================================== */
.steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

@media (max-width: 900px) { .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .steps { grid-template-columns: 1fr; } }

.step { display: grid; gap: 0.7rem; align-content: start; }

.step__num {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  color: var(--muted-2);
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--line);
}

.step__body { font-size: 0.875rem; line-height: 1.75; color: var(--muted); }

/* ==========================================================================
   Accordion
   ========================================================================== */
.acc { border-top: 1px solid var(--ink); }
.acc__item { border-bottom: 1px solid var(--line-2); }

.acc__btn {
  width: 100%;
  background: none;
  border: 0;
  padding: 1.35rem 2.5rem 1.35rem 0;
  text-align: left;
  cursor: pointer;
  position: relative;
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--ink);
  transition: opacity 0.3s var(--ease);
}

.acc__btn:hover { opacity: 0.55; }

.acc__btn::before,
.acc__btn::after {
  content: "";
  position: absolute;
  right: 2px;
  top: 50%;
  background: currentColor;
  transition: transform 0.35s var(--ease-out), opacity 0.25s;
}
.acc__btn::before { width: 12px; height: 1px; transform: translateY(-50%); }
.acc__btn::after { width: 1px; height: 12px; right: 7px; transform: translateY(-50%); }
.acc__btn[aria-expanded="true"]::after { transform: translateY(-50%) rotate(90deg); opacity: 0; }

.acc__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s var(--ease-out);
}
.acc__item.is-open .acc__panel { grid-template-rows: 1fr; }
.acc__panel-inner { overflow: hidden; }

.acc__body {
  padding-bottom: 1.5rem;
  padding-right: clamp(0rem, 6vw, 5rem);
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.8;
}
.acc__body p + p { margin-top: 0.9em; }
.acc__body strong { color: var(--ink); font-weight: 700; }

/* ==========================================================================
   Forms
   ========================================================================== */
.field { display: grid; gap: 0.45rem; }

.field__label {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.field__input,
.field__select,
.field__textarea {
  width: 100%;
  padding: 0.8rem 0.9rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 0;
  font-size: 0.9375rem;
  transition: border-color 0.3s var(--ease);
}

.field__textarea { min-height: 130px; resize: vertical; }

.field__input:focus,
.field__select:focus,
.field__textarea:focus { outline: none; border-color: var(--ink); }

.field__hint { font-size: 0.75rem; color: var(--muted-2); line-height: 1.6; }
.field__error { font-size: 0.75rem; color: #b3261e; display: none; }

.field.has-error .field__input,
.field.has-error .field__select,
.field.has-error .field__textarea { border-color: #b3261e; }
.field.has-error .field__error { display: block; }

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.1rem;
}
.form-grid > .field--full { grid-column: 1 / -1; }

@media (max-width: 640px) { .form-grid { grid-template-columns: 1fr; } }

/* Choice tiles */
.choices { display: grid; gap: 0.4rem; }
.choices--cols { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }

.choice {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.8rem 0.95rem;
  background: #fff;
  border: 1px solid var(--line);
  cursor: pointer;
  transition: border-color 0.3s var(--ease);
}

.choice:hover { border-color: var(--muted-2); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }

.choice__dot {
  width: 14px; height: 14px;
  border: 1px solid var(--line);
  border-radius: 50%;
  flex: none;
  position: relative;
  transition: border-color 0.3s var(--ease);
}
.choice__dot::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--ink);
  transform: scale(0);
  transition: transform 0.25s var(--ease-out);
}
.choice--check .choice__dot { border-radius: 0; }
.choice--check .choice__dot::after { border-radius: 0; }

.choice input:checked ~ .choice__dot { border-color: var(--ink); }
.choice input:checked ~ .choice__dot::after { transform: scale(1); }
.choice:has(input:checked) { border-color: var(--ink); }
.choice input:focus-visible ~ .choice__dot { outline: 1px solid var(--ink); outline-offset: 3px; }

.choice__text { flex: 1; min-width: 0; }

.choice__name {
  display: block;
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
}

.choice__meta {
  display: block;
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-top: 0.15rem;
}

.choice__price { font-weight: 700; font-size: 0.8125rem; flex: none; }

/* Slots */
.slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 0.4rem; }

.slot {
  padding: 0.65rem 0.4rem;
  text-align: center;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 0;
  font-family: var(--f-ui);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease),
    color 0.25s var(--ease);
}

.slot:hover:not(:disabled) { border-color: var(--muted-2); }
.slot[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
.slot:disabled { opacity: 0.3; cursor: not-allowed; text-decoration: line-through; }

.form-status {
  margin-top: 1.25rem;
  padding: 0.9rem 1rem;
  font-size: 0.875rem;
  display: none;
  border: 1px solid;
}
.form-status.is-ok { display: block; border-color: var(--line); color: var(--ink); background: var(--wash); }
.form-status.is-err { display: block; border-color: #b3261e; color: #b3261e; }

/* Colour picker for strings that come in more than one colour.
   Shares the swatch styling with the dampener picker. */
.colour-picker {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.colour-picker__name {
  margin-left: 0.35rem;
  font-family: var(--f-ui);
  font-size: 0.5938rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* On a string card the picker sits under the copy */
.scard .colour-picker { margin-top: 0.1rem; }

/* In the tension panel it sits under the caption */
.tension__swatch .colour-picker { margin-top: 0.5rem; }

/* Note about stock that will grow over time */
.stocknote {
  border-left: 2px solid var(--ink);
  padding: 0.95rem 1.15rem;
  background: var(--paper);
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--ink-2);
  max-width: 66ch;
}

.stocknote strong { font-weight: var(--w-head); }

/* Label with a control beside it (e.g. the tension unit toggle) */
.field__labelrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

/* Colour picker inside an add-on row */
.choice--haspicker { align-items: flex-start; }
.choice--haspicker .choice__dot { margin-top: 0.15rem; }

.choice__colours {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.5rem;
}

.swatch-btn {
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  cursor: pointer;
  transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}

.swatch-btn:hover { transform: translateY(-1px); }

.swatch-btn[aria-pressed="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px var(--ink);
}

.swatch-btn--any {
  width: auto;
  padding: 0 0.4rem;
  font-family: var(--f-ui);
  font-size: 0.5625rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  background: #fff;
}

.swatch-btn--any[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
  box-shadow: none;
}

/* Quantity toggle on an add-on that has a multi-buy price */
.choice__qty {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.5rem;
}

.qty-btn {
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 0;
  background: #fff;
  cursor: pointer;
  font-family: var(--f-ui);
  font-size: 0.5938rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease);
}

.qty-btn:hover { border-color: var(--muted-2); }

.qty-btn[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

/* Three ways to book — text, call, or the form */
.quick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--grid-gap);
}

.quick__opt {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 1.15rem 1.25rem;
  border: 1px solid var(--line);
  background: #fff;
  transition: border-color 0.3s var(--ease), background-color 0.3s var(--ease),
    transform 0.3s var(--ease-out);
}

.quick__opt:hover {
  border-color: var(--ink);
  transform: translateY(-2px);
}

.quick__opt--active { border-color: var(--ink); background: var(--wash); }

.quick__icon { width: 22px; height: 22px; flex: none; color: var(--ink); }
.quick__text { display: grid; gap: 0.2rem; min-width: 0; }

.quick__name {
  font-weight: var(--w-head);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.3;
}

.quick__meta {
  font-size: 0.75rem;
  color: var(--muted);
  line-height: 1.45;
}

@media (max-width: 780px) {
  .quick { grid-template-columns: 1fr; }
}

/* String recommendation from the ticked preferences */
.suggestion {
  margin-top: 1rem;
  padding: 0.9rem 1.05rem;
  border-left: 2px solid var(--ink);
  background: var(--wash);
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--ink-2);
}

.suggestion strong { font-weight: var(--w-head); }

/* Pay-on-collection note */
.paynote {
  border: 1px solid var(--line);
  padding: 1.1rem 1.25rem;
  background: var(--wash);
}

.paynote__title {
  font-weight: var(--w-head);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.paynote__body {
  margin-top: 0.45rem;
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--muted);
}

/* Booking layout */
.booking {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: start;
}

.booking__aside {
  position: sticky;
  top: 90px;
  border: 1px solid var(--line);
  background: #fff;
}

.summary__head { padding: 1rem 1.15rem; border-bottom: 1px solid var(--line); background: var(--wash); }
.summary__body { padding: 1.15rem; display: grid; gap: 0.75rem; }

.summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.9rem;
  font-size: 0.8125rem;
}
.summary__row span:first-child { color: var(--muted); }
.summary__row span:last-child { font-weight: 700; text-align: right; }

.summary__total {
  border-top: 1px solid var(--line);
  padding: 1rem 1.15rem;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
.summary__total-val { font-weight: 700; font-size: 1.125rem; }
.summary__note { padding: 0 1.15rem 1.15rem; font-size: 0.75rem; color: var(--muted-2); line-height: 1.65; }

.fieldset { border: 0; padding: 0; margin: 0; }
.fieldset + .fieldset { margin-top: 2.5rem; }

.fieldset__head {
  display: flex;
  align-items: baseline;
  gap: 0.8rem;
  padding-bottom: 0.85rem;
  margin-bottom: 1.2rem;
  border-bottom: 1px solid var(--ink);
}

.fieldset__num { font-family: var(--f-ui); font-size: 0.625rem; letter-spacing: 0.16em; color: var(--muted-2); }

.fieldset__title {
  font-family: var(--f-sans);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

@media (max-width: 940px) {
  .booking { grid-template-columns: 1fr; }
  .booking__aside { position: static; order: -1; }
}

/* ==========================================================================
   Misc blocks
   ========================================================================== */
.callout {
  border: 1px solid var(--line);
  padding: clamp(1.25rem, 3vw, 2rem);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
}

.callout__title { font-weight: 700; font-size: 0.8125rem; letter-spacing: 0.12em; text-transform: uppercase; }
.callout__body { color: var(--muted); font-size: 0.875rem; margin-top: 0.5rem; max-width: 52ch; line-height: 1.75; }

.info-list { display: grid; gap: 1.35rem; }
.info { display: grid; gap: 0.25rem; }
.info__key {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.info__val { font-size: 0.9375rem; line-height: 1.7; }
.info__val a { border-bottom: 1px solid var(--line); transition: border-color 0.3s; }
.info__val a:hover { border-color: var(--ink); }

.hours { display: grid; gap: 0.4rem; }
.hours__row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.8438rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--line-2);
}
.hours__row span:first-child { color: var(--muted); }

.map-frame {
  border: 1px solid var(--line);
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--wash);
}
.map-frame iframe { width: 100%; height: 100%; border: 0; display: block; }

.contact__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

@media (max-width: 900px) { .contact__grid { grid-template-columns: 1fr; } }

/* Sits directly under the fixed header */
.hero-bleed { padding-top: calc(68px + clamp(0.5rem, 1.5vw, 1.25rem)); }

/* Page header */
.phead { padding-top: clamp(6rem, 11vw, 9rem); padding-bottom: clamp(2rem, 4vw, 3.25rem); }
.phead__title { margin-top: 0.9rem; }
.phead__lede { margin-top: 1.1rem; }

/* CTA band — the one block that is genuinely centred, so it carries its own
   centring rather than relying on a centred wrapper. */
.cta-band {
  text-align: center;
  max-width: 780px;
  margin-inline: auto;
}
.cta-band__title { margin-top: 0.9rem; }
.cta-band__lede { margin-top: 1.1rem; margin-inline: auto; }
.cta-band__cta { margin-top: 1.75rem; justify-content: center; }

/* Tension explorer */
.tension {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}

.tension__value { font-weight: 700; font-size: clamp(2rem, 4vw, 3rem); letter-spacing: 0.02em; line-height: 1; }
.tension__value sup {
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  margin-left: 0.4em;
  color: var(--muted-2);
  top: -1.5em;
}

.range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 1px;
  background: var(--line);
  margin-top: 1.5rem;
  cursor: pointer;
}
.range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--ink);
  cursor: pointer;
  transition: transform 0.25s var(--ease-out);
}
.range::-webkit-slider-thumb:hover { transform: scale(1.15); }
.range::-moz-range-thumb {
  width: 16px; height: 16px;
  border: 0;
  border-radius: 50%;
  background: var(--ink);
  cursor: pointer;
}

/* Unit toggle — KG / LB */
.unit-toggle { display: inline-flex; border: 1px solid var(--line); }

.unit-toggle button {
  padding: 0.4rem 0.8rem;
  background: #fff;
  border: 0;
  cursor: pointer;
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease);
}

.unit-toggle button + button { border-left: 1px solid var(--line); }
.unit-toggle button[aria-pressed="true"] { background: var(--ink); color: #fff; }

/* In-stock string picker */
.stringpick { display: flex; flex-wrap: wrap; gap: 0.35rem; }

.stringpick button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.7rem;
  background: #fff;
  border: 1px solid var(--line);
  cursor: pointer;
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease),
    color 0.25s var(--ease);
}

.stringpick button:hover { border-color: var(--muted-2); }
.stringpick button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }

.stringpick__dot {
  width: 11px;
  height: 11px;
  flex: none;
  border: 1px solid rgba(0, 0, 0, 0.18);
}

/* Recommended-range readout */
.tension__rec {
  margin-top: 1.1rem;
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--line);
  background: var(--wash);
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--ink-2);
}

.tension__rec strong { font-weight: 700; }

.tension__status {
  display: inline-block;
  margin-top: 0.5rem;
  font-family: var(--f-ui);
  font-size: 0.5938rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.2rem 0.45rem;
  border: 1px solid currentColor;
}

.tension__status--in { color: #2c7a4b; }
.tension__status--low { color: #a06a00; }
.tension__status--high { color: #b3261e; }

/* Range track showing the recommended band */
.range-wrap { position: relative; margin-top: 1.5rem; }

.range-band {
  position: absolute;
  top: 0;
  height: 5px;
  background: rgba(18, 18, 18, 0.14);
  pointer-events: none;
  transition: left 0.3s var(--ease), width 0.3s var(--ease);
}

.range-wrap .range { margin-top: 0; position: relative; z-index: 1; height: 5px; background: transparent; }

.range-rail {
  position: absolute;
  top: 2px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line);
  pointer-events: none;
}

/* The art panel: the string's own coil, then the racquet strung in it */
.tension__swatch { margin-bottom: var(--grid-gap); }

.tension__swatch-img {
  background: var(--wash);
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.tension__swatch-img svg { width: 74%; height: 74%; }

/* Caption and colour picker sit centred under the photo rather than ranged
   left off its edge. */
.tension__swatch-cap {
  padding-top: 0.7rem;
  font-family: var(--f-ui);
  font-size: 0.5938rem;
  font-weight: var(--w-ui);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}

.tension__swatch .colour-picker { justify-content: center; }

.tension__swatch { margin-bottom: 0; }

@media (max-width: 860px) {
  .tension { grid-template-columns: 1fr; }
  .tension__art { max-width: 320px; margin-inline: auto; }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.ftr { border-top: 1px solid var(--line); padding-top: clamp(2.5rem, 5vw, 4rem); padding-bottom: 1.75rem; }

.ftr__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: clamp(1.75rem, 4vw, 3rem);
  padding-bottom: 2.5rem;
}

.ftr__brand-name {
  font-weight: 700;
  font-size: 0.875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.ftr__blurb { margin-top: 0.85rem; font-size: 0.8438rem; max-width: 32ch; line-height: 1.8; color: var(--muted); }

.ftr__h {
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: 0.9rem;
}

.ftr__list { display: grid; gap: 0.55rem; }

/* Social button under the footer contact column */
.ftr__social { margin-top: 1.1rem; }
.ftr__list a { font-size: 0.8438rem; color: var(--ink-2); transition: opacity 0.3s var(--ease); }
.ftr__list a:hover { opacity: 0.55; }

.ftr__bottom {
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: space-between;
  font-family: var(--f-ui);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
}

@media (max-width: 860px) { .ftr__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .ftr__grid { grid-template-columns: 1fr; } }

/* ==========================================================================
   Floating review button — fixed bottom-left, on every page
   ========================================================================== */
.gbtn {
  position: fixed;
  left: var(--gutter);
  bottom: var(--gutter);
  z-index: 90;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.7rem 1rem;
  background: var(--paper);
  border: 1px solid var(--ink-2);
  color: var(--ink-2);
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 2px 14px -6px rgba(0, 0, 0, 0.25);
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease),
    transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease);
}

.gbtn:hover {
  background: var(--ink);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 10px 24px -10px rgba(0, 0, 0, 0.45);
}

.gbtn__star {
  width: 13px;
  height: 13px;
  flex: none;
  fill: currentColor;
  transition: transform 0.45s var(--ease-out);
}

.gbtn:hover .gbtn__star { transform: rotate(72deg) scale(1.1); }

/* Entry animation, once, after the page has settled */
.js .gbtn {
  opacity: 0;
  transform: translateY(10px);
}

.js .gbtn.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 0.6s var(--ease-out), transform 0.6s var(--ease-out),
    background-color 0.35s var(--ease), color 0.35s var(--ease),
    box-shadow 0.35s var(--ease);
}

.js .gbtn.is-in:hover { transform: translateY(-2px); }

/* Collapse to the star alone on small screens so it never covers content */
@media (max-width: 640px) {
  .gbtn { padding: 0.7rem; gap: 0; }
  .gbtn__text { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js .gbtn { opacity: 1; transform: none; }
  .gbtn:hover { transform: none; }
}

/* ==========================================================================
   Centred page treatment
   Applied via `class="page-centered"` on <body>. Used on Why Precision
   Tennis, where the content reads as a single centred statement rather than
   a left-anchored index.
   ========================================================================== */
.page-centered .wrap,
.page-centered .wrap--narrow {
  margin-inline: auto;
}

.page-centered .sec-head,
.page-centered .lede,
.page-centered .body-text,
.page-centered .tension__verdict-body,
.page-centered .svc__body {
  margin-inline: auto;
  text-align: center;
}

.page-centered .sec-head { max-width: 62ch; }

/* Split rows stack their halves centred rather than edge-to-edge */
.page-centered .split {
  align-items: center;
  justify-items: center;
}

.page-centered .split__copy {
  margin-inline: auto;
  text-align: center;
}

/* Numbered principles read as centred cards */
.page-centered .step { text-align: center; }
.page-centered .step__num { border-bottom: 0; padding-bottom: 0.2rem; }

.page-centered .btn-row { justify-content: center; }

/* The pull-quote statement is already centred; keep it wider here */
.page-centered .statement { max-width: 52ch; }

/* Media blocks stay centred within their column */
.page-centered .split__media { width: 100%; }

@media (max-width: 860px) {
  .page-centered .split__copy { text-align: center; }
}

/* ---------- Utilities ---------- */
.mt-1 { margin-top: 1rem; }
.mt-2 { margin-top: 2rem; }
.mt-3 { margin-top: 3rem; }
.mt-4 { margin-top: 4rem; }
.center { text-align: center; }

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

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--gutter);
  z-index: 200;
  background: var(--ink);
  color: #fff;
  padding: 0.7rem 1.1rem;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: top 0.3s var(--ease);
}
.skip-link:focus { top: 0; }

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .bed.is-animating .bed__mains,
  .bed.is-animating .bed__crosses { animation: none; clip-path: inset(0 0 0 0); }
}
