/* ============================================================
   Quran Mini — play-card.css
   Now-playing card + verse expand/collapse animation, driven by
   the HTMX swap lifecycle (see play-card.js):
     - .htmx-added    : card inserted, start state (hidden)
     - settle phase   : htmx removes .htmx-added → card transitions
                        to the visible base state
     - .htmx-swapping : card being swapped out (fading to hidden)
   The verse expands while it contains a card and collapses when
   the card enters its swapping (close) phase.

   On mobile (< 1024px) the card is additionally docked to the
   bottom of the viewport (above the sticky footer) — see the
   "Mobile dock" section at the end of this file.
   ============================================================ */

/* The verse hosts the card as its second grid row. */
.verse {
  display: grid;
  grid-template-rows: auto minmax(0, 0fr);
  row-gap: 0;
  align-items: start; /* content hugs the top; don't stretch items in their tracks */
  padding: 1rem 0.5rem;
  transition:
    background-color 0.25s ease,
    grid-template-rows 0.38s cubic-bezier(0.22, 1, 0.36, 1),
    row-gap 0.38s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Verse expands while it contains a card or bookmark notice. */
.verse:has(.now-playing-card),
.verse:has(.bookmark-notice) {
  background: var(--color-accent-soft);
  grid-template-rows: auto minmax(0, 1fr);
  row-gap: 12px;
  border-radius: 0.5rem;
}

/* Hide the border on the verse above the one with an open play card */
.verse:has(+ .verse .now-playing-card) {
  border-bottom: 0;
}

.verse:has(+ .verse .bookmark-notice) {
  border-bottom: 0;
}

/* Closing: as soon as the card enters its swapping (delete) phase,
   start collapsing the verse. The card still fades out on top. */
.verse:has(.now-playing-card.htmx-swapping) {
  background: transparent;
  grid-template-rows: auto minmax(0, 0fr);
  row-gap: 0;
}

.verse:has(.bookmark-notice.is-closing) {
  background: transparent;
  grid-template-rows: auto minmax(0, 0fr);
  row-gap: 0;
}

/* Hide the play button while the card is open, but reveal it as
   soon as the card enters its swapping (close) phase — matching
   reader.html where .is-playing is dropped before the card is
   removed, so the play icon reappears while the card fades out. */
.verse:has(.now-playing-card):not(:has(.now-playing-card.htmx-swapping))
  .verse-actions .icon-btn:last-child {
  display: none;
}

.now-playing-card {
  display: flex;
  align-items: center;
  gap: 12px;
  /*width: 100%;*/
  min-height: 0;
  overflow: hidden;
  background: var(--color-bg);
  border-radius: var(--radius-sm);
  outline: 1px solid var(--color-accent-outline);
  box-shadow: 0 2px 4px color-mix(
    in oklch,
    var(--color-accent) 18%,
    transparent
  );
  padding: 12px 14px;
  opacity: 1;
  translate: 0 0;
  transition:
    opacity 0.25s ease,
    translate 0.25s ease;
  margin: 0 0.5rem;
}

.bookmark-notice {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 0;
  overflow: hidden;
  background: var(--color-bg);
  border-radius: var(--radius-sm);
  outline: 1px solid var(--color-accent-outline);
  box-shadow: 0 2px 4px color-mix(in oklch, var(--color-accent) 18%, transparent);
  padding: 12px 14px;
  opacity: 0;
  translate: 0 6px;
  transition: opacity 0.25s ease, translate 0.25s ease;
}

.bookmark-notice.is-visible {
  opacity: 1;
  translate: 0 0;
}

.bookmark-notice.is-closing {
  opacity: 0;
  translate: 0 6px;
}

.bookmark-notice__icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  color: var(--color-accent);
}

.bookmark-notice__message {
  flex: 1 1 0;
  min-width: 0;
  color: var(--color-ink);
  font-size: 13px;
  font-weight: 600;
}

.bookmark-notice__action {
  color: var(--color-accent);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

/* Open: card inserted by htmx starts hidden, then settles visible. */
.now-playing-card.htmx-added {
  opacity: 0;
  translate: 0 6px;
}

/* Close: card is swapped out (delete) — fade it out while the
   swap delay elapses. */
.now-playing-card.htmx-swapping {
  opacity: 0;
  translate: 0 6px;
}

.now-playing-card__info {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 2px;
}

.now-playing-card__track {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-ink);
  white-space: nowrap;
}

.now-playing-card__time {
  font-size: 11.5px;
  color: var(--color-muted);
}

/* User-facing playback/metadata error, shown inside the card and
   hidden until play-card.js reveals it. */
.now-playing-card__error {
  font-size: 11.5px;
  line-height: 1.4;
  color: #b3261e;
  white-space: normal;
}

html[data-theme="dark"] .now-playing-card__error {
  color: #f2b8b5;
}

.now-playing-card__error[hidden] {
  display: none;
}

.now-playing-card .icon-audio-lines {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  color: var(--color-accent);
}

.verse:has(.now-playing-card) .now-playing-card .icon-audio-lines {
  animation: audio-pulse 1.4s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}

@keyframes audio-pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.55;
    transform: scale(1.18);
  }
}

.now-playing-card .icon-btn svg {
  width: 18px;
  height: 18px;
}

.now-playing-card .icon-pause {
  width: 20px;
  height: 20px;
  color: var(--color-accent);
}

.now-playing-card .icon-skip-forward {
  color: var(--color-faint);
}

@media (prefers-reduced-motion: reduce) {
  .now-playing-card,
  .bookmark-notice,
  .verse {
    transition: none;
  }

  .now-playing-card.htmx-added,
  .now-playing-card.htmx-swapping {
    opacity: 1;
    translate: 0 0;
  }

  .bookmark-notice {
    opacity: 1;
    translate: 0 0;
  }

  .now-playing-card .icon-audio-lines {
    animation: none;
  }
}

/* ============================================================
   Mobile dock (< 1024px)
   ------------------------------------------------------------
   The card stays in its HTMX-inserted DOM slot (last child of
   the active .verse) so every lifecycle selector above keeps
   working, but it is pulled out of flow and pinned to the bottom
   of the viewport, just above the sticky footer (which is left
   untouched at z-index: 10). While the card exists, .content
   gains matching bottom padding so the final verses can scroll
   clear of the dock. Desktop (>= 1024px) keeps the in-verse
   layout above.
   ============================================================ */
@media (max-width: 1023px) {
  /* Docked geometry:
     --now-playing-dock-offset : height of the sticky footer the
        dock must clear (progress-group = 1rem padding + 12px
        labels + 10px gap + 4px track + 1px border ≈ 4rem).
     --now-playing-dock-height : docked card height, with slack
        for a visible error line (see .now-playing-card__error). */
  :root {
    --now-playing-dock-offset: 4rem;
    --now-playing-dock-height: 4.75rem;
  }

  .now-playing-card {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(var(--now-playing-dock-offset) + env(safe-area-inset-bottom));
    z-index: 11; /* above the sticky footer layer (z-index: 10) */
    width: auto; /* let left/right + auto margins center the dock */
    margin-inline: auto;
    max-width: 640px; /* align with the footer__inner content column */
    margin: 0 1rem 0.5rem 1rem;
    box-shadow: 0 2px 24px color-mix( in oklch, var(--color-accent) 28%, transparent );
  }

  /* The card is out of flow now, so the verse must not expand a
     phantom second row; keep the active-verse highlight only. */
  .verse:has(.now-playing-card) {
    grid-template-rows: auto minmax(0, 0fr);
    row-gap: 0;
  }

  /* Reserve room below the content so the last verses scroll
     clear of the docked card. */
  body:has(.now-playing-card) .content {
    padding-bottom: calc(
      var(--now-playing-dock-height) +
      var(--now-playing-dock-offset) +
      env(safe-area-inset-bottom)
    );
  }
}
