/* ============================================================
   MOSS PADELKLUBB — shared shell
   Everything the three designs have in common: the reset, the
   preview bar, and — most importantly — the structural system
   that stops the page reading as loose floating parts.

   THE FIX FOR "FLOATY":
   1. Two continuous hairline RAILS run down the page at the
      content edges. Every band redraws them in its own colour,
      and because bands stack with zero gap the lines read as
      one unbroken pair from header to footer.
   2. Bands butt directly against each other. No gaps, no
      free-floating rounded rectangles on a background.
   3. Nothing has a drop shadow. Separation comes from an edge
      or a colour change, never from hovering above the page.
   4. One vertical rhythm (--band-y) for every section.
   5. Card groups share their edges (1px grid gaps over a rule
      colour) so a group reads as one divided panel.
   ============================================================ */

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

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

body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--on-ground);
  background: var(--ground);
  font-size: 16px;
  line-height: 1.55;
  /* No overflow-x clip here: nothing on the page overflows the
     document, and a clip on body would only create a clipping context
     for positioned layers to get trapped in. Verified at 320-1920px. */
}

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

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

/* A lime ring on a lime band measured 1.00:1 — invisible. The ring is
   now an ink/paper core with a lime halo, so it carries its own
   contrast whatever it lands on, including the lime CTA bands. */
:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--focus-halo);
  border-radius: 2px;
}
/* The one fixed ground pins its own ring: inheriting the theme's would
   leak a dark outline onto navy in light mode (measured 1.10:1). */
.band--navy :focus-visible { --focus-ring: var(--n-0); --focus-halo: var(--lime); }
/* Anything sitting on the inverted material takes the inverted ring,
   otherwise it inherits the page ground's tokens and lands dark-on-dark
   (or light-on-light) — measured 1.10:1 before this rule. */
.band--invert :focus-visible,
.on-invert :focus-visible {
  --focus-ring: var(--on-invert);
  --focus-halo: var(--accent-on-invert);
}

@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;
  }
}

/* ============================================================
   1. STRUCTURE — bands and rails
   ============================================================ */

.band {
  position: relative;
  background: var(--band-bg, transparent);
  color: var(--band-fg, inherit);
}

/* The wrap carries the vertical rhythm so the rails run through it
   unbroken. The rails sit at --gutter; the content is held a further
   --pad inside them, so type keeps clear of the lines on both sides. */
.wrap {
  position: relative;
  max-width: calc(var(--container) + var(--gutter) * 2);
  margin-inline: auto;
  padding: var(--band-y) calc(var(--gutter) + var(--pad));
}

.wrap--flush { padding-block: 0; }

/* The rails. Drawn per band so the colour always suits the
   ground it crosses; continuous because bands never gap. */
.wrap::before,
.wrap::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--hair);
  background: var(--rail, transparent);
  pointer-events: none;
}
.wrap::before { left: var(--gutter); }
.wrap::after  { right: var(--gutter); }

/* Semantic grounds. Every ground on the page is one of these, so the
   whole thing is carried by the token layer — swap the palette in
   tokens.css and the page follows, with nothing to edit here. */
.band--base   { --band-bg: var(--ground);   --band-fg: var(--on-ground); --rail: var(--ground-rail); }
.band--raised { --band-bg: var(--ground-2); --band-fg: var(--on-ground); --rail: var(--ground-rail); }
.band--invert { --band-bg: var(--invert);   --band-fg: var(--on-invert); --rail: var(--invert-rail); }

/* The one fixed ground, which stays put while the page flips around it:
   navy, for the closing call to action. It pins the inverted inks as
   well, so shared components written against --on-invert still read on
   it in either mode. Lime is an accent on this page — buttons, pennant,
   ticks, selection — never a ground of its own. */
.band--navy  { --band-bg: var(--navy);       --band-fg: var(--text-on-dark);--rail: var(--navy-3);
               --on-invert: var(--text-on-dark);
               --on-invert-muted: rgba(236, 238, 248, 0.66);
               --invert-rail: var(--navy-3);
               --accent-on-invert: var(--lime); }

/* ============================================================
   2. TYPE
   ============================================================ */

.display {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: 0.92;
  letter-spacing: -0.01em;
  margin: 0;
}

.label {
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  line-height: 1;
}

.mono { font-family: var(--font-mono); }

.lede {
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.6;
  max-width: 34em;
  margin: 0;
}

/* ============================================================
   3. COMPONENTS (ported from the sketch's design system)
   ============================================================ */

.pennant {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 7px 22px 12px;
  background: var(--lime);
  color: var(--lime-ink);
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
  clip-path: var(--pennant);
}
.pennant--ink   { background: var(--ink);  color: var(--lime); }

.badge {
  display: inline-flex;
  align-items: center;
  padding: 5px 11px;
  border-radius: var(--r-pill);
  background: var(--lime);
  color: var(--lime-ink);
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
}
.badge--navy  { background: var(--navy); color: var(--text-on-dark); }
/* A benefit the club has decided on but not started yet. It carries no
   fill — the lime badge is for things you get today, and a pending one
   that borrowed it would read as the loudest item on the list. */
.badge--soon {
  background: none;
  color: inherit;
  border: var(--hair) solid currentColor;
  opacity: 0.6;
  padding: 4px 9px;
  vertical-align: 0.15em;
}

/* ---------- pending benefits ----------
   Struck through and tagged, never hidden: the club wants members to
   see what is coming. The line is decoration only — every pending item
   also carries the word, because a line-through is not announced by a
   screen reader and reads as a discount rather than as "not yet". */
.is-soon > .tick { background: none; border: var(--hair) solid currentColor; color: inherit; opacity: 0.5; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  height: var(--control-md);
  padding-inline: 22px;
  border: var(--rule) solid transparent;
  border-radius: var(--r-sm);
  background: var(--lime);
  color: var(--lime-ink);
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: var(--tracking-btn);
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease), transform 120ms var(--ease);
}
.btn:hover  { background: var(--lime-bright); }
.btn:active { transform: translateY(1px); }

.btn--sm { height: var(--control-sm); padding-inline: 16px; font-size: 12.5px; }
.btn--lg { height: var(--control-lg); padding-inline: 30px; font-size: 16px; }
.btn--pill  { border-radius: var(--r-pill); }
.btn--block { display: flex; width: 100%; }

.btn--outline {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}
.btn--outline:hover { background: var(--ink); color: var(--lime); }

.btn--dark {
  background: var(--navy);
  color: var(--text-on-dark);
  border-color: var(--navy);
}
.btn--dark:hover { background: var(--navy-2); border-color: var(--navy-2); }

/* Outline button on the page ground, whichever mode that is. */
.btn--onGround {
  background: transparent;
  color: var(--on-ground-strong);
  border-color: var(--on-ground-strong);
}
.btn--onGround:hover {
  background: var(--on-ground-strong);
  color: var(--ground);
  border-color: var(--on-ground-strong);
}

.btn[disabled] { opacity: 0.45; cursor: not-allowed; }

/* The club line — a seam between two bands, not a strip of its own.
   It was a marquee: display type on a lime ground, scrolling on a 34s
   loop. Three things at once said advertisement — the motion, the full
   sheet of accent, and type at headline weight — so all three go. What
   is left is a dateline: one static line, small, tracked out, in the
   muted ink, held between two hairlines. */
.clubline {
  border-block: var(--hair) solid var(--rail);
}
.clubline__t {
  margin: 0;
  padding-block: 13px;
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--on-ground-muted);
  text-align: center;
}

/* ---------- the poster headline ----------
   One headline line per row: the word at its natural width, then a
   rule that runs on to the right rail. The words are never stretched
   or tracked, yet every line measures the full page — so the lines
   stack into one solid block locked to both edges instead of reading
   as ragged type. The ball rests on the last rule rather than
   floating loose in a corner.

   Only the mechanics live here; v-tavla.css supplies the colour and
   scale that make the block read as a scoreboard headline on the
   theme-following ground. */

.posterhead {
  display: flex;
  flex-direction: column;
}
.posterline {
  display: flex;
  align-items: flex-end;
  gap: 0.26em;
  line-height: 0.9;
}
.posterline b { font-weight: inherit; }
.posterline__run {
  flex: 1;
  height: 0.055em;
  min-width: 0.5em;
  margin-bottom: 0.2em;
  background: currentColor;
  opacity: 0.32;
}
.posterline__ball {
  flex: none;
  display: block;
  margin-bottom: -0.02em;
}
.posterline__ball .ball {
  width: 0.58em;
  height: auto;
}

/* ============================================================
   4. SITE HEADER
   ============================================================ */

.siteheader {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--band-bg);
  color: var(--band-fg);
  border-bottom: var(--hair) solid var(--rail);
}
.siteheader__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 72px;
}
/* width:auto matters for the <img> variant: the tag carries a width
   attribute, so height alone leaves it at its intrinsic 1030px. The
   .logomark span gets its width from aspect-ratio instead. */
.siteheader__logo img { height: 46px; width: auto; }
.siteheader__logo .logomark { height: 46px; }

/* The club mark as a themed background. Only the variant the current
   palette selects is ever fetched, so this costs one request, not two. */
/* Cream on the page's dark ground, black on the inverted paper of the
   offer card. Only the variant actually in use is ever fetched. */
.logomark {
  display: block;
  aspect-ratio: 1030 / 672;
  height: 46px;
  background: url(../img/logo-cream.png) left center / contain no-repeat;
}
.logomark--invert { background-image: url(../img/logo-black.png); }
.siteheader__spacer { flex: 1; }

.sitenav {
  display: none;
  align-items: center;
  gap: clamp(16px, 2vw, 28px);
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.sitenav a { padding-block: 4px; border-bottom: var(--rule) solid transparent; }
.sitenav a:hover { border-bottom-color: var(--lime); }

.siteheader__actions { display: flex; align-items: center; gap: var(--sp-2); }

.navtoggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: var(--hair) solid var(--rail);
  border-radius: var(--r-sm);
  background: transparent;
  cursor: pointer;
}
.navtoggle svg { width: 20px; height: 20px; }

.mobilenav { display: none; border-top: var(--hair) solid var(--rail); }
.mobilenav.is-open { display: block; }
.mobilenav a {
  display: block;
  padding: 15px calc(var(--gutter) + var(--pad));
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-bottom: var(--hair) solid var(--rail);
}
.mobilenav a:last-child { border-bottom: 0; }

@media (min-width: 900px) {
  .sitenav { display: flex; }
  .navtoggle { display: none; }
  .mobilenav { display: none !important; }
  .siteheader__logo img { height: 54px; width: auto; }
  .siteheader__logo .logomark { height: 54px; }
}

/* Words that only the screen reader needs — a link whose purpose the
   sighted reader takes from an icon or from the column it sits in.
   Clipped rather than display:none, which would take it out of the
   accessibility tree along with the layout. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Skip link. Clipped rather than parked at left:-9999px, which
   counts as document overflow and drags the scroll origin. */
.skip {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  z-index: 300;
}
.skip:focus {
  width: auto;
  height: auto;
  overflow: visible;
  clip-path: none;
  left: var(--gutter);
  top: 60px;
  padding: 10px 16px;
  background: var(--lime);
  color: var(--lime-ink);
  font-family: var(--font-label);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ============================================================
   5. SHARED SECTION FURNITURE
   ============================================================ */

/* Section head. Always hard against the left rail so every
   section starts on the same line. */
.sechead {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-4);
  padding-bottom: var(--sp-6);
  margin-bottom: var(--sp-6);
  border-bottom: var(--hair) solid var(--rail);
}
.sechead__h {
  font-size: clamp(32px, 5vw, 58px);
  color: var(--band-fg);
}
.sechead--dark .sechead__h { color: var(--text-on-dark); }

/* When the section below draws its own top rule (a table), the
   heading drops its rule so the two don't stack up as a pair of
   parallel lines. */
.sechead--flush {
  padding-bottom: 0;
  border-bottom: 0;
}

.events__more {
  display: flex;
  justify-content: center;
  margin-top: var(--sp-7);
}

.tick {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--lime);
  color: var(--lime-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  margin-top: 2px;
}

.hide-sm { display: none; }
@media (min-width: 900px) { .hide-sm { display: inline-flex; } }

/* ============================================================
   6. FOOTER
   ============================================================ */

.sitefooter__grid {
  display: grid;
  gap: var(--sp-7);
  grid-template-columns: 1fr;
}
.sitefooter__brand img { height: 66px; width: auto; }
.sitefooter__brand .logomark { height: 66px; }
.sitefooter__brand p {
  margin: var(--sp-4) 0 0;
  max-width: 26em;
  font-size: 15px;
  color: var(--on-ground-muted);
}
.sitefooter__h {
  font-size: 24px;
  color: var(--on-ground);
  margin-bottom: var(--sp-4);
}
.sitefooter__lbl {
  margin: var(--sp-4) 0 4px;
  color: var(--on-ground-muted);
  font-size: 11px;
}
.sitefooter__lbl:first-of-type { margin-top: 0; }
.sitefooter__val {
  margin: 0;
  font-weight: 600;
  font-size: 17px;
  color: var(--on-ground);
}
.sitefooter__note {
  margin: 2px 0 0;
  font-size: 14px;
  color: var(--on-ground-muted);
}
.sitefooter__mail {
  font-weight: 700;
  font-size: 16px;
  color: var(--accent-on-ground);
  border-bottom: var(--hair) solid currentColor;
  /* 25px tall as an inline link was the one sub-44px touch target;
     pad it out without moving the baseline. */
  display: inline-block;
  padding-block: 10px;
}
.sitefooter__shot { display: none; }
.sitefooter__shot .photo { aspect-ratio: 4 / 3; }

.sitefooter__cta {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  align-self: start;
}
.sitefooter__legal {
  margin: var(--sp-7) 0 0;
  padding-top: var(--sp-5);
  border-top: var(--hair) solid var(--rail);
  font-size: 12.5px;
  color: var(--on-ground-muted);
}

@media (min-width: 760px) {
  .sitefooter__grid { grid-template-columns: 1.4fr 1fr; }
}
@media (min-width: 1040px) {
  .sitefooter__grid { grid-template-columns: 1.4fr 1fr 200px 220px; }
  .sitefooter__shot { display: block; }
}

/* ============================================================
   7. PHOTOGRAPHY
   Real images fill their slot and are cropped by it. Until the
   club supplies one, the slot renders as a labelled placeholder
   carrying the shot brief — visible, on-brand, and impossible to
   mistake for finished work.
   ============================================================ */

.photo {
  margin: 0;
  position: relative;
  overflow: hidden;
  /* Theme-aware: this is what shows while the image is still loading,
     and a fixed light grey here flashed as a bright block on a dark
     page — worst at the foot, where two slots sit close together. */
  background: var(--ground-2);
}
.photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Slots crop hard — a 4:3 frame into a 21:8 band throws away most of
     the height — so a slot can say which part of the frame to keep
     rather than accepting the centre and losing the subject. */
  object-position: var(--photo-pos, 50% 50%);
  display: block;
}

.photo--empty {
  aspect-ratio: var(--photo-ar, 16 / 10);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 6px;
  padding: var(--sp-5);
  background: transparent;
  /* A hatched field, so the slot reads as "nothing here yet" rather
     than as a grey box someone forgot to style. */
  background-image: repeating-linear-gradient(
    -45deg,
    var(--ph-line) 0 1px,
    transparent 1px 9px
  );
  border: var(--hair) solid var(--ph-line);
}
.photo--dark  { --ph-line: rgba(236, 238, 248, 0.22); --ph-ink: rgba(236, 238, 248, 0.85); }
.photo--light { --ph-line: rgba(22, 22, 15, 0.18);    --ph-ink: rgba(22, 22, 15, 0.75); }
.photo--theme  { --ph-line: var(--ground-rail); --ph-ink: var(--on-ground-muted); }
/* For slots sitting on the inverted material, e.g. the footer. */
.photo--invert { --ph-line: var(--invert-rail); --ph-ink: var(--on-invert); }

.photo__slot {
  color: var(--lime);
  background: var(--navy-deep);
  padding: 5px 10px;
}
.photo--light .photo__slot { background: var(--ink); }
.photo__brief {
  color: var(--ph-ink);
  font-size: 14px;
  line-height: 1.4;
  max-width: 30ch;
}
.photo__spec {
  color: var(--ph-ink);
  opacity: 0.6;
  font-size: 11.5px;
}
