/* ==========================================================================
   Power Star Radio
   Layout model
   - .app-shell is a 2-row grid: topbar, then stage. Nothing is absolutely
     positioned against magic viewport numbers.
   - Wide layout  : portrait fills the left, card + quote stack in a right column.
   - Compact layout: portrait is the full background, card sits at the bottom.
     Used for narrow screens AND for portrait-orientation tablets, where the
     side-by-side split does not have room to work.
   ========================================================================== */

:root {
  --bg: #080808;
  --line: rgba(255, 255, 255, .15);
  --line-soft: rgba(255, 255, 255, .07);
  --text: #f5f5f2;
  --text-2: #bdbdb8;
  --muted: #8b8b86;
  --accent: #ff941f;
  --shadow: 0 28px 80px rgba(0, 0, 0, .5);

  --gutter: clamp(18px, 3.3vw, 56px);
  --card-radius: 26px;

  /* Vertical rhythm inside the player card. */
  --card-gap: clamp(16px, 2.2vh, 26px);
}

* { box-sizing: border-box; }

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  /* The design is viewport-locked; the stage scrolls internally if it must. */
  overflow: hidden;
}

body {
  font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

button, input { font: inherit; color: inherit; }

:where(button, [href], input, summary):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}

.app-shell {
  position: relative;
  display: grid;
  /* minmax(0,…) — an `auto` track would grow to the topbar's min-content
     width and drag the whole layout wider than the viewport on small phones. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  isolation: isolate;
  background: var(--bg);
}

/* ---------------------------------------------------------------- portrait */

/* Colour powder blast — painted by powder.js.
   It sits in FRONT of the portrait and screens onto it, so the pigment reads
   as dust hanging in the air rather than a backdrop he is pasted over. It
   stays behind the topbar and card, which keeps all UI text unaffected.
   The mask thins the powder over his face so the portrait stays readable. */
.powder-layer {
  position: absolute;
  inset: 0;
  z-index: -3;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
  mix-blend-mode: screen;
  -webkit-mask-image: radial-gradient(88% 74% at 32% 46%, rgba(0, 0, 0, .04) 0 28%, rgba(0, 0, 0, .42) 58%, #000 92%);
  mask-image: radial-gradient(88% 74% at 32% 46%, rgba(0, 0, 0, .04) 0 28%, rgba(0, 0, 0, .42) 58%, #000 92%);
  /* Painted one frame after load; fades in rather than popping. */
  opacity: 0;
  transition: opacity .9s ease;
}

/* Transparent: the powder layer below is the backdrop now. */
.portrait-layer { position: absolute; inset: 0; z-index: -4; }

/* The image lives on ::before so it can be `cover`-sized inside a box narrower
   than the viewport. `cover` guarantees it always fills that box, so the hard
   letterbox seams the old `auto`-sized background produced cannot come back. */
.portrait-layer::before {
  content: "";
  position: absolute;
  inset: 0;

  width: 110%;

  background-image: url("./assets/img/portrait-wide.png");
  /* `cover`, not `100% auto`. With `100% auto` the image height is driven by
     the box WIDTH, so any viewport narrower/taller than ~1.6:1 left a hard
     black edge under the image. `cover` is identical wherever the box is wide
     enough (so the wide-screen framing is unchanged) and only kicks in to fill
     the gap where the old value fell short. Inherited by the compact and
     landscape rules below, which override image/position but not size. */
  background-size: cover;
  /* Lengths, not percentages: the image is wider than its box, so percentage
     positioning runs backwards here (higher % pulls it left). */
  background-position: 10% 0%;
  background-repeat: no-repeat;

  filter: saturate(.92) contrast(1.03);

  -webkit-mask-image: none;
  mask-image: none;
}

.portrait-layer::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;

  background:
    linear-gradient(
      0deg,
      rgba(8, 8, 8, .20),
      rgba(8, 8, 8, 0) 34%
    );
}

.grain {
  position: absolute; inset: 0; z-index: 10;
  opacity: .1; pointer-events: none; mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.48'/%3E%3C/svg%3E");
}

/* ----------------------------------------------------------------- topbar */

.topbar {
  position: relative;
  z-index: 12;
  /* Three tracks so the live badge centres on the viewport rather than on
     whatever space is left between the brand and the buttons. */
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding:
    calc(clamp(18px, 3vh, 40px) + env(safe-area-inset-top))
    calc(var(--gutter) + env(safe-area-inset-right))
    0
    calc(var(--gutter) + env(safe-area-inset-left));
}

/* Softens the portrait directly under the header so the wordmark stays
   legible against hair detail. */
.topbar::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 220px;
  z-index: -1;
  background: linear-gradient(180deg, rgba(6, 6, 6, .5), rgba(6, 6, 6, .18) 55%, rgba(6, 6, 6, 0));
  pointer-events: none;
}

.brand { display: flex; align-items: center; gap: clamp(10px, 1vw, 16px); min-width: 0; overflow: hidden; justify-self: start; }

/* ------------------------------------------------------------ live badge */

.live-pill {
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 11px;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 999px;
  background: rgba(10, 10, 11, .45);
  backdrop-filter: blur(10px);
  line-height: 1;
  white-space: nowrap;
}
.live-pill[hidden] { display: none; }   /* beats the inline-flex above */

.live-dot {
  flex: none;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #2fd671;
  animation: livePulse 2.2s ease-out infinite;
}
@keyframes livePulse {
  0% { box-shadow: 0 0 0 0 rgba(47, 214, 113, .5); }
  70% { box-shadow: 0 0 0 8px rgba(47, 214, 113, 0); }
  100% { box-shadow: 0 0 0 0 rgba(47, 214, 113, 0); }
}

.live-pill strong {
  font-family: "Bebas Neue", sans-serif;
  font-size: 18px;
  font-weight: 400;
  letter-spacing: .05em;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.live-label { color: var(--muted); font-size: 12px; letter-spacing: .03em; }
.brand-mark { flex: none; width: clamp(40px, 3.6vw, 58px); color: var(--accent); display: grid; place-items: center; }
.brand-mark svg { width: 100%; height: auto; }

.brand-copy { display: flex; flex-direction: column; min-width: 0; }
.brand-copy strong {
  font-family: "Bebas Neue", sans-serif;
  font-size: clamp(19px, 1.9vw, 31px);
  font-weight: 400;
  line-height: 1;
  letter-spacing: .07em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.brand-copy small {
  margin-top: 6px;
  color: var(--accent);
  font-family: "Bebas Neue", sans-serif;
  /* Tracking is folded into the width budget so the lockup never collides. */
  font-size: clamp(10px, .9vw, 15px);
  line-height: 1;
  letter-spacing: .28em;
  white-space: nowrap;
}

.top-actions { display: flex; align-items: center; gap: clamp(8px, .9vw, 15px); flex: none; justify-self: end; }

.outline-btn {
  height: clamp(44px, 4.4vh, 54px);
  padding: 0 clamp(14px, 1.4vw, 22px);
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 12px;
  background: rgba(12, 12, 13, .5);
  backdrop-filter: blur(9px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease, transform .2s ease;
  font-family: "Bebas Neue", sans-serif;
  font-size: clamp(15px, 1.2vw, 17px);
  letter-spacing: .14em;
  white-space: nowrap;
}
.outline-btn svg { width: 22px; height: 22px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.6; }
.outline-btn:hover { border-color: rgba(255, 148, 31, .6); background: rgba(255, 148, 31, .09); }
.outline-btn:active { transform: translateY(1px); }

/* ------------------------------------------------------------------ stage */

.radio-stage {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(392px, 33vw, 512px);
  grid-template-rows: auto auto;
  align-content: center;
  /* `safe` keeps content reachable if it ever outgrows the stage. */
  align-content: safe center;
  gap: clamp(16px, 2.6vh, 32px) 0;
  padding:
    clamp(16px, 2.6vh, 34px)
    calc(var(--gutter) + env(safe-area-inset-right))
    calc(clamp(18px, 3vh, 40px) + env(safe-area-inset-bottom))
    calc(var(--gutter) + env(safe-area-inset-left));
  overflow-y: auto;
  overscroll-behavior: contain;
}

.player-card {
  grid-column: 2;
  grid-row: 1;
  padding: clamp(24px, 2.1vw, 34px);
  border: 1px solid rgba(255, 255, 255, .17);
  border-radius: var(--card-radius);
  background: transparent !important;
  backdrop-filter: blur(16px) saturate(.85);
  box-shadow: var(--shadow), inset 0 1px rgba(255, 255, 255, .04);
}

/* --------------------------------------------------------- now playing */

.now-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "eyebrow   heart"
    "copy      copy"
    "transport transport";
  align-items: center;
  gap: 12px;
}

.eyebrow {
  grid-area: eyebrow;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--accent);
  font-family: "Bebas Neue", sans-serif;
  font-size: 15px;
  letter-spacing: .19em;
  line-height: 1;
}
.eq-mini { display: inline-flex; align-items: flex-end; gap: 3px; height: 14px; }
.eq-mini i { width: 2px; background: var(--accent); opacity: .75; animation: eq 1s ease-in-out infinite alternate; }
.eq-mini i:nth-child(1) { height: 6px; }
.eq-mini i:nth-child(2) { height: 12px; animation-delay: .1s; }
.eq-mini i:nth-child(3) { height: 8px; animation-delay: .2s; }
.eq-mini i:nth-child(4) { height: 14px; animation-delay: .3s; }
@keyframes eq { to { transform: scaleY(.45); opacity: .35; } }

.heart-btn {
  grid-area: heart;
  justify-self: end;
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  margin: -6px -6px -6px 0;
  border: 0; border-radius: 50%;
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  transition: transform .18s ease;
}
.heart-btn svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.heart-btn:hover { transform: scale(1.08); }
.heart-btn.active svg { fill: var(--accent); }

.song-copy { grid-area: copy; min-width: 0; }
.song-copy h1 {
  margin: 0;
  font-family: Caveat, cursive;
  font-size: clamp(40px, 3.5vw, 58px);
  font-weight: 500;
  /* Caveat has deep descenders; a tight line-height clips them under overflow. */
  line-height: 1.12;
  letter-spacing: -.01em;
  color: #f1f1ef;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.song-meta-line { margin: 10px 0 0; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.artist { color: var(--text-2); font-family: "Bebas Neue", sans-serif; font-size: 17px; letter-spacing: .18em; line-height: 1; }
.song-label {
  color: var(--muted);
  font-family: "Noto Sans Devanagari", Inter, sans-serif;
  font-size: 14px;
  line-height: 1.3;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.transport {
  grid-area: transport;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 2vw, 30px);
  margin-top: 4px;
}
.transport-btn {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #f0f0ed;
  cursor: pointer;
  transition: color .18s ease, transform .18s ease;
}
.transport-btn svg { width: 26px; height: 26px; fill: currentColor; }
.transport-btn:hover { color: var(--accent); transform: scale(1.06); }
.main-play {
  width: 74px; height: 74px;
  border: 1px solid rgba(255, 255, 255, .28);
  box-shadow: inset 0 0 0 1px rgba(255, 148, 31, .08);
}
.main-play svg { width: 31px; height: 31px; }
.pause-icon { display: none; }
.is-playing .play-icon { display: none; }
.is-playing .pause-icon { display: block; }

/* ------------------------------------------------------------- progress */

.progress-wrap { margin-top: var(--card-gap); }
.progress {
  display: block;
  width: 100%;
  height: 18px;                 /* tall hit area, thin visual track */
  margin: 0;
  -webkit-appearance: none;     /* Safari needs the prefix to drop the native UI */
  appearance: none;
  background: transparent;
  outline: none;
  cursor: pointer;
  /* The card sits inside a scrollable stage. Without this, iOS claims a drag
     that starts here as a scroll gesture and the slider never sees it, so the
     bar cannot be dragged with a finger. */
  touch-action: none;
}
.progress::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 5px;
  background: linear-gradient(90deg, var(--accent) var(--played, 0%), rgba(255, 255, 255, .23) var(--played, 0%));
}
.progress::-moz-range-track {
  height: 3px;
  border-radius: 5px;
  background: linear-gradient(90deg, var(--accent) var(--played, 0%), rgba(255, 255, 255, .23) var(--played, 0%));
}
.progress::-webkit-slider-thumb {
  -webkit-appearance: none;     /* required in Safari, or the native thumb stays */
  appearance: none;
  width: 13px; height: 13px;
  margin-top: -5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(255, 148, 31, .12);
}
.progress::-moz-range-thumb {
  width: 13px; height: 13px;
  border: 0; border-radius: 50%;
  background: var(--accent);
}
/* Finger-sized target. 18px is fine for a mouse but far too thin to grab on a
   phone; the track stays visually the same, only the hit area grows.
   Thumb offset must stay -(thumbHeight - trackHeight) / 2 to stay centred. */
@media (pointer: coarse) {
  .progress { height: 32px; }
  .progress::-webkit-slider-runnable-track { height: 4px; }
  .progress::-moz-range-track { height: 4px; }
  .progress::-webkit-slider-thumb { width: 18px; height: 18px; margin-top: -7px; }
  .progress::-moz-range-thumb { width: 18px; height: 18px; }
}

.time-row {
  margin-top: 4px;
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.divider { height: 1px; background: var(--line-soft); margin: var(--card-gap) 0; }

/* ---------------------------------------------------------------- power */

.power-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }

.power-btn {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 88px;
  padding: 6px 20px 6px 6px;
  border: 1px solid rgba(255, 148, 31, .85);
  border-radius: 999px 18px 18px 999px;
  background: rgba(6, 6, 6, .45);
  text-align: left;
  cursor: pointer;
  transition: background .2s ease, box-shadow .2s ease, transform .12s ease;
}
.power-btn:hover { background: rgba(255, 148, 31, .07); box-shadow: 0 0 30px rgba(255, 148, 31, .12); }
.power-btn:active { transform: scale(.992); }

.power-orb {
  flex: none;
  display: grid;
  place-items: center;
  width: 74px; height: 74px;
  border: 2px solid var(--accent);
  border-radius: 50%;
  color: var(--accent);
  box-shadow: inset 0 0 30px rgba(255, 148, 31, .05), 0 0 0 5px rgba(255, 148, 31, .03);
}
.power-orb svg { width: 32px; height: 32px; fill: currentColor; }

.power-copy { display: flex; flex-direction: column; min-width: 0; }
.power-copy strong { color: var(--accent); font-family: "Bebas Neue", sans-serif; font-size: clamp(28px, 2.4vw, 34px); font-weight: 400; letter-spacing: .24em; line-height: 1; }
.power-copy small { margin-top: 7px; color: var(--accent); font-family: "Bebas Neue", sans-serif; font-size: 12px; letter-spacing: .09em; line-height: 1; }
.power-copy em { margin-top: 5px; color: #7f7f7c; font-size: 11px; font-style: normal; line-height: 1.2; }

/* Quote shown inside the card (compact layout only). */
.dialogue-quote {
  display: none;
  position: relative;
  margin: 0;
  padding: 14px 30px 12px;
  border: 1px solid var(--line-soft);
  border-radius: 16px;
  color: var(--text-2);
  font-family: "Noto Sans Devanagari", sans-serif;
}
.dialogue-quote p { margin: 0; font-size: 16px; line-height: 1.45; text-align: center; }
.dialogue-quote small { display: block; margin-top: 5px; color: #757571; font-family: Inter, sans-serif; font-size: 11px; line-height: 1.35; text-align: center; }
.quote-open, .quote-close { position: absolute; color: var(--accent); font-family: Georgia, serif; font-size: 34px; line-height: 1; }
.quote-open { top: 8px; left: 10px; }
.quote-close { right: 10px; bottom: -4px; }

.duck-status {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 0;
  margin-top: 0;
  overflow: hidden;
  opacity: 0;
  transform: translateY(4px);
  color: var(--accent);
  font-family: "Bebas Neue", sans-serif;
  font-size: 12px;
  letter-spacing: .12em;
  transition: opacity .2s ease, transform .2s ease, height .2s ease, margin-top .2s ease;
}
.duck-status svg { width: 17px; height: 17px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; }
.dialogue-active .duck-status { height: 20px; margin-top: 14px; opacity: 1; transform: translateY(0); }
.dialogue-active .power-orb { box-shadow: 0 0 34px rgba(255, 148, 31, .34), inset 0 0 18px rgba(255, 148, 31, .13); animation: pulse 1s ease-in-out infinite alternate; }
@keyframes pulse { to { transform: scale(1.04); } }

/* Quote shown under the card (wide layout only). */
.desktop-quote {
  grid-column: 2;
  grid-row: 2;
  position: relative;
  margin: 0;
  padding: 4px 36px;
  text-align: center;
  color: var(--text-2);
  font-family: "Noto Sans Devanagari", sans-serif;
}
.desktop-quote span, .desktop-quote b {
  position: absolute;
  color: var(--accent);
  font-family: Georgia, serif;
  font-size: 40px;
  font-weight: 400;
  line-height: 1;
}
.desktop-quote span { left: 0; top: 2px; }
.desktop-quote b { right: 0; bottom: 10px; }
.desktop-quote p { margin: 0; font-size: clamp(19px, 1.4vw, 26px); line-height: 1.5; color: #e6e6e2; text-shadow: 0 1px 12px rgba(0, 0, 0, .55); }
/* Sits directly on the powder, so it needs more weight than card-level text. */
.desktop-quote small { display: block; margin-top: 8px; color: rgba(255, 255, 255, .68); font-family: Inter, sans-serif; font-size: 11px; text-shadow: 0 1px 8px rgba(0, 0, 0, .6); }

/* ----------------------------------------------------------------- drawer */

.drawer {
  position: fixed;
  z-index: 30;
  top: 0; right: 0;
  width: min(440px, 100vw);
  height: 100dvh;
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  visibility: hidden;                 /* keeps controls out of the tab order */
  background: #0a0a0b;                /* opaque: the page behind was ghosting through */
  border-left: 1px solid rgba(255, 255, 255, .12);
  box-shadow: -24px 0 90px rgba(0, 0, 0, .5);
  transition: transform .32s cubic-bezier(.2, .7, .2, 1), visibility 0s linear .32s;
}
.drawer.open { transform: translateX(0); visibility: visible; transition-delay: 0s; }

.drawer-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: calc(26px + env(safe-area-inset-top)) 22px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.drawer-header small { color: var(--accent); font-family: "Bebas Neue", sans-serif; font-size: 13px; letter-spacing: .2em; }
.drawer-header h2 { margin: 6px 0 0; font-family: "Bebas Neue", sans-serif; font-size: 28px; font-weight: 400; letter-spacing: .03em; }
.drawer-close {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: 50%;
  background: transparent;
  font-size: 25px;
  line-height: 1;
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease;
}
.drawer-close:hover { border-color: var(--accent); background: rgba(255, 148, 31, .08); }

.song-search {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 46px;
  margin: 16px 18px 10px;
  padding: 0 14px;
  border: 1px solid rgba(255, 255, 255, .11);
  border-radius: 12px;
  background: rgba(255, 255, 255, .035);
  transition: border-color .2s ease;
}
.song-search:focus-within { border-color: rgba(255, 148, 31, .55); }
.song-search svg { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--muted); stroke-width: 1.7; }
.song-search input { width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--text); font-size: 14px; }
.song-search input::placeholder { color: #686865; }

.song-list {
  flex: 1;
  min-height: 0;
  padding: 2px 10px calc(14px + env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: #3b3b3b transparent;
}

.song-item {
  display: grid;
  grid-template-columns: 26px 54px minmax(0, 1fr) 26px;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  text-align: left;
  cursor: pointer;
  transition: background .16s ease;
}
.song-item + .song-item { box-shadow: 0 -1px rgba(255, 255, 255, .05); }
.song-item:hover { background: rgba(255, 255, 255, .05); }
.song-item.active { background: rgba(255, 148, 31, .09); }

.song-index { color: #646461; font-family: "Bebas Neue", sans-serif; font-size: 15px; text-align: center; }
.song-item.active .song-index { color: var(--accent); }
.song-thumb { width: 54px; height: 40px; object-fit: cover; border-radius: 7px; background: #1a1a1a; filter: saturate(.8) brightness(.85); }
.song-meta { min-width: 0; }
.song-meta strong { display: block; font-size: 13.5px; font-weight: 500; color: #e4e4e1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.song-meta small { display: block; margin-top: 4px; color: #6d6d69; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.song-play { color: #777; font-size: 15px; text-align: center; }
.song-item.active .song-play { color: var(--accent); }

.drawer-footer {
  padding: 13px 20px calc(13px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line-soft);
  color: #565653;
  font-size: 10px;
  text-align: center;
}

.drawer-scrim {
  position: fixed;
  z-index: 29;
  inset: 0;
  border: 0;
  background: rgba(0, 0, 0, .58);
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s;
}
.drawer-scrim.open { opacity: 1; pointer-events: auto; }

/* ------------------------------------------------------------ utilities */

.toast {
  position: fixed;
  z-index: 50;
  left: 50%;
  bottom: calc(26px + env(safe-area-inset-bottom));
  max-width: min(420px, calc(100vw - 32px));
  padding: 11px 16px;
  transform: translate(-50%, 16px);
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 12px;
  background: rgba(18, 18, 19, .97);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .35);
  color: #ddd;
  font-size: 12.5px;
  line-height: 1.4;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease, transform .22s ease;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* Deliberately kept INSIDE the viewport. Chrome throttles and suspends
   cross-origin iframes that sit entirely offscreen, which stalls YouTube the
   moment the tab is backgrounded. Near-zero opacity behind the portrait hides
   it without moving it out of view; do not park this at -10000px again. */
.youtube-player {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 320px;
  height: 180px;
  z-index: -5;
  opacity: .01;
  pointer-events: none;
  border: 0;
}

/* ==========================================================================
   Compact layout — narrow screens, and portrait tablets where the
   side-by-side split has no room.
   ========================================================================== */

@media (max-width: 900px), (orientation: portrait) and (max-width: 1080px) {
  .portrait-layer::before {
    width: 100%;
    /* Capped height so a tall, narrow phone crops the face less; the bottom
       of the frame dissolves into the page behind the card. */
    bottom: auto;
    height: 78%;
    background-image: url("./assets/img/portrait-tall.jpg");
    background-position: 50% 0%;
    -webkit-mask-image: linear-gradient(180deg, #000 0 70%, rgba(0, 0, 0, .7) 86%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 0 70%, rgba(0, 0, 0, .7) 86%, transparent 100%);
  }
  .portrait-layer::after {
    background:
      linear-gradient(0deg, rgba(8, 8, 8, .8) 4%, rgba(8, 8, 8, .5) 22%, rgba(8, 8, 8, .04) 55%, rgba(8, 8, 8, .42) 100%),
      radial-gradient(95% 55% at 50% 34%, transparent 0 42%, rgba(0, 0, 0, .32) 100%);
  }

  /* Face sits higher and more central here than on the wide layout. */
  .powder-layer {
    -webkit-mask-image: radial-gradient(78% 46% at 48% 33%, rgba(0, 0, 0, .04) 0 26%, rgba(0, 0, 0, .42) 58%, #000 92%);
    mask-image: radial-gradient(78% 46% at 48% 33%, rgba(0, 0, 0, .04) 0 26%, rgba(0, 0, 0, .42) 58%, #000 92%);
  }

  /* Brand + two buttons + badge cannot share a phone's width, so the badge
     drops to its own centred row. */
  .topbar {
    padding-top: calc(clamp(14px, 2.2vh, 22px) + env(safe-area-inset-top));
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "brand   actions"
      "live    live";
    row-gap: 10px;
  }
  .brand { grid-area: brand; }
  .top-actions { grid-area: actions; }
  .live-pill { grid-area: live; padding: 6px 12px 6px 10px; margin-left: 75%;
    zoom: 0.8; }
  .live-pill strong { font-size: 16px; }
  .live-label { font-size: 11px; }
  .brand-copy strong { font-size: 18px; }
  .brand-copy small { font-size: 9px; letter-spacing: .22em; margin-top: 5px; }
  .outline-btn { height: 44px; padding: 0 14px; gap: 8px; font-size: 14px; }

  /* Card is content-sized and pinned to the bottom — no fixed height to
     crush the contents into. */
  .radio-stage {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto;
    align-content: stretch;
    gap: 0;
    padding-top: 0;
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
    padding-inline: calc(12px + env(safe-area-inset-left)) calc(12px + env(safe-area-inset-right));
  }
  .player-card {
    grid-column: 1;
    grid-row: 2;
    align-self: end;
    padding: 16px 16px 15px;
    border-radius: 22px;
    background: linear-gradient(150deg, rgba(19, 19, 20, .9), rgba(8, 8, 9, .84));
    --card-gap: 13px;
    /* Keeps the controls from stretching edge to edge on portrait tablets;
       no effect at phone widths. */
    width: 90%;
    max-width: 680px;
    margin-inline: auto;
    zoom: 0.75;
  }

  /* Transport moves beside the song copy so the card stays short. */
  .now-grid {
    grid-template-areas:
      "eyebrow heart"
      "copy    transport";
    gap: 8px 12px;
    zoom: 0.85;
  }
  .eyebrow { font-size: 12px; letter-spacing: .16em; gap: 8px; }
  .eq-mini { height: 11px; }
  .eq-mini i { width: 1.5px; }
  .eq-mini i:nth-child(1) { height: 5px; }
  .eq-mini i:nth-child(2) { height: 9px; }
  .eq-mini i:nth-child(3) { height: 6px; }
  .eq-mini i:nth-child(4) { height: 11px; }

  .heart-btn { width: 38px; height: 38px; }
  .heart-btn svg { width: 23px; height: 23px; }

  .song-copy h1 {
    /* Two lines: the transport sits in the same row, so a single line leaves
       long titles ("Kawana Kalamawa Se Likhal Karamwa") as one clipped word. */
    font-size: clamp(25px, 7vw, 33px);
    -webkit-line-clamp: 2;
    line-height: 1.16;
  }
  .song-meta-line { margin-top: 5px; flex-direction: row; align-items: baseline; gap: 7px; }
  .artist { font-size: 12px; letter-spacing: .16em; flex: none; }
  .song-label { font-size: 11px; }
  .song-label::before { content: "·"; margin-right: 7px; color: #565653; }

  .transport { gap: 0; margin-top: 0; margin-right: 30px; zoom: 1.50; }
  .transport-btn { width: 40px; height: 40px; }
  .transport-btn svg { width: 30px; height: 30px; }
  .main-play { width: 50px; height: 50px; margin-inline: 3px; }
  .main-play svg { width: 30px; height: 30px; }

  .time-row { font-size: 11px; }

  /* Full-width POWER pill, quote underneath. Side by side has no room to
     breathe at phone widths and was wrapping the pill's own label. */
  .power-row { gap: 10px; }
  .power-btn { min-height: 64px; gap: 12px; padding: 5px 16px 5px 5px; border-radius: 999px 16px 16px 999px; zoom: 0.85; }
  .power-orb { width: 54px; height: 54px; }
  .power-orb svg { width: 25px; height: 25px; }
  .power-copy strong { font-size: 27px; letter-spacing: .2em; }
  .power-copy small { margin-top: 5px; font-size: 10px; }
  .power-copy em { display: none; }

  .dialogue-quote { display: block; padding: 10px 26px 9px; border-radius: 14px; }
  .dialogue-quote p { font-size: 14px; line-height: 1.4; }
  .dialogue-quote small { margin-top: 3px; font-size: 9.5px; }
  .quote-open, .quote-close { font-size: 26px; }
  .quote-open { top: 6px; left: 7px; }
  .quote-close { right: 7px; bottom: -3px; }

  .duck-status { font-size: 11px; }
  .dialogue-active .duck-status { height: 18px; margin-top: 11px; }

  .desktop-quote { display: none; }

  .drawer { width: 100%; }
  .toast { bottom: calc(16px + env(safe-area-inset-bottom)); }
}

/* Phones — the brand lockup plus two labelled buttons cannot share this
   width, so the actions collapse to icons. */
@media (max-width: 440px) {
  .outline-btn { width: 44px; padding: 0; gap: 0; }
  /* Hidden visually but still the button's accessible name. */
  .outline-btn span {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Small phones — trade the least important lines for breathing room. */
@media (max-width: 380px) {
  .brand-copy strong { font-size: 16px; }
  .brand-copy small { font-size: 8px; letter-spacing: .2em; }
  .dialogue-quote small { display: none; }
}

/* Short wide screens cannot fit the card and the pull quote together. */
@media (max-height: 660px) {
  .desktop-quote { display: none; }
  /* Trim the enlarged touch target back where vertical space is tight — at
     full size it pushed the card past the bottom on short touch screens.
     Only the hit area shrinks; the thumb stays centred on the track. */
  .progress { height: 22px; }
}

/* Short viewports — phones in landscape, small laptops. Drop the optional
   copy so the card still fits without clipping. */
@media (max-height: 560px) {
  .song-copy h1 { font-size: clamp(26px, 5vw, 32px); -webkit-line-clamp: 1; }
  .power-btn { min-height: 58px; }
  .power-orb { width: 48px; height: 48px; }
  .power-orb svg { width: 22px; height: 22px; }
  .power-copy strong { font-size: 24px; }
  .power-copy small, .power-copy em { display: none; }
  .dialogue-quote, .desktop-quote { display: none; }
  .player-card { padding: 14px 16px; --card-gap: 10px; }
  .main-play { width: 50px; height: 50px; }
  .main-play svg { width: 22px; height: 22px; }
  .transport-btn { width: 40px; height: 40px; }
}

/* Phone in landscape: keep the portrait on the left and float a compact
   card on the right rather than stacking into a viewport that has no height. */
@media (orientation: landscape) and (max-height: 500px) {
  .portrait-layer::before {
    /* Undo the compact layout's capped height, which would otherwise leave a
       hard horizontal edge partway down the screen. */
    bottom: 0;
    height: auto;
    width: min(58vw, 620px);
    background-image: url("./assets/img/portrait-wide.png");
    background-position: 46% 16%;
    -webkit-mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, .78) 66%, transparent 93%);
    mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, .78) 66%, transparent 93%);
  }
  .portrait-layer::after {
    background:
      linear-gradient(90deg, rgba(8, 8, 8, 0) 30%, rgba(8, 8, 8, .55) 58%, var(--bg) 86%),
      radial-gradient(115% 85% at 30% 36%, transparent 0 40%, rgba(0, 0, 0, .42) 100%);
  }

  .topbar { padding-top: calc(10px + env(safe-area-inset-top)); }

  .radio-stage {
    grid-template-columns: minmax(0, 1fr) clamp(300px, 46vw, 400px);
    grid-template-rows: auto;
    align-content: safe center;
    padding-top: 10px;
    padding-bottom: calc(10px + env(safe-area-inset-bottom));
  }
  .player-card { grid-column: 2; grid-row: 1; align-self: center; }

  .now-grid {
    grid-template-areas:
      "eyebrow heart"
      "copy    transport";
  }
  .song-meta-line { flex-direction: row; align-items: baseline; gap: 7px; }
  .song-label::before { content: "·"; margin-right: 7px; color: #565653; }
  .artist { font-size: 12px; }
  .song-label { font-size: 11px; }
  .transport { gap: 2px; margin-top: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

.song-copy h1 {
  margin: 0;
  font-family: Caveat, cursive;
  font-size: clamp(40px, 3.5vw, 58px);
  font-weight: 500;
  line-height: 1.12;

  /* ADD THIS */
  min-height: 2.24em;

  letter-spacing: -.01em;
  color: #f1f1ef;

  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
