/* ============================================================
   Jr Jams — landing page
   Design tokens mirror the app's DesignTokens.swift exactly.
   ============================================================ */

/* ---------- Fonts (self-hosted) ---------- */
@font-face {
  font-family: 'DynaPuff';
  src: url('Fonts/DynaPuff/DynaPuff-VariableFont_wdth,wght.ttf') format('truetype-variations');
  font-weight: 400 700;
  font-stretch: 75% 100%;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  color-scheme: light; /* the cream theme is the brand — always */

  --cream:  #FDFAD5;
  --yellow: #FADA09;
  --green:  #048745;
  --pink:   #FB939B;
  --blue:   #099CDE;
  --ink:    #262626;
  --np-bg:  #040504;

  --on-pink:   #4D1A26;
  --on-yellow: #332600;
  --on-green:  #FFFFFF;
  --on-blue:   #FFFFFF;

  --text-1: #1A1A1A;
  --text-2: #4D4D4D;

  --font-display: 'DynaPuff', ui-rounded, 'SF Pro Rounded', system-ui, 'Segoe UI', sans-serif;
  --font-body: ui-rounded, 'SF Pro Rounded', 'Nunito', system-ui, 'Segoe UI', sans-serif;

  --fs-display: clamp(2.125rem, 1.45rem + 2.6vw, 2.75rem);   /* 34 → 44 */
  --fs-headline: clamp(1.25rem, 1.12rem + .6vw, 1.5rem);     /* 20 → 24 */
  --fs-body: 1.0625rem;                                       /* 17 */
  --fs-small: .9375rem;                                       /* 15 */
  --fs-caption: .875rem;                                      /* 14 */

  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px;

  --radius-tile: clamp(24px, 2.4vw, 32px);

  --shadow-sm: 0 2px 4px rgba(0,0,0,.08);
  --shadow-md: 0 4px 8px rgba(0,0,0,.10);
  --shadow-lg: 0 8px 16px rgba(0,0,0,.12);

  --gap: clamp(12px, 1.6vw, 20px);
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: #B2DAE3;   /* flat light-blue sky (CSS clouds drift on top, see body::after) */
  color: var(--text-1);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Idle: keep the footer tight. Only while a song plays does `.playing`
     reserve room so the floating playbar never covers the footer. */
  padding-bottom: 40px;
}
body.playing { padding-bottom: 280px; }

/* Clouds photo disabled while we trial the CSS clouds on desktop too (see
   body::after). Restore this rule (and remove the body::after base rule) to
   go back to the photo backdrop. */
body::before { display: none; }

/* CSS clouds — a horizontally-tiled, drifting band, inset from the top/bottom
   of the viewport so they never touch the edges. Desktop scale here; the
   mobile @media block overrides with a smaller tile. */
body::after {
  content: "";
  position: fixed;
  left: 0; right: 0;
  top: 13%; bottom: 24%;
  z-index: -1;
  pointer-events: none;
  background-repeat: repeat-x;
  background-size: 900px 100%;
  background-position: 0 0;
  background-image:
    /* cloud A — upper */
    radial-gradient(160px 100px at 180px 24%, rgba(255,255,255,.96), rgba(255,255,255,0) 72%),
    radial-gradient(120px 80px at 100px 30%, rgba(255,255,255,.92), rgba(255,255,255,0) 72%),
    radial-gradient(132px 86px at 290px 30%, rgba(255,255,255,.92), rgba(255,255,255,0) 72%),
    /* cloud B — lower */
    radial-gradient(180px 110px at 610px 62%, rgba(255,255,255,.94), rgba(255,255,255,0) 72%),
    radial-gradient(124px 80px at 525px 66%, rgba(255,255,255,.9),  rgba(255,255,255,0) 72%),
    radial-gradient(136px 88px at 700px 66%, rgba(255,255,255,.9),  rgba(255,255,255,0) 72%);
  animation: cloud-drift-lg 80s linear infinite;
}
@keyframes cloud-drift-lg {
  from { background-position: 0 0; }
  to   { background-position: -900px 0; }   /* one full tile → seamless wrap */
}

img, svg, video { max-width: 100%; }

h1, h2, h3 { font-family: var(--font-display); font-weight: 600; line-height: 1.15; margin: 0; }
p { margin: 0; }
figure { margin: 0; }

a { color: inherit; }

button {
  font: inherit;
  color: inherit;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
}

:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--cream), 0 0 0 6px var(--ink) !important;
}

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

.skip-link {
  position: fixed;
  top: -100px;            /* off-screen until focused (top offset avoids iOS fixed+transform quirks) */
  left: 12px;
  z-index: 200;
  background: var(--ink);
  color: #fff;
  font-family: var(--font-display);
  font-size: var(--fs-small);
  padding: 12px 20px;
  border-radius: 999px;
  text-decoration: none;
  transition: top .2s ease-out;
}
.skip-link:focus { top: 12px; }

/* ---------- Grain overlay (whole page) ---------- */
.grain {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  opacity: .06;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 240px 240px;
}

/* ---------- Flower motif (brand mark, reused via <use href="#jr-flower">) ---------- */
/* The sprite lives in the DOM but takes no space. */
.flower-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
/* Base instance: petals inherit `color` (currentColor); size is set per context. */
.flower { display: inline-block; line-height: 0; }

/* ---------- Bento grid ---------- */
.bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--gap);
  /* ~95vw wide, kept centered; capped so tiles don't balloon on ultrawide. */
  max-width: min(95vw, 1600px);
  margin-inline: auto;
  padding: clamp(16px, 3vw, 40px) clamp(16px, 4vw, 48px) 0;
}

.span-2 { grid-column: span 2; }
.span-3 { grid-column: span 3; }
.span-4 { grid-column: span 4; }
.span-6 { grid-column: span 6; }

/* Grid items default to min-width:auto (their content's minimum), which on very
   narrow screens can force a column wider than its 1fr track and blow the whole
   grid past the container (lost right margin). Let tiles shrink to their track. */
.bento > .tile { min-width: 0; }

/* ---------- Tiles ---------- */
.tile {
  position: relative;
  border-radius: var(--radius-tile);
  background: #fff;
  box-shadow: var(--shadow-sm), var(--shadow-md);
  padding: clamp(20px, 2.6vw, 32px);
  transition: transform .25s ease-out, box-shadow .25s ease-out;
}

/* ---------- Scroll reveal: bento cards rise + fade into view ----------
   Gated on .has-js (set before paint) so no-JS users always see content.
   Driven by a transition (not a keyframe animation) so that a hover which
   interrupts the reveal redirects smoothly from the current position instead
   of snapping to the hover transform when the animation ends. The slow reveal
   duration only applies until JS adds .done; after that .tile's own .25s
   transition governs hover/press. */
.has-js .bento > .tile:not(.in) { opacity: 0; transform: translateY(28px); }
.has-js .bento > .tile:not(.done) {
  transition: opacity .62s cubic-bezier(.22, .61, .36, 1),
              transform .62s cubic-bezier(.22, .61, .36, 1);
  transition-delay: var(--reveal-delay, 0ms);
}

/* soft radial-gradient ring, like the app's tile borders */
.tile::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: radial-gradient(130% 130% at 0% 0%,
      rgba(255,255,255,.5) 0%,
      rgba(255,255,255,.12) 50%,
      rgba(0,0,0,.08) 100%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
          mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

/* subtle top sheen + bottom shade, like SongTile.swift */
.sheen::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(180deg,
      rgba(255,255,255,.16) 0%, rgba(255,255,255,0) 30%,
      rgba(0,0,0,0) 70%, rgba(0,0,0,.04) 100%);
  pointer-events: none;
}

.tile.media { padding: 0; overflow: hidden; }

/* ---------- Hero ---------- */
.tile-hero {
  background: var(--cream);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--sp-4);
  padding-block: clamp(24px, 3.4vw, 44px);
}

/* Hero split: the app-icon mark tile beside the tall pink-video tile.
   Both share one grid row, so grid stretch makes the video match the
   hero's height (the "double height" tile) with no fixed number. */
.hero-main  { grid-column: span 4; }
.hero-video { grid-column: span 2; }

.tile-hero .hero-icon {
  width: clamp(128px, 15vw, 208px);
  height: auto;
  margin-bottom: var(--sp-1);
  cursor: pointer;   /* tap it for a burst of flowers */
  transition: transform .12s ease-out;
  /* one-time wiggle a beat after the page-load reveal settles, to draw the eye.
     Uses the `rotate` property so it composes with the hover/press `transform`. */
  animation: icon-wiggle .85s ease-in-out 1.4s 1;
}
/* hover grows a touch; press pushes in (active wins over hover) */
.tile-hero .hero-icon:hover { transform: scale(1.04); }
.tile-hero .hero-icon:active { transform: scale(.92); }
@keyframes icon-wiggle {
  0%, 100% { rotate: 0deg; }
  12% { rotate: -8deg; }
  28% { rotate:  6deg; }
  44% { rotate: -5deg; }
  60% { rotate:  3deg; }
  76% { rotate: -1.5deg; }
}

/* Flower burst: a physics layer behind the hero content. Content sits above
   it (z-index 1); flowers fall and bounce within the tile (overflow hidden). */
.tile-hero { overflow: hidden; }
.tile-hero > :not(.hero-burst) { position: relative; z-index: 1; }
.hero-burst {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.burst-flower { position: absolute; top: 0; left: 0; will-change: transform; }
.burst-flower .flower { display: block; width: 100%; height: 100%; }
@media (prefers-reduced-motion: reduce) { .hero-burst { display: none; } }

/* Video fills the tall tile; absolute so the video's own size never
   forces the tile height (the row height comes from the hero beside it).
   object-fit: cover keeps the aspect ratio with no skew; the centred
   phone stays in frame while only the pink carpet is cropped. */
.tile-video.hero-video {
  aspect-ratio: auto;
  min-height: 340px;
}
.tile-video.hero-video video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.tagline {
  font-family: var(--font-display);
  font-size: var(--fs-display);
  font-weight: 600;
  line-height: 1.1;
  color: var(--ink);
  max-width: 14ch;
}

.hero-sub {
  color: var(--text-2);
  font-size: var(--fs-body);
  line-height: 1.35;
  max-width: 30ch;   /* narrow column: wraps into a tidy block on desktop + mobile */
}

.hero-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
}
.hero-cta .caption { color: var(--text-2); font-size: var(--fs-caption); }

/* Apple badge — never restyle the art itself; effects live on the wrapper. */
.badge-link {
  display: inline-block;
  border-radius: 13px;
  line-height: 0;
  transition: transform .15s ease-out, box-shadow .15s ease-out;
}
.badge-link img { height: 54px; width: auto; display: block; }
.badge-link:hover { transform: scale(1.04); box-shadow: var(--shadow-md); }
.badge-link:active { transform: scale(.94); }

/* ---------- Tilt mark (the hero app icon "wiggles") ---------- */
.tilt-target {
  flex: none;
  border-radius: 22.5%;
  box-shadow: var(--shadow-md), var(--shadow-lg);
  will-change: transform;
  transition: transform .5s ease-out;
}
.tilt-permission {
  font-family: var(--font-display);
  font-size: var(--fs-caption);
  background: var(--ink);
  color: #fff;
  padding: 8px 16px;
  border-radius: 999px;
}
.tilt-permission:active { transform: scale(.94); }

/* ---------- Stat tiles ---------- */
.tile-stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-1);
  min-height: 150px;
}
.stat-number {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(3rem, 2.2rem + 3.4vw, 4.75rem);
  line-height: 1;
}
.stat-label {
  font-size: var(--fs-body);
  line-height: 1.3;
  max-width: 22ch;
}
.stat-number.stat-word {
  font-size: clamp(2rem, 1.5rem + 2.2vw, 3.1rem);
  line-height: 1.05;
}

.tile.c-yellow { background: var(--yellow); color: var(--on-yellow); }
.tile.c-green  { background: var(--green);  color: var(--on-green); }
.tile.c-blue   { background: var(--blue);   color: var(--on-blue); }
.tile.c-pink   { background: var(--pink);   color: var(--on-pink); }
.tile.c-ink    { background: var(--ink);    color: #fff; }

/* ---------- Video tiles ---------- */
.tile-video video,
.tile-video img.poster-still {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.tile-video { aspect-ratio: 16 / 9; }
.tile-video.portraitish { aspect-ratio: auto; min-height: 100%; }

.vid-toggle {
  position: absolute;
  right: var(--sp-4);
  bottom: var(--sp-4);
  width: 48px; height: 48px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(4,5,4,.62);
  color: #fff;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: transform .12s ease-out;
  z-index: 2;
}
.vid-toggle:active { transform: scale(.9); }
.vid-toggle svg { width: 20px; height: 20px; }

/* ---------- Section intro tile ---------- */
.tile-listen {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-3);
  background: #fff;
}
.tile-listen h2 { font-size: var(--fs-display); color: var(--ink); }
.tile-listen p { color: var(--text-2); line-height: 1.35; max-width: 26ch; }

/* animated equalizer doodle */
.eq {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 34px;
  margin-bottom: var(--sp-2);
}
.eq span {
  width: 9px;
  border-radius: 999px;
  animation: eq-bounce 1s ease-in-out infinite;
}
.eq span:nth-child(1) { background: var(--blue);   height: 55%; animation-delay: 0s;   }
.eq span:nth-child(2) { background: var(--green);  height: 90%; animation-delay: .18s; }
.eq span:nth-child(3) { background: var(--yellow); height: 65%; animation-delay: .36s; }
.eq span:nth-child(4) { background: var(--pink);   height: 80%; animation-delay: .54s; }
@keyframes eq-bounce {
  0%, 100% { transform: scaleY(.55); }
  50%      { transform: scaleY(1); }
}
.eq span { transform-origin: bottom; }

/* ---------- Song tiles ---------- */
.song-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  text-align: center;
  aspect-ratio: 4 / 5;
  gap: clamp(24px, 3.5vw, 44px);
  padding: clamp(34px, 5vw, 64px) clamp(14px, 2vw, 24px) clamp(14px, 1.8vw, 20px);
  -webkit-tap-highlight-color: transparent;
}
/* playful tilt on hover, varying direction per tile; eases back on hover-off
   via .tile's own .25s transform transition */
.song-tile:nth-of-type(1) { --tilt: -1.2deg; }
.song-tile:nth-of-type(2) { --tilt:  1deg;   }
.song-tile:nth-of-type(3) { --tilt: -0.8deg; }
.song-tile:nth-of-type(4) { --tilt:  1.2deg; }
.song-tile:nth-of-type(5) { --tilt: -1deg;   }
.song-tile:hover { transform: translateY(-4px) scale(1.04) rotate(var(--tilt, 0deg)); box-shadow: var(--shadow-md), var(--shadow-lg); }
.song-tile:active { transform: scale(.94); transition-duration: .12s; }
/* JS adds .tapped on tap (mobile) for a squish-and-bounce, so a quick tap has
   visible feedback even though :active only lasts while the finger is down */
.song-tile.tapped { animation: tile-tap .3s ease; }
@keyframes tile-tap {
  0%   { transform: scale(1); }
  35%  { transform: scale(.92); }
  70%  { transform: scale(1.03); }
  100% { transform: scale(1); }
}

.art-wrap {
  position: relative;
  display: block;
  flex: none;
  width: min(82%, 288px);
  aspect-ratio: 1;
  margin-top: var(--sp-1);
}
/* white radial glow behind the disc, like the app */
.art-wrap::before {
  content: "";
  position: absolute;
  inset: -9%;
  border-radius: 50%;
  background: radial-gradient(circle,
      rgba(255,255,255,.6) 0%,
      rgba(255,255,255,.2) 55%,
      rgba(255,255,255,0) 75%);
  filter: blur(4px);
}
.art-disc {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  /* static gradient ring that does NOT rotate with the art */
  box-shadow: inset 1.5px 1.5px 1px rgba(0,0,0,.10),
              inset -1px -1px 1px rgba(255,255,255,.16);
}
.art-disc::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid rgba(0,0,0,.08);
  pointer-events: none;
}
.art {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 50%;
  will-change: transform;
}

.song-title {
  font-family: var(--font-display);
  font-weight: 650;
  /* fluid: scales with viewport width, ~16px → ~32px on large desktop */
  font-size: clamp(1rem, 0.6rem + 1.6vw, 2rem);
  line-height: 1.15;
  display: block;
}
.song-genre {
  display: block;
  /* fluid: ~12.8px → ~21px on large desktop */
  font-size: clamp(0.8rem, 0.6rem + 0.8vw, 1.3rem);
  margin-top: 3px;
  opacity: .95;
}


/* ---------- Story ---------- */
.tile-story {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(24px, 4vw, 64px);
  background: var(--cream);
}
.story-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-4);
}
.tile-story h2 { font-size: var(--fs-display); color: var(--ink); }
.tile-story p { color: var(--text-2); max-width: 58ch; }
.story-sign {
  font-family: var(--font-display);
  color: var(--ink);
  font-size: var(--fs-headline);
}
.story-photo {
  margin: 0;
  flex: none;
  width: clamp(200px, 22vw, 320px);
  /* white frame with an even border on all four sides */
  background: #fff;
  padding: clamp(10px, 0.9vw, 14px);
  border-radius: clamp(16px, 1.8vw, 24px);
  box-shadow: 0 14px 28px rgba(0,0,0,.18), 0 4px 10px rgba(0,0,0,.10);
  --base-t: rotate(-3.5deg);
  --tilt: 0deg;   /* hovering the card adds a slight decorative tilt */
  --scale: 1;     /* the image's own hover grows / press shrinks */
  transform: var(--base-t) rotate(var(--tilt)) scale(var(--scale));
  cursor: pointer;
  transition: transform .18s ease-out;
}
/* story content sits above the flower-burst layer */
.tile-story > :not(.hero-burst) { position: relative; z-index: 1; }
/* Hovering anywhere on the About card gives the photo a slight decorative
   tilt. The image's own hover still grows it and press still pushes in — all
   three compose via the --tilt / --scale variables above. */
.tile-story:hover .story-photo { --tilt: 2.5deg; }
.story-photo:hover  { --scale: 1.04; }
.story-photo:active { --scale: .92; }
/* Large desktop only: enlarge, shift left, and run off the bottom (clipped) */
@media (min-width: 1200px) {
  .tile-story { overflow: hidden; }
  .story-photo {
    align-self: end;
    width: clamp(300px, 26vw, 400px);
    margin-bottom: calc(-1 * clamp(40px, 6vw, 90px));
    --base-t: translateX(clamp(-64px, -3.5vw, -20px)) rotate(-3.5deg);
  }
}
.story-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: center 42%;
  border-radius: clamp(8px, 1vw, 12px);
}
@media (max-width: 760px) {
  .tile-story {
    grid-template-columns: 1fr;
    padding-bottom: 0;          /* photo runs to the bottom edge */
    overflow: hidden;           /* clip the overflow to the card's rounded box */
  }
  .story-photo {
    width: min(280px, 74%);
    justify-self: center;
    margin-top: var(--sp-4);
    margin-bottom: calc(-1 * clamp(32px, 9vw, 60px)); /* overflows, then gets clipped by the card */
    --base-t: rotate(-4deg);
  }
}

/* ---------- Feature tiles ---------- */
.tile-feature {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--sp-1);
  min-height: 170px;
}
.tile-feature h2 { font-size: var(--fs-headline); }
.tile-feature p { font-size: var(--fs-small); line-height: 1.35; opacity: .96; max-width: 28ch; }
.feature-doodle {
  position: absolute;
  top: clamp(14px, 2vw, 22px);
  right: clamp(14px, 2vw, 22px);
  width: clamp(34px, 3.6vw, 46px);
  height: auto;
  pointer-events: none;
}
/* gentle bob, same as the CTA flowers. The `transform` property is kept free
   for the JS-driven 360 spin (hover/tap), which composes with the float's
   translate/rotate. */
.feature-doodle.flower {
  animation: flower-float 5s ease-in-out infinite;
  transition: transform .7s cubic-bezier(.2, .6, .2, 1);
}

/* ---------- Closing CTA ---------- */
.tile-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--sp-4);
  padding-block: clamp(40px, 6vw, 72px);
}
.tile-cta h2 {
  font-size: clamp(2.4rem, 1.8rem + 3vw, 3.4rem);
  color: var(--cream);
}
.tile-cta p { color: rgba(255,255,255,.85); line-height: 1.35; max-width: 40ch; }
.tile-cta .badge-link { margin-top: var(--sp-2); }   /* match the hero's text-to-button gap */
.cta-stars {
  position: absolute;
  inset: 0;
  z-index: 0;               /* behind the CTA text */
  pointer-events: none;
  overflow: hidden;
  border-radius: inherit;
}
/* CTA text/button sit above the flowers so nothing overlaps them */
.tile-cta > :not(.cta-stars) { position: relative; z-index: 1; }
/* Scattered flowers that bob gently. Positions kept; size + base rotation
   (--rot) vary per flower for a hand-scattered look. */
.cta-stars svg {
  position: absolute;
  height: auto;
  animation: flower-float 5s ease-in-out infinite;
}
.cta-stars svg:nth-child(1) { left: 7%;  top: 18%;    width: 44px; animation-delay: 0s; }
.cta-stars svg:nth-child(2) { left: 14%; bottom: 16%; width: 30px; animation-delay: 1.2s; }
.cta-stars svg:nth-child(3) { right: 8%; top: 22%;    width: 34px; animation-delay: .6s; }
.cta-stars svg:nth-child(4) { right: 15%; bottom: 20%; width: 52px; animation-delay: 1.8s; }
/* float via the individual translate/rotate properties so the `transform`
   property stays free for the JS cursor-swarm on the CTA flowers (they compose) */
@keyframes flower-float {
  0%, 100% { translate: 0 0;     rotate: var(--rot, -4deg); }
  50%      { translate: 0 -9px;  rotate: calc(var(--rot, -4deg) + 8deg); }
}

/* ---------- Footer ---------- */
.site-footer {
  max-width: min(95vw, 1600px);
  margin-inline: auto;
  padding: clamp(28px, 4vw, 48px) clamp(16px, 4vw, 48px) 8px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  color: var(--ink);
  font-size: var(--fs-small);
}
.footer-legal {
  font-family: var(--font-display);
  color: var(--ink);
  font-size: var(--fs-body);
}
.site-footer a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  border-radius: 6px;
}
.site-footer a:hover { text-decoration: none; }
.footer-copy { font-size: var(--fs-caption); }

/* ---------- Now-playing bar ---------- */
.playbar {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: 24px;
  z-index: 90;
  margin-inline: auto;
  width: min(560px, calc(100% - 32px));
  border-radius: 24px;
  background: var(--np-bg);
  color: #fff;
  overflow: hidden;
  box-shadow: 0 8px 16px rgba(0,0,0,.25), 0 2px 4px rgba(0,0,0,.1), 0 0 0 1.5px rgba(255,255,255,.12);
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .3s ease-out, transform .3s ease-out;
}
.playbar.show { opacity: 1; transform: translateY(0); }
.playbar.hiding { opacity: 0; transform: none; }
.playbar[hidden] { display: none; }

.playbar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5) var(--sp-3);
  background: var(--song-color, var(--yellow));
  color: var(--song-text, var(--on-yellow));
}
.np-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.np-label { font-size: var(--fs-caption); }
.np-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-headline);
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.np-lyrics {
  flex-shrink: 0;
  font-size: var(--fs-caption);
  font-weight: 500;
  padding: 10px 18px;
  border-radius: 999px;
  background: rgba(0,0,0,.14);
  color: inherit;
  box-shadow: inset .5px .5px 0 rgba(255,255,255,.25);
  transition: transform .12s ease-out;
}
.playbar-head.light-text .np-lyrics { background: rgba(255,255,255,.18); }
.np-lyrics:hover { transform: scale(1.05); }
.np-lyrics:active { transform: scale(.94); }

.playbar-body {
  position: relative;              /* positioning context for the flowers */
  overflow: hidden;                /* clip drifting flowers to the body */
  border-top: 1px solid rgba(255,255,255,.08);
  padding: var(--sp-4) var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

/* Flowers drift behind the controls while a song plays. */
.playbar-flowers {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.pf {
  position: absolute;
  top: var(--y, 20%);
  left: 100%;                      /* rest at the right edge so it appears as soon as it drifts in */
  width: var(--size, 26px);
  height: var(--size, 26px);
  opacity: 0;                      /* fade in only while a song is playing */
  transition: opacity .6s ease;
  /* positive, staggered delays so flowers enter from the right one at a time
     once the song starts (nothing pre-positioned mid-bar). */
  animation: pf-drift var(--drift, 34s) linear var(--delay, 0s) infinite;
  animation-play-state: paused;    /* only run while a song is playing */
}
.pf .flower {
  display: block;
  width: 100%;
  height: 100%;
  animation: pf-spin var(--spin, 20s) linear var(--delay, 0s) infinite;
  animation-play-state: paused;
}
/* playing: full opacity + drifting; pausing removes the class → flowers fade out */
.playbar.is-playing .pf { opacity: 1; }
.playbar.is-playing .pf,
.playbar.is-playing .pf .flower { animation-play-state: running; }
@keyframes pf-drift {
  from { left: 100%; }
  to   { left: -15%; }
}
@keyframes pf-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.playbar-controls {
  position: relative;              /* sit above the drifting flowers */
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-5);
}
.pb-btn {
  position: relative;
  width: 56px; height: 56px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: #141414;             /* opaque, so drifting flowers pass BEHIND, never through */
  transition: transform .12s ease-out, background .12s ease-out;
}
/* radial-gradient ring like PlaybarCircleButtonStyle */
.pb-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  padding: 1px;
  background: radial-gradient(130% 130% at 0% 0%,
      rgba(255,255,255,.22) 0%,
      rgba(255,255,255,.06) 40%,
      rgba(0,0,0,.35) 100%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
          mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}
.pb-btn:active { transform: scale(.92); background: #000; }
.pb-btn svg { width: 28px; height: 28px; }
.pb-btn.big { width: 72px; height: 72px; }
.pb-btn.big svg { width: 34px; height: 34px; }
.pb-repeat { color: var(--blue); }
.pb-play   { color: var(--green); }
.pb-stop   { color: var(--pink); }
.repeat-dot {
  position: absolute;
  bottom: 8px;
  left: 50%;
  translate: -50% 0;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--blue);
  opacity: 0;
  transition: opacity .15s ease-out;
}
.pb-repeat[aria-pressed="true"] .repeat-dot { opacity: 1; }

.playbar audio { display: none; }  /* headless: playback driven by the custom buttons */
.playbar :focus-visible {
  box-shadow: 0 0 0 3px var(--np-bg), 0 0 0 6px #fff !important;
}

/* ---------- Lyrics sheet ---------- */
.lyrics-sheet {
  border: 0;
  padding: 0;
  width: min(600px, calc(100vw - 24px));
  max-height: min(78dvh, 720px);
  border-radius: 32px;
  background: var(--song-color, var(--yellow));
  color: var(--song-text, var(--on-yellow));
  box-shadow: 0 24px 48px rgba(0,0,0,.35);
  overflow: hidden;
  display: none;
  flex-direction: column;
}
.lyrics-sheet[open] { display: flex; animation: sheet-in .3s ease-out; }
@keyframes sheet-in {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
.lyrics-sheet::backdrop { background: rgba(4,5,4,.5); }
.sheet-grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .05;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 240px 240px;
}
.sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
  flex-shrink: 0;
}
.sheet-title { font-size: var(--fs-headline); font-weight: 700; }
.sheet-close {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(0,0,0,.12);
  transition: transform .12s ease-out;
}
.lyrics-sheet.light-text .sheet-close { background: rgba(255,255,255,.16); }
.sheet-close:active { transform: scale(.92); }
.sheet-close svg { width: 16px; height: 16px; }
.sheet-body {
  overflow-y: auto;
  padding: 0 var(--sp-5) var(--sp-7);
  overscroll-behavior: contain;
}
.sheet-body p { white-space: pre-line; line-height: 1.7; }
.lyrics-sheet :focus-visible {
  box-shadow: 0 0 0 3px var(--song-color, var(--yellow)), 0 0 0 6px currentColor !important;
}

@media (max-width: 620px) {
  .lyrics-sheet {
    width: 100vw;
    max-width: 100vw;
    margin: auto 0 0;
    max-height: 82dvh;
    border-radius: 28px 28px 0 0;
  }
  /* bottom-sheet motion: slide up from the bottom on open, slide down out on
     close. The .closing class is added by JS so the close animation can play
     before the <dialog> actually closes. */
  .lyrics-sheet[open] { animation: sheet-up .34s cubic-bezier(.2, .8, .2, 1); }
  .lyrics-sheet.closing { animation: sheet-down .26s ease-in forwards; }
  @keyframes sheet-up   { from { transform: translateY(100%); } to { transform: none; } }
  @keyframes sheet-down { from { transform: none; } to { transform: translateY(100%); } }
  .sheet-head::before {
    content: "";
    position: absolute;
    top: 10px; left: 50%;
    translate: -50% 0;
    width: 42px; height: 5px;
    border-radius: 999px;
    background: currentColor;
    opacity: .35;
  }
}

/* ---------- Responsive grid ---------- */
@media (max-width: 980px) {
  .bento { grid-template-columns: repeat(4, 1fr); }
  .span-6, .span-4, .span-3 { grid-column: span 4; }
  .span-2 { grid-column: span 2; }
  /* when features drop from 3-up to 2-up, the orphaned third spans the row */
  .tile-feature.feature-full { grid-column: 1 / -1; }
  /* hero + tall video stack full-width instead of a 50/50 split */
  .hero-main, .hero-video { grid-column: span 4; }
  .tile-video.hero-video { min-height: 0; aspect-ratio: 3 / 2; }
  .tile-video { aspect-ratio: 3 / 2; }
}

@media (max-width: 620px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .span-6, .span-4, .span-3 { grid-column: span 2; }
  .span-2 { grid-column: span 2; }
  /* the CTA flowers crowd the text on a narrow screen; hide them on mobile */
  .cta-stars { display: none; }
  /* hero and video stack; the video gets its own aspect ratio now that
     there's no side tile to borrow height from */
  .hero-main, .hero-video { grid-column: span 2; }
  /* square on mobile so more of the (tall) phone shows */
  .tile-video.hero-video { min-height: 0; aspect-ratio: 1 / 1; }
  /* song tiles go 2-up, exactly like the app on iPhone */
  .song-tile.span-2 { grid-column: span 1; }
  /* 5 songs would leave Dinosaur Stories alone in the last 2-up row; hide it here */
  .song-tile[data-song="ancient-names"] { display: none; }
  .song-tile { gap: var(--sp-2); padding-top: clamp(20px, 2.6vw, 32px); }
  /* touch: hover can stick after a tap, so drop the tilt/scale on mobile and
     keep only the press. :active is redeclared after so it still wins on tap. */
  .song-tile:hover  { transform: none; box-shadow: var(--shadow-sm), var(--shadow-md); }
  .song-tile:active { transform: scale(.94); }
  .art-wrap { width: 82%; }
  .tile-video { aspect-ratio: 4 / 3; }
  .badge-link img { height: 48px; }
  .playbar-controls { gap: var(--sp-4); }
  body { padding-bottom: 48px; }
  body.playing { padding-bottom: 300px; }
  /* mobile: the fixed clouds image can't fill Safari's changing viewport, so
     drop it and use a soft sky gradient instead. It's the body background (not
     a fixed image), so it covers the whole scrollable page with no toolbar gap:
     sky-blue at the top of the page easing into a cool near-white below, which
     keeps the cream/white cards popping. */
  body {
    background: #B2DAE3;   /* single soft light blue sky (clouds drift on top) */
  }
  body::before { display: none; }
  /* soft CSS clouds floating in a FIXED band that's inset from the top and
     bottom of the viewport, so they never touch the screen edges. Sits over
     the sky gradient and behind the content (z-index:-1). Pure gradients, so
     no image and no Safari fill/gap problem. */
  body::after {
    content: "";
    position: fixed;
    left: 0; right: 0;
    top: 13%; bottom: 24%;
    z-index: -1;
    pointer-events: none;
    /* one 520px-wide tile holding two soft clouds, repeated horizontally so the
       sky is always populated. Drifts left by exactly one tile → seamless loop.
       Because it tiles, clouds are on screen at every position, so when the
       animation is frozen (reduced motion) they stay visible. */
    background-repeat: repeat-x;
    background-size: 520px 100%;
    background-position: 0 0;
    background-image:
      /* cloud A — upper */
      radial-gradient(72px 46px at 95px 22%,  rgba(255,255,255,.94), rgba(255,255,255,0) 72%),
      radial-gradient(54px 36px at 58px 26%,  rgba(255,255,255,.9),  rgba(255,255,255,0) 72%),
      radial-gradient(60px 40px at 150px 26%, rgba(255,255,255,.9),  rgba(255,255,255,0) 72%),
      /* cloud B — lower */
      radial-gradient(82px 50px at 340px 60%, rgba(255,255,255,.9),  rgba(255,255,255,0) 72%),
      radial-gradient(56px 38px at 298px 63%, rgba(255,255,255,.86), rgba(255,255,255,0) 72%),
      radial-gradient(62px 42px at 388px 63%, rgba(255,255,255,.86), rgba(255,255,255,0) 72%);
    animation: cloud-drift 50s linear infinite;
  }
  @keyframes cloud-drift {
    from { background-position: 0 0; }
    to   { background-position: -520px 0; }   /* one full tile → seamless wrap */
  }
  /* mobile: the playbar is ~343px vs ~560px on desktop, so the fixed-size
     flowers crowd together; scale them down to the same size-to-bar ratio
     so their spacing reads like the desktop version */
  .playbar-flowers .pf { transform: scale(.62); }

  /* mobile: tighten only the heading→body gap in the text cards — it read
     too loose next to the card padding. The negative margin pulls the body
     up toward its heading; the icon/signature/button spacing is untouched. */
  .tile-listen h2 + p { margin-top: -6px; }   /* 12 -> ~6 */
  .story-text  h2 + p { margin-top: -8px; }   /* 16 -> ~8 */
  .tile-cta    h2 + p { margin-top: -5px; }   /* 16 -> ~11 */
  .tagline + .hero-sub { margin-top: -5px; }  /* 16 -> ~11 */
}

/* ---------- Reduced motion: calm everything, keep it usable ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .song-tile:hover,
  .badge-link:hover,
  .np-lyrics:hover { transform: none; }
  .tilt-target { transition: none; }
  .eq span { animation: none; transform: none; }
  /* keep the CTA flowers static (hold their base rotation), no bobbing */
  .cta-stars svg,
  .feature-doodle.flower { animation: none; transform: rotate(var(--rot, 0deg)); }
  /* no drifting/rotating flowers in the player when motion is reduced */
  .playbar-flowers { display: none; }
  /* never hide bento cards behind the scroll-reveal when motion is reduced */
  .has-js .bento > .tile:not(.in) { opacity: 1; transform: none; }
  .has-js .bento > .tile:not(.done) { transition: none; }
}
