/* OBEINSON FREQUENCY X — now-playing row.
 *
 * Two jobs: make the station you are listening to obvious in the results
 * list, and lift it to the top so you never have to hunt for it.
 *
 * WHY THIS IS NOT IN dial-colors.css. That file's contract is colour only —
 * no width, height, margin, padding, grid or flex — so a vendor drop cannot
 * collide with it on layout. `order` is a grid/flex property, so it belongs
 * here instead of quietly breaking that promise.
 *
 * PIN TO TOP, AND BACK AGAIN. #qsList is a CSS grid, and grid items honour
 * `order`, so `order:-1` on the playing row floats it to the top. When the
 * listener picks a different station the app moves `.on` to that row, and
 * this rule follows it — the previous station drops back into its original
 * position on its own. No JS, no DOM reordering, nothing to keep in sync and
 * nothing to restore by hand. The row keeps its real index number, so a
 * station pinned from position 7 still reads "7".
 *
 * GREEN, NOT BLUE. The app ALREADY highlights the playing row — these three
 * selectors, with !important on every line:
 *
 *   html body .qsOverlay #qsList .qsRow.on,
 *   html body #qsList .qsRow.on,
 *   html body .qsRow.on { background-image:linear-gradient(...#3b8fd9...);
 *                         animation-name:onAirBlink ... }
 *
 * It works. The problem is that it is BLUE, in an app whose panels, buttons
 * and links are already blue, so the one row that should stand out is the
 * one colour that cannot. Green is the "live / active / ok" hue in this
 * app's role system and the one that reads instantly against this theme.
 *
 * The selectors below are copied from that rule deliberately. It sits at
 * (1,3,3) with !important, so a tidier selector loses no matter how many
 * !importants it carries; matching it exactly and loading later is what makes
 * these land. If a vendor update changes those selectors, change these.
 *
 * It also restores something that had been broken: `.qsRow.on b{color:#f2665c}`
 * was being overridden by the catalog's own `.qsRow .qsInfo b` colour rule in
 * dial-colors.css, which carries !important and more specificity. The playing
 * station's title had silently stopped changing colour at all.
 *
 * The pulse is deliberately slow (1.6s) and low-amplitude. A fast, hard flash
 * next to a list people read is an irritant, and the row also carries static
 * cues — tint, border, and a solid left bar — so the state is never carried by
 * motion alone. Anyone with Reduce Motion on gets those without the pulse.
 */

:root[data-theme="dark"] #qsList .qsRow.on {
  order: -1;
}

html body .qsOverlay #qsList .qsRow.on,
html body #qsList .qsRow.on,
html body .qsRow.on {
  /* Stops chosen so white text clears AA across the WHOLE gradient: 6.28:1,
     5.51:1, 4.79:1 left to right. The vendor's blue version of this row did
     not — white on its #3b8fd9/#5fb0ea/#8ec9f5 measures 3.43, 2.36 and 1.78:1,
     so the row everyone is meant to read was the least readable in the list.
     The vivid part of the signal is carried by the accents and the pulse,
     which can be bright without any text sitting on them. */
  background-image: linear-gradient(135deg, #0a7019 0%, #0b7a1b 55%, #0c851d 100%) !important;
  background-color: #0a7019 !important;
  border: 1px solid #00ff22 !important;
  animation-name: obnNowPulse !important;
  animation-duration: 1.6s !important;
  animation-timing-function: ease-in-out !important;
  animation-iteration-count: infinite !important;
}

/* The left bar is the static half of the signal: it does not depend on the
   animation running, so the row still reads as live with motion disabled. */
@keyframes obnNowPulse {
  0%, 100% { box-shadow: 0 0 0 2px rgba(0, 255, 34, .55), inset 4px 0 0 0 #00ff22;
             filter: brightness(1); }
  50%      { box-shadow: 0 0 0 7px rgba(0, 255, 34, .20), inset 4px 0 0 0 #00ff22;
             filter: brightness(1.16); }
}

/* On the green gradient the title must be light, not the catalog's cyan. */
html body .qsRow.on .qsInfo b,
html body #qsList .qsRow.on .qsInfo b {
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
}
html body .qsRow.on .qsMeta em,
html body .qsRow.on .qsMeta em.geo,
html body .qsRow.on .qsMeta em.br,
html body .qsRow.on .qsMeta em.routeBadge,
html body .qsRow.on .qsNum {
  color: #eafff0 !important;
  -webkit-text-fill-color: #eafff0 !important;
}

html body .qsRow.on .qsThumb {
  outline: 2px solid #00ff22 !important;
  outline-offset: 2px;
}

/* The vendor paints this button red and runs `flashred` on it. Dark ink on
   the bright green keeps it readable — the same reasoning polish.css records
   for accent buttons. */
html body .qsRow.on .qsPlay,
html body #qsList .qsRow.on .qsPlay {
  background: #00ff22 !important;
  border-color: #00ff22 !important;
  color: #07140a !important;
  animation: none !important;
}

/* Reduce Motion: polish.css already stills every animation in the app with
   the conventional blanket rule, so this is belt and braces rather than the
   only guard — but this file should not depend on another file's blanket to
   be accessible. The static cues stay. */
@media (prefers-reduced-motion: reduce) {
  html body .qsRow.on,
  html body #qsList .qsRow.on,
  html body .qsOverlay #qsList .qsRow.on {
    animation: none !important;
    box-shadow: 0 0 0 2px rgba(0, 255, 34, .55), inset 4px 0 0 0 #00ff22 !important;
    filter: none !important;
  }
}
