/* Now-playing radio shown on every page (see static/scripts/radio.js).
   The widget lives outside <body> so page styles and the body fade-in
   can't trap or restyle it, and so it survives page swaps. */

#radio-root {
  --text-color: #111111;
  --subtext-color: #666666;

  font-family: 'Poppins', sans-serif;
  line-height: 1.8;
  color: #111111;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

#radio-root *,
#radio-root *::before,
#radio-root *::after {
  box-sizing: border-box;
}

/* The /radio page is the radio itself; the floating card steps aside there. */
#radio-root.on-radio-page .radio-wrapper {
  display: none;
}

/* Hidden until there's a song to show. */
.radio-wrapper.pending {
  visibility: hidden;
}

/* First colors on a page are applied without the fade (see radio.js). */
#radio-root.instant .radio,
#radio-root.instant .radio *,
#radio-root.instant .radio-handle::before {
  transition: none !important;
}

/* Where the card would cover the page's text, leave room at the bottom
   so the end of the page can scroll clear of it. */
@media (max-width: 1440px) {
  body {
    padding-bottom: calc(var(--radio-height, 0px) + 48px) !important;
  }
}


.radio-wrapper {
  position: fixed !important;
  top: auto !important;
  left: auto !important;
  right: 32px !important;
  bottom: 32px !important;
  width: 340px;
  z-index: 999;
  margin: 0;
}

/* Card colors follow the current cover (set from JS).
   Registered so they can fade smoothly between songs. */
@property --radio-a { syntax: "<color>"; inherits: true; initial-value: #e4e4e8; }
@property --radio-b { syntax: "<color>"; inherits: true; initial-value: #d2d2d7; }
@property --radio-text { syntax: "<color>"; inherits: true; initial-value: #111111; }
@property --radio-sub { syntax: "<color>"; inherits: true; initial-value: #666666; }
@property --radio-c { syntax: "<color>"; inherits: true; initial-value: #d2d2d7; }

.radio {
  --radio-a: #e4e4e8;
  --radio-b: #d2d2d7;
  --radio-text: #111111;
  --radio-sub: #666666;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: 100%;
  padding: 12px;
  box-sizing: border-box;
  border-radius: 14px;
  color: var(--radio-text);
  background: linear-gradient(
    145deg,
    color-mix(in srgb, var(--radio-a) 92%, transparent),
    color-mix(in srgb, var(--radio-b) 92%, transparent)
  );
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: --radio-a 1.2s ease, --radio-b 1.2s ease, --radio-c 1.2s ease, --radio-text 0.8s ease, --radio-sub 0.8s ease;
}

/* Two soft blobs of the cover's colors drifting behind the content.
   They're blurred circles, so they have no edges to show, and they only
   translate (no rotation), so they never swing out of the card. */
.radio::before,
.radio::after {
  content: "";
  position: absolute;
  z-index: -1;
  width: 85%;
  aspect-ratio: 1;
  border-radius: 50%;
  filter: blur(42px);
  opacity: 0.75;
  pointer-events: none;
  will-change: transform;
}

.radio::before {
  top: -35%;
  left: -25%;
  background: color-mix(in srgb, var(--radio-a) 75%, white);
  animation: blobDriftA 17s ease-in-out infinite alternate;
}

.radio::after {
  right: -30%;
  bottom: -40%;
  background: var(--radio-c, var(--radio-b));
  animation: blobDriftB 21s ease-in-out infinite alternate;
}

@keyframes blobDriftA {
  0% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(28%, 18%, 0) scale(1.15); }
  100% { transform: translate3d(8%, 34%, 0) scale(0.95); }
}

@keyframes blobDriftB {
  0% { transform: translate3d(0, 0, 0) scale(1.05); }
  50% { transform: translate3d(-24%, -20%, 0) scale(0.9); }
  100% { transform: translate3d(-10%, -32%, 0) scale(1.1); }
}

/* The heading reads as a section title on the home page; elsewhere it would
   float over the page's text, so only the card is shown. */
#radio-root:not(.on-home) .radio-wrapper > h1 {
  display: none;
}

/* The "radio" heading, spaced from the card like "home" and its tabs.
   Fully specified because each page styles h1 differently. */
.radio-wrapper > h1 {
  margin: 0 0 1.25rem;
  font-family: 'Poppins', sans-serif;
  font-size: clamp(1.75rem, 5vw, 2.25rem);
  font-weight: 500;
  line-height: 1.25;
  text-transform: lowercase;
  color: #111111;
}

.radio-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.radio-track {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 8px;
  min-width: 0;
  box-sizing: border-box;
}

.radio-track.current {
  padding: 6px;
  opacity: 1;
}

.radio-track:not(.current) {
  opacity: 0.55;
}

.radio-track:nth-child(3) {
  opacity: 0.45;
}

.radio-track:nth-child(4) {
  opacity: 0.38;
}

.radio-track:nth-child(5) {
  opacity: 0.32;
}

.radio-cover {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: 8px;
  object-fit: cover;
  background: #bcbcc0;
}

.radio-track.current .radio-cover {
  width: 52px;
  height: 52px;
  border-radius: 8px;
}

/* Play/pause at the end of the current song's row: just the icon, no
   circle behind it (the button keeps a comfortable tap area). */
.radio-play {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  color: var(--radio-text);
  background: none;
  opacity: 0.9;
  transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}

.radio-play[hidden] {
  display: none;
}

.radio-play:hover {
  opacity: 1;
  transform: scale(1.1);
}

.radio-play:active {
  transform: scale(0.93);
}

.radio-play:focus-visible {
  outline: 2px solid var(--radio-text);
  outline-offset: 2px;
}

.radio-play svg {
  width: 22px;
  height: 22px;
}

.radio-play .icon-play {
  margin-left: 2px; /* optical centering of the triangle */
}

/* Shows play, or pause while the song is playing. */
.radio-play .icon-pause,
.radio-play.playing .icon-play {
  display: none;
}

.radio-play.playing .icon-pause {
  display: block;
}

.radio-play.loading svg {
  animation: playWait 0.8s ease-in-out infinite alternate;
}

@keyframes playWait {
  from { opacity: 0.45; }
  to { opacity: 1; }
}

.radio-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.radio-name {
  font-size: 0.9rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.radio-track.current .radio-name {
  font-size: 1rem;
}

.radio-artist {
  font-size: 0.75rem;
  color: var(--radio-sub);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.radio-track.current .radio-artist {
  font-size: 0.8rem;
}

/* LYRICS */

.radio-lyrics {
  margin-top: 10px;
  /* Plays each time the lyrics appear (they stay hidden until ready). */
  animation: radioLyricsIn 0.5s ease both;
}

@keyframes radioLyricsIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.radio-lyrics[hidden],
.radio-lyrics [hidden] {
  display: none !important;
}

/* A window onto the scrolling column of lines, fading out at the edges. */
.lyrics-viewport {
  position: relative;
  height: 8.4rem;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 24%, #000 76%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 24%, #000 76%, transparent 100%);
}

.lyrics-track {
  will-change: transform;
  transition: transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
}

.lyric {
  margin: 0;
  padding: 3px 0;
  font-size: 1.05rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--radio-text);
  opacity: 0.22;
  filter: blur(1.4px);
  /* Lines only ever move up and down, as one column (no resizing), so
     nothing looks like it's shifting around; they just light up. */
  transition:
    opacity 0.55s ease,
    filter 0.55s ease;
}

.lyric.near {
  opacity: 0.45;
  filter: blur(0.5px);
}

.lyric.active {
  opacity: 1;
  filter: none;
}

/* Scrolling through the lyrics: the column follows the wheel or finger
   closely, and every line is lit enough to read. */
.radio-lyrics.browsing .lyrics-track {
  transition: transform 0.18s ease-out;
}

.radio-lyrics.browsing .lyric:not(.active) {
  opacity: 0.6;
  filter: none;
}

/* Replaying a song: click a line to jump to it. */
.radio-lyrics.seekable .lyric {
  cursor: pointer;
}

.radio-lyrics.seekable .lyric:not(.active):hover {
  opacity: 0.85;
  filter: none;
}

/* Word-by-word lines (test page): each syllable is see-through text showing
   a gradient clipped to its letters. The gradient's soft edge slides across
   as the syllable is sung, set by --wipe (0 to 1) from radio.js. The idea
   comes from YouLyPlus. */
.lyric-row {
  display: block;
}

.lyric-row.bg {
  margin-top: 1px;
  font-size: 0.72em;
  font-weight: 500;
}

.lyric-word {
  display: inline-block;
  white-space: nowrap;
}

.syl {
  --wipe: 0;
  --lyric-lit: var(--radio-text);
  --lyric-dim: color-mix(in srgb, var(--radio-text) 35%, transparent);
  --lyric-edge: 0.6em;

  display: inline-block;
  /* Room for glyph edges to be painted, without moving the text. */
  padding: 0.1em 0;
  margin: -0.1em 0;
  color: transparent;
  background-color: var(--lyric-lit);
  -webkit-background-clip: text;
  background-clip: text;
  font-variant-ligatures: none;
  transition: filter 0.6s ease;
}

/* Only the line being sung shows the wipe; the rest look like plain lines. */
.lyric.words.active .syl {
  background-color: transparent;
  background-image: linear-gradient(
    90deg,
    var(--lyric-lit) calc(var(--wipe) * (100% + var(--lyric-edge)) - var(--lyric-edge)),
    var(--lyric-dim) calc(var(--wipe) * (100% + var(--lyric-edge)))
  );
}

/* Long held notes glow while they last (a glow only, nothing moves). */
.lyric.words.active .syl.held.singing {
  filter: drop-shadow(0 0 0.3em color-mix(in srgb, var(--radio-text) 55%, transparent));
  transition: filter 0.8s ease;
}

.lyric-note {
  font-size: 0.75rem;
  color: var(--radio-sub);
}

@media (prefers-reduced-motion: reduce) {
  .radio::before,
  .radio::after,
  .radio-play.loading svg,
  .radio-lyrics {
    animation: none;
  }

  .lyrics-track,
  .lyric,
  .syl {
    transition: none;
  }

}

/* Hidden YouTube player that plays the current song's audio. */
.yt-audio {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
}

/* On smaller screens, keep it in the bottom-right
   but make it smaller rather than moving it into
   the page content. */

@media (max-width: 750px) {
  .radio-wrapper {
    right: 16px !important;
    bottom: 16px !important;
    width: 280px;
  }

  .radio {
    padding: 10px;
  }
}

/* ---------- desktop: hide to just the cover ----------
   A small badge on the card's corner (shown on hover) folds it down to a
   cover thumbnail in the same spot; clicking that brings it back. */

.radio-hide,
.radio-mini {
  display: none;
}

.radio-frame {
  position: relative;
}

@media (min-width: 641px) {
  /* Folded down, only the thumbnail takes clicks; the rest of the card's
     spot lets them through to the page. */
  .radio-wrapper.minimized {
    pointer-events: none;
  }

  .radio-wrapper.minimized .radio-mini {
    pointer-events: auto;
  }

  .radio {
    transform-origin: bottom right;
    transition:
      --radio-a 1.2s ease, --radio-b 1.2s ease, --radio-c 1.2s ease,
      --radio-text 0.8s ease, --radio-sub 0.8s ease,
      opacity 0.25s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
      visibility 0s;
  }

  .radio-wrapper > h1 {
    transition: opacity 0.25s ease;
  }

  .radio-hide {
    display: grid;
    place-items: center;
    position: absolute;
    top: -9px;
    right: -9px;
    z-index: 1;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: #3c3c43;
    background: rgba(255, 255, 255, 0.95);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.16);
    cursor: pointer;
    opacity: 0;
    transform: scale(0.8);
    transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.22, 1, 0.36, 1), color 0.2s ease;
  }

  .radio-hide svg {
    width: 14px;
    height: 14px;
  }

  .radio-wrapper:hover .radio-hide,
  .radio-hide:focus-visible {
    opacity: 1;
    transform: scale(1);
  }

  .radio-hide:hover {
    color: #111111;
  }

  .radio-hide:focus-visible,
  .radio-mini:focus-visible {
    outline: 2px solid rgba(60, 60, 67, 0.6);
    outline-offset: 2px;
  }

  .radio-mini {
    display: block;
    position: absolute;
    right: 0;
    bottom: 0;
    width: 52px;
    height: 52px;
    padding: 0;
    border: 0;
    border-radius: 12px;
    background: var(--radio-mini-cover, none) center / cover, var(--radio-handle, #d2d2d7);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: scale(0.6);
    transform-origin: bottom right;
    transition:
      opacity 0.2s ease, transform 0.3s cubic-bezier(0.22, 1, 0.36, 1),
      box-shadow 0.3s ease, visibility 0s 0.3s;
  }

  /* While a song is playing, a ring in the cover's color breathes around it. */
  .radio-wrapper.is-playing .radio-mini {
    animation: radioMiniPulse 2.4s ease-in-out infinite;
  }

  @keyframes radioMiniPulse {
    0%, 100% { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18), 0 0 0 0 var(--radio-handle, #d2d2d7); }
    50% { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18), 0 0 0 4px var(--radio-handle, #d2d2d7); }
  }

  .radio-wrapper.minimized .radio,
  .radio-wrapper.minimized .radio-hide,
  .radio-wrapper.minimized > h1 {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }

  .radio-wrapper.minimized .radio {
    transform: scale(0.85);
    transition:
      --radio-a 1.2s ease, --radio-b 1.2s ease, --radio-c 1.2s ease,
      --radio-text 0.8s ease, --radio-sub 0.8s ease,
      opacity 0.2s ease, transform 0.3s cubic-bezier(0.22, 1, 0.36, 1),
      visibility 0s 0.3s;
  }

  .radio-wrapper.minimized .radio-mini {
    opacity: 1;
    visibility: visible;
    transform: scale(1);
    transition:
      opacity 0.25s ease 0.08s, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1) 0.08s,
      box-shadow 0.3s ease, visibility 0s;
  }

  .radio-wrapper.minimized .radio-mini:hover {
    transform: scale(1.06);
  }
}

@media (min-width: 641px) and (prefers-reduced-motion: reduce) {
  .radio-wrapper.is-playing .radio-mini {
    animation: none;
  }
}

.radio-handle {
  display: none;
}

/* Phones: a compact floating card (cover, title, play) with a grab handle
   above it. Swipe up to reveal the lyrics, down to fold them away, and down
   again to tuck the card off screen with just the handle left showing. */
@media (max-width: 640px) {
  .radio-wrapper {
    left: 12px !important;
    right: 12px !important;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important;
    width: auto;
    max-width: none;
    transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
    /* Vertical drags move the card instead of scrolling the page. */
    touch-action: none;
  }

  .radio-wrapper.dragging {
    transition: none;
  }

  /* Tucked away: the card sits just below the screen, handle still visible. */
  .radio-wrapper.collapsed {
    transform: translateY(calc(100% + 12px));
  }

  .radio-wrapper > h1 {
    display: none !important;
  }

  .radio {
    border-radius: 14px;
    padding: 12px 14px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.14);
  }

  /* Grab handle floating just above the card. */
  .radio-handle {
    display: block;
    position: absolute;
    top: -24px;
    left: 50%;
    width: 72px;
    height: 24px;
    margin-left: -36px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
  }

  .radio-handle::before {
    content: "";
    position: absolute;
    bottom: 7px;
    left: 50%;
    width: 38px;
    height: 5px;
    margin-left: -19px;
    border-radius: 3px;
    /* Same color as the card (set from the cover in radio.js). */
    background: var(--radio-handle, #d2d2d7);
    /* White halo keeps it readable over page text; the faint ring and
       shadow keep light colors visible on a white page. */
    box-shadow:
      0 0 0 2.5px rgba(255, 255, 255, 0.92),
      0 0 0 3.5px rgba(0, 0, 0, 0.06),
      0 1px 6px rgba(0, 0, 0, 0.15);
    transition: background-color 1.2s ease, filter 0.2s ease;
  }

  .radio-handle:active::before {
    filter: brightness(0.85);
  }

  .radio-handle:focus-visible {
    outline: 2px solid rgba(60, 60, 67, 0.6);
    outline-offset: -2px;
    border-radius: 12px;
  }

  /* Lyrics fold out above the song when the card is swiped up. */
  .radio-lyrics {
    max-height: 0;
    margin-top: 0;
    opacity: 0;
    overflow: hidden;
    transition:
      max-height 0.45s cubic-bezier(0.22, 1, 0.36, 1),
      margin-top 0.45s cubic-bezier(0.22, 1, 0.36, 1),
      opacity 0.3s ease;
  }

  .radio-wrapper.expanded .radio-lyrics {
    max-height: 10rem;
    margin-top: 10px;
    opacity: 1;
  }

  .radio-track.current {
    padding: 0;
    gap: 10px;
  }

  .radio-track.current .radio-cover {
    width: 40px;
    height: 40px;
    border-radius: 8px;
  }

  .radio-track.current .radio-name {
    font-size: 0.9rem;
  }

  .radio-track.current .radio-artist {
    font-size: 0.75rem;
  }

  .radio-play {
    width: 36px;
    height: 36px;
  }
}

@media (max-width: 640px) and (prefers-reduced-motion: reduce) {
  .radio-wrapper,
  .radio-lyrics {
    transition: none;
  }
}

/* The card opens the /radio page (anywhere on it but the play button). */
#radio-root:not(.on-radio-page) .radio,
#radio-root:not(.on-radio-page) .radio-track {
  cursor: pointer;
}
