﻿/* ---------- Splash + auth ---------- */

.splash {
  width: 100%; /* the boot splash host is a row-flex container - without this the column packs left */
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  animation: splashin 0.4s ease both;
}
.splash-stage { width: 96px; height: 96px; }
.splash-icon {
  width: 100%; height: 100%;
  border-radius: 24px;
  animation: logopop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.splash .brand {
  font-size: 26px; font-weight: 800; letter-spacing: -0.5px;
  animation: brandup 0.55s 0.18s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
.splash .eq {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 14px;
  animation: brandup 0.55s 0.28s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
.splash .eq i {
  width: 4px;
  height: 100%;
  border-radius: 2px;
  background: #fff;
  animation: eqbar 0.9s ease-in-out infinite;
}
.splash .eq i:nth-child(1) { animation-delay: 0s; }
.splash .eq i:nth-child(2) { animation-delay: 0.15s; }
.splash .eq i:nth-child(3) { animation-delay: 0.3s; }
.splash .eq i:nth-child(4) { animation-delay: 0.1s; }
.splash .eq i:nth-child(5) { animation-delay: 0.22s; }
.splash.bye { animation: splashout 0.34s cubic-bezier(0.4, 0, 0.2, 1) forwards; }
@keyframes splashin { from { opacity: 0; } }
@keyframes logopop { from { transform: scale(0.55) rotate(-6deg); opacity: 0; } }
@keyframes brandup { from { opacity: 0; transform: translateY(10px); } }
@keyframes eqbar { 0%, 100% { transform: scaleY(0.3); } 50% { transform: scaleY(1); } }
@keyframes splashout { to { opacity: 0; transform: scale(1.05); } }

/* Auth = full-bleed brand video (R2, served by /api/file/*) with the poster
   showing until the first frames decode, then a fade-in over it. Content
   stacks at the bottom over a scrim, like the reference mockup. */
.authstage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  background: #0b0817;
}
.authbg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.7s ease;
  pointer-events: none;
  background: #0b0817 center / cover no-repeat;
}
.authbg.on { opacity: 1; }
.authscrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(11, 8, 23, 0.25) 0%, rgba(11, 8, 23, 0) 30%, rgba(11, 8, 23, 0.12) 55%, rgba(11, 8, 23, 0.82) 82%, rgba(11, 8, 23, 0.92) 100%);
  pointer-events: none;
}
.authwrap {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  padding: 30px 30px calc(34px + var(--safe-bottom));
  max-width: 480px;
  width: 100%;
  margin: 0 auto;
}
/* Staggered entrance cascade for the auth card */
.authwrap > * { animation: authup 0.45s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
.authwrap > *:nth-child(1) { animation-delay: 0s; }
.authwrap > *:nth-child(2) { animation-delay: 0.07s; }
.authwrap > *:nth-child(3) { animation-delay: 0.14s; }
.authwrap > *:nth-child(4) { animation-delay: 0.21s; }
@keyframes authup { from { opacity: 0; transform: translateY(14px); } }

.authwrap h1 {
  font-size: 34px;
  line-height: 1.12;
  font-weight: 800;
  color: #fff;
  text-align: center;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);
  margin-bottom: 10px;
}
.authwrap .sub {
  color: rgba(255, 255, 255, 0.82);
  font-size: 15px;
  text-align: center;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
  margin-bottom: 26px;
}
.authwrap .err { color: #ff9db8; font-size: 12px; text-align: center; text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6); margin: 0 0 10px; }
.authwrap .err:empty { display: none; }

.gbtn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 12px 16px;
  border-radius: 12px;
  background: #fff;
  color: #1f1f27;
  font-weight: 700;
  font-size: 14px;
}
/* Gradient glow pill over the video - the branded Google button */
.gbtn.grad {
  min-height: 56px;
  border-radius: 999px;
  font-size: 16px;
  color: #fff;
  border: 1.5px solid transparent;
  background:
    linear-gradient(rgba(17, 12, 32, 0.72), rgba(17, 12, 32, 0.72)) padding-box,
    linear-gradient(100deg, #ff3bd4, #b44cff 45%, #4aa8ff) border-box;
  box-shadow:
    0 0 22px rgba(255, 60, 200, 0.35),
    0 0 44px rgba(122, 76, 255, 0.22),
    0 10px 30px rgba(0, 0, 0, 0.45);
}
.gbtn.grad:active { transform: scale(0.98); }
.gbtn .gicon { display: flex; }
.gbtn .gicon svg { width: 18px; height: 18px; }
.gbtn.hidden { display: none; }
/* GIS: Google's real button renders invisibly ON TOP of the custom pill and
   becomes the click target (official button keeps handling the popup). The
   iframe is scaled so its hit area covers the taller pill; it's transparent,
   so the distortion is invisible. Without .on, clicks fall through to the
   pill's redirect fallback. */
.gbtnwrap { position: relative; }
.gbtnwrap .gsihost {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 0;
  overflow: hidden;
  align-items: center;
  justify-content: center;
}
.gbtnwrap .gsihost.on { display: flex; }
.gbtnwrap .gsihost.on iframe { transform: scale(1.9); transform-origin: center; }

/* ---------- Discover ---------- */

/* Hero: the banner photo takes the full top, edge-to-edge, with the title +
   credits pill overlaid on it (the pill stays a SIBLING - never nest a button
   in a button - absolutely positioned above the banner's click target). */
.discoverhero { position: relative; }
.discover-top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 20px 0;
}
.discover-top h1 {
  flex: 1;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 3.5px;
  text-transform: uppercase;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.45);
}

/* Credit display: bare diamond glyph + amount, styled like header text -
   no border, no background. Taps into the paywall. */
.creditpill {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  /* Solid translucent (NOT backdrop-filter): a blur here re-renders every
     frame while Discover scrolls - visible lag + artifacts on WebView. */
  background: rgba(10, 10, 14, 0.55);
  border: 0;
  border-radius: 50px;
  color: #fff;
  flex-shrink: 0;
  transition: transform 0.16s cubic-bezier(0.34, 1.1, 0.64, 1), opacity 0.15s ease;
}
.creditpill:active { transform: scale(0.92); opacity: 0.75; }
.creditpill svg { width: 13px; height: 13px; }
.creditpill .cp-amount { font-size: 13.5px; font-weight: 800; letter-spacing: 0.3px; }

/* Create banner: generated photo (Atlas one-shot, scripts/resize-banner.ps1) -
   subject on the right, copy on the dark left wall. Taps open the create sheet.
   Full-bleed hero: square at the top edge (it rises behind the overlaid
   discover-top), softly rounded only at the bottom. */
.createbanner {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 252px;
  margin: 0;
  padding-top: 44px; /* keeps the copy clear of the overlaid title row */
  border-radius: 0 0 22px 22px;
  overflow: hidden;
  background: #101014 url("../img/banner-create.jpg") center 28% / cover no-repeat;
  text-align: left;
  transition: transform 0.16s cubic-bezier(0.34, 1.1, 0.64, 1);
}
.createbanner:active { filter: brightness(0.9); }
.createbanner::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(4, 4, 7, 0.6) 0%, rgba(4, 4, 7, 0) 32%),
    linear-gradient(90deg, rgba(4, 4, 7, 0.45) 0%, rgba(4, 4, 7, 0.12) 45%, rgba(4, 4, 7, 0) 65%);
}
.createbanner .cb-copy { position: relative; padding: 10px 20px 18px; max-width: 72%; }
/* Big display heading (sentence case, three lines) - the hero's voice. */
.createbanner .cb-title {
  font-size: 29px;
  font-weight: 650;
  letter-spacing: -0.4px;
  line-height: 1.16;
  color: #fff;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.35);
}
.createbanner .cb-sub { font-size: 12px; line-height: 1.5; color: rgba(255, 255, 255, 0.78); margin-top: 10px; }
.createbanner .cb-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
  padding: 8px 15px;
  border-radius: 50px;
  background: #fff;
  color: #0b0b0d;
  font-size: 12.5px;
  font-weight: 700;
}
.createbanner .cb-cta svg { width: 12px; height: 12px; }

/* Section rows: sentence-case label + optional right action (See all â€º). */
.sechead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px 8px;
}
.sechead .sec { font-size: 15px; font-weight: 700; color: var(--text); }
.sechead .seeall {
  border: 0;
  background: none;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
  padding: 4px 0;
}

/* Community list header: title + Trending/Recent/For you sort chips. */
.community-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 16px 20px 4px;
}
.community-head .ch-shm { min-width: 0; }
.community-head .ch-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.community-head .ch-sub { font-size: 11px; color: var(--muted); margin-top: 2px; }
.sortchips { display: flex; gap: 4px; flex-shrink: 0; }
.sortchip {
  border: 0;
  border-radius: 50px;
  padding: 4px 7px;
  background: var(--surface);
  color: var(--text-2);
  font-size: 10px;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
}
.sortchip.on { background: #fff; color: #0b0b0d; font-weight: 700; }

.chipgroup { padding-top: 2px; }
.chiplabel {
  padding: 0 20px 2px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--muted);
}
.clearbtn {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---------- Genre tiles: solid color cards + genre glyph ---------- */

/* Art is a generated SVG (scripts/make-genre-icons.mjs): one solid brand
   color per genre with a white glyph, oversized bottom-right. No photo
   treatment - the card IS the design. */
.gtiles { display: flex; gap: 10px; overflow-x: auto; padding: 2px 20px 10px; }
.gtile {
  position: relative;
  flex-shrink: 0;
  width: 106px;
  border-radius: 14px;
  background: var(--surface);
  overflow: hidden;
  transition: transform 0.16s cubic-bezier(0.34, 1.1, 0.64, 1);
}
.gtile:active { transform: scale(0.97); }
.gtile img {
  display: block;
  width: 100%;
  height: 106px;
  object-fit: cover;
  border-radius: 14px;
}
.gtile .glabel {
  position: absolute;
  left: 10px;
  top: 9px;
  right: 8px;
  z-index: 1;
  text-align: left;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.2px;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gtile.on::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 14px;
  box-shadow: inset 0 0 0 3px #fff;
}
.gtile.on .glabel { text-decoration: underline; text-underline-offset: 3px; }

.clearpill {
  padding: 6px 13px;
  border-radius: 50px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-2);
}

/* ---------- Library ---------- */

.libhead { display: flex; align-items: center; padding: 22px 20px 2px; }
.libhead .ht { flex: 1; }
.libhead h1 { font-size: 22px; font-weight: 700; letter-spacing: 3.5px; text-transform: uppercase; }
.libhead .hsub { font-size: 10.5px; color: var(--text-2); margin-top: 4px; text-transform: uppercase; letter-spacing: 1.6px; }
.libhead .plus {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--elevated);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.libhead .plus svg { width: 20px; height: 20px; }

.libsearch { display: flex; gap: 10px; padding: 12px 20px 4px; }
.libsearch .searchwrap { flex: 1; position: relative; }
.libsearch input { border-radius: 50px; padding: 11px 16px; }
.libsearch .sortbtn {
  width: 44px;
  border-radius: 50px;
  background: var(--surface);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-2);
}
.libsearch .sortbtn svg { width: 18px; height: 18px; }

/* Playlist rows share the exact geometry of song rows (.row) so tab flips
   never shift content: same padding, 52px cover, 68px height. */
.playlistitem {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px 9px 16px;
  border-radius: 10px;
  width: 100%;
  text-align: left;
}
.playlistitem .collage {
  width: 48px; height: 48px;
  border-radius: 6px;
  background: var(--elevated);
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  flex-shrink: 0;
}
.playlistitem .collage img { width: 100%; height: 100%; object-fit: cover; }
.playlistitem .collage .ph { background: var(--surface); }
.playlistitem .pmeta { flex: 1; min-width: 0; }
.playlistitem .pname { font-size: 13.5px; font-weight: 500; letter-spacing: 0.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.playlistitem .psub { font-size: 11px; color: var(--text-2); margin-top: 3px; }
/* Pinned virtual playlist (Liked) - not deletable, hearts are its membership */
.playlistitem.pinned .pname { color: #fff; }

/* Bulk add-to-playlist context row ("N songs"): the base .collage/.cover
   sizes are scoped to .playlistitem/.row, so unsized here the images paint
   at natural size and balloon over the whole sheet. */
.addsong .cover {
  width: 44px; height: 44px;
  border-radius: 10px;
  object-fit: cover;
  flex-shrink: 0;
}
.addsong .collage {
  width: 44px; height: 44px;
  border-radius: 10px;
  flex-shrink: 0;
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
.addsong .collage img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- Profile ---------- */

/* Hero (mock): big round avatar left with pencil badge, name/handle/bio/stats
   stacked to its right, overflow action top-right. */
.hero-xl {
  position: relative;
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 18px;
  padding: 20px 20px 0;
}
.hero-xl .avbtn { margin-top: 2px; }
.hero-xl .avatar {
  width: 96px; height: 96px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--elevated);
  flex-shrink: 0;
  box-shadow: none;
}
.hero-xl .edbadge {
  position: absolute;
  right: -3px; bottom: -3px;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: #0c0c0e;
  border: 1.5px solid #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
.hero-xl .edbadge svg { width: 14px; height: 14px; }
.hero-xl .hx { flex: 1; min-width: 0; padding-top: 2px; }
.hero-xl .hname { font-size: 30px; font-weight: 700; line-height: 1.05; }
.hero-xl .hhandle { font-size: 14px; color: var(--text-2); margin-top: 4px; }
.hero-xl .bio { padding: 12px 0 0; }
/* Stat line wraps to its own full-width row under the hero - three stats
   never fit beside the avatar on phone widths */
.hero-xl .statline { flex-basis: 100%; gap: 20px; margin-top: 2px; }
.hero-xl .heromenu, .hero-xl .topaction {
  flex-shrink: 0;
  width: 38px; height: 38px;
  margin: 0;
}
.hero-xl .hactions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  margin-top: 4px;
}
/* Profile overflow (report / block) next to the follow pill */
.heromenu { flex-shrink: 0; }
/* Blocked-profile hero: quiet outlined unblock pill */
.unblockbtn {
  flex-shrink: 0;
  padding: 8px 18px;
  border-radius: 50px;
  font-size: 13px;
  font-weight: 700;
  border: 1px solid var(--border);
  color: var(--text);
  background: var(--surface);
}
.unblockbtn:active { transform: scale(0.95); }
.bio { font-size: 12px; color: var(--text-2); white-space: pre-wrap; text-transform: uppercase; letter-spacing: 1.6px; line-height: 1.8; }

/* Placeholder avatar: the blob-face artwork (web/img/avatar-placeholder.webp) */
.avatar.avph { background: #05050a; }

/* Own avatar is a "change photo" button (opens the edit sheet) */
.avbtn {
  position: relative;
  flex-shrink: 0;
  border-radius: 50%;
  padding: 0;
  line-height: 0;
}
.edcambadge {
  position: absolute;
  right: -2px; bottom: -2px;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}
.edcambadge svg { width: 13px; height: 13px; color: #000; }

/* Handle-claim nudge (default user_XXXXXX handle) */
.claimbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 20px 0;
  padding: 10px 14px;
  width: calc(100% - 40px);
  text-align: left;
  font-size: 12.5px;
  font-weight: 600;
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 12px;
}

.profile-actions { display: flex; gap: 10px; padding: 12px 20px 2px; }

/* Profile tab pager: horizontal finger-follow swiping between the Songs /
   Liked / Library pages (makePager drives the track transform). Vertical
   gestures stay native so the pane keeps scrolling.
   The pager surface fills ALL the leftover pane height: flex-stretch keeps
   the viewport covering the empty area below short pages (empty Liked, few
   songs), so tab swipes work there too instead of dying on dead space.
   flex-shrink 0 keeps tall pages overflowing into the pane scroll. */
.profilecontent {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  box-sizing: border-box;
}
/* The hero/stats/tabbar shell (heroskel) and the pager body both stretch:
   flex-grow hands every leftover pane pixel to the pager viewport, so tab
   swipes also work on the empty area below short pages. flex-shrink 0 keeps
   tall pages overflowing into the pane scroll instead of being clamped. */
.profilecontent .heroskel {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.profilecontent .probody {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.prow-viewport {
  position: relative;
  overflow: hidden;
  touch-action: pan-y;
  flex: 1 0 auto;
}
.prow-track { display: flex; align-items: flex-start; will-change: transform; }
.prow-page { flex: 0 0 100%; width: 100%; min-width: 0; }

/* Followers / Following list page */
.followrow {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 20px;
  text-align: left;
}
.followrow .meta { flex: 1; min-width: 0; }
.followrow .title { font-size: 13.5px; font-weight: 500; letter-spacing: 0.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.followrow .sub { font-size: 11px; color: var(--text-2); margin-top: 2px; }
.savatar { width: 42px !important; height: 42px !important; }
.rowchev { color: var(--muted); transform: rotate(180deg); display: flex; }
.rowchev svg { width: 18px; height: 18px; }

/* ---------- Playlist page ---------- */

.plhead { display: flex; align-items: center; gap: 16px; padding: 8px 20px 0; }
.plhead .collage {
  width: 92px; height: 92px;
  border-radius: 18px;
  background: var(--elevated);
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  flex-shrink: 0;
}
.plhead .collage img { width: 100%; height: 100%; object-fit: cover; }
.plhead .collage.single img { grid-column: 1 / span 2; grid-row: 1 / span 2; }
.plhead .pm { flex: 1; min-width: 0; }
.plhead .pname { font-size: 20px; font-weight: 700; }
.plhead .psub { font-size: 11.5px; color: var(--text-2); margin-top: 4px; display: flex; align-items: center; gap: 5px; }
.plhead .psub svg { width: 12px; height: 12px; }

.playall { display: flex; padding: 14px 20px 4px; }
.playall .solidbtn { flex: 1; }

/* ---------- Settings ---------- */

.setgroup { margin: 14px 20px 0; background: var(--surface); border: 1px solid var(--border); border-radius: 18px; overflow: hidden; }
.setitem {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 15px 16px;
  width: 100%;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.setitem:last-child { border-bottom: none; }
/* Legal links are <a> rows - strip UA blue/underline so they match the rows */
a.setitem { color: inherit; text-decoration: none; }
a.setitem:active { background: rgba(255, 255, 255, 0.05); }
.setitem .si { flex: 1; min-width: 0; }
.setitem .st { font-size: 14px; font-weight: 600; }
.setitem .ss { font-size: 11px; color: var(--text-2); margin-top: 2px; }
.setitem select { width: 150px; flex-shrink: 0; padding: 8px 10px; font-size: 13px; }
.setitem .accav { width: 40px; height: 40px; flex-shrink: 0; }
.setitem .accav .avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; display: block; }

/* ---------- Paywall ---------- */

.paywrap {
  position: relative;
  z-index: 1;
  padding: 2px 20px calc(28px + var(--safe-bottom));
  max-width: 480px;
  margin: 0 auto;
}
/* Background hero: bright daylight lifestyle photo (paywall-specific, distinct
   from the Discover banner), subject right, copy over the darkened left. The
   photo fades into the page background before the plan cards start. Absolute
   inside #page so it scrolls away with the content. */
.payhero-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 290px;
  background: #0b0b0f url("../img/paywall-hero.webp") 44% 30% / cover no-repeat;
  /* Photo fades in when loaded (paywall.js adds .art-in via an Image
     preloader) - a sudden pop reads as broken; onerror reveals too, so a
     failed download degrades to the flat backdrop + scrim, never invisible. */
  opacity: 0;
  transition: opacity 0.6s ease;
  z-index: 0;
  pointer-events: none;
}
.payhero-bg.art-in { opacity: 1; }
.payhero-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0.52) 0%, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, 0.4) 62%, var(--bg) 93%),
    linear-gradient(90deg, rgba(0, 0, 0, 0.58) 0%, rgba(0, 0, 0, 0.14) 52%, rgba(0, 0, 0, 0) 72%);
}
.payhead { position: relative; z-index: 1; }
.paybrand {
  flex: 1;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 3px;
  text-transform: uppercase;
}
.premiumpill {
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.35);
  padding: 5px 10px;
  border-radius: 999px;
}
.payh1 {
  font-size: 38px;
  font-weight: 800;
  letter-spacing: -0.5px;
  line-height: 1.05;
  margin: 16px 0 12px;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.65);
}
.paysub.top { text-align: left; font-size: 13.5px; line-height: 1.5; color: rgba(255, 255, 255, 0.96); margin: 0 0 6px; max-width: 30ch; text-shadow: 0 1px 16px rgba(0, 0, 0, 0.65); }

/* Rating + trust row over the hero: laurel | 4.8 + five stars | laurel,
   divider, trusted-by blurb - everything gets a hard text shadow so it holds
   against the photo. */
.payrate { display: flex; align-items: center; gap: 9px; margin: 8px 0 2px; }
.prl { width: 19px; height: 27px; color: rgba(255, 255, 255, 0.95); display: flex; filter: drop-shadow(0 1px 6px rgba(0, 0, 0, 0.6)); }
.prl svg { width: 100%; height: 100%; }
.prl.flip { transform: scaleX(-1); }
.prscore { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.prscore b { font-size: 17px; font-weight: 800; line-height: 1; text-shadow: 0 1px 10px rgba(0, 0, 0, 0.65); }
.prstars { display: flex; gap: 1.5px; color: #fff; }
.prstars svg { width: 11px; height: 11px; filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.55)); }
.prdiv { width: 1px; height: 30px; background: rgba(255, 255, 255, 0.4); margin: 0 4px; flex-shrink: 0; }
.prtrust { font-size: 11px; line-height: 1.4; color: rgba(255, 255, 255, 0.95); text-shadow: 0 1px 10px rgba(0, 0, 0, 0.65); }

.payh2 { font-size: 17px; font-weight: 800; letter-spacing: 0.2px; margin: 24px 0 12px; }

/* Plan cards: full-bleed photo radio list (reference design). EVERY card
   shows its photo art IN COLOR - unselected cards are slightly dimmed, the
   selected card is full brightness and gains a solid white ring. The radio
   mark leads the plan name; lines indent to the name. The right column
   carries SAVE % / price / weekly comparison. Art lives in ::before
   (filtered), text scrim in ::after (unfiltered), content above both. */
.paycards { position: relative; }
.paycard {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  border-radius: 24px;
  background: #0c0c0e;
  border: 1.5px solid rgba(255, 255, 255, 0.32);
  padding: 16px;
  margin-top: 14px;
  min-height: 110px;
  text-align: left;
  cursor: pointer;
  /* NO transform transition/press-scale here: the user reads card squish as
     "scaley" - press feedback is opacity-only (button:active) on this sheet. */
  transition: border-color 0.25s ease;
}
.paycard::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  /* Card art DISABLED for now (header hero stays): re-enable by restoring the
     --art lines below and this background:
     background: var(--art) right var(--art-y, 0%) / auto 200% no-repeat;
     (2048x870 sources; the 200% zoom + right anchor shifted each face left of
     the price block - see git history). */
  filter: brightness(0.96) saturate(1);
  /* Art fades in when loaded (paywall.js adds .art-in via an Image
     preloader) - onerror reveals too, so a failed download just loses the
     photo, never the text legibility. */
  opacity: 0;
  transition: filter 0.3s ease, opacity 0.45s ease;
  pointer-events: none;
}
.paycard.art-in::before { opacity: 1; }
.paycard::after {
  /* text scrim - dark ONLY on the left where the copy sits; the photo stays
     clear on the right (reference design). */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.88) 0%, rgba(0, 0, 0, 0.55) 32%, rgba(0, 0, 0, 0.1) 60%, rgba(0, 0, 0, 0) 82%);
  pointer-events: none;
}
/* Card art sources - DISABLED for now (header hero stays). Restore together
   with the ::before background to bring the photos back.
.paycard[data-id="melodix.sub.weekly"] { --art: url("../img/card-weekly.webp"); --art-y: 25%; }
.paycard[data-id="melodix.sub.monthly"] { --art: url("../img/card-monthly.webp"); --art-y: 25%; }
.paycard[data-id="melodix.sub.yearly"] { --art: url("../img/card-yearly.webp"); --art-y: 25%; }
*/
/* Selected: full-brightness art + solid white ring + white-filled check */
.paycard.selected { border-color: #fff; background: #0c0c0e; }
.paycard.selected::before { filter: brightness(1.04) saturate(1.05); }
.paycard > * { position: relative; z-index: 1; }
.pc-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pc-name { display: flex; align-items: center; gap: 10px; font-size: 19px; font-weight: 800; letter-spacing: 0.2px; text-shadow: 0 1px 12px rgba(0, 0, 0, 0.65); }
.pcmark {
  display: inline-flex;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.9);
  color: transparent;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.pcmark svg { width: 12px; height: 12px; }
.paycard.selected .pcmark {
  border-color: #fff;
  background: #fff;
  color: #0b0b0f;
}
.pc-line { display: block; font-size: 13.5px; color: rgba(255, 255, 255, 0.97); margin-top: 13px; margin-left: 34px; text-shadow: 0 1px 9px rgba(0, 0, 0, 0.7); }
.pc-line.dim { color: rgba(255, 255, 255, 0.8); margin-top: 5px; }
.pcright { display: flex; flex-direction: column; align-items: flex-end; flex-shrink: 0; margin-left: 4px; }
.pcsave { font-size: 10.5px; font-weight: 800; letter-spacing: 0.9px; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 2px 10px rgba(0, 0, 0, 0.85); }
.pcnum { display: block; font-size: 25px; font-weight: 800; margin-top: 3px; letter-spacing: -0.3px; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 2px 8px rgba(0, 0, 0, 0.85), 0 4px 20px rgba(0, 0, 0, 0.8); }
.pcper { display: block; font-size: 11.5px; color: rgba(255, 255, 255, 0.9); margin-top: 3px; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 2px 10px rgba(0, 0, 0, 0.8); white-space: nowrap; }
/* MOST POPULAR: white pill with crown, overlapping the card's top edge */
.pcpop {
  position: absolute;
  top: -12px;
  right: 14px;
  display: flex;
  align-items: center;
  gap: 5px;
  background: #fff;
  color: #0b0b0f;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.9px;
  text-transform: uppercase;
  padding: 5px 11px;
  border-radius: 999px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}
.pcpop svg { width: 11px; height: 11px; }

/* One solid white Subscribe button under the cards (reference design) */
.paygo {
  width: 100%;
  margin-top: 16px;
  padding: 16px 20px;
  border-radius: 999px;
  background: #fff;
  color: #0b0b0f;
  font-size: 16px;
  font-weight: 800;
  transition: transform 0.16s cubic-bezier(0.34, 1.1, 0.64, 1);
}
.paygo:active { opacity: 0.75; }
.paygo:disabled { opacity: 0.6; }
.paycancel {
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  color: #fff;
  margin-top: 12px;
}
.paycancel .u { text-decoration: underline; text-underline-offset: 3px; }
.paybilling {
  margin-top: 16px;
  text-align: center;
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--text-2);
}
.paylegal {
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.paylegal:active { color: var(--text-2); }

.payh3 { font-size: 19px; font-weight: 800; margin: 34px 0 14px; }

/* Credit packs: borderless vertical rows, filled coin-stack icon on a soft
   square, price right - matching the premium reference (no chevron). */
.paypacklist { display: flex; flex-direction: column; gap: 10px; }
.paypackrow {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #151518;
  border: 0;
  border-radius: 16px;
  padding: 14px 16px;
  text-align: left;
  transition: transform 0.16s cubic-bezier(0.34, 1.1, 0.64, 1);
}
.paypackrow:active { opacity: 0.75; }
.paypackrow:disabled { opacity: 0.55; }

/* Rewarded-ad row (free credits): same row language as the packs, bolt icon. */
.payadcard {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #151518;
  border-radius: 16px;
  padding: 14px 16px;
}
.payadcard .pkcoin { background: linear-gradient(135deg, #7c3aed, #ec4899); }
.payadbtn {
  flex-shrink: 0;
  background: #fff;
  color: #000;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 10px 16px;
  border-radius: 11px;
  transition: opacity 0.15s ease;
}
.payadbtn:active { opacity: 0.75; }
.payadbtn:disabled { opacity: 0.4; }

/* Ad player: fullscreen black overlay (lives at #app - absolute, clips to the
   app column on desktop) with the Atlas-generated promo creative, countdown
   and claim button (appears when the ad completes). Opacity-only exit. */
.adhost {
  position: absolute;
  inset: 0;
  z-index: 60;
  background: #000;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity 0.28s ease, transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.adhost.open { opacity: 1; transform: scale(1); }
.adhost .adclose {
  position: absolute;
  top: calc(var(--safe-top) + 10px);
  right: 12px;
  z-index: 3;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
.adhost .adclose svg { width: 18px; height: 18px; }
.adhost .adcreative {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center 30%;
  background-color: #000;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.adhost.open .adcreative { opacity: 0.9; }
.adhost .adcreative::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.05) 40%, rgba(0, 0, 0, 0.8) 88%);
}
.adhost .adbrand {
  position: absolute;
  left: 22px;
  top: calc(var(--safe-top) + 74px);
  display: flex;
  align-items: center;
  gap: 10px;
  color: #fff;
  z-index: 2;
}
.adhost .adnote {
  width: 40px;
  height: 40px;
  border-radius: 13px;
  background: linear-gradient(135deg, #7c3aed, #ec4899);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.adhost .adnote svg { width: 20px; height: 20px; }
.adhost .adtag {
  font-size: 15px;
  font-weight: 800;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55);
  max-width: 260px;
  line-height: 1.3;
}
.adhost .adbottom {
  position: absolute;
  left: 22px;
  right: 22px;
  bottom: calc(var(--safe-bottom) + 22px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  z-index: 2;
}
.adhost .adtimer {
  font-size: 13px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.85);
  font-variant-numeric: tabular-nums;
}
.adhost .adtimer b { color: #fff; }
.adhost .adclaim {
  background: #fff;
  color: #000;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  padding: 14px 22px;
  border-radius: 14px;
  transition: opacity 0.15s ease;
}
.adhost .adclaim:disabled { opacity: 0.45; }
.adhost .adclaim:not(:disabled):active { opacity: 0.75; }
.pkcoin {
  width: 42px; height: 42px;
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #fff;
}
.pkcoin svg { width: 21px; height: 21px; }
.pkmain { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.pkc { font-size: 15px; font-weight: 800; }
.pks { font-size: 12px; color: var(--text-2); line-height: 1.35; }
.pkp { font-size: 15px; font-weight: 800; flex-shrink: 0; }

.payrestore {
  display: block;
  margin: 16px auto 0;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-2);
}
.payfine {
  margin-top: 20px;
  text-align: center;
  font-size: 10.5px;
  line-height: 1.7;
  color: var(--text-2);
}

