/* ==========================================================================
   Flawless Gymnastics — flawlessrhythmic.com
   Plain CSS, no build step. Uses 2026-Baseline features: cascade layers,
   native nesting, oklch(), container queries, :has(), and scroll-driven
   animations behind @supports (Firefox has not shipped those — the site is
   complete and readable without them).

   Palette sampled from the client's real logo files 2026-08-24.
   CONTRAST RULE: --pink fails WCAG on cream (2.35:1) and white fails on
   --pink (2.59:1). --pink is for fills, rules and decorative art only.
   All text and buttons use --pink-deep (5.66:1 on white, 5.14:1 on cream).
   ========================================================================== */

@layer reset, tokens, base, layout, components, utilities;

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }
  html { -webkit-text-size-adjust: 100%; }
  body { -webkit-font-smoothing: antialiased; }
  img, picture, svg { display: block; max-width: 100%; }
  /* Let width/aspect-ratio drive sizing. Without this, the HTML height
     attribute is a used value and aspect-ratio is silently ignored.
     Applies to <video> for exactly the same reason — a 1024-tall attribute
     stretched the 9:16 players into 9:30 letterboxes. */
  img, video { height: auto; }
  button, input, select, textarea { font: inherit; color: inherit; }
  h1, h2, h3, h4 { text-wrap: balance; }
  p, li { text-wrap: pretty; }
}

@layer tokens {
  :root {
    /* Brand — verified from assets/logo-*.jpg */
    --cream: #F5F4F0;
    --pink: #FF70A6;
    --pink-deep: #C41E63;
    --ink: #2B2422;

    --cream-warm: color-mix(in oklab, var(--cream) 92%, var(--pink) 8%);
    --cream-deep: color-mix(in oklab, var(--cream) 84%, var(--pink) 16%);
    --ink-soft: color-mix(in oklab, var(--ink) 72%, var(--cream) 28%);
    --rule: color-mix(in oklab, var(--pink) 28%, var(--cream) 72%);
    /* SRG Academy's own mark is gold. MEASURED: #C6B299 is 1.87:1 on cream —
       it FAILS as text there, exactly like --pink. Gold is decorative, or
       text on --ink only (7.42:1). */
    --gold: #C6B299;

    /* Program accents, taken from the client's own schedule graphics */
    --a-little-stars: #E8407C;
    --a-recreational: #7B3FA0;
    --a-preteam:      #2C74C4;
    --a-l3:           #3E9B4F;
    --a-l4:           #C8912E;
    --a-l5:           #D2662A;
    --a-l67:          #7B4FA8;

    --serif: "Playfair Display", "Didot", "Bodoni MT", Georgia, serif;
    --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

    /* Fluid type — 320px to 1280px viewport */
    --step--1: clamp(0.83rem, 0.79rem + 0.2vw, 0.94rem);
    --step-0:  clamp(1rem, 0.95rem + 0.25vw, 1.13rem);
    --step-1:  clamp(1.2rem, 1.11rem + 0.44vw, 1.5rem);
    --step-2:  clamp(1.44rem, 1.28rem + 0.8vw, 2rem);
    --step-3:  clamp(1.73rem, 1.45rem + 1.4vw, 2.66rem);
    --step-4:  clamp(2.07rem, 1.6rem + 2.36vw, 3.55rem);
    --step-5:  clamp(2.49rem, 1.71rem + 3.9vw, 4.74rem);

    --gutter: clamp(1.25rem, 4vw, 2.5rem);
    --measure: 62ch;
    --wrap: 1180px;
    --radius: 1.25rem;

    --shadow-sm: 0 1px 2px oklch(0 0 0 / .04), 0 4px 12px oklch(0 0 0 / .05);
    --shadow-md: 0 2px 4px oklch(0 0 0 / .05), 0 12px 32px oklch(0 0 0 / .08);

    --ease: cubic-bezier(.22, .61, .36, 1);
  }
}

@layer base {
  html { scroll-behavior: smooth; }

  body {
    background: var(--cream);
    color: var(--ink);
    font-family: var(--sans);
    font-size: var(--step-0);
    line-height: 1.65;
  }

  h1, h2, h3 {
    font-family: var(--serif);
    font-weight: 500;
    line-height: 1.08;
    letter-spacing: -0.015em;
  }

  a { color: var(--pink-deep); text-underline-offset: 0.2em; }
  a:hover { text-decoration-thickness: 2px; }

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

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

  .skip {
    position: absolute;
    inset-inline-start: -9999px;
    top: 0;
    z-index: 100;
    background: var(--pink-deep);
    color: #fff;
    padding: 0.75rem 1.25rem;
    border-radius: 0 0 8px 0;

    &:focus { inset-inline-start: 0; }
  }

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

@layer layout {
  .wrap {
    width: min(100% - (var(--gutter) * 2), var(--wrap));
    margin-inline: auto;
  }

  .section {
    padding-block: clamp(3.5rem, 9vw, 7rem);
    position: relative;
  }

  .section-head {
    text-align: center;
    margin-bottom: clamp(2rem, 5vw, 3.5rem);

    & .eyebrow { margin-bottom: 0.75rem; }
    & > p {
      max-width: 52ch;
      margin-inline: auto;
      margin-top: 1rem;
      color: var(--ink-soft);
    }
  }

}

@layer components {

  /* ---------- Buttons ---------- */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.9rem 1.6rem;
    border-radius: 999px;
    border: 2px solid transparent;
    font-weight: 600;
    font-size: var(--step-0);
    text-decoration: none;
    cursor: pointer;
    transition: transform .2s var(--ease), background-color .2s var(--ease),
                box-shadow .2s var(--ease);

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

  .btn--primary {
    background: var(--pink-deep);
    color: #fff;
    box-shadow: var(--shadow-sm);

    &:hover {
      background: color-mix(in oklab, var(--pink-deep) 88%, #000 12%);
      box-shadow: var(--shadow-md);
    }
  }

  .btn--ghost {
    border-color: var(--pink-deep);
    color: var(--pink-deep);
    background: transparent;

    &:hover { background: color-mix(in oklab, var(--pink) 12%, transparent); }
  }

  .btn--sm { padding: 0.6rem 1.15rem; font-size: var(--step--1); }

  /* ---------- Header ---------- */
  .site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: color-mix(in oklab, var(--cream) 88%, transparent);
    backdrop-filter: blur(12px) saturate(1.4);
    border-bottom: 1px solid transparent;
    transition: border-color .3s var(--ease);

    /* Draws a hairline only once the page has scrolled */
    @supports (animation-timeline: scroll()) {
      animation: header-line steps(1) both;
      animation-timeline: scroll(root block);
      animation-range: 20px 21px;
    }
  }

  @keyframes header-line {
    to { border-bottom-color: var(--rule); }
  }

  .site-header > .wrap {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-height: 4.5rem;

    /* The header carries nine items and the wordmark; the 1180px content
       measure is 44px too narrow for that row, and no viewport width helps
       because .wrap is capped. The header alone gets a wider measure. */
    --wrap: 78rem;
  }

  .brand {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-height: 44px;
    min-width: 0;

    @media (width >= 78rem) { flex: none; }
    text-decoration: none;
    color: var(--ink);
    margin-inline-end: auto;

    & img { width: 42px; height: 42px; border-radius: 50%; }

    & b {
      font-family: var(--serif);
      font-size: clamp(1.05rem, 0.9rem + 0.5vw, 1.3rem);
      font-weight: 600;
      line-height: 1.05;
      letter-spacing: 0.01em;

      /* Only the desktop row needs a single line; on a phone it may wrap. */
      @media (width >= 78rem) { white-space: nowrap; }
    }
    & span {
      display: block;
      font-size: 0.63rem;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--ink-soft);
      margin-top: 2px;
    }
  }

  .nav {
    display: flex;
    align-items: center;
    gap: clamp(0.6rem, 1.1vw, 1.05rem);

    & a {
      text-decoration: none;
      color: var(--ink);
      font-size: 0.82rem;
      font-weight: 500;
      letter-spacing: 0.005em;
      display: inline-flex;
      align-items: center;
      min-height: 44px;
      /* Eight items in one row will squeeze until labels break across two
         lines ("Program and / Schedule"), which reads as clutter. In the
         vertical popover the opposite is true — labels must be free to wrap. */
      @media (width >= 78rem) {
        white-space: nowrap;
        flex: none;
      }

      &:hover { color: var(--pink-deep); }
      &[aria-current="page"] {
        color: var(--pink-deep);
        text-decoration: underline;
        text-decoration-thickness: 2px;
        text-underline-offset: 0.35em;
      }
    }
  }

  .nav-toggle { display: none; }

  /* Mobile nav uses the native popover API — zero JavaScript.
     Threshold is 78rem: with nine items the row needs ~1175px, so anything
     narrower squeezes labels or overflows. Below this everything lives in the
     popover, which holds any number of items comfortably. */
  @media (width < 78rem) {
    .nav-toggle {
      display: inline-flex;
      align-items: center;
      gap: 0.5rem;
      background: transparent;
      border: 1px solid var(--rule);
      border-radius: 999px;
      padding: 0.5rem 0.95rem;
      min-height: 44px;
      font-size: var(--step--1);
      font-weight: 600;
      color: var(--ink);
      cursor: pointer;
    }

    .nav[popover]:not(:popover-open) { display: none; }

    .nav[popover] {
      position: fixed;
      inset: auto 0 0 0;
      width: 100%;
      max-width: none;
      margin: 0;
      border: 0;
      border-radius: var(--radius) var(--radius) 0 0;
      background: var(--cream);
      box-shadow: 0 -8px 40px oklch(0 0 0 / .16);
      padding: 1.5rem var(--gutter) 2rem;
      flex-direction: column;
      align-items: stretch;
      gap: 0;

      &::backdrop { background: oklch(0 0 0 / .3); backdrop-filter: blur(2px); }

      /* :not(.btn) so the CTA keeps the sans button styling */
      & a:not(.btn) {
        font-size: var(--step-1);
        font-family: var(--serif);
        padding-block: 0.85rem;
        border-bottom: 1px solid var(--rule);
      }
      & .nav__portal { margin-top: 1rem; justify-content: center; }
    }
  }

  /* Above the mobile breakpoint the nav is a plain flex row again. The
     `popover` attribute stays on the element, so the UA styles it as a
     fixed, bordered, centred dialog — every one of those has to be undone
     explicitly or the desktop header collapses into a floating box. */
  @media (width >= 78rem) {
    .nav[popover] {
      position: static;
      inset: auto;
      display: flex;
      inline-size: auto;
      block-size: auto;
      max-inline-size: none;
      max-block-size: none;
      margin: 0;
      padding: 0;
      border: 0;
      background: none;
      box-shadow: none;
      overflow: visible;
      color: inherit;
    }
    .nav[popover]::backdrop { display: none; }
  }

  /* ---------- Hero ---------- */
  .hero {
    position: relative;
    overflow: clip;
    padding-block: clamp(3rem, 8vw, 6rem) clamp(3.5rem, 9vw, 6.5rem);
    text-align: center;
    isolation: isolate;
  }

  .hero__wash {
    position: absolute;
    inset: 0;
    z-index: -1;
    object-fit: cover;
    width: 100%;
    height: 100%;
    opacity: 0.34;
    mask-image: radial-gradient(ellipse 92% 70% at 50% 30%, #000 18%, transparent 72%);
  }

  .hero__badge {
    width: clamp(112px, 22vw, 168px);
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: 50%;
    margin-inline: auto;
    margin-bottom: clamp(1.25rem, 3vw, 2rem);
    filter: drop-shadow(0 8px 24px oklch(0 0 0 / .1));
  }

  .hero h1 {
    font-size: var(--step-5);
    max-width: 18ch;
    margin-inline: auto;

    & em {
      font-style: italic;
      color: var(--pink-deep);
    }
  }

  .hero__sub {
    font-size: var(--step-1);
    color: var(--ink-soft);
    max-width: 46ch;
    margin: 1.4rem auto 0;
  }

  .hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    justify-content: center;
    margin-top: clamp(1.75rem, 4vw, 2.5rem);
  }

  .hero__note {
    margin-top: 1.25rem;
    font-size: var(--step--1);
    color: var(--ink-soft);
  }

  /* ---------- The ribbon: the site's signature device ----------
     One continuous path threading the page, drawn on scroll.
     pathLength="1" lets us dash it without measuring in JS.        */
  .ribbon {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 50%;
    translate: -50% 0;
    width: min(120%, 1400px);
    height: 100%;
    z-index: -1;
    pointer-events: none;
    overflow: visible;
  }

  .ribbon path {
    fill: none;
    stroke: var(--pink);
    stroke-width: 2.5;
    stroke-linecap: round;
    opacity: 0.38;   /* it crosses body copy, so it stays a whisper */
  }

  @supports (animation-timeline: view()) {
    .ribbon path {
      stroke-dasharray: 1;
      stroke-dashoffset: 1;
      animation: ribbon-draw linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 62%;
    }
  }

  @keyframes ribbon-draw {
    to { stroke-dashoffset: 0; }
  }

  /* ---------- Pathway / program tiers ---------- */
  .tier {
    & + .tier { margin-top: clamp(2.5rem, 6vw, 4rem); }
  }

  /* The tier heading doubles as a link to the SRG page — give it a real
     target height rather than relying on the heading's line box. */
  .tier__head h3 a {
    display: inline-block;
    padding-block: 0.45rem;
    text-decoration: none;

    &:hover { text-decoration: underline; text-underline-offset: 0.15em; }
  }

  .tier__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem 1rem;
    padding-bottom: 0.9rem;
    margin-bottom: 1.75rem;
    border-bottom: 2px solid var(--rule);

    & h3 { font-size: var(--step-3); }
    & p {
      color: var(--ink-soft);
      font-size: var(--step--1);
      margin-inline-start: auto;
    }
  }

  .cards {
    display: grid;
    gap: 1.1rem;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  }

  /* The five competitive levels never tile evenly: auto-fit gives four
     columns past 1280px, stranding one card alone in a four-wide row.
     Capping at three yields a balanced 3 + 2. */
  .cards--levels {
    @media (width >= 64rem) { grid-template-columns: repeat(3, 1fr); }
  }

  /* Exactly four items: 1 / 2 / 4 never strands one on its own row. */
  .cards--four {
    @media (width >= 40rem) { grid-template-columns: repeat(2, 1fr); }
  }

  .card {
    --accent: var(--pink-deep);
    container-type: inline-size;
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    background: #fff;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    padding: 1.5rem 1.4rem 1.4rem;
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: transform .25s var(--ease), box-shadow .25s var(--ease);

    /* the program's color rail */
    &::before {
      content: "";
      position: absolute;
      inset-block: 0;
      inset-inline-start: 0;
      width: 5px;
      background: var(--accent);
    }

    &:hover {
      transform: translateY(-4px);
      box-shadow: var(--shadow-md);
    }

    /* Whole card is clickable via the stretched link on the title */
    &:has(a:focus-visible) {
      outline: 3px solid var(--pink-deep);
      outline-offset: 3px;
    }

    & h4 {
      font-family: var(--serif);
      font-size: var(--step-2);
      font-weight: 500;
      line-height: 1.1;
    }

    & .card__who {
      font-size: var(--step--1);
      font-weight: 600;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--accent);
    }

    & dl {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 0.3rem 0.9rem;
      font-size: var(--step--1);
      margin-top: 0.35rem;
      padding-top: 0.85rem;
      border-top: 1px solid var(--rule);
    }
    & dt { font-weight: 600; color: var(--ink-soft); }
    & dd { margin: 0; }

    /* A sub-heading inside the definition list: spans both columns and
       separates the schedule block from the dates above it. */
    & .times-head {
      grid-column: 1 / -1;
      margin-top: 0.5rem;
      padding-top: 0.6rem;
      border-top: 1px solid var(--rule);
      color: var(--accent);
      font-size: 0.72rem;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }
    & .times-head + dd { display: none; }
    & .times-head ~ dd { white-space: nowrap; }

    & .card__link {
      margin-top: auto;
      padding-top: 1rem;
      font-weight: 600;
      font-size: var(--step--1);
      text-decoration: none;

      &::after { content: " →"; }
      &:hover { text-decoration: underline; }
    }
  }

  /* ---------- Why / value props ---------- */
  .why {
    background: var(--cream-warm);
    border-block: 1px solid var(--rule);
  }

  .why__list {
    list-style: none;
    padding: 0;
    display: grid;
    gap: 1rem;
    /* 20rem caps this at three columns on the widest layout. At 15rem a
       1180px row fitted four, which shrank every photo and made a
       five-photo group end 4 + 1. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));

    /* Five points: cap at three so it reads 3 + 2, not 4 + 1. */
    @media (width >= 64rem) { grid-template-columns: repeat(3, 1fr); }
    counter-reset: why;
  }

  .why__list li {
    counter-increment: why;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1.5rem 1.35rem;
    background: color-mix(in oklab, #fff 72%, transparent);
    border-radius: var(--radius);
    border: 1px solid color-mix(in oklab, var(--rule) 60%, transparent);

    &::before {
      content: counter(why, decimal-leading-zero);
      font-family: var(--serif);
      font-size: var(--step-2);
      color: var(--pink);
      line-height: 1;
    }

    & b { font-size: var(--step-1); font-family: var(--serif); font-weight: 500; }
  }

  /* ---------- Coach strip ---------- */
  .coach {
    display: grid;
    gap: clamp(1.5rem, 4vw, 3rem);
    align-items: center;
    grid-template-columns: 1fr;

    @media (width >= 48rem) {
      grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    }
  }

  /* Holds a real photograph now. The old placeholder styling (grid
     centring, 2rem padding, a gradient ground and a max-height cap)
     shrank the photo to a thumbnail floating in a coloured box. */
  .coach__portrait {
    aspect-ratio: 4 / 5;
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow-md);
  }

  .coach__body {
    & h3 { font-size: var(--step-3); }
    & .coach__role {
      color: var(--pink-deep);
      font-weight: 600;
      font-size: var(--step-0);
      margin-top: 0.5rem;
      max-width: 34ch;
    }
    & p { margin-top: 1rem; max-width: var(--measure); color: var(--ink-soft); }
    & .btn { margin-top: 1.5rem; }
  }

  /* ---------- Visit ---------- */
  .visit {
    display: grid;
    gap: clamp(1.5rem, 4vw, 3rem);
    grid-template-columns: 1fr;

    @media (width >= 48rem) { grid-template-columns: 1fr 1fr; }
  }

  .visit address {
    font-style: normal;
    font-size: var(--step-1);
    line-height: 1.5;
  }

  .visit__meta {
    margin-top: 1.5rem;
    display: grid;
    gap: 0.75rem;
    font-size: var(--step--1);

    & > div { display: flex; gap: 0.75rem; align-items: center; }
    & dt { font-weight: 600; min-width: 6.5rem; }
    & a { display: inline-flex; align-items: center; min-height: 44px; }
  }

  .map-frame {
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--cream-warm);
    min-height: 18rem;

    & iframe { display: block; width: 100%; height: 100%; min-height: 18rem; border: 0; }
  }

  /* ---------- Final CTA ---------- */
  .cta-band {
    background: var(--ink);
    color: var(--cream);
    text-align: center;

    & h2 {
      font-size: var(--step-4);
      max-width: 20ch;
      margin-inline: auto;
      /* --pink is legible at display size on the dark ink ground */
      & em { font-style: italic; color: var(--pink); }
    }
    & p {
      margin: 1.25rem auto 0;
      max-width: 48ch;
      color: color-mix(in oklab, var(--cream) 78%, var(--ink) 22%);
    }
    & .btn--primary {
      margin-top: 2rem;
      background: var(--pink);
      color: var(--ink); /* dark on pink = 5.89:1, passes AA */
      &:hover { background: color-mix(in oklab, var(--pink) 85%, #fff 15%); }
    }
  }

  /* ---------- Footer ---------- */
  .site-footer {
    background: var(--cream-warm);
    border-top: 1px solid var(--rule);
    padding-block: clamp(2.5rem, 6vw, 4rem) 2rem;
    font-size: var(--step--1);

    & .cols {
      display: grid;
      gap: 2rem;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
    }

    & h4 {
      font-size: var(--step--1);
      letter-spacing: 0.14em;
      text-transform: uppercase;
      color: var(--ink-soft);
      margin-bottom: 0.85rem;
    }

    & ul { list-style: none; padding: 0; display: grid; }
    & li { display: flex; }
    & a {
      color: var(--ink);
      text-decoration: none;
      padding-block: 0.6rem;
      min-height: 44px;
      display: inline-flex;
      align-items: center;

      &:hover { color: var(--pink-deep); text-decoration: underline; }
    }

    & .colophon {
      margin-top: 2.5rem;
      padding-top: 1.5rem;
      border-top: 1px solid var(--rule);
      display: flex;
      flex-wrap: wrap;
      gap: 0.5rem 1.5rem;
      color: var(--ink-soft);
    }
  }

  /* ---------- Interior page hero ---------- */
  .page-hero {
    padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(2rem, 5vw, 3.5rem);
    background: var(--cream-warm);
    border-bottom: 1px solid var(--rule);
    text-align: center;

    & h1 { font-size: var(--step-4); max-width: 20ch; margin-inline: auto; }
    & > .wrap > p {
      max-width: 54ch;
      margin: 1.1rem auto 0;
      color: var(--ink-soft);
      font-size: var(--step-1);
    }
  }

  /* ---------- Season schedule table ----------
     8 columns will never fit a phone, so the table scrolls inside its own
     container and the program column stays pinned. */
  .table-scroll {
    overflow-x: auto;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    background: #fff;
    -webkit-overflow-scrolling: touch;
  }

  .schedule {
    border-collapse: collapse;
    width: 100%;
    /* 46rem suits the 7-column season table. A 3-column events table forced to
       the same width scrolls sideways for no reason, so pages override it. */
    min-width: var(--table-min, 46rem);
    font-size: var(--step--1);
    font-variant-numeric: tabular-nums;

    & th, & td {
      padding: 0.85rem 0.9rem;
      text-align: left;
      vertical-align: top;
      border-bottom: 1px solid var(--rule);

      /* Tighter gutters on a phone: a 3-column table missed fitting by 7px. */
      @media (width < 40rem) { padding-inline: 0.6rem; }
    }

    /* Stacking order matters here. Without it, cells scrolled under the
       pinned first column paint straight over it — stray digits appeared
       beside the row labels — and the "Program" heading slid away while the
       labels it describes stayed put. */
    & thead th {
      background: var(--pink-deep);
      color: #fff;
      font-weight: 600;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      font-size: 0.72rem;
      /* Sticky for the horizontal pin only. `overflow-x: auto` makes
         .table-scroll a scroll container on BOTH axes, so a `top` offset
         resolves against a box that never scrolls vertically and does nothing
         — it only parked the headings under the site header. */
      position: sticky;
      z-index: 3;
    }

    /* The corner cell is pinned on both axes, so it must sit above both. */
    & thead th:first-child {
      inset-inline-start: 0;
      z-index: 4;
      /* A sub-pixel gap between the container's padding edge and the pinned
         cell let fragments of scrolled text show through. The shadow paints
         over that strip and is clipped by the scroll container. */
      box-shadow: -6px 0 0 0 var(--pink-deep);
    }

    & tbody th {
      font-weight: 600;
      font-size: var(--step-0);
      font-family: var(--serif);
      position: sticky;
      inset-inline-start: 0;
      z-index: 2;
      background: #fff;
      /* The rail is an INSET shadow, not a border. With
         `border-collapse: collapse` the browser paints collapsed borders in
         the table's own layer, so a sticky cell leaves its border behind when
         it pins — the rail vanished and text showed through the gap. An inset
         shadow belongs to the cell and travels with it. The outer white
         shadow covers the sub-pixel seam at the container edge. */
      box-shadow: inset 4px 0 0 0 var(--accent, var(--pink)), -8px 0 0 0 #fff;
      padding-inline-start: 1.05rem;
      min-width: 9.5rem;
    }

    /* Every program name links to its own description. The link lives inside the
       sticky <th>, so it inherits the cell colour and only underlines on
       hover/focus — ten permanently underlined row headers read as noise. */
    & tbody th a {
      color: inherit;
      text-decoration: none;
      text-underline-offset: 3px;

      /* An inline link here is only ~21px tall, under the 24px WCAG 2.5.8
         floor. Negative block margins let it absorb the cell's own vertical
         padding, so the target grows to the full row height without making
         the row any taller. */
      display: flex;
      align-items: center;
      min-height: 44px;
      margin-block: -0.85rem;
      padding-block: 0.85rem;

      &:hover, &:focus-visible {
        color: var(--pink-deep);
        text-decoration: underline;
        text-decoration-thickness: 2px;
      }
    }

    & tbody tr:last-child :is(th, td) { border-bottom: 0; }
    & .none { color: color-mix(in oklab, var(--ink) 35%, var(--cream) 65%); }
    & .ballet { color: var(--pink-deep); font-weight: 600; }
  }

  .table-hint {
    font-size: var(--step--1);
    color: var(--ink-soft);
    margin-top: 0.75rem;

    @media (width >= 52rem) { display: none; }
  }

  /* ---------- Per-program detail ---------- */
  .program {
    --accent: var(--pink-deep);
    scroll-margin-top: 6rem;
    padding-block: clamp(2rem, 5vw, 3rem);
    border-top: 1px solid var(--rule);
    display: grid;
    gap: clamp(1rem, 3vw, 2.5rem);
    grid-template-columns: 1fr;

    @media (width >= 46rem) { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); }

    & h3 {
      font-size: var(--step-3);
      &::after {
        content: "";
        display: block;
        width: 2.5rem;
        height: 4px;
        background: var(--accent);
        border-radius: 2px;
        margin-top: 0.75rem;
      }
    }

    & .program__who {
      font-size: var(--step--1);
      font-weight: 600;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--accent);
      margin-bottom: 0.5rem;
    }

    & p { color: var(--ink-soft); max-width: var(--measure); }
    & .btn { margin-top: 1.25rem; }
  }

  .times {
    list-style: none;
    padding: 0;
    margin: 1rem 0 0;
    display: grid;
    gap: 0.4rem;
    font-size: var(--step--1);

    & li {
      display: flex;
      gap: 0.85rem;
      padding-block: 0.4rem;
      border-bottom: 1px solid color-mix(in oklab, var(--rule) 55%, transparent);
    }
    & b { min-width: 5.5rem; font-weight: 600; }
  }

  /* ---------- Prose (About / bio) ---------- */
  .prose {
    max-width: var(--measure);
    margin-inline: auto;

    & p + p { margin-top: 1.1rem; }
    & p { color: var(--ink-soft); }
    & p.lead {
      font-size: var(--step-1);
      color: var(--ink);
      font-family: var(--serif);
      line-height: 1.4;
    }
  }

  .notes {
    display: grid;
    gap: 1rem;
    /* 20rem caps this at three columns on the widest layout. At 15rem a
       1180px row fitted four, which shrank every photo and made a
       five-photo group end 4 + 1. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
    list-style: none;
    padding: 0;
    margin-top: 2rem;

    & li {
      background: color-mix(in oklab, #fff 70%, transparent);
      border: 1px solid var(--rule);
      border-radius: var(--radius);
      padding: 1.25rem;
      font-size: var(--step--1);
    }
    & b { display: block; font-family: var(--serif); font-size: var(--step-1); font-weight: 500; margin-bottom: 0.3rem; }
  }

  /* Exactly five apparatus — auto-fit would break them 4+1, which reads as an
     accident. One row of five states the fact. */
  .notes--five {
    @media (width >= 72rem) { grid-template-columns: repeat(5, 1fr); }
  }

  /* Parent Portal is an outbound link to a separate system, so it gets a
     distinct treatment from the in-site nav items at every width. */
  .nav .nav__portal {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-weight: 600;
    color: var(--pink-deep);
    border: 1px solid color-mix(in oklab, var(--pink-deep) 45%, transparent);
    border-radius: 999px;
    padding-inline: 0.75rem;
    min-height: 40px;
    font-size: 0.8rem;

    & svg { flex: none; }

    &:hover {
      background: color-mix(in oklab, var(--pink) 12%, transparent);
      border-color: var(--pink-deep);
    }
  }

  /* ---------- Forms ---------- */
  .form {
    display: grid;
    gap: 1.1rem;
    max-width: 34rem;
  }
  .field {
    display: grid;
    gap: 0.4rem;

    & label {
      font-size: var(--step--1);
      font-weight: 600;
    }
    & .hint { font-size: 0.78rem; color: var(--ink-soft); font-weight: 400; }

    & input, & select, & textarea {
      width: 100%;
      padding: 0.75rem 0.9rem;
      border: 1px solid var(--line, var(--rule));
      border-radius: 10px;
      background: #fff;
      color: var(--ink);
      font-size: var(--step-0);
      min-height: 48px;

      &:focus-visible {
        outline: 3px solid var(--pink-deep);
        outline-offset: 2px;
        border-color: var(--pink-deep);
      }
      &:user-invalid {
        border-color: #B42318;
        background: #FEF3F2;
      }
    }
    & textarea { min-height: 8rem; resize: vertical; }

    /* Native validation message, shown only once the field has been touched */
    & input:user-invalid + .err,
    & textarea:user-invalid + .err { display: block; }
    & .err { display: none; color: #B42318; font-size: 0.78rem; }
  }

  .form__note {
    font-size: var(--step--1);
    color: var(--ink-soft);
    max-width: 44ch;
  }

  .free-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--pink-deep);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: 0.3em 0.75em;
    border-radius: 999px;
  }

  /* ---------- SRG: levels & criteria ---------- */
  .level {
    --accent: var(--pink-deep);
    scroll-margin-top: 7rem;
    background: #fff;
    border: 1px solid var(--rule);
    border-inline-start: 5px solid var(--accent);
    border-radius: var(--radius);
    padding: 1.5rem 1.5rem 1.4rem;
    margin-bottom: 1rem;

    & header {
      display: flex;
      flex-wrap: wrap;
      align-items: baseline;
      gap: 0.4rem 1rem;
      margin-bottom: 0.9rem;
    }
    & h3 { font-size: var(--step-2); }
    & .level__load {
      font-size: var(--step--1);
      font-weight: 600;
      color: var(--accent);
      margin-inline-start: auto;
    }
    & p { color: var(--ink-soft); max-width: var(--measure); }
  }

  .criteria {
    list-style: none;
    padding: 0;
    margin: 1rem 0 0;
    display: grid;
    gap: 0.5rem;
    font-size: var(--step--1);

    & li {
      display: flex;
      gap: 0.6rem;
      align-items: flex-start;
    }
    & li::before {
      content: "";
      flex: none;
      width: 6px; height: 6px;
      margin-top: 0.55em;
      border-radius: 50%;
      background: var(--accent);
    }
  }

  /* ---------- Conduct ---------- */
  .conduct {
    counter-reset: rule;
    list-style: none;
    padding: 0;
    display: grid;
    gap: 0.75rem;

    & li {
      counter-increment: rule;
      display: grid;
      /* Two cells only. All text lives in one child div — three loose
         children would wrap the third into the 2rem number column. */
      grid-template-columns: 2rem minmax(0, 1fr);
      gap: 0.9rem;
      align-items: start;
      background: color-mix(in oklab, #fff 70%, transparent);
      border: 1px solid var(--rule);
      border-radius: var(--radius);
      padding: 1.1rem 1.25rem;
    }
    & li::before {
      content: counter(rule, decimal-leading-zero);
      font-family: var(--serif);
      font-size: var(--step-1);
      color: var(--pink);
      line-height: 1.1;
    }
    & b {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0.5rem;
      font-size: var(--step-0);
      margin-bottom: 0.2rem;
    }
    & span { display: block; font-size: var(--step--1); color: var(--ink-soft); }
  }

  /* ---------- Empty-state panel for data we don't have yet ---------- */
  .awaiting {
    border: 2px dashed var(--rule);
    border-radius: var(--radius);
    padding: clamp(1.75rem, 5vw, 2.75rem);
    text-align: center;
    background: color-mix(in oklab, #fff 55%, transparent);

    & svg { width: 34px; margin: 0 auto 0.9rem; color: var(--pink); opacity: .7; }
    & b { display: block; font-family: var(--serif); font-size: var(--step-2); font-weight: 500; }
    & p { color: var(--ink-soft); max-width: 46ch; margin: 0.5rem auto 0; font-size: var(--step--1); }
    & .todo { margin-top: 1rem; }
  }

  /* ---------- FAQ (native <details>, no JavaScript) ---------- */
  .faq-group {
    /* A link target now, so it must clear the sticky header — same 6rem the
       other anchored components use. */
    scroll-margin-top: 6rem;
    font-size: var(--step-2);
    padding-bottom: 0.6rem;
    margin-bottom: 1.25rem;
    border-bottom: 2px solid var(--rule);
  }

  .faqs, .disclose {
    display: grid;
    gap: 0.6rem;

    & details {
      background: #fff;
      border: 1px solid var(--rule);
      border-radius: var(--radius);
      overflow: hidden;

      &[open] { border-color: color-mix(in oklab, var(--pink) 45%, var(--cream)); }
    }

    & summary {
      display: flex;
      align-items: center;
      gap: 0.9rem;
      padding: 1.05rem 1.25rem;
      min-height: 44px;
      cursor: pointer;
      font-weight: 600;
      font-size: var(--step-0);
      list-style: none;

      &::-webkit-details-marker { display: none; }

      /* chevron */
      &::after {
        content: "";
        flex: none;
        margin-inline-start: auto;
        width: 9px; height: 9px;
        border-right: 2px solid var(--pink-deep);
        border-bottom: 2px solid var(--pink-deep);
        rotate: 45deg;
        transition: rotate .2s var(--ease);
      }
      &:hover { color: var(--pink-deep); }
    }

    & details[open] > summary::after { rotate: -135deg; }

    & details > div {
      padding: 0 1.25rem 1.25rem;
      border-top: 1px solid var(--rule);
      padding-top: 1rem;
    }
    & details p {
      color: var(--ink-soft);
      max-width: var(--measure);
      font-size: var(--step--1);
      & + p { margin-top: 0.75rem; }
    }

    /* A paragraph following the list needs the same separation. */
    & .plain-list + p { margin-top: 0.9rem; }

    /* Terms that read better as a list than as a run-on sentence. */
    & .plain-list {
      margin: 0.75rem 0 0;
      padding-inline-start: 1.15rem;
      display: grid;
      gap: 0.35rem;
      color: var(--ink-soft);
      font-size: var(--step--1);
      max-width: var(--measure);

      & li::marker { color: var(--pink-deep); }
    }
  }

  /* ---------- Disclosure rows for long detail blocks ----------
     Same accordion mechanics as the FAQ, but the summary carries scannable
     metadata (name, who, when) so a parent can find the right row without
     opening anything. */
  .disclose {
    & details {
      border-inline-start: 5px solid var(--accent, var(--pink-deep));
      scroll-margin-top: 6rem;
    }

    & summary {
      flex-wrap: wrap;
      gap: 0.15rem 0.9rem;
      padding-block: 0.95rem;
    }

    & .d-name {
      font-family: var(--serif);
      font-size: var(--step-1);
      font-weight: 500;
      line-height: 1.15;
      /* Absorb the free space. Without this both .d-when and the chevron carry
         `margin-inline-start: auto`, the row splits the slack between them, and
         the date lands wherever the title happens to end. */
      flex: 1;
    }
    & .d-who {
      flex-basis: 100%;
      font-size: 0.7rem;
      font-weight: 700;
      letter-spacing: 0.09em;
      text-transform: uppercase;
      color: var(--accent, var(--pink-deep));
    }
    & .d-when {
      font-size: var(--step--1);
      font-weight: 400;
      color: var(--ink-soft);
      margin-inline-start: auto;
      padding-inline-end: 0.5rem;
    }

    & details > div { padding-top: 1.1rem; }
    & .times { margin-top: 0; }
    & .criteria { margin-top: 0; }
  }

  /* ---------- Program picker: chip rail + one open panel ----------
     Zero JavaScript. Hidden radios drive it, so it is keyboard and screen
     reader operable as a normal radio group. Every option's name and age
     stays visible while one panel is open — the point is comparing, not
     just reading. */
  .picker {
    display: grid;
  }

  .picker > input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
  }

  .picker__rail {
    display: flex;
    gap: 0.6rem;
    overflow-x: auto;
    padding-block: 0.25rem 1rem;
    scrollbar-width: thin;
    scroll-snap-type: x proximity;

    & label {
      --on: 0;
      flex: none;
      scroll-snap-align: start;
      cursor: pointer;
      min-width: 8.5rem;
      padding: 0.7rem 1rem;
      border-radius: var(--radius);
      border: 1px solid var(--rule);
      background: #fff;
      display: grid;
      gap: 0.1rem;
      transition: border-color .18s var(--ease), background-color .18s var(--ease);

      /* the accent rail doubles as the selected state */
      border-inline-start: 4px solid
        color-mix(in oklab, var(--accent, var(--pink-deep)) calc(var(--on) * 100%),
                  var(--rule));
      background: color-mix(in oklab, var(--accent, var(--pink))
                  calc(var(--on) * 8%), #fff);

      & b {
        font-family: var(--serif);
        font-size: var(--step-0);
        font-weight: 500;
        line-height: 1.15;
        white-space: nowrap;
      }
      & span {
        font-size: 0.75rem;
        font-weight: 600;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: color-mix(in oklab, var(--accent, var(--pink-deep))
                calc(40% + var(--on) * 60%), var(--ink-soft));
        white-space: nowrap;
      }

      &:hover { border-color: var(--pink-deep); }
    }
  }

  .picker > input:focus-visible ~ .picker__rail {
    outline: 3px solid var(--pink-deep);
    outline-offset: 4px;
    border-radius: var(--radius);
  }

  .picker__panel {
    display: none;
    scroll-margin-top: 6rem;
    background: #fff;
    border: 1px solid var(--rule);
    border-inline-start: 5px solid var(--accent, var(--pink-deep));
    border-radius: var(--radius);
    padding: clamp(1.25rem, 3vw, 1.75rem);

    & h3 { font-size: var(--step-2); }
    & .program__who {
      font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em;
      text-transform: uppercase; color: var(--accent, var(--pink-deep));
      margin-bottom: 0.3rem;
    }
    & p { color: var(--ink-soft); max-width: var(--measure); margin-top: 0.6rem; }
    & .times { margin-top: 1rem; }
  }

  .picker > input:nth-of-type(1):checked ~ .picker__panels > .picker__panel:nth-child(1) { display: block; }
  .picker > input:nth-of-type(2):checked ~ .picker__panels > .picker__panel:nth-child(2) { display: block; }
  .picker > input:nth-of-type(3):checked ~ .picker__panels > .picker__panel:nth-child(3) { display: block; }
  .picker > input:nth-of-type(4):checked ~ .picker__panels > .picker__panel:nth-child(4) { display: block; }
  .picker > input:nth-of-type(5):checked ~ .picker__panels > .picker__panel:nth-child(5) { display: block; }
  .picker > input:nth-of-type(6):checked ~ .picker__panels > .picker__panel:nth-child(6) { display: block; }
  .picker > input:nth-of-type(7):checked ~ .picker__panels > .picker__panel:nth-child(7) { display: block; }
  .picker > input:nth-of-type(8):checked ~ .picker__panels > .picker__panel:nth-child(8) { display: block; }

  .picker > input:nth-of-type(1):checked ~ .picker__rail > label:nth-child(1) { --on: 1; }
  .picker > input:nth-of-type(2):checked ~ .picker__rail > label:nth-child(2) { --on: 1; }
  .picker > input:nth-of-type(3):checked ~ .picker__rail > label:nth-child(3) { --on: 1; }
  .picker > input:nth-of-type(4):checked ~ .picker__rail > label:nth-child(4) { --on: 1; }
  .picker > input:nth-of-type(5):checked ~ .picker__rail > label:nth-child(5) { --on: 1; }
  .picker > input:nth-of-type(6):checked ~ .picker__rail > label:nth-child(6) { --on: 1; }
  .picker > input:nth-of-type(7):checked ~ .picker__rail > label:nth-child(7) { --on: 1; }
  .picker > input:nth-of-type(8):checked ~ .picker__rail > label:nth-child(8) { --on: 1; }


  /* ---------- Photography ---------- */
  /* Collapsible gallery groups. Same chevron language as the FAQ accordion,
     but the summary reads as a section heading rather than a boxed row, so the
     groups still scan as page structure when they are all closed. */
  /* Collapsible gallery groups. The summary is styled as a section heading —
     centred serif, same weight as an <h2> elsewhere — so a closed group still
     reads as page structure rather than as a form control. The chevron is
     positioned rather than flowed, so it cannot pull the title off centre. */
  .gal-group {
    border-top: 1px solid var(--rule-strong);

    & > summary {
      position: relative;
      text-align: center;
      padding: clamp(1.75rem, 4vw, 2.5rem) 2.5rem 0.9rem;
      cursor: pointer;
      list-style: none;
      font-family: var(--serif);
      font-weight: 500;
      font-size: var(--step-3);
      line-height: 1.15;
      transition: color .2s var(--ease);

      &::-webkit-details-marker { display: none; }

      &::after {
        content: "";
        position: absolute;
        inset-inline-end: 0.6rem;
        inset-block-start: 50%;
        width: 11px; height: 11px;
        border-right: 2px solid var(--pink-deep);
        border-bottom: 2px solid var(--pink-deep);
        rotate: 45deg;
        translate: 0 -65%;
        transition: rotate .2s var(--ease);
      }
      &:hover { color: var(--pink-deep); }
    }

    &[open] > summary::after { rotate: -135deg; translate: 0 -25%; }

    & .gal-blurb {
      text-align: center;
      max-width: 52ch;
      margin: 0 auto clamp(1.5rem, 4vw, 2.25rem);
      color: var(--ink-soft);
    }
    & .gallery { padding-bottom: clamp(2rem, 5vw, 3rem); }
  }

  /* A photo inside an accordion answer. The crop is 2:1, so the slot is too —
     object-fit would otherwise crop it a second time. */
  .event-photo {
    aspect-ratio: 2 / 1;
    margin-top: 1rem;
  }
  .event-photo figcaption { padding-bottom: 0; }

  /* Summer Show gallery. The slots match the crops exactly, 2:1 for the wide
     frames and 9:16 for the tall ones, so object-fit never crops a second time.
     Six tracks divide cleanly into 6 / 3 / 2, which is why the band, the pair
     and the trio all fill their rows. */
  .showgrid {
    display: grid;
    gap: 0.9rem;
    grid-template-columns: 1fr;

    & .sg-band, & .sg-wide { aspect-ratio: 2 / 1; }
    & .sg-tall { aspect-ratio: 9 / 16; }

    @media (width >= 48rem) {
      grid-template-columns: repeat(6, 1fr);

      & .sg-band { grid-column: 1 / -1; }
      & .sg-wide { grid-column: span 3; }
      & .sg-tall { grid-column: span 2; }
    }
  }

  .photo {
    margin: 0;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--cream-deep);

    /* <picture> sits between the figure and the img. It has no height of its
       own, so `height: 100%` on the img resolves against nothing and the image
       letterboxes whenever its crop ratio differs from the slot's. */
    & > picture {
      display: block;
      width: 100%;
      height: 100%;
    }

    & img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }
    & figcaption {
      font-size: var(--step--1);
      color: var(--ink-soft);
      padding: 0.6rem 0.15rem 0;
    }
  }

  /* Masonry-ish gallery that never leaves a stranded final row */
  .gallery {
    display: grid;
    gap: 0.9rem;
    /* 20rem caps this at three columns on the widest layout. At 15rem a
       1180px row fitted four, which shrank every photo and made a
       five-photo group end 4 + 1. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
    /* Wide items span two tracks, which otherwise strands half-empty rows.
       `dense` lets a later single-track photo backfill the hole. */
    grid-auto-flow: dense;

    & .photo {
      aspect-ratio: 4 / 5;
      box-shadow: var(--shadow-sm);
      transition: transform .25s var(--ease), box-shadow .25s var(--ease);

      &:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
    }
    & .photo--wide { aspect-ratio: 3 / 2; grid-column: span 1; }

    @media (width >= 48rem) {
      & .photo--wide { grid-column: span 2; }

      /* A wide photo in the final position leaves the rest of its row empty.
         Letting it run the full width turns that hole into a closing band. */
      & .photo--wide:last-child {
        grid-column: 1 / -1;
        aspect-ratio: 2 / 1;
      }
    }

    /* Exactly two photos: a spanning wide plus one single leaves half a row
       empty. Two equal columns fills it. */
    &:has(> .photo:nth-child(2):last-child) {
      @media (width >= 48rem) {
        grid-template-columns: repeat(2, 1fr);

        & .photo--wide { grid-column: auto; aspect-ratio: 4 / 5; }
      }
    }

    /* Exactly three photos: a wide + two singles wraps to 2 + 1 and strands
       one. Three equal columns fills the row instead. */
    &:has(> .photo:nth-child(3):last-child) {
      @media (width >= 60rem) {
        grid-template-columns: repeat(3, 1fr);

        & .photo--wide { grid-column: auto; aspect-ratio: 4 / 5; }
      }
    }
  }

  /* Photo beside prose */
  .feature {
    display: grid;
    gap: clamp(1.25rem, 4vw, 3rem);
    align-items: center;
    grid-template-columns: 1fr;

    @media (width >= 48rem) {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      &.feature--flip > .photo { order: 2; }
    }

    & > .photo { aspect-ratio: 4 / 5; box-shadow: var(--shadow-md); }
    & h2, & h3 { margin-bottom: 0.75rem; }
    & p { color: var(--ink-soft); max-width: var(--measure); }
    & p + p { margin-top: 0.9rem; }
  }

  /* ---------- Results: the numbers, stated plainly ---------- */
  .results {
    display: grid;
    gap: 0.6rem;
    grid-template-columns: repeat(3, 1fr);

    @media (width >= 40rem) { gap: 1rem; }
  }

  /* Four stat cards. 3-across would strand one on its own row, and 4-across on a
     phone leaves ~75px per card — so it reads 2x2 on mobile, 4-up from 40rem. */
  .results--four {
    grid-template-columns: repeat(2, 1fr);

    @media (width >= 40rem) { grid-template-columns: repeat(4, 1fr); }
  }

  .result-card {
    background: #fff;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    padding: 1rem 0.6rem;
    text-align: center;

    @media (width >= 40rem) { padding: 1.5rem 1.35rem; }

    & b {
      display: block;
      font-family: var(--serif);
      font-size: clamp(1.9rem, 7vw, 3.4rem);
      line-height: 1;
      color: var(--pink-deep);
      font-weight: 500;
      font-variant-numeric: tabular-nums;
    }
    & span {
      display: block;
      margin-top: 0.4rem;
      font-size: 0.72rem;
      line-height: 1.35;
      color: var(--ink-soft);
      text-wrap: pretty;

      @media (width >= 40rem) { font-size: var(--step--1); margin-top: 0.5rem; }
    }
  }

  .placings {
    list-style: none;
    padding: 0;
    margin: 1.5rem 0 0;
    display: grid;
    gap: 0.6rem;

    & li {
      display: flex;
      flex-wrap: wrap;
      align-items: baseline;
      gap: 0.4rem 0.9rem;
      background: color-mix(in oklab, #fff 70%, transparent);
      border: 1px solid var(--rule);
      border-radius: var(--radius);
      padding: 0.9rem 1.15rem;
      font-size: var(--step--1);
    }
    & .place {
      font-family: var(--serif);
      font-size: var(--step-1);
      color: var(--pink-deep);
      min-width: 2.6rem;
      font-variant-numeric: tabular-nums;
    }
    & .who { font-weight: 600; }
    & .what { color: var(--ink-soft); margin-inline-start: auto; }
  }

  /* ---------- SRG Academy mark ---------- */
  .srg-mark {
    width: clamp(120px, 24vw, 180px);
    height: auto;
    margin-inline: auto;
    margin-bottom: clamp(1rem, 3vw, 1.5rem);
  }

  /* ---------- Vertical video beside text ----------
     The source is 9:16 (shot for Reels). Letterboxing it into a 16:9 band left
     71% of the row empty and read as a failed image. Pairing it with a column
     of copy uses the width for something, and the portrait shape becomes an
     asset rather than a problem. */
  .vsplit {
    display: grid;
    gap: clamp(1.5rem, 4vw, 3rem);
    align-items: center;
    grid-template-columns: 1fr;

    @media (width >= 52rem) {
      grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    }


    & > figure {
      margin: 0;
      border-radius: var(--radius);
      overflow: hidden;
      box-shadow: var(--shadow-md);
      background: var(--ink);
      max-width: 22rem;
      margin-inline: auto;
      width: 100%;
    }

    & > figure video {
      display: block;
      width: 100%;
      aspect-ratio: 9 / 16;
      object-fit: cover;
    }

    & h2 { margin-bottom: 0.75rem; }
    & p { color: var(--ink-soft); max-width: var(--measure); }
    & p + p { margin-top: 0.9rem; }
    & .btn { margin-top: 1.5rem; }
  }

  /* ---------- Map skeleton ----------
     The OSM iframe is lazy, so the frame sits empty for a moment. A quiet
     shimmer reads as loading rather than broken. */
  .map-frame {
    position: relative;

    &::before {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(100deg,
        var(--cream-warm) 30%, var(--cream-deep) 50%, var(--cream-warm) 70%)
        0 0 / 300% 100%;
      animation: shimmer 1.6s linear infinite;
    }
    & iframe { position: relative; z-index: 1; }
  }

  @keyframes shimmer { to { background-position: -300% 0; } }

  @media (prefers-reduced-motion: reduce) {
    .map-frame::before { animation: none; }
  }

  /* ---------- Proof band ---------- */
  .proof {
    background: var(--ink);
    color: var(--cream);
    text-align: center;

    & .results { margin-top: clamp(1.5rem, 4vw, 2.25rem); }

    & .result-card {
      background: color-mix(in oklab, var(--cream) 8%, transparent);
      border-color: color-mix(in oklab, var(--cream) 18%, transparent);

      & b { color: var(--pink); }
      & span { color: color-mix(in oklab, var(--cream) 76%, var(--ink) 24%); }
    }
  }

  /* ---------- TODO-CLIENT flag (preview only, strip before launch) ---------- */
  .todo {
    display: inline-block;
    background: repeating-linear-gradient(45deg, #FFF3C4, #FFF3C4 8px, #FFE79A 8px, #FFE79A 16px);
    border: 1px dashed #A9862B;
    color: #6B540F;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    padding: 0.15em 0.5em;
    border-radius: 4px;
  }
}

@layer utilities {
  /* A deep link (e.g. /programs.html#level-4) must beat the picker's default
     radio selection. These sit in `utilities` because the :nth-of-type rules
     that drive the picker are far more specific (0,6,1 vs 0,3,0) — layer
     order settles it without !important. */
  .picker:has(.picker__panel:target) .picker__panel:not(:target) { display: none; }
  .picker .picker__panel:target { display: block; }

  /* Lives in `utilities` on purpose: descendant paragraph rules in the
     `components` layer (.coach__body p, .section-head > p) set their own
     color and out-specify a bare .eyebrow. The layer order settles it. */
  .eyebrow {
    font-size: var(--step--1);
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--pink-deep);
  }

  /* Honeypot. Taken out of the layout and off-screen rather than display:none,
     which some bots detect and skip. aria-hidden + tabindex -1 keep it away
     from screen readers and keyboard users. */
  .hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
  }

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

  /* ::before, not ::after — .card__link uses ::after for its arrow, and
     this rule (utilities layer) would otherwise win and erase it. */
  .stretched::before {
    content: "";
    position: absolute;
    inset: 0;
  }

  .center { text-align: center; }
}

/* Same-document view transitions for in-page nav (progressive enhancement) */
@view-transition { navigation: auto; }
