/* The guest song board, after dark.
 *
 * Everything here is prefixed .sd- ("song desk") and only ever appears on the
 * pages a guest reaches by scanning the paper (and the DJ's screens beside
 * them). It's the storefront's pop look turned inside out: ink ground, cream
 * type, butter / pink / sky / cobalt for the things worth pressing, 2px borders
 * and hard offset shadows. What lives in this file rather than in Tailwind
 * classes is the movement: the equaliser in the header, the bouncing heart,
 * the sheen on the top three, the spinning record.
 *
 * Written for a phone in a dark room on venue wifi: no images, and every
 * animation short enough that it has finished before anyone has decided
 * whether they like it.
 */

/* ── The header's little equaliser ──────────────────────────────────────────
   Five chunky bars keeping time under the couple's names, one in each of the
   pop colours. The only thing on the page that moves on its own, so it's what
   says "this is live" without a word. */
.sd-eq {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 16px;
}
.sd-eq span {
  display: block;
  width: 4px;
  height: 100%;
  border-radius: 1px;
  background: var(--color-pop-butter);
  transform-origin: bottom;
  animation: sd-eq 1.1s ease-in-out infinite;
}
.sd-eq span:nth-child(2) { animation-duration: 0.78s; background: var(--color-pop-pink); }
.sd-eq span:nth-child(3) { animation-duration: 1.35s; background: var(--color-pop-sky); }
.sd-eq span:nth-child(4) { animation-duration: 0.92s; background: var(--color-pop-pink); }
.sd-eq span:nth-child(5) { animation-duration: 1.18s; }

@keyframes sd-eq {
  0%, 100% { transform: scaleY(0.32); }
  50%      { transform: scaleY(1); }
}

/* ── Album art ──────────────────────────────────────────────────────────────
   A square with a 2px rim and a hard shadow — and, when the guest typed the
   song in by hand rather than tapping a suggestion, a quaver on a tinted plate
   at the same size, so a queue of mixed rows still lines up. */
.sd-art {
  position: relative;
  flex: none;
  overflow: hidden;
  border: 2px solid var(--color-pop-cream);
  border-radius: 12px;
  background: var(--color-pop-cobalt);
  box-shadow: 3px 3px 0 #000;
}
/* The picture sits over the quaver rather than replacing it, so removing a
   failed one uncovers the stand-in with nothing to re-layout. */
.sd-art img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--color-pop-cobalt);
}
.sd-art-blank {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--color-pop-cream);
}

/* ── The vote button ────────────────────────────────────────────────────────
   One thumb-sized target: the heart and the count. Voted is filled butter;
   not voted is an outline on the dark panel. Both press down into their
   shadow, like a real button. */
.sd-vote {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  flex: none;
  min-width: 3.6rem;
  min-height: 3.6rem;
  padding: 0.5rem 0.55rem;
  border: 2px solid var(--color-pop-cream);
  border-radius: 14px;
  background: #262626;
  color: var(--color-pop-cream);
  font-family: var(--font-pop);
  box-shadow: 3px 3px 0 #000;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.1s ease, box-shadow 0.1s ease, background 0.16s ease;
}
.sd-vote:hover { background: #303030; }
.sd-vote:active { transform: translate(3px, 3px); box-shadow: 0 0 0 #000; }
.sd-vote:focus-visible { outline: 3px solid var(--color-pop-sky); outline-offset: 3px; }
.sd-vote.is-mine {
  border-color: var(--color-pop-ink);
  background: var(--color-pop-butter);
  color: var(--color-pop-ink);
  box-shadow: 3px 3px 0 var(--color-pop-pink);
}
.sd-vote.is-mine:active { box-shadow: 0 0 0 var(--color-pop-pink); }
.sd-vote-heart { font-size: 1.2rem; line-height: 1; }
.sd-vote-count { font-size: 0.95rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }

/* On the bright top-three cards the unvoted button flips to white-on-ink, so
   it reads as a button rather than a hole in the card. */
.sd-top .sd-vote:not(.is-mine) {
  border-color: var(--color-pop-ink);
  background: #fff;
  color: var(--color-pop-ink);
  box-shadow: 3px 3px 0 var(--color-pop-ink);
}
.sd-top .sd-vote.is-mine { box-shadow: 3px 3px 0 var(--color-pop-ink); }
.sd-top .sd-vote:active { box-shadow: 0 0 0 var(--color-pop-ink); }

/* The bounce. Played once, on the button that was just tapped and on nothing
   else — the server marks that one row (see SongRequestsController#respond_with_board),
   so the ten-second refresh never sets a screenful of hearts jumping. */
.sd-vote.is-popped .sd-vote-heart {
  animation: sd-pop 0.5s cubic-bezier(0.3, 1.6, 0.5, 1);
}
.sd-vote.is-popped::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 16px;
  border: 3px solid var(--color-pop-pink);
  animation: sd-ring 0.5s ease-out forwards;
  pointer-events: none;
}

@keyframes sd-pop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.55) rotate(-8deg); }
  60%  { transform: scale(0.88) rotate(4deg); }
  100% { transform: scale(1) rotate(0); }
}
@keyframes sd-ring {
  0%   { opacity: 0.9; transform: scale(1); }
  100% { opacity: 0;   transform: scale(1.5); }
}

/* A song that has just joined the list slides in rather than appearing, so the
   guest who asked for it can see which one is theirs. */
.sd-row.is-new { animation: sd-in 0.4s ease-out; }

@keyframes sd-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ── The top three ──────────────────────────────────────────────────────────
   Bright cards on the dark page — butter, pink, sky — with a faint sheen that
   passes over now and then, so the chart reads as the prize it is. */
.sd-top {
  position: relative;
  overflow: hidden;
  border: 2px solid var(--color-pop-ink);
  background: var(--color-pop-butter);
  color: var(--color-pop-ink);
  box-shadow: 5px 5px 0 var(--color-pop-cream);
}
.sd-top:nth-child(2) { background: var(--color-pop-pink); }
.sd-top:nth-child(3) { background: var(--color-pop-sky); }
.sd-top .sd-art { border-color: var(--color-pop-ink); box-shadow: 3px 3px 0 var(--color-pop-ink); }
.sd-top::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgb(255 255 255 / 0.35) 50%, transparent 65%);
  transform: translateX(-100%);
  animation: sd-sheen 6.5s ease-in-out infinite;
  pointer-events: none;
}

@keyframes sd-sheen {
  0%, 85%  { transform: translateX(-100%); }
  100%     { transform: translateX(100%); }
}

/* ── The empty list ─────────────────────────────────────────────────────────
   The record spins until somebody puts something on it. */
.sd-disc {
  animation: sd-spin 7s linear infinite;
}

@keyframes sd-spin {
  to { transform: rotate(360deg); }
}

/* Somebody who has asked not to be moved at gets a still page. Every animation
   here is decoration — nothing is the only way anything is said. */
@media (prefers-reduced-motion: reduce) {
  .sd-eq span,
  .sd-top::before,
  .sd-disc,
  .sd-row.is-new,
  .sd-vote.is-popped .sd-vote-heart,
  .sd-vote.is-popped::after {
    animation: none;
  }
}

/* ── The search suggestions ─────────────────────────────────────────────────
   Apple's catalogue, dropped under the song box. Dark, with the sleeve big
   enough to recognise a record by. The rows are built in song_search_controller
   with font-body / font-ui on them; the type is set here instead. */
.sd-suggest {
  position: absolute;
  inset-inline: 0;
  top: 100%;
  z-index: 30;
  margin-top: 0.5rem;
  max-height: 19rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0.35rem;
  border: 2px solid var(--color-pop-cream);
  border-radius: 16px;
  background: #1c1c1c;
  box-shadow: 6px 6px 0 #000;
}
.sd-suggest li {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.45rem;
  border: 2px solid transparent;
  border-radius: 12px;
  cursor: pointer;
}
.sd-suggest li[aria-selected="true"] {
  border-color: var(--color-pop-ink);
  background: var(--color-pop-butter);
}
.sd-suggest img,
.sd-suggest .sd-suggest-blank {
  width: 2.9rem;
  height: 2.9rem;
  flex: none;
  border: 2px solid var(--color-pop-cream);
  border-radius: 10px;
  object-fit: cover;
  background: var(--color-pop-cobalt);
}
.sd-suggest .sd-suggest-blank {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-pop-cream);
}
.sd-suggest-song {
  display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-pop);
  font-weight: 700;
  color: var(--color-pop-cream);
}
.sd-suggest-artist {
  display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-label);
  font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgb(255 246 229 / 0.6);
}
.sd-suggest li[aria-selected="true"] .sd-suggest-song,
.sd-suggest li[aria-selected="true"] .sd-suggest-artist { color: var(--color-pop-ink); }
.sd-suggest li[aria-selected="true"] img,
.sd-suggest li[aria-selected="true"] .sd-suggest-blank { border-color: var(--color-pop-ink); }
