/* ==========================================================================
   Jump! Gymnastics — design system

   Type and button language captured from the live Elementor kit
   (--e-global-color-* / --e-global-typography-*) on September 6, 2026.

   The palette was captured from the same kit, then reconciled against Jump!'s
   own brand palette on September 9, 2026. Where the two disagreed the brand palette
   won, because the website is a rendering of the brand and not the other way
   round. The only disagreement of any size was the teal. Nothing here is
   invented except --cream and --pink-deep, both flagged where they are set.
   ========================================================================== */

:root{
  /* --- The eight-color brand palette (+ neutrals) ---------------------- */
  --sky:      #72A6D9;  /* Elementor "primary"   */
  --orange:   #F47920;  /* Elementor "secondary" */
  --lime:     #BACD32;  /* Elementor "text"      */
  --yellow:   #FFDF28;  /* Elementor "accent"    */
  --navy:     #3551A3;
  --red:      #F2295B;
  --rose:     #E366A6;
  --grass:    #7AB742;
  --teal:     #00AAB0;
  --cocoa:    #5B4722;
  --crimson:  #DA1C39;
  --pink:     #F9428C;  /* the hot-pink pill button */
  --cream:    #FFF8EE;  /* hero ground: warmer than white, still lets
                           the photography and the confetti carry */
  --pink-deep:#D62D74;  /* footer ground. NOT from the Elementor kit: it is the
                           brand pink brought down until white text clears the
                           4.5:1 contrast bar. See the footer block below. */

  /* --- From Jump!'s own brand palette, September 9, 2026 -----------------------
     Amy sent the brand kit. Most of it already matched the Elementor kit
     exactly (light blue, lime, grass, orange, rose, cocoa). These are the
     ones that did not, plus three the site had never carried. */
  --yellow-lt:#FFE548;  /* brand yellow, light  */
  --yellow-dp:#FFD815;  /* brand yellow, deep   */
  --indigo:   #120052;  /* brand deep indigo    */
  --lime-pale:#F4F6C6;  /* brand pale lime      */

  /* Teal has to exist twice, and this is not a second opinion about the
     brand color. #00AAB0 is the brand teal and it is what fills a shape.
     But it measures 2.85:1 against white, so small type in it — every
     .eyebrow on the site — fails AA, and white type ON it fails too. This
     is the same hue darkened to exactly the point where it clears 4.5:1,
     for those two jobs only. It was already failing at the old #00A0AB
     (3.17:1); moving to the true brand teal made it slightly worse, which
     is what surfaced it. */
  --teal-ink: #008489;

  /* --- Neutrals -------------------------------------------------------- */
  --white:    #FFFFFF;
  --paper:    #F6F6F6;
  --slate:    #5E6365;
  --ink:      #5E6365;
  --black:    #0D0D0D;

  /* --- Semantic -------------------------------------------------------- */
  --bg:        var(--white);
  --bg-alt:    var(--paper);
  --text:      var(--ink);
  --text-soft: var(--slate);
  --heading:   var(--black);

  /* --- Type ------------------------------------------------------------ */
  --display: "Baloo 2", "Trebuchet MS", system-ui, sans-serif;
  /* The live site sets its biggest headline in Love Ya Like A Sister, not
     Baloo — that hand-lettered look is a lot of what Randy means by "the
     vibe". It is on Google Fonts under the OFL, so there is no licensing
     question and no file to host. Jump!'s Canva kit names Minya Nouvelle
     instead; that one is NOT a Google font and its license needs checking,
     so it is flagged to Amy rather than guessed at. Display only — it is
     unreadable at body sizes. */
  --display-hero: "Love Ya Like A Sister", var(--display);
  --body: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Fluid scale — mobile first, no media queries needed for size */
  --step--1: clamp(.875rem, .84rem + .18vw, 1rem);
  --step-0:  clamp(1rem, .95rem + .25vw, 1.125rem);   /* 16 → 18, matches live 18px */
  --step-1:  clamp(1.15rem, 1.05rem + .5vw, 1.5rem);  /* live large body = 24px */
  --step-2:  clamp(1.4rem, 1.2rem + 1vw, 2rem);
  --step-3:  clamp(1.75rem, 1.4rem + 1.75vw, 2.75rem);
  --step-4:  clamp(2.1rem, 1.5rem + 3vw, 3.75rem);    /* live H1 = 60px */

  /* --- Shape ----------------------------------------------------------- */
  --pill: 50px;          /* live primary button radius */
  --pill-sm: 30px;       /* live secondary button radius */
  --card-radius: 28px;
  --img-radius: 24px;

  /* --- Rhythm ---------------------------------------------------------- */
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --section: clamp(3.5rem, 8vw, 7rem);
  --wrap: 1200px;
  --wrap-narrow: 760px;

  /* --- Depth ----------------------------------------------------------- */
  --lift-1: 0 2px 6px rgba(13,13,13,.06), 0 8px 24px rgba(13,13,13,.06);
  --lift-2: 0 4px 12px rgba(13,13,13,.08), 0 18px 44px rgba(13,13,13,.10);
  --ring: 0 0 0 4px rgba(249,66,140,.28);
}

/* ==========================================================================
   Reset / base
   ========================================================================== */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;overflow-x:hidden}
body{
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--body);
  font-size:var(--step-0);
  font-weight:500;              /* live body weight */
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img,svg,video{max-width:100%;height:auto;display:block}
a{color:inherit}
button{font:inherit;color:inherit}

h1,h2,h3,h4,.display{
  font-family:var(--display);
  font-weight:900;              /* live display weight */
  line-height:1.12;
  color:var(--heading);
  margin:0 0 .5em;
  letter-spacing:-.01em;
}
h1{font-size:var(--step-4)}
h2{font-size:var(--step-3)}
h3{font-size:var(--step-2)}
h4{font-size:var(--step-1)}
p{margin:0 0 1.1em}
p:last-child{margin-bottom:0}

/* Skip link — was present on the old site, kept */
.skip{
  position:absolute;left:-9999px;top:0;z-index:999;
  background:var(--pink);color:#fff;padding:.75rem 1.25rem;
  border-radius:0 0 var(--pill-sm) 0;font-family:var(--display);font-weight:700;
}
.skip:focus{left:0}

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

/* ==========================================================================
   Layout
   ========================================================================== */
.wrap{width:min(100% - (var(--gutter) * 2), var(--wrap));margin-inline:auto}
.wrap-narrow{width:min(100% - (var(--gutter) * 2), var(--wrap-narrow));margin-inline:auto}
.section{padding-block:var(--section)}
.section--tint{background:var(--bg-alt)}

/* --------------------------------------------------------------------------
   Color bands.

   Randy asked for the old site's colors and backgrounds. That site runs
   full-bleed bands of lime, sky and teal behind whole sections; this build had
   been using the same palette almost entirely as accents on white. Amy's call
   was a middle path — a few color moments, not every section — so there are
   three on the homepage: lime behind the programs, lime behind the reviews,
   and the navy Adventure Path that was already there. The programs band was
   --lime-pale until BugHerd #17, where Randy pinned its divider and asked to
   see it "in the right colors"; the band on his own site is the full lime.
   --lime-pale and .section--limepale are kept for whoever wants the quieter
   version back, and because the pale lime is a real brand color.

   The text overrides are not taste. Measured on lime #BACD32: --ink is 5.08:1
   and passes, but --slate (which .lede uses) is 3.44:1 and does not, and the
   teal .eyebrow is worse. So a lime band restates those in ink and black.
   Sky #72A6D9 is deliberately NOT used as a text band: --ink on it is 3.50:1,
   which fails for body copy, and fixing that would mean black body text and a
   different-looking section.
   -------------------------------------------------------------------------- */
.section--limepale{background:var(--lime-pale)}

.section--lime{background:var(--lime)}
.section--lime h2,.section--lime h3{color:var(--black)}
.section--lime .eyebrow{color:var(--black)}
.section--lime .lede,.section--lime p{color:var(--ink)}

/* --------------------------------------------------------------------------
   Section dividers — the "transitions" between those bands. Geometry copied
   off the live site; see templates/layout.mjs.

   line-height:0 matters: an inline SVG in a block sits on the text baseline
   and leaves a few pixels of the section's own background showing under it,
   which reads as a hairline stripe between two colors.
   -------------------------------------------------------------------------- */
.divide{display:block;width:100%;line-height:0;margin:0}
/* A divider that closes a section is its LAST child, so the section's bottom
   padding rendered underneath it — the same defect the hero had. On the pale
   lime band nobody could see it; on the brand lime it is a stripe of green
   below a white wave. The gap moves above the divider so the shape ends the
   section. Only sections that actually close with one are touched. */
.section:has(> .divide:last-child){padding-bottom:0}
.section > .divide:last-child{margin-top:var(--section)}
.divide svg{display:block;width:100%;height:var(--dh,44px)}
.divide--flip svg{transform:scaleY(-1)}
/* The bands are the point of these, and at 390px a 52px wave eats a third of
   what is on screen. Scale them down rather than dropping them. */
@media (max-width:700px){.divide svg{height:calc(var(--dh,44px) * .6)}}

.eyebrow{
  font-family:var(--display);font-weight:800;
  font-size:var(--step--1);letter-spacing:.14em;text-transform:uppercase;
  color:var(--teal-ink);margin:0 0 .75rem;   /* not --teal: see the note in :root */
}
.lede{font-size:var(--step-1);line-height:1.55;color:var(--text-soft)}
.center{text-align:center}
.stack > * + *{margin-top:1rem}

/* --------------------------------------------------------------------------
   Background overlays.

   BugHerd #17: "I will also want to see background overlays to make the site
   look professional." That is Elementor's own term for a feature, not a vague
   ask — jumpgymnastics.com carries six .elementor-background-overlay layers,
   and two of them do the visible work: gymnastics line-art tiled over the lime
   band at 5 percent, and a confetti-dots texture behind the hero. Both are
   Jump!'s own artwork, now in the GCS bucket beside the photography.

   Served through Netlify's image CDN rather than straight from the bucket,
   because a CSS background never passes through optimizeImages() in build.mjs
   — that only rewrites <img> tags, so a background would ship the full-size
   original with no format negotiation. Measured against the live deploy with a
   real browser Accept header: the lime texture is 14.2 KB as WebP at 450px
   where the 1080px original is 70.3 KB, and the dots are 11.3 KB against
   112 KB. About 26 KB for the pair, less than one of the photographs.

   The path is root-relative, so on a local build or a --base= preview these
   404 and each section falls back to its flat color — exactly how it looked
   before. Decorative, so nothing is lost when that happens.
   -------------------------------------------------------------------------- */
/* position, not just isolation. `inset:0` resolves against the nearest
   POSITIONED ancestor, and isolation does not create one — .hero already had
   position:relative so its overlay was contained, .section--lime did not, and
   the gymnastics texture tiled across the entire page. Caught by painting the
   ::before boxes solid red on the deploy rather than by reading the CSS. */
.hero,.section--lime{position:relative;isolation:isolate}
.hero::before,.section--lime::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
}
/* The same 5 percent he uses. Any more and it competes with the reviews. */
.section--lime::before{
  background:url("/.netlify/images?url=https%3A%2F%2Fstorage.googleapis.com%2Fjump-gymnastics%2Fsite%2Fgymnastics-overlay-2.png&w=450&q=75") repeat;
  background-size:450px auto;
  opacity:.05;
}
/* multiply rather than opacity alone: the source is colored dots on a WHITE
   ground, and laying that over the cream hero at full strength would repaint
   the hero white. Multiplied, white is a no-op and only the dots land. */
.hero::before{
  background:url("/.netlify/images?url=https%3A%2F%2Fstorage.googleapis.com%2Fjump-gymnastics%2Fsite%2Fdots-02.jpg&w=1400&q=75") repeat center top;
  background-size:cover;
  mix-blend-mode:multiply;opacity:.45;
}

/* ==========================================================================
   Buttons — pill language taken from the live site
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  font-family:var(--display);font-weight:700;
  font-size:clamp(1rem,.95rem + .35vw,1.35rem);
  text-transform:uppercase;letter-spacing:.02em;
  text-decoration:none;cursor:pointer;
  padding:.7em 1.5em;border-radius:var(--pill);border:0;
  background:var(--pink);color:#fff;
  box-shadow:0 4px 0 rgba(0,0,0,.12);
  transition:transform .18s cubic-bezier(.34,1.56,.64,1), box-shadow .18s, background-color .18s;
}
.btn:hover{transform:translateY(-3px);box-shadow:0 7px 0 rgba(0,0,0,.14)}
.btn:active{transform:translateY(1px);box-shadow:0 2px 0 rgba(0,0,0,.14)}
.btn:focus-visible{box-shadow:var(--ring), 0 4px 0 rgba(0,0,0,.12)}

.btn--sm{font-size:1.0625rem;font-weight:900;padding:.6em 1.35em;border-radius:var(--pill-sm)}
.btn--rose{background:var(--rose)}
.btn--teal{background:var(--teal-ink)}   /* white label needs the darker teal */
.btn--navy{background:var(--navy)}
.btn--ghost{
  background:transparent;color:var(--navy);
  box-shadow:inset 0 0 0 3px currentColor;
}
.btn--ghost:hover{background:var(--navy);color:#fff;box-shadow:none}

/* ==========================================================================
   Header — Randy's one written request: "the main menu should be on one line"
   ========================================================================== */
.header{
  /* One number drives the bar height and the top of the mobile drawer, so the
     two can never drift apart when the logo size changes. */
  --headerH:96px;
  position:sticky;top:0;z-index:100;
  background:rgba(255,255,255,.94);
  backdrop-filter:saturate(1.6) blur(10px);
  border-bottom:1px solid rgba(13,13,13,.07);
  transition:box-shadow .25s;
}
.header[data-stuck="true"]{box-shadow:var(--lift-1)}
.header__bar{
  display:flex;align-items:center;gap:clamp(.6rem,1.6vw,1.75rem);
  min-height:var(--headerH);
}
.header__logo{flex:0 0 auto;display:flex;align-items:center}
/* The logo is the brand. It was undersized on both phone and desktop. The
   floor of 52px is what the horizontal menu can live beside at 880px, which
   is now the narrowest width that menu has to survive; see the breakpoint
   note below. */
.header__logo img{height:clamp(52px,5.1vw,70px);width:auto}

.nav{margin-left:auto;display:flex;align-items:center;gap:clamp(.25rem,1.1vw,1.1rem)}
.nav__list{
  display:flex;align-items:center;gap:clamp(.15rem,.9vw,.9rem);
  list-style:none;margin:0;padding:0;
}
.nav__link{
  display:block;text-decoration:none;
  font-family:var(--display);font-weight:800;
  font-size:clamp(.82rem,.62rem + .42vw,1.0625rem);
  text-transform:uppercase;letter-spacing:.03em;
  color:var(--ink);white-space:nowrap;
  padding:.5rem .55rem;border-radius:12px;
  transition:color .18s, background-color .18s;
}
.nav__link:hover,.nav__item[data-open="true"] > .nav__link{color:var(--pink);background:rgba(249,66,140,.08)}

/* dropdowns */
.nav__item{position:relative}
.nav__item--has-menu > .nav__link::after{
  content:"";display:inline-block;margin-left:.4em;
  border:.3em solid transparent;border-top-color:currentColor;
  transform:translateY(.15em);
}
.nav__sub{
  position:absolute;top:calc(100% + .35rem);left:50%;translate:-50% 0;
  min-width:230px;list-style:none;margin:0;padding:.5rem;
  background:#fff;border-radius:20px;box-shadow:var(--lift-2);
  opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity .18s, transform .18s, visibility .18s;
}
.nav__item[data-open="true"] .nav__sub{opacity:1;visibility:visible;transform:none}
.nav__sub a{
  display:block;padding:.6rem .85rem;border-radius:12px;text-decoration:none;
  font-family:var(--display);font-weight:700;font-size:1rem;color:var(--ink);
  transition:background-color .15s,color .15s;
}
.nav__sub a:hover{background:var(--paper);color:var(--pink)}

.nav__cta{display:flex;align-items:center;gap:.5rem;margin-left:.35rem}

.nav__toggle{
  display:none;margin-left:auto;
  background:var(--navy);color:#fff;border:0;border-radius:14px;
  width:48px;height:48px;align-items:center;justify-content:center;cursor:pointer;
}
.nav__toggle span,.nav__toggle span::before,.nav__toggle span::after{
  display:block;width:22px;height:3px;background:#fff;border-radius:3px;position:relative;
}
.nav__toggle span::before,.nav__toggle span::after{content:"";position:absolute;left:0}
.nav__toggle span::before{top:-7px}
.nav__toggle span::after{top:7px}

/* --------------------------------------------------------------------------
   Where the menu stops being a menu.

   This was one breakpoint at 1080px, and 1080 was wrong by a long way. A
   laptop with the browser not maximized sits at around 1000 CSS pixels, which
   is where Amy opened the homepage on September 14 and found a logo, a blue square
   and no navigation at all. Measured in her own browser at innerWidth 1002:
   logo 81px + bar gap 16px + menu 797px = 894px inside a 922px bar. The
   horizontal menu fitted with 28px to spare and was being hidden anyway.

   So there are two breakpoints now. Between 880 and 1080 the menu tightens
   instead of vanishing: smaller label, less padding, less gap, smaller
   buttons. Measured with those values the menu is 653px wide, and because
   every length in the tightened block is a rem or a px rather than a vw, it
   is 653px everywhere in the band. At the bottom of it, 880px, that is
   653 + 81 logo + 14 gap = 748px against an 810px bar: 62px spare, so there
   is room for another nav item or a slightly larger logo before this needs
   revisiting. Below 880 it runs out and the drawer takes over.
   -------------------------------------------------------------------------- */
@media (max-width:1080px) and (min-width:880px){
  .header{--headerH:88px}
  .nav{gap:.3rem}
  .nav__list{gap:.15rem}
  .nav__link{font-size:.82rem;letter-spacing:.02em;padding:.5rem .35rem}
  .nav__cta{gap:.4rem;margin-left:.3rem}
  .nav__cta .btn{font-size:.95rem;padding:.55em 1.1em}
}

@media (max-width:879px){
  .header{--headerH:84px}
  .nav__toggle{display:flex}
  .nav{
    position:fixed;inset:var(--headerH) 0 0;margin:0;
    flex-direction:column;align-items:stretch;justify-content:flex-start;
    gap:0;padding:1.25rem var(--gutter) 3rem;
    background:#fff;overflow-y:auto;
    /* Fade rather than park the panel off-screen: a fixed element sitting at
       100vw adds to the document scroll width and gives the whole page a
       phantom horizontal scroll. */
    opacity:0;visibility:hidden;transform:translateY(-10px);pointer-events:none;
    transition:opacity .25s ease, transform .25s ease, visibility .25s;
  }
  body[data-nav="open"] .nav{opacity:1;visibility:visible;transform:none;pointer-events:auto}
  body[data-nav="open"]{overflow:hidden}
  /* The header creates its own containing block (its backdrop blur does), so
     inset:...0 measured the panel against the 84px header instead of the
     screen and it came out 68px tall: one menu item at a time, scrolling
     inside itself (Randy, BugHerd #124, iPhone, 10/16/2026). An explicit
     height from the viewport does not depend on what contains it. */
  .nav{bottom:auto;height:calc(100vh - var(--headerH));height:calc(100dvh - var(--headerH))}
  .nav__list{flex-direction:column;align-items:stretch;gap:0}
  .nav__link{font-size:1.25rem;padding:.85rem .25rem;border-radius:0;border-bottom:1px solid rgba(13,13,13,.07)}
  .nav__item--has-menu > .nav__link::after{float:right;transform:translateY(.5em);transition:rotate .2s}
  .nav__item[data-open="true"] > .nav__link::after{rotate:180deg}
  .nav__sub{
    position:static;translate:none;opacity:1;visibility:visible;transform:none;
    box-shadow:none;background:var(--paper);border-radius:16px;
    margin:.4rem 0;display:none;
  }
  .nav__item[data-open="true"] .nav__sub{display:block}
  .nav__cta{margin:1.5rem 0 0;flex-direction:column;align-items:stretch}
  .nav__cta .btn{width:100%}
}

/* ==========================================================================
   Hero

   Natalie asked for bright and whimsical. An EARLIER DRAFT OF THIS BUILD —
   not jumpgymnastics.com, which has never done this — put a dark gradient
   over the hero photograph, which is the one move guaranteed to make a sunny
   gym read as moody. Spelled out because the old wording said "the previous
   treatment" and was read as a description of their live site, which then
   nearly went to the client as fact. Their hero is a cut-out photograph on
   white with a dots pattern behind it; ours is a photograph on warm cream
   with the words beside it. Neither has anything laid over the photography.

   One photograph since BugHerd #15 — see HERO_SHOTS in templates/home.mjs.
   Location pages have always used one.
   ========================================================================== */
/* The divider is the hero's LAST child, so the section's bottom padding used
   to render underneath it — 88px of cream below the wave. That was invisible
   while the wave was white and became obvious the moment it turned into a blue
   brush stroke (BugHerd #17). The space belongs between the copy and the
   divider, not under the divider, so it moves onto the grid. A hero with no
   divider — every location page — looks identical either way, because the
   padding is the same color as what it sits on. */
.hero{
  position:relative;overflow:hidden;background:var(--cream);
  padding-block:clamp(2.5rem,6vw,4.5rem) 0;
}
.hero__grid{
  position:relative;display:grid;gap:clamp(2rem,5vw,3rem);
  align-items:center;grid-template-columns:1fr;
  padding-bottom:clamp(3.5rem,8vw,5.5rem);
}
@media (min-width:980px){.hero__grid{grid-template-columns:1.12fr 1fr}}

.hero h1{
  font-family:var(--display-hero);
  /* Love Ya Like A Sister is a wide, all-caps-feeling face with a small
     x-height: it needs to run smaller and looser than Baloo at the same
     visual weight, or it fills the column and the descenders collide. */
  letter-spacing:.005em;
  color:var(--navy);
  /* Baloo 2 has a deep descender; the display line-height needs a little more
     room here than it does over a photo. */
  line-height:1.18;
  font-size:clamp(2rem,1.35rem + 2.5vw,3.1rem);
}
.hero h1 .accent{color:var(--orange);display:inline-block}
.hero__lede{font-size:var(--step-1);color:var(--text-soft);max-width:34rem}
.hero__actions{display:flex;flex-wrap:wrap;gap:.85rem;margin-top:1.85rem}

.hero__badge{
  display:inline-flex;align-items:center;gap:.6rem;
  background:var(--yellow);color:var(--black);
  font-family:var(--display);font-weight:800;font-size:var(--step--1);
  text-transform:uppercase;letter-spacing:.08em;
  padding:.5rem 1rem;border-radius:var(--pill-sm);margin-bottom:1.1rem;
}
/* At 390px the full award line wrapped to two full-width rows and swallowed
   the top of the hero. Tighten it so it stays one pill. */
@media (max-width:560px){
  .hero__badge{
    font-size:.7rem;letter-spacing:.045em;gap:.4rem;
    padding:.38rem .75rem;margin-bottom:.85rem;
  }
}

/* The five CSS confetti squares that used to sit here are gone, markup and
   all. They were a stand-in for the scattered dots on Jump!'s own hero, and
   that artwork is now the real hero overlay above — two of them side by side
   read as a mistake rather than as decoration. Nothing replaced them: the
   overlay does the job on every hero, so there is no class to style. */

/* On a phone the collage used to sit under the headline, the lede and two
   buttons, which put every photograph below the fold — on a children's gym
   site the room is the pitch, so it leads instead. The copy is still the
   first thing in the DOM, so screen readers and search engines are
   unaffected; only the visual order changes. */
@media (max-width:979px){
  .hero{padding-block:clamp(1.5rem,4vw,2.5rem) 0}
  .hero__grid{gap:clamp(1.5rem,4vw,2rem);padding-bottom:clamp(2.5rem,7vw,4rem)}
  .hero__art{order:-1}
}

/* --------------------------------------------------------------------------
   Image placeholders. Branded rather than gray, and labeled with the shot
   that belongs there, so nobody reviews one as if it were the final art and
   Jillian can read the page as a shot list.
   -------------------------------------------------------------------------- */
.ph{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.5rem;text-align:center;padding:1.25rem;
  background:color-mix(in srgb, var(--ph,var(--sky)) 20%, #fff);
  border:2px dashed color-mix(in srgb, var(--ph,var(--sky)) 55%, #fff);
  color:color-mix(in srgb, var(--ph,var(--sky)) 72%, var(--black));
  border-radius:inherit;   /* inherits .shot's circle / rounded square */
  width:100%;height:100%;
}
.ph__tag{
  font-family:var(--display);font-weight:800;font-size:.68rem;
  letter-spacing:.14em;text-transform:uppercase;opacity:.75;
}
.ph__label{
  font-family:var(--display);font-weight:700;
  font-size:clamp(.78rem,.7rem + .3vw,.95rem);line-height:1.3;
  max-width:24ch;
}
/* In a circle there is far less usable room, so only the tag survives. */
.shot--round .ph__label{display:none}
.shot--round .ph__tag{font-size:.62rem}

/* --- the photographs ------------------------------------------------------ */
.hero__art{
  position:relative;display:grid;gap:.9rem;align-items:stretch;
  grid-template-columns:1.25fr 1fr;grid-template-rows:auto auto;
}
.hero__art > figure{position:relative;z-index:1;margin:0}
.shot{overflow:hidden;box-shadow:var(--lift-2);background:var(--paper)}
.shot img{width:100%;height:100%;object-fit:cover}
.shot--lead{grid-row:span 2;border-radius:36px;rotate:-1.5deg}
.shot--round{border-radius:50%;aspect-ratio:1;rotate:3deg}
.shot--square{border-radius:28px;aspect-ratio:4/3.1;rotate:-2.5deg}

.hero__ring{
  position:absolute;width:7rem;height:7rem;z-index:0;
  border:9px solid var(--c,var(--yellow));border-radius:50%;
  right:-1.25rem;top:-1.75rem;
}
/* The ring is Jump!'s own frog head now (Randy, BugHerd #121 and #125,
   10/16/2026: "I would love for the circle in the hero section to be a frog
   head so that we continue to have branding showing from the start").
   One silhouette, painted in the page's colour through a mask, so every gym
   keeps its own colour without a PNG per colour. It sits BEHIND the photo
   and peeks out over its top corner (Randy, BugHerd #131, 10/16/2026: "I
   still think it should be behind the image. Just peaking out."), raised far
   enough that roughly half the head clears the photo on a phone too.
   Pink is the button colour, not a brand colour, so a pink gym's frog is
   painted yellow instead (BugHerd #132) - set inline in location.mjs. */
.hero__ring{
  border:0;border-radius:0;
  width:clamp(4.75rem,9vw,7.5rem);height:clamp(4.75rem,9vw,7.5rem);
  right:-1.75rem;top:-3.75rem;z-index:0;rotate:8deg;
  background:var(--c,var(--yellow));
  -webkit-mask:url(/assets/img/frog-head.png) center/contain no-repeat;
          mask:url(/assets/img/frog-head.png) center/contain no-repeat;
}
@media (max-width:979px){.hero__ring{right:.75rem;top:-2.6rem}}

/* Fewer than three photos is the likely state for a while, and a gym that
   opens later may only ever have one. Degrade honestly rather than leaving a
   hole: with two the lead stops spanning, with one it fills the column. */
.hero__art[data-shots="2"]{grid-template-rows:auto}
.hero__art[data-shots="2"] .shot--lead{grid-row:auto;aspect-ratio:4/4.6}
.hero__art[data-shots="1"]{grid-template-columns:1fr;grid-template-rows:auto}
.hero__art[data-shots="1"] .shot--lead{grid-row:auto;aspect-ratio:5/4.2;rotate:-1.25deg}

/* A gym with no photograph at all still gets a hero, just a wordier one. */
.hero__art:empty{display:none}

/* ==========================================================================
   Pillars — "Build a lifelong love of physical activity"
   ========================================================================== */
.pillars{
  display:grid;gap:clamp(1rem,2.5vw,1.75rem);
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  margin-top:2.5rem;
}
.pillar{
  background:#fff;border-radius:var(--card-radius);padding:1.75rem 1.5rem;
  box-shadow:var(--lift-1);border-top:6px solid var(--c,var(--sky));
  transition:transform .25s cubic-bezier(.34,1.4,.64,1), box-shadow .25s;
}
.pillar:hover{transform:translateY(-6px);box-shadow:var(--lift-2)}
.pillar__icon{
  width:58px;height:58px;border-radius:18px;display:grid;place-items:center;
  background:color-mix(in srgb, var(--c,var(--sky)) 16%, #fff);
  color:var(--c,var(--sky));margin-bottom:1rem;
}
.pillar__icon svg{width:30px;height:30px}
.pillar h3{font-size:var(--step-1);margin-bottom:.4rem}
.pillar p{font-size:var(--step--1);color:var(--text-soft);margin:0}
/* A card can hold a short list instead of a paragraph — the employment page
   puts its pay, benefits and requirements in four of them. The marker takes
   the card's own accent so the four read as a set of four different things. */
.pillar ul{margin:.35rem 0 0;padding-left:1.15rem;font-size:var(--step--1);
  color:var(--text-soft);line-height:1.6}
.pillar li{margin-bottom:.45rem}
.pillar li:last-child{margin-bottom:0}
.pillar li::marker{color:var(--c,var(--sky));font-weight:700}

/* ==========================================================================
   Programs
   ========================================================================== */
.programs{
  display:grid;gap:clamp(1rem,2.5vw,1.75rem);
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  margin-top:2.5rem;
}
.program{
  position:relative;display:flex;flex-direction:column;
  background:#fff;border-radius:var(--card-radius);overflow:hidden;
  box-shadow:var(--lift-1);text-decoration:none;color:inherit;
  transition:transform .25s cubic-bezier(.34,1.4,.64,1), box-shadow .25s;
}
.program:hover{transform:translateY(-8px);box-shadow:var(--lift-2)}
.program__media{aspect-ratio:16/10;overflow:hidden;background:var(--paper)}
.program__media img{width:100%;height:100%;object-fit:cover;transition:scale .45s ease}
.program:hover .program__media img{scale:1.05}
.program__body{padding:1.5rem;display:flex;flex-direction:column;flex:1;gap:.5rem}
.program__kicker{
  font-family:var(--display);font-weight:800;font-size:.8rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--c,var(--pink));
}
.program h3{margin:0;font-size:var(--step-2)}
.program p{font-size:var(--step--1);color:var(--text-soft);margin:0}
.program__more{
  margin-top:auto;padding-top:.85rem;
  font-family:var(--display);font-weight:800;text-transform:uppercase;
  font-size:.95rem;letter-spacing:.05em;color:var(--c,var(--pink));
  display:inline-flex;align-items:center;gap:.4rem;
}
.program:hover .program__more{gap:.7rem}
.program__more span{transition:translate .2s}
.program:hover .program__more span{translate:4px 0}

/* --------------------------------------------------------------------------
   Team cards.

   A person gets a .program card — same radius, same shadow, same hover — but a
   team is not a program grid. .programs is repeat(auto-fit,minmax(280px,1fr)),
   which is right for three programs and wrong for one owner: measured at
   1002px the single card filled the whole 922px wrap and the square portrait
   above it came out 922px tall. Amy's word for it was "enormous", and it was.

   A row of people should be a row of people-sized cards, centered, whether
   there is one of them or nine. Flex rather than grid for exactly that: a
   card has a natural size and the row centers whatever is left over.
   -------------------------------------------------------------------------- */
.team{
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:clamp(1rem,2.5vw,1.75rem);margin-top:2.5rem;
}
.team .program{flex:1 1 240px;max-width:min(100%,320px)}
/* A headshot is portrait. The 16/10 program crop takes the top of the head
   off, which is why this was carrying an inline override before it had a
   stylesheet of its own. */
.team .program__media{aspect-ratio:1}

/* ==========================================================================
   Adventure Path
   ========================================================================== */
.adventure{background:var(--navy);color:#fff;position:relative;overflow:hidden}
.adventure h2,.adventure h3{color:#fff}
.adventure .eyebrow{color:var(--yellow)}
.adventure__grid{display:grid;gap:clamp(2rem,5vw,4rem);align-items:center;grid-template-columns:1fr}
@media (min-width:900px){.adventure__grid{grid-template-columns:1fr 1fr}}
.adventure p{color:rgba(255,255,255,.86)}

.levels{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1.5rem;padding:0;list-style:none}
.level{
  font-family:var(--display);font-weight:800;font-size:.95rem;
  padding:.5rem 1rem;border-radius:var(--pill);
  background:rgba(255,255,255,.12);border:2px solid rgba(255,255,255,.22);
  color:#fff;white-space:nowrap;
}
.level[data-tone="1"]{background:var(--teal-ink);border-color:var(--teal-ink)}
.level[data-tone="2"]{background:var(--grass);border-color:var(--grass)}
.level[data-tone="3"]{background:var(--yellow);border-color:var(--yellow);color:var(--black)}
.level[data-tone="4"]{background:var(--orange);border-color:var(--orange)}
.level[data-tone="5"]{background:var(--pink);border-color:var(--pink)}
.level[data-tone="6"]{background:var(--rose);border-color:var(--rose)}

.stat-row{display:flex;flex-wrap:wrap;gap:clamp(1.25rem,4vw,3rem);margin-top:2rem}
.stat__num{font-family:var(--display);font-weight:900;font-size:var(--step-3);color:var(--yellow);line-height:1}
.stat__label{font-size:var(--step--1);color:rgba(255,255,255,.8);margin-top:.25rem}

/* ==========================================================================
   Locations
   ========================================================================== */
.locations{
  display:grid;gap:clamp(1rem,2.5vw,1.5rem);
  grid-template-columns:repeat(auto-fit,minmax(250px,1fr));
  margin-top:2.5rem;
}
.location{
  display:flex;flex-direction:column;gap:.5rem;
  background:#fff;border-radius:var(--card-radius);padding:1.6rem 1.4rem;
  box-shadow:var(--lift-1);text-decoration:none;color:inherit;
  border-left:7px solid var(--c,var(--sky));
  transition:transform .25s cubic-bezier(.34,1.4,.64,1), box-shadow .25s;
}
.location:hover{transform:translateY(-6px);box-shadow:var(--lift-2)}
.location h3{margin:0;font-size:var(--step-1)}
.location__addr{font-size:var(--step--1);color:var(--text-soft);font-style:normal;margin:0}
.location__stats{
  display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.35rem;
}
.chip{
  font-family:var(--display);font-weight:700;font-size:.8rem;
  padding:.28rem .7rem;border-radius:var(--pill);
  background:color-mix(in srgb, var(--c,var(--sky)) 15%, #fff);
  color:color-mix(in srgb, var(--c,var(--sky)) 78%, var(--black));
  white-space:nowrap;
}
.chip[data-state="loading"]{background:var(--paper);color:var(--text-soft)}
.location__more{
  margin-top:auto;padding-top:.9rem;font-family:var(--display);font-weight:800;
  text-transform:uppercase;font-size:.9rem;letter-spacing:.05em;color:var(--c,var(--sky));
}

/* ==========================================================================
   Testimonials
   ========================================================================== */
.quotes{
  display:grid;gap:clamp(1rem,2.5vw,1.5rem);
  grid-template-columns:repeat(auto-fit,minmax(290px,1fr));
  margin-top:2.5rem;
}
.quote{
  background:#fff;border-radius:var(--card-radius);padding:1.75rem 1.5rem;
  box-shadow:var(--lift-1);display:flex;flex-direction:column;gap:.9rem;
}
.quote__stars{color:var(--yellow);font-size:1.15rem;letter-spacing:.1em}
.quote blockquote{margin:0;font-size:var(--step--1);color:var(--text);line-height:1.6}
.quote figcaption{
  margin-top:auto;font-family:var(--display);font-weight:800;color:var(--navy);font-size:1rem;
}

/* ==========================================================================
   Awards — Natalie item 3: on the desktop homepage, and not a long list on mobile
   ========================================================================== */
.awards{background:var(--bg-alt)}
.awards__row{
  display:flex;flex-wrap:wrap;align-items:stretch;justify-content:center;
  gap:clamp(1.25rem,4vw,3.5rem);margin-top:2rem;
}
/* Natalie item 3 again: on a phone this must be a compact two-up block, not a
   long vertical list. Flex-wrap was landing one per row at 390px, so the small
   screens get an explicit two-column grid. */
@media (max-width:560px){
  .awards__row{display:grid;grid-template-columns:1fr 1fr;gap:1rem;align-items:stretch}
  .award,.award--text{max-width:none;width:100%;justify-content:center}
  .award img{height:clamp(54px,15vw,78px)}
  .award--text .award__num{font-size:1.9rem}
  .award--text{padding:.9rem .75rem}
  .award__caption{font-size:.74rem}
}
.award{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  gap:.6rem;max-width:170px;text-align:center;align-self:stretch}
.award img{height:clamp(74px,9vw,112px);width:auto;object-fit:contain}
.award__caption{
  font-family:var(--display);font-weight:700;font-size:.82rem;line-height:1.3;
  color:var(--text-soft);
}
/* Six badges since the woman-owned badge (BugHerd #291): one even row on desktop
   instead of five plus one left over. */
@media (min-width:900px){
  .awards__row{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:clamp(1rem,2.2vw,2rem)}
  .award{max-width:none}
}
.award--text{
  display:grid;place-items:center;text-align:center;gap:.15rem;
  background:var(--yellow);color:var(--black);
  border-radius:var(--card-radius);padding:1.1rem 1.35rem;max-width:200px;
  align-self:center;
}
.award--text .award__num{font-family:var(--display);font-weight:900;font-size:2.4rem;line-height:1}
.award--text .award__caption{color:var(--black);font-weight:800}

/* ==========================================================================
   Franchising — Natalie item 4
   ========================================================================== */
/* Amy, September 15: "Color block feels off brand..maybe an orange or another color
   the kit." It was a teal-to-green gradient — two colors the brand owns, but
   not two colors anyone looks at and thinks Jump!.

   Orange is the obvious answer, and choosing it forces the other half of the
   change. Brand orange #F47920 measures 2.76:1 against white, so the white
   type this panel used to carry would have failed AA on it worse than it did
   on the teal. Black on that same orange is 6.97:1. An orange panel can only
   work with dark type, so the ground goes light and the words go black.

   The sweep runs brand orange to the brand's deep yellow, and black clears AA
   the whole way along it: 6.97:1 at the orange end, 14.7:1 at the yellow.

   The button stays navy. White on navy is 7.5:1, and navy is the one button
   color in the kit that still reads as a button against an orange ground —
   the pink one drops to 3.4:1, which only passes because the label is large. */
/* Solid navy with a large frog head tucked into the corner, in place of the
   orange-to-yellow gradient (Randy, BugHerd #202: "This gradient is looking
   very 80s"). */
.franchise{
  position:relative;overflow:hidden;isolation:isolate;
  background:var(--navy);
  color:#fff;border-radius:var(--card-radius);
  padding:clamp(2rem,5vw,3.5rem);
  display:grid;gap:1.5rem;align-items:center;grid-template-columns:1fr;
}
@media (min-width:820px){.franchise{grid-template-columns:1.6fr auto}}
.franchise::after{
  content:"";position:absolute;z-index:-1;right:-2.5rem;bottom:-3rem;width:16rem;height:16rem;rotate:-12deg;
  background:var(--grass);opacity:.35;
  -webkit-mask:url(/assets/img/frog-head.png) center/contain no-repeat;
          mask:url(/assets/img/frog-head.png) center/contain no-repeat;
}
.franchise h2{color:#fff;margin-bottom:.35rem}
.franchise p{color:rgba(255,255,255,.9);margin:0;max-width:60ch}

/* ==========================================================================
   Footer
   ========================================================================== */
/* Amy asked for pink instead of black, then approved bringing the shade down.

   The brand pink #F9428C is a demanding ground: full-strength white measures
   3.38:1 on it, fine for large headings but under the 4.5:1 AA bar for the
   addresses, links and legal line, and there is a lot of small print in a
   footer. --pink-deep is that pink darkened until white clears the bar at
   4.68:1. Nothing here is set at less than full-opacity white; the old footer
   used 75%, which on either pink is unreadable. The legal band stays, now for
   hierarchy rather than rescue, and measures 7.89:1. */
.footer{background:var(--pink-deep);color:#fff;padding-block:clamp(3rem,6vw,4.5rem) 0}
.footer h2,.footer h3{color:#fff}
.footer a{color:#fff;text-decoration:none;transition:opacity .15s}
.footer a:hover{text-decoration:underline;text-underline-offset:3px}
.footer__grid{
  display:grid;gap:clamp(1.75rem,4vw,3rem);
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
}
.footer__brand img{height:56px;width:auto;margin-bottom:1rem}
.footer h3{font-size:1rem;letter-spacing:.1em;text-transform:uppercase;margin-bottom:.9rem}
.footer ul{list-style:none;margin:0;padding:0;display:grid;gap:.55rem;font-size:var(--step--1)}
.footer__gyms{display:grid;gap:1.25rem;font-size:var(--step--1);font-style:normal}
.footer__gym{font-style:normal}
.footer__gym strong{color:#fff;font-family:var(--display);font-weight:800;display:block}
.footer__social{display:flex;gap:.6rem;margin-top:1.25rem}
.footer__social a{
  width:42px;height:42px;border-radius:14px;display:grid;place-items:center;
  /* was pink-on-black; pink on pink would be invisible, so navy carries it */
  background:rgba(255,255,255,.2);transition:background-color .18s,transform .18s;
}
.footer__social a:hover{background:var(--navy);transform:translateY(-3px)}
.footer__social svg{width:20px;height:20px;fill:currentColor}
.footer__legal{
  margin-top:clamp(2rem,5vw,3rem);
  display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;
  font-size:.85rem;color:#fff;
}
/* It sits outside .wrap so the band runs edge to edge while the text inside
   stays on the grid. */
.footer__legalband{
  background:rgba(13,13,13,.32);
  margin-top:clamp(2rem,5vw,3rem);padding-block:1.1rem;
}
.footer__legalband .footer__legal{margin-top:0}

/* ==========================================================================
   Motion — Natalie 1B: "items that move in (slide, drop, tumble)"
   Cheap, CSS-driven, and fully off when the visitor asks for less motion.
   ========================================================================== */
[data-anim]{opacity:0;will-change:transform,opacity}
[data-anim="rise"]   {transform:translateY(34px)}
[data-anim="drop"]   {transform:translateY(-30px)}
[data-anim="left"]   {transform:translateX(-40px)}
[data-anim="right"]  {transform:translateX(40px)}
[data-anim="tumble"] {transform:translateY(28px) rotate(-8deg) scale(.92)}
[data-anim="pop"]    {transform:scale(.86)}

[data-anim].is-in{
  opacity:1;transform:none;
  transition:opacity .62s cubic-bezier(.22,.61,.36,1),
             transform .72s cubic-bezier(.34,1.32,.64,1);
  transition-delay:var(--d,0ms);
}

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

/* Print — parents do print the fee sheets */
@media print{
  .header,.nav,.hero__actions,.footer__social{display:none}
  body{font-size:11pt}
  .section{padding-block:1rem}
}

/* ==========================================================================
   LOCATION PAGE
   Everything below is only used by /locations/<gym>/.
   ========================================================================== */

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

.section--tight{padding-block:clamp(2rem,4vw,3rem)}

/* The location hero is the homepage hero — one photograph on cream, words
   beside it — so the two pages read as the same site. It used to be "with one
   photo instead of three"; since BugHerd #15 the homepage runs one as well.
   The ring picks up the gym's accent. */
.hero--location h1 .accent{color:var(--c,var(--pink))}
.hero__meta{
  font-style:normal;color:var(--text-soft);font-size:var(--step-0);
  margin-top:1rem;
}
.hero__meta a{color:var(--pink);text-decoration:none;font-weight:700}
.hero__meta a:hover{text-decoration:underline}

/* ---- quick facts --------------------------------------------------------- */
.factbar{
  display:grid;gap:clamp(.75rem,2vw,1.25rem);
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
}
.fact{
  background:var(--paper);border-radius:var(--card-radius);
  padding:1.25rem 1rem;text-align:center;
}
.fact__num{
  display:block;font-family:var(--display);font-weight:900;
  font-size:clamp(1.6rem,1.2rem + 1.6vw,2.4rem);line-height:1;color:var(--navy);
}
.fact__label{
  display:block;margin-top:.35rem;font-size:.82rem;color:var(--text-soft);
  font-family:var(--display);font-weight:700;
}

/* ---- filters ------------------------------------------------------------- */
.filters{
  display:flex;flex-wrap:wrap;gap:.75rem 1rem;align-items:flex-end;
  margin:2rem 0 1rem;padding:1.15rem;background:#fff;
  border-radius:var(--card-radius);box-shadow:var(--lift-1);
}
.filter{display:flex;flex-direction:column;gap:.3rem;min-width:150px;flex:1 1 150px}
.filter > span{
  font-family:var(--display);font-weight:800;font-size:.76rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text-soft);
}
.filter select{
  font:inherit;font-size:.95rem;padding:.6rem .75rem;
  border:2px solid rgba(13,13,13,.12);border-radius:14px;background:#fff;color:var(--ink);
}
.filter select:focus-visible{border-color:var(--pink);outline:none;box-shadow:var(--ring)}
.filter--check{flex-direction:row;align-items:center;gap:.55rem;flex:0 0 auto;padding-bottom:.6rem}
.filter--check span{
  font-family:var(--display);font-weight:700;font-size:.95rem;
  text-transform:none;letter-spacing:0;color:var(--ink);
}
.filter--check input{width:20px;height:20px;accent-color:var(--pink)}
.filter__reset{
  background:none;border:0;cursor:pointer;padding:.6rem .5rem;
  font-family:var(--display);font-weight:800;font-size:.9rem;
  text-transform:uppercase;letter-spacing:.05em;color:var(--pink);
}
.filter__reset:hover{text-decoration:underline}
.filters__count{
  font-family:var(--display);font-weight:700;color:var(--text-soft);
  font-size:.95rem;margin:0 0 1.5rem;
}

/* ---- class list ---------------------------------------------------------- */
.classlist__loading,.classlist__empty{
  background:#fff;border-radius:var(--card-radius);padding:2rem 1.5rem;
  text-align:center;color:var(--text-soft);box-shadow:var(--lift-1);margin:0;
}
.classgroup{margin-bottom:clamp(2rem,4vw,3rem)}
.classgroup__title{
  display:flex;align-items:center;gap:.65rem;
  font-size:var(--step-2);margin-bottom:1rem;color:var(--c,var(--navy));
}
.classgroup__count{
  font-size:.9rem;font-weight:800;background:var(--c,var(--navy));color:#fff;
  border-radius:var(--pill);padding:.15rem .7rem;
}
.classgroup__grid{
  display:grid;gap:clamp(.85rem,2vw,1.25rem);
  grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr));
}

.class{
  background:#fff;border-radius:var(--card-radius);padding:1.35rem;
  box-shadow:var(--lift-1);border-top:5px solid var(--c,var(--sky));
  display:flex;flex-direction:column;gap:.55rem;
  transition:transform .2s cubic-bezier(.34,1.4,.64,1), box-shadow .2s;
}
.class:hover{transform:translateY(-4px);box-shadow:var(--lift-2)}
.class__head{display:flex;align-items:center;justify-content:space-between;gap:.6rem}
.class__program{
  font-family:var(--display);font-weight:800;font-size:.72rem;
  letter-spacing:.11em;text-transform:uppercase;color:var(--c,var(--sky));
}
.class__state{
  font-family:var(--display);font-weight:800;font-size:.72rem;
  padding:.2rem .6rem;border-radius:var(--pill);white-space:nowrap;
}
.class__state--open{background:rgba(122,183,66,.16);color:#4c7a25}
.class__state--low{background:rgba(244,121,32,.18);color:#a2500f}
.class__state--full{background:rgba(13,13,13,.08);color:var(--slate)}
.class__state--waitlist{background:rgba(114,166,217,.22);color:#2b5f8f}
.class__state--unknown{background:var(--paper);color:var(--slate)}
.class__name{font-size:var(--step-1);margin:0;line-height:1.2}
.class__level{
  margin:0;font-family:var(--display);font-weight:700;
  font-size:.9rem;color:var(--text-soft);
}
/* A confirmed note about the whole program, e.g. "Members only". Content, not
   feed — Jackrabbit has no field for it. */
.class__note{
  margin:0;align-self:start;
  font-family:var(--display);font-weight:800;font-size:.7rem;
  letter-spacing:.08em;text-transform:uppercase;
  color:var(--c,var(--navy));background:color-mix(in srgb,var(--c,var(--navy)) 12%,#fff);
  padding:.2rem .55rem;border-radius:var(--pill);display:inline-block;
}
.classgroup__note{
  font-family:var(--display);font-weight:800;font-size:.72rem;
  letter-spacing:.08em;text-transform:uppercase;
  color:#fff;background:var(--c,var(--navy));
  padding:.2rem .6rem;border-radius:var(--pill);
}
.class__meta{display:grid;gap:.3rem;margin:.35rem 0 0;font-size:.88rem}
.class__meta > div{display:flex;gap:.5rem}
.class__meta dt{
  font-family:var(--display);font-weight:800;color:var(--text-soft);
  min-width:58px;margin:0;
}
.class__meta dd{margin:0;color:var(--ink)}
.class__desc{font-size:.85rem;color:var(--text-soft);margin:.35rem 0 0}
.class__cta{
  margin-top:auto;padding-top:.85rem;text-decoration:none;
  font-family:var(--display);font-weight:800;font-size:.92rem;
  text-transform:uppercase;letter-spacing:.04em;color:var(--c,var(--pink));
}
.class__cta:hover{text-decoration:underline}
/* A class nobody can join should not be shouting Register in brand pink. */
.class__cta[data-cta="full"],
.class__cta[data-cta="later"]{color:var(--slate)}
.class__cta[data-cta="waitlist"]{color:var(--navy)}

/* ---- fees ---------------------------------------------------------------- */
.fees{
  display:grid;gap:clamp(1.25rem,3vw,2rem);margin-top:2rem;
  grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));
}
.fees__block{
  background:#fff;border-radius:var(--card-radius);padding:1.6rem;box-shadow:var(--lift-1);
}
.fees__block h3{font-size:var(--step-1);margin-bottom:.5rem}
.fees__note{font-size:.86rem;color:var(--text-soft);margin-bottom:1rem}
.feetable{width:100%;border-collapse:collapse;font-size:.94rem}
.feetable th{
  text-align:left;font-family:var(--display);font-weight:800;font-size:.76rem;
  letter-spacing:.09em;text-transform:uppercase;color:var(--text-soft);
  padding:0 0 .6rem;border-bottom:2px solid rgba(13,13,13,.08);
}
.feetable td{padding:.85rem 0;border-bottom:1px solid rgba(13,13,13,.07);vertical-align:top}
.feetable tr:last-child td{border-bottom:0}
.feetable__detail{display:block;font-size:.83rem;color:var(--text-soft);margin-top:.2rem;font-weight:400}
.feetable__value{
  text-align:right;white-space:nowrap;
  font-family:var(--display);font-weight:900;font-size:1.1rem;color:var(--navy);
}
.feetable__cadence{font-size:.78rem;font-weight:700;color:var(--text-soft)}

/* ---- calendar ------------------------------------------------------------ */
.calendar{display:grid;gap:.75rem;margin-top:2rem}
.cal{
  display:flex;align-items:center;gap:1.1rem;
  background:#fff;border-radius:var(--card-radius);padding:1rem 1.25rem;
  box-shadow:var(--lift-1);border-left:6px solid var(--c,var(--sky));
}
.cal__date{
  flex:0 0 auto;width:58px;text-align:center;line-height:1;
  background:var(--paper);border-radius:16px;padding:.55rem 0;
}
.cal__mon{
  display:block;font-family:var(--display);font-weight:800;font-size:.7rem;
  text-transform:uppercase;letter-spacing:.08em;color:var(--c,var(--sky));
}
.cal__day{display:block;font-family:var(--display);font-weight:900;font-size:1.5rem;color:var(--navy)}
.cal__body{flex:1}
.cal__body h3{margin:0;font-size:var(--step-1)}
.cal__body p{margin:.15rem 0 0;font-size:.88rem;color:var(--text-soft)}
.cal__cta{
  flex:0 0 auto;text-decoration:none;font-family:var(--display);font-weight:800;
  font-size:.85rem;text-transform:uppercase;letter-spacing:.04em;color:var(--c,var(--sky));
}
.cal__cta:hover{text-decoration:underline}
@media (max-width:520px){
  .cal{flex-wrap:wrap;gap:.75rem}
  .cal__cta{width:100%;text-align:right}
}

/* ---- visit --------------------------------------------------------------- */
.visit{display:grid;gap:clamp(1.5rem,4vw,3rem);grid-template-columns:1fr;align-items:center}
@media (min-width:860px){.visit{grid-template-columns:1fr 1fr}}
.visit__address{font-style:normal;font-size:var(--step-1);line-height:1.6;margin:1rem 0}
.visit__address a{color:var(--pink);font-weight:700;text-decoration:none}
.visit__address a:hover{text-decoration:underline}
.hours{border-collapse:collapse;font-size:.95rem;margin:1rem 0}
.hours th{
  text-align:left;font-family:var(--display);font-weight:800;
  padding:.35rem 1.5rem .35rem 0;color:var(--ink);
}
.hours td{padding:.35rem 0;color:var(--text-soft)}
.visit__areas{font-size:.9rem;color:var(--text-soft);margin-top:1rem}
.visit__mapcard{
  display:flex;align-items:center;gap:1rem;text-decoration:none;color:inherit;
  background:#fff;border-radius:var(--card-radius);padding:1.5rem;
  box-shadow:var(--lift-1);border:3px dashed color-mix(in srgb,var(--c,var(--sky)) 40%,#fff);
  transition:transform .2s, box-shadow .2s;
}
.visit__mapcard:hover{transform:translateY(-4px);box-shadow:var(--lift-2)}
.visit__mapcard svg{width:48px;height:48px;flex:0 0 auto;color:var(--c,var(--sky))}
.visit__mapcard strong{display:block;font-family:var(--display);font-size:1.15rem;margin-bottom:.15rem}
.visit__mapcard span{font-size:.9rem;color:var(--text-soft)}

/* ---- form ---------------------------------------------------------------- */
.form{
  background:#fff;border-radius:var(--card-radius);padding:clamp(1.4rem,3vw,2rem);
  box-shadow:var(--lift-1);display:grid;gap:1.1rem;margin-top:2rem;
}
.form__hp{position:absolute;left:-9999px}
.form__row{display:grid;gap:1.1rem;grid-template-columns:1fr}
@media (min-width:620px){.form__row{grid-template-columns:1fr 1fr}}
.field{display:flex;flex-direction:column;gap:.35rem}
.field > span{font-family:var(--display);font-weight:800;font-size:.92rem;color:var(--ink)}
.field em{color:var(--pink);font-style:normal}
.field input,.field select,.field textarea{
  font:inherit;font-size:1rem;padding:.75rem .85rem;
  border:2px solid rgba(13,13,13,.12);border-radius:16px;background:#fff;color:var(--ink);
}
.field textarea{resize:vertical}
.field input:focus-visible,.field select:focus-visible,.field textarea:focus-visible{
  border-color:var(--pink);outline:none;box-shadow:var(--ring);
}
.field--check{flex-direction:row;align-items:flex-start;gap:.7rem}
.field--check input{width:22px;height:22px;flex:0 0 auto;margin-top:.15rem;accent-color:var(--pink)}
.field--check span{font-family:var(--body);font-weight:400;font-size:.86rem;color:var(--text-soft)}
.field--check a{color:var(--pink)}
.form .btn{justify-self:start}

/* Long class lists: show a screenful, keep the rest in the DOM behind a button
   so the page stays scrollable by a human but complete for a crawler. */
.class.is-extra{display:none}
.classgroup[data-expanded="true"] .class.is-extra{display:flex}
.classgroup__more{
  display:block;width:100%;margin-top:1rem;cursor:pointer;
  background:#fff;border:2px dashed color-mix(in srgb,var(--c,var(--sky)) 45%,#fff);
  border-radius:var(--pill);padding:.85rem 1.25rem;
  font-family:var(--display);font-weight:800;font-size:1rem;
  text-transform:uppercase;letter-spacing:.04em;color:var(--c,var(--sky));
  transition:background-color .18s,transform .18s;
}
.classgroup__more:hover{background:color-mix(in srgb,var(--c,var(--sky)) 8%,#fff);transform:translateY(-2px)}
.classgroup__more:focus-visible{box-shadow:var(--ring);outline:none}

/* A second .team row directly under the first (About Us: the owners on top,
   the headquarters team below - BugHerd #178). */
.team + .team{margin-top:clamp(1rem,2.5vw,1.75rem)}
.award__link{display:block;transition:transform .2s}.award__link:hover{transform:translateY(-3px)}

/* ---- program picker (gym pages, BugHerd #174) ----------------------------
   Teal cards with a pink button, the look of Jump!'s own class wizard, so a
   returning parent recognizes the first step. */
.picker{margin-top:2rem}
.picker__ask{text-align:center;font-weight:600;color:var(--text);margin:0 0 1.25rem}
.picker__cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(.9rem,2.2vw,1.5rem);max-width:1040px;margin-inline:auto}
.picker__card{
  display:flex;flex-direction:column;text-decoration:none;color:#fff;text-align:center;
  background:var(--teal-ink);border-radius:24px;overflow:hidden;box-shadow:var(--lift-2);
  transition:transform .2s ease, box-shadow .2s ease;
}
.picker__card:hover{transform:translateY(-4px)}
.picker__card:focus-visible{outline:3px solid var(--pink);outline-offset:3px}
.picker__photo{display:block;aspect-ratio:4/3;overflow:hidden;background:var(--paper)}
.picker__photo img,.picker__photo .ph{width:100%;height:100%;object-fit:cover}
.picker__body{display:flex;flex-direction:column;align-items:center;gap:.2rem;padding:1rem 1rem 1.35rem}
.picker__name{font-family:var(--display);font-weight:900;font-size:clamp(1.35rem,2.4vw,1.75rem);letter-spacing:.04em;text-transform:uppercase}
.picker__ages{font-weight:600;font-size:.95rem;opacity:.95}
.picker__btn{
  margin-top:.7rem;background:var(--pink);color:#fff;border-radius:999px;padding:.55rem 1.35rem;
  font-family:var(--display);font-weight:800;font-size:.85rem;letter-spacing:.06em;text-transform:uppercase;
}
.picker__also{text-align:center;margin:1.4rem 0 0;font-weight:600;color:var(--text-soft);display:flex;flex-wrap:wrap;justify-content:center;gap:.4rem .9rem}
.picker__also span{display:contents}
.picker__other{color:var(--teal-ink);font-weight:700}
.picker__all{text-align:center;margin:.75rem 0 0}
.picker__all a{color:var(--text-soft);font-size:.92rem}
@media (max-width:700px){
  .picker__cards{grid-template-columns:1fr;max-width:420px}
  .picker__card{flex-direction:row;text-align:left}
  .picker__photo{flex:0 0 42%;aspect-ratio:auto;min-height:150px}
  .picker__body{align-items:flex-start;justify-content:center}
}

.picked{margin-top:1.75rem;display:grid;gap:1rem;justify-items:center;scroll-margin-top:110px}
.picked__bar{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;justify-content:center}
.picked__tag{background:var(--teal-ink);color:#fff;border-radius:999px;padding:.45rem 1.1rem;font-family:var(--display);font-weight:800;letter-spacing:.03em}
.picked__change{background:none;border:0;padding:0;color:var(--pink-deep);font-weight:700;text-decoration:underline;cursor:pointer}
.picked__ages{display:grid;gap:.6rem;justify-items:center}
.picked__ask{font-weight:600;color:var(--text)}
.picked__chips{display:flex;flex-wrap:wrap;gap:.5rem;justify-content:center}
.chip{
  border:2px solid var(--teal);background:#fff;color:var(--teal-ink);border-radius:999px;
  padding:.4rem 1rem;font-family:var(--display);font-weight:800;font-size:.95rem;cursor:pointer;min-width:2.8rem;
}
.chip.is-on{background:var(--teal-ink);border-color:var(--teal-ink);color:#fff}
.chip:focus-visible{outline:3px solid var(--pink);outline-offset:2px}
/* Once a program is chosen the cards do the program and age work, so the
   filter row keeps only Day and open spots. */
.filters--picked .filter:nth-of-type(1),.filters--picked .filter:nth-of-type(2){display:none}

/* ---- yearly calendar (gym pages, BugHerd #172/#173) ---------------------- */
.yearcal{list-style:none;margin:2rem 0 0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:.85rem}
.yearcal__item{
  position:relative;display:flex;align-items:center;gap:1rem;background:#fff;border-radius:var(--card-radius);
  padding:.9rem 1.1rem;box-shadow:var(--lift-1);border-left:6px solid var(--grass);
}
.yearcal__item:nth-child(4n+2){border-left-color:var(--sky)}
.yearcal__item:nth-child(4n+3){border-left-color:var(--orange)}
.yearcal__item:nth-child(4n+4){border-left-color:var(--rose)}
.yearcal__date{flex:0 0 auto;width:54px;text-align:center;line-height:1;background:var(--paper);border-radius:14px;padding:.5rem 0}
.yearcal__mon{display:block;font-family:var(--display);font-weight:800;font-size:.7rem;text-transform:uppercase;letter-spacing:.08em;color:var(--teal-ink)}
.yearcal__day{display:block;font-family:var(--display);font-weight:900;font-size:1.45rem;color:var(--navy)}
.yearcal__body{display:grid;gap:.15rem;min-width:0}
.yearcal__title{font-family:var(--display);font-weight:800;font-size:1.05rem;line-height:1.2;color:var(--heading)}
.yearcal__span{font-size:.86rem;color:var(--text-soft)}
.yearcal__now{position:absolute;top:-.6rem;right:.9rem;background:var(--pink);color:#fff;border-radius:999px;padding:.15rem .6rem;font-size:.7rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase}
.yearcal__item.is-now{box-shadow:0 0 0 2px var(--pink),var(--lift-1)}
/* These set their own display, which outranks the browser's [hidden] rule,
   so hidden has to be restated or a past event and the empty picked bar
   would still show. */
.yearcal__item[hidden],.picker[hidden],.picker__also[hidden],.picked[hidden],.picked__ages[hidden],.filters[hidden],.filters__count[hidden],.classlist[hidden]{display:none}

/* Gym pages: the line under the filters before anything is chosen (#174). */
.classlist__prompt{margin:1.25rem 0 0;padding:1.1rem 1.25rem;background:#fff;border-radius:var(--card-radius);box-shadow:var(--lift-1);text-align:center;font-weight:600;color:var(--text)}
.classlist__all{display:inline;background:none;border:0;padding:.75rem .25rem;margin-left:.1rem;color:var(--pink-deep);font:inherit;font-weight:700;text-decoration:underline;cursor:pointer}
.classlist__prompt[hidden]{display:none}

/* ---- program row on gym pages (Randy, 10/27/2026) ------------------------ */
.progstrip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(.8rem,2vw,1.25rem);margin-top:1.75rem}
@media (max-width:980px){.progstrip{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.progstrip{grid-template-columns:1fr}}
.progstrip__item{display:flex;flex-direction:column;gap:.35rem;background:#fff;border-radius:var(--card-radius);padding:1.1rem 1.2rem 1.15rem;box-shadow:var(--lift-1);border-top:6px solid var(--c)}
.progstrip__item h3{margin:0;font-size:var(--step-1)}
.progstrip__item p{margin:0;color:var(--text-soft);font-size:.92rem;flex:1}
.progstrip__links{display:flex;gap:1rem;flex-wrap:wrap;margin-top:.6rem}
.progstrip__links a{font-family:var(--display);font-weight:800;font-size:.82rem;letter-spacing:.04em;text-transform:uppercase;text-decoration:none;color:color-mix(in srgb,var(--c) 70%,#000)}
.progstrip__links a:hover{text-decoration:underline}

/* BugHerd #276 (Randy): the Enroll Now button under the Tadpoles/Pollywogs/
   Frogs cards sat 40px under the cards and 224px above the next heading,
   because two full section paddings stacked under it. Half the bottom
   padding here evens that out. */
.section--groups{padding-bottom:calc(var(--section) / 2)}
