/* ==========================================================================
   ELITE AMENITIES — stylesheet
   St. Johns FL amenity staffing / lifeguards / swim & tennis programs.
   Palette from client's Pantone logo. Marcellus (display) + Figtree (body).
   Section order: reset, tokens, base, layout, buttons, chips/tags/lnk,
   header, mobile nav, hero+bento, waterline, ticker, services, band,
   programs, directors, certification, areas, careers, faq, quote, footer,
   callbar, skip link, reduced motion.
   ========================================================================== */

/* ---------- 1. Small modern reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
body { min-height: 100svh; line-height: 1.5; -webkit-font-smoothing: antialiased; }
img, picture, svg { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }
p { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }

/* ---------- 2. Tokens ---------- */
:root {
  --pool:     #7499C1;
  --sand:     #D6CBA9;
  --sky:      #ACC1D9;
  --deep:     #12293F;
  --deep-2:   #1D3E5C;
  --pool-dk:  #3C6893;
  --cabana:   #FAF8F4;
  /* Third light ground, alongside #fff and --cabana. Cool where cabana is
     warm, so a band of it reads as a change next to EITHER of them. */
  --tint:     color-mix(in srgb, var(--sky) 14%, #fff);
  --line:     rgba(18,41,63,.12);
  --ink-soft: #33475C;
  --stat-l:   #4A6076;

  --font-display: 'Marcellus', Georgia, serif;
  --font-body: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* The logo's three wave ribbons (sky / sand / pool), redrawn as a stretchable
     mark. Declared once here and reused by the <em> accent and the eyebrow tick.
     preserveAspectRatio="none" lets it stretch to whatever it underlines. */
  --wave-mark: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 26" preserveAspectRatio="none"><path fill="%23ACC1D9" d="M22 6.0 40 5.6 58 5.8 75 5.3 93 4.1 111 2.5 129 1.1 147 0.4 164 0.8 182 2.5 200 6.0 L200 6.0 182 6.4 164 6.2 147 6.7 129 7.9 111 9.5 93 10.9 75 11.6 58 11.2 40 9.5 22 6.0Z"/><path fill="%23D6CBA9" d="M8 13.5 27 12.8 45 12.7 64 11.9 82 10.4 101 8.7 120 7.4 138 7.0 157 7.8 175 9.8 194 13.5 L194 13.5 175 14.0 157 13.6 138 13.8 120 14.8 101 16.3 82 17.8 64 18.7 45 18.5 27 17.0 8 13.5Z"/><path fill="%237499C1" d="M0 21.0 18 20.0 36 19.6 54 18.4 72 16.6 90 14.8 108 13.6 126 13.4 144 14.6 162 16.9 180 21.0 L180 21.0 162 21.6 144 21.0 126 21.0 108 21.8 90 23.2 72 24.8 54 26.0 36 26.0 18 24.7 0 21.0Z"/></svg>');

  --wrap-pad: clamp(20px, 5vw, 48px);
  --sec-pad: clamp(72px, 9vw, 130px);
  --radius-lg: 18px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --shadow-tile: 0 1px 2px rgba(18,41,63,.04), 0 12px 32px -12px rgba(18,41,63,.14);
}

/* ---------- 3. Base ---------- */
body {
  font-family: var(--font-body);
  background: var(--cabana);
  color: var(--deep);
  font-size: 1rem;
}

h1, h2, h3, .prog__k, .stat__n, .hdr__tel, .ticker__set span,
.cert__h, .classes time, .dir__hd h3 {
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--deep);
}

/* em inside headings = accent, never italic (Marcellus has no italic) */
h1 em, h2 em {
  font-style: normal;
  color: var(--pool-dk);
  /* The logo's three wave ribbons, redrawn as the accent mark. Painted as a
     background on the <em> itself (not an absolute ::after) so it survives a
     line break — box-decoration-break gives each line fragment its own mark,
     which is why this no longer needs white-space:nowrap. Dropping that nowrap
     also cleared the 320px horizontal overflow the old rule caused. */
  background-image: var(--wave-mark);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% .26em;
  /* padding-bottom - background-size = the clear space under the glyphs. */
  padding-bottom: .32em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
/* An inline element's padding paints but adds no layout height, so the mark
   would sit on top of whatever follows the heading. Reserve real space under
   any heading carrying one. */
h1:has(em), h2:has(em) { padding-bottom: .39em; }
/* When the accent lands mid-heading, the next line runs straight through the
   mark — no underline can sit below the descenders at 1.15 leading. Section
   heads get enough room for the mark to live between the lines. */
.shead h2:has(em) { line-height: 1.45; }
/* --pool-dk is only legible on light grounds (2.5:1 on --deep). On the dark
   sections the accent switches to the sky tint (~7.5:1). The ribbon mark is
   all mid-tones, so it holds up on both grounds unchanged. */
.band em, .sec--cert em, .sec--quote em, .ftr em { color: var(--sky); }

.eyebrow {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: .72rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--pool-dk);
}
/* Same three ribbons, tick-sized, in front of every section label — carries the
   logo's palette through the page in small doses instead of one big band. */
.eyebrow::before {
  content: '';
  display: inline-block;
  width: 2.1em;
  height: .62em;
  margin-right: .7em;
  vertical-align: baseline;
  background-image: var(--wave-mark);
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
/* Centred section heads read better with the tick above the label than beside it. */
.shead--center .eyebrow::before { display: block; margin: 0 auto .5em; }

/* ---------- 4. Layout ---------- */
.wrap {
  max-width: 1240px;
  margin-inline: auto;
  padding-inline: var(--wrap-pad);
}

.sec { padding-block: var(--sec-pad); }
.sec--services   { background: var(--cabana); }
.sec--programs   { background: #fff; }
.sec--dirs       { background: color-mix(in srgb, var(--sky) 12%, #fff); }
.sec--cert       { background: var(--deep); }
.sec--areas      { background: var(--cabana); }
.sec--careers    { background: #fff; }
.sec--faq        { background: var(--cabana); }
.sec--quote      { background: var(--deep); }
/* Opt-in ground for a section that would otherwise stack on a same-coloured
   neighbour. boca-raton.html runs #swim and #tennis back to back and both are
   .sec--programs, so the pair rendered as one uninterrupted white column whose
   only break was a small eyebrow. Tinting the first restores the change-of-
   ground that every other boundary on the site uses. Keep this AFTER the block
   above — it wins on source order, not specificity. */
.sec--tint       { background: var(--tint); }

.shead { max-width: 680px; margin-bottom: clamp(36px, 5vw, 56px); }
.shead--center { max-width: 620px; margin-inline: auto; text-align: center; }
.shead h2 { font-size: clamp(1.8rem, 3.4vw, 2.6rem); line-height: 1.15; margin-top: .5em; }
.shead__p { margin-top: 1em; color: var(--ink-soft); font-size: 1.02rem; }

/* ---------- 5. Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  background: var(--deep);
  color: #fff;
  border-radius: 999px;
  padding: .82em 1.6em;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .92rem;
  line-height: 1;
  transition: transform .2s ease, background-color .2s ease;
  white-space: nowrap;
}
.btn svg { width: 1em; height: 1em; fill: currentColor; }
.btn:hover { transform: translateY(-2px); background: var(--pool-dk); }

.btn--ghost {
  background: transparent;
  color: var(--deep);
  border: 1.5px solid var(--deep);
}
.btn--ghost:hover { background: var(--deep); color: #fff; }

.btn--light { background: #fff; color: var(--deep); }
.btn--light:hover { background: var(--sand); color: var(--deep); transform: translateY(-2px); }

/* A default .btn sitting straight on a --deep ground is dark-on-dark and
   disappears (only its white label shows). Any solid button on a dark
   section inverts to the light treatment automatically. */
.sec--cert > .wrap .btn:not(.btn--ghost):not(.btn--ghostlight):not(.btn--light),
.quote__side .btn:not(.btn--ghost):not(.btn--ghostlight):not(.btn--light) {
  background: #fff;
  color: var(--deep);
}
.sec--cert > .wrap .btn:not(.btn--ghost):not(.btn--ghostlight):not(.btn--light):hover,
.quote__side .btn:not(.btn--ghost):not(.btn--ghostlight):not(.btn--light):hover {
  background: var(--sand);
  color: var(--deep);
}

.btn--ghostlight {
  background: transparent;
  color: #fff;
  border: 1.5px solid rgba(255,255,255,.55);
}
.btn--ghostlight:hover { background: rgba(255,255,255,.12); border-color: #fff; }

.btn--sm { padding: .6em 1.3em; font-size: .82rem; }
.btn--block { width: 100%; justify-content: center; }

:focus-visible {
  outline: 3px solid var(--pool);
  outline-offset: 2px;
  border-radius: 4px;
}
.btn:focus-visible { outline-offset: 3px; border-radius: 999px; }
.seg__b:focus-visible, .chips li a:focus-visible, .callbar a:focus-visible { border-radius: 999px; }

/* ---------- 6. Chips / tags / lnk ---------- */
.chips { display: flex; flex-wrap: wrap; gap: .6em; margin-top: 1.4em; }
.chips li {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  font-size: .82rem;
  font-weight: 600;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .5em 1em;
  background: #fff;
}
.chips li::before {
  content: '✓';
  color: var(--pool-dk);
  font-weight: 800;
  font-size: .9em;
}
.chips--light li {
  color: #fff;
  background: rgba(255,255,255,.06);
  border-color: rgba(255,255,255,.25);
}
.chips--light li::before { color: var(--sand); }

.tags { display: flex; flex-wrap: wrap; gap: .55em; margin-top: 1.2em; }
.tags li {
  font-size: .8rem;
  font-weight: 600;
  color: var(--deep);
  background: color-mix(in srgb, var(--sand) 45%, #fff);
  border-radius: 999px;
  padding: .5em 1.05em;
}

.lnk {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  margin-top: 1.4em;
  font-weight: 700;
  font-size: .92rem;
  color: var(--pool-dk);
}
.lnk span { display: inline-block; transition: transform .2s ease; }
.lnk:hover span, .lnk:focus-visible span { transform: translateX(4px); }

/* ---------- 7. Header ---------- */
.skip {
  position: fixed;
  top: -100%;
  left: 12px;
  z-index: 999;
  background: var(--deep);
  color: #fff;
  padding: .8em 1.2em;
  border-radius: var(--radius-sm);
  font-weight: 700;
  transition: top .2s ease;
}
.skip:focus { top: 12px; }

.hdr {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--cabana) 82%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color .25s ease;
}
.hdr.is-stuck { border-bottom-color: var(--line); }

.hdr__in {
  max-width: 1240px;
  margin-inline: auto;
  padding-inline: var(--wrap-pad);
  height: 76px;
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
}

.hdr__logo { display: inline-flex; flex-shrink: 0; }
.hdr__logo img { height: 46px; width: auto; }

.hdr__nav { display: none; align-items: center; gap: clamp(16px, 2.4vw, 32px); margin-right: auto; }
.hdr__nav a {
  position: relative;
  font-weight: 600;
  font-size: .9rem;
  color: var(--deep);
  padding-block: .3em;
}
.hdr__nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 2px;
  background: var(--pool-dk);
  transition: right .25s ease;
}
.hdr__nav a:hover::after,
.hdr__nav a:focus-visible::after { right: 0; }

.hdr__act { display: none; align-items: center; gap: 20px; }
.hdr__tel { font-size: 1.05rem; color: var(--deep); }

.hdr__burger {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  margin-left: auto;
  padding: 0;
}
.hdr__burger span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--deep);
  border-radius: 2px;
  transition: transform .28s ease, opacity .2s ease;
}
.hdr__burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hdr__burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.hdr__burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ---------- 8. Mobile nav ---------- */
.mnav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--cabana);
  border-bottom: 1px solid var(--line);
  padding: 8px var(--wrap-pad) 20px;
  animation: mnavDown .28s ease;
}
/* [hidden] and .mnav{display:flex} share specificity — without this, the
   class declaration can win the cascade tie and the menu never hides. */
.mnav[hidden] { display: none; }
.mnav a {
  padding: .9em .2em;
  font-weight: 600;
  font-size: 1rem;
  border-bottom: 1px solid var(--line);
}
.mnav a.btn { border-bottom: none; margin-top: 12px; text-align: center; }

@keyframes mnavDown {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (min-width: 1024px) {
  .hdr__nav, .hdr__act { display: flex; }
  .hdr__burger, .mnav { display: none !important; }
}

/* ---------- 9. Hero + Bento ---------- */
.hero { position: relative; padding-top: clamp(36px, 5vw, 56px); }

.hero__wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(circle at 12% 18%, rgba(172,193,217,.4), transparent 55%),
    radial-gradient(circle at 88% 6%, rgba(214,203,169,.32), transparent 50%);
}

.hero > .wrap { position: relative; z-index: 1; }

.hero__top {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: clamp(20px, 3vw, 32px);
}

.segwrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.segwrap::-webkit-scrollbar { display: none; }

.seg {
  position: relative;
  display: inline-flex;
  gap: 2px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px;
  width: max-content;
}
.seg__b {
  position: relative;
  z-index: 1;
  padding: .62em 1.15em;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: .85rem;
  color: rgba(18,41,63,.7);
  border-radius: 999px;
  white-space: nowrap;
  transition: color .3s ease;
}
.seg__b.is-on { color: #fff; }
.seg__ink {
  position: absolute;
  top: 4px;
  left: 4px;
  height: calc(100% - 8px);
  width: 0;
  background: var(--deep);
  border-radius: 999px;
  transition: transform .38s cubic-bezier(.65,0,.35,1), width .38s cubic-bezier(.65,0,.35,1);
  z-index: 0;
}

.bento {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
}

.tile {
  background: #fff;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-tile);
  overflow: hidden;
}
/* Never clip copy tiles — only the photo tile needs its image cropped.
   (A fixed-height grid + overflow:hidden silently ate the hero CTA once.) */
.tile--pitch, .tile--stat { overflow: visible; }
.tile--pitch, .tile--stat { padding: clamp(22px, 3vw, 32px); }
/* The aspect-ratio has to live on the TILE, because the img below is absolutely
   positioned and contributes no height. Without it the photo tile collapsed to
   a 2px bordered sliver on phones — the hero image simply did not render under
   640px. The wider breakpoints re-declare this; do not remove the base value. */
.tile--photo { padding: 0; position: relative; aspect-ratio: 16 / 10; }
/* Absolute so the image's intrinsic aspect NEVER feeds back into grid row
   sizing — the three audience images have different aspects (16:10, 4:3, 3:4)
   and a portrait one was stretching the whole hero. The tile takes its size
   from the grid; the image just fills it. */
.tile--photo img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.tile--sand { background: color-mix(in srgb, var(--sand) 30%, #fff); }

/* Sized to sit INSIDE a bento tile alongside the CTA and chips —
   this is not a full-bleed hero headline. */
.pitch :is(h1, h2) {
  font-size: clamp(2rem, 3.1vw, 3rem);
  line-height: 1.08;
  letter-spacing: -.012em;
}
/* The accented phrases are unbreakable so the wave mark never splits across
   two lines. On small phones the longest of them ("your own neighborhood")
   is wider than the tile at 2rem, so step the headline down rather than let
   it push the page sideways. */
@media (max-width: 430px) {
  .pitch :is(h1, h2) { font-size: 1.45rem; }
}
.pitch p { margin-top: .8em; color: var(--ink-soft); font-size: clamp(.98rem, 1.05vw, 1.06rem); max-width: 52ch; }
.pitch__act { display: flex; flex-wrap: wrap; gap: .7em; margin-top: 1.25em; }

.tile__cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  align-items: center;
  gap: .6em;
  padding: 1.4em 1.2em 1.1em;
  color: #fff;
  font-size: .85rem;
  font-weight: 500;
  background: linear-gradient(to top, rgba(18,41,63,.85), rgba(18,41,63,0));
}
.dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--sand);
  flex-shrink: 0;
  animation: dotPulse 2.4s ease-in-out infinite;
}
@keyframes dotPulse {
  0%, 100% { opacity: .5; transform: scale(.85); }
  50% { opacity: 1; transform: scale(1.15); }
}

.stat__n {
  font-size: clamp(2.6rem, 5vw, 3.9rem);
  color: var(--deep);
  line-height: 1;
}
.stat__l { margin-top: .6em; font-family: var(--font-body); font-weight: 500; font-size: .92rem; color: var(--stat-l); }

/* From tablet up the HERO BENTO's stat tiles are wide, short strips rather
   than tall blocks — number beside its label, not above it. That keeps the
   bento to a tall row + a thin row, which is what lets the waterline clear the
   fold on a laptop screen. Phones keep the stacked version; there is no room
   to sit a 2.6rem numeral next to two lines of text at 360px.
   Scoped to .bento on purpose: the Boca page puts .tile--stat in a 3-up
   .statrow where each tile is ~380px wide and must stay stacked. */
@media (min-width: 640px) {
  .bento .tile--stat {
    display: flex;
    align-items: center;
    gap: clamp(16px, 1.8vw, 26px);
  }
  .bento .tile--stat .stat__n { flex: none; font-size: clamp(2.3rem, 3.4vw, 3.1rem); }
  .bento .tile--stat .stat__l { margin-top: 0; }
}

/* The audience toggle hides tiles with the `hidden` attribute, which only
   works because nothing re-declares `display`. The flex rule above DID, and
   the off-audience tiles came back as a phantom 4th grid row. Keep this. */
.tile[hidden] { display: none; }

.hero__note {
  margin-top: clamp(24px, 3.5vw, 36px);
  font-size: .95rem;
  color: var(--ink-soft);
  max-width: 62ch;
}
.hero__note strong { color: var(--deep); }

/* Tablet bento: 2-col, pitch/photo span both, stats one each */
@media (min-width: 640px) and (max-width: 1023.98px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .t-pitch { grid-column: 1 / -1; }
  .t-photo { grid-column: 1 / -1; aspect-ratio: 16 / 10; }
  /* .t-a is the one tile shared by communities and careers, and each of those
     audiences now carries only it — so it takes the whole row rather than
     leaving an empty half-column. Residents is the audience with TWO stats
     (camp ages + swim ages), and those sit one per column by default. */
  .bento .t-a { grid-column: 1 / -1; }
  .hero__top { flex-direction: row; align-items: center; justify-content: space-between; }
}

/* Desktop bento: the signature 6-col grid, audience-driven placement */
@media (min-width: 1024px) {
  .hero__top { flex-direction: row; align-items: center; justify-content: space-between; }

  .bento {
    grid-template-columns: repeat(6, 1fr);
    /* Rows 1-2 carry the pitch/photo and must grow to fit their content;
       row 3 is the stat strip. min-height (never height) so nothing clips. */
    grid-template-rows: auto auto minmax(92px, auto);
    min-height: clamp(440px, 56vh, 600px);
  }
  /* Height comes from the rows it spans, not from its own content. */
  .t-photo { aspect-ratio: auto; min-height: 340px; }

  /* One stat per audience now sits under the pitch as a full-width strip.
     (Communities/residents used to carry a second 3:1 tile here.) */
  #bento[data-aud="communities"] .t-pitch { grid-column: 1 / 5; grid-row: 1 / 3; }
  #bento[data-aud="communities"] .t-photo { grid-column: 5 / 7; grid-row: 1 / 4; }
  #bento[data-aud="communities"] .t-a     { grid-column: 1 / 5; grid-row: 3 / 4; }

  /* Residents is the one audience with two stats — camp ages and swim ages
     split the strip beside the full-height photo. */
  #bento[data-aud="residents"] .t-photo { grid-column: 1 / 3; grid-row: 1 / 4; }
  #bento[data-aud="residents"] .t-pitch { grid-column: 3 / 7; grid-row: 1 / 3; }
  #bento[data-aud="residents"] .t-c     { grid-column: 3 / 5; grid-row: 3 / 4; }
  #bento[data-aud="residents"] .t-e     { grid-column: 5 / 7; grid-row: 3 / 4; }

  /* Careers dropped its second stat tile ("7 open roles", removed Aug 17 2026),
     so the experience tile takes the whole of row 3 — otherwise columns 4-6
     sit empty under the photo. */
  #bento[data-aud="careers"] .t-pitch { grid-column: 1 / 4; grid-row: 1 / 3; }
  #bento[data-aud="careers"] .t-photo { grid-column: 4 / 7; grid-row: 1 / 3; }
  #bento[data-aud="careers"] .t-a     { grid-column: 1 / 7; grid-row: 3 / 4; }
}

/* ---------- 10. Waterline seam ---------- */
.waterline {
  width: 100%;
  height: 130px;
  margin-top: -1px;
  pointer-events: none;
  line-height: 0;
}
.waterline svg { display: block; width: 100%; height: 100%; }
.wv--sky  { fill: var(--sky);  opacity: .55; }
.wv--sand { fill: var(--sand); opacity: .75; }
.wv--pool { fill: var(--pool); opacity: 1; }

/* SECTION SEAM — a slim, static restatement of the waterline above, for
   boundaries in the middle of the page. Same three logo ribbons, no JS.
   ⚠️ Deliberately NOT named .waterline: main.js queries '.waterline svg' and
   '.waterline .wv' to swap in a seamless periodic path and run the drift
   timeline, and it expects exactly one of them (querySelector). Naming this
   .waterline would hand the hero's animation the wrong element.
   The seam carries the ground of the section ABOVE it as its own background;
   its bottom ribbon is filled with the ground of the section BELOW, so the
   seam melts into that section and the ribbons read as the transition. */
.seam { line-height: 0; pointer-events: none; margin-bottom: -1px; }
.seam svg { display: block; width: 100%; height: clamp(34px, 4vw, 56px); }
.seam__wv--sky  { fill: var(--sky);  opacity: .55; }
.seam__wv--sand { fill: var(--sand); opacity: .75; }
.seam__wv--pool { fill: var(--pool); }
/* Ground-above / ground-below pair. Add a new modifier per boundary rather
   than hardcoding colours on the paths. */
.seam--tint { background: var(--tint); }
.seam--tint .seam__wv--base { fill: #fff; }

/* The waterline is the logo's three ribbons, so it needs to be ON SCREEN when
   the page loads — it was landing ~100px under the fold on a laptop. On a tall
   display the hero already clears it, so this only tightens the short ones.
   Keyed to viewport HEIGHT, not width: the problem is vertical, and a 1440x800
   laptop and a 1440x1100 desktop want different answers at the same width.
   Must stay AFTER the .waterline block above — same specificity, later wins.
   1100px is the handoff: untightened, the waves bottom out 1090px down, so
   anything taller than that already clears them. Don't lower it or you reopen
   a band of viewport heights that gets the waves half-cut.
   ⚠️ MEASURE THIS AT ~1600px WIDE, NOT 1440. The untightened hero grows with
   viewport WIDTH until two things top out: .wrap caps at 1240px, and
   .pitch h1's clamp(2rem, 3.1vw, 3rem) reaches 3rem at 1548px wide. Past
   ~1548px the height plateaus — 1600 and 1920 both bottom out at exactly
   1090. At 1440 it reads only 1023, which is how the old 980 value shipped
   too low: it was measured on a 1440 laptop, but a 1920x1200 desktop
   (~1070px viewport) fell in the dead band and got the waves clipped.
   Aug 17 2026: raised 980 -> 1100. Part of that was the Communities pitch
   gaining two chips ("FAST Swim Program certified" / "Certified swim
   instructors"), which wraps them to a third row and adds 45px — but 980 was
   already wrong before that (3-chip untightened height at 1600 wide = 1045).
   Re-measure at 1600 wide any time the pitch copy, chips, or CTAs change. */
@media (min-width: 1024px) and (max-height: 1100px) {
  .hero { padding-top: 28px; }
  .hero__top { margin-bottom: 20px; }
  .bento { min-height: 0; gap: 12px; }
  .bento .tile--pitch, .bento .tile--stat { padding: 22px 26px; }
  .pitch :is(h1, h2) { font-size: clamp(1.9rem, 2.6vw, 2.5rem); }
  .pitch__act { margin-top: 1em; }
  .pitch .chips { margin-top: .9em; }
  .hero__note { margin-top: 18px; }
  .waterline { height: 104px; }
}

/* Second step for genuinely short screens (1366x768 laptops, iPad landscape).
   At 1024 wide the h1 wraps to three lines, so the step above alone only
   cleared ~27px of the band.
   ⚠️ Was 790 until Aug 17 2026, for the same reason the tier above was 980:
   both were tuned on a 1440 laptop. On a WIDE short window (1600x800) step
   one alone leaves the hero 835px tall, so 791-835 clipped. Step two brings
   it to 783, so 840 covers that band with margin. Same rule as above —
   re-measure at ~1600 wide, not 1440.
   ⚠️ KNOWN REMAINING GAP: at >=1548px wide AND <=783px tall (e.g. 1600x768),
   even step two leaves ~15px of wave below the fold. Pre-existing and not
   yet fixed; it needs a third step or a hard cap on .pitch h1 out wide. */
@media (min-width: 1024px) and (max-height: 840px) {
  .hero { padding-top: 20px; }
  .hero__top { margin-bottom: 14px; }
  .bento .tile--pitch, .bento .tile--stat { padding: 18px 24px; }
  .pitch p { margin-top: .6em; }
  .pitch__act { margin-top: .85em; }
  .pitch .chips { margin-top: .75em; }
  .hero__note { margin-top: 14px; font-size: .9rem; }
  .waterline { height: 92px; }
}

/* ---------- 11. Ticker marquee ---------- */
.ticker {
  background: var(--deep);
  height: 62px;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.ticker__track {
  display: flex;
  width: max-content;
  will-change: transform;
}
.ticker__set { display: flex; align-items: center; flex-shrink: 0; }
.ticker__set span {
  font-family: var(--font-display);
  font-size: 1rem;
  color: rgba(255,255,255,.82);
  white-space: nowrap;
  letter-spacing: .01em;
}
.ticker__set span::after {
  content: '\25C6';
  display: inline-block;
  margin: 0 1.7em;
  font-size: .38em;
  vertical-align: middle;
  color: var(--sand);
}
.ticker:hover .ticker__track,
.ticker__track.is-paused { animation-play-state: paused; }

/* ---------- 12. Services ---------- */
.svcs {
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
  margin-top: 8px;
}
.svc {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-tile);
}
.svc__media { aspect-ratio: 4 / 3; overflow: hidden; background: var(--sky); }
.svc__media img { width: 100%; height: 100%; object-fit: cover; }
.svc__body { padding: clamp(22px, 3vw, 32px); }
.svc__body h3 { font-size: 1.3rem; margin-bottom: .55em; }
.svc__body > p { color: var(--ink-soft); }

.svc__cols { display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 1.4em; }
.svc__cols h4 { font-family: var(--font-body); font-weight: 700; font-size: .85rem; letter-spacing: .04em; text-transform: uppercase; color: var(--pool-dk); margin-bottom: .7em; }
.svc__cols ul { display: flex; flex-direction: column; gap: .55em; }
.svc__cols li {
  position: relative;
  padding-left: 1.3em;
  font-size: .92rem;
  color: var(--ink-soft);
}
.svc__cols li::before {
  content: '';
  position: absolute;
  left: 0; top: .45em;
  width: 7px; height: 7px;
  background: var(--sand);
}

.rates { display: flex; flex-direction: column; gap: 1em; margin-top: 1.2em; }
.rates dt { font-size: .74rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--pool-dk); }
.rates dd { margin-top: .3em; color: var(--ink-soft); font-size: .95rem; }
.rates dd strong { display: inline-block; font-family: var(--font-display); font-size: 1.5rem; color: var(--deep); margin-right: .35em; }
.rates dd span { display: block; margin-top: .2em; font-size: .85rem; }

.fineprint { margin-top: 1.2em; font-size: .82rem; color: var(--stat-l); font-style: italic; }

/* Scope-boundary line: what is an extra vs what is standard, and who supplies
   what. Deliberately NOT .fineprint — these are things the client wants read,
   not terms to be skimmed past, so they stay upright rather than italic. */
.addon { margin-top: 1.1em; font-size: .86rem; color: var(--ink-soft); }
.addon strong { color: var(--pool-dk); font-weight: 700; }

/* The programming half of the client's core-services sheet. Deliberately a
   panel and not a 5th .svc card: .svcs is a 3-col grid at 1024+, so a 5th
   card would orphan one in its own row, and every image on this page is
   already spoken for. Sand ground separates it from the white cards. */
.svcmore {
  margin-top: 28px;
  padding: clamp(22px, 3vw, 32px);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--sand) 26%, #fff);
}
.svcmore__head h3 { font-size: 1.3rem; margin-bottom: .45em; }
.svcmore__head p { color: var(--ink-soft); max-width: 60ch; }
/* .tags are a sand chip by default, which is near-invisible on a sand panel. */
.svcmore .tags li { background: #fff; }

/* Trust line straight off the flyer — closes the section rather than sitting
   inside any one card, because it is true of every service above it. */
.svccreds {
  margin-top: 24px;
  padding-left: 16px;
  border-left: 3px solid var(--sand);
  font-size: .9rem;
  color: var(--ink-soft);
  max-width: 88ch;
}
.svccreds strong { color: var(--deep); }

@media (min-width: 768px) {
  .svcmore__head { display: flex; align-items: baseline; gap: 24px; }
  .svcmore__head h3 { flex: none; max-width: 15ch; margin-bottom: 0; }
}

@media (min-width: 768px) {
  .svcs { grid-template-columns: repeat(2, 1fr); }
  .svc--wide { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr 1.15fr; align-items: stretch; }
  .svc--wide .svc__media { aspect-ratio: auto; height: 100%; }
  .svc__cols { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .svcs { grid-template-columns: repeat(3, 1fr); }
  .svc--wide { grid-column: 1 / -1; }
}
/* Location pages carry 3 service cards, not the homepage's 4. With the first
   one spanning full width, repeat(3,1fr) strands an empty cell on row 2, so
   the two remaining cards sit left with a hole beside them. Two columns fill
   the row exactly. ⚠️ Must stay AFTER the .svcs rules above — equal
   specificity, later wins, which is what beats their media queries. Same
   pattern as .areas--duo. */
@media (min-width: 1024px) {
  .svcs--duo { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- 13. CTA band ---------- */
.band { background: var(--deep); color: #fff; padding-block: clamp(48px, 6vw, 72px); }
.band__in {
  display: flex;
  flex-direction: column;
  gap: 28px;
}
.band h2 { color: #fff; font-size: clamp(1.5rem, 3vw, 2.1rem); line-height: 1.2; }
.band p { margin-top: .6em; color: rgba(255,255,255,.78); }
.band__act { display: flex; flex-wrap: wrap; gap: 14px; }

@media (min-width: 768px) {
  .band__in { flex-direction: row; align-items: center; justify-content: space-between; }
  .band__act { flex-shrink: 0; }
}

/* ---------- 14. Programs ---------- */
.progs { display: flex; flex-direction: column; gap: clamp(40px, 6vw, 64px); margin-top: 8px; }
/* Cap the media so a portrait shot (swim-lesson is 3:4) can't tower over a
   short body column and leave a void beside it. */
.prog__media img {
  width: 100%; height: auto;
  max-height: 560px; object-fit: cover;
  border-radius: var(--radius-lg); box-shadow: var(--shadow-tile);
}
.prog__k { color: var(--pool-dk); font-size: 1.05rem; margin-bottom: .3em; }
.prog__body h3 { font-size: clamp(1.4rem, 2.4vw, 1.75rem); margin-bottom: .55em; }
.prog__body > p { color: var(--ink-soft); }

.facts { display: flex; flex-direction: column; gap: .8em; margin-top: 1.4em; }
.facts li { font-size: .92rem; color: var(--ink-soft); }
.facts li span {
  display: block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .68rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--pool-dk);
  margin-bottom: .3em;
}

@media (min-width: 900px) {
  .prog { display: grid; grid-template-columns: 5fr 6fr; gap: 40px; align-items: center; }
  .prog--flip .prog__media { order: 2; }
  .prog--flip .prog__body { order: 1; }
}
@media (min-width: 1024px) {
  .prog__media { position: relative; z-index: 1; margin-right: -24px; }
  .prog--flip .prog__media { margin-right: 0; margin-left: -24px; }
}

/* ---------- 15. Directors ---------- */
.dirs { display: grid; grid-template-columns: 1fr; gap: 24px; margin-top: 8px; }
.dir {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(24px, 3vw, 36px);
  box-shadow: var(--shadow-tile);
}
.dir__hd h3 { font-size: 1.3rem; }
.dir__role { margin-top: .3em; font-weight: 600; font-size: .78rem; letter-spacing: .07em; text-transform: uppercase; color: var(--pool-dk); }
.dir > p { margin-top: 1.1em; color: var(--ink-soft); }

.creds { display: flex; flex-direction: column; gap: .6em; margin-top: 1.3em; }
.creds li { position: relative; padding-left: 1.5em; font-size: .9rem; color: var(--ink-soft); }
.creds li::before {
  content: '✓';
  position: absolute;
  left: 0; top: 0;
  color: var(--pool-dk);
  background: color-mix(in srgb, var(--sand) 55%, #fff);
  width: 1.1em; height: 1.1em;
  border-radius: 50%;
  font-size: .78rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

@media (min-width: 768px) { .dirs { grid-template-columns: repeat(2, 1fr); } }
/* Eric is the only director as of Aug 17 2026, and a lone card in a 2-col
   grid reads as a missing second person. Keep it single-column and centred,
   capped so the bio doesn't run to a 1240px measure. Must stay AFTER the
   media query above — equal specificity, later wins. */
.dirs--solo { grid-template-columns: 1fr; max-width: 720px; margin-inline: auto; }

/* ---------- 16. Certification ---------- */
.cert { display: flex; flex-direction: column; gap: clamp(32px, 5vw, 48px); color: #fff; }
.cert__media { position: relative; }
.cert__media > img:first-child { width: 100%; height: auto; border-radius: var(--radius-lg); }
.cert__inset {
  display: none;
  width: 46%;
  height: auto;
  border-radius: var(--radius-md);
  border: 8px solid var(--deep);
  box-shadow: 0 20px 44px -16px rgba(0,0,0,.45);
}
.cert__body h2 { color: #fff; margin-top: .5em; }
.cert__body > p { margin-top: 1em; color: rgba(255,255,255,.82); max-width: 60ch; }

.cert__grid { display: flex; flex-direction: column; gap: 16px; margin-top: 1.8em; }
.cert__card {
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--radius-md);
  padding: 1.4em 1.5em;
}
.cert__card h3 { color: #fff; font-size: 1.05rem; }
.cert__card p { margin-top: .5em; color: rgba(255,255,255,.75); font-size: .92rem; }
/* .sec--cert's ground is var(--deep) and so is .btn's default fill, so a plain
   button renders invisible here. The hover has to be restated too: .btn:hover
   swaps in var(--pool-dk), which would leave deep text on a mid-blue. */
.cert__card .btn { background: #fff; color: var(--deep); margin-top: 1em; }
.cert__card .btn:hover { background: var(--cabana); color: var(--deep); }

/* Each course carries its own photo. A thumbnail beside the copy, not a
   banner above it: these cards live in the narrow right-hand column of a
   2-col section, and three stacked banners would make the section taller
   than the sticky-header viewport. */
/* ⚠️ Scoped to cards that HAVE a thumbnail. Unscoped this hit every .cert__card,
   including Boca's people cards, whose children are a bare <h3> and <p> — they
   became flex items and rendered SIDE BY SIDE. Only the homepage's course cards
   wrap their copy in .cert__cardbody, so only they should go horizontal. */
.cert__card:has(.cert__thumb) { display: flex; gap: 1.1em; align-items: flex-start; }
.cert__cardbody { min-width: 0; }
.cert__thumb {
  flex: none;
  width: 76px; height: 76px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(255,255,255,.18);
}
@media (min-width: 480px) { .cert__thumb { width: 104px; height: 104px; } }

.cert__h { margin-top: 2em; font-size: 1.15rem; color: #fff; display: flex; flex-direction: column; gap: .3em; }
.cert__h span { font-family: var(--font-body); font-weight: 500; font-size: .78rem; color: rgba(255,255,255,.6); letter-spacing: .02em; }

.classes { display: flex; flex-direction: column; margin-top: 1em; }
.classes li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .3em 1em;
  padding: .9em 0;
  border-top: 1px solid rgba(255,255,255,.14);
  font-size: .92rem;
}
.classes li:last-child { border-bottom: 1px solid rgba(255,255,255,.14); }
.classes time { font-family: var(--font-display); color: var(--sand); font-size: 1.05rem; min-width: 8em; }
.classes span { color: #fff; font-weight: 600; }
/* Class-type column. Sky rather than white so the eye reads date -> type ->
   place as three distinct columns instead of one run-on line. Needs the
   .classes prefix to outrank `.classes span` above on specificity — a bare
   .classes__type loses to it and silently renders white. */
.classes .classes__type { color: var(--sky); font-weight: 700; font-size: .82rem; letter-spacing: .02em; min-width: 12.5em; }
.classes small { flex-basis: 100%; color: rgba(255,255,255,.6); }
.cert .btn { margin-top: 1.8em; }

@media (min-width: 640px) {
  .cert__inset { display: block; position: absolute; right: clamp(-14px, -2vw, -28px); bottom: clamp(-14px, -2vw, -28px); }
}
@media (min-width: 1024px) {
  .cert { flex-direction: row; align-items: center; }
  .cert__media, .cert__body { flex: 1 1 0; }
  /* The address deliberately stays on its own row even out wide. It used to
     sit inline (nowrap + margin-left:auto), but the class-type column added
     Aug 17 2026 makes four columns in a ~550px half-section — the venue name
     then wrapped to 3-4 lines. Date | type | venue on one row, address under. */
  .classes small { margin-left: 0; }
}

/* ---------- 17. Service area ---------- */
.areas { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 8px; }
.areas li {
  padding-top: 18px;
  border-top: 3px solid var(--sand);
}
.areas h3 { font-size: 1.15rem; }
.areas p { margin-top: .5em; color: var(--ink-soft); font-size: .92rem; }

/* 8 counties as of Aug 18 2026 (Volusia added — Ormond Beach is Volusia, not
   Flagler). 4-up on desktop, not 8-up: at 8 columns each cell is ~150px and
   "Palm Beach County" wraps to three lines. 4 divides 8 evenly, so desktop is
   a clean 4/4 and the 640px tier is 3/3/2 — neither orphans a card. Was
   repeat(6) at six counties and repeat(4) at seven — re-pick this if it changes.
   .areas--duo (location pages) must stay AFTER this to win on equal specificity. */
@media (min-width: 640px)  { .areas { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .areas { grid-template-columns: repeat(4, 1fr); } }

/* ---------- 18. Careers ---------- */
.careers { display: flex; flex-direction: column-reverse; gap: clamp(28px, 4vw, 40px); align-items: center; }
.careers__body h2 { margin-top: .5em; }
.careers__body > p { margin-top: 1em; color: var(--ink-soft); max-width: 56ch; }
/* Cap the media the same way .prog__media does — the hiring shot is a
   portrait (1100x1466), and unconstrained it towers over the body column. */
.careers__media img {
  width: 100%; height: auto;
  max-height: 520px; object-fit: cover;
  border-radius: var(--radius-lg); box-shadow: var(--shadow-tile);
}

.roles { display: grid; grid-template-columns: 1fr; gap: 10px; margin-top: 1.6em; }
.roles li {
  font-size: .88rem;
  font-weight: 600;
  color: var(--deep);
  background: color-mix(in srgb, var(--sand) 32%, #fff);
  border-radius: 999px;
  padding: .65em 1.1em;
  text-align: center;
}
.careers .pitch__act { margin-top: 1.8em; }

@media (min-width: 640px) { .roles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) {
  .careers { flex-direction: row; align-items: center; }
  .careers__body, .careers__media { flex: 1 1 0; }
}

/* ---------- 19. FAQ ---------- */
.faqwrap { max-width: 820px; }
.faq { border-top: 1px solid var(--line); margin-top: 8px; }
.faq details { border-bottom: 1px solid var(--line); padding-block: .3em; }
.faq summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 1.1em 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--deep);
  -webkit-tap-highlight-color: transparent;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  flex-shrink: 0;
  width: 1.4em; height: 1.4em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-size: 1.3rem;
  color: var(--pool-dk);
  border: 1px solid var(--line);
  border-radius: 50%;
  transition: transform .25s ease;
}
.faq details[open] summary::after { content: '\00D7'; transform: rotate(180deg); }

@media (hover: hover) {
  .faq summary:hover { color: var(--pool-dk); }
  .faq summary:hover::after { border-color: var(--pool-dk); }
}

.faq details > div { overflow: hidden; }
.faq details > div p { padding-bottom: 1.3em; color: var(--ink-soft); max-width: 68ch; }

/* Native <details> needs no JS to open/close — this is the functional
   baseline. main.js progressively enhances this into a smooth height +
   opacity tween (GSAP) by intercepting the click; without GSAP the browser's
   instant native toggle below still works correctly. */
.faq details:not([open]) > div { display: none; }

/* ---------- 20. Quote ---------- */
.quote { display: flex; flex-direction: column; gap: clamp(32px, 5vw, 48px); color: #fff; }
.quote__side h2 { color: #fff; margin-top: .5em; }
.quote__side > p { margin-top: 1em; color: rgba(255,255,255,.8); max-width: 52ch; }

.quote__facts { display: flex; flex-direction: column; gap: .8em; margin-top: 1.8em; }
.quote__facts li { display: flex; gap: .8em; align-items: baseline; font-size: .95rem; }
/* min-width is what keeps the three values in one column. It must clear the
   WIDEST label — "CALL OR TEXT" as of Aug 17 2026, not the old 4-char "CALL".
   That label measures ~90px, so 8em (92px) technically fits but leaves only
   2px; 8.75em keeps ~10px of slack for font fallback / other platforms.
   Below 480px the labels go full width on their own row instead: at this
   floor the label + gap left too little for the email on a 320px screen. */
.quote__facts span { font-weight: 700; font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; color: var(--sand); min-width: 8.75em; }
@media (max-width: 479px) {
  .quote__facts li { flex-wrap: wrap; gap: .15em .8em; }
  .quote__facts span { min-width: 100%; }
}
.quote__facts a { color: #fff; font-weight: 600; }
.quote .chips { margin-top: 1.8em; }

.qform {
  background: #fff;
  border-radius: var(--radius-lg);
  padding: clamp(22px, 3vw, 34px);
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
  box-shadow: var(--shadow-tile);
}
/* min-width:0 — grid items default to min-width:auto, so without this the .f
   track can't shrink below an input's intrinsic size and the form pushes the
   page sideways at 320px. */
.f { display: flex; flex-direction: column; gap: .5em; min-width: 0; }
.f[hidden] { display: none; } /* same [hidden]-vs-class cascade fix as .mnav */
.f--full { grid-column: 1 / -1; }
.f label { font-size: .85rem; font-weight: 600; color: var(--deep); }
.f input, .f select, .f textarea {
  width: 100%;
  min-width: 0;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: .8em .9em;
  font-size: .95rem;
  color: var(--deep);
  transition: border-color .2s ease, box-shadow .2s ease;
}
.f input:focus, .f select:focus, .f textarea:focus {
  outline: none;
  border-color: var(--pool);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--pool) 45%, transparent);
}
.f textarea { resize: vertical; min-height: 100px; }
.err { font-size: .8rem; color: #C0392B; }
.err:empty { display: none; }
.f input[aria-invalid="true"], .f select[aria-invalid="true"], .f textarea[aria-invalid="true"] {
  border-color: #C0392B;
}
.promise { margin-top: .8em; font-size: .8rem; color: var(--stat-l); text-align: center; }

/* Honeypot. Off-screen rather than display:none, which the better bots detect
   and skip. .qform isn't positioned, so this anchors to the page — -9999px
   puts it out of reach either way. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* The send failed. Lives inside .f--full, not directly in the grid, so no
   grid-column here. Same red as .err, on the same white card. */
.qform__err { margin-top: .8em; font-size: .85rem; font-weight: 600; color: #C0392B; text-align: center; }
.qform__err[hidden] { display: none; }

.qform__ok { grid-column: 1 / -1; text-align: center; padding: 1.5em 0; }
.qform__ok h3 { font-size: 1.4rem; }
.qform__ok p { margin-top: .7em; color: var(--ink-soft); }
.qform__ok a { color: var(--pool-dk); font-weight: 700; }

@media (min-width: 640px) { .qform { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .quote { flex-direction: row; align-items: center; } .quote__side, .qform { flex: 1 1 0; } }

/* ---------- 21. Footer ---------- */
.ftr { background: var(--deep); color: #fff; padding-top: clamp(48px, 6vw, 72px); }
.ftr__in { display: flex; flex-direction: column; gap: 40px; padding-bottom: 40px; }
.ftr__brand img { height: 40px; width: auto; }
.ftr__tag { margin-top: 1em; color: rgba(255,255,255,.65); max-width: 34ch; font-size: .92rem; }

.ftr__nav { display: grid; grid-template-columns: 1fr; gap: 28px; }
.ftr__nav h3 { font-family: var(--font-body); font-weight: 700; font-size: .78rem; letter-spacing: .07em; text-transform: uppercase; color: var(--sand); margin-bottom: 1em; }
.ftr__nav div { display: flex; flex-direction: column; gap: .7em; }
.ftr__nav a, .ftr__nav p { color: rgba(255,255,255,.78); font-size: .92rem; }
.ftr__nav a:hover { color: #fff; }

.ftr__btm {
  border-top: 1px solid rgba(255,255,255,.12);
  padding-block: 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: .82rem;
  color: rgba(255,255,255,.6);
}
.ftr__btm a { color: rgba(255,255,255,.75); }
.ftr__btm-left { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }

/* FPM credit — one pure-alpha lockup asset tinted per site via CSS mask, so it
   picks up this site's palette instead of landing as black-and-white. */
.fpm-credit { display: inline-flex; align-items: center; gap: .55rem; text-decoration: none; }
.fpm-credit__label {
  font-size: .78rem; color: var(--sky); opacity: .72;
  transition: opacity 180ms cubic-bezier(.2,.8,.2,1), color 180ms cubic-bezier(.2,.8,.2,1);
}
.fpm-credit__mark {
  display: block; width: 183px; height: 36px; background-color: var(--sky);
  -webkit-mask-image: url(/img/fpm-credit-lockup-v1.png);
  mask-image: url(/img/fpm-credit-lockup-v1.png);
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  opacity: .72;
  transition: opacity 180ms cubic-bezier(.2,.8,.2,1), background-color 180ms cubic-bezier(.2,.8,.2,1);
}
.fpm-credit:hover .fpm-credit__mark, .fpm-credit:focus-visible .fpm-credit__mark { opacity: 1; background-color: var(--sand); }
.fpm-credit:hover .fpm-credit__label, .fpm-credit:focus-visible .fpm-credit__label { opacity: 1; color: var(--sand); }
@media (max-width: 700px) {
  .fpm-credit__mark { width: 152px; height: 30px; }
  .fpm-credit__label { font-size: .74rem; }
}

@media (min-width: 640px) { .ftr__nav { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px) {
  .ftr__in { flex-direction: row; justify-content: space-between; }
  .ftr__nav { flex: 1 1 0; margin-left: auto; max-width: 640px; }
  .ftr__btm { flex-direction: row; justify-content: space-between; }
}

/* ---------- 22. Sticky mobile call bar ---------- */
.callbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 90;
  display: flex;
  transform: translateY(100%);
  transition: transform .3s ease;
  padding-bottom: env(safe-area-inset-bottom);
  box-shadow: 0 -8px 24px rgba(18,41,63,.18);
}
.callbar.is-on { transform: translateY(0); }
.callbar a {
  flex: 1 1 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  padding: 1em 0;
  font-weight: 700;
  font-size: .92rem;
  color: #fff;
}
.callbar a svg { width: 1.1em; height: 1.1em; fill: currentColor; }
.callbar__tel { background: var(--deep); }
.callbar__cta { background: var(--pool-dk); }

@media (min-width: 768px) { .callbar { display: none; } }

/* ---------- 23. Motion & animation hygiene ---------- */
/* No blanket will-change: entrance tweens are transform/opacity only and run
   once, so a permanent compositor hint would just hold layers for nothing. */

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Anchor targets must clear the sticky header — covers native :target,
   keyboard navigation, and the reduced-motion instant-jump path, not just
   the JS smooth-scroll offset. */
:where(#services, #programs, #directors, #certification, #areas, #careers, #faq, #quote,
       #swim, #events, #staffing, #areas-boca, #faq-boca) {
  scroll-margin-top: 96px;
}

/* ==========================================================================
   BOCA RATON LOCATION PAGE — additive block.
   Only new selectors introduced anywhere in this file: .crumb, .lochero,
   .lochero__grid, .lochero__media, .statrow. Everything else on
   boca-raton.html reuses classes already defined above unchanged.
   ========================================================================== */

/* Breadcrumb row above the location hero copy. */
.crumb {
  display: flex;
  align-items: center;
  gap: .55em;
  font-size: .82rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: clamp(16px, 2.5vw, 26px);
}
.crumb a { color: var(--pool-dk); }
.crumb a:hover, .crumb a:focus-visible { text-decoration: underline; }
.crumb span[aria-current] { color: var(--deep); }

/* Two-column locale hero: copy (reuses .pitch) + media tile. No bento,
   no audience toggle — this page has one audience. */
.lochero .wrap { padding-bottom: clamp(28px, 4vw, 44px); }

.lochero__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(32px, 5vw, 56px);
  align-items: center;
}
@media (min-width: 900px) {
  .lochero__grid { grid-template-columns: 1.05fr .95fr; }
}

/* Right column: photo with the credential chips stacked under it. Keeping the
   chips here rather than in .pitch is what balances the two columns — the copy
   column runs much taller than a 16:9 photo on its own. */
.lochero__side {
  display: grid;
  gap: 14px;
  align-content: center;
}

.lochero__media {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-tile);
  line-height: 0;
}
.lochero__media img { width: 100%; height: auto; display: block; }

/* The column gap already separates these from the photo — .chips' own
   margin-top is meant for when it trails body copy. */
.lochero__side .chips { margin-top: 0; }

/* 2-up stat strip beneath the hero grid, above the waterline. Was 3-up until
   the swim-ratio stat came out; two tiles means each is wide enough to run the
   number inline with its label, which is what lets the waterline clear the
   fold on a laptop (see the short-viewport block below). */
.statrow {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
  margin-top: clamp(32px, 5vw, 48px);
}
@media (min-width: 640px) {
  .statrow { grid-template-columns: repeat(2, 1fr); }
}

/* The waterline is the logo's three ribbons, so it has to be ON SCREEN when
   the page loads — same requirement the homepage solves in its own block near
   .waterline. Untightened this hero ends ~995px down and the whole 104px band
   sits under the fold on a 14" laptop.

   Keyed to viewport HEIGHT for the same reason as the homepage: the problem is
   vertical. A tall display already clears the waves and keeps the roomier
   spacing.

   The handoff is 1100px, NOT the homepage's 1100-by-coincidence and NOT the
   980 this started at — this hero is taller, and untightened its waves now end
   1098px down. Every previous value left a dead band: at 980 it was ~985-1009,
   and at 1010 it was ~1011-1098 (the Aug 17 2026 hero chips added two rows and
   +89px). In that band tightening is off but the waves still don't fit, so the
   bottom of the band gets clipped.
   ⚠️ MEASURE AT ~1600 WIDE, NOT 1440: this hero grows with viewport WIDTH until
   .wrap caps at 1240 and .pitch h1's clamp tops out at 1548, so a 1440 laptop
   understates the height. If you change anything above that moves the
   untightened height — chips especially — re-measure and move this to match. */
@media (min-width: 1024px) and (max-height: 1100px) {
  .lochero { padding-top: 18px; }
  .lochero .crumb { margin-bottom: 12px; }
  .lochero .wrap { padding-bottom: 22px; }
  .lochero__grid { gap: clamp(28px, 4vw, 44px); }

  /* Trim the copy column — it, not the photo, is what sets the grid height. */
  .lochero .pitch :is(h1, h2) { font-size: clamp(1.9rem, 2.7vw, 2.45rem); }
  .lochero .pitch > p { font-size: .95rem; }
  .lochero .pitch__act { margin-top: .9em; }

  /* At default size these are too wide to pair up in a ~520px column, so all
     three stack. Shaving them lets two share a row and drops a whole row. */
  .lochero__side .chips li { font-size: .72rem; padding: .4em .8em; }

  .statrow { margin-top: 22px; }
  /* Number inline with the label instead of stacked above it — roughly halves
     the strip's height, the single biggest saving available here. */
  .statrow .tile--stat {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 18px 24px;
  }
  .statrow .tile--stat .stat__n { flex: none; font-size: clamp(2.2rem, 3.2vw, 2.9rem); }
  .statrow .tile--stat .stat__l { margin-top: 0; }
}

/* Service area on a location page — two counties, not the homepage's six.
   The shared .areas grid goes to repeat(6, 1fr) at 1024px, which squeezes two
   cards into narrow stubs against the left edge with four empty columns beside
   them, under a centred section header. Size to two columns and centre the
   pair. These rules sit after the .areas block above on purpose: same
   specificity, later wins, so they beat its media queries at every width. */
.areas--duo {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  max-width: 640px;
  margin-inline: auto;
  gap: clamp(24px, 4vw, 48px);
}
@media (max-width: 559px) {
  .areas--duo { grid-template-columns: minmax(0, 1fr); max-width: 340px; }
}

/* Centred, width-capped chip block. Left alone, ten locations run the full
   page width and leave an orphaned two-chip row hanging off the left edge. */
.chips--center {
  justify-content: center;
  max-width: 860px;
  margin-inline: auto;
}

/* Drops the ✓ that .chips li::before adds. A tick reads as "we are certified
   in this" — right for a credential chip, wrong for a list of place names,
   which is what the service-area block is. Place names only. */
.chips--plain li::before { content: none; }

/* Closing note under a centred section reads as debris when left-aligned. */
.areas__note { text-align: center; max-width: 640px; margin-inline: auto; }

/* Second, tighter tier. A 1280x800 laptop leaves only ~700px of page once the
   menu bar and browser chrome are gone, and the block above still lands the
   waves ~18px under it. The photo is the last big block that can give: crop it
   to a wider ratio instead of letting its 16:9 height set the column. */
@media (min-width: 1024px) and (max-height: 780px) {
  .lochero__media { aspect-ratio: 16 / 7.5; }
  .lochero__media img { height: 100%; object-fit: cover; }
  .statrow .tile--stat { padding: 14px 22px; }
}
