/* The song page (song.html) only: the song hero, the mode cards and the cover that previews
   them. Loaded after base.css, whose tokens and cards it uses. */

/* The top of the song page as one grid (round 4, the client's order):
     cover | genre · title · artist · level + time · tags    1fr: the room above Start is the cat's
     cover | Start · Unlock · bookmark                      auto: so Start's bottom edge = the cover's
     modes |
   The cover is the preview stage and the mode cards sit directly under it, so hovering a card
   plays it just above the pointer. Right column content too tall for the cover — a long title
   plus tags — grows the 1fr row and pushes Start down; it never overlaps. */
.song-hero {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  grid-template-areas: "cover ident" "cover actions" "modes .";
  grid-template-rows: 1fr auto auto;
  column-gap: clamp(28px, 4vw, 52px); row-gap: 20px; margin-top: 22px;
}
.big-cover {
  grid-area: cover; align-self: start; position: relative; aspect-ratio: 16 / 10; border-radius: 22px; overflow: hidden;
  border: 1px solid var(--line); box-shadow: 0 30px 70px var(--shadow);
}
.big-cover .cover-art { position: absolute; inset: 0; }
/* 56px of padding + the 20px row gap = a 76px floor between the tags and Start, because that
   room is the cat's: Mochi's head stands 66px above Start (measured at its 72px perch), so 76 keeps
   its ears 10px clear of the last tag however long the title runs. It was 24px, and two lines of
   tags put the walking cat's head on "Wedding". */
.song-ident { grid-area: ident; padding-bottom: 56px; min-width: 0; }
/* Wraps, never truncates, on its own page: the long titles are real (item 13). A size down from
   the 44px it was, so two lines of a long title still leave the cat its room. */
.song-ident h1 { font-size: clamp(24px, 2.6vw, 34px); font-weight: 800; margin: 8px 0 4px; text-wrap: balance; overflow-wrap: break-word; }
.song-ident .by { font-size: 17px; color: var(--muted); }
.song-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin-top: 12px;
             font-size: 14px; font-weight: 700; color: var(--control-ink); }
.song-meta .level .paw-i { width: 15px; height: 15px; }
/* Paws then the word, the way the clock is an icon then the time: the cards keep paws only, but
   here there is room to say it (round 5, the client: "Easy, Medium, Hard next to the paws"). */
.song-level { display: inline-flex; align-items: center; gap: 7px; }
.song-time { display: inline-flex; align-items: center; gap: 6px; font-variant-numeric: tabular-nums; }
.song-time .i { width: 15px; height: 15px; }
/* The tags replace the facts: each one a way into Home's search (index.html?q=). The site's
   own chip, a size down — 36px, the group chips' height, so they stay a fair touch target. */
.song-tags { list-style: none; padding: 0; margin: 16px 0 0; display: flex; flex-wrap: wrap; gap: 8px; }
.song-tags a {
  display: inline-flex; align-items: center; height: 36px; padding: 0 13px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--control-bg); color: var(--control-ink);
  font-size: 13px; font-weight: 700; text-decoration: none; transition: background 160ms ease;
}
.song-tags a:hover { background: var(--control-hover); color: var(--text); }
/* Start, Unlock and the bookmark, one row (round 5, option A of docs/mockups/round5-start-row.html).
   Start takes the width; Unlock and the bookmark are dark and Start's height, so the row reads as
   one bar with smaller jobs at its end, and nothing in it is wider than Start. */
.song-actions { grid-area: actions; display: flex; gap: 10px; }
/* A container, so the label can drop the mode's name when Unlock leaves Start too narrow for it.
   240px is the longest label, "Try demo · Interactive Score", measured (239px of content box; at
   1440px Start has 247, on a phone ~130). The chosen card and the cover's Watch button still name
   the mode. Re-measure if a mode is renamed. */
.cta-start { flex: 1; min-width: 0; position: relative; container-type: inline-size; }
/* Clipped, not display: none — the link's accessible name keeps the mode. */
@container (width < 240px) { .cta-mode { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } }
.cta-label { display: inline-flex; align-items: center; gap: 8px; }
.bookmark { flex: none; width: 48px; height: 48px; padding: 0; justify-content: center; border-radius: 14px; }
.bookmark img { width: 20px; height: 20px; }
.bookmark[aria-pressed="true"] { background: var(--tint); border-color: color-mix(in srgb, var(--pink) 45%, transparent); }
/* Unlock only while a LOCKED mode is chosen — the two free modes never need it. It slides rather
   than appearing: Start gives up the width as Unlock takes it, so the cat sitting on Start's end
   glides instead of jumping. That is a width animation on purpose — the row's layout IS the
   change — on one button, for 220ms. Off, it is zero wide, borderless and pulled back over the row
   gap, and `visibility` takes it out of the tab order and the accessibility tree. */
.unlock-open {
  flex: none; max-width: 160px; padding: 0 18px; gap: 8px; overflow: hidden; white-space: nowrap;
  transition: max-width 220ms ease, padding 220ms ease, margin 220ms ease, border-width 220ms ease, opacity 160ms ease, visibility 220ms;
}
.unlock-open[data-off] { max-width: 0; padding: 0; margin-left: -10px; border-width: 0; opacity: 0; visibility: hidden; }
/* The cat perched on Start: sitting on the button's top edge, the rest of it clipped behind the
   button, the way the hero's cat sits on the keybed. Decorative — pointer-events off, so a click
   on the cat is a click on nothing; the button is the target. */
.start-cat { position: absolute; right: 22px; bottom: calc(100% - 3px); width: 72px; pointer-events: none; --cat-from: 120%; }
/* A band below the cat, so a pat lands ON the button's face instead of stopping at its edge, where
   it was cut off (cat-moves.js tapTap). 15% of the perch is cat3d.js's PAD.bottom (20 of 140
   units); --cat-from starts the climb-in that much deeper, or its ears showed in the band first. */
.start-cat .cat-stage { display: block; padding-bottom: 15%; margin-bottom: -15%; }

/* The mode row's label line: what it is on the left, how to use it on the right. */
.row-label {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 4px 12px; margin: 0 0 10px;
  font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--dim);
}
.row-label > span { display: inline-flex; align-items: center; gap: 6px; }
.row-label > span + span { font-size: 12.5px; font-weight: 700; letter-spacing: 0; text-transform: none; }
.on-touch { display: none; }
@media (hover: none) { .on-hover { display: none; } .on-touch { display: inline; } }

.song-modes { grid-area: modes; display: flex; flex-direction: column; }
/* The cards: every mode at once, in one row under the cover. Each stands up — icon on top,
   check in the corner — which is what lets four share the cover's width. Each is a native
   radio in a label, so the whole card is the hit target and the checked state is the
   platform's. Same surface, border and radius as the song cards, so they read as this site's. */
.mode-grid { flex: 1; display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 12px; padding-top: 4px; }
.mode-opt {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; padding: 14px 14px 15px;
  border-radius: 16px; cursor: pointer; border: 1px solid var(--line); background: var(--surface);
  transition: background 140ms ease, border-color 140ms ease, transform 140ms ease;
}
.mode-opt:hover { border-color: color-mix(in srgb, var(--pink) 45%, transparent); transform: translateY(-2px); }
/* With no tick, the chosen card says so three ways: a pink border, a pink wash, and its icon
   tile turning brand pink — so it never rests on one hue alone. */
.mode-opt:has(input:checked) {
  border-color: color-mix(in srgb, var(--pink) 80%, transparent);
  background: color-mix(in srgb, var(--pink) 10%, var(--surface));
}
.mode-opt:has(input:focus-visible) { outline: 3px solid #ffd2e5; outline-offset: 2px; }
.mode-ico { flex: none; width: 38px; height: 38px; border-radius: 11px; display: grid; place-items: center; background: var(--tint); transition: background 140ms ease; }
.mode-ico img { width: 19px; height: 19px; filter: brightness(0) invert(1); }
.mode-opt:has(input:checked) .mode-ico { background: linear-gradient(135deg, #ff8fc0, #ff4f9a); }
.mode-name { font-size: 15px; font-weight: 800; line-height: 1.2; }
/* On the card's top edge, so it costs the card no line of its own. */
.tag-rec {
  position: absolute; top: -9px; left: 12px; display: inline-flex; align-items: center; gap: 4px; height: 18px; padding: 0 7px;
  border-radius: 999px; font-size: 10px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  background: #fff2f8; color: #c8196a; box-shadow: 0 2px 6px rgba(0,0,0,.3);
}
.tag-rec .paw-i { width: 9px; height: 9px; color: var(--pink); }
/* Demo: the same tag, in the dark — "you can try this" is a fact about access, not a
   recommendation, so it must not wear the recommendation's cream. */
.tag-demo { background: #3d0f26; color: var(--pink-soft); border: 1px solid rgba(255,145,191,.45); box-shadow: none; }
.mode-tag { display: contents; }


/* The big cover as the preview stage: the song's picture at rest, a mode's live preview laid
   over it while you look at that mode, labelled in the top-right corner. */
.pv { position: absolute; inset: 0; overflow: hidden; }
.pv .keyboard .white span { display: none; }
.cover-pv { z-index: 1; opacity: 0; transition: opacity 180ms ease; }
.big-cover[data-previewing] .cover-pv { opacity: 1; }
.cover-pv-label, .cover-watch { z-index: 2; }
.cover-pv-label {
  position: absolute; top: 14px; right: 14px; height: 26px; padding: 0 11px; border-radius: 999px; display: inline-flex; align-items: center;
  font-size: 12px; font-weight: 800; color: #fff; background: rgba(20,10,16,.78); border: 1px solid rgba(255,255,255,.16);
  opacity: 0; transition: opacity 160ms ease;
}
.big-cover[data-previewing] .cover-pv-label { opacity: 1; }
.cover-watch {
  position: absolute; left: 14px; bottom: 14px; display: inline-flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 14px 0 11px; border-radius: 999px; border: 1px solid rgba(255,255,255,.16);
  background: rgba(20,10,16,.8); color: #fff; font-size: 13px; font-weight: 800; cursor: pointer;
}
.cover-watch span { display: inline-flex; align-items: center; gap: 6px; }
.cover-watch .i { width: 12px; height: 12px; }
/* play.svg is baked dark for the pink buttons; on this dark pill it is whitened — the filter the
   view switch's current row already uses (header.css), exact for white. */
.cover-watch .w-off .i { filter: brightness(0) invert(1); }
.cover-watch .w-on, .big-cover[data-previewing] .cover-watch .w-off { display: none; }
.big-cover[data-previewing] .cover-watch .w-on { display: inline-flex; }
.cover-watch:hover { background: rgba(20,10,16,.92); }

/* The previews themselves, as played on the stage. */
/* Waterfall: the app's own sky, tiles and keyboard. */
.pv-waterfall {
  --keys-h: 28%;   /* a share, not px: the same preview fills a small card or the big cover */
  display: grid; grid-template-rows: minmax(0, 1fr) var(--keys-h);
  background-color: #1a0f17;
  background-image:
    linear-gradient(90deg, rgba(255,255,255,.03) 0 1px, transparent 1px),
    radial-gradient(120% 60% at 50% 100%, rgba(255,79,154,.18), transparent 72%),
    linear-gradient(180deg, #170d15 0%, #23131e 58%, #2c1826 100%);
  background-size: calc(100% / var(--white-key-count, 15)) 100%, 100% 100%, 100% 100%;
}
.pv-fall { position: relative; overflow: hidden; }
.pv .hero-note { border-radius: 5px; }
.pv .strike-paw { width: 16px; height: 15px; }

/* Effortless Play: the lab's stage — paws arriving from the right into the judgement line. */
.pv-effortless { background: radial-gradient(70% 90% at 26% 50%, rgba(255,79,154,.12), transparent 70%), linear-gradient(180deg, #1c1018, #2a1622); }
.pv-line {
  position: absolute; left: 26%; top: 0; bottom: 0; width: 3px; transform: translateX(-50%);
  background: linear-gradient(180deg, #ff91bf, #ff4f9a 45%, #ffd36e);
  box-shadow: 0 0 14px 3px rgba(255,79,154,.45);
}
.pv-line::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 46px; transform: translateX(-50%);
                   background: linear-gradient(90deg, transparent, rgba(255,145,191,.1), transparent); }
.pv-paw { position: absolute; width: 34px; height: 32px; translate: -50% -50%; fill: var(--channel);
          filter: drop-shadow(0 0 6px color-mix(in srgb, var(--channel) 70%, transparent)); }
.pv-ring { position: absolute; width: 56px; height: 56px; border-radius: 50%; border: 2px solid var(--channel); pointer-events: none; }
.pv-verdict { position: absolute; z-index: 1; white-space: nowrap; font-size: 15px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
              color: #ffc2dc; text-shadow: 0 0 10px rgba(255,79,154,.8); }

/* Interactive Sheet: keyboard on top, the real engraving under it, the playing bar's block. */
.pv-interactive { display: grid; grid-template-rows: 19% minmax(0, 1fr); background: #241420; }
.pv-page { position: relative; overflow: hidden; margin: 8px 8px 0; border-radius: 6px 6px 0 0; background: #fff; }
.pv-strip { position: absolute; left: 0; top: 4px; height: calc(100% - 4px); aspect-ratio: 1200 / 288; will-change: transform; }
.pv-strip img { display: block; width: 100%; height: 100%; }
.pv-block { position: absolute; height: 16.7%; border-radius: 3px; transition: left 180ms ease, width 180ms ease; }
.pv-block.treble { top: 37.5%; background: color-mix(in srgb, var(--ch-1) 34%, transparent); }
.pv-block.bass { top: 70.8%; background: color-mix(in srgb, var(--ch-2) 34%, transparent); }

/* Sheet Music: the real engraved page, read slowly. */
.pv-score { will-change: transform; position: absolute; left: 18px; top: 20px; width: 150%; border-radius: 6px; overflow: hidden; box-shadow: 0 12px 30px rgba(0,0,0,.5); }
.pv-score img { display: block; width: 100%; }
.pv-sheet { background: #241420; }


@media (max-width: 960px) {
  /* Stacked: cover, who the song is, the cards (the cover still in view above them), then the
     Start row right after the choice it starts. */
  .song-hero { grid-template-columns: minmax(0, 1fr); grid-template-areas: "cover" "ident" "modes" "actions"; grid-template-rows: none; row-gap: 0; }
  .song-ident { margin-top: 22px; padding-bottom: 0; }
  .song-modes { margin-top: 22px; }
  /* Room above Start for the cat perched on it: stacked, the cards sit right on top of the button.
     Its head stands 59px above Start at this 58px perch; 68 keeps the ears 9px off the last card
     (54 let them touch it). */
  .song-actions { margin-top: 68px; }
  .start-cat { width: 58px; }
}
@media (max-width: 640px) {
  .mode-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }   /* four fit a tablet row, not a phone's */
}
@media (prefers-reduced-motion: reduce) {
  .cover-pv, .unlock-open { transition: none; }
}
