/* ============================================================================
 * VibeDial — "Studio Polish" layer (2026-07, build vd11)
 * ----------------------------------------------------------------------------
 * Loaded LAST, after vibedial.css and vibedial-redesign.css. Purely additive
 * visual refinement built on the existing token system (--c1/--c2/--c3,
 * --text/--muted, --radius*, --font-display). No structural/grid changes, so
 * it degrades cleanly to the base look if this one <link> is removed.
 *
 * Scope of this layer:
 *   1. Global finish — focus rings, selection, scrollbars, tap highlight
 *   2. Hero — living gradient wordmark + calmer aurora
 *   3. Station cards — branded art tile, play affordance, quieter meta,
 *      now-playing equalizer, keyboard focus, staggered entrance
 *   4. Lanes, search, transport — cohesive motion + lit states
 *   5. Accessibility — prefers-reduced-motion, prefers-contrast honored
 * ========================================================================= */

/* ---- 0. Tokens this layer adds ------------------------------------------ */
:root {
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --ease-spring: cubic-bezier(.34, 1.3, .5, 1);
  --focus-ring: 0 0 0 2px var(--bg-deep, #04050d), 0 0 0 4px color-mix(in srgb, var(--c1) 85%, transparent);
  --card-art: 52px;
}

/* ---- 1. Global finish --------------------------------------------------- */

/* One consistent, on-brand keyboard focus ring everywhere. Mouse users never
   see it (:focus-visible only), so it stays clean while being fully accessible. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
[tabindex]:focus-visible,
.station-card:focus-visible,
.genre:focus-visible,
.quickvibe:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}
.station-card:focus-visible { border-radius: var(--radius); }

/* Brand-tinted text selection instead of the browser default blue. */
::selection {
  background: color-mix(in srgb, var(--c2) 42%, transparent);
  color: var(--text);
}

/* Slim, themed scrollbars for the station list and any overflow area. */
.station-list,
.vibedock-body,
.genre-scroll {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--c1) 34%, transparent) transparent;
}
.station-list::-webkit-scrollbar,
.vibedock-body::-webkit-scrollbar { width: 10px; height: 10px; }
.station-list::-webkit-scrollbar-thumb,
.vibedock-body::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--c1) 30%, transparent);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: content-box;
}
.station-list::-webkit-scrollbar-thumb:hover,
.vibedock-body::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--c1) 55%, transparent);
  background-clip: content-box;
}

/* Kill the grey mobile tap-flash; we provide our own :active feedback. */
button, .station-card, .genre, .quickvibe, .tiny-pill, .mobile-dock-btn {
  -webkit-tap-highlight-color: transparent;
}

/* ---- 2. Hero: living gradient wordmark ---------------------------------- */
/* The landing wordmark gets a slow, luxurious brand-gradient sweep. Falls back
   to a static fill where background-clip:text isn't supported. */
body.landing-mode .station-title {
  background: linear-gradient(100deg, var(--c1), var(--c2) 42%, var(--c3) 72%, var(--c1));
  background-size: 240% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--c2);
  animation: vd-wordmark-sweep 14s ease-in-out infinite;
}
@keyframes vd-wordmark-sweep {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

/* ---- 3. Station cards --------------------------------------------------- */

.station-card {
  position: relative;
  gap: 14px;
  padding: 12px 14px;
  border-radius: 20px;
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--cardAccent, var(--c1)) 7%, transparent), transparent 60%),
    rgba(255, 255, 255, .028);
  will-change: transform;
}
.station-card:hover {
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--cardAccent, var(--c1)) 13%, transparent), transparent 62%),
    rgba(255, 255, 255, .05);
  box-shadow: 0 16px 44px rgba(0, 0, 0, .40);
}
.station-card:active { transform: translateY(-1px) scale(.995); }

/* Branded art tile. When the logo is just the ♫ glyph, it becomes a tactile
   gradient chip keyed to the card's own accent — a per-station color identity.
   Real logos (img) sit in the same frame with a crisp edge. */
.station-card .station-logo {
  flex: 0 0 var(--card-art);
  width: var(--card-art);
  height: var(--card-art);
  border-radius: 15px;
  display: grid;
  place-items: center;
  font-size: 20px;
  color: color-mix(in srgb, var(--cardAccent, var(--c1)) 90%, white);
  background:
    radial-gradient(120% 120% at 25% 20%, color-mix(in srgb, var(--cardAccent, var(--c1)) 42%, transparent), transparent 70%),
    linear-gradient(145deg, color-mix(in srgb, var(--cardAccent, var(--c1)) 22%, #121425), rgba(255,255,255,.03));
  border: 1px solid color-mix(in srgb, var(--cardAccent, var(--c1)) 34%, var(--line));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10);
  overflow: hidden;
  position: relative;
  transition: transform 200ms var(--ease-out), color 160ms ease, box-shadow 200ms ease;
}
.station-card .station-logo img { width: 100%; height: 100%; object-fit: cover; }

/* Concentric vinyl grooves drawn purely in CSS behind the glyph — subtle depth
   that reinforces the "record" identity without any image asset. */
.station-card .station-logo::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    repeating-radial-gradient(circle at 50% 50%,
      rgba(255, 255, 255, .05) 0 1px, transparent 1px 4px);
  opacity: .5;
  pointer-events: none;
}
.station-card:hover .station-logo { transform: scale(1.04) rotate(-1.5deg); }

/* Hover/focus reveals a play triangle over the art — a clear "this plays".
   Pure CSS, no injected element: an inset scrim darkens the tile, the ♫ glyph
   fades out (color→transparent), and the ::after draws a centered play glyph. */
.station-card:hover .station-logo,
.station-card:focus-visible .station-logo {
  color: transparent;
  box-shadow: inset 0 0 0 100px color-mix(in srgb, var(--bg-deep, #04050d) 42%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, .10);
}
.station-card .station-logo::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 0; height: 0;
  border-style: solid;
  border-width: 8px 0 8px 13px;
  border-color: transparent transparent transparent #fff;
  transform: translate(-40%, -50%) scale(.6);
  opacity: 0;
  transition: opacity 160ms ease, transform 220ms var(--ease-spring);
  z-index: 3;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .55));
}
.station-card:hover .station-logo::after,
.station-card:focus-visible .station-logo::after { opacity: 1; transform: translate(-40%, -50%) scale(1); }

.station-card .station-name {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  font-size: 1.02rem;
}

/* Quieter meta row: the shouty bold "Excellent" becomes a calm colored dot +
   label, format is de-emphasized, tags read as ghost pills. Density down,
   scannability up. */
.station-card .station-detail { gap: 6px 7px; margin-top: 3px; }
.station-card .tiny-pill {
  font-weight: 600;
  font-size: 11px;
  border-radius: 999px;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease, transform 120ms var(--ease-out);
}
.station-card .tiny-pill.provider,
.station-card .tiny-pill.format-pill {
  background: transparent;
  color: var(--muted);
  border: 1px solid transparent;
  padding-left: 4px; padding-right: 4px;
}
/* Quality → semantic colored dot. .intel carries good/warn/etc; we tint by a
   colored leading dot rather than a loud filled pill. */
.station-card .tiny-pill.intel {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  padding-left: 2px;
  gap: 5px;
  display: inline-flex;
  align-items: center;
}
.station-card .tiny-pill.intel::before {
  content: "";
  width: 7px; height: 7px; border-radius: 999px;
  background: var(--c1);
  box-shadow: 0 0 8px color-mix(in srgb, var(--c1) 80%, transparent);
}
.station-card .tiny-pill.intel.good::before { background: #56e0a0; box-shadow: 0 0 8px #56e0a088; }
.station-card .tiny-pill.intel.warn::before,
.station-card .tiny-pill.intel.fair::before { background: var(--c3); box-shadow: 0 0 8px color-mix(in srgb, var(--c3) 70%, transparent); }
.station-card .tiny-pill.intel.bad::before,
.station-card .tiny-pill.intel.poor::before { background: #ff6b6b; box-shadow: 0 0 8px #ff6b6b88; }

/* Tag + country chips: interactive ghost pills that light up on hover. */
.station-card .tiny-pill.tag-pill,
.station-card .tiny-pill.country-chip {
  background: color-mix(in srgb, var(--cardAccent, var(--c1)) 9%, rgba(255,255,255,.03));
  border: 1px solid color-mix(in srgb, var(--cardAccent, var(--c1)) 20%, var(--line));
  color: color-mix(in srgb, var(--text) 88%, transparent);
}
.station-card .tiny-pill.tag-pill:hover,
.station-card .tiny-pill.country-chip:hover {
  transform: translateY(-1px);
  background: color-mix(in srgb, var(--cardAccent, var(--c1)) 20%, transparent);
  border-color: color-mix(in srgb, var(--cardAccent, var(--c1)) 45%, var(--line));
  color: var(--text);
}

/* Score → a quiet ring badge. */
.station-card .score {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 11px;
  color: color-mix(in srgb, var(--text) 82%, transparent);
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(255,255,255,.03);
}

/* "Tap to play" action label — subtle, appears on hover/focus. */
.station-card .vd-card-action-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .01em;
  color: color-mix(in srgb, var(--cardAccent, var(--c1)) 75%, var(--text));
  opacity: 0;
  transform: translateX(4px);
  transition: opacity 160ms ease, transform 200ms var(--ease-out);
}
.station-card:hover .vd-card-action-label,
.station-card:focus-visible .vd-card-action-label { opacity: 1; transform: none; }

/* Favorite star: satisfying pop + brand-gold when active. */
.station-card .star { transition: transform 160ms var(--ease-spring), color 160ms ease; }
.station-card .star:hover { transform: scale(1.18); }
.station-card .star:active { transform: scale(.9); }
.station-card .star.is-active,
.station-card .star[aria-pressed="true"],
.station-card .star.active { color: var(--c3); filter: drop-shadow(0 0 6px color-mix(in srgb, var(--c3) 60%, transparent)); }

/* Now-playing: the active station card gets a lit edge + a live equalizer in
   its art tile. `.is-active`/`.playing`/`[aria-current]` cover the app's hooks. */
.station-card.is-active,
.station-card.is-playing,
.station-card[aria-current="true"] {
  border-color: color-mix(in srgb, var(--cardAccent, var(--c1)) 55%, var(--line));
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--cardAccent, var(--c1)) 18%, transparent), transparent 60%),
    rgba(255,255,255,.05);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--cardAccent, var(--c1)) 40%, transparent),
              0 14px 40px color-mix(in srgb, var(--cardAccent, var(--c1)) 22%, transparent);
}
.station-card.is-active .station-logo,
.station-card.is-playing .station-logo,
.station-card[aria-current="true"] .station-logo { position: relative; }

/* Active + playing: the lit edge gently "breathes" so the eye is drawn to the
   station that's actually on air. Pure animated box-shadow, no element needed.
   The hover play-triangle is suppressed on the active card (it's already on). */
.station-card.is-active.is-playing,
.station-card.is-playing[aria-current="true"] {
  animation: vd-nowplaying-breathe 3.2s ease-in-out infinite;
}
@keyframes vd-nowplaying-breathe {
  0%, 100% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--cardAccent, var(--c1)) 40%, transparent),
                          0 12px 34px color-mix(in srgb, var(--cardAccent, var(--c1)) 16%, transparent); }
  50%      { box-shadow: 0 0 0 1px color-mix(in srgb, var(--cardAccent, var(--c1)) 60%, transparent),
                          0 16px 46px color-mix(in srgb, var(--cardAccent, var(--c1)) 30%, transparent); }
}
.station-card.is-active .station-logo::after,
.station-card.is-playing .station-logo::after { opacity: 0 !important; }
.station-card.is-active .station-logo,
.station-card.is-playing .station-logo { color: color-mix(in srgb, var(--cardAccent, var(--c1)) 90%, white); }

/* Staggered entrance for freshly rendered cards (first ~10). Subtle rise+fade.
   Uses nth-child delays so no JS is required. */
@keyframes vd-card-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.station-list > .station-card {
  animation: vd-card-in .42s var(--ease-out) both;
}
.station-list > .station-card:nth-child(1) { animation-delay: .02s; }
.station-list > .station-card:nth-child(2) { animation-delay: .06s; }
.station-list > .station-card:nth-child(3) { animation-delay: .10s; }
.station-list > .station-card:nth-child(4) { animation-delay: .14s; }
.station-list > .station-card:nth-child(5) { animation-delay: .18s; }
.station-list > .station-card:nth-child(6) { animation-delay: .22s; }
.station-list > .station-card:nth-child(7) { animation-delay: .26s; }
.station-list > .station-card:nth-child(8) { animation-delay: .30s; }
.station-list > .station-card:nth-child(n+9) { animation-delay: .34s; }

/* ---- 4. Lanes, search, transport ---------------------------------------- */

/* Audio-lane chips: smoother, with a lit active pill and hover rise. */
.genre {
  transition: transform 150ms var(--ease-out), background 160ms ease, border-color 160ms ease, color 160ms ease;
}
.genre:hover { transform: translateY(-1px); }
.genre.active,
.genre.is-active,
.genre[aria-selected="true"] {
  background: linear-gradient(135deg, color-mix(in srgb, var(--c1) 26%, transparent), color-mix(in srgb, var(--c2) 22%, transparent));
  border-color: color-mix(in srgb, var(--c1) 45%, var(--line));
  color: var(--text);
}

/* Search field: a focus ring that blooms the brand color on the whole wrap. */
.search-input-wrap {
  transition: box-shadow 200ms ease, border-color 200ms ease;
  border-radius: var(--radius-pill);
}
.search-input-wrap:focus-within {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--c1) 30%, transparent);
}
#searchInput::placeholder { color: color-mix(in srgb, var(--muted) 85%, transparent); }

/* Search / filter icon buttons: gentle press. */
.searchbtn, .input-clear-btn {
  transition: transform 140ms var(--ease-out), filter 160ms ease;
}
.searchbtn:active { transform: scale(.94); }

/* ---- 5. Panels: faint noise texture for cinematic depth ----------------- */
/* An extremely subtle SVG grain reduces gradient banding and adds a premium,
   filmic finish. data-URI, no network. Sits above the panel bg, below content. */
.panel::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  opacity: .028;
  z-index: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Lift real content above the grain — but NEVER touch the now-playing art
   backdrop, which is position:absolute/inset:0 and must stay a full-panel wash.
   (Overriding its position collapsed it into a visible box around the turntable;
   the base stylesheet excludes it for exactly this reason.) */
.panel > *:not(.np-art-backdrop) { position: relative; z-index: 1; }

/* ---- 5b. Feather the now-playing art glow so it never hard-clips -------- */
/* The backdrop fills the whole player panel (position:absolute; inset:0) and
   the panel clips its rounded corners. Because the turntable sits in the left
   third, its colored glow reaches the panel's left edge and gets sliced off in
   a straight line. A soft radial mask centered on the disc fades the whole
   backdrop to transparent before it meets any edge, so the glow dissolves into
   the panel instead of being cut. Tuned to the disc's position, not the panel
   center. */
.panel.player .np-art-backdrop {
  /* closest-side sizes the fade to the NEAREST panel edge (the left one, since
     the disc sits in the left third), so the glow is a contained halo that
     reaches zero opacity before it can hit any edge — no straight-line clip. */
  -webkit-mask-image: radial-gradient(circle closest-side at 33% 47%, #000 46%, rgba(0,0,0,.35) 78%, transparent 96%);
          mask-image: radial-gradient(circle closest-side at 33% 47%, #000 46%, rgba(0,0,0,.35) 78%, transparent 96%);
}
/* On narrow/mobile layouts the disc is horizontally centered, so re-center. */
@media (max-width: 820px) {
  .panel.player .np-art-backdrop {
    -webkit-mask-image: radial-gradient(circle closest-side at 50% 34%, #000 46%, rgba(0,0,0,.35) 78%, transparent 96%);
            mask-image: radial-gradient(circle closest-side at 50% 34%, #000 46%, rgba(0,0,0,.35) 78%, transparent 96%);
  }
}

/* ---- 6. Accessibility --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  body.landing-mode .station-title { animation: none; }
  .station-list > .station-card { animation: none; }
  .station-card, .station-card .station-logo, .genre, .star, .searchbtn,
  .vd-card-action-label, .tag-pill, .country-chip { transition: none !important; }
}
@media (prefers-contrast: more) {
  .station-card .tiny-pill.provider,
  .station-card .tiny-pill.format-pill,
  .station-card .tiny-pill.intel { color: var(--text); }
  .station-card { border-color: var(--line-strong, rgba(255,255,255,.28)); }
}
