/* ==========================================================================
   Bootcamp SE16 — base.css
   Design tokens, reset, typography and every shared component.
   Every page loads this first. Page sheets add layout only, never tokens.

   Palette rule (brief §4): black, white, one red, plus neutral greys.
   The red is rationed to primary CTAs and the disc. If a section feels flat,
   add space or scale before adding colour.
   ========================================================================== */

/* --- Fonts. Self-hosted, four weights, latin subset. No CDN calls. --------
   Big Shoulders Display carries the headlines: condensed, civic, closer to
   park signage than to a gym logo. Archivo does everything a person reads at
   length, because a condensed face at 15px is a chore. */
@font-face {
  font-family: "Big Shoulders";
  src: url("/fonts/BigShoulders-900.woff2") format("woff2");
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("/fonts/Archivo-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("/fonts/Archivo-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("/fonts/Archivo-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Brand */
  --red: #dd3333;         /* CTAs, the disc, the band. Never decoration */
  --red-bright: #e8402f;  /* red on dark grounds only */
  --red-deep: #c22a2a;    /* small text on the light ground: #dd3333 is 4.2:1 there */
  --ink: #111110;
  --white: #ffffff;

  /* Neutral ramp */
  --grey-900: #1a1a18;
  --grey-800: #2e2c27;
  --grey-600: #55534b;
  --grey-400: #8a867c;
  --grey-200: #dedbd2;
  --grey-100: #efece4;
  --grey-50: #fffefb;

  /* Semantic aliases. Components use these, not the raw ramp. */
  --text-heading: var(--ink);
  --text-body: var(--grey-800);
  --text-muted: var(--grey-600);   /* lightest colour permitted for copy */
  --surface: #f7f6f2;              /* warm off-white, the page ground */
  --surface-card: var(--grey-50);  /* cards sit slightly lighter than the page */
  --surface-tint: var(--grey-100);
  --surface-dark: var(--grey-900);
  --border: var(--grey-200);
  --whatsapp: #25d366;

  /* Type families */
  --font-heading: "Big Shoulders", "Archivo Narrow", Impact, system-ui, sans-serif;
  --font-body: "Archivo", system-ui, -apple-system, "Helvetica Neue", sans-serif;

  /* Type scale. rem-based, so it steps up with the root size below. */
  --text-xs: 0.7rem;      /* eyebrow labels, the red band, captions. One size, not four */
  --text-sm: 0.882rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.294rem;
  --text-2xl: clamp(1.4rem, 1.2rem + 1vw, 1.65rem);
  --text-3xl: clamp(2.1rem, 1.4rem + 3vw, 3.6rem);
  --text-4xl: clamp(2.4rem, 1.5rem + 4vw, 4.4rem);
  --text-display: clamp(1.95rem, 1rem + 4.6vw, 5.4rem);
  --text-figure: clamp(3.2rem, 2rem + 6vw, 6rem);   /* facts set as type */

  /* Spacing, 4px base */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;

  /* Radius as hierarchy: one for interactive, one for containers, one full */
  --radius-btn: 12px;
  --radius-card: 16px;
  --radius-full: 999px;

  /* Quiet elevation: hairlines first, shadows barely there */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 6px 20px rgba(0, 0, 0, 0.07);
  --hairline: 1px solid var(--border);

  --transition: 180ms ease;
  --container: 1140px;
  --header-h: 72px;
  --stickybar-h: 76px;
}

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

* { margin: 0; }

html {
  font-size: 106.25%;            /* 17px base — this audience skews 28-65 */
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (min-width: 768px) {
  html { font-size: 112.5%; }    /* 18px */
}

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

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 400;
  line-height: 1.65;
  color: var(--text-body);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
}

img, picture, svg, video {
  display: block;
  max-width: 100%;
  height: auto;
}

input, button, textarea, select { font: inherit; color: inherit; }

/* --- Typography ---------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--font-heading);
  color: var(--text-heading);
  text-wrap: balance;
}

h1 {
  font-size: var(--text-4xl);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.035em;
}

h2 {
  font-size: var(--text-3xl);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.028em;
}

h3 {
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

h4 {
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

p { text-wrap: pretty; }
p + p { margin-top: var(--space-4); }

.lead {
  font-size: var(--text-lg);
  color: var(--text-body);
}

/* Body links are ink and underlined. Red is for CTAs, not inline text. */
a { color: inherit; }

.prose a,
p a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--transition);
}

.prose a:hover,
p a:hover { color: var(--red-deep); }

:where(a, button, summary, input, textarea, select):focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Session times and prices must line up in columns, never jitter */
.tabular { font-variant-numeric: tabular-nums; }

/* --- Layout -------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-6);
}

.container-narrow {
  width: 100%;
  max-width: 720px;
  margin-inline: auto;
  padding-inline: var(--space-6);
}

.section { padding-block: clamp(3.5rem, 8vw, 6rem); }
.section-sm { padding-block: clamp(2.5rem, 5vw, 3.5rem); }
.section-tint { background: var(--surface-tint); }

.section-dark {
  background: var(--surface-dark);
  color: var(--grey-200);
}

.section-dark h1,
.section-dark h2,
.section-dark h3,
.section-dark h4 { color: var(--white); }

.section-dark .prose a,
.section-dark p a { color: var(--white); }
.section-dark .prose a:hover { color: var(--red-bright); }

.section-head {
  max-width: 44rem;
  margin-bottom: var(--space-10);
}

.section-head p {
  margin-top: var(--space-3);
  font-size: var(--text-lg);
  color: var(--text-muted);
}

.section-dark .section-head p { color: var(--grey-400); }

.grid { display: grid; gap: var(--space-6); }

@media (min-width: 640px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 900px) {
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
  .grid-4 { grid-template-columns: repeat(4, 1fr); }
  .grid-2\@lg { grid-template-columns: repeat(2, 1fr); }
}

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

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--space-4);
  z-index: 1000;
  padding: var(--space-3) var(--space-4);
  background: var(--ink);
  color: var(--white);
  border-radius: var(--radius-btn);
  text-decoration: none;
}

.skip-link:focus { top: var(--space-3); }

/* --- Buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 48px;               /* tap target */
  padding: var(--space-3) var(--space-6);
  font-family: var(--font-heading);
  font-size: var(--text-base);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: var(--radius-btn);
  cursor: pointer;
  transition: background var(--transition), color var(--transition),
    border-color var(--transition), transform var(--transition);
}

.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--red);
  color: var(--white);
  border-color: var(--red);
}

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

.btn-secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}

.btn-secondary:hover {
  background: var(--ink);
  color: var(--white);
}

.btn-ghost-dark {
  background: transparent;
  color: var(--white);
  border-color: rgba(255, 255, 255, 0.5);
}

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

/* Ink on the WhatsApp green, not white. White on #25D366 is a 1.98:1
   contrast ratio, which fails AA badly and is genuinely hard to read for an
   audience that skews older. Ink on the same green is 10.6:1 and the button
   is still unmistakably WhatsApp. */
.btn-whatsapp {
  background: var(--whatsapp);
  color: var(--ink);
  border-color: var(--whatsapp);
}

.btn-whatsapp:hover { filter: brightness(0.93); }

.btn-lg {
  min-height: 56px;
  padding: var(--space-4) var(--space-8);
  font-size: var(--text-lg);
}

.btn-icon { width: 1.15em; height: 1.15em; flex: none; fill: currentColor; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* --- Header -------------------------------------------------------------- */
.header {
  position: sticky;
  top: 0;
  z-index: 900;
  background: var(--white);
  border-bottom: var(--hairline);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  min-height: var(--header-h);
}

.logo { flex: none; display: block; }
.logo img { height: 44px; width: auto; }

.nav {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  margin-left: auto;
}

.nav-link {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  padding-block: var(--space-2);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  transition: border-color var(--transition), color var(--transition);
}

.nav-link:hover { color: var(--red-deep); }

.nav-link[aria-current="page"] { border-bottom-color: var(--red); }

.header .btn { flex: none; }

/* The nav panel carries its own CTA for the mobile layout. Above the
   breakpoint the header's own CTA is the one on show. */
@media (min-width: 901px) {
  .nav > .btn { display: none; }
}

.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 48px;
  height: 48px;
  margin-left: auto;
  padding: 0 12px;
  background: none;
  border: 0;
  cursor: pointer;
}

.menu-toggle span {
  display: block;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform var(--transition), opacity var(--transition);
}

.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 900px) {
  .menu-toggle { display: flex; }

  .nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin: 0;
    padding: var(--space-2) var(--space-6) var(--space-6);
    background: var(--white);
    border-bottom: var(--hairline);
    box-shadow: var(--shadow-md);
    display: none;
  }

  .nav[data-open="true"] { display: flex; }

  .nav-link {
    padding-block: var(--space-4);
    font-size: var(--text-base);
    border-bottom: var(--hairline);
  }

  .nav-link[aria-current="page"] {
    border-bottom-color: var(--border);
    color: var(--red-deep);
  }

  .nav .btn { margin-top: var(--space-4); }

  /* The header CTA is duplicated inside the panel on mobile */
  .header > .container > .btn { display: none; }
}

/* --- Hero ---------------------------------------------------------------- */
.hero { position: relative; }

.hero-media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--grey-100);
}

.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-body { padding-block: var(--space-10) var(--space-8); }

.hero-body h1 { max-width: 18ch; }

.hero-body .lead {
  margin-top: var(--space-4);
  max-width: 52ch;
  color: var(--text-muted);
}

.hero-price {
  display: flex;
  flex-wrap: wrap;          /* never let the price itself be squeezed away */
  align-items: baseline;
  gap: var(--space-1) var(--space-2);
  margin-top: var(--space-6);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--text-xl);
  color: var(--ink);
}

.hero-price .amount {
  flex: none;
  font-size: var(--text-2xl);
  font-variant-numeric: tabular-nums;
}

.hero-body .btn-row { margin-top: var(--space-6); }

/* Overlay variant: text sits on the image from 900px up */
@media (min-width: 900px) {
  .hero-overlay { display: grid; }

  .hero-overlay > * { grid-area: 1 / 1; }

  .hero-overlay .hero-media { aspect-ratio: 21 / 9; }

  .hero-overlay .hero-media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(0, 0, 0, 0.72) 0%, rgba(0, 0, 0, 0.45) 45%, rgba(0, 0, 0, 0.1) 100%);
  }

  .hero-overlay .hero-body {
    position: relative;
    align-self: center;
    padding-block: var(--space-12);
    color: var(--grey-200);
  }

  .hero-overlay .hero-body h1 { color: var(--white); }
  .hero-overlay .hero-body .lead { color: var(--grey-200); }
  .hero-overlay .hero-price { color: var(--white); }
  .hero-overlay .hero-body > * { max-width: 34rem; }
}

/* --- Proof strip --------------------------------------------------------- */
.proof-strip {
  border-block: var(--hairline);
  background: var(--surface-tint);
}

.proof-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4) var(--space-8);
  padding-block: var(--space-4);
}

.proof-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-body);
}

.proof-item strong {
  font-family: var(--font-heading);
  font-weight: 800;
  color: var(--ink);
}

.stars {
  display: inline-flex;
  gap: 2px;
  color: var(--red);
  flex: none;
}

.stars svg { width: 1em; height: 1em; fill: currentColor; }

/* --- Cards --------------------------------------------------------------- */
.card {
  padding: var(--space-6);
  background: var(--white);
  border: var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition);
}

.card:hover { box-shadow: var(--shadow-md); }

.card h3 { margin-bottom: var(--space-2); }
.card p { color: var(--text-muted); }

.card-media {
  overflow: hidden;
  border-radius: var(--radius-card);
  background: var(--grey-100);
}

.card-media img { width: 100%; }

/* In a two-column grid the other column can outgrow the photo (a map under
   directions does). The photo keeps its own height instead of stretching
   into an empty grey box. */
.grid > .card-media { align-self: start; }

.section-dark .card {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: none;
}

.section-dark .card p { color: var(--grey-400); }

/* Numbered step cards */
.step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  margin-bottom: var(--space-4);
  font-family: var(--font-heading);
  font-weight: 800;
  color: var(--white);
  background: var(--red);
  border-radius: var(--radius-full);
}

/* --- Reviews ------------------------------------------------------------- */
.review-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6);
  background: var(--white);
  border: var(--hairline);
  border-radius: var(--radius-card);
}

.review-card blockquote {
  font-size: var(--text-lg);
  color: var(--text-body);
}

.review-meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: auto;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.review-meta cite {
  font-family: var(--font-heading);
  font-weight: 700;
  font-style: normal;
  color: var(--ink);
}

.pill {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--white);
  background: var(--red);
  border-radius: var(--radius-full);
  white-space: nowrap;
}

.pill-quiet {
  color: var(--text-muted);
  background: var(--grey-100);
  border: var(--hairline);
}

/* --- Photo band ---------------------------------------------------------- */
.photo-band {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 900px) {
  .photo-band { grid-template-columns: repeat(4, 1fr); }
}

.photo-band img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-card);
}

/* --- Venue card ---------------------------------------------------------- */
.venue-card {
  padding: var(--space-6);
  background: var(--white);
  border: var(--hairline);
  border-radius: var(--radius-card);
}

.venue-card h3 { margin-bottom: var(--space-1); }

.venue-card address {
  font-style: normal;
  color: var(--text-muted);
  margin-bottom: var(--space-4);
}

.venue-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* --- CTA band ------------------------------------------------------------ */
.cta-band { text-align: center; }

.cta-band .container-narrow > .btn-row {
  justify-content: center;
  margin-top: var(--space-8);
}

.cta-band p {
  margin-top: var(--space-4);
  font-size: var(--text-lg);
  color: var(--grey-400);
}

.cta-price {
  display: block;
  margin-top: var(--space-6);
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  font-weight: 800;
  color: var(--white);
  font-variant-numeric: tabular-nums;
}

/* --- Breadcrumbs --------------------------------------------------------- */
.breadcrumbs {
  padding-block: var(--space-4) 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
}

.breadcrumbs li + li::before {
  content: "/";
  margin-right: var(--space-2);
  color: var(--grey-400);
}

.breadcrumbs a {
  color: var(--text-muted);
  text-decoration: none;
}

.breadcrumbs a:hover { color: var(--ink); text-decoration: underline; }

.breadcrumbs [aria-current="page"] { color: var(--ink); font-weight: 600; }

/* --- FAQ. Native details, so it works with JS off and matches FAQPage. ---- */
.faq-list {
  display: grid;
  gap: var(--space-3);
  max-width: 48rem;
}

.faq {
  padding: var(--space-4) var(--space-6);
  background: var(--white);
  border: var(--hairline);
  border-radius: var(--radius-card);
}

.faq summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "";
  flex: none;
  width: 0.7em;
  height: 0.7em;
  margin-top: 0.35em;
  border-right: 2.5px solid var(--red);
  border-bottom: 2.5px solid var(--red);
  transform: rotate(45deg);
  transition: transform var(--transition);
}

.faq[open] summary::after { transform: rotate(-135deg); }

.faq > *:not(summary) { margin-top: var(--space-3); color: var(--text-muted); }

/* --- Comparison table ---------------------------------------------------- */
.table-wrap { overflow-x: auto; }

.compare {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-base);
}

.compare th,
.compare td {
  padding: var(--space-4);
  text-align: left;
  border-bottom: var(--hairline);
  vertical-align: top;
}

.compare thead th {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}

.compare tbody th {
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--text-muted);
}

/* --- Sticky mobile bar + WhatsApp float ---------------------------------- */
.sticky-bar { display: none; }

.whatsapp-fab {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 998;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  background: var(--whatsapp);
  color: var(--ink);          /* same contrast reason as .btn-whatsapp */
  border-radius: var(--radius-full);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
  transition: transform var(--transition);
}

.whatsapp-fab:hover { transform: scale(1.06); }
.whatsapp-fab svg { width: 32px; height: 32px; fill: currentColor; }

@media (max-width: 768px) {
  .whatsapp-fab { display: none; }

  .sticky-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 999;
    display: flex;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(10px);
    border-top: var(--hairline);
  }

  .sticky-bar .btn {
    flex: 1;
    min-height: 52px;
    padding-inline: var(--space-3);
  }

  /* Keep the bar from covering the last of the footer */
  .footer { padding-bottom: calc(var(--space-12) + var(--stickybar-h)); }
}

/* --- Footer -------------------------------------------------------------- */
.footer {
  padding-block: var(--space-16) var(--space-8);
  background: var(--surface-dark);
  color: var(--grey-400);
  font-size: var(--text-sm);
}

.footer-grid {
  display: grid;
  gap: var(--space-10);
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .footer-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1000px) {
  .footer-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; }
}

.footer h2,
.footer h3 {
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--white);
  margin-bottom: var(--space-4);
}

.footer-logo { height: 40px; width: auto; margin-bottom: var(--space-4); }

.footer ul { list-style: none; padding: 0; display: grid; gap: var(--space-2); }

.footer a { color: var(--grey-400); text-decoration: none; }
.footer a:hover { color: var(--white); text-decoration: underline; }

.footer address { font-style: normal; }

.footer-venue + .footer-venue { margin-top: var(--space-6); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  align-items: center;
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.footer-bottom ul { display: flex; flex-wrap: wrap; gap: var(--space-4); }

/* --- Forms (shared bones; form.css carries page layout) ------------------ */
.field { display: grid; gap: var(--space-2); margin-bottom: var(--space-5); }

.field label {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--ink);
}

.field input,
.field textarea,
.field select {
  width: 100%;
  min-height: 48px;
  padding: var(--space-3) var(--space-4);
  background: var(--white);
  border: 1.5px solid var(--grey-200);
  border-radius: var(--radius-btn);
  transition: border-color var(--transition);
}

.field input:focus,
.field textarea:focus { border-color: var(--ink); }

.field textarea { min-height: 120px; resize: vertical; }

.field-error {
  font-size: var(--text-sm);
  color: var(--red-deep);
  font-weight: 600;
}

.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] { border-color: var(--red); }

.radio-row { display: grid; gap: var(--space-3); }

@media (min-width: 520px) {
  .radio-row { grid-template-columns: repeat(2, 1fr); }
}

.radio-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1.5px solid var(--grey-200);
  border-radius: var(--radius-btn);
  cursor: pointer;
  transition: border-color var(--transition), background var(--transition);
}

.radio-card:has(input:checked) {
  border-color: var(--red);
  background: rgba(221, 51, 51, 0.04);
}

.radio-card input { width: 20px; height: 20px; min-height: 0; accent-color: var(--red); }

/* Honeypot. Must not be display:none — some bots skip hidden fields. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-note { font-size: var(--text-sm); color: var(--text-muted); }

.form-success,
.form-fallback {
  padding: var(--space-6);
  border-radius: var(--radius-card);
  border: var(--hairline);
}

.form-success { background: var(--grey-50); }

.form-fallback { background: #fff6f6; border-color: #f3c9c9; }

[hidden] { display: none !important; }

/* --- Consent banner (injected by analytics.js) --------------------------- */
.consent {
  position: fixed;
  left: var(--space-4);
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: 1100;
  max-width: 34rem;
  margin-inline: auto;
  padding: var(--space-5) var(--space-6);
  background: var(--white);
  border: var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.16);
  font-size: var(--text-sm);
}

@media (max-width: 768px) {
  .consent { bottom: calc(var(--stickybar-h) + var(--space-3)); }
}

.consent p { color: var(--text-muted); }

.consent .btn-row { margin-top: var(--space-4); }

.consent .btn { min-height: 44px; padding-inline: var(--space-5); }

/* ==========================================================================
   Club-noticeboard components
   Facts set as type, photographs shown undimmed, numbered rows instead of
   card grids. Added when the first build read as generic: competent, but
   every section was heading + lead + a row of identical boxes.
   ========================================================================== */

/* --- Split hero ----------------------------------------------------------
   The overlay hero darkened the members' faces, which is the one thing that
   persuades a nervous beginner. Here the photograph is never dimmed: type
   sits beside it, and the image runs to the right edge of the viewport. */
.hero-split { padding-block: var(--space-8) 0; }

.hero-split .hero-body { padding-block: 0 var(--space-10); }

.hero-split h1 {
  font-size: var(--text-display);
  max-width: 19ch;
}

.hero-split .lead {
  margin-top: var(--space-6);
  max-width: 46ch;
  font-size: var(--text-lg);
  color: var(--text-muted);
}

.hero-split .btn-row { margin-top: var(--space-8); }

.hero-photo {
  margin-top: var(--space-8);
  background: var(--grey-100);
  overflow: hidden;
  border-radius: var(--radius-card);
}

.hero-photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

@media (min-width: 900px) {
  .hero-split > .container {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
    align-items: center;
    gap: clamp(2.5rem, 5vw, 4.5rem);
    max-width: none;
    padding-right: 0;
    padding-left: max(var(--space-6), calc((100vw - var(--container)) / 2));
  }

  .hero-split .hero-body { padding-block: var(--space-12); }

  .hero-photo {
    margin-top: 0;
    border-radius: var(--radius-card) 0 0 var(--radius-card);
  }

  .hero-photo img { aspect-ratio: 4 / 3.2; max-height: 38rem; }
}

/* --- The price, carried in the brand's own device -------------------------
   The red disc is the identity. Reusing it for the headline price is the one
   place a big red shape is not decoration. */
.disc-price {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 8.5rem;
  height: 8.5rem;
  padding: var(--space-2);
  background: var(--red);
  color: var(--white);
  border-radius: var(--radius-full);
  text-align: center;
  font-family: var(--font-heading);
  line-height: 1;
}

.disc-price .from {
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  /* No opacity here. Fading white on this red drops it to 3.65:1 and fails
     AA. Hierarchy comes from size and weight instead. */
}

.disc-price .amount {
  margin-block: 0.12em 0.08em;
  font-size: 2.6rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}

.disc-price .unit { font-size: var(--text-sm); font-weight: 600; }

.hero-price-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin-top: var(--space-8);
}

.hero-price-row p {
  max-width: 24ch;
  color: var(--text-muted);
  font-size: var(--text-base);
}

@media (min-width: 900px) {
  .proof-inner-split {
    display: grid;
    grid-template-columns: 1.1fr 0.9fr;
    gap: var(--space-12);
    align-items: end;
  }
}

/* --- Numbered rows, replacing identical card grids ------------------------
   Three equal bordered boxes is the template look. These are rules and
   numerals: unequal columns, no chrome, the index doing the structural work. */
.rows { border-top: var(--hairline); }

.row-item {
  display: grid;
  gap: var(--space-3) var(--space-8);
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
  border-bottom: var(--hairline);
}

@media (min-width: 800px) {
  .row-item {
    grid-template-columns: 4.5rem minmax(0, 15rem) minmax(0, 1fr);
    align-items: start;
  }
}

.row-index {
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  font-weight: 800;
  color: var(--red);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.row-item h3 {
  font-size: var(--text-xl);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.row-item p { color: var(--text-muted); max-width: 62ch; }

.section-dark .rows { border-top-color: rgba(255, 255, 255, 0.16); }
.section-dark .row-item { border-bottom-color: rgba(255, 255, 255, 0.16); }
.section-dark .row-index { color: var(--red-bright); }
.section-dark .row-item p { color: var(--grey-400); }

/* --- Section headings with a bit more presence --------------------------- */
.section-head-lg { max-width: 34rem; margin-bottom: var(--space-6); }

.section-head-lg h2 { font-size: var(--text-3xl); }

.section-head-lg + .section-sub {
  max-width: 58ch;
  margin-bottom: var(--space-10);
  font-size: var(--text-lg);
  color: var(--text-muted);
}

/* --- Asymmetric photo band -----------------------------------------------
   Four equal squares reads as a gallery widget. Unequal weights read as a
   composition. */
.photo-band-alt {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(2, 1fr);
}

.photo-band-alt img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-card);
}

.photo-band-alt figure { margin: 0; min-height: 0; }

@media (min-width: 900px) {
  .photo-band-alt {
    grid-template-columns: 1.6fr 1fr 1fr;
    grid-template-rows: repeat(2, minmax(0, 11rem));
  }
  .photo-band-alt figure:nth-child(1) { grid-row: span 2; }
  .photo-band-alt figure:nth-child(4) { grid-column: 2 / span 2; }
}

/* ==========================================================================
   Motion
   Energy without theatrics. Everything animates transform and opacity only,
   never layout properties, and the whole layer switches off under
   prefers-reduced-motion (handled by the global reset near the top, plus the
   explicit guards below for anything JS drives).
   ========================================================================== */

/* --- Scroll reveals -------------------------------------------------------
   Sections lift in as they arrive. JS adds .is-in; without JS everything is
   visible, because the base state is only applied once .js-motion is set. */
.js-motion .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 620ms cubic-bezier(0.16, 1, 0.3, 1),
              transform 620ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: opacity, transform;
}

.js-motion .reveal.is-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Children arrive just behind their parent, which reads as one movement
   rather than a dozen separate ones. */
.js-motion .reveal-group > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 560ms cubic-bezier(0.16, 1, 0.3, 1),
              transform 560ms cubic-bezier(0.16, 1, 0.3, 1);
}

.js-motion .reveal-group.is-in > * { opacity: 1; transform: none; }
.js-motion .reveal-group.is-in > *:nth-child(2) { transition-delay: 80ms; }
.js-motion .reveal-group.is-in > *:nth-child(3) { transition-delay: 160ms; }
.js-motion .reveal-group.is-in > *:nth-child(4) { transition-delay: 240ms; }
.js-motion .reveal-group.is-in > *:nth-child(5) { transition-delay: 320ms; }

/* --- Hero: a sequence, not a still ----------------------------------------
   Three real photographs cross-fading, with a very slow drift on whichever is
   showing. This is the closest thing to motion available until there is real
   footage to use. The first frame is the LCP element and is never delayed. */
.hero-photo { position: relative; }

.hero-photo .frame {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1100ms ease;
}

.hero-photo .frame img { width: 100%; height: 100%; object-fit: cover; }

.hero-photo .frame.is-on { opacity: 1; }

/* The first image sits in normal flow so it sizes the box and stays the LCP */
.hero-photo > img { position: relative; z-index: 0; }

.js-motion .hero-photo.is-cycling > img,
.js-motion .hero-photo .frame img { animation: drift 18s ease-in-out infinite alternate; }

@keyframes drift {
  from { transform: scale(1); }
  to   { transform: scale(1.055); }
}

/* --- The proof figures ----------------------------------------------------
   These do not count up. They emphasise on arrival instead: the number is the
   credibility, and a counter that ticks through "0.0 from 0 reviews" states
   something untrue, however briefly. */
.js-motion .proof-statement.reveal .fig {
  display: inline-block;
  transform: scale(0.9);
  opacity: 0;
  transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1) 120ms,
              opacity 500ms ease 120ms;
}

.js-motion .proof-statement.reveal.is-in .fig { transform: none; opacity: 1; }

/* --- Buttons: a bit of push ---------------------------------------------- */
.btn {
  transition: background-color var(--transition), color var(--transition),
              border-color var(--transition), transform 140ms ease;
}

.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn-primary .arrow {
  display: inline-block;
  margin-left: 0.45em;
  transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1);
}

.btn-primary:hover .arrow { transform: translateX(4px); }

/* --- Cards and rows lift on hover ---------------------------------------- */
.card {
  transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 220ms ease, border-color var(--transition);
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: var(--grey-400);
}

.row-item { transition: background-color var(--transition); }
.row-item .row-index { transition: transform 240ms cubic-bezier(0.16, 1, 0.3, 1); }
.row-item:hover .row-index { transform: translateX(5px); }

/* Photographs breathe slightly when pointed at */
.photo-band-alt figure { overflow: hidden; border-radius: var(--radius-card); }
.photo-band-alt img { transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1); }
.photo-band-alt figure:hover img { transform: scale(1.04); }

/* --- The one hard guard --------------------------------------------------
   Anything above that a user has asked not to see, stops here. */
@media (prefers-reduced-motion: reduce) {
  .js-motion .reveal,
  .js-motion .reveal-group > * { opacity: 1 !important; transform: none !important; }
  .js-motion .hero-photo > img,
  .js-motion .hero-photo .frame img { animation: none !important; }
  .hero-photo .frame { transition: none; }
  .btn:hover, .card:hover { transform: none; }
  .photo-band-alt figure:hover img { transform: none; }
}

/* ==========================================================================
   Signage treatment
   The design moved from a soft, rounded, white-page look to park-signage:
   condensed display capitals, square corners, hairlines, and one red band
   doing the shouting. Overrides sit here so the cascade settles last.
   ========================================================================== */

/* --- Headings -------------------------------------------------------------
   Big Shoulders ships at 900 only, so h1 and h2 take it and everything
   smaller stays on Archivo. A condensed face at 17px is a chore to read, and
   this audience is 28 to 65. */
h1, h2 {
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.005em;      /* condensed faces need air, not tightening */
}

h1 { line-height: 0.86; }
h2 { line-height: 0.9; }

h3, h4 {
  font-family: var(--font-body);
  font-weight: 700;
  letter-spacing: -0.01em;
  text-transform: none;
}

h3 { font-size: var(--text-xl); line-height: 1.3; }

/* Article titles stay sentence case on the body face. A long post title in
   condensed capitals is a wall. */
.post-head h1,
.post-body h2,
.post-body h3 {
  font-family: var(--font-body);
  font-weight: 700;
  text-transform: none;
  letter-spacing: -0.02em;
  line-height: 1.12;
}

.post-head h1 { font-size: clamp(2rem, 1.4rem + 2.4vw, 3rem); }
.post-body h2 { font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2rem); line-height: 1.2; }

/* --- Small caps label, used throughout ---------------------------------- */
.lbl,
.section-sub-label {
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--red-deep);
}

/* --- Buttons: square, uppercase, no nonsense ---------------------------- */
.btn {
  font-family: var(--font-body);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--text-sm);
  border-radius: 0;
}

.btn-lg { padding: 18px 30px; }

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

.btn-secondary {
  background: transparent;
  color: var(--ink);
  border: 1px solid #c9c5b8;
}

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

/* Ink is the quieter primary on a light ground */
.btn-ink { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.btn-ink:hover { background: #000; }

/* --- Cards and rows ------------------------------------------------------ */
.card {
  background: var(--surface-card);
  border: var(--hairline);
  border-radius: 0;
  box-shadow: none;
}

.card:hover { box-shadow: none; border-color: var(--grey-400); transform: none; }

.row-index {
  font-family: var(--font-heading);
  font-weight: 900;
  font-size: 2.6rem;
  color: var(--red);
  line-height: 1;
}

/* --- The red band --------------------------------------------------------
   The proof line used to be large figures on the page ground. It is now the
   one saturated element on the site, directly under the header, carrying the
   four facts a stranger needs before anything else. */
.proof-statement {
  background: var(--red);
  border: 0;
  padding-block: 0;
  color: var(--white);
}

.proof-inner-split,
.proof-statement .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;   /* four facts, one evenly spaced line */
  gap: var(--space-3) var(--space-6);
  padding-block: var(--space-5);
  grid-template-columns: none;
}

.proof-statement p {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  line-height: 1.4;
  color: var(--white);
  max-width: none;
  margin: 0;
}

.proof-statement .fig,
.proof-statement .fig-red {
  font-size: 1em;
  color: var(--white);
  font-weight: 700;
  letter-spacing: 0.08em;
}

.proof-statement .quiet {
  display: block;
  font-family: var(--font-body);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.92);
  max-width: 60ch;
  margin: 0;
}

/* --- Header on the light ground ----------------------------------------- */
.header { background: var(--surface); border-bottom: var(--hairline); }

.nav-link {
  font-weight: 600;
  font-size: var(--text-sm);
}

/* --- Dark sections ------------------------------------------------------- */
.section-dark { background: var(--grey-900); }
.section-dark .btn-secondary,
.section-dark .btn-ghost-dark { border-color: rgba(255, 255, 255, 0.4); color: var(--white); }
.section-dark .btn-secondary:hover,
.section-dark .btn-ghost-dark:hover { background: var(--white); border-color: var(--white); color: var(--ink); }

/* --- Photographs keep a hint of softness, nothing else does ------------- */
.hero-photo,
.card-media img,
.post-media img,
.photo-band-alt img { border-radius: 0; }

/* --- The wide hero -------------------------------------------------------
   A photograph the full width of the page, with the headline in a panel that
   overlaps its lower edge. The panel is what makes this safe: these are
   photographs of a group with faces edge to edge, so a scrim across the
   picture would dim the one thing that persuades anybody. The panel gives the
   type a guaranteed ground and every face stays lit. */
.hero-wide { padding: 0; }

.hero-frame {
  position: relative;
  width: 100%;
  height: clamp(15rem, 42vw, 32rem);
  overflow: hidden;
  background: var(--grey-900);
}

/* On a short laptop screen the full-height photo pushed the hero buttons
   below the fold (785px at 1280 x 720). Cap it by the viewport's height. */
@media (min-width: 900px) {
  .hero-frame { height: min(clamp(15rem, 42vw, 32rem), 52vh); }
}

.hero-frame > img,
.hero-frame .hero-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
}

/* Only the top strip is darkened, for the header. It stops well above
   anybody's face. */
.hero-frame::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 150px;
  background: linear-gradient(to bottom, rgba(10, 10, 10, 0.5), rgba(10, 10, 10, 0));
  pointer-events: none;
}

.hero-panel {
  position: relative;
  background: var(--surface);
  max-width: 54rem;
  margin-top: clamp(-7.5rem, -9vw, -3rem);
  padding: clamp(1.75rem, 3.5vw, 2.5rem) clamp(1.5rem, 3vw, 2.75rem) clamp(1.5rem, 3vw, 2.25rem);
  box-shadow: 0 -3px 0 var(--red);
}

/* The short, emotive homepage headline gets the full display size. The other
   pages carry longer, more descriptive H1s that need a calmer setting. */
.hero-panel h1 {
  font-size: var(--text-4xl);
  margin-top: var(--space-3);
  overflow-wrap: normal;       /* never break a headline mid-word */
  hyphens: none;
}

body.home .hero-panel h1 { font-size: var(--text-display); margin-top: 0; }

/* The homepage H1 opens with the category and place in label type, so the
   heading carries "outdoor bootcamp Canada Water" without changing the look. */
.hero-panel h1 .hero-kicker {
  display: block;
  line-height: 1.4;
  margin-bottom: var(--space-3);
}

.hero-panel .lead {
  color: var(--text-muted);
  max-width: 46ch;
  margin-top: var(--space-5);
}

.hero-panel .btn-row { margin-top: var(--space-6); }

@media (min-width: 900px) {
  .hero-panel-row {
    display: flex;
    align-items: flex-end;
    gap: var(--space-8);
    margin-top: var(--space-6);
  }
  .hero-panel-row .lead {
    margin-top: 0;
    flex: 1 1 auto;
    min-width: 22rem;      /* below this the row wraps instead of crushing it */
    max-width: 44ch;
  }
  .hero-panel-row .btn-row { margin-top: 0; flex: 0 0 auto; }
}

/* --- Hero slider ---------------------------------------------------------
   Three frames: the park, a session in progress, and winter. The header is
   the only place the site can say outdoors, coached and all year in pictures
   rather than words. Frames beyond the first are lazy and are only added
   once the page has loaded, so the first stays the LCP element. */
.hero-slide {
  opacity: 0;
  transition: opacity 900ms ease;
}

.hero-slide.is-on { opacity: 1; }

.hero-dots {
  position: absolute;
  right: clamp(1rem, 4vw, 3rem);
  bottom: clamp(5rem, 9vw, 7rem);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-3);
}

.hero-caption {
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--white);
  background: rgba(17, 17, 16, 0.5);
  padding: 6px 11px;
}

.hero-dots-row { display: flex; gap: 8px; }

.hero-dot {
  width: 38px;
  height: 4px;
  border: 0;
  padding: 0;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.42);
  transition: background-color 200ms ease;
}

.hero-dot[aria-current="true"] { background: var(--white); }
.hero-dot:hover { background: rgba(255, 255, 255, 0.75); }

.hero-pause {
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--white);
  background: rgba(17, 17, 16, 0.5);
  border: 0;
  padding: 6px 11px;
  cursor: pointer;
}
.hero-pause:hover { background: rgba(17, 17, 16, 0.75); }

@media (max-width: 620px) {
  /* The headline panel overlaps the bottom of the photo by about 3rem on a
     phone, so the dots must sit above that overlap or end up half behind it. */
  .hero-dots { bottom: auto; top: calc(100% - 5.25rem); }
  .hero-dots { flex-direction: row; align-items: center; }
  .hero-caption { display: none; }
}

/* Homepage only: the header sits on the photograph. Everywhere else it is a
   solid bar, because most pages have no image behind it. */
body.home .header {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 5;
  background: transparent;
  border-bottom: 0;
}

body.home .header .nav-link { color: var(--white); text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6); }
body.home .header .nav-link:hover { color: #ffd9d4; }
body.home .header .menu-toggle span { background: var(--white); }

/* The white links are for the photograph. Once the menu collapses into its
   white panel they need ink again, or they vanish (audit, 28 Sep 2026). */
@media (max-width: 900px) {
  body.home .header .nav-link { color: var(--ink); text-shadow: none; }
  body.home .header .nav-link:hover { color: var(--red-deep); }
  body.home .header .nav-link[aria-current="page"] { color: var(--red-deep); }
}

/* The logo is a black wordmark, so on the photograph it swaps for the
   reversed one the brand already has. */
body.home .header .logo img { content: url("/images/logo-bootcamp-se16-white.svg"); }

body.home main { padding-top: 0; }

/* Legal pages: a privacy policy does not need its section headings in
   condensed capitals at display size. Same calmer setting as article text. */
.prose-legal h2 {
  font-family: var(--font-body);
  font-weight: 700;
  text-transform: none;
  letter-spacing: -0.02em;
  line-height: 1.2;
  font-size: clamp(1.35rem, 1.1rem + 1vw, 1.7rem);
  margin-top: var(--space-8);
}

/* ==========================================================================
   Alignment pass
   One left edge for text, one measure for prose, one rhythm around headings.
   Measured on 29 Aug: hero text sat 42px right of the content beneath it, narrow
   prose centred at a different x from everything else, and the gap under a
   section heading ran from 0 to 87px depending on the page.
   ========================================================================== */

/* 1. The hero panel's text lands on the same left edge as everything below.
      The panel keeps its inset; it is the box that moves, not the words. */
.hero-panel {
  --panel-pad-x: clamp(1.5rem, 3vw, 2.75rem);
  padding-inline: var(--panel-pad-x);
  margin-left: calc(-1 * var(--panel-pad-x));
}

@media (max-width: 899px) {
  .hero-panel {
    --panel-pad-x: var(--space-6);
    margin-inline: calc(-1 * var(--space-6));
    max-width: none;
  }
}

/* The lead reads as a paragraph above the buttons, at every width. The
   side-by-side row squeezed it into a ragged column with buttons floating
   beside it. */
.hero-panel-row { display: block; }
.hero-panel .lead,
.hero-panel-row .lead { max-width: 44rem; margin-top: var(--space-5); }
.hero-panel-row .btn-row { margin-top: var(--space-6); }

/* 2. Narrow prose shares the container's left edge. Only articles keep the
      centred reading column, because there everything on the page is narrow. */
.container-narrow { max-width: var(--container); }
.container-narrow > * { max-width: 44rem; }
.post .container-narrow { max-width: 720px; }
.post .container-narrow > * { max-width: none; }
/* Where the content is centred, the capped blocks have to be centred too, or
   centred text sits in a 44rem box hugging the left edge (147px off centre at
   1440px on every call-to-action band until 25 Sep 2026). */
.cta-band .container-narrow > *,
.container-narrow.is-centred > * { margin-inline: auto; }
.container-narrow.is-centred { text-align: center; }

/* 3. Headings: one gap to whatever follows, and room for descenders on the
      tight display leading so a comma cannot touch the next line. */
.section-head h2,
.section-head-lg h2 { margin-bottom: var(--space-4); padding-bottom: 0.06em; }
.section-head p,
.section-head-lg + .section-sub { margin-top: 0; }
.section-head-lg { margin-bottom: 0; max-width: 42rem; }
.section-head-lg + .section-sub { margin-bottom: var(--space-10); }
.prose h2 { margin-top: var(--space-10); margin-bottom: var(--space-3); }
.prose h2:first-child { margin-top: 0; }

/* 4. Section headings a step smaller. At 65px a two-column heading was
      wrapping to five lines beside a photograph. */
:root { --text-3xl: clamp(1.9rem, 1.3rem + 2.4vw, 3rem); }

/* 5. The last thing in a section must not add to the section's own padding */
.section > .container > :last-child,
.section > .container-narrow > :last-child { margin-bottom: 0; }

/* 6. A bare heading followed by a paragraph still gets its gap. The two
      cross-promotion sections (SE16 pointing at BR2 and back) sit in a plain
      div that none of the heading rules reached. */
div:not([class]) > h2 + p { margin-top: var(--space-4); }

/* 7. A heading sharing a row with a photograph sits a step smaller. At full
      size a 530px column wrapped "Training in the middle of Canada Water" to
      five lines. */
.grid h2 { font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem); }

/* --- Click-to-load map ---------------------------------------------------
   A link to the Google listing that becomes the embedded map on click.
   Same box before and after, so nothing shifts when the map arrives. */
.map-embed {
  position: relative;
  aspect-ratio: 4 / 3;
  margin: var(--space-5) 0;
  background: var(--surface-tint);
  border: var(--hairline);
  overflow: hidden;
}
.map-embed > iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.map-embed-wide { aspect-ratio: 16 / 9; }


/* --- Classes hub (/services/): session name, then where it runs ------------ */
.service-sessions {
  list-style: none;
  padding: 0;
  margin: var(--space-6) 0 0;
  border-top: var(--hairline);
  max-width: 46rem;
}
.service-sessions li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  padding: var(--space-4) 0;
  border-bottom: var(--hairline);
}
.service-sessions strong {
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--text-heading);
}
.service-sessions span { color: var(--text-muted); }
.service-sessions li { scroll-margin-top: calc(var(--header-h) + var(--space-4)); }
.service-sessions .service-desc { flex-basis: 100%; margin: 0; max-width: 60ch; }
.service-more { margin-top: var(--space-5); color: var(--text-muted); }

/* --- Gaps the flow rules never covered --------------------------------------
   Only p + p gets a gap by default; every other pairing relies on the component
   setting its own. These are the pairings that were rendering at 0px. */
.prose > :is(ul, ol) + *,
.prose > h1 + * { margin-top: var(--space-4); }
.lbl + h1 { margin-top: var(--space-3); }
.section-sub + .btn-row { margin-top: var(--space-8); }



/* --- Member videos ----------------------------------------------------------
   The players are embedded directly and load lazily, as the maps do. Debbie's
   story leads because it is the before and after; the two shorter ones sit
   side by side underneath. */
.video-embed {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  background: var(--ink);
  overflow: hidden;
}

.video-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.video-feature {
  display: grid;
  gap: var(--space-6) var(--space-10);
  align-items: center;
  margin-bottom: var(--space-10);
}

@media (min-width: 900px) {
  .video-feature { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
}

.video-story h3 { margin-bottom: var(--space-3); }
.video-story p { color: var(--text-body); }
.video-story blockquote {
  margin: var(--space-5) 0 0;
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  line-height: 1.1;
  color: var(--ink);
}

.video-pair { margin-bottom: var(--space-12); }

.video-caption {
  margin-top: var(--space-3);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.video-caption strong { color: var(--ink); }

/* --- Before and after --------------------------------------------------------
   Each photo is a single image with the before on the left half and the after
   on the right, so each half gets a label, at the bottom because faces fill
   the top. Square frames with
   a centred crop keep the join in the middle whatever the source proportions. */
.before-after { margin-bottom: var(--space-12); }
.before-after-after-rows { margin: var(--space-12) 0 0; }
.before-after h3 { margin-bottom: var(--space-2); }
.before-after > p { color: var(--text-muted); margin-bottom: var(--space-6); max-width: 44rem; }

.ba-card { margin: 0; }

.ba-frame {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--grey-100);
}

.ba-frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ba-label {
  position: absolute;
  bottom: var(--space-3);
  left: var(--space-3);
  padding: 0.2rem 0.55rem;
  background: rgba(17, 17, 16, 0.82);
  color: var(--white);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.ba-after {
  left: calc(50% + var(--space-3));
  background: var(--red);
}

.ba-card figcaption {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink);
}

/* Trial page on a phone: the form sits under the explanation and a photo, so
   a button near the top jumps straight to it. Desktop has the form alongside. */
.jump-to-form { margin-top: var(--space-6); }
@media (min-width: 900px) { .jump-to-form { display: none; } }
#trial-form, #book { scroll-margin-top: calc(var(--header-h) + var(--space-4)); }


/* ==========================================================================
   Softer, 1 October 2026
   Steph asked for the site to feel softer after seeing mindsetstudio.co.uk:
   rounded buttons, corners and icons everywhere. The radius tokens above went
   from 0 to 12px (controls) and 16px (containers); this block overrides the
   places the square "signage" pass had forced to 0, and rounds the ones that
   never used a token.
   ========================================================================== */
.btn,
.card,
.post-body blockquote { border-radius: var(--radius-btn); }
.card { border-radius: var(--radius-card); }

.hero-photo,
.hero-photo img,
.card-media,
.card-media img,
.post-media img,
.photo-band-alt figure,
.photo-band-alt img,
.video-embed,
.ba-frame,
.map-embed,
.tt-booking,
.tt-footnote,
.venue-card,
.review-card,
.faq,
.form-panel { border-radius: var(--radius-card); }

.video-embed,
.ba-frame,
.map-embed { overflow: hidden; }

.hero-panel { border-radius: var(--radius-card); }
.lbl,
.hero-caption,
.hero-pause { border-radius: var(--radius-full); }
.hero-dot { border-radius: var(--radius-full); }

/* The mobile menu drops as a rounded sheet rather than a hard-edged slab */
@media (max-width: 900px) {
  .nav { border-radius: 0 0 var(--radius-card) var(--radius-card); }
}

/* Inputs and choices match the buttons */
.field input,
.field textarea,
.field select,
.radio-card { border-radius: var(--radius-btn); }

/* --- Headline highlights --------------------------------------------------
   One phrase per headline in red, the way Carrie's site colours "Real
   Results." Large type only: red on the cream ground is 4.3:1, fine at
   heading sizes, not for body text. */
.hl { color: var(--red); }
.section-dark .hl { color: var(--red-bright); }

/* The homepage headline arrives a phrase at a time. The words are in the HTML
   from the start; only their entrance is staged, and never for anyone who
   has asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  body.home .hero-panel h1 .h-line {
    display: inline-block;
    animation: h-rise 650ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }
  body.home .hero-panel h1 .h-line:nth-of-type(2) { animation-delay: 140ms; }
  body.home .hero-panel h1 .h-line:nth-of-type(3) { animation-delay: 300ms; }
}
@keyframes h-rise {
  from { opacity: 0; transform: translateY(0.35em); }
  to   { opacity: 1; transform: none; }
}
body.home .hero-panel h1 { font-size: clamp(2.2rem, 1rem + 4vw, 4.6rem); }
/* "Finally, something you stick at." reads as the line under the promise */
body.home .hero-panel h1 .h-sub {
  display: block;
  margin-top: 0.2em;
  font-size: 0.5em;
  line-height: 1.1;
  color: var(--ink);
}

/* A radio never shrinks when its label wraps */
.radio-card input { flex-shrink: 0; }

/* --- Results bar ----------------------------------------------------------
   Replaces the one-line red proof strip under the hero. Real figures only, and
   they do not count up from zero (see "The counting numbers were removed on
   purpose" in BUILD-NOTES). */
.results-bar {
  background: var(--red);
  color: var(--white);
}
.results-bar .container {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6) var(--space-4);
  padding-block: var(--space-8);
}
@media (min-width: 760px) {
  .results-bar .container { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.results-bar .result { text-align: center; margin: 0; }
.result-fig {
  display: block;
  font-family: var(--font-heading);
  font-weight: 900;
  font-size: clamp(2.4rem, 1.6rem + 3vw, 3.6rem);
  line-height: 1;
  color: var(--white);
}
.results-bar .result-fig { white-space: nowrap; }
.result-unit { font-size: 0.5em; text-transform: uppercase; letter-spacing: 0.04em; }

.result-label {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.92);
}

/* --- Quiz box -------------------------------------------------------------
   The highlighted invitation to the SE16 Starting Point. */
.quiz-box {
  display: grid;
  gap: var(--space-6);
  align-items: center;
  padding: clamp(1.75rem, 4vw, 3rem);
  background: var(--grey-900);
  color: var(--grey-400);
  border-radius: var(--radius-card);
  box-shadow: 0 18px 40px -18px rgba(221, 51, 51, 0.45);
}
@media (min-width: 900px) {
  .quiz-box { grid-template-columns: 1fr auto; gap: var(--space-10); }
}
.quiz-box h2 {
  color: var(--white);
  font-size: var(--text-3xl, clamp(1.8rem, 1.2rem + 2.4vw, 2.8rem));
  margin-top: var(--space-4);
}
.quiz-box h2 .hl { color: var(--red-bright); }
.quiz-box p { margin-top: var(--space-3); max-width: 52ch; }
.quiz-badge {
  display: inline-block;
  padding: 6px 14px;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--white);
  background: linear-gradient(90deg, var(--red), #f06b3c);
  border-radius: var(--radius-full);
}
.quiz-box .btn { white-space: nowrap; }
@media (max-width: 899px) {
  .quiz-box { text-align: center; }
  .quiz-box p { margin-inline: auto; }
  .quiz-box .btn { width: 100%; }
}

/* --- WhatsApp on phones ----------------------------------------------------
   The floating button now shows at every width, as on Carrie's site. On a
   phone it sits above the sticky bar, which carries Call and the trial. */
@media (max-width: 768px) {
  .whatsapp-fab {
    display: flex;
    right: var(--space-4);
    bottom: calc(var(--stickybar-h) + var(--space-3));
    width: 56px;
    height: 56px;
  }
}

/* A heading followed straight by a paragraph always gets a gap. The trial
   page's H1 and the form success panels sat flush against their text. Any
   component with its own spacing (class selectors) still wins. */
:where(main) :is(h1, h2) + p { margin-top: var(--space-4); }

/* When the quiz box follows a section on the same plain ground, the two
   paddings stacked into a 200px gap. Let the box sit closer. */
.section:not(.section-tint):not(.section-dark) + .section:has(> .container > .quiz-box) { padding-top: 0; }

/* Footer: a heading that follows a list or a venue block gets room above
   it. "Office hours" sat right under "Contact page" with no gap. */
.footer :is(ul, address, .footer-venue) + :is(h2, h3, .footer-venue) { margin-top: var(--space-8); }

/* Steph's hero copy (4 Oct 2026) is two lead paragraphs. Keep the buttons
   above the fold on a 1280 x 720 laptop: a wider panel so the strapline sits
   on one line, a tighter gap between the paragraphs, and a slightly shorter
   photo on short screens. Checked at 1280x720, 1440x900 and 1024x768. */
body.home .hero-panel { max-width: 66rem; }
body.home .hero-panel .lead + .lead { margin-top: var(--space-3); }
@media (min-width: 900px) {
  body.home .hero-frame { height: min(clamp(15rem, 42vw, 32rem), 46vh); }
}

/* --- Canada Water rewrite (5 Oct 2026) -----------------------------------
   Steph's copy runs several short paragraphs per numbered row, so the row's
   text column wraps them rather than each paragraph taking a grid cell. */
.row-body p + p { margin-top: var(--space-3); }

.hero-panel .lead + .lead { margin-top: var(--space-3); }
.hero-offer {
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.pull-quote {
  margin: 0 0 var(--space-10);
  max-width: 48rem;
}
.pull-quote p {
  font-family: var(--font-heading);
  font-size: clamp(1.4rem, 1rem + 1.6vw, 2.1rem);
  line-height: 1.2;
  color: var(--ink);
}
.pull-quote cite {
  display: block;
  margin-top: var(--space-3);
  font-style: normal;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.trial-card {
  padding: clamp(1.5rem, 4vw, 2.5rem);
  background: var(--surface-card);
  border: var(--hairline);
  border-radius: var(--radius-card);
}
.trial-price {
  font-family: var(--font-heading);
  font-weight: 900;
  font-size: clamp(3rem, 2rem + 4vw, 4.5rem);
  line-height: 1;
  color: var(--red);
  margin: var(--space-2) 0 var(--space-4);
}

/* Canada Water hero: Steph's two-paragraph intro is long, so a wider panel,
   a smaller second paragraph and a shorter photo keep the buttons in view on
   a 1280 x 800 laptop. */
.page-cw .hero-panel { max-width: 70rem; }
.page-cw .hero-panel .lead { max-width: none; }
.page-cw .hero-panel .lead + .lead { font-size: var(--text-base); }
@media (min-width: 900px) {
  .page-cw .hero-frame { height: min(clamp(15rem, 42vw, 32rem), 34vh); }
}
