/* Venue screen: a projected, unattended, read-only display.
   Sizing is viewport-relative throughout so the same stylesheet reads correctly at
   1920x1080 and at 4K without a second breakpoint.

   Direction: Arabic is the default interface, so layout uses logical properties and
   mirrors with <html dir>. Three things deliberately do NOT mirror: the progress bar and
   its timecodes (media, see .progress), the visualiser and QR canvases (pixels drawn in
   absolute coordinates; nothing here transforms them), and lyric lines, which take their
   direction from their own script in karaoke.js whatever the interface language.

   Room-facing type: Arabic at the same pixel size reads smaller than Latin, and the
   uppercase + wide tracking that gives the English kickers their presence has no Arabic
   equivalent (base.css resets the tracking). The `html[lang="ar"]` rules at the end of
   each section give the Arabic kickers size and weight instead. Uppercase is an English
   styling only; the dictionary carries sentence-case text and never relies on it. */

:root {
  --screen-pad: 2.2vw;
  --panel-bg: rgba(20, 24, 34, 0.62);
  --panel-line: rgba(255, 255, 255, 0.07);
}

html, body { height: 100%; overflow: hidden; }

/* Several elements below carry a display rule, which would otherwise beat [hidden]. */
[hidden] { display: none !important; }

body.screen {
  display: flex;
  flex-direction: column;
  padding: var(--screen-pad);
  gap: 1.6vh;
  /* Two soft pools of light rather than a flat field: a flat dark rectangle behind a
     stage reads as "the screen is broken". */
  background:
    radial-gradient(1100px 700px at 12% -10%, rgba(212, 160, 74, 0.13), transparent 62%),
    radial-gradient(1000px 800px at 96% 104%, rgba(63, 182, 168, 0.10), transparent 60%),
    var(--bg);
  user-select: none;
  -webkit-user-select: none;
  cursor: default;
}

body.hide-cursor, body.hide-cursor * { cursor: none !important; }

/* ─── connection indicator ─────────────────────────────────────────────────── */

.conn {
  position: fixed;
  inset-block-start: 1.1vh; inset-inline-end: 1.1vw;
  z-index: 50;
  display: flex; align-items: center; gap: 0.5vw;
  padding: 0.5vh 0.9vw;
  border-radius: 999px;
  background: rgba(10, 12, 17, 0.8);
  border: 1px solid rgba(227, 86, 74, 0.35);
  color: var(--fg-faint);
  font-size: clamp(11px, 0.75vw, 20px);
  letter-spacing: 0.04em;
}
.conn[hidden] { display: none; }
.conn-dot {
  width: 0.55em; height: 0.55em; border-radius: 50%;
  background: var(--danger);
  animation: conn-pulse 1.6s ease-in-out infinite;
}
@keyframes conn-pulse { 50% { opacity: 0.25; } }

/* ─── event header ─────────────────────────────────────────────────────────── */

.event-head {
  display: flex;
  align-items: baseline;
  gap: 1.6vw;
  flex-wrap: wrap;
  padding-bottom: 1.2vh;
  border-bottom: 1px solid var(--panel-line);
  flex: 0 0 auto;
}
.event-name {
  font-size: clamp(20px, 1.9vw, 52px);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--fg);
}
.event-name.ar { letter-spacing: 0; }
.event-sub {
  font-size: clamp(13px, 1.05vw, 30px);
  color: var(--fg-muted);
  font-weight: 500;
}

/* ─── stage layout ─────────────────────────────────────────────────────────── */

.stage {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(300px, 26vw, 660px);
  gap: 2vw;
}

.performance, .standby {
  min-width: 0; min-height: 0;
  display: flex;
  flex-direction: column;
  grid-column: 1;
  grid-row: 1;
}

/* Exactly one of the two start-side columns (left in English, right in Arabic, since
   the grid follows <html dir>) is live at a time. */
body.is-idle .performance,
body:not(.is-idle) .standby { display: none; }

.side {
  min-width: 0; min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 1.6vh;
}

/* ─── now playing ──────────────────────────────────────────────────────────── */

.np {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 1.4vw;
  padding-bottom: 1.6vh;
}

.np-art {
  flex: 0 0 auto;
  width: clamp(78px, 7.4vw, 190px);
  aspect-ratio: 1;
  border-radius: clamp(8px, 0.7vw, 18px);
  overflow: hidden;
  position: relative;
  box-shadow: 0 0.9vh 3vh rgba(0, 0, 0, 0.5);
  background: var(--bg-raised);
}
.np-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Deterministic placeholder: hue pair comes from the song id, so a given song always
   gets the same artwork stand-in instead of flickering between renders. */
.np-art .art-fallback {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: linear-gradient(140deg, hsl(var(--h1) 55% 42%), hsl(var(--h2) 48% 22%));
}
.np-art .art-glyph {
  font-size: clamp(30px, 3.4vw, 88px);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.86);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

.np-meta { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 0.5vh; }

/* Primary = the interface language's title, secondary = the other script (app.js
   renderTitles). The .ar/.en class on each line comes from its own text, so an Arabic
   title is set right to left in Arabic type even when it is the secondary line. */
.np-titles { display: flex; flex-direction: column; gap: 0.15vh; }
.np-title-primary {
  font-size: clamp(26px, 2.5vw, 68px);
  font-weight: 700;
  line-height: 1.18;
}
.np-title-secondary {
  font-size: clamp(16px, 1.35vw, 38px);
  font-weight: 600;
  color: var(--fg-muted);
  line-height: 1.2;
}
/* Arabic letterforms stack taller (dots, hamza, descending tails); Latin leading clips
   them when a long title wraps. */
.np-title-primary.ar, .np-title-secondary.ar { line-height: 1.4; }
/* Arabic and English artist names sit in separate directioned spans — never inlined
   into one another, where bidi reordering would scramble the punctuation between them. */
.np-artist {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35em 0.7em;
  font-size: clamp(14px, 1.15vw, 32px);
  color: var(--accent);
  font-weight: 600;
}
.np-artist > span + span {
  color: var(--fg-muted);
  font-weight: 500;
  font-size: 0.82em;
}
.np-singer {
  font-size: clamp(13px, 1.02vw, 28px);
  color: var(--fg-muted);
}
.np-singer .name { color: var(--fg); font-weight: 650; }

/* Media stays LTR in both languages (index.html puts dir="ltr" on .progress): the fill
   grows from the left and elapsed sits left of total, as on every player and DJ tool. */
.progress { margin-top: 0.7vh; }
.progress-track {
  height: clamp(5px, 0.42vh, 10px);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.09);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), #f0c479);
}
.progress-times {
  display: flex; justify-content: space-between;
  margin-top: 0.45vh;
  font-size: clamp(12px, 0.85vw, 24px);
  color: var(--fg-faint);
}

/* ─── karaoke lyrics ───────────────────────────────────────────────────────── */

.lyrics {
  flex: 1 1 auto;
  min-height: 0;
  position: relative;
  overflow: hidden;
  /* Feather the top and bottom so lines dissolve at the edges rather than clipping. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 13%, #000 87%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 13%, #000 87%, transparent 100%);
}

.lyrics-track {
  position: absolute;
  inset-block-start: 0; inset-inline: 0;
  will-change: transform;
}

.lyric-line {
  padding: 0.85vh 1.2vw;
  text-align: center;
  font-weight: 700;
  line-height: 1.24;
  font-size: clamp(22px, 2.35vw, 62px);
  color: var(--fg);
  /* The two ends of the karaoke gradient. Declared on the line rather than the word
     because .k-word paints its text transparent, which would make `currentColor`
     resolve to transparent and leave the not-yet-sung half invisible. */
  --k-dim: var(--fg);
  --k-lit: #e9c46a;
  opacity: 0.16;
  transform: scale(0.94);
  transform-origin: center;
  transition: opacity 320ms ease, color 320ms ease, transform 320ms ease, text-shadow 320ms ease;
}
.lyric-line.ar { font-size: clamp(24px, 2.6vw, 70px); line-height: 1.4; }

.lyric-line.active {
  opacity: 1;
  transform: scale(1);
  color: #fff8ea;
  --k-dim: #fff8ea;
  font-size: clamp(34px, 4.1vw, 108px);
  text-shadow: 0 0 4.5vh rgba(212, 160, 74, 0.45);
}
.lyric-line.active.ar { font-size: clamp(36px, 4.4vw, 116px); }

/* Progressive falloff away from the active line, in both directions. */
.lyric-line.d1 { opacity: 0.55; transform: scale(0.98); }
.lyric-line.d2 { opacity: 0.32; }
.lyric-line.d3 { opacity: 0.20; }
.lyric-line.d4 { opacity: 0.12; }
.lyric-line.d5 { opacity: 0.07; }
/* Sung lines dim faster than upcoming ones — the eye should lead, not trail. */
.lyric-line.past.d1 { opacity: 0.34; }
.lyric-line.past.d2 { opacity: 0.18; }
.lyric-line.past.d3 { opacity: 0.10; }
.lyric-line.past.d4, .lyric-line.past.d5 { opacity: 0.05; }

.lyrics-empty {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 1.4vh;
  text-align: center;
}
.lyrics-empty[hidden] { display: none; }
.lyrics-empty .glyph {
  display: flex; gap: 0.7vw; align-items: flex-end;
  height: clamp(34px, 4vh, 80px);
}
.lyrics-empty .bar {
  width: clamp(6px, 0.5vw, 14px);
  background: linear-gradient(180deg, var(--accent), rgba(212, 160, 74, 0.25));
  border-radius: 999px;
  animation: bar-bob 1.5s ease-in-out infinite;
}
.lyrics-empty .bar:nth-child(2) { animation-delay: 0.18s; }
.lyrics-empty .bar:nth-child(3) { animation-delay: 0.36s; }
.lyrics-empty .bar:nth-child(4) { animation-delay: 0.54s; }
.lyrics-empty .bar:nth-child(5) { animation-delay: 0.72s; }
@keyframes bar-bob { 0%, 100% { height: 32%; } 50% { height: 100%; } }
.lyrics-empty .headline {
  font-size: clamp(24px, 2.3vw, 60px);
  font-weight: 700;
  color: var(--fg-muted);
}
.lyrics-empty .sub {
  font-size: clamp(14px, 1.1vw, 30px);
  color: var(--fg-faint);
}
html[lang="ar"] .lyrics-empty .sub { font-size: clamp(16px, 1.3vw, 34px); }

/* Per-word karaoke fill.
   ONE text node per word, painted by a hard-edged gradient that is clipped to the
   glyphs. The sweep edge can therefore sit *inside* a letter — that sub-letter
   precision is what makes it track a voice rather than stepping word to word.

   Deliberately not two stacked copies of the text: two copies of the same Arabic
   run do not lay out identically inside an absolutely-positioned box, and the
   glyphs visibly doubled. A single text node cannot misalign with itself.

   --k   0..1 fill fraction, set per frame from the vowel-weighted timing
   --k-to  gradient direction; `to left` for Arabic so the fill starts at the right.
           Physical on purpose: set per word from its own script (karaoke.js), so the
           interface's <html dir> can never reverse a sweep. */
.k-word {
  --k: 0;
  --k-to: to right;
  background-image: linear-gradient(
    var(--k-to),
    var(--k-lit, #e9c46a) 0 calc(var(--k) * 100%),
    var(--k-dim, currentColor) calc(var(--k) * 100%) 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  /* Painting only the glyphs means the gradient box must not stretch across the
     whole line, or every word would share one sweep. */
  display: inline-block;
}
/* Once a line is behind us every word is fully sung; forcing --k avoids leaving a
   half-filled word frozen on screen when the singer moves on. */
.lyric-line.past .k-word { --k: 1; }

/* Spectrum bars along the bottom of the performance column. Sized in vh so it stays
   a band across the foot of the screen on a projector as well as a 4K TV, and kept
   out of the layout flow of the lyrics above it. Never mirrored in RTL: the frequency
   axis is data (lows on the left), and a canvas ignores `direction` for what it draws. */
/* The attribute has to beat `display: block`, or hiding the canvas leaves its
   band of dead height behind -- which is the whole reason for hiding it. */
.visualiser[hidden] { display: none; }
.visualiser {
  display: block;
  width: 100%;
  height: 9vh;
  min-height: 48px;
  margin-top: auto;
  opacity: 0.9;
  pointer-events: none;
}
/* ── four-beat tempo lights ──────────────────────────────────────────────────
   Grey at rest, "greenish" as the bar fills, and full green on the fourth. The
   transition is deliberately short: a slow fade would smear the beat and defeat the
   point of a metronome. The row follows the reading direction on purpose: counting
   one-two-three-four runs right to left for an Arabic room. */
.metronome {
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
  gap: clamp(8px, 1vw, 16px);
  margin: 0 0 1.4vh;
}
.metronome .beat {
  width: clamp(34px, 4.4vw, 74px);
  height: clamp(7px, 0.9vh, 12px);
  border-radius: 999px;
  background: #2a2f38;                     /* grey — not yet reached */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
  transition: background 90ms linear, box-shadow 90ms linear;
}
.metronome .beat.lit {
  background: #4e8f63;                     /* greenish — beats 1..3 */
  box-shadow: 0 0 10px rgba(78, 143, 99, 0.45);
}
.metronome .beat.accent {
  background: #45e07a;                     /* full green — the fourth */
  box-shadow: 0 0 22px rgba(69, 224, 122, 0.75);
}
body.is-idle .metronome { display: none; }

/* Aurora is a wash of light rather than a row of bars, so it needs vertical room to
   read as one. It still sits below the lyrics and never overlaps them — legibility of
   the words is the screen's actual job. The blur softens the band edges the 24-band
   source would otherwise show at this size. */
body.viz-aurora .visualiser {
  height: 22vh;
  min-height: 120px;
  opacity: 1;
  filter: blur(3px) saturate(1.2);
}

/* Nothing playing means nothing to show; the standby column owns the screen then. */
body.is-idle .visualiser { display: none; }

/* Discreet by design: the auto-estimate caveat is honest, not an alarm. Discreet is not
   the same as illegible, though — the Arabic gets the size lift it needs to be read. */
.lyrics-note {
  flex: 0 0 auto;
  text-align: center;
  padding-top: 0.8vh;
  font-size: clamp(11px, 0.72vw, 19px);
  color: var(--fg-faint);
  opacity: 0.55;
}
html[lang="en"] .lyrics-note { letter-spacing: 0.05em; text-transform: uppercase; }
html[lang="ar"] .lyrics-note { font-size: clamp(13px, 0.9vw, 24px); }
.lyrics-note[hidden] { display: none; }

/* ─── standby ──────────────────────────────────────────────────────────────── */

.standby { align-items: center; justify-content: center; }
.standby-inner {
  display: flex; flex-direction: column; align-items: center;
  gap: 1.5vh;
  text-align: center;
  max-width: 90%;
}
.standby-kicker {
  font-size: clamp(11px, 0.8vw, 21px);
  color: var(--fg-faint);
}
html[lang="en"] .standby-kicker { letter-spacing: 0.34em; text-transform: uppercase; }
/* Without the tracked capitals the kicker would shrink to a whisper; in Arabic it gets
   its presence from size and weight instead, still well below the event name. */
html[lang="ar"] .standby-kicker { font-size: clamp(16px, 1.25vw, 34px); font-weight: 600; }
.standby-name {
  font-size: clamp(30px, 3.4vw, 92px);
  font-weight: 700;
  line-height: 1.2;
}
.standby-line {
  width: clamp(60px, 7vw, 180px);
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  opacity: 0.7;
}
.standby-call {
  font-size: clamp(16px, 1.5vw, 42px);
  font-weight: 600;
  color: var(--accent);
}
html[lang="ar"] .standby-call { font-size: clamp(19px, 1.75vw, 48px); font-weight: 700; line-height: 1.4; }

/* ─── side panels ──────────────────────────────────────────────────────────── */

.panel {
  background: var(--panel-bg);
  border: 1px solid var(--panel-line);
  border-radius: clamp(12px, 1vw, 26px);
  padding: clamp(12px, 1.1vw, 30px);
  min-height: 0;
}
.queue-panel { flex: 1 1 auto; display: flex; flex-direction: column; overflow: hidden; }
.signup-panel { flex: 0 0 auto; }
.shouts-panel { flex: 0 1 auto; display: flex; flex-direction: column; overflow: hidden; }

.panel-title {
  font-size: clamp(12px, 0.85vw, 23px);
  color: var(--fg-faint);
  font-weight: 700;
  margin-bottom: 1.2vh;
}
html[lang="en"] .panel-title { letter-spacing: 0.2em; text-transform: uppercase; }
/* Arabic panel titles read as headings by size, and a touch brighter than the English
   kicker grey, which only works at a distance because of its capitals. */
html[lang="ar"] .panel-title {
  font-size: clamp(16px, 1.15vw, 31px);
  color: var(--fg-muted);
  line-height: 1.3;
}

.queue-list {
  list-style: none;
  margin: 0; padding: 0;
  display: flex; flex-direction: column;
  gap: 1vh;
  overflow: hidden;
  flex: 1 1 auto;
}

.queue-item {
  display: flex;
  align-items: center;
  gap: 0.9vw;
  min-width: 0;
}
.queue-num {
  flex: 0 0 auto;
  width: clamp(26px, 2.2vw, 58px);
  height: clamp(26px, 2.2vw, 58px);
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(212, 160, 74, 0.12);
  border: 1px solid rgba(212, 160, 74, 0.28);
  color: var(--accent);
  font-weight: 700;
  font-size: clamp(12px, 0.95vw, 26px);
  font-variant-numeric: tabular-nums;
}
.queue-text { min-width: 0; display: flex; flex-direction: column; gap: 0.15vh; }
/* The singer's name is the thing guests are looking for from across the room. */
.queue-singer {
  font-size: clamp(17px, 1.55vw, 44px);
  font-weight: 700;
  color: var(--fg);
  line-height: 1.16;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.queue-song {
  font-size: clamp(12px, 0.98vw, 27px);
  color: var(--fg-muted);
  line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.queue-item.up-next .queue-num { background: var(--accent); border-color: var(--accent); color: #1a1204; }

.queue-more {
  flex: 0 0 auto;
  margin-top: 1vh;
  font-size: clamp(12px, 0.9vw, 24px);
  color: var(--fg-faint);
}
.queue-more[hidden] { display: none; }

.queue-empty {
  color: var(--fg-faint);
  font-size: clamp(13px, 1vw, 27px);
  padding: 1.5vh 0;
}
html[lang="ar"] .queue-empty { font-size: clamp(15px, 1.15vw, 31px); line-height: 1.5; }
html[lang="ar"] .queue-more { font-size: clamp(14px, 1.05vw, 28px); }

/* ─── signup / QR ──────────────────────────────────────────────────────────── */

.signup-body { display: flex; align-items: center; gap: 1.1vw; }
.signup-copy { min-width: 0; display: flex; flex-direction: column; gap: 0.8vh; }
.signup-lead {
  font-size: clamp(15px, 1.3vw, 36px);
  font-weight: 700;
  line-height: 1.15;
}
/* Two stacked Arabic lines at Latin leading collide (dots of one line into the next). */
html[lang="ar"] .signup-lead { font-size: clamp(16px, 1.4vw, 38px); line-height: 1.5; }

.qr-host {
  flex: 0 0 auto;
  background: #fff;
  border-radius: clamp(6px, 0.5vw, 14px);
  padding: clamp(6px, 0.5vw, 14px);
  line-height: 0;
  width: clamp(120px, 11vw, 300px);
}
.qr-host canvas {
  display: block;
  width: 100%; height: auto;
  /* Never let the browser blur module edges — a soft QR is a slow QR to scan. */
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
.qr-host-lg { width: clamp(180px, 21vh, 420px); }

.signup-url {
  font-size: clamp(12px, 0.92vw, 25px);
  font-weight: 600;
  color: var(--accent);
  word-break: break-all;
  /* A URL is an LTR data token in either language... */
  direction: ltr;
  unicode-bidi: isolate;
  /* ...but it lines up with the copy around it: `match-parent` resolves start/end
     against the parent's direction, so it sits flush right under the Arabic lead and
     centred in the standby column, instead of drifting to its own (left) start. */
  text-align: match-parent;
  line-height: 1.25;
}
.signup-url-lg {
  font-size: clamp(15px, 1.45vw, 40px);
  color: var(--fg);
  word-break: break-all;
}

/* Captures tonight — a quiet count under the signup QR. Sized well below the queue and
   lyrics: it is ambient reassurance that the capture feature is alive, not information
   anyone in the room needs to read from across the hall. */
/* A running sentence (app.js renderCaptures), so plain inline flow: the count span sits
   on the text baseline wherever the language's word order puts it. */
.captures-line {
  display: block;
  margin-top: 1.1vh;
  padding-top: 1.1vh;
  border-top: 1px solid var(--line-soft);
  color: var(--fg-faint);
  font-size: clamp(11px, 0.85vw, 22px);
}
.captures-count {
  color: var(--teal);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-size: clamp(14px, 1.15vw, 30px);
}
html[lang="ar"] .captures-line { font-size: clamp(13px, 0.98vw, 25px); line-height: 1.5; }

/* ─── transport ──────────────────────────────────────────────────────────────
   Floats over the stage rather than taking layout space: it comes and goes, and a
   bar that reflowed the lyrics every time somebody walked past the screen would be
   worse than no bar at all.

   Centred with a physical left + translateX, which is symmetric and so correct in
   both directions. The buttons are words, not ▶/⏭ glyphs, so they follow the reading
   order: the primary (play/pause) leads at the start in either language, and the
   language switch closes the bar at the end, behind a divider. */
.transport {
  position: fixed;
  left: 50%;
  bottom: calc(var(--screen-pad) * 0.8);
  transform: translateX(-50%);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 999px;
  background: rgba(12, 15, 22, 0.88);
  border: 1px solid var(--panel-line);
  box-shadow: var(--shadow);
  backdrop-filter: blur(10px);
  animation: transport-in 140ms ease-out;
}
.transport[hidden] { display: none; }

@keyframes transport-in {
  from { opacity: 0; transform: translate(-50%, 8px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

.tbtn {
  font: inherit;
  font-size: clamp(0.9rem, 1.15vw, 1.15rem);
  font-weight: 600;
  color: var(--fg);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 999px;
  /* Generous because the likeliest input device here is a thumb on a propped-up
     tablet, not a mouse. */
  padding: 0.6em 1.3em;
  min-width: 6.5em;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.tbtn:hover:not(:disabled) { background: #1b2130; border-color: #333c4e; }
.tbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tbtn:disabled { opacity: 0.4; cursor: default; }

.tbtn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #1a1206;
}
.tbtn-primary:hover:not(:disabled) { background: #e0af58; border-color: #e0af58; }

/* Armed state for the two-tap skip: it should look like it is waiting for an answer.
   The :hover variant is not redundant — arming happens *on* a click, so the pointer is
   still over the button, and the plain hover rule outranks a single class. */
.tbtn-skip.is-armed,
.tbtn-skip.is-armed:hover:not(:disabled) {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
  min-width: 11em;
}

.transport-note {
  font-size: 0.9rem;
  color: var(--fg-faint);
  padding-inline-end: 6px;
}
.transport-note.is-error { color: var(--danger); }
.transport-note[hidden] { display: none; }

/* Arabic labels at Latin sizes look a size smaller on the same pill. */
html[lang="ar"] .tbtn { font-size: clamp(1rem, 1.3vw, 1.3rem); }
html[lang="ar"] .transport-note { font-size: 1rem; }

/* The language switch: separated from the playback commands by a divider and a wider
   gap, same height as the buttons (so it is as easy to hit with a thumb), but drawn as a
   ghost so nobody mistakes it for a fourth transport command. */
.transport-lang {
  display: flex;
  align-items: center;
  margin-inline-start: 4px;
  padding-inline-start: 14px;
  border-inline-start: 1px solid var(--line);
  align-self: stretch;
}
/* .tbtn (later in the cascade than base.css's .lang-toggle) supplies the pill size and
   padding, so the switch matches the transport buttons in both languages; base.css
   still picks the right font for its label's own script. */
.tbtn.tbtn-lang {
  min-width: 0;
  min-height: 0;
  background: transparent;
  color: var(--fg-muted);
}
.tbtn.tbtn-lang:hover:not(:disabled) { color: var(--fg); }

/* The cursor auto-hide must not take the buttons with it. */
body.hide-cursor .transport, body.hide-cursor .transport * { cursor: pointer !important; }
body.hide-cursor .tbtn:disabled { cursor: default !important; }

/* ─── shout-outs ───────────────────────────────────────────────────────────── */
.shouts-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1vh; overflow: hidden; }
.shout-item { min-width: 0; }
.shout-name { font-size: clamp(11px, 0.8vw, 21px); color: var(--fg-faint); font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shout-text { font-size: clamp(14px, 1.05vw, 28px); color: var(--fg); line-height: 1.35;
  overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.shout-item.is-new { animation: shout-in 0.6s ease-out; }
@keyframes shout-in { from { opacity: 0; transform: translateY(-0.6em); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .shout-item.is-new { animation: none; } }
