/* Home (index.html) only: the full-screen hero with its keyboard, tiles and cat, and the gifts
   band. Loaded after base.css, whose tokens it reads. */

/* ---- the hero: the whole first screen ------------------------------------
   One full-bleed waterfall: the app's own keyboard (keys.js + keyboard.css, not a picture of
   them) spans the bottom edge, tiles fall onto it, and the headline sits on the calm left side
   of the sky. The keyboard's range is chosen per width (hero.js) so the music always lands to
   the RIGHT of the words and to the LEFT of the cat. Its height is the hero's; the bar stays. */
.hero {
  --keys-h: clamp(96px, 17vh, 164px);
  position: relative; overflow: hidden;
  /* The first screen, floored for short laptops and capped for tall monitors, where a 2000px
     sky would stretch every tile to match. */
  min-height: clamp(600px, calc(100svh - var(--bar-h)), 1080px);
  display: grid; grid-template-rows: minmax(0, 1fr) var(--keys-h);
  background-color: var(--sky-mid);
  background-image:
    linear-gradient(90deg, var(--sky-grid) 0 1px, transparent 1px),
    radial-gradient(90% 65% at 66% 100%, var(--sky-glow), transparent 72%),
    linear-gradient(180deg, var(--sky-top) 0%, var(--sky-mid) 58%, var(--sky-bottom) 100%);
  background-size: calc(100% / var(--white-key-count, 43)) 100%, 100% 100%, 100% 100%;
}
.hero-sky { position: relative; min-height: 0; }
.hero-fall {
  position: absolute; inset: 0; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 28%);
          mask-image: linear-gradient(180deg, transparent 0, #000 28%);
}
.hero-sky::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg, var(--scrim) 0%, var(--scrim) 26%, transparent 54%);
}
.hero-copy {
  position: relative; z-index: 2; height: 100%;
  display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
  padding: 48px 0 64px;
}
.hero-copy > * { max-width: min(640px, 52vw); }
.hero h1, .hero h1 span { text-wrap: balance; }
.hero h1 { font-size: clamp(44px, 6.2vw, 92px); line-height: 1.04; font-weight: 600; letter-spacing: -.03em; margin: 18px 0 22px; }
.hero h1 span {
  display: block;
  background: linear-gradient(90deg, #ff4f9a, var(--pink-light) 55%, #ffb8d6);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.lede { font-size: clamp(16px, 1.35vw, 19px); color: var(--muted); max-width: 44ch; }
.cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }
.proof { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 28px 0 0; padding: 0; list-style: none;
         font-size: 13.5px; font-weight: 700; color: var(--dim); }
.proof li { display: flex; align-items: center; gap: 6px; }
.proof .paw-i { color: var(--pink); width: 12px; height: 12px; }

.hero-note {
  position: absolute; bottom: 0; border-radius: 7px;
  background: linear-gradient(180deg, oklch(from var(--channel) calc(l + (1 - l) * .62) calc(c * .55) h) 0, var(--channel) 26px);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.55), inset 0 -4px 5px -2px rgba(255,255,255,.5),
              0 0 12px -2px color-mix(in srgb, var(--channel) 62%, transparent),
              0 0 30px -6px color-mix(in srgb, var(--channel) 48%, transparent);
  will-change: transform;
}
.hero-note.black-col {
  background: linear-gradient(180deg, oklch(from var(--channel) calc(l * .86) c h) 0, oklch(from var(--channel) calc(l * .66) c h) 26px);
}
/* The keybed: a dark rail behind the keys, the piano's own key slip. */
.hero-keys-bed { position: relative; z-index: 3; padding-top: 7px; background: var(--keybed);
                 box-shadow: 0 -14px 34px -10px var(--shadow); }
.hero-keys { height: 100%; }
/* The paws a strike throws: cream, as in the app. */
.strike-paw { position: absolute; z-index: 4; width: 18px; height: 17px; bottom: calc(var(--keys-h) + 4px); pointer-events: none; fill: #fff2f8; }

/* ---- the cat -------------------------------------------------------------
   The one character on the page, sitting on the keyboard at the right-hand end. Everything it
   does is tied to the music or to you, never idle decoration: its head bobs on the beat, a paw
   taps when a note lands (left paw for channel 1, right for channel 2), its eyes shut happily
   while it plays and open to look at you at the end of every phrase, and they follow the
   pointer while you are near. Tap it: a boop, a meow, and the sound comes on. The rest of what
   it does — a wave, a spin, a nap… — is cat-moves.js, cued from hero() in hero.js. In 3D where
   WebGL allows (cat3d.js), drawn from this same SVG rig, which stays as the fallback.
   CSS owns the loops (tail, breath); hero.js owns everything that has to hit a beat. */
.cat-corner {
  position: absolute; z-index: 5; right: clamp(8px, 4vw, 64px); bottom: calc(var(--keys-h) - 6px);
  width: clamp(112px, 12vw, 176px);
}
.cat-say {
  position: absolute; right: 74%; bottom: 74%; z-index: 6; white-space: nowrap; pointer-events: none;
  padding: 8px 13px; border-radius: 16px 16px 4px 16px;
  background: var(--surface); color: var(--text); border: 1px solid var(--line);
  box-shadow: 0 10px 28px var(--shadow);
  font-size: 14px; font-weight: 800;
  opacity: 0; transform: translateY(6px) scale(.7); transform-origin: 100% 100%;
  transition: opacity 160ms ease, transform 260ms cubic-bezier(.3,1.5,.5,1);
}
.cat-say[data-show] { opacity: 1; transform: none; }
.sound-pill {
  position: absolute; z-index: 5; bottom: calc(var(--keys-h) + 16px);
  right: calc(clamp(8px, 4vw, 64px) + clamp(112px, 12vw, 176px) + 6px);
  height: 34px; padding: 0 13px; border-radius: 999px; font-size: 13px;
}
.sound-pill[aria-pressed="true"] { background: var(--tint); color: var(--text); }

/* ---- the gifts band: "Unlock 3 songs free" --------------------------------
   Where the Plus band was, on its surface: the three free unlocks, side by side under the intro
   (round 7 added the gift code; beside a fourth column the cards were too narrow for the code),
   each a card with its action at the bottom so the buttons line up whatever the copy above says. */
.gifts-band {
  position: relative; margin-top: 64px; padding: 36px clamp(20px, 4vw, 44px); border-radius: 26px;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px 24px; align-items: stretch;
  /* Lit evenly from above, with a faint bloom underneath, both sized in % so they scale with the
     band. It was one 420x260px glow pinned to the top-right corner (the Plus card's, where the
     napping cat was), which left the band lopsided once three cards and a wide intro filled it. */
  background:
    radial-gradient(120% 85% at 50% 0%, rgba(255,145,191,.2), transparent 72%),
    radial-gradient(120% 60% at 50% 100%, rgba(255,79,154,.1), transparent 72%),
    linear-gradient(135deg, #3a1a2d, #2a1422);
  border: 1px solid rgba(255,145,191,.22);
}
/* The intro's line runs the band's width, short of the cat: three across, the app card's cat sits
   up into this row at its right end, 1.38 x its width (cat.css .coon-perch: 130px, so ~180px).
   It was 42ch, which left half the row empty beside it. Pretty, not balanced: balance evens the
   lines by shortening both, which brought the empty space back; pretty fills, minus a lone word. */
.gifts-intro { grid-column: 1 / -1; }
.gifts-intro h2 { font-size: var(--text-2xl); font-weight: 800; margin: 10px 0 12px; }
.gifts-intro p:last-child { color: var(--muted); max-width: calc(100% - 200px); text-wrap: pretty; }
/* The card's surface is its ::before, a layer of its own (it once hid a napping Mochi's lower
   half behind the card); the Maine Coon napping on the app card (cat.css, .coon-perch) lies on
   its top edge, a layer above. */
.gift-card { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
             padding: 22px; border-radius: 18px; border: 1px solid var(--line); }
.gift-card::before { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; background: var(--surface); }
.gift-card > :not(.coon-perch) { position: relative; z-index: 1; }
.gift-card h3 { font-size: 18px; font-weight: 800; }
.gift-card > :is(p, label) { color: var(--muted); font-size: 14px; }   /* > : not the code's error */
.gift-card > .play, .gift-card > .load, .gift-card > .stores, .gift-code { margin-top: auto; }
.gift-card .play, .gift-card .load { width: 100%; justify-content: center; }
.gift-card .stores { padding-top: 6px; }
/* The code card: the site's text field (tokens.css --field-*, sunk, so it never reads as one more
   button) in the Unlock dialog's code type, at the card buttons' 48px and corner, and Redeem is the
   plain secondary, like Pick a song. A round tried a dashed ticket edge and a pink-tint Redeem
   here: dashed reads as a drop zone or a disabled slot, and one-off styles broke the band's set.
   Field and Redeem share a row once the CARD is wide enough for the whole code beside the button,
   a container query, since the card's width changes at three breakpoints; narrower, they stack. */
.gift-code { width: 100%; padding-top: 6px; container-type: inline-size; }
.gift-code-row { display: grid; gap: 8px; }
@container (min-width: 300px) { .gift-code-row { grid-template-columns: minmax(0, 1fr) auto; } }
.gift-code input {
  min-width: 0; height: 48px; padding: 0 14px; border-radius: 14px;
  border: 1px solid var(--control-line); background: var(--field-bg); box-shadow: var(--field-shadow);
  color: var(--text); font: inherit; font-size: 16px; letter-spacing: .06em;   /* 16, not less: iOS zooms on focus under it */
}
.gift-code input::placeholder { color: var(--dim); }
.gift-code input:focus-visible { outline: 3px solid #ffd2e5; outline-offset: 2px; }
.gift-code input[aria-invalid] { border-color: #ff8fab; }
.gift-error { margin-top: 8px; color: #ffa8bf; font-size: 13px; font-weight: 700; }   /* unlock.css .field-error's */
.gift-ico { width: 38px; height: 38px; border-radius: 11px; display: grid; place-items: center; background: var(--tint); margin-bottom: 4px; }
.gift-ico img { width: 19px; height: 19px; }


@media (max-width: 960px) {
  /* Phones and tablets stack: words on top, the music underneath, so the tiles fade in lower. */
  .hero-copy { justify-content: flex-start; padding-top: 40px; }
  .hero-copy > * { max-width: 100%; }
  .hero-sky::after { background: linear-gradient(180deg, var(--scrim) 0%, var(--scrim) 42%, transparent 70%); }
  .hero-fall { -webkit-mask-image: linear-gradient(180deg, transparent 0 44%, #000 70%);
                       mask-image: linear-gradient(180deg, transparent 0 44%, #000 70%); }
}
/* Three across, narrower than this, squeezes the typed code and the store badges out of their cards.
   Stacked, the app card (last) sits this far below the code card because its cat, sitting up, and
   its hearts need the room; three across, they have it beside the intro's short lines. */
@media (max-width: 860px) {
  .gifts-band { grid-template-columns: minmax(0, 1fr); }
  .gifts-intro p:last-child { max-width: none; }   /* stacked, the cat is on the last card, not here */
  .gift-card[data-nap] { margin-top: 76px; }
}
@media (max-width: 640px) {
  .hero { --keys-h: 104px; }
  .proof { display: none; }   /* secondary, and it sat where the tiles start falling */
  .hero-fall { -webkit-mask-image: linear-gradient(180deg, transparent 0 52%, #000 72%);
                       mask-image: linear-gradient(180deg, transparent 0 52%, #000 72%); }
  .sound-pill span { display: none; }
  .sound-pill { width: 34px; padding: 0; justify-content: center; }
}
/* Reduced motion: the cat sits still with its eyes open, the tiles freeze on one frame
   (hero.js), and a tap still gets its answer in words. */
@media (prefers-reduced-motion: reduce) {
  .cat-say { transition: none; }
}
