/* ============================================================
   LESON AUDIO — Sound System Kit
   Design System v1.0 / 2026
   High-contrast, type-led system for a music production & DJ school
   ============================================================ */

/* ---------- 00 FONTS ----------
   Display: Hatsch Sans (uppercase-only grotesque, Mans Greback) — Regular only.
   Label:   Utah WGL Condensed (Light) — onlinewebfonts.com, CC BY 4.0. */
/* NOTE: the PERSONAL-USE build of Hatsch Sans replaces every numeral with a
   "PERSONAL USE ONLY / mn.sg/hatsch-sans" watermark glyph. unicode-range omits
   U+0030-0039 so digits fall through to Archivo instead. Once a commercial
   licence is bought, drop the unicode-range lines to use Hatsch's real numerals. */
@font-face {
  font-family: "Hatsch Sans";
  src: url("fonts/HatschSans.otf") format("opentype");
  font-weight: 400 900;     /* one file covers the range; heavier weights are synthesised */
  font-style: normal;
  font-display: swap;
  unicode-range: U+0-2F, U+3A-10FFFF;   /* everything except the digits 0-9 */
}
@font-face {
  font-family: "Hatsch Sans";
  src: url("fonts/HatschSans-Italic.otf") format("opentype");
  font-weight: 400 900;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0-2F, U+3A-10FFFF;
}
@font-face {
  font-family: "Utah WGL Condensed";
  src: url("fonts/UtahWGLCondensed-Light.ttf") format("truetype");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- 01 TOKENS ---------- */
:root {
  /* Colour */
  --c-ink:    #0a0a0a;
  --c-paper:  #f4f2ee;
  --c-panel:  #e7e5e1;
  --c-line:   #1f1f1f;
  --c-muted:  #f4f2ee;   /* was #7d7a73 — secondary text is now white */
  --c-rule:   #7d7a73;   /* the old grey, kept for borders/outlines only */
  --c-accent: #f4f2ee;
  /* Not in the original Sound System Kit — added for the announcement bar.
     Measured 4.73:1 against --c-paper text, clearing WCAG AA (4.5:1) for the
     bar's 13px copy. A brighter #e01b22 only reached 4.32:1 and failed. */
  --c-brand:  #2b5cff;   /* was red #d41a20; matched for contrast on both grounds */

  /* Spacing */
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 40px;
  --space-5: 64px;
  --space-6: 96px;

  /* Type families
     Display: Hatsch Sans (uppercase-only) — Archivo fallback while loading.
     Label:   Hatsch Sans too. Every label rule uppercases its text, so the
              missing lowercase is never hit (.player__time is digits only).
     Body:    Archivo — Hatsch is uppercase-only, so paragraphs stay in a neutral sans. */
  --font-display: "Hatsch Sans", "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-label:   "Hatsch Sans", "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-body:    "Archivo", "Helvetica Neue", Arial, sans-serif;
  /* Wordmark: the heaviest genuine Helvetica-family black available.
     macOS "Helvetica Neue" has NO Black cut — weights 600-900 all render as Bold —
     so Arial Black (Helvetica's metric-compatible twin) is the real black face here.
     Named Helvetica Blacks lead the stack for systems that do ship them. */
  --font-logo: "Helvetica Now Display Black", "Helvetica Neue Black", "HelveticaNeue-Black",
               "Helvetica Black", "Arial Black", "Archivo",
               "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Type scale */
  --t-display: clamp(54px, 11vw, 118px);
  --t-h1:      clamp(40px, 7.4vw, 74px);
  --t-h2:      clamp(24px, 3.4vw, 30px);
  --t-title:   17px;
  --t-body:    16px;

  --maxw: 1240px;
  --radius: 14px;
  /* Shared button shape — squared-off corners, centred labels.
     Every button uses this, so future buttons match by default. */
  --btn-radius: 6px;
  /* Hatsch's ascent sits well above its cap height, so an all-caps label
     lands ~2.8px low in a 28px button. Shift it up by half that, in em so
     it scales with any button size. Optical centring, not geometric. */
  --btn-cap-shift: 0.127em;

  /* "Liquid glass" rim: hairline inset highlights that read as a bevelled
     glass edge, plus a soft outer bloom. Two variants, because the rim only
     shows if it is drawn in the opposite value to the surface it sits on —
     white insets on the dark/transparent buttons, black on the paper-filled
     ones. The inner 0 0 6px 6px wash is halved from the source (which was
     sized for an 80px demo button); at our ~42px buttons the full value
     floods the whole face instead of vignetting the edge. */
  --glass-on-dark:
    0 0 8px rgba(0,0,0,0.03),
    0 2px 6px rgba(0,0,0,0.08),
    inset 3px 3px 0.5px -3.5px rgba(255,255,255,0.09),
    inset -3px -3px 0.5px -3.5px rgba(255,255,255,0.85),
    inset 1px 1px 1px -0.5px rgba(255,255,255,0.6),
    inset -1px -1px 1px -0.5px rgba(255,255,255,0.6),
    inset 0 0 3px 3px rgba(255,255,255,0.12),
    inset 0 0 2px 2px rgba(255,255,255,0.06),
    0 0 12px rgba(0,0,0,0.15);
  --glass-on-light:
    0 0 6px rgba(0,0,0,0.03),
    0 2px 6px rgba(0,0,0,0.08),
    inset 3px 3px 0.5px -3px rgba(0,0,0,0.9),
    inset -3px -3px 0.5px -3px rgba(0,0,0,0.85),
    inset 1px 1px 1px -0.5px rgba(0,0,0,0.6),
    inset -1px -1px 1px -0.5px rgba(0,0,0,0.6),
    inset 0 0 3px 3px rgba(0,0,0,0.12),
    inset 0 0 2px 2px rgba(0,0,0,0.06),
    0 0 12px rgba(255,255,255,0.15);

  /* Hero/header run near full-bleed — text sits close to the corners */
  --edge: clamp(20px, 1.75vw, 40px);
  --header-h: clamp(62px, 5vw, 100px);
}

/* ---------- RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  background: var(--c-ink);
  color: var(--c-paper);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.55;
  font-weight: 600;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
ul { list-style: none; }

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

/* ---------- LAYOUT ---------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--space-3);
}
.section { padding-block: var(--space-6); }
.section--tight { padding-block: var(--space-5); }

.eyebrow {
  font-family: var(--font-label);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  font-size: 12px;
  color: var(--c-muted);
}

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3);
  border-bottom: 1px solid var(--c-line);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-4);
}
.section-head h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--t-h2);
  text-transform: uppercase;
  letter-spacing: -0.01em;
  line-height: 1;
}
.section-head .eyebrow { margin-bottom: 10px; }

/* ---------- 04 COMPONENTS: CTA BUTTONS ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 10px;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 700;
  font-size: 13px;
  /* asymmetric vertical padding = optical centring for all-caps labels */
  padding: calc(14px - var(--btn-cap-shift)) 26px calc(14px + var(--btn-cap-shift));
  text-indent: 0.16em;   /* offsets the trailing letter-spacing after the last glyph */
  /* the glass rim draws the edge, so the border is only here to hold the
     box size steady — a visible 1px outline on top of it reads as two edges */
  border: 1px solid transparent;
  background: transparent;
  color: var(--c-paper);
  border-radius: var(--btn-radius);
  box-shadow: var(--glass-on-dark);
  transition: transform .18s ease, background .18s ease, color .18s ease,
              box-shadow .18s ease;
  white-space: nowrap;
}
/* the rim alone is enough on a flat section, but the hero ghost buttons sit on
   video that measures 41–163 luminance behind them with only a ~0.35 scrim —
   a hairline keeps the edge from dissolving on the bright frames */
.btn--ghost { border-color: rgba(244, 242, 238, .35); }
.btn--solid { background: var(--c-paper); color: var(--c-ink); box-shadow: var(--glass-on-light); }
/* each hover swaps the surface, so the rim has to swap value with it */
.btn--solid:hover {
  background: transparent; color: var(--c-paper);
  box-shadow: var(--glass-on-dark); transform: translateY(-2px);
}
.btn--ghost:hover {
  background: var(--c-paper); color: var(--c-ink);
  box-shadow: var(--glass-on-light); transform: translateY(-2px);
}

.link-arrow {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 700;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--c-paper);
  white-space: nowrap;   /* keeps the arrow on the label's line */
  transition: gap .18s ease, opacity .18s ease;
}
.link-arrow:hover { gap: 14px; opacity: .8; }

/* ---------- METADATA LABELS ---------- */
.tag {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-weight: 600;
  font-size: 11px;
  color: var(--c-muted);
  border: 1px solid var(--c-line);
  padding: 5px 11px;
  border-radius: 999px;
}
.tag--fill { background: var(--c-paper); color: var(--c-ink); border-color: var(--c-paper); }

/* ============================================================
   ANNOUNCEMENT BANNER
   ============================================================ */
.announce {
  background: var(--c-brand);
  color: var(--c-paper);
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 13px;
  font-weight: 500;
}
.announce__inner {
  position: relative;              /* anchors the close button */
  display: flex;
  align-items: center;
  justify-content: center;         /* badge + message sit centred in the bar */
  gap: var(--space-2);
  /* extra right room so long copy never runs under the ✕ */
  padding: 10px calc(var(--edge) + 28px);
  max-width: none;
}
.announce__new {
  background: var(--c-paper);
  color: var(--c-brand);
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 4px;
  letter-spacing: 0.14em;
  font-size: 11px;
}
.announce__msg { flex: 0 1 auto; text-align: center; }
.announce__msg a { text-decoration: underline; text-underline-offset: 3px; font-weight: 700; }
.announce__close {
  position: absolute; right: var(--edge); top: 50%;
  transform: translateY(-50%);
  background: none; border: none; color: var(--c-paper);
  font-size: 16px; line-height: 1; padding: 4px;
}
.announce.is-hidden { display: none; }

/* ============================================================
   HEADER / NAV
   ============================================================ */
/* Transparent over the hero video; .is-dark is toggled by script.js once the hero scrolls past */
.header {
  position: sticky; top: 0; z-index: 50;
  background: transparent;
  color: var(--c-paper);
  transition: background .25s ease, color .25s ease;
}
.header.is-dark {
  background: rgba(10,10,10,0.82);
  backdrop-filter: blur(10px);
  color: var(--c-paper);
  border-bottom: 1px solid var(--c-line);
}
.header__inner {
  display: flex; align-items: center; justify-content: space-between;
  height: var(--header-h);
  max-width: none;
  padding-inline: var(--edge);
}
.brand {
  display: inline-flex; align-items: center;
  font-family: var(--font-logo);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: -0.005em;
  font-size: clamp(20px, 1.95vw, 34px);
  white-space: nowrap;
}
.nav { display: flex; align-items: center; gap: var(--space-4); }
/* baseline (not center) so the Enroll label sits on the same line as the
   plain nav links — the button's padding+border make its box taller than theirs */
.nav__links { display: flex; align-items: baseline; gap: clamp(16px, 1.6vw, 34px); }
.nav__links a {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: clamp(11px, 0.8vw, 14px);
  font-weight: 700;
  color: var(--c-paper);
  transition: color .18s ease, opacity .18s ease;
}
.nav__links a:hover { opacity: .6; }
.header.is-dark .nav__links a { color: var(--c-muted); font-weight: 600; }
.header.is-dark .nav__links a:hover { color: var(--c-paper); opacity: 1; }
/* ---- ENROLL NOW: outlined pill with a dropdown (Camps / Classes) ---- */
.nav__enroll { position: relative; }
.enroll-btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: clamp(11px, 0.8vw, 14px);
  font-weight: 700;
  color: currentColor;
  background: transparent;             /* transparent fill */
  border: 1.5px solid currentColor;    /* black stroke on the light header */
  border-radius: var(--btn-radius);
  padding: calc(0.62em - var(--btn-cap-shift)) 1.15em calc(0.62em + var(--btn-cap-shift));
  line-height: 1;
  text-align: center;
  text-indent: 0.12em;   /* offsets the trailing letter-spacing after the last glyph */
  /* keeps the stroke this item was asked for, and carries the glass rim
     under it; the rim follows the fill, not the header */
  box-shadow: var(--glass-on-light);
  transition: background .18s ease, color .18s ease, box-shadow .18s ease;
}
.header.is-dark .enroll-btn { box-shadow: var(--glass-on-dark); }
.enroll-btn[aria-expanded="true"] { background: var(--c-ink); color: var(--c-paper); box-shadow: var(--glass-on-dark); }
.header.is-dark .enroll-btn[aria-expanded="true"] { background: var(--c-paper); color: var(--c-ink); box-shadow: var(--glass-on-light); }
@media (hover: hover) {
  .nav__enroll:hover .enroll-btn { background: var(--c-ink); color: var(--c-paper); box-shadow: var(--glass-on-dark); }
  .header.is-dark .nav__enroll:hover .enroll-btn { background: var(--c-paper); color: var(--c-ink); box-shadow: var(--glass-on-light); }
}

.enroll-menu {
  position: absolute; top: calc(100% + 8px); right: 0;
  /* Sizes to its longest label, never narrower than the button. Was
     width:100%, which fit "Camps" but wrapped "After School Programs" onto
     three ragged lines and made the panel look broken. */
  width: max-content;
  min-width: 100%;
  max-width: min(280px, calc(100vw - var(--edge) * 2));
  background: var(--c-paper);
  border: 1.5px solid var(--c-ink);
  border-radius: var(--btn-radius);
  padding: 0;
  overflow: hidden;     /* clips each row's hover fill to the rounded corners */
  display: flex; flex-direction: column;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
  box-shadow: 0 14px 34px rgba(0,0,0,.18);
  z-index: 60;
}
/* click-open via aria-expanded (JS); hover-open only where hover really exists.
   Deliberately no :focus-within — it would fight the click-to-close toggle. */
.enroll-btn[aria-expanded="true"] + .enroll-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
@media (hover: hover) {
  .nav__enroll:hover .enroll-menu { opacity: 1; visibility: visible; transform: translateY(0); }
}
/* keep the gap hoverable so the pointer can travel to the panel */
.enroll-menu::before { content: ""; position: absolute; left: 0; right: 0; top: -12px; height: 12px; }

/* Both selectors on purpose. `.header.is-dark .nav__links a` is (0,3,1) and
   paints links with --c-muted, which is now WHITE — so on every dark-header
   page it out-specified a (0,2,1) rule here and rendered the menu as white
   text on its own paper background. It looked like an empty box. */
.nav__links .enroll-menu a,
.header.is-dark .nav__links .enroll-menu a {
  display: block;
  color: var(--c-ink);
  font-size: clamp(11px, 0.8vw, 14px);
  font-weight: 700;
  letter-spacing: 0.12em;
  /* same box as .enroll-btn (incl. the transparent border) so each row is
     exactly the button's height */
  padding: calc(0.62em - var(--btn-cap-shift)) 1.15em calc(0.62em + var(--btn-cap-shift));
  border: 1.5px solid transparent;
  line-height: 1;
  text-align: center;   /* matches the centred button above it */
  text-indent: 0.12em;
  white-space: nowrap;  /* every row is exactly one line, like the button */
  opacity: 1;
}
.nav__links .enroll-menu a:hover,
.header.is-dark .nav__links .enroll-menu a:hover { background: var(--c-ink); color: var(--c-paper); opacity: 1; }

.nav__toggle { display: none; background: none; border: none; color: inherit; }
.nav__toggle span { display: block; width: 22px; height: 2px; background: currentColor; margin: 4px 0; }

/* ---- Nav collapses to the hamburger only on narrow screens ----
   The full link row is back at desktop width. Everything from here to the
   closing brace is inside the query on purpose: at >880px the links are a
   plain flex row (see .nav__links above) and the toggle stays hidden. */
@media (max-width: 880px) {
.nav__links { display: none; }
.nav__links.is-open {
  display: flex; flex-direction: column; gap: var(--space-2);
  align-items: stretch;
  position: absolute; top: var(--header-h); left: auto; right: 0;
  width: min(320px, calc(100vw - var(--edge) * 2));
  background: var(--c-ink);
  border: 1px solid var(--c-line); border-radius: 3px;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
  padding: var(--space-3);
  z-index: 60;
}
.nav__toggle { display: block; cursor: pointer; padding: 6px; }
.nav__toggle span:last-child { margin-bottom: 0; }
/* the panel is its own dark surface, so links keep paper colour in it */
.header .nav__links.is-open a { color: var(--c-paper); font-weight: 700; }
.header .nav__links.is-open a:hover { opacity: .6; }
/* the flyout sits inline inside the panel rather than floating */
.nav__enroll { position: static; }
.nav__links.is-open .enroll-btn { width: 100%; }
.nav__links.is-open .enroll-menu {
  position: static; min-width: 0; margin-top: 10px;
  box-shadow: none; transform: none;
  max-height: 0; padding-block: 0; overflow: hidden;
  transition: max-height .2s ease, opacity .2s ease;
}
.nav__links.is-open .enroll-btn[aria-expanded="true"] + .enroll-menu {
  max-height: 200px; transform: none;
}
}

/* ============================================================
   HERO
   ============================================================ */
.hero {
  position: relative;
  /* pulled up so the video runs behind the transparent header */
  margin-top: calc(-1 * var(--header-h));
  min-height: 94vh;           /* keeps the tagline above the fold */
  padding: 0;
  background: var(--c-ink);
  color: var(--c-paper);
  /* video fills the section; centre block takes the slack, copy sits at the
     bottom — column flow means the two can never overlap */
  display: flex;
  flex-direction: column;
}
/* hero background video */
/* full-bleed: fills the whole hero, no inset margin or rounding */
.hero__media {
  position: absolute; inset: 0;
  z-index: 0;
  overflow: hidden;            /* clips the scaled-up video (see below) */
  background: var(--c-ink);    /* shows while the video buffers */
}
/* scrims: bottom keeps the copy legible, top keeps the transparent
   header's white logo/nav legible over bright frames */
.hero__media::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to top,
      rgba(10,10,10,.78) 0%, rgba(10,10,10,.35) 26%, rgba(10,10,10,0) 58%),
    linear-gradient(to bottom,
      rgba(10,10,10,.55) 0%, rgba(10,10,10,.22) 10%, rgba(10,10,10,0) 24%),
    rgba(10,10,10,.42);   /* flat tint so the centred headline reads over any frame */
  pointer-events: none;
}

/* ---- centred hero block ---- */
.hero__center {
  position: relative; z-index: 2;
  flex: 1; min-height: 0;
  display: grid; place-items: center;
  padding: var(--space-5) var(--edge) var(--space-3);
  text-align: center;
}
/* px/vw, not ch — ch resolves against this element's 16px body font and would
   squeeze the 82px headline onto extra lines */
.hero__center-inner { max-width: min(760px, 90vw); }
.hero__headline {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(24px, 3.6vw, 54px);
  line-height: 0.96; letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--c-paper);
  text-wrap: balance;
}
.hero__sub {
  margin: var(--space-2) auto 0;
  /* px not ch — ch shrank with the smaller font and squeezed this to 3 lines */
  max-width: min(470px, 100%);
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.5;
  font-weight: 600;
  color: var(--c-paper);
}
.hero__actions {
  margin-top: var(--space-3);
  display: flex; flex-wrap: wrap; gap: var(--space-2);
  justify-content: center;
}
.hero__locations {
  margin-top: var(--space-3);
  display: flex; flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-4);
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-size: clamp(11px, 0.85vw, 13px);
  font-weight: 700;
  color: rgba(244,242,238,.85);
}
/* absolute so the video's intrinsic 1080px height can't stretch the hero and
   push the tagline below the fold — the band is sized purely by the flex row */
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;           /* fill the band, no letterboxing */
  display: block;
  /* The source had baked-in 150px pillarbox bars each side. They are now
     cropped out of the file itself (ffmpeg crop=1620:1080:150:0), so the old
     transform: scale(1.1852) workaround is gone — object-fit does the work. */
}
/* no controls anywhere, incl. the iOS/Safari overlay play button */
.hero__video::-webkit-media-controls,
.hero__video::-webkit-media-controls-start-playback-button { display: none !important; }

/* hero copy — tagline bottom-left, scroll cue bottom-right */
.hero__copy {
  position: relative; z-index: 3; flex: none;
  display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-4);
  padding-inline: var(--edge);
  padding-block-end: var(--space-4);
  max-width: none;
}
.hero__tagline {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(17px, 1.55vw, 28px); line-height: 1.06;
  letter-spacing: -0.005em; text-transform: uppercase;
  color: var(--c-paper);
}
.hero__scroll {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: .2em;
  font-size: 12px; color: rgba(244,242,238,.72); white-space: nowrap;
  display: inline-flex; align-items: center; gap: 8px; padding-bottom: 6px;
}
.hero__scroll:hover { color: var(--c-paper); }
.hero__scroll .arr { animation: bob 1.6s ease-in-out infinite; }
@keyframes bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(4px); } }
@media (prefers-reduced-motion: reduce) { .mc, .drop, .hero__scroll .arr { animation: none; } }

/* ============================================================
   SUBPAGE HEADER BAND (about.html, contact.html, …)
   ============================================================ */
.page-hero {
  padding-block: clamp(34px, 4.2vw, 66px) var(--space-4);
  border-bottom: 1px solid var(--c-line);
}
.page-hero h1 {
  font-family: var(--font-display); font-weight: 900;
  font-size: var(--t-h1); line-height: 0.94;
  letter-spacing: -0.02em; text-transform: uppercase;
  margin-top: 12px;
}
.page-hero p {
  color: var(--c-muted); font-size: 17px; line-height: 1.55;
  max-width: 56ch; margin-top: var(--space-3);
}

/* ---- inverted band: paper ground, ink type ----
   Everything inside has to flip, not just the background. The outlined
   "MASTERY" is the trap: its stroke is --c-rule on a dark page, which on paper
   would be near-invisible, and the diamond markers are paper-on-paper. */
.band--paper {
  background: var(--c-paper);
  color: var(--c-ink);
}
.band--paper .mastery__title { color: var(--c-ink); }
.band--paper .mastery__title .out { -webkit-text-stroke: 1.5px var(--c-ink); }
.band--paper .mastery__copy p { color: #3d3b37; }
.band--paper .mastery__copy p.mastery__where {
  font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: .14em;
  font-size: clamp(11px, 1vw, 13px); font-weight: 700;
  color: var(--c-brand);
  max-width: 46ch; margin-bottom: var(--space-2);
}
.band--paper .mastery__list li { color: var(--c-ink); }
.band--paper .mastery__list li::before { background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230a0a0a' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='m9 12 2 2 4-4'/></svg>") center / contain no-repeat; }
.band--paper .mastery__video { border-color: rgba(10,10,10,.18); }

/* ---- forms ---- */
.form { display: grid; gap: var(--space-3); max-width: 620px; }
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.field label {
  display: block; margin-bottom: 8px;
  font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: 0.16em;
  font-size: 11px; color: var(--c-muted);
}
.field label .req { color: var(--c-brand); }
.field input, .field select, .field textarea {
  width: 100%;
  /* Not transparent. These sit on a blue gradient, and a see-through box with
     a #1f1f1f rim disappeared into it — the reported "can't see the words". */
  background: rgba(10,10,10,.72);
  border: 1px solid rgba(244,242,238,.42);   /* .28 measured 2.26:1 — under the 3:1 UI minimum */
  border-radius: var(--btn-radius);
  color: var(--c-paper);
  font-family: var(--font-body);
  font-size: 15px;
  padding: 13px 15px;
  transition: border-color .18s ease, background .18s ease;
}
/* #55524c on blue was ~1.4:1. This clears 4.5:1 on the field ground above. */
.field input::placeholder, .field textarea::placeholder { color: #9b978f; }
.field input:hover, .field select:hover, .field textarea:hover {
  border-color: rgba(244,242,238,.68);
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  background: var(--c-ink);
  border-color: var(--c-paper);
  box-shadow: 0 0 0 3px rgba(43,92,255,.35);
}
.field select { appearance: none; cursor: pointer; }
.field select option { background: var(--c-ink); color: var(--c-paper); }
.field textarea { min-height: 150px; resize: vertical; }
.form__note { font-size: 13px; color: var(--c-muted); }
.form__note:empty { display: none; }

/* ---- program fee cards ----
   Replaces the per-venue session listings on the three discipline pages: one
   card per PROGRAM TYPE, not per school, so adding a campus never grows this
   block. Paper cards on the near-black page, with a solid ink footer bar. */
.fees-head { text-align: center; max-width: 640px; margin: 0 auto var(--space-5); }
.fees-head h2 {
  font-family: var(--font-display); font-weight: 900;
  font-size: var(--t-h2); text-transform: uppercase; line-height: 1;
}
.fees-head p { margin-top: var(--space-2); color: var(--c-muted); }

.fees {
  display: grid; gap: var(--space-3);
  grid-template-columns: repeat(3, 1fr);
  align-items: stretch;
}
.fee {
  display: flex; flex-direction: column;
  background: var(--c-paper); color: var(--c-ink);
  border-radius: 14px; overflow: hidden;
  text-align: center;
}
.fee__body {
  flex: 1 1 auto;                 /* the footer bars line up across cards */
  padding: var(--space-4) var(--space-3) var(--space-4);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
}
/* The price is the number a parent came to find. It was set at 17px, smaller
   than the body copy under it, so the card led with the word "Classes" and
   buried the cost. The materials fee stays small on purpose — it is the
   footnote, not the headline. */
.fee__price {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(24px, 2.2vw, 32px); line-height: 1;
  letter-spacing: -0.02em;
  display: flex; flex-direction: column; gap: 6px;
}
.fee__plus {
  font-family: var(--font-body); font-weight: 500;
  font-size: 13px; letter-spacing: 0; color: #55524c;
}
.fee__count {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(26px, 2.8vw, 38px); text-transform: uppercase;
  line-height: 1; letter-spacing: -0.01em;
  margin: var(--space-2) 0 var(--space-2);
}
.fee__kind { font-size: 14px; line-height: 1.5; color: #3a3833; }
.fee__cta {
  display: block; padding: 15px var(--space-3);
  background: var(--c-ink); color: var(--c-paper);
  font-family: var(--font-label); font-weight: 700;
  text-transform: uppercase; letter-spacing: .14em; font-size: 12px;
  transition: background .18s ease;
}
.fee__cta:hover { background: var(--c-brand); }
.fees__note {
  margin-top: var(--space-4); text-align: center;
  font-size: 14px; color: var(--c-muted);
}

/* ---- city cards ----
   Grouped by CITY rather than by class, the way a parent actually searches:
   where first, what second. Adding a class to a venue grows a list inside an
   existing card instead of adding another card to scan. */
.city-list { display: grid; gap: var(--space-3); }
.city {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: var(--space-3);
  transition: border-color .18s ease, background .18s ease;
  cursor: pointer;
}
.city:hover { border-color: var(--c-rule); }
.city.is-active { border-color: var(--c-paper); background: rgba(244,242,238,.04); }

.city__head { display: flex; gap: var(--space-2); align-items: flex-start; }
.city__num {
  flex: none; width: 26px; height: 26px; border-radius: 5px;
  background: var(--c-brand); color: var(--c-paper);
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 900; font-size: 14px;
  line-height: 1;
}
.city__head h3 {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(19px, 1.9vw, 25px); text-transform: uppercase;
  line-height: 1; letter-spacing: -0.01em;
}
.city__site { font-size: 13px; color: var(--c-muted); margin-top: 5px; }

.city__tags { display: flex; flex-wrap: wrap; gap: 6px; margin: var(--space-2) 0; }

.city__classes { display: grid; gap: 10px; margin-top: var(--space-2); }
.city__classes li {
  display: flex; gap: var(--space-2); align-items: center; justify-content: space-between;
  padding-top: 10px; border-top: 1px solid var(--c-line);
}
.city__classes strong { display: block; font-weight: 800; font-size: 15px; }
.city__classes span { display: block; font-size: 13px; color: var(--c-muted); margin-top: 3px; }
.city__classes a {
  flex: none;
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .12em; font-size: 11px; font-weight: 700;
  padding: 9px 16px; border-radius: 999px;
  background: var(--c-paper); color: var(--c-ink);
  transition: background .18s ease, color .18s ease;
}
.city__classes a:hover { background: var(--c-brand); color: var(--c-paper); }
/* The price was 12px muted grey — the one number a parent is looking for,
   set smaller than everything around it. Now the total leads. */
/* Queen of Apostles has its own page (the one the printed QR points at) but
   nothing linked to it from here, so it was effectively unreachable. */
.city__actions { flex: none; display: flex; align-items: center; gap: 10px; }
.city__more {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .12em; font-size: 11px; font-weight: 700;
  padding: 9px 16px; border-radius: 999px;
  border: 1px solid var(--c-rule); color: var(--c-paper);
  background: transparent;
  transition: border-color .18s ease, color .18s ease;
}
.city__more:hover { border-color: var(--c-paper); }

/* A class that is listed but not taking sign-ups. Reads as a state, not a
   button, so nobody taps it expecting a form. */
.city__closed {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .12em; font-size: 11px; font-weight: 700;
  padding: 9px 16px; color: var(--c-muted);
  white-space: nowrap;
}

.city__price {
  margin-top: var(--space-3);
  padding-top: var(--space-2);
  border-top: 1px solid var(--c-line);
  display: grid; gap: 3px;
}
.city__amount {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(28px, 3vw, 38px); line-height: 1;
  letter-spacing: -0.02em;
}
.city__plus { font-size: 14px; color: var(--c-muted); }
.city__via {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 10px; color: var(--c-muted);
  margin-top: 4px;
}
.camp__blurb { margin-top: var(--space-2); font-size: 14px; color: var(--c-muted); max-width: 62ch; }

/* ---- provider page hero with a school crest ----
   The supplied artwork is only 160px wide, so it is displayed well under that
   to stay crisp on a retina screen rather than sized to fill the space. */
.page-hero--crest {
  display: grid; grid-template-columns: 1fr auto;
  gap: var(--space-4); align-items: center;
}
.page-hero__crest {
  width: clamp(74px, 8vw, 104px);
  height: auto;
  flex: none;
  justify-self: end;
}
@media (max-width: 640px) {
  .page-hero--crest { grid-template-columns: 1fr; gap: var(--space-3); }
  .page-hero__crest { justify-self: start; width: 74px; }
}

/* ---- course dates ----
   A full session-by-session list, the way a recreation-department booking page
   shows it. Parents check this against a calendar, so every date is spelled
   out rather than summarised as a range. */
.coursedates {
  margin-top: var(--space-5);
  border: 1px solid rgba(244,242,238,.28);
  border-radius: var(--radius);
  overflow: hidden;
  background: rgba(10,10,10,.4);
}
.coursedates__head {
  padding: var(--space-3);
  border-bottom: 1px solid rgba(244,242,238,.18);
}
.coursedates__head h2 {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(22px, 2.4vw, 32px); text-transform: uppercase;
  line-height: 1; letter-spacing: -0.01em;
}
.coursedates__head p { margin-top: 8px; font-size: 14px; color: var(--c-muted); }
.coursedates__head strong { color: var(--c-paper); font-weight: 800; }

/* the table is the one thing on the page allowed to scroll sideways */
.coursedates__scroll { overflow-x: auto; }
.cd { width: 100%; border-collapse: collapse; font-size: 14px; }
.cd th {
  text-align: left; font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: .14em; font-size: 10px;
  font-weight: 700; color: rgba(244,242,238,.6);
  padding: 12px var(--space-2); white-space: nowrap;
}
.cd td { padding: 13px var(--space-2); vertical-align: middle; }
.cd tbody tr { border-top: 1px solid rgba(244,242,238,.12); }
/* zebra striping is what makes a long date list scannable */
.cd tbody tr:nth-child(even) { background: rgba(244,242,238,.035); }
.cd__n {
  font-family: var(--font-display); font-weight: 900;
  color: rgba(244,242,238,.45); width: 1%; padding-left: var(--space-3);
}
.cd__dow { font-weight: 800; white-space: nowrap; }
.cd__date { white-space: nowrap; }
.cd__short { display: none; }
.cd__long  { display: inline; }
.cd__time { white-space: nowrap; color: var(--c-muted); }
.cd__where { color: var(--c-muted); padding-right: var(--space-3); }
.coursedates__note {
  padding: var(--space-3);
  border-top: 1px solid rgba(244,242,238,.18);
  font-size: 13px; color: var(--c-muted);
}

/* ---- contact / interest form ---- */
.enquire-grid {
  display: grid; grid-template-columns: 0.85fr 1.15fr;
  gap: var(--space-5); align-items: start;
}
.enquire-title {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(30px, 3.6vw, 50px); text-transform: uppercase;
  line-height: .95; letter-spacing: -0.02em;
  margin: 10px 0 var(--space-3);
}
.enquire-lead { color: var(--c-muted); max-width: 42ch; }

.enquire-contact { margin-top: var(--space-4); display: grid; gap: var(--space-3); }
.enquire-contact li {
  display: grid; gap: 4px;
  padding-top: var(--space-2);
  border-top: 1px solid rgba(244,242,238,.25);
}
.enquire-contact .k {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .16em; font-size: 10px; color: rgba(244,242,238,.65);
}
.enquire-contact .v {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(17px, 1.7vw, 21px); text-transform: uppercase; line-height: 1.1;
}
a.enquire-contact__x:hover { text-decoration: underline; }
.enquire-contact a.v:hover { color: var(--c-paper); text-decoration: underline; text-underline-offset: 4px; }

/* The card is what makes the fields legible: it puts an ink ground between
   the inputs and the blue gradient behind the section. */
.enquire-card {
  background: rgba(10,10,10,.55);
  border: 1px solid rgba(244,242,238,.18);
  border-radius: var(--radius);
  padding: var(--space-4);
  backdrop-filter: blur(6px);
}
.enquire-card .form { max-width: none; }
/* Private lessons: its own panel in the aside column. Lighter ground than
   the form card beside it so the two read as two offers, not one form with a
   footnote. */
.lesson-cta {
  /* leads the aside now, so the gap belongs underneath it */
  margin-bottom: var(--space-5);
  padding: var(--space-3);
  border: 1px solid rgba(244,242,238,.28);
  border-radius: var(--radius);
  background: rgba(10,10,10,.4);
}
.lesson-cta h3 {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(22px, 2.2vw, 30px); text-transform: uppercase;
  line-height: 1; letter-spacing: -0.01em;
  margin: 8px 0 10px;
}
.lesson-cta p { font-size: 14px; line-height: 1.55; color: var(--c-muted); }
.lesson-cta .btn { margin-top: var(--space-3); width: 100%; text-align: center; }

.field--captcha { min-height: 78px; }
/* Grid children default to min-width:auto, so the reCAPTCHA iframe's fixed
   304px floor was pushing the whole column past the viewport on a phone. */
.enquire-grid > * { min-width: 0; }

/* Honeypot. Off-screen rather than display:none — some bots skip hidden
   fields, and this still keeps it away from people and screen readers. */
.hp {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden;
}

/* ---- location cards ---- */
.locations { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.location {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: var(--space-3);
}
.location h3 {
  font-family: var(--font-display); font-weight: 800;
  font-size: 22px; text-transform: uppercase; line-height: 1; margin-bottom: 10px;
}
.location p { color: var(--c-muted); font-size: 15px; }

@media (max-width: 760px) {
  .form__row { grid-template-columns: 1fr; }
  .locations { grid-template-columns: 1fr; }
}

/* ============================================================
   DIGITAL MASTERY
   ============================================================ */
.mastery {
  display: grid;
  grid-template-columns: 1fr 1.12fr;
  gap: var(--space-5);
  align-items: center;
}
.mastery__title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--t-h1);
  /* 0.92 pressed DIGITAL onto MASTERY; the outlined stroke on the second line
     needs the extra room more than solid type would */
  line-height: 1.04;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  margin: 12px 0 var(--space-3);
}
/* outlined second line — the monochrome stand-in for the red accent */
.mastery__title .out {
  color: transparent;
  -webkit-text-stroke: 1.5px var(--c-rule);
}
.mastery__copy p { color: var(--c-muted); font-size: 17px; max-width: 48ch; }
.mastery__list { margin-top: var(--space-4); display: grid; gap: 14px; }
.mastery__list li {
  display: flex; align-items: center; gap: 14px;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 14px;
  font-weight: 700;
}
.mastery__list li::before {
  content: ""; flex: none;
  width: 20px; height: 20px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232b5cff' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='m9 12 2 2 4-4'/></svg>") center / contain no-repeat;
}
.mastery__video {
  position: relative;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  overflow: hidden;
  background: #0f0f0f;
}
.mastery__video iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0;
}

/* ============================================================
   STAT BLOCKS
   ============================================================ */
.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--c-line); border-radius: var(--radius);
  overflow: hidden;
}
.stat { padding: var(--space-4) var(--space-3); border-right: 1px solid var(--c-line); }
.stat:last-child { border-right: none; }
.stat__num {
  font-family: var(--font-display);
  font-weight: 900; font-size: clamp(38px, 5vw, 56px);
  line-height: 1; letter-spacing: -0.02em;
}
.stat__label {
  font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: 0.16em;
  font-size: 12px; color: var(--c-muted); margin-top: 10px;
}

/* ============================================================
   COURSE CARDS
   ============================================================ */
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); }

.course {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: var(--space-3);
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, rgba(255,255,255,0.015), transparent);
  transition: border-color .2s ease, transform .2s ease;
}
.course:hover { border-color: var(--c-rule); transform: translateY(-4px); }
.course__meta { display: flex; justify-content: space-between; margin-bottom: var(--space-4); }
.course h3 {
  font-family: var(--font-display);
  font-weight: 800; font-size: 24px; text-transform: uppercase;
  letter-spacing: -0.01em; line-height: 1; margin-bottom: 12px;
}
.course p { color: var(--c-muted); font-size: 15px; margin-bottom: var(--space-3); flex: 1; }
.course__foot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-2);
  border-top: 1px solid var(--c-line); padding-top: var(--space-2);
}
.course__price { font-family: var(--font-display); font-weight: 800; font-size: 22px; }

/* ---- fused card strip: three panels sharing their seams, only the outer
   corners rounded, so the row reads as one object instead of three floating
   cards. Overlapping the borders by -1px keeps every panel the same width —
   dropping a border on all but one would leave that panel 1px wider. ---- */
.card-strip { display: flex; }
.card-strip .course {
  flex: 1 1 0; min-width: 0;
  padding: 0;                        /* the image goes full-bleed; the inner
                                        blocks carry their own padding */
  border-radius: 0;
  overflow: hidden;                  /* lets the outer radius clip the image */
}
.card-strip .course + .course { margin-left: -1px; }
/* The panels were near-transparent and just let the page ground show through.
   Over the blue ramp that made card and background the same colour, so the
   strip vanished into it; they now carry their own opaque ground. */
.card-strip .course { background-color: var(--c-ink); }

.card-strip .course:first-child {
  border-top-left-radius: var(--radius); border-bottom-left-radius: var(--radius);
}
.card-strip .course:last-child {
  border-top-right-radius: var(--radius); border-bottom-right-radius: var(--radius);
}
/* a panel that lifts on hover tears the shared seam, so lighten instead */
.card-strip .course:hover { transform: none; border-color: var(--c-line); background: #101011; }
.card-strip .course:hover .ph { border-color: #3a3a35; }

.card-strip .ph {
  border-radius: 0;
  border-top: none; border-left: none; border-right: none;   /* seam only */
  /* the body below grows to fill the panel; without this the aspect-ratio
     box is treated as shrinkable and collapses to ~1px */
  flex: none;
}
.card-strip .course__body {
  padding: var(--space-3) var(--space-3) 0;
  flex: 1; display: flex; flex-direction: column;
}
.card-strip .course h3 { margin-bottom: 10px; }
/* the descriptions differ in length; letting them absorb the slack keeps
   every button row on one shared baseline across the strip */
.card-strip .course p { margin-bottom: var(--space-2); flex: 1; }
.card-strip .course__actions {
  display: flex; gap: 10px; padding: var(--space-3);
}
.card-strip .course__actions .btn { flex: 1; padding-inline: 0; }

/* ============================================================
   LESSON CARD STRIP (horizontal scroller)
   ============================================================ */
.strip {
  display: flex;
  /* `safe` matters: plain `center` makes the first card unreachable once the
     row overflows (it gets clipped past the scroll origin). */
  justify-content: safe center;
  gap: var(--space-2);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  padding-bottom: var(--space-2);
  scrollbar-width: thin;
  scrollbar-color: #3a3a37 transparent;
}
.strip::-webkit-scrollbar { height: 6px; }
.strip::-webkit-scrollbar-thumb { background: #3a3a37; border-radius: 999px; }
.strip::-webkit-scrollbar-track { background: transparent; }
.strip:focus-visible { outline: 1px solid var(--c-rule); outline-offset: 6px; }

.lesson-card {
  flex: 0 0 clamp(236px, 26vw, 330px);
  scroll-snap-align: start;
  display: flex; flex-direction: column;
}
.lesson-card__img {
  aspect-ratio: 3 / 4;
  margin-bottom: var(--space-2);
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(160deg, #171715, #0e0e0d);
  border: 1px dashed #2c2c29;      /* dashed = placeholder; drop it once real images land */
  display: grid; place-items: center;
  font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: .24em; font-size: 11px;
  color: var(--c-muted);
}
.lesson-card__img img,
.lesson-card__img video { width: 100%; height: 100%; object-fit: cover; display: block; }
.lesson-card__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.lesson-card h3 {
  font-family: var(--font-display); font-weight: 800;
  font-size: 22px; text-transform: uppercase;
  line-height: 1; letter-spacing: -0.01em; margin-bottom: 10px;
}
/* full class name lives here, not in the foot — it can wrap without
   knocking the Book links out of alignment across cards */
.lesson-card__full {
  display: block;
  font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: .14em;
  font-size: 11px; color: var(--c-muted);
  margin-bottom: 10px;
}
.lesson-card p { color: var(--c-muted); font-size: 14px; flex: 1; margin-bottom: var(--space-2); }
/* cards are image + button only, so the link centres under the frame */
.lesson-card__foot {
  display: flex; align-items: baseline; justify-content: center;
  padding-top: var(--space-2);
}

/* ============================================================
   WORK CARDS
   ============================================================ */
.grid-3.work { gap: var(--space-2); }
.work-card { display: block; }
.work-card__img {
  aspect-ratio: 4/3; border-radius: var(--radius); overflow: hidden;
  background: linear-gradient(135deg, #161616, #0d0d0d);
  border: 1px solid var(--c-line);
  position: relative;
  display: flex; align-items: center; justify-content: center;
  transition: transform .25s ease;
}
.work-card:hover .work-card__img { transform: translateY(-4px); }
.work-card__img::after {
  content: ""; position: absolute; inset: 0;
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,.03) 0 2px, transparent 2px 9px);
}
.work-card__play {
  width: 54px; height: 54px; border-radius: 50%;
  border: 1px solid var(--c-rule); color: var(--c-paper);
  display: grid; place-items: center; font-size: 14px; position: relative; z-index: 1;
}
.work-card__cap {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-top: var(--space-2); gap: var(--space-2);
}
.work-card__cap h3 {
  font-family: var(--font-display); font-weight: 800; font-size: 18px;
  text-transform: uppercase; letter-spacing: 0.01em;
}
.work-card__cap span { font-family: var(--font-label); color: var(--c-muted); font-size: 13px; }
.work-card__tags { display: flex; gap: 6px; margin-top: 8px; }

/* ============================================================
   TRACK PLAYER
   ============================================================ */
.player {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: var(--space-3);
  display: flex; align-items: center; gap: var(--space-3);
  background: linear-gradient(180deg, rgba(255,255,255,0.02), transparent);
}
.player__btn {
  width: 56px; height: 56px; flex: none; border-radius: 50%;
  background: var(--c-paper); color: var(--c-ink); border: none;
  display: grid; place-items: center; font-size: 16px;
  transition: transform .18s ease;
}
.player__btn:hover { transform: scale(1.06); }
.player__info { flex: none; }
.player__now {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: 0.16em; font-size: 11px; color: var(--c-muted);
}
.player__track { font-family: var(--font-display); font-weight: 800; font-size: 17px; text-transform: uppercase; margin-top: 2px; }
.player__wave { flex: 1; display: flex; align-items: center; gap: 3px; height: 44px; min-width: 80px; }
.player__wave span {
  flex: 1; background: #3a3a37; border-radius: 2px;
  height: 30%; transition: background .2s ease;
}
.player.is-playing .player__wave span { animation: wave 1.1s ease-in-out infinite; background: var(--c-rule); }
@keyframes wave { 0%,100% { height: 18%; } 50% { height: 90%; background: var(--c-paper); } }
.player__time { font-family: var(--font-label); color: var(--c-muted); font-size: 13px; flex: none; }

/* ============================================================
   INSTRUCTOR CARDS
   ============================================================ */
.grid-3.team { gap: var(--space-2); }
.tutor__img {
  aspect-ratio: 1/1; border-radius: var(--radius); overflow: hidden;
  background: linear-gradient(160deg, #1a1a1a, #0c0c0c);
  border: 1px solid var(--c-line); position: relative;
  display: flex; align-items: flex-end; padding: var(--space-2);
}
.tutor__img::before {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(0deg, rgba(255,255,255,.025) 0 1px, transparent 1px 6px);
}
.tutor__tag { position: relative; z-index: 1; }
.tutor__name {
  font-family: var(--font-display); font-weight: 800; font-size: 20px;
  text-transform: uppercase; margin-top: var(--space-2);
}
.tutor__role { font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.14em; font-size: 12px; color: var(--c-muted); margin-top: 2px; }

/* ============================================================
   FAQ ACCORDION
   ============================================================ */
/* ---- FAQ accordion ----
   Layout ported from the shadcn accordion block; the type is the site's own
   display face rather than the source's Oswald. No chevron: the dim-to-bright
   shift on the question is the open/closed signal. */
.faq-wrap { display: grid; grid-template-columns: 0.7fr 1.3fr; gap: var(--space-5); }
.faq-wrap--stack { grid-template-columns: 1fr; gap: var(--space-3); justify-items: center; }
.faq-wrap--stack > div:first-child { text-align: center; }
/* the block centres on the page; the rows inside stay left-aligned, since
   centring a numeral-plus-question row leaves the numbers ragged */
.faq-wrap--stack .faq { max-width: 900px; width: 100%; margin-inline: auto; }

.faq__item { border-top: 1px solid var(--c-line); }
.faq__item:last-child { border-bottom: 1px solid var(--c-line); }
.faq__q {
  width: 100%; background: none; border: none;
  display: flex; align-items: flex-start; gap: 16px;
  padding: var(--space-3) 0 var(--space-3) var(--space-3);
  text-align: left; cursor: pointer;
  /* the source used text-foreground/20, which lands at ~1.9:1 on this ground
     and fails even the 3:1 large-text floor; 0.42 keeps the effect at 4.3:1 */
  color: rgba(244, 242, 238, .42);
  transition: color .2s ease;
}
.faq__q:hover { color: rgba(244, 242, 238, .72); }
.faq__item.is-open .faq__q { color: var(--c-paper); }
.faq__q:focus-visible { outline: 2px solid var(--c-paper); outline-offset: -4px; }

.faq__n {
  flex: none; font-family: var(--font-label);
  font-size: 12px; font-weight: 700; letter-spacing: .1em;
  padding-top: .85em;      /* optical: aligns the numeral to the cap line */
}
.faq__t {
  /* same face and weight as the QUESTIONS heading above it */
  font-family: var(--font-display);
  font-weight: 800; text-transform: uppercase;
  /* Hatsch sets much wider than Oswald's condensed cut, so the same clamp
     ceiling would wrap most questions onto three lines */
  font-size: clamp(22px, 2.9vw, 38px);
  line-height: 1.05; letter-spacing: -0.01em;
}

.faq__a { max-height: 0; overflow: hidden; transition: max-height .3s ease; }
.faq__a p {
  color: var(--c-muted);
  padding: 0 0 var(--space-3) var(--space-3);
  max-width: 68ch;
}
@media (min-width: 900px) {
  .faq__q { padding-left: 56px; }              /* md:pl-14 */
  .faq__a p { padding-left: 80px; }            /* md:px-20 */
}

/* ============================================================
   CTA BANNER
   ============================================================ */
.cta-banner {
  position: relative;              /* the ripple canvas anchors to this */
  border-top: 1px solid var(--c-line);
  text-align: center;
  padding-block: var(--space-6);
  overflow: hidden;
}
/* WebGL ripple background. pointer-events stay off so the button underneath is
   still clickable; the section itself listens for the pointer instead. */
.cta-banner .ripple {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block; pointer-events: none;
  z-index: 0;
}
/* The ripple runs at full strength at the edges, but the sub-paragraph is
   small white text and was landing straight on bright red bands. This scrim
   sits between canvas and copy: near-opaque behind the text, gone by the
   edges, so the shader still reads as a full-bleed background. */
.cta-banner::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(ellipse 62% 72% at 50% 50%,
    rgba(10, 10, 10, .90) 0%,
    rgba(10, 10, 10, .62) 45%,
    rgba(10, 10, 10, 0) 78%);
}
.cta-banner > .wrap { position: relative; z-index: 1; }
.cta-banner h2 {
  font-family: var(--font-display); font-weight: 900;
  font-size: var(--t-h1); text-transform: uppercase; line-height: 0.95;
  letter-spacing: -0.02em; margin-bottom: var(--space-3);
}

/* ============================================================
   FOOTER / INFO PANEL
   ============================================================ */
.footer { border-top: 1px solid var(--c-line); padding-block: var(--space-5) var(--space-4); }
.footer__top { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--space-4); }
.footer__brand .brand { font-size: 22px; margin-bottom: var(--space-2); }
.footer__brand p { color: var(--c-muted); max-width: 32ch; font-size: 14px; }
.footer__col h4 {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.16em;
  font-size: 12px; color: var(--c-muted); margin-bottom: var(--space-2);
}
.footer__col li { margin-bottom: 10px; }
.footer__col a { font-size: 14px; color: var(--c-paper); opacity: .85; transition: opacity .15s; }
.footer__col a:hover { opacity: 1; }
.footer__bar {
  display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--space-2);
  border-top: 1px solid var(--c-line); margin-top: var(--space-5); padding-top: var(--space-3);
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.12em;
  font-size: 11px; color: var(--c-muted);
}

/* ============================================================
   COOKIE BANNER
   ============================================================ */
.cookie {
  position: fixed; right: var(--space-3); bottom: var(--space-5); z-index: 60;
  max-width: 380px; background: var(--c-paper); color: var(--c-ink);
  border-radius: var(--radius); padding: var(--space-3);
  box-shadow: 0 18px 50px rgba(0,0,0,.5);
}
.cookie.is-hidden { display: none; }
.cookie p { font-size: 13px; line-height: 1.5; margin-bottom: var(--space-2); }
.cookie__row { display: flex; gap: var(--space-1); }
/* the cookie card is the one paper surface on the site, so every rim in here
   is the mirror of the same button elsewhere */
.cookie .btn {
  /* keeps the optical cap-shift while overriding the size */
  padding: calc(10px - var(--btn-cap-shift)) 18px calc(10px + var(--btn-cap-shift));
  font-size: 12px; border-color: var(--c-ink); color: var(--c-ink);
  box-shadow: var(--glass-on-light);
}
.cookie .btn--solid { background: var(--c-ink); color: var(--c-paper); box-shadow: var(--glass-on-dark); }
.cookie .btn--solid:hover { background: transparent; color: var(--c-ink); box-shadow: var(--glass-on-light); }
.cookie .btn--ghost:hover { background: var(--c-ink); color: var(--c-paper); box-shadow: var(--glass-on-dark); }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 900px) {
  .mastery { grid-template-columns: 1fr; gap: var(--space-4); }
  .grid-3 { grid-template-columns: 1fr 1fr; }
  .stats { grid-template-columns: 1fr 1fr; }
  .stat:nth-child(2) { border-right: none; }
  .stat:nth-child(1), .stat:nth-child(2) { border-bottom: 1px solid var(--c-line); }
  .faq-wrap { grid-template-columns: 1fr; gap: var(--space-3); }
  .footer__top { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
}

@media (max-width: 640px) {
  /* stacked buttons look untidy at their natural widths — match them */
  .hero__actions { flex-direction: column; align-items: center; }
  .hero__actions .btn { width: 100%; max-width: 300px; }
  .cookie { left: var(--space-2); right: var(--space-2); max-width: none; }
  .grid-3 { grid-template-columns: 1fr; }
  .player { flex-wrap: wrap; }
  .player__wave { order: 4; width: 100%; flex-basis: 100%; }
  .announce__msg { font-size: 11px; }
}
@media (max-width: 760px) {
  .hero { min-height: 88vh; }
  .hero__copy { flex-direction: column; align-items: flex-start; bottom: var(--space-3); }
  /* .about-grid's mobile override lives at the end of this file — declared here
     it would be overridden by the base rule that follows. */
}

/* ============================================================
   ABOUT / INSTRUCTOR
   ============================================================ */
.about-grid {
  display: grid; grid-template-columns: 0.85fr 1.15fr;
  gap: var(--space-5); align-items: center;
}
.about__photo { aspect-ratio: 4/5; }
.about h2.big {
  font-family: var(--font-display); font-weight: 900; font-size: var(--t-h1);
  text-transform: uppercase; line-height: 0.95; letter-spacing: -0.02em;
  margin: 10px 0 var(--space-3);
}
.about p { color: var(--c-muted); font-size: 17px; max-width: 56ch; }
.about__credits { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--space-4); }

.course__tagline {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: 0.14em; font-size: 12px; color: var(--c-muted);
}

/* ============================================================
   CLASS PAGES (music-production / dj / songwriting)
   ============================================================ */
.lead {
  font-size: clamp(18px, 1.7vw, 25px);
  line-height: 1.4;
  color: var(--c-paper);
  max-width: 46ch;
}
.prose p { color: var(--c-muted); font-size: 16px; line-height: 1.6; max-width: 62ch; margin-top: var(--space-3); }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); align-items: start; }
.split--media { align-items: center; }
.split__img { width: 100%; height: auto; border-radius: var(--radius); display: block; }

/* ---- Classes section: vertical black-to-blue ground ----
   Stays dark, so the section head, cards and buttons keep working exactly as
   they do everywhere else on the site. Blue matches the ripple shader. */
.band--blue {
  background: linear-gradient(180deg, var(--c-ink) 0%, #0000ff 100%);
}

/* ---- quick register: pick a location, go straight to its page ---- */
.quickreg { text-align: center; }
/* the pair is flipped: Find Your Class leads, the stat bar follows it */
.quickreg + .stats { margin-top: var(--space-5); }
.quickreg__head {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(26px, 3.6vw, 46px); text-transform: uppercase;
  line-height: 1; letter-spacing: -0.02em; margin-bottom: var(--space-3);
}
.quickreg__bar {
  display: flex; align-items: stretch;
  max-width: 720px; margin-inline: auto;
  /* rounded-xl + a 2px rim, per the reference dropdown, instead of the old
     pill — a pill bar over a rounded-xl menu read as two different widgets */
  border: 2px solid var(--c-paper); border-radius: 14px;
  background: var(--c-ink);
  position: relative;
}

/* ---- custom listbox (ported from the dropdown-01 React component) ----
   Same behaviour without React/framer-motion: chevron rotates, the panel
   fades and slides, rows invert on hover, the chosen row keeps a tick. */
.dd { flex: 1; min-width: 0; position: relative; }
.dd__btn {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  background: transparent; border: none; color: var(--c-paper);
  font-family: inherit; font-size: clamp(14px, 1.2vw, 16px); font-weight: 600;
  padding: 18px var(--space-3); cursor: pointer; text-align: left;
  border-radius: 12px 0 0 12px;
}
.dd__value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd__chev {
  flex: none; width: 20px; height: 20px;
  transition: transform .3s ease;
}
.dd__btn[aria-expanded="true"] .dd__chev { transform: rotate(180deg); }
.dd__btn:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -4px; }

.dd__menu {
  position: absolute; top: calc(100% + 10px); left: -2px; right: -2px;
  z-index: 70;
  background: var(--c-ink);
  border: 2px solid var(--c-paper); border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 26px 60px rgba(0,0,0,.55);
  text-align: left;
  opacity: 0; visibility: hidden; transform: translateY(-10px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s;
}
.dd.is-open .dd__menu { opacity: 1; visibility: visible; transform: translateY(0); }

.dd__menu li {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: 15px var(--space-3);
  cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.dd__menu li + li { border-top: 1px solid #2a2a2a; }
.dd__menu li:hover,
.dd__menu li.is-cursor { background: var(--c-paper); color: var(--c-ink); }
.dd__text { display: grid; gap: 2px; min-width: 0; }
.dd__label { font-weight: 800; font-size: 15px; }
.dd__desc { font-size: 13px; color: var(--c-muted); }
.dd__menu li:hover .dd__desc,
.dd__menu li.is-cursor .dd__desc { color: #55524c; }

.dd__check {
  flex: none; width: 19px; height: 19px;
  opacity: 0; transform: scale(.5);
  transition: opacity .18s ease, transform .18s cubic-bezier(.2,1.6,.4,1);
}
.dd__menu li[aria-selected="true"] .dd__check { opacity: 1; transform: scale(1); }

/* the staggered entrance the reference does with framer-motion */
.dd.is-open .dd__menu li { animation: ddIn .22s ease both; }
.dd.is-open .dd__menu li:nth-child(1) { animation-delay: .00s; }
.dd.is-open .dd__menu li:nth-child(2) { animation-delay: .05s; }
.dd.is-open .dd__menu li:nth-child(3) { animation-delay: .10s; }
.dd.is-open .dd__menu li:nth-child(4) { animation-delay: .15s; }
@keyframes ddIn { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .dd__menu, .dd__chev, .dd__check { transition: none; }
  .dd.is-open .dd__menu li { animation: none; }
}

.quickreg__go {
  flex: none; border-radius: 0 12px 12px 0;
  padding-inline: clamp(22px, 3vw, 44px);
}
.quickreg__note {
  color: var(--c-muted); font-size: 14px; line-height: 1.6;
  max-width: 68ch; margin: var(--space-2) auto 0;
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* the single hero CTA carries more weight now that it stands alone */
.btn--lg { padding-inline: clamp(34px, 4vw, 54px); font-size: 14px; }
@media (max-width: 560px) {
  .quickreg__bar { flex-direction: column; }
  .dd__btn { border-radius: 12px 12px 0 0; }
  .quickreg__go { width: 100%; border-radius: 0 0 12px 12px; }
}

/* ---- provider cards: which body handles registration ---- */
.provider-links { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: var(--space-3); }
.provider-card {
  display: grid; gap: 6px;
  padding: var(--space-3);
  border: 1px solid var(--c-line); border-radius: 3px;
  background: var(--c-ink); color: var(--c-paper);
  transition: border-color .2s ease, transform .2s ease;
}
.provider-card:hover { border-color: var(--c-brand); transform: translateY(-2px); }
.provider-card__k {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px; font-weight: 700; color: var(--c-brand);
}
.provider-card__t {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(20px, 2vw, 26px); text-transform: uppercase; line-height: 1.05;
}
.provider-card__m { color: var(--c-muted); font-size: 14px; }
@media (max-width: 700px) { .provider-links { grid-template-columns: 1fr; } }

/* ---- notice panel: coming-soon / adult 1:1 ---- */
.notice {
  border: 1px solid var(--c-line);
  border-left: 3px solid var(--c-brand);
  border-radius: 3px;
  padding: var(--space-3);
  margin-top: var(--space-4);
  max-width: 78ch;
}
.notice__head {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 12px; font-weight: 700;
  color: var(--c-brand); margin-bottom: 10px;
}
.notice p { color: var(--c-muted); font-size: 15px; line-height: 1.6; }
.notice p + p { margin-top: 12px; }
.notice a { color: var(--c-paper); text-decoration: underline; text-underline-offset: 3px; }

/* ---- class-page intro: two-tone headline, copy, diamond list, image ---- */
.intro-split {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--space-5); align-items: center;
}
.intro-title {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(34px, 5vw, 72px);
  line-height: 0.94; letter-spacing: -0.02em;
  text-transform: uppercase;
  margin-bottom: var(--space-3);
}
.intro-title .accent { color: var(--c-brand); display: block; }
.intro-split__copy p {
  color: var(--c-muted);
  font-size: clamp(15px, 1.25vw, 18px); line-height: 1.6;
  max-width: 52ch; margin-bottom: var(--space-2);
}
.diamond-list { margin-top: var(--space-3); display: grid; gap: 14px; list-style: none; }
.diamond-list li {
  display: flex; align-items: center; gap: 14px;
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: 0.1em; font-size: 14px; font-weight: 700;
}
.diamond-list li::before {
  content: ""; flex: none;
  width: 20px; height: 20px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232b5cff' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='m9 12 2 2 4-4'/></svg>") center / contain no-repeat;
}
.intro-split__media { position: relative; }
.intro-split__media img {
  position: relative; z-index: 1;
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: var(--radius); display: block;
}

/* Features grid — port of the features-4 block. Tailwind drew the lattice
   with `divide-x divide-y border`, which relies on `> * + *` and leaves the
   first cell of each row without a left edge. A 1px grid gap over a line-
   coloured backdrop gives the same look as a true lattice, at any cell count. */
.feat-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--c-line);
  border: 1px solid var(--c-line);
  border-radius: 3px;
  overflow: hidden;              /* keeps the corner cells inside the radius */
}
.feat {
  background: var(--c-ink);
  padding: var(--space-4);       /* p-12 */
  transition: background .3s ease;
}
.feat:hover { background: #101011; }
.feat__head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.feat__icon {
  width: 16px; height: 16px;     /* size-4 */
  flex: none; color: var(--c-brand);
}
.feat h3 {
  font-family: var(--font-label);
  font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
  line-height: 1;
}
.feat p { color: var(--c-muted); font-size: 14px; line-height: 1.55; }

/* the lead paragraph that sat under the heading in the source block.
   The head's own bottom margin is meant to clear a grid, not a sentence, so
   tighten it when a lead follows. Without :has() the lead just sits looser —
   no fallback needed. */
/* .page-class .section-head sets the same margin at equal specificity and is
   declared later, so this has to out-specify it rather than just match it */
.section-head:has(+ .section-lead),
.page-class .section-head:has(+ .section-lead) { margin-bottom: var(--space-2); }
.section-lead {
  color: var(--c-muted);
  font-size: clamp(15px, 1.3vw, 18px); line-height: 1.55;
  max-width: 62ch;
  margin: 0 0 var(--space-4);
}

/* numbered learning path */
.path { display: grid; gap: var(--space-2); counter-reset: step; }
.path li {
  counter-increment: step;
  display: flex; gap: var(--space-2); align-items: baseline;
  border-bottom: 1px solid var(--c-line); padding-bottom: var(--space-2);
  font-family: var(--font-display); font-weight: 800;
  font-size: 17px; text-transform: uppercase;
}
.path li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-label); font-size: 12px;
  letter-spacing: .14em; color: var(--c-muted); flex: none;
}

/* format / at-a-glance rows */
.facts { display: grid; gap: 0; border-top: 1px solid var(--c-line); }
.facts div {
  display: flex; justify-content: space-between; gap: var(--space-3);
  padding: 14px 0; border-bottom: 1px solid var(--c-line);
}
.facts dt, .facts .k {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .16em; font-size: 11px; color: var(--c-muted);
}
.facts .v { font-size: 15px; text-align: right; }

/* ============================================================
   SPLICE BONUS BANNER (music-production, songwriting)
   Partner brand colour — deliberately outside the mono palette.
   ============================================================ */
.bonus {
  --c-splice: #1e44f5;
  background: var(--c-splice);
  color: #fff;
  padding-block: var(--space-4);
  position: relative;
  overflow: hidden;
}
/* decorative outlined diamond, top-left */
.bonus::before {
  content: "";
  position: absolute; top: -60px; left: -40px;
  width: 180px; height: 180px;
  border: 1px solid rgba(255,255,255,.28);
  transform: rotate(45deg);
  pointer-events: none;
}
.bonus__head {
  text-align: center;
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(30px, 5.4vw, 76px);
  line-height: 0.9; letter-spacing: -0.02em;
  text-transform: uppercase;
  position: relative;
}
.bonus__head span { display: block; color: var(--c-ink); }
.bonus__body {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--space-4); align-items: center;
  margin-top: var(--space-3);
}
.bonus__logo {
  display: grid; place-items: center;
  font-family: var(--font-body);
  font-weight: 700; font-size: clamp(34px, 4vw, 58px);
  letter-spacing: -0.03em; color: #fff;
}
.bonus__logo img { max-width: 260px; height: auto; }
.bonus h3 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(18px, 1.8vw, 26px);
  text-transform: uppercase; line-height: 1.05; margin-bottom: var(--space-2);
}
.bonus p { font-size: 16px; line-height: 1.6; max-width: 46ch; color: rgba(255,255,255,.92); }

/* The same band inside a content column rather than full-bleed: the school
   pages render it within .wrap, so it needs its own edges and a headline that
   is not sized for the full viewport. Placed here, ahead of the max-width:760
   query below, so that query still stacks the body on a phone. */
.bonus--inline {
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-3);
  margin-top: var(--space-4);
}
.bonus--inline .bonus__head { font-size: clamp(24px, 3.4vw, 42px); }
.bonus--inline .bonus__logo img { max-width: 190px; }
.bonus--inline::before { top: -70px; left: -50px; width: 150px; height: 150px; }

/* Class flyer (school pages). The poster is the loud thing on the page, so the
   frame around it stays quiet: no heading, no caption, just margin. Capped
   well below the column width — at full bleed a 1:1 poster pushes everything
   under it off the first screen. */
.flyer {
  /* Left-aligned, not centred: the wrap is wider than the poster, and centring
     lines it up with neither the class card nor the map. Flush left puts it on
     the same edge as the card above it. */
  margin: var(--space-4) 0 0;
  max-width: 460px;
}
.flyer img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
}

/* ============================================================
   ENROLL / CLASSES PAGE
   ============================================================ */
.jump { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--space-3); }
.jump a {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px;
  color: var(--c-paper);
  border: 1px solid var(--c-line); border-radius: 999px;
  padding: 7px 14px; transition: background .18s ease, color .18s ease;
}
.jump a:hover { background: var(--c-paper); color: var(--c-ink); }

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

.venue { scroll-margin-top: calc(var(--header-h) + 20px); }
.venue__note {
  color: var(--c-muted); font-size: 14px; max-width: 62ch;
  margin-top: calc(var(--space-4) * -1 + 4px); margin-bottom: var(--space-4);
}

.course__cta { margin-top: var(--space-3); }
.course__cta .btn { width: 100%; }
.status {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px; color: var(--c-muted);
  border: 1px dashed #3a3a37; border-radius: var(--btn-radius);
  padding: calc(14px - var(--btn-cap-shift)) 26px calc(14px + var(--btn-cap-shift));
  width: 100%; justify-content: center;
}

/* how registration works */
.howto { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.howto__item { border: 1px solid var(--c-line); border-radius: var(--radius); padding: var(--space-3); }
.howto__item h3 {
  font-family: var(--font-display); font-weight: 800; font-size: 17px;
  text-transform: uppercase; margin-bottom: 10px;
}
.howto__item p { color: var(--c-muted); font-size: 14px; }

/* tighter header on the finder page so the whole table lands above the fold */
.page-hero--tight { padding-block: clamp(28px, 3.6vw, 52px) var(--space-3); }
.page-hero--tight h1 { font-size: clamp(30px, 4.4vw, 52px); }
.section--finder { padding-block: var(--space-4) var(--space-6); }

/* ============================================================
   TESTIMONIALS
   ============================================================ */
.quotes { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); }
.quote {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: var(--space-3); display: flex; flex-direction: column;
}
.quote__mark {
  font-family: var(--font-display); font-weight: 900;
  font-size: 40px; line-height: .7; color: #35342f; margin-bottom: var(--space-2);
}
.quote p { font-size: 15px; line-height: 1.65; flex: 1; }
.quote__by { margin-top: var(--space-3); padding-top: var(--space-2); border-top: 1px solid var(--c-line); }
.quote__name { font-family: var(--font-display); font-weight: 800; font-size: 14px; text-transform: uppercase; }
.quote__meta {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px; color: var(--c-muted); margin-top: 4px;
}
/* unmistakably a placeholder until a real quote replaces it */
.quote--todo { border-style: dashed; border-color: #3a3a37; }
.quote--todo p { color: var(--c-muted); font-style: italic; }
.quote--todo .quote__name, .quote--todo .quote__meta { color: #55524c; }
.quote__flag {
  align-self: flex-start; margin-bottom: var(--space-2);
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: .16em;
  font-size: 10px; color: var(--c-brand);
  border: 1px solid var(--c-brand); border-radius: var(--btn-radius); padding: 4px 9px;
}
@media (max-width: 900px) { .quotes { grid-template-columns: 1fr; } }

/* ============================================================
   ENROLL OVERVIEW PAGE
   ============================================================ */
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }

/* numbered format steps */
.steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-2); }
.step {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: var(--space-3); display: grid; gap: 10px; align-content: start;
}
.step__n {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .18em; font-size: 11px; color: var(--c-muted);
}
.step h3 {
  font-family: var(--font-display); font-weight: 800; font-size: 17px;
  text-transform: uppercase; line-height: 1.05;
}
.step p { color: var(--c-muted); font-size: 14px; line-height: 1.55; }

/* included / credentials checklist */
.checks { display: grid; grid-template-columns: 1fr 1fr; gap: 12px var(--space-4); }
.checks li {
  display: flex; gap: 12px; align-items: baseline;
  font-size: 15px; border-bottom: 1px solid var(--c-line); padding-bottom: 12px;
}
.checks li::before {
  content: ""; flex: none; width: 18px; height: 18px;
  align-self: center;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232b5cff' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='m9 12 2 2 4-4'/></svg>") center / contain no-repeat;
}

/* ---- staff split: photo left, checkmark grid right ---- */
.staff-split {
  display: grid; grid-template-columns: 1fr 1.15fr;
  gap: var(--space-5); align-items: center;
}
.staff-split__media img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius);
}
.staff-title {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(30px, 4.2vw, 56px); text-transform: uppercase;
  line-height: .95; letter-spacing: -0.02em;
  margin: 10px 0 var(--space-4);
}
/* lead-in variant: a bold term, then the explanation.
   The base .checks li is a FLEX container, which is fine for a bare string but
   turns "<strong>Term</strong> – rest" into two side-by-side flex items, each
   in its own narrow column. So this variant goes back to normal flow and hangs
   the tick in the left gutter instead. */
.checks--lead li {
  display: block; position: relative;
  padding-left: 30px; line-height: 1.5;
}
.checks--lead li::before {
  position: absolute; left: 0; top: 3px;
  align-self: auto; margin: 0;
}
.checks--lead strong { font-weight: 800; }

/* pricing */
.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); }
.tier {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: var(--space-3); display: flex; flex-direction: column;
}
.tier--feature { border-color: var(--c-paper); }
.tier h3 {
  font-family: var(--font-display); font-weight: 800; font-size: 20px;
  text-transform: uppercase; line-height: 1; margin-bottom: 6px;
}
.tier__meta {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px; color: var(--c-muted);
}
.tier__price {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(30px, 3.4vw, 44px); line-height: 1; margin: var(--space-3) 0 6px;
}
.tier__sub { color: var(--c-muted); font-size: 13px; }
.tier ul { margin: var(--space-3) 0; display: grid; gap: 9px; flex: 1; }
.tier li { color: var(--c-muted); font-size: 14px; padding-bottom: 9px; border-bottom: 1px solid var(--c-line); }
.tier .btn { width: 100%; }

@media (max-width: 900px) { .steps { grid-template-columns: 1fr 1fr; } .tiers { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .steps { grid-template-columns: 1fr; } .checks { grid-template-columns: 1fr; } }

/* ============================================================
   CLASS LANDING PAGE — conversion layout
   ============================================================ */
/* alternating band to break up the flat black */
.band {
  background: #0e0e0d;
  border-block: 1px solid var(--c-line);
}

/* facts + CTA inside the video hero */
.hero-facts {
  display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4);
  margin-top: var(--space-4);
}
.hero-facts div { display: grid; gap: 3px; }
.hero-facts dt, .hero-facts .k {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .16em; font-size: 10px; color: rgba(244,242,238,.6);
}
.hero-facts .v {
  font-family: var(--font-display); font-weight: 800;
  font-size: 19px; text-transform: uppercase; line-height: 1;
}
/* the Partners cell carries a logo where its siblings carry a word, so the
   image is sized to sit on the same optical line as their 19px caps */
.fact-partner .v { display: flex; align-items: center; min-height: 19px; margin-top: -6px; }
.fact-logo { height: 34px; width: auto; display: block; }

.hero-cta { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }

/* gear / software strip */
.gear { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.gear span {
  border: 1px solid var(--c-line); border-radius: var(--radius);
  padding: 14px 18px; font-size: 14px; color: var(--c-paper);
  display: flex; align-items: center; gap: 10px;
}
.gear span::before { content: ""; width: 6px; height: 6px; background: var(--c-brand); border-radius: 50%; flex: none; }

/* ---- Dates & pricing, centred ---- */
.page-class #sessions .section-head {
  grid-template-columns: 1fr;
  justify-items: center; text-align: center;
}
.page-class #sessions .section-head h2,
.page-class #sessions .section-head > a { grid-column: 1; }
.page-class #sessions .section-head h2 { max-width: none; }
#sessions .ctable__note { text-align: center; margin-inline: auto; }

/* instructor strip */
.tutor-band { display: grid; grid-template-columns: auto 1fr auto; gap: var(--space-4); align-items: center; }
.tutor-band__name { font-family: var(--font-display); font-weight: 900; font-size: clamp(24px,2.6vw,36px); text-transform: uppercase; line-height: 1; }
.tutor-band p { color: var(--c-muted); font-size: 15px; max-width: 62ch; margin-top: 10px; }

@media (max-width: 900px) {
  .tutor-band { grid-template-columns: 1fr; gap: var(--space-3); }
}

/* ============================================================
   VIDEO-BACKGROUND PAGE HEADER (class pages)
   Drop a file at the <source> path and it plays; until then the
   section just shows the ink background.
   ============================================================ */
.page-hero--video {
  position: relative;
  padding-block: clamp(56px, 7.5vw, 110px) clamp(42px, 5.4vw, 76px);
  border-bottom: 1px solid var(--c-line);
  overflow: hidden;
}
.page-hero__media { position: absolute; inset: 0; z-index: 0; background: var(--c-ink); }
.page-hero__video { width: 100%; height: 100%; object-fit: cover; display: block; }
.page-hero__media::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(to top, rgba(10,10,10,.9) 0%, rgba(10,10,10,.45) 40%, rgba(10,10,10,.15) 75%),
    rgba(10,10,10,.35);
}
.page-hero--video .page-hero__inner { position: relative; z-index: 2; }
.page-hero--video h1 { margin-top: 12px; }
/* muted grey is unreadable over bright frames — lift the sub-copy */
.page-hero--video p { color: rgba(244,242,238,.92); }
.page-hero--video .eyebrow { color: rgba(244,242,238,.75); }
@media (prefers-reduced-motion: reduce) { .page-hero__video { display: none; } }

/* ============================================================
   IMAGE PLACEHOLDERS
   Swap the inner <span>s for <img src="media/…" alt="…" /> — it will cover the frame.
   ============================================================ */
.ph {
  position: relative;
  display: grid; place-items: center; align-content: center;
  background: linear-gradient(160deg, #171715, #0e0e0d);
  border: 1px dashed #2f2f2b;
  border-radius: var(--radius);
  overflow: hidden;
  text-align: center;
  color: var(--c-muted);
  font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: .22em; font-size: 11px;
}
/* .ph is position:relative and carries the aspect-ratio. Taking the media out
   of flow lets that ratio define the box — left in flow, a square photo's own
   intrinsic size wins and a 16:9 slot renders square. */
.ph img, .ph video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.ph__hint {
  display: block; margin-top: 7px;
  font-size: 10px; letter-spacing: .14em; color: #55524c; text-transform: none;
}
.ph--wide     { aspect-ratio: 21 / 9; }
.ph--16       { aspect-ratio: 16 / 9; }
.ph--square   { aspect-ratio: 1 / 1; }
.ph--portrait { aspect-ratio: 3 / 4; }

.gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
.gallery .ph__hint { display: none; }   /* too cramped in a 3-up */

/* ============================================================
   SPEED LESSON FEATURE (video + explainer)
   ============================================================ */
/* ---- speed lesson: copy left, video right ----
   Was a centred column with the video stacked above two paragraphs; the split
   matches the class-page intro so the two read as the same family. */
.lesson-split {
  display: grid;
  /* video leads, copy follows — the wider track is the first one now */
  grid-template-columns: 1.15fr 1fr;
  gap: var(--space-5); align-items: center;
}
.lesson-split__video { order: -1; }
.lesson-split__copy p {
  color: var(--c-muted); font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.65; max-width: 52ch; margin-bottom: var(--space-2);
}
.lesson-split__copy p.lead-note { color: rgba(244, 242, 238, .92); }
.lesson-split__video {
  position: relative; aspect-ratio: 16 / 9;
  border: 1px solid var(--c-line); border-radius: var(--radius);
  overflow: hidden; background: #0f0f0f;
  box-shadow: 0 30px 70px rgba(0, 0, 0, .45);
}
.lesson-split__video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* The speed-lesson band inside a content column rather than full-bleed, for
   the school pages. Same reasoning as .bonus--inline: it needs its own edges
   because nothing else is providing them. */
.lesson-band {
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-3);
  margin-top: var(--space-4);
}
.lesson-band .intro-title { font-size: clamp(24px, 3.2vw, 40px); }
@media (max-width: 900px) {
  .lesson-split { grid-template-columns: 1fr; gap: var(--space-3); }
  .lesson-split__copy p { max-width: none; }
}

/* ============================================================
   FINDER LAYOUT — list left, sticky map right
   ============================================================ */
.finder-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(300px, 400px);
  gap: var(--space-4);
  /* stretch, not start: the map column takes the row's height, which is set
     by the list beside it. The map used to be sized purely off the viewport,
     so a page with one class card left ~220px of dead space under it. */
  align-items: stretch;
}
.finder-grid .map-wrap {
  position: relative;
  margin-bottom: 0;
  /* The wrapper now spans the whole row so the map can stick inside it, which
     means its own border and rounded box would show as an empty bar above the
     map once it sticks. All visible chrome moves onto the map itself.
     overflow must not be hidden here either — that clips a sticky child. */
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: none;
}
/* Sticky moved onto the map itself. The wrapper now spans the whole row, so
   on the long classes list the map still follows the scroll inside it, while
   on a single-card page it simply matches the card and the gap disappears. */
.finder-grid #cityMap {
  position: sticky;
  top: calc(var(--header-h) + var(--space-2));
  height: min(62vh, 100%);
  min-height: 280px;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
}

/* ============================================================
   LOCATION MAP (Leaflet + OSM, dark-filtered)
   ============================================================ */
.map-wrap {
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: var(--space-3);
}
#cityMap {
  height: clamp(260px, 34vh, 420px); width: 100%;
  border: 0; display: block; background: #e8e6e1;
}
/* invert only the tiles — markers/popups live in other panes and stay correct */

/* ============================================================
   EVENT CARDS (classes.html — worldcup-style listing)
   ============================================================ */
.finder-count {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .16em; font-size: 12px; color: var(--c-muted);
  margin-bottom: var(--space-3);
}
.event-list { display: grid; gap: var(--space-2); }
.event {
  display: grid;
  grid-template-columns: 1.4fr .9fr auto;
  gap: var(--space-3);
  align-items: center;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  padding: var(--space-3);
  transition: border-color .2s ease;
}
.event:hover { border-color: var(--c-rule); }
.event.is-hidden, .city.is-hidden { display: none; }
.event h3 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(18px, 1.8vw, 24px); text-transform: uppercase;
  line-height: 1.05; letter-spacing: -0.01em;
}
.event__venue { margin-top: 8px; font-size: 14px; }
.event__venue .addr { color: var(--c-muted); display: block; font-size: 13px; margin-top: 2px; }
.event__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.event__note { color: var(--c-muted); font-size: 12px; margin-top: 10px; }

.event__facts { display: grid; gap: 10px; }
.event__facts div { display: flex; justify-content: space-between; gap: var(--space-2); border-bottom: 1px solid var(--c-line); padding-bottom: 8px; }
.event__facts .k {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px; color: var(--c-muted);
}
.event__facts .v { font-size: 14px; text-align: right; white-space: nowrap; }

.event__cta { display: grid; gap: 8px; justify-items: stretch; min-width: 190px; }
.event__cta .micro {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .12em; font-size: 10px; color: var(--c-muted); text-align: center;
}
/* The price on the provider pages was a 10px micro line while the class and
   camp cards led with the total. Same treatment here — it reuses the
   .city__amount/plus/via spans, minus the city card's divider rule. */
.event__price { display: grid; gap: 3px; text-align: center; }
.event__price .city__via { margin-top: 2px; }

/* ============================================================
   CLASS FINDER TABLE (classes.html)
   ============================================================ */
/* ---- program type tabs ----
   Deliberately heavier than the location chips below them: this is the first
   decision a parent makes, and the chips are a refinement inside it. */
.progtabs {
  display: inline-flex; gap: 4px; padding: 4px;
  border: 1px solid var(--c-line); border-radius: 999px;
  margin-bottom: var(--space-2);
}
.progtabs button {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .12em; font-size: 12px; font-weight: 700;
  color: var(--c-muted); background: transparent;
  border: none; border-radius: 999px;
  padding: 10px 20px; white-space: nowrap;
  transition: background .18s ease, color .18s ease;
}
.progtabs button:hover { color: var(--c-paper); }
.progtabs button[aria-selected="true"] {
  background: var(--c-paper); color: var(--c-ink);
}
.progtabs__blurb {
  font-size: 14px; color: var(--c-muted);
  max-width: 52ch; margin-bottom: var(--space-3);
}

.filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: var(--space-3); }
.filters button {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px; font-weight: 700;
  color: var(--c-paper); background: transparent;
  border: 1px solid var(--c-line); border-radius: 999px;
  padding: 8px 15px; transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.filters button:hover { border-color: var(--c-rule); }
.filters button[aria-pressed="true"] {
  background: var(--c-paper); color: var(--c-ink); border-color: var(--c-paper);
}

.ctable { width: 100%; border-collapse: collapse; }
.ctable th {
  text-align: left;
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .16em; font-size: 11px; color: var(--c-muted);
  font-weight: 700; padding: 0 var(--space-2) 12px 0;
  border-bottom: 1px solid var(--c-paper);
}
.ctable td { padding: 16px var(--space-2) 16px 0; border-bottom: 1px solid var(--c-line); vertical-align: middle; }
.ctable td:last-child, .ctable th:last-child { padding-right: 0; text-align: right; }
.ctable tr.is-hidden { display: none; }
.ctable .cls {
  font-family: var(--font-display); font-weight: 800;
  font-size: 17px; text-transform: uppercase; line-height: 1.1;
}
.ctable .where { font-size: 14px; }
.ctable .meta { font-size: 14px; color: var(--c-muted); white-space: nowrap; }
.ctable .btn { padding: 10px 20px; font-size: 11px; }
.ctable .soon {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 11px; color: var(--c-muted);
  border: 1px dashed #3a3a37; border-radius: var(--btn-radius);
  padding: 10px 16px; display: inline-block; white-space: nowrap;
}
.ctable__empty { color: var(--c-muted); font-size: 15px; padding: var(--space-4) 0; }
.ctable__note { color: var(--c-muted); font-size: 13px; margin-top: var(--space-3); max-width: 70ch; }

/* ============================================================
   RESPONSIVE — must stay LAST so these win over the base rules above
   ============================================================ */
@media (max-width: 760px) {
  .about-grid { grid-template-columns: 1fr; gap: var(--space-3); }
  .about__photo { aspect-ratio: 4/3; }
  .split { grid-template-columns: 1fr; gap: var(--space-4); }
  .grid-2, .howto { grid-template-columns: 1fr; }
  .gallery { grid-template-columns: 1fr 1fr; }
  .finder-grid { grid-template-columns: 1fr; }
  .finder-grid .map-wrap { position: static; order: -1; margin-bottom: var(--space-3); }
  .finder-grid #cityMap { height: clamp(240px, 32vh, 320px); }
  .ctable thead { display: none; }
  .ctable, .ctable tbody, .ctable tr, .ctable td { display: block; width: 100%; }
  .ctable tr {
    border: 1px solid var(--c-line); border-radius: var(--radius);
    padding: var(--space-2) var(--space-3); margin-bottom: var(--space-2);
  }
  .ctable td { border: none; padding: 7px 0; display: flex; justify-content: space-between; gap: var(--space-2); align-items: baseline; }
  .ctable td::before {
    content: attr(data-label);
    font-family: var(--font-label); text-transform: uppercase;
    letter-spacing: .14em; font-size: 11px; color: var(--c-muted); flex: none;
  }
  .ctable td.cls { display: block; padding-top: 4px; }
  .ctable td.cls::before { content: none; }
  .ctable td:last-child { text-align: left; padding-top: var(--space-2); }
  .ctable td:last-child::before { content: none; }
  .ctable .btn, .ctable .soon { width: 100%; text-align: center; }
  .event { grid-template-columns: 1fr; gap: var(--space-2); }
  .event__tags { display: none; }   /* duplicates the facts rows when stacked */
  .event__cta { min-width: 0; }
  .event__facts .v { white-space: normal; }
  .bonus__body { grid-template-columns: 1fr; gap: var(--space-3); text-align: center; }
  .bonus p { margin-inline: auto; }
}
/* sm:grid-cols-2 lg:grid-cols-3 */
@media (max-width: 900px) { .feat-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) {
  .feat-grid { grid-template-columns: 1fr; }
  /* p-12 was sized for a wide grid; at 375px it leaves 245px for the text */
  .feat { padding: var(--space-3); }
}


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

/* ============================================================
   CLASS PAGES — craft pass
   Fixes the "template" tells: uniform section rhythm, everything
   boxed in 1px rectangles, flat type scale, zero motion.
   ============================================================ */

/* ---- 1. asymmetric section heads with real type contrast ----
   label sits in a narrow left rail, heading runs large beside it */
/* The 190px first column used to hold the section eyebrow. With the eyebrows
   gone the rail is empty, and it left every heading indented 190px from the
   content beneath it — so the heading now starts at the wrap edge. */
.page-class .section-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: var(--space-3);
  border-bottom: none;
  padding-bottom: 0;
  margin-bottom: var(--space-5);
}
.page-class .section-head > div:first-child { display: contents; }
.page-class .section-head h2 {
  grid-column: 1;
  font-size: clamp(30px, 4.2vw, 60px);
  line-height: .95;
  letter-spacing: -0.025em;
  max-width: 16ch;
}
.page-class .section-head > a { grid-column: 2; }
.page-class .section-head .link-arrow { align-self: end; }

/* ---- 2. feature steps (port of the FeatureSteps React block) ----
   Its Tailwind tokens map onto ours: primary -> red, primary-foreground ->
   paper, muted-foreground -> muted, background -> ink. The framer-motion
   enter/exit is done with three states instead of a library: panels rest
   BELOW the frame, the active one sits at zero, and the one being replaced
   is pushed ABOVE — which is what y:100 -> 0 -> -100 was doing. */
.fsteps {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--space-4); align-items: center;
}
.fsteps__list { display: grid; gap: var(--space-4); list-style: none; margin: 0; padding: 0; }
.fstep {
  display: flex; align-items: center; gap: var(--space-3);
  opacity: .3;                       /* animate opacity 0.3 -> 1 */
  transition: opacity .5s ease;
}
.fstep.is-active { opacity: 1; }
.fstep__dot {
  flex: none; width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  border: 2px solid var(--c-rule); background: var(--c-line);
  color: var(--c-paper);
  font-family: var(--font-label); font-weight: 700; font-size: 15px;
  cursor: pointer; padding: 0;
  /* a real button, so the rotation is pausable by keyboard and touch too —
     the React original had no control at all, which fails WCAG 2.2.2 */
  transition: transform .5s ease, background .5s ease, border-color .5s ease;
}
.fstep__dot:focus-visible { outline: 2px solid var(--c-paper); outline-offset: 3px; }
/* The icon carries its own circle, so the button's ring and fill step aside
   once it shows — otherwise the dot renders two concentric rings. Pending
   steps keep the CSS ring, since they show a number and have no icon. */
.fstep.is-active .fstep__dot,
.fstep.is-done .fstep__dot {
  background: transparent; border-color: transparent;
  color: var(--c-brand);
}
.fstep.is-active .fstep__dot { transform: scale(1.1); }
/* The numeral's line box is centred by place-items, but a digit has no
   descender, so its ink sits ~0.19em below the box centre and reads low in
   the circle. Measured: ink centre 4.89px above baseline vs box centre 7.50px
   at 14px. Same correction the buttons make with --btn-cap-shift. */
.fstep__n { line-height: 1; transform: translateY(-0.186em); }
.fstep__check { display: none; width: 100%; height: 100%; overflow: visible; }
.fstep.is-active .fstep__n, .fstep.is-done .fstep__n { display: none; }
.fstep.is-active .fstep__check, .fstep.is-done .fstep__check { display: block; }
.fstep h3 {
  font-family: var(--font-display); font-weight: 800; text-transform: uppercase;
  font-size: clamp(18px, 1.8vw, 25px); line-height: 1.1;
  letter-spacing: -0.01em; margin-bottom: 6px;
}
.fstep p { color: var(--c-muted); font-size: clamp(14px, 1.1vw, 17px); line-height: 1.5; }

.fsteps__media {
  position: relative; overflow: hidden;
  border-radius: var(--radius);
  height: clamp(200px, 30vw, 400px);
  perspective: 1000px;      /* without depth the rotateX reads as a flat squash */
}
.fsteps__panel {
  position: absolute; inset: 0;
  opacity: 0; transform: translateY(100px) rotateX(-20deg);
  transition: opacity .5s ease-in-out, transform .5s ease-in-out;
}
.fsteps__panel.is-active { opacity: 1; transform: none; }
.fsteps__panel.is-leaving { opacity: 0; transform: translateY(-100px) rotateX(20deg); }
.fsteps__panel .ph {
  width: 100%; height: 100%; aspect-ratio: auto;
  border-radius: 0; border: none;
}
.fsteps__panel .ph img, .fsteps__panel .ph video { width: 100%; height: 100%; object-fit: cover; }
/* The panels hold real images now, as direct children rather than inside a
   .ph placeholder, so the rule above stopped matching and they were laid out
   unsized at object-fit: fill. These are screenshots where the whole frame is
   the point, hence contain rather than cover — cropping a Spotify page or a
   Splice screen to fill a 2:1 box just cuts the content off. */
.fsteps__panel > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  object-position: center;
}
/* No bottom scrim. It existed to blend a full-bleed photo into the page; over
   a contained screenshot it reads as a black bar across the bottom. */
@media (prefers-reduced-motion: reduce) {
  .fstep, .fstep__dot, .fsteps__panel { transition: none; }
  .fsteps__panel { transform: none; }
}

/* ---- 3. de-boxed gear: one editorial row, dot separators ---- */
.page-class .gear { gap: 0 var(--space-3); align-items: baseline; }
.page-class .gear span {
  border: none; border-radius: 0; padding: 6px 0;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(15px, 1.5vw, 21px); text-transform: uppercase;
  letter-spacing: -0.01em;
}
.page-class .gear span::before {
  width: 5px; height: 5px; margin-right: 4px;
  background: var(--c-brand); opacity: .9;
}

/* ---- 4. hero facts on a hairline rail ---- */
.page-class .hero-facts { gap: 0; border-top: 1px solid rgba(244,242,238,.25); margin-top: var(--space-5); }
.page-class .hero-facts div { padding: var(--space-2) var(--space-4) 0 0; }
.page-class .hero-facts div + div {
  padding-left: var(--space-4);
  border-left: 1px solid rgba(244,242,238,.16);
}
.page-class .hero-facts .v { font-size: clamp(17px, 1.7vw, 22px); }

/* ---- 6. motion: arrows travel, not just recolour ---- */
.page-class .btn span[aria-hidden] { transition: transform .22s cubic-bezier(.2,.7,.3,1); display: inline-block; }
.page-class .btn:hover span[aria-hidden] { transform: translateX(4px); }

/* ---- 7. scroll reveal (JS adds .is-in) ---- */
.reveal { opacity: 0; transform: translateY(16px); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity .7s cubic-bezier(.2,.7,.3,1), transform .7s cubic-bezier(.2,.7,.3,1);
  transition-delay: var(--d, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.is-in { opacity: 1; transform: none; transition: none; }
}

/* ---- 8. sticky enrol bar, appears once the hero is past ---- */
.enrol-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  background: rgba(10,10,10,.92);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--c-line);
  transform: translateY(105%);
  transition: transform .35s cubic-bezier(.2,.7,.3,1);
}
.enrol-bar.is-up { transform: none; }
.enrol-bar__inner {
  max-width: var(--maxw); margin-inline: auto;
  padding: 12px var(--space-3);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
}
.enrol-bar__what { display: grid; gap: 2px; min-width: 0; }
.enrol-bar__name {
  font-family: var(--font-display); font-weight: 800;
  font-size: 15px; text-transform: uppercase; line-height: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.enrol-bar__meta {
  font-family: var(--font-label); text-transform: uppercase;
  letter-spacing: .14em; font-size: 10px; color: var(--c-muted);
}
.enrol-bar .btn { padding-block: 10px; flex: none; }

@media (max-width: 900px) {
  .page-class .section-head { grid-template-columns: 1fr; gap: var(--space-2); }
  /* the desktop head puts the link in column 2; leaving that in place here
     would spawn an implicit column and squeeze the heading beside it */
  .page-class .section-head h2,
  .page-class .section-head > a { grid-column: 1; }
  .page-class .hero-facts div + div { padding-left: 0; border-left: none; }
  .page-class .hero-facts div { padding-right: var(--space-3); }
}

/* ---- card strip: below 900px the seams turn horizontal, so the rounding
   moves from the left/right ends to the top/bottom ones ---- */
@media (max-width: 900px) {
  .card-strip { flex-direction: column; }
  /* flex:1 1 0 sized the panels along the row axis; once the direction flips
     that basis applies to height and every card collapses to its borders */
  .card-strip .course { flex: 0 0 auto; }
  .card-strip .course + .course { margin-left: 0; margin-top: -1px; }
  .card-strip .course:first-child {
    border-radius: var(--radius) var(--radius) 0 0;
  }
  .card-strip .course:last-child {
    border-radius: 0 0 var(--radius) var(--radius);
  }
}
@media (max-width: 480px) {
  .card-strip .course__actions { flex-direction: column; }
}

/* ---- feature steps: single column below 900px. The source put the media
   first on mobile and second on desktop (order-1 md:order-2), so the image
   leads on a phone rather than sitting under three paragraphs. ---- */
@media (max-width: 900px) {
  .fsteps { grid-template-columns: 1fr; gap: var(--space-3); }
  .fsteps__media { order: -1; }
  .fsteps__list { gap: var(--space-3); }
}
@media (max-width: 560px) {
  .fstep { gap: var(--space-2); }
  .fstep__dot { width: 38px; height: 38px; font-size: 14px; }
}

/* ---- class-page intro: stack below 900px. Without this the two columns hold
   at any width and collapse to ~150px each on a phone. ---- */
@media (max-width: 900px) {
  .intro-split { grid-template-columns: 1fr; gap: var(--space-3); }
  .intro-split__copy p { max-width: none; }
  .intro-split__media img { aspect-ratio: 4 / 3; }
}

/* ---- program fee cards: 3 → 2 → 1 across ---- */
@media (max-width: 900px) {
  .fees { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 620px) {
  .fees { grid-template-columns: 1fr; }
}

/* ---- program tabs: the labels stop fitting side by side on a phone ----
   `1 1 auto`, not `1 1 0`: with three tabs, equal thirds would give "All" a
   column it does not need and wrap "After School Programs" onto three lines.
   Sizing to content first shares the slack where it is actually wanted. */
@media (max-width: 480px) {
  .progtabs { display: flex; width: 100%; border-radius: 14px; }
  .progtabs button { flex: 1 1 auto; padding: 10px 10px; letter-spacing: .04em; font-size: 11px; white-space: normal; border-radius: 11px; }
}

/* ---- staff split: stack the photo above the list on narrow screens ---- */
@media (max-width: 900px) {
  .staff-split { grid-template-columns: 1fr; gap: var(--space-4); }
  .staff-split__media img { aspect-ratio: 16 / 9; }
}

/* ---- contact form: stack the aside above the card on narrow screens ---- */
@media (max-width: 900px) {
  .enquire-grid { grid-template-columns: 1fr; gap: var(--space-4); }
}
@media (max-width: 560px) {
  .enquire-card { padding: var(--space-3); }
  .form__row { grid-template-columns: 1fr; }
}

/* ---- reCAPTCHA is a fixed 304x78 iframe and cannot be made fluid, so it is
   scaled down on the narrowest screens rather than allowed to overflow. ---- */
@media (max-width: 420px) {
  .field--captcha {
    transform: scale(.88);
    transform-origin: left top;
    min-height: 0;
    height: 69px;                /* 78 * .88, so the scale leaves no dead gap */
  }
}

/* ---- city cards: the register pill drops under the class name on a phone ---- */
@media (max-width: 560px) {
  .city__classes li { flex-direction: column; align-items: flex-start; gap: 10px; }
  .city__classes a { align-self: stretch; text-align: center; }
}

/* ---- course dates: drop to the short date form and hide the venue column
   on a phone, where every row repeats the same location anyway ---- */
@media (max-width: 700px) {
  .cd__long  { display: none; }
  .cd__short { display: inline; }
  .cd__where, .cd th:last-child { display: none; }
  .cd td, .cd th { padding-inline: 10px; }
  .cd__n { padding-left: var(--space-2); }
}

/* ---- city card: the two actions stack with the card on a phone ---- */
@media (max-width: 560px) {
  .city__actions { width: 100%; }
  .city__actions a,
  .city__actions .city__closed { flex: 1 1 0; text-align: center; }
}

/* The class blurb on a school page. Sits under the tags, above the "no class
   on…" note, because it is the pitch and that is the logistics. */
.event__desc {
  margin-top: 10px;
  font-size: 15px;
  line-height: 1.55;
  max-width: 54ch;
}
