/* Little Peaches — Coming Soon landing page
   Page-specific styles. Design tokens (colors, type, spacing, motion) are
   linked in index.html from the design system; nothing here hardcodes a
   raw color, font, or spacing value. */

html, body {
  margin: 0;
  padding: 0;
  background: var(--cream-50);
}

.page {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--cream-50);
}

/* ---------- decorative backdrop (boho waves), non-interactive ---------- */

.backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.backdrop__waves {
  position: absolute;
  top: 0;
  right: 0;
  width: min(46vw, 560px);
  height: 100%;
}

.waves-svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

.wave {
  opacity: 0;
  transform: scale(0.96);
  transform-box: fill-box;
  transform-origin: 50% 0%;
  /* One-time entrance (--duration-slow, all layers together — this is
     "Step 1: background" of the page-load sequence, so it stays quick and
     immediate rather than staggered or dramatic), then a continuous
     "breathing" loop layered on afterward — flowing movement and an
     opacity rise/fall, both scoped to this one keyframe so each layer's
     depth and drift stay in step with *itself*. Breathe duration/delay
     still vary per layer below so the four layers never brighten/dim in
     sync with each other once the ambient loop takes over.
     Split into longhand animation-* properties rather than the `animation`
     shorthand: mixing var() into a duration/delay *slot inside a
     shorthand list* is unreliable in Safari even when plain var() on the
     longhand property works fine — this is the standard cross-browser-safe
     way to drive animation timing from custom properties. */
  animation-name: wave-in, wave-breathe;
  animation-duration: var(--duration-slow), var(--breathe-dur, 24s);
  animation-timing-function: var(--ease-out), var(--ease-in-out);
  animation-delay: var(--in-delay, 0s), var(--breathe-delay, 0s);
  animation-iteration-count: 1, infinite;
  animation-fill-mode: both, none;
}

/* nth-of-type targets each <path>'s position among its own <svg> siblings,
   so this varies the breathing rate per layer across all three wave
   compositions without touching a single path's colors, opacity, shape or
   position. Entrance (--in-delay) is intentionally left at its 0s default
   for every layer now — Step 1 of the page-load sequence is the background
   appearing immediately and all at once, not staggering in piece by piece. */
.wave:nth-of-type(1) { --breathe-dur: 10s; --breathe-delay: 0s; }
.wave:nth-of-type(2) { --breathe-dur: 13s; --breathe-delay: 2s; }
.wave:nth-of-type(3) { --breathe-dur: 8s; --breathe-delay: 3.6s; }
.wave:nth-of-type(4) { --breathe-dur: 11s; --breathe-delay: 1s; }

@keyframes wave-in { from { opacity: 0; transform: scale(0.96); } to { opacity: var(--wave-opacity, 0.16); transform: scale(1); } }

/* Opacity swings proportionally around each layer's own --wave-opacity
   (e.g. a layer set to 0.34 breathes roughly between ~0.19 and ~0.5) rather
   than a fixed amount, so every layer keeps its existing relative depth
   while still visibly, clearly rising and falling — a further bump on top
   of the first breathing pass, per "increase intensity... applies to the
   waves too." Durations were also shortened (was 19–31s, now 14–23s) for a
   faster cycle, still slow/organic rather than a visible slide. */
@keyframes wave-breathe {
  0%   { opacity: var(--wave-opacity, 0.16); transform: scale(1) translate(0, 0) rotate(0deg); }
25%  { opacity: calc(var(--wave-opacity, 0.16) * 1.45); transform: scale(1.05) translate(16px, -18px) rotate(1.5deg); }
50%  { opacity: calc(var(--wave-opacity, 0.16) * 0.58); transform: scale(0.96) translate(-12px, 12px) rotate(-1deg); }
75%  { opacity: calc(var(--wave-opacity, 0.16) * 1.25); transform: scale(1.025) translate(-16px, -7px) rotate(1deg); }
  100% { opacity: var(--wave-opacity, 0.16); transform: scale(1) translate(0, 0) rotate(0deg); }
}

/* Two additional wave compositions, reusing the exact .wave/.waves-svg
   treatment above (same colors, opacity values, blur, animation) with new
   shapes/containers only — the original .backdrop__waves block is untouched. */
.backdrop__waves--top {
  top: 0;
  left: 0;
  right: 0;
  width: auto;
  height: 30vh;
}

.backdrop__waves--left {
  top: 0;
  left: 0;
  right: auto;
  width: min(40vw, 480px);
  height: 100%;
}

/* ---------- floating decorative elements (peach / leaf / sparkle) ---------- */

.floaty {
  position: absolute;
  opacity: 0;
  display: block;
}

/* Each element supplies its own --base-r (static rest tilt), --fx/--fy/--fr
   (drift distance + extra rotation) and --fdur/--fdelay (its own loop speed
   and offset) via inline style, so no two instances move identically even
   though they all share these same three keyframes.

   --reveal-decor-delay is the base offset for every floaty's entrance (and
   the infinite drift loop, kept in lockstep with it so they stay synced —
   the loop starts exactly when the element becomes visible, not partway
   through its cycle). It now defaults to 0: decorations begin fading in
   immediately alongside the background rather than waiting for it. Each
   element's own --fdelay stagger is scaled down (× 0.5) on top of that so
   the full spread of decorations finishes entering well inside the ~2–3s
   page-load budget while keeping the same relative order/organic feel. */

/* All three use the same longhand-property pattern as .wave above, for the
   same reason: var() inside an `animation` shorthand's duration/delay slot
   is unreliable in Safari. */

.floaty--peach {
  width: 24px;
  height: auto;
  animation-name: floaty-in, peach-drift;
  animation-duration: 600ms, var(--fdur, 11s);
  animation-timing-function: var(--ease-out), var(--ease-in-out);
  animation-delay: calc(var(--reveal-decor-delay, 0ms) + var(--fdelay, 0s) * 0.5), calc(var(--reveal-decor-delay, 0ms) + var(--fdelay, 0s) * 0.5);
  animation-iteration-count: 1, infinite;
  animation-fill-mode: both, none;
}

.floaty--leaf {
  width: 30px;
  height: auto;
  animation-name: floaty-in, leaf-drift;
  animation-duration: 600ms, var(--fdur, 9s);
  animation-timing-function: var(--ease-out), var(--ease-in-out);
  animation-delay: calc(var(--reveal-decor-delay, 0ms) + var(--fdelay, 0s) * 0.5), calc(var(--reveal-decor-delay, 0ms) + var(--fdelay, 0s) * 0.5);
  animation-iteration-count: 1, infinite;
  animation-fill-mode: both, none;
}

.floaty--sparkle {
  width: 16px;
  height: auto;
  transform-box: fill-box;
  transform-origin: 50% 50%;
  animation-name: floaty-in, star-pulse;
  animation-duration: 600ms, var(--fdur, 3.5s);
  animation-timing-function: var(--ease-out), var(--ease-in-out);
  animation-delay: calc(var(--reveal-decor-delay, 0ms) + var(--fdelay, 0s) * 0.5), calc(var(--reveal-decor-delay, 0ms) + var(--fdelay, 0s) * 0.5);
  animation-iteration-count: 1, infinite;
  animation-fill-mode: both, none;
}

@keyframes floaty-in { from { opacity: 0; } to { opacity: 0.9; } }

/* Peaches: drift is now a 4-stop loop instead of a single there-and-back
   tween (0/33/66/100), covers noticeably more ground (was up to ~7px, now
   up to ~16px), rotates further (was ~3–5deg, now ~6–9deg) and adds a
   gentle scale breathe — still "floating," just unmistakably in motion
   rather than barely perceptible. Durations dropped from ~19–26s to
   ~8–14s (set per instance via --fdur). */
@keyframes peach-drift {
  0% { transform: rotate(var(--base-r, 0deg)) translate(0, 0) scale(1); }
  33% { transform: rotate(calc(var(--base-r, 0deg) + var(--fr, 7deg))) translate(var(--fx, 12px), var(--fy, -10px)) scale(1.06); }
  66% { transform: rotate(calc(var(--base-r, 0deg) - var(--fr, 7deg) * 0.6)) translate(calc(var(--fx, 12px) * -0.7), calc(var(--fy, -10px) * -0.8)) scale(0.96); }
  100% { transform: rotate(var(--base-r, 0deg)) translate(0, 0) scale(1); }
}

/* Leaves: same 4-stop shape as the peaches, more distance and rotation
   (leaves were always meant to move a bit more than the peaches — that
   relative difference is preserved, just scaled up with everything else). */
@keyframes leaf-drift {
  0% { transform: rotate(var(--base-r, 0deg)) translate(0, 0) scale(1); }
  33% { transform: rotate(calc(var(--base-r, 0deg) + var(--fr, 10deg))) translate(var(--fx, 14px), var(--fy, -11px)) scale(1.07); }
  66% { transform: rotate(calc(var(--base-r, 0deg) - var(--fr, 10deg) * 0.6)) translate(calc(var(--fx, 14px) * -0.7), calc(var(--fy, -11px) * -0.8)) scale(0.95); }
  100% { transform: rotate(var(--base-r, 0deg)) translate(0, 0) scale(1); }
}

/* Stars: still "mostly stationary" (no positional drift), but the
   scale/opacity shimmer is now bigger and carries a slight non-uniform
   scaleX/scaleY (a gentle squash-and-stretch) as its version of "organic
   distortion" — the star is the one SVG-shape decoration here, so unlike
   the raster peach/leaf images it can wobble its proportions slightly
   without touching the underlying path data at all. */
@keyframes star-pulse {
  0%, 100% { opacity: var(--s-lo, 0.5); transform: rotate(var(--base-r, 0deg)) scale(var(--s-sc-lo, 0.9), calc(var(--s-sc-lo, 0.9) * 1.06)); }
  50% { opacity: var(--s-hi, 0.8); transform: rotate(calc(var(--base-r, 0deg) + var(--fr, 0deg))) scale(var(--s-sc-hi, 1.05), calc(var(--s-sc-hi, 1.05) * 0.94)); }
}

/* ---------- header (peach mark + programmatic wordmark) ---------- */

/* Header, hero content and footer all start fading in together, almost
   immediately (--reveal-*-delay below share one small fallback so none of
   them stagger relative to each other) — not after the floating
   decorations, but gradually alongside them. --reveal-content-duration is
   deliberately longer than a typical UI fade so this group is still
   visibly settling in while the decorations finish their own (faster,
   staggered) entrance, landing just after them rather than long before or
   long after — see the floaty rules above for their timing. */
.brand-header {
  position: relative;
  z-index: 1;
  width: 100%;
  background: var(--peach-200);
  border-bottom: 1px solid var(--border-peach);
  opacity: 0;
  animation-name: header-in;
  animation-duration: var(--reveal-content-duration, 1500ms);
  animation-timing-function: var(--ease-out);
  animation-delay: var(--reveal-header-delay, 100ms);
  animation-fill-mode: both;
}

/* --brand-mark-scale is the single source of truth for the logo's size —
   the peach icon, "little peaches" wordmark and "Early Learning Academy"
   tagline all derive their size from this one clamp() (each at its own
   fixed ratio to it) instead of each running its own independent
   clamp(). That's what makes them scale together as one logo rather than
   three responsive elements that happen to sit near each other: they can
   only ever grow or shrink in lockstep, because there's only one value
   driving all three. */
.brand-header__inner {
  --brand-mark-scale: clamp(28px, 4vw, 40px);
  max-width: var(--container-lg);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-7) var(--gutter-page) var(--space-6);
  text-align: center;
}

.brand-header__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
}

.brand-header__icon {
  height: var(--brand-mark-scale);
  width: auto;
  display: block;
}

.brand-header__title {
  font: var(--type-display);
  font-size: var(--brand-mark-scale);
  color: var(--text-heading);
  line-height: 1;
}

.brand-header__tagline {
  /* 0.25 reproduces the size the tagline already rendered at on desktop
     (10px at the 40px reference scale) — now it actually scales with the
     mark instead of being stuck there at every viewport. Split into
     longhand font-* properties rather than the `font` shorthand so the
     calc() reads clearly and stays consistent with this file's existing
     shorthand-avoidance pattern elsewhere. */
  font-weight: var(--weight-semibold);
  font-size: calc(var(--brand-mark-scale) * 0.25);
  line-height: 1.2;
  font-family: var(--font-sans);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--text-accent);
  white-space: nowrap;
  text-align: center;
  transform: translateX(18px);
}

@keyframes header-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

/* ---------- hero ---------- */

/* The hero is a grid with the centered content in its own cell and four
   decoration zones (top/bottom/left/right) as separate sibling cells —
   not an overlay positioned by guesswork on top of the content. Because
   each zone is a distinct grid area with its own box, a decoration placed
   inside one structurally cannot reach into the content cell; there's no
   coordinate that could accidentally drift into the protected area. Below
   1100px width (or 700px height) there isn't reliable room for side rails
   or top/bottom bands at all, so the grid collapses to the original
   single-column flex layout and every decoration zone is hidden — see the
   media query near the bottom of this file. */
.hero {
  position: relative;
  z-index: 1;
  flex: 1;
  display: grid;
  grid-template-columns: 1fr minmax(0, 760px) 1fr;
  grid-template-rows: minmax(64px, 1fr) auto minmax(64px, 1fr);
  grid-template-areas:
    "top    top     top"
    "left   content right"
    "bottom bottom  bottom";
  column-gap: var(--space-6);
  row-gap: var(--space-3);
  align-items: center;
  justify-items: center;
  width: 100%;
  padding: 0 var(--gutter-page);
  box-sizing: border-box;
}

.hero__content {
  grid-area: content;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  text-align: center;
  min-width: 0;
}

/* Each zone is its own positioning context (position:relative), so every
   .floaty inside it is placed with top/left percentages of that small
   zone's own box — never of the page — which is what makes "structurally
   can't overlap the content" true rather than aspirational. */
.hero__decor {
  position: relative;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.hero__decor--top { grid-area: top; }
.hero__decor--bottom { grid-area: bottom; }
.hero__decor--left { grid-area: left; }
.hero__decor--right { grid-area: right; }

.hero__title {
  margin: 0;
  max-width: 760px;
  font: var(--type-display);
  font-size: clamp(32px, 5.4vw, 54px);
  color: var(--text-heading);
  text-wrap: pretty;
  opacity: 0;
  animation-name: hero-rise;
  animation-duration: var(--reveal-content-duration, 1500ms);
  animation-timing-function: var(--ease-out);
  animation-delay: var(--reveal-title-delay, 100ms);
  animation-fill-mode: both;
}

.hero__facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-4) var(--space-7);
  max-width: 1000px;
  opacity: 0;
  animation-name: hero-rise;
  animation-duration: var(--reveal-content-duration, 1500ms);
  animation-timing-function: var(--ease-out);
  animation-delay: var(--reveal-facts-delay, 100ms);
  animation-fill-mode: both;
}

.hero__fact {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  white-space: nowrap;
  font: var(--type-body-sm);
  font-size: clamp(12px, 1.4vw, 14px);
  color: var(--text-body);
}

.hero__fact-bullet {
  width: 14px;
  height: auto;
  display: block;
  flex: 0 0 auto;
}

/* The CTA's entrance uses its own keyframes (cta-rise) rather than the
   shared hero-rise, because its transform also has to carry the hover/
   active scale (via --cta-scale) once the entrance finishes. A CSS
   animation with fill-mode:both keeps controlling `transform` forever
   after it completes — that's what made the old hover scale silently
   stop working, since a plain `.cta-button:hover { transform: scale(...) }`
   can't out-compete an animation still holding the property. Routing the
   scale through the same var() the entrance keyframe already reads sidesteps
   that: the keyframe's held end value re-evaluates live as --cta-scale
   changes on hover/active, so there's only ever one thing driving
   `transform` on this element, not two fighting over it. */
.hero__cta {
  opacity: 0;
  --cta-scale: 1;

  animation-name: cta-rise;
  animation-duration: var(--reveal-content-duration, 1500ms);
  animation-timing-function: var(--ease-out);
  animation-delay: var(--reveal-cta-delay, 100ms);
  animation-fill-mode: both;
}

@keyframes hero-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
@keyframes cta-rise {
  from { opacity: 0; transform: translateY(6px) scale(var(--cta-scale, 1)); }
  to   { opacity: 1; transform: translateY(0) scale(var(--cta-scale, 1)); }
}

/* CTA styled to match the design system's Button (variant="primary" size="lg"),
   built as a real anchor since it navigates to an external URL. */
.cta-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 17px 34px;
  border-radius: var(--radius-pill);
  background: var(--brand-primary);
  color: var(--text-on-peach);
  font: var(--type-button);
  font-size: var(--text-md);
  text-decoration: none;
  border: 1px solid var(--brand-primary);
  box-shadow: var(--shadow-sm);

  /* Design system's shared hover/press transition token — already covers
     background/border-color/color/box-shadow plus transform at
     --duration-fast with --ease-out, which is exactly what the hover and
     active scale below need. */
  transition: var(--transition-control);

  transform: scale(var(--cta-scale, 1));
}

.cta-button:hover {
  background: var(--brand-primary-hover);
  border-color: var(--brand-primary-hover);
  color: var(--text-heading);
  --cta-scale: 1.04;
}

.cta-button:active {
  background: var(--brand-primary-press);
  --cta-scale: 0.98;
}
.cta-button:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ---------- footer ---------- */

.site-footer {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  background: var(--surface-green);
  color: var(--text-on-green);
  padding: var(--space-5) var(--gutter-page);
  text-align: center;
  font: var(--type-body-sm);
  letter-spacing: var(--tracking-wide);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  opacity: 0;
  animation-name: hero-rise;
  animation-duration: var(--reveal-content-duration, 1500ms);
  animation-timing-function: var(--ease-out);
  animation-delay: var(--reveal-footer-delay, 100ms);
  animation-fill-mode: both;
}

.site-footer__links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-7);
  flex-wrap: nowrap;
}

.site-footer__link {
  color: var(--cream-50);
  text-decoration: none;
  transition: var(--transition-control);
}

.site-footer__link:hover,
.site-footer__link:focus-visible {
  color: var(--peach-300);
}

.site-footer__link:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-green);
  border-radius: var(--radius-xs);
}

.site-footer__divider {
  opacity: 0.5;
}

.site-footer__credit {
  margin-top: var(--space-3);
  font-size: 9px;
  line-height: 1.2;
  letter-spacing: 0.04em;
  color: var(--cream-50);
  text-align: center;
  opacity: 0.65;
}

/* ---------- reduced motion: stop everything, including the ambient loops ----------
   Every page load replays the entrance in full (no "already seen this
   session" shortcut) — the only thing that ever shows the settled state
   immediately is a genuine prefers-reduced-motion preference. */

@media (prefers-reduced-motion: reduce) {
  .backdrop *,
  .hero__decor *,
  .brand-header,
  .hero__title,
  .hero__facts,
  .hero__cta,
  .site-footer {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    stroke-dashoffset: 0 !important;
  }
  .wave { opacity: var(--wave-opacity, 0.16) !important; }
}

/* ---------- responsive ---------- */

/* Root cause of the previous bug: below the width/height thresholds, .hero
   dropped out of grid entirely (display:flex) and every decoration zone
   was display:none — an all-or-nothing cutoff. Worse, the *height* half of
   that query (`max-height: 699px`) fired on ANY short window regardless of
   width, so a wide, ordinarily "large" desktop window that just happened
   to be short would lose every decoration too — which is almost certainly
   what read as "disappearing at larger sizes."
   The fix keeps .hero as `display: grid` at every viewport size — never
   falling back to flex — because it's the grid's *row* separation
   (top / content / bottom), not the column count, that makes overlap
   structurally impossible: each row has a `minmax(64px, 1fr)` floor that
   never goes to zero, so it doesn't need a height media query as a safety
   net at all. Only the *column* count changes with width: below 1100px
   there's no longer reliable room for left/right side rails, so those two
   zones hide and the grid collapses to a single column — top/content/
   bottom stay separate grid rows regardless. Within the remaining top and
   bottom bands, only the *count* of decorations is reduced at narrower
   widths (via :nth-child, purely so a ~375px-wide band doesn't look
   crowded) — never their visibility as a whole, and never by removing the
   grid structure that keeps them clear of the content. */
@media (max-width: 1099px) {
  .hero {
    grid-template-columns: 1fr;
    grid-template-areas: "top" "content" "bottom";
  }
  .hero__decor--left,
  .hero__decor--right {
    display: none;
  }
}

/* Below 1100px, every remaining tier (tablet down through the smallest
   phone) keeps one of each decoration type per band — peach + leaf + star,
   6 total — never fewer. A stricter mobile-only cull used to drop this to
   4 (a peach + a leaf per band, no star); that's what let the visible
   count fall below the 6-minimum on narrow screens, so that extra cull is
   gone rather than patched. The three survivors in each band (the first
   three in DOM order) are positioned near the left edge, center, and right
   edge of the band respectively — see their left% values in index.html —
   so the side rails' left/right presence carries over into the collapsed
   single-column layout instead of the remaining decorations bunching
   toward one side. Narrower widths only scale them down a little; their
   left/right spread stays intact all the way to the smallest phone. */
@media (max-width: 1099px) {
  .hero__decor--top .floaty:nth-child(n+4),
  .hero__decor--bottom .floaty:nth-child(n+4) {
    display: none;
  }
}

@media (max-width: 639px) {
  .hero__decor .floaty--peach { width: 19px; }
  .hero__decor .floaty--leaf { width: 24px; }
  .hero__decor .floaty--sparkle { width: 13px; }
}

@media (max-width: 760px) {
  .backdrop__waves { width: 68vw; opacity: 0.9; }
  .backdrop__waves--left { width: 58vw; }
  .backdrop__waves--top { height: 20vh; }
  .brand-header__inner { padding: var(--space-6) var(--space-4) var(--space-5); }
  .hero__content { gap: var(--space-4); }
  .hero__facts { gap: var(--space-3) var(--space-5); }
  .site-footer { gap: var(--space-4); font-size: var(--text-xs); }
}

@media (max-width: 420px) {
  .hero__fact { white-space: normal; }
}
