* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; font-family: -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; }

.screen { position: fixed; inset: 0; }
.fill { position: absolute; inset: 0; }

/* ---- Pairing screen ---- */
#pairing-screen {
  background: #0b0d11;
  align-items: center; justify-content: center; flex-direction: column;
  color: #fff; text-align: center;
}
.pairing-box .brand { font-size: 22px; letter-spacing: .3em; color: #fff; margin-bottom: 24px; }
.pairing-box .brand .brand-accent { color: #c75d2c; }
.pair-code { font-size: 96px; font-weight: 700; letter-spacing: .12em; margin-bottom: 24px; }
.pair-hint { font-size: 22px; color: #b7bec9; }

/* ---- Web-screen registration ---- */
#web-screen {
  background: #0b0d11;
  display: flex; align-items: center; justify-content: center; flex-direction: column;
  color: #fff; text-align: center;
}
.web-name { font-size: 40px; font-weight: 700; margin-bottom: 28px; }
.web-pw { display: flex; gap: 12px; margin-bottom: 20px; }
.web-pw-input {
  font-size: 24px; padding: 12px 16px; border-radius: 8px; border: 1px solid #2a2f39;
  background: #151922; color: #fff; width: 320px; outline: none;
}
.web-pw-input:focus { border-color: #c75d2c; }
.web-pw-btn {
  font-size: 24px; padding: 12px 24px; border-radius: 8px; border: none;
  background: #c75d2c; color: #fff; cursor: pointer;
}
.web-pw-btn:disabled { opacity: .5; cursor: default; }

/* ---- Player ---- */
/* isolation: contain the crossfade z-indexes (_applyTransition puts the showing image slot at
   z-index:2). Without a stacking context here, that z-index:2 escapes and paints the image OVER the
   sibling #overlay-layer, so overlays vanish behind image items (but show over widgets, which carry
   no z-index). isolate keeps the slot z-indexes inside this container; the overlay layer, later in
   the DOM, then always paints on top. */
#playlist-container { background: #000; isolation: isolate; }
/* Transition layer: clips slide/wipe/motion to the screen and never fights the inner img's motion. */
.pl-slot { position: absolute; inset: 0; overflow: hidden; background: #000; }
.pl-media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; background: #000; }
.pl-widget { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 28px; background: #000; }

/* ---- Overlays ---- */
.overlay-layer { pointer-events: none; }
.overlay-box {
  position: absolute; display: flex; align-items: center;
  padding: 4px 10px; font-size: 24px; white-space: nowrap; overflow: hidden;
}
.ticker-inner { display: inline-block; }

/* Seamless marquee: translate by exactly one content-copy's width (set as --ticker-unit-w
   by overlays.js), not a fixed -100% of a padded element — see overlays.js startScroll(). */
@keyframes ticker-scroll-seamless {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-1 * var(--ticker-unit-w))); }
}

/* Feed Builder "cards" mode (renderFeedCardsWidget) — same seamless-loop technique as the text
   ticker above (duplicate one pass, translate by exactly 50% = one copy-width), mirrors Android's
   FeedCardsHtml.kt exactly. Card content is block-level (image + wrapped title), so it needs the
   ticker's white-space:nowrap/overflow:hidden box styling overridden back to normal flow. */
.overlay-box.feed-cards { white-space: normal; padding: 0; }
@keyframes feed-cards-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
