/* ==========================================================================
   AnyWhere — design tokens
   ========================================================================== */
:root {
  /* Palette sourced directly from the AnyKids logo (Any=black, K=blue,
     I=green, D=yellow, S=red, banner=orange) — every color below is either
     one of those five exact values or a tint/shade mixed from one. */
  --cream: #fffbf9;
  --navy: #0a0a0a;
  --ink: #141414;

  --blue-600: #0165ff;
  --blue-500: #1f77ff;
  --blue-400: #4d93ff;
  --blue-shadow: #0153d1;
  --blue-shadow-deep: #0144ab;

  --green-500: #049f01;
  --green-shadow-deep: #036b01;

  --yellow-500: #ffd200;
  --yellow-shadow-deep: #ab8d00;

  --red-500: #f10000;
  --red-shadow-deep: #a10000;

  --orange-500: #fe6704;
  --orange-400: #fe6704;
  --orange-shadow: #d85803;
  --orange-dark: #5e2601;

  --peach-50: #fdf2ea;
  --peach-100: #ffefe5;
  --peach-200: #ffdfc9;
  --peach-300: #ffdbc2;
  --peach-panel: #ffede1;

  --white: #ffffff;
  --border-ink: rgba(10, 10, 10, 0.14);

  --font-display: 'Helvetica', Arial, sans-serif;
  --font-heading: 'Helvetica', Arial, sans-serif;
  --font-body: 'Helvetica', Arial, sans-serif;

  --container: 1160px;
  --section-pad: clamp(3.5rem, 6vw, 6.5rem);
  --radius-lg: 2.5rem;
  --radius-md: 1.75rem;
  --radius-pill: 999px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  --title-reveal-color: var(--navy);
  --title-reveal-rgb: 10, 10, 10;
}

/* ==========================================================================
   Reset
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
/* Note: overflow-x:hidden is deliberately NOT set on html/body — forcing that
   axis makes the other one compute to `auto`, turning the document into a
   scroll container and silently breaking `position: sticky` for any
   descendant (used by the testimonials scroll-stack). Any element that
   bleeds past the viewport gets its own local overflow:hidden wrapper
   instead (see .hero, .method, .decor-clip). */
body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
/* Subtle halftone texture over the whole page — a fixed dot-grid overlay,
   low enough opacity to read as paper grain rather than a visible pattern.
   pointer-events:none keeps it fully out of the way of clicks/hover.
   Plain inset:0 is safe here — the header (z-index 50, above this
   overlay's 49) is now always a solid full-bleed bar, so it opaquely
   covers whatever the overlay paints underneath it. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 49;
  pointer-events: none;
  background-image: radial-gradient(circle, rgba(10, 10, 10, 0.01) 1px, transparent 1.2px);
  background-size: 5px 5px;
  mix-blend-mode: multiply;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
ul { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, p { margin: 0; }
.container {
  width: min(100% - 2.5rem, var(--container));
  margin-inline: auto;
}
:focus-visible {
  outline: 3px solid var(--blue-500);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ==========================================================================
   Buttons
   — one reusable, physical "stadium signage" button: a hard offset shadow
   (--btn-shadow-*) that reads as depth. Any variant just needs to set those
   three custom properties + a background; hover/press/shine below apply
   automatically, so a future .btn variant inherits the full interaction
   for free.
   ========================================================================== */
/* Shared "reflexo" gloss band: a fixed diagonal highlight, always visible
   (not hover-triggered, unlike the ::after sweep on each of these below) —
   gives cards and buttons a glassy/3D look at rest, reference-inspired.
   Two bands (one thin, one thicker) drawn as color-stops within a single
   ::before box — a real second pseudo-element isn't available since
   ::after is already the hover-sweep on all three of these elements.
   Painted first so real content still stacks on top without its own
   z-index (pseudo-elements paint before an element's real children).
   Stops are percentages of the gradient line across the FULL box (inset:0)
   rather than a small rotated rectangle positioned via top/left/height% —
   that older approach sized the band relative to the element's own height,
   so it looked fine on short wide buttons but wildly overstretched on
   taller, near-square cards (.pillar), where it clipped down to a single
   solid-looking slab instead of two thin streaks. A full-box gradient
   always spans exactly 0%-100% of the box by construction, so the two
   bands stay proportional on any aspect ratio.
   .btn keeps the original hard-edged, thinner bands (locked in, don't
   touch). .reason-card/.pillar use a separate pair, same hard-edged style,
   just wider bands and dimmer opacity. */
.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  /* Opacity dropped from 0.16/0.22 — those read fine on the original
     larger buttons, but on the smaller ones added since (nav pill links,
     age-card CTAs) the same bands cover proportionally more of the face,
     washing it out to a solid whitish patch instead of a thin sheen. */
  background: linear-gradient(100deg,
    transparent 0%, transparent 8%,
    rgba(255, 255, 255, 0.11) 8%, rgba(255, 255, 255, 0.11) 14%,
    transparent 14%, transparent 26%,
    rgba(255, 255, 255, 0.15) 26%, rgba(255, 255, 255, 0.15) 40%,
    transparent 40%, transparent 100%);
  pointer-events: none;
  z-index: 0;
}
.reason-card::before,
.pillar::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg,
    transparent 0%, transparent 4%,
    rgba(255, 255, 255, 0.0275) 4%, rgba(255, 255, 255, 0.0275) 26%,
    transparent 26%, transparent 36%,
    rgba(255, 255, 255, 0.045) 36%, rgba(255, 255, 255, 0.045) 64%,
    transparent 64%, transparent 100%);
  pointer-events: none;
  z-index: 0;
}

.btn {
  --btn-shadow-color: var(--blue-shadow);
  --btn-shadow-x: 3px;
  --btn-shadow-y: 4px;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border: 1.5px solid var(--btn-shadow-color);
  border-radius: var(--radius-pill);
  padding: calc(1.05em - 1.5px) calc(2.3em - 1.5px);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--white);
  white-space: nowrap;
  box-shadow: var(--btn-shadow-x) var(--btn-shadow-y) 0 var(--btn-shadow-color);
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.btn--blue {
  background: linear-gradient(90deg, var(--blue-400), var(--blue-600));
  --btn-shadow-color: var(--blue-shadow);
}
.btn--orange {
  background: linear-gradient(90deg, var(--orange-400), var(--orange-500));
  --btn-shadow-color: var(--orange-shadow);
}
.btn--sm { padding: 0.8em 1.8em; font-size: 0.8rem; }

/* one-shot glass shine + physical sink, mouse/trackpad only — touch devices
   don't get a lingering hover state, so they skip straight to the :active press */
@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    transform: translateY(2px);
    box-shadow: 0 0 0 0 var(--btn-shadow-color);
  }
  .btn::after {
    content: '';
    position: absolute;
    top: -60%;
    left: -50%;
    width: 45%;
    height: 220%;
    background: linear-gradient(75deg,
      rgba(255, 255, 255, 0) 0%,
      rgba(255, 255, 255, 0) 32%,
      rgba(255, 255, 255, 0.5) 50%,
      rgba(255, 255, 255, 0) 68%,
      rgba(255, 255, 255, 0) 100%);
    transform: translateX(-120%) rotate(25deg);
    opacity: 0;
    pointer-events: none;
  }
  .btn:hover::after {
    animation: shine-sweep 0.85s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  }
  .btn:hover svg { transform: translateX(3px); }
}
/* Shared sweep: travels well past both edges of whatever it's applied to
   (buttons, cards, and the method pillars) so it always reads as crossing
   the whole face, not stopping partway. Tilted 25deg instead of the
   gradient's own 75deg so the on-screen angle (75+25=100deg) matches the
   static gloss on .btn/.reason-card/.pillar above. */
@keyframes shine-sweep {
  0% { transform: translateX(-120%) rotate(25deg); opacity: 0; }
  15% { opacity: 1; }
  55% { opacity: 1; }
  100% { transform: translateX(320%) rotate(25deg); opacity: 0; }
}
.btn svg { transition: transform 0.35s var(--ease); }
.btn:active {
  transform: translateY(3px) scale(0.97);
  box-shadow: 0 0 0 0 var(--btn-shadow-color);
  transition-duration: 0.12s;
}
@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
  .btn::after { display: none; }
  .btn:hover, .btn:active {
    transform: none;
    box-shadow: var(--btn-shadow-x) var(--btn-shadow-y) 0 var(--btn-shadow-color);
  }
}

/* ==========================================================================
   Decorative blobs
   ========================================================================== */
/* Local clip for decor that would otherwise bleed past the viewport edge —
   scoped to just this element so it can't interfere with position:sticky
   elsewhere in the section (see the testimonials scroll-stack). */
.decor-clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

/* Small hand-drawn doodle accents (star/heart/cloud/etc.) — same absolute,
   click-through positioning as .decor, just smaller and always placed via
   inline style per instance since each one's spot is hand-picked per
   section. Hidden below 640px: at that width there's no spare margin left
   around the centered content for them to sit in without crowding text.
   Base rotation is set per-instance via the --r custom property (rather
   than inline transform:rotate()) so the animation variants below can
   layer their own motion on top of it without clobbering it — a CSS
   animation replaces the whole `transform` value for its duration, so
   any rotation baked into an inline `transform` would be lost the moment
   the animation starts. */
.doodle {
  position: absolute;
  pointer-events: none;
  z-index: 0;
  user-select: none;
  opacity: 0.9;
  /* --doodle-scale (overridden below on narrow screens) has to be baked
     into every keyframe too, not just this resting transform — a running
     CSS animation replaces the whole `transform` value each frame, so any
     keyframe that omits it would snap that doodle back to full size the
     moment its animation starts. */
  transform: rotate(var(--r, 0deg)) scale(var(--doodle-scale, 1));
}
@media (max-width: 640px) {
  /* Shrunk rather than hidden — each instance keeps its hand-picked
     corner spot (top/left/right/bottom from its inline style), just at
     roughly half the size, so it still clears the stacked single-column
     content at this width instead of sitting on top of it. */
  .doodle { --doodle-scale: 0.55; }
}

/* Animation variants — applied to a deliberate subset of doodles (not all,
   or the page would feel jittery). Each keyframe re-applies rotate(var(--r))
   and scale(var(--doodle-scale)) every step so the instance's hand-picked
   tilt and (on mobile) shrunk size survive the animation. */
@keyframes doodle-float {
  0%, 100% { transform: rotate(var(--r, 0deg)) scale(var(--doodle-scale, 1)) translateY(0); }
  50% { transform: rotate(var(--r, 0deg)) scale(var(--doodle-scale, 1)) translateY(-12px); }
}
@keyframes doodle-sway {
  0%, 100% { transform: rotate(var(--r, 0deg)) scale(var(--doodle-scale, 1)); }
  50% { transform: rotate(calc(var(--r, 0deg) + 10deg)) scale(var(--doodle-scale, 1)); }
}
@keyframes doodle-pulse {
  0%, 100% { transform: rotate(var(--r, 0deg)) scale(var(--doodle-scale, 1)); }
  50% { transform: rotate(var(--r, 0deg)) scale(calc(var(--doodle-scale, 1) * 1.12)); }
}
.doodle--float { animation: doodle-float 3.6s ease-in-out infinite; }
.doodle--sway { animation: doodle-sway 3.2s ease-in-out infinite; }
.doodle--pulse { animation: doodle-pulse 2.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .doodle--float, .doodle--sway, .doodle--pulse { animation: none; }
}

/* ==========================================================================
   Header
   ========================================================================== */
/* Full-bleed bar spanning the top edge of the hero only — .site-header sits
   in normal document flow at the very top of the page, absolutely
   positioned (not fixed) so it overlays just the hero's opening and then
   scrolls away with the rest of the page like any other content, instead
   of staying pinned to the viewport site-wide. Always transparent, on
   every scroll position. */
.site-header {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 50;
  background: transparent;
}
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0.9rem 0;
}
.logo { display: inline-flex; align-items: center; }
.logo img { height: 51px; width: auto; display: block; }
/* Links grouped in their own floating capsule pill, distinct from the
   header bar behind it. */
.nav-links {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  background: var(--peach-100);
  border-radius: var(--radius-pill);
  padding: 0.35rem 1.3rem;
}
.nav-links a {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--navy);
  padding: 0.55em 0.9em;
  border-radius: var(--radius-pill);
  transition: background 0.25s var(--ease), color 0.25s var(--ease), transform 0.25s var(--ease);
}
.nav-links a:hover {
  background: var(--orange-500);
  color: var(--white);
  transform: translateY(-2px);
}
/* The hamburger/menu button is retired everywhere (see the mobile media
   query below) — .nav-actions no longer holds anything visible on any
   viewport, so it's dropped from the flex row entirely rather than left
   as an empty flex item, which used to eat into the space-between gap and
   push .nav-links away from the header's right edge. */
.nav-actions { display: none; }

/* Mobile drops the menu entirely — no hamburger, no link drawer, just the
   centered logo. (.nav-actions carrying the toggle button is already
   display:none above, on every viewport.) */
@media (max-width: 860px) {
  .nav { justify-content: center; }
  .nav-links, .nav-scrim { display: none; }
}

/* ==========================================================================
   Hero
   — background is a client-supplied flat comp (images/HERO/HERO-BG.png,
   HERO-MOBILE-BG.png for the stacked mobile layout), not built from
   separate decor/photo elements: it already bakes in the photo collage,
   color blobs, speech bubbles and the cream backdrop watermark. .hero-visual
   is locked to the image's own aspect-ratio (so background-size:100% 100%
   never distorts it) and .hero-inner is sized/positioned to sit exactly in
   the blank area the comp reserves for text — measured from the source
   PNGs: the collage starts at ~42% of the width on desktop, and the text
   band is the top ~45% of the height on mobile.
   ========================================================================== */
.hero {
  position: relative;
  /* Clears the absolutely-positioned site-header, which overlays this
     section's top edge — the background/aspect-ratio box below can't
     carry this padding itself,
     since combined with box-sizing:border-box that would shrink the area
     available to the background image and squash it out of its own ratio. */
  padding-top: clamp(4.5rem, 8vw, 5.5rem);
  overflow: hidden;
  /* Capped so the aspect-ratio box below can't grow taller than this on
     ultra-wide monitors — full-bleed width with no cap meant the box's
     height (locked to width via aspect-ratio) kept climbing past ~1920px
     too, so the collage baked into the image (a fixed proportion of the
     box) drifted further and further from .hero-inner's text, which just
     centers in the middle of whatever height the box ends up with. */
  max-width: 1920px;
  margin-inline: auto;
}
.hero-visual {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2rem);
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  /* Lives here, not on .hero-inner: padding-box background-origin (the
     default) already covers the whole padding area, so this doesn't shift
     the background at all. Putting it on .hero-inner instead — combined
     with that element's own capped width — was the ultra-wide bug: past
     ~1985px viewport this padding alone exceeds the text column's width,
     and with box-sizing:border-box that collapses the content area to
     ~0, wrapping every single word onto its own line.
     min(100vw, 1920px): matches .hero's own max-width above, so this
     stays in lockstep with the centered box's real width instead of
     still growing off 100vw once .hero itself has stopped growing. */
  padding-left: max(1.25rem, calc((min(100vw, 1920px) - var(--container)) / 2));
  /* A plain 1.25rem floor (matching the left side's own floor) let
     .hero-collage's flex:1 growth run the image right up against the
     viewport edge at in-between widths (~1000-1300px) where there's no
     extra container-centering slack to fall back on yet. This scales
     with viewport instead of sitting at that floor, so there's always a
     visible gutter, not just at the two ends of the range. */
  padding-right: clamp(1.25rem, 5vw, 3rem);
}
.hero-inner {
  position: relative;
  z-index: 1;
  text-align: left;
  width: min(34vw, 520px);
  flex-shrink: 0;
}
/* Desktop only (hidden on mobile below, which keeps the original full-
   bleed background-image treatment instead) — a real flex column sized
   to the actual photo collage, cropped out of the old full-width hero
   image (which baked in a huge blank margin on the left for the text to
   sit over, via background-position/padding tricks). That margin was a
   FIXED share of the image's own width, so any padding-left formula
   trying to keep .hero-inner inside it broke at some viewport width or
   other — this just gives text and image their own independent boxes
   instead of overlaying one on the other. Capped narrower than before
   (was 900px) so it can't grow flush against the padding-right gutter
   above at medium-wide viewports, on top of that gutter's own scaling. */
.hero-collage {
  flex: 1 1 0;
  min-width: 0;
  max-width: 950px;
  margin-left: -4.5rem;
}
.hero-collage img {
  width: 100%;
  height: auto;
  display: block;
  -webkit-user-drag: none;
}
.hero-title {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--orange-500);
  font-size: clamp(1.5rem, 2.4vw, 2.2rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  opacity: 0;
  transform: translateY(14px);
}
.hero-title em {
  font-style: normal;
  font-weight: 700;
  color: var(--blue-600);
}
/* The "not this / actually this" contrast line above the real headline —
   faded so it reads as the thing being dismissed, with the punchline
   underneath at full weight. */
.hero-title-strike {
  display: block;
  font-size: 0.6em;
  font-weight: 500;
  color: var(--navy);
  opacity: 0.5;
  margin-bottom: 0.9em;
}
/* Bigger on desktop only — at 0.6em it read as an afterthought next to
   the large main line; mobile's own proportions already read fine as-is. */
@media (min-width: 861px) {
  .hero-title-strike { font-size: 0.85em; }
}
.hero-title-main { display: block; }
.hero-cta { margin-top: 1.75rem; opacity: 0; transform: translateY(14px); }
/* Mobile has its own copy of the CTA, placed below the photo collage
   instead of inside .hero-inner above it — see the mobile media query.
   Hidden by default (desktop keeps the button in the text column). */
.hero-cta--mobile { display: none; }
@media (max-width: 860px) {
  /* The desktop side-by-side layout (.hero-inner text + .hero-collage
     photo as independent flex columns) doesn't apply here — mobile keeps
     its original single full-bleed background-image treatment instead,
     photo below text, so every desktop-only spacing property added to
     .hero-visual above needs resetting back out. */
  .hero-visual {
    /* Slightly taller than the image's native 1080/1440 ratio — with
       background-size:100% auto (below) the image keeps its own real
       proportions and just anchors to the bottom, so the extra height
       shows up as a small buffer of blank space above the collage. Kept
       tight on purpose so the photo collage sits close under the text
       instead of leaving a big dead gap underneath it. */
    aspect-ratio: 1080 / 1460;
    background-image: url(../images/HERO/HERO-MOBILE-BG.png);
    background-size: 100% auto;
    background-position: bottom center;
    background-color: var(--cream);
    align-items: flex-start;
    gap: 0;
    padding: 0;
  }
  .hero-collage { display: none; }
  .hero-inner {
    /* .hero-visual's blank zone (the buffer height above + the image's own
       built-in blank top) works out to ~40% of the box's total height (see
       the aspect-ratio comment above) — that height has to stay matched to
       the image's own built-in blank area regardless of how much text is
       in it, so with the subtitle gone (title only, now) the fix for the
       leftover space is in how content ALIGNS within this box, not its
       height: flex-end instead of center pins the (shorter) title to the
       bottom, flush against the collage, instead of centering it and
       leaving growing gaps above and below as content shrinks. */
    width: 100%;
    height: 40%;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 0 1.5rem 1.25rem;
    text-align: center;
  }
  /* The desktop CTA sits inside .hero-inner, in the blank zone above the
     collage — on mobile the button moves to .hero-cta--mobile instead,
     below the whole photo collage, so this copy is dropped from layout. */
  .hero-inner .hero-cta { display: none; }
  /* Sized up to actually fill the navbar-to-collage band above instead of
     floating in it with empty space top and bottom. */
  .hero-title { font-size: clamp(1.95rem, 8.4vw, 2.6rem); }
  .hero-cta--mobile {
    display: flex;
    justify-content: center;
    padding: 1.75rem 1.5rem 0.5rem;
  }
  .hero-cta--mobile .btn, .hero-cta .btn { padding: 0.55em 1.2em; font-size: 0.68rem; }
}

.hero.is-ready .hero-title { transition: opacity 0.7s var(--ease) 0.15s, transform 0.7s var(--ease) 0.15s; opacity: 1; transform: none; }
.hero.is-ready .hero-cta { transition: opacity 0.7s var(--ease) 0.4s, transform 0.7s var(--ease) 0.4s; opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .hero-title, .hero-cta { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ==========================================================================
   Marquee — endless scrolling strip between the hero and the next section.
   .marquee-track holds two identical .marquee-group copies back to back;
   animating translateX(-50%) scrolls exactly one copy's width, so the loop
   seams invisibly into the next copy instead of jumping/snapping.
   .marquee-stack layers a second bar (.marquee--back) behind the straight
   one, tilted a couple degrees and scrolling in reverse — same technique
   as the old .wave bands (overscanned left/right so the rotated edges
   never show a gap, clipped by the stack's own overflow:hidden), with a
   fixed height taller than either bar so the back one's rotated corners
   peek out above/below the front bar instead of getting clipped flush.
   ========================================================================== */
.marquee-stack {
  position: relative;
  overflow: hidden;
  /* Tall enough to fit the *rotated* back bar's full bounding box, not just
     its own straight height — a bar rotated -3deg and overscanned to 116%
     width adds roughly sin(3deg) * 116vw =~ 6vw of extra vertical reach on
     top of its ~50px straight height. Too short here was clipping straight
     through the back bar's text instead of just peeking its edges. */
  height: clamp(110px, calc(6.5vw + 55px), 230px);
}
.marquee {
  background: var(--orange-500);
  overflow: hidden;
  padding: 0.9rem 0;
}
.marquee--front {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  z-index: 1;
}
.marquee--back {
  position: absolute;
  top: 50%;
  left: -8%;
  right: -8%;
  transform: translateY(-50%) rotate(-3deg);
  filter: brightness(0.82);
  z-index: 0;
}
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee-scroll 24s linear infinite;
}
.marquee-track--reverse { animation-direction: reverse; }
.marquee-group { display: flex; align-items: center; flex-shrink: 0; }
.marquee-group span {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--white);
  white-space: nowrap;
  padding: 0 1.5rem;
}
.marquee-icon { width: 16px; height: 16px; flex-shrink: 0; }
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
}

/* ==========================================================================
   Section shell
   ========================================================================== */
.section { position: relative; padding: var(--section-pad) 0; }
.section-head { max-width: 640px; margin: 0 auto 2.75rem; text-align: center; }
.eyebrow {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 0.75rem;
}
.eyebrow--blue { color: var(--blue-600); }
.eyebrow--orange { color: var(--orange-500); }
.section-title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.9rem, 3.6vw, 2.85rem);
  line-height: 1.15;
  color: var(--navy);
}
.section-title--blue { color: var(--blue-600); }
.section-title--orange { color: var(--orange-500); }
.section-title strong { font-weight: 700; }

/* ==========================================================================
   Section-title block reveal
   A solid block wipes in from the left (hiding the text completely), then
   wipes out to the right, uncovering it. One-shot, driven by main.js
   (.js-section-title + IntersectionObserver). See the JS for the animation
   timeline — this just lays out the three layers.
   ========================================================================== */
.section-title-line {
  position: relative;
  display: block;
  width: max-content;
  max-width: 100%;
  /* Each line now shrink-wraps to its own text (JS splits multi-line
     headings into one .section-title-line per visual line), so it needs
     its own centering — a block box doesn't pick up the ancestor's
     text-align just because it's narrower than its container. */
  margin-inline: auto;
  padding-block: 0.17em 0.14em;
  margin-block: -0.17em -0.14em;
  overflow: hidden;
  isolation: isolate;
}
.section-title-text {
  position: relative;
  z-index: 1;
  display: block;
  visibility: hidden;
}
.section-title-wipe {
  position: absolute;
  z-index: 2;
  top: 0.035em;
  right: 0;
  bottom: 0.025em;
  left: 0;
  background: var(--title-reveal-color);
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
  backface-visibility: hidden;
  pointer-events: none;
}
.section-title-blur {
  position: absolute;
  top: -0.035em;
  bottom: -0.035em;
  width: clamp(34px, 8vw, 92px);
  opacity: 0;
  filter: blur(8px);
  transform: scaleX(1.28);
  pointer-events: none;
}
.section-title-blur.is-entering {
  right: -0.1em;
  left: auto;
  opacity: 0.62;
  background: linear-gradient(90deg,
    rgba(var(--title-reveal-rgb), 0),
    rgba(var(--title-reveal-rgb), 0.24),
    rgba(var(--title-reveal-rgb), 0.82));
}
.section-title-blur.is-exiting {
  right: auto;
  left: -0.1em;
  opacity: 0.58;
  background: linear-gradient(90deg,
    rgba(var(--title-reveal-rgb), 0.82),
    rgba(var(--title-reveal-rgb), 0.24),
    rgba(var(--title-reveal-rgb), 0));
}
@media (prefers-reduced-motion: reduce) {
  .section-title-text { visibility: visible; }
  .section-title-wipe,
  .section-title-blur { display: none; }
}

.section-sub {
  margin-top: 1rem;
  font-size: 1.05rem;
  color: var(--navy);
  opacity: 0.85;
}
.section-cta { display: flex; justify-content: center; margin-top: 2.75rem; }

.reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
.reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ==========================================================================
   Reasons (3 feature cards)
   ========================================================================== */
.reasons-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.75rem;
}
.reason-card {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(143deg, var(--peach-100) 5%, var(--peach-200) 97%);
  border: 1.5px solid #f9d0b3;
  border-radius: var(--radius-md);
  box-shadow: 6px 7px 0 0 #f9d0b3;
  padding: 2.5rem 2rem;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.reason-card:hover {
  transform: translateY(-6px) scale(1.025);
  box-shadow: 6px 7px 0 0 #f9d0b3, 0 20px 30px -14px rgba(181, 76, 7, 0.28);
}
.reason-card::after {
  content: '';
  position: absolute;
  top: -60%;
  left: -50%;
  width: 45%;
  height: 220%;
  background: linear-gradient(75deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0) 32%,
    rgba(255, 255, 255, 0.55) 50%,
    rgba(255, 255, 255, 0) 68%,
    rgba(255, 255, 255, 0) 100%);
  transform: translateX(-120%) rotate(25deg);
  opacity: 0;
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .reason-card:hover::after {
    animation: shine-sweep 0.85s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  }
}
@media (prefers-reduced-motion: reduce) {
  .reason-card { transition: none; }
  .reason-card::after { display: none; }
}
.reason-card h3 {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.2rem;
  color: var(--navy);
  margin-bottom: 0.85rem;
}
.reason-card p { font-size: 0.95rem; color: var(--navy); opacity: 0.85; font-weight: 300; }

@media (max-width: 860px) {
  .reasons-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Method (pillars)
   ========================================================================== */
.method {
  /* Full-bleed at any viewport width: the section itself is already
     edge-to-edge (only .method-inner is width-constrained), so the beige
     background always spans the full screen — no side margins to fight. */
  background: var(--peach-50);
  overflow: hidden;
}
.method-inner {
  position: relative;
  z-index: 1;
  width: min(100% - 2.5rem, var(--container));
  margin-inline: auto;
  padding: clamp(3rem, 6vw, 5rem) 0;
}
/* Learning journey — a 6-step dashed timeline (👶 → 🌎) replacing the old
   4-pillar grid. Equal-width flex columns (not content-sized) keep each
   dot perfectly centered under the dashed connector regardless of how
   long its label is. */
.timeline { margin-top: 2.5rem; }
.timeline-track {
  position: relative;
  display: flex;
  gap: 0.25rem;
}
.timeline-track::before {
  content: '';
  position: absolute;
  top: 32px;
  left: calc(100% / 12);
  right: calc(100% / 12);
  border-top: 3px dashed var(--peach-300);
  z-index: 0;
}
.timeline-step {
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  text-align: center;
}
.timeline-dot {
  --dot-bg: var(--blue-600);
  --dot-shadow: var(--blue-shadow-deep);
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.7rem;
  line-height: 1;
  background: var(--dot-bg);
  border: 1.5px solid var(--dot-shadow);
  box-shadow: 4px 5px 0 0 var(--dot-shadow);
}
.timeline-dot--green { --dot-bg: var(--green-500); --dot-shadow: var(--green-shadow-deep); }
.timeline-dot--yellow { --dot-bg: var(--yellow-500); --dot-shadow: var(--yellow-shadow-deep); }
.timeline-dot--red { --dot-bg: var(--red-500); --dot-shadow: var(--red-shadow-deep); }
.timeline-dot--orange { --dot-bg: var(--orange-500); --dot-shadow: var(--orange-shadow); }
/* A little "hop" on hover, not a constant loop — playful without being
   distracting while you're just reading the section. */
@keyframes timeline-hop {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}
@media (hover: hover) and (pointer: fine) {
  .timeline-step:hover .timeline-dot {
    animation: timeline-hop 0.6s ease-in-out;
  }
}
@media (prefers-reduced-motion: reduce) {
  .timeline-step:hover .timeline-dot { animation: none; }
}
.timeline-label {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--navy);
}
@media (max-width: 700px) {
  /* A dashed line across a wrapped, multi-row grid reads as broken, so it
     drops here in favor of a simple centered wrap — the steps stay legible
     as a sequence without needing the literal connector. */
  .timeline-track { flex-wrap: wrap; justify-content: center; row-gap: 1.75rem; }
  .timeline-track::before { display: none; }
  .timeline-step { flex: 0 1 30%; min-width: 84px; }
  .timeline-dot { width: 52px; height: 52px; font-size: 1.4rem; }
}

/* ==========================================================================
   Age groups carousel
   — full-bleed infinite-loop carousel (autoplay + drag): spans the whole
   viewport edge-to-edge (the section itself is already full-width, so no
   100vw hack is needed here either), giving the loop far more room before a
   card ever needs to be partway off either edge. The card set is cloned
   once in JS for a seamless wraparound.
   ========================================================================== */
.ages-carousel {
  position: relative;
  z-index: 1;
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
  margin-top: 2.75rem;
  padding: 0.5rem 0 1.5rem;
}
.ages-carousel.is-dragging { cursor: grabbing; }
.ages-track {
  display: flex;
  gap: 1.25rem;
  width: max-content;
  padding-left: max(1.25rem, calc((100% - var(--container)) / 2));
  will-change: transform;
}
.age-card {
  --card-w: clamp(230px, 80vw, 300px);
  --age-card-bg: var(--orange-500);
  --age-card-shadow: var(--orange-shadow);
  position: relative;
  width: var(--card-w);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--age-card-shadow);
  box-shadow: 6px 7px 0 0 var(--age-card-shadow);
  background: var(--age-card-bg);
  color: var(--white);
  overflow: hidden;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.age-card--blue { --age-card-bg: var(--blue-600); --age-card-shadow: var(--blue-shadow-deep); }
.age-card--green { --age-card-bg: var(--green-500); --age-card-shadow: var(--green-shadow-deep); }
@media (min-width: 600px) {
  .age-card { --card-w: clamp(300px, 46vw, 380px); }
}
@media (min-width: 1024px) {
  .age-card { --card-w: clamp(300px, 29vw, 340px); }
}
.age-card-photo { aspect-ratio: 4 / 3; overflow: hidden; }
.age-card-photo--zoom img { transform: scale(1.35); }
.age-card-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  -webkit-user-drag: none;
}
.age-card-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
  flex: 1;
  padding: 1.3rem 1.3rem 1.5rem;
}
.age-card-badge {
  background: rgba(255, 255, 255, 0.22);
  padding: 0.3em 0.85em;
  border-radius: var(--radius-pill);
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
}
.age-card-body h3 { font-family: var(--font-heading); font-weight: 700; font-size: 1.5rem; }
.age-card-points { display: flex; flex-direction: column; gap: 0.3rem; flex: 1; font-size: 0.88rem; opacity: 0.95; }
.age-card-points li::before { content: '— '; opacity: 0.7; }
.age-card-btn { margin-top: 0.3rem; }
.ages-carousel:not(.is-dragging) .age-card:hover {
  transform: translateY(-8px);
  box-shadow: 8px 10px 0 0 var(--age-card-shadow);
}

/* Entrance: cards rise + fade in, staggered, once, when the carousel first enters view */
.stagger-group .age-card {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.stagger-group.is-visible .age-card { opacity: 1; transform: none; }
.ages-track .age-card:nth-child(1) { transition-delay: 0s; }
.ages-track .age-card:nth-child(2) { transition-delay: 0.08s; }
.ages-track .age-card:nth-child(3) { transition-delay: 0.16s; }
.ages-track .age-card:nth-child(n+4) { transition-delay: 0.24s; }
@media (prefers-reduced-motion: reduce) {
  .stagger-group .age-card { opacity: 1; transform: none; transition: none; }
  .age-card { transition: none; }
}

.ages-hint {
  text-align: center;
  font-size: 0.85rem;
  color: var(--navy);
  opacity: 0.55;
  margin-top: 1.25rem;
}

/* ==========================================================================
   Gallery — real photos from the school, laid out as a desktop mosaic
   (a couple of tall/wide cells among the square ones, via grid spans) that
   collapses into a swipeable horizontal strip on mobile — native scroll-
   snap, no drag JS needed since (unlike the age-card carousel) nothing
   here needs click-through cards or buttons, just a quick swipe.
   ========================================================================== */
.gallery-grid {
  /* 1 wide/tall feature (2x2) + 4 plain squares (1x1 each) = 8 cells,
     exactly filling a 4-column x 2-row grid with no leftover gaps. */
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 15vw);
  gap: 1rem;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 1.25rem;
}
.gallery-item {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-md);
  isolation: isolate;
}
.gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.5s var(--ease);
}
.gallery-caption {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2.2rem 1rem 0.85rem;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.68), rgba(10, 10, 10, 0));
  color: var(--white);
  font-family: var(--font-heading);
  font-size: 0.82rem;
  font-weight: 600;
}
@media (hover: hover) and (pointer: fine) {
  .gallery-item:hover img { transform: scale(1.06); }
}
@media (prefers-reduced-motion: reduce) {
  .gallery-item img { transition: none; }
}
.gallery-item--wide { grid-column: span 2; grid-row: span 2; }

@media (max-width: 860px) {
  .gallery-grid {
    display: flex;
    grid-template-rows: unset;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 0.9rem;
    padding: 0 1.25rem;
  }
  .gallery-item {
    flex: 0 0 72%;
    aspect-ratio: 3 / 4;
    scroll-snap-align: center;
  }
  .gallery-item--wide { flex-basis: 72%; aspect-ratio: 3 / 4; }
}

/* ==========================================================================
   Testimonials — scroll-locked stepped stack
   .testimonials-pin is a plain 100vh block. When it exactly fills the
   viewport, JS (see main.js) takes over wheel/touch input: the page stops
   moving and each scroll gesture advances or regresses one card instead.
   Once the last card is reached (or, going back up, once the first card is
   reached), control is handed back and normal page scroll continues. No
   tall spacer / position:sticky needed — freezing scroll while the section
   already fills the screen keeps it visually in place on its own.
   Reduced-motion gets a plain static stacked list instead (below), and the
   scroll-lock never engages in the first place.
   ========================================================================== */
.testimonials-section {
  /* The pin section's own content already provides the visual weight of
     a full screen — the generic .section bottom padding on top of that
     read as an oversized gap before the CTA banner. */
  padding-bottom: 0;
}
.testimonials-pin {
  /* Must be exactly 100vh: the scroll-lock only reads as "locked" because
     freezing the page while this block fully covers the viewport hides the
     fact that scrolling has stopped. Anything shorter (75vh was tried to
     shrink the gap before the CTA banner) leaves a strip of the next
     section visible-but-frozen at the bottom while cards cycle above it —
     looks broken, not intentional. Fix the gap via align-items/padding
     below instead, never via height. */
  position: relative;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(10rem, 5vh, 1rem);
}
.testimonial-stack {
  position: relative;
  z-index: 1;
  width: min(100% - 2.5rem, 760px);
  margin-inline: auto;
  height: 190px;
}
.testimonial-card {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.25rem;
  align-items: center;
  border: 1px solid var(--ink);
  border-radius: 1.4rem;
  padding: 1.6rem 2rem;
  color: var(--white);
  box-shadow: 0 10px 20px -12px rgba(10, 10, 10, 0.2);
  transition:
    opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.6s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.5s var(--ease);
  opacity: 0;
  visibility: hidden;
  transform: translateY(60px) scale(0.96);
  z-index: 1;
}
.testimonial-card:nth-child(1) { background: var(--blue-500); }
.testimonial-card:nth-child(2) { background: var(--orange-500); }
.testimonial-card:nth-child(3) { background: var(--blue-500); }
.testimonial-card.is-active {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1) rotate(0deg);
  z-index: 20;
  box-shadow: 0 24px 48px -16px rgba(10, 10, 10, 0.35);
}
.testimonial-card.is-behind {
  opacity: clamp(0.45, calc(1 - 0.16 * var(--depth, 1)), 1);
  visibility: visible;
  transform:
    translateY(calc(var(--depth, 1) * -18px))
    scale(calc(1 - var(--depth, 1) * 0.035))
    rotate(calc(var(--depth, 1) * -0.8deg));
  z-index: calc(20 - var(--depth, 1));
}
.testimonial-card.is-hidden {
  opacity: 0;
  visibility: hidden;
  transform: translateY(60px) scale(0.96);
  z-index: 1;
}
.avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.9rem;
  color: var(--navy);
  flex-shrink: 0;
}
.testimonial-card h3 { font-family: var(--font-heading); font-weight: 700; font-size: 1.1rem; margin-bottom: 0.35rem; }
.testimonial-card p { font-size: 0.9rem; opacity: 0.95; }

@media (max-width: 640px) {
  .testimonial-stack { height: 330px; }
  .testimonial-card { grid-template-columns: 1fr; text-align: center; padding: 1.5rem 1.4rem; }
  .avatar { margin-inline: auto; }
}

@media (prefers-reduced-motion: reduce) { 
  .testimonials-pin { height: auto; }
  .testimonial-stack {
    height: auto;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }
  .testimonial-card {
    position: relative;
    inset: auto;
    opacity: 1;
    visibility: visible;
    filter: none;
    transform: none;
    z-index: auto;
    transition: none;
  }
}

/* ==========================================================================
   CTA banner
   ========================================================================== */
.cta-banner {
  position: relative;
  background: var(--orange-500);
  padding: clamp(3.5rem, 7vw, 5.5rem) 0;
  text-align: center;
  color: var(--white);
}
.cta-banner-inner { max-width: 620px; margin-inline: auto; display: flex; flex-direction: column; align-items: center; gap: 1.6rem; }
.cta-banner h2 { align-self: stretch; font-family: var(--font-heading); font-weight: 700; font-size: clamp(1.7rem, 3.6vw, 2.5rem); }
.cta-banner h2 strong { font-weight: 700; }
.cta-banner p { font-size: 1.02rem; opacity: 0.95; }
.cta-banner-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem 1.8rem;
  font-size: 1.02rem;
  font-weight: 600;
}
.cta-banner-list li { display: flex; align-items: center; gap: 0.5rem; }
.cta-banner-list li::before { content: '✓'; font-weight: 700; }
.cta-banner-note { font-size: 0.9rem; opacity: 0.8; margin-top: -0.6rem; }

/* ==========================================================================
   FAQ
   ========================================================================== */
.faq-panel {
  position: relative;
  z-index: 1;
  background: var(--peach-panel);
  border: 1px solid var(--ink);
  border-radius: var(--radius-lg);
  width: min(100% - 2.5rem, 1000px);
  margin-inline: auto;
  padding: clamp(2.5rem, 5vw, 4rem) clamp(1.5rem, 5vw, 4rem);
}
.faq-list { display: flex; flex-direction: column; gap: 1.1rem; margin-top: 2.5rem; }
.faq-item {
  background: var(--peach-300);
  border-radius: 0.9rem;
  overflow: hidden;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.faq-item:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 22px -14px rgba(181, 76, 7, 0.35);
}
@media (prefers-reduced-motion: reduce) {
  .faq-item { transition: none; }
}
.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: none;
  border: none;
  text-align: left;
  padding: 1.35rem 1.6rem;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--ink);
}
.faq-icon {
  flex-shrink: 0;
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  color: var(--orange-500);
  font-family: var(--font-heading);
  font-size: 1.6rem;
  font-weight: 700;
  transition: transform 0.25s var(--ease);
}
.faq-item[data-open="true"] .faq-icon { transform: rotate(135deg); }
.faq-answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s var(--ease);
}
.faq-item[data-open="true"] .faq-answer { grid-template-rows: 1fr; }
.faq-answer-inner { overflow: hidden; }
.faq-answer p { padding: 0 1.6rem 1.35rem; font-size: 0.95rem; color: var(--navy); opacity: 0.85; }
@media (prefers-reduced-motion: reduce) {
  .faq-answer { transition: none; }
  .faq-icon { transition: none; }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  position: relative;
  background: var(--orange-dark);
  color: var(--white);
  padding: 4rem 0 0;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  gap: 2.5rem;
  padding-bottom: 3rem;
}
.footer-brand { display: flex; flex-direction: column; align-items: flex-start; gap: 1.1rem; }
.footer-brand .logo img { height: 63px; }
.footer-tagline { font-size: 0.92rem; line-height: 1.5; opacity: 0.85; max-width: 32ch; }
.footer-heading {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-bottom: 1.1rem;
}
.footer-links { display: flex; flex-direction: column; align-items: flex-start; gap: 0.8rem; }
.footer-links a {
  font-size: 0.95rem;
  font-weight: 500;
  opacity: 0.92;
  transition: opacity 0.2s var(--ease);
}
.footer-links a:hover { opacity: 1; text-decoration: underline; }
.footer-note-line { font-size: 0.85rem; opacity: 0.7; line-height: 1.5; }
.footer-map-wrap { padding-bottom: 2.5rem; }
.footer-map {
  position: relative;
  height: 260px;
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 16px 32px -16px rgba(0, 0, 0, 0.4);
}
.footer-map iframe { display: block; width: 100%; height: 100%; }
.footer-map-btn {
  position: absolute;
  top: 1rem;
  left: 1rem;
  background: var(--orange-500);
  color: var(--white);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 0.65em 1.2em;
  border-radius: var(--radius-pill);
  box-shadow: 0 10px 20px -10px rgba(0, 0, 0, 0.5);
}
.footer-map-address {
  margin-top: 0.85rem;
  font-size: 0.85rem;
  opacity: 0.75;
  text-align: center;
}
.footer-bottom {
  padding: 1.5rem 0;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.footer-note {
  font-size: 0.82rem;
  opacity: 0.75;
  text-align: center;
}
@media (max-width: 700px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 480px) {
  .footer-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Floating WhatsApp button — fixed bottom-right, always on top (z-index 90,
   just under the modal's 100). Desktop shows only the round icon; mobile
   adds the text pill next to it (reference-matched: pill + separate round
   button side by side). WhatsApp's own green, not the site's orange/blue —
   this is a universally recognized convention for this exact action.
   ========================================================================== */
.whatsapp-float {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  transition: opacity 0.25s var(--ease);
}
.whatsapp-float.is-hidden {
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .whatsapp-float { transition: none; }
}
.whatsapp-float-label { display: none; }
.whatsapp-float-icon {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  border-radius: 50%;
  background: #22e065;
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.4);
  transition: transform 0.25s var(--ease);
}
.whatsapp-float-icon svg { width: 28px; height: 28px; }
.whatsapp-float:hover .whatsapp-float-icon { transform: scale(1.08); }
@media (max-width: 860px) {
  .whatsapp-float {
    right: auto;
    left: 50%;
    transform: translateX(-50%);
  }
  .whatsapp-float-label {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    background: #22e065;
    color: var(--white);
    font-family: var(--font-heading);
    font-weight: 500;
    font-size: 0.85rem;
    padding: 0.9em 1.3em;
    border-radius: var(--radius-pill);
    box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.4);
  }
  .whatsapp-float-icon { width: 48px; height: 48px; }
  .whatsapp-float-icon svg { width: 24px; height: 24px; }
}
@media (prefers-reduced-motion: reduce) {
  .whatsapp-float-icon { transition: none; }
}

/* ==========================================================================
   CTA popup modal — opens on any .js-wa button click (see main.js), in
   place of jumping straight to WhatsApp. Overlay is a plain fixed inset:0
   so it always covers the full viewport evenly, and everything inside the
   card is centered (flex column, text-align:center) — no stray shadow or
   off-center content.
   ========================================================================== */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(10, 10, 10, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s var(--ease);
}
.modal-overlay[data-open="true"] { opacity: 1; pointer-events: auto; }
.modal-card {
  position: relative;
  width: min(100%, 380px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  text-align: center;
  background: var(--white);
  border: 1px solid #000;
  border-radius: 0.9rem;
  padding: 2.5rem 2rem 2rem;
  box-shadow: 0 30px 60px -20px rgba(10, 10, 10, 0.4);
  transform: scale(0.92) translateY(12px);
  transition: transform 0.3s var(--ease);
}
.modal-overlay[data-open="true"] .modal-card { transform: scale(1) translateY(0); }
.modal-close {
  position: absolute;
  top: 0.9rem;
  right: 0.9rem;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: var(--peach-100);
  color: var(--navy);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-logo { height: 34px; width: auto; }
.modal-title { font-family: var(--font-heading); font-weight: 700; font-size: 1.3rem; color: var(--navy); }
.modal-text { font-size: 0.92rem; color: var(--navy); opacity: 0.8; }
.modal-cta { margin-top: 0.4rem; }
@media (prefers-reduced-motion: reduce) {
  .modal-overlay, .modal-card { transition: none; }
}
