/* ============================================================
   SRDELI — Channel Page (channel-clean.css) v4.0
   ------------------------------------------------------------
   LAYOUT ARCHITECTURE
   The channel page is a viewport-locked full-height layout:
   - body: overflow hidden (no page scroll)
   - .container: fixed height = 100svh - topbar
   - .chan297-page: CSS Grid — 2 cols × 3 rows
     Row 1: Title (spans both columns)
     Row 2: Video | Chat (chat spans rows 2–3)
     Row 3: Viewers
   - Uniform gap between ALL 4 elements
   - Grid shrink-wraps content, vertically & horizontally centered
   - fitLayout() JS computes exact 16:9 video size and sets
     grid-template-columns/rows with !important
   - Under 1100px: single column, chat fills remaining space,
     never scrollable

   JS-INJECTED ELEMENTS (must be styled here):
   - .chan297-loading / .chan297-spinner
   - .chan297-freeze
   - .chan297-context-surface
   - .chan297-controls / .chan297-ctrl / .chan297-volume
   - .chan297-gate / .chan297-gate-title / .chan297-password-form
   - .chan297-secret / .chan297-secret-input / .chan297-secret-toggle
   - .chan297-submit / .chan297-error / .chan297-gate-message

   JS INLINE-STYLE CONSTRAINTS (must not fight):
   - hardenGate(): !important on gate panel sizing/grid
   - hardenControls(): !important on control bar position/grid
   - fitLayout(): !important on page grid-template-*, frame/chat dimensions
   - forceUiVisibility(): !important on controls opacity/transform
   ============================================================ */

/* ═══════════════════════════════════════════
   1. FULL-HEIGHT VIEWPORT LOCK
   ═══════════════════════════════════════════ */
body:has(.chan297-page) {
  overflow: hidden;
}
.container:has(.chan297-page),
main.container:has(.chan297-page) {
  height: calc(100svh - var(--topbar));
  margin-top: 0;
  margin-bottom: 0;
  padding: var(--sp-2) var(--page-pad) var(--sp-2);
  min-height: 0;
  max-width: var(--container);
}

/* ═══════════════════════════════════════════
   2. PAGE WRAPPER — 4-element tight grid
   Grid:  title  | title
          video  | chat
          viewers| chat
   ═══════════════════════════════════════════ */
.chan297-page {
  height: 100%;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr clamp(280px, 20vw, 340px);
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: var(--sp-2);
  align-content: center;
  justify-content: center;
  overflow: hidden;
  max-width: 100%;
  margin: 0;
}

/* No-chat mode: single column */
.chan297-page:not(:has(.chan297-chat)) {
  grid-template-columns: 1fr;
}

/* ═══════════════════════════════════════════
   3. HEADER — spans both columns
   ═══════════════════════════════════════════ */
.chan297-head {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 0 4px;
}
.chan297-titleblock {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.chan297-titleblock h1 {
  font-size: clamp(20px, 2.6vw, 26px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  line-height: 1.2;
}
.chan297-titleblock p {
  color: var(--text-2);
  font-size: 13px;
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ═══════════════════════════════════════════
   4. PLAYER FRAME — grid cell (1, 2)
   fitLayout() overrides width/height with !important.
   ═══════════════════════════════════════════ */
#channel-player-frame,
.chan297-frame {
  position: relative;
  width: 100%;
  min-width: 0;
  min-height: 0;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: var(--r-lg);
  overflow: hidden;
}
#channel-player,
.chan297-player {
  width: 100%;
  height: 100%;
  position: relative;
  background: #000;
}
#channel-player video,
.chan297-player video {
  width: 100% !important;
  height: 100% !important;
  background: #000;
  object-fit: contain;
}

/* Player state modifiers on #channel-player */
.chan297-player.is-gated,
.chan297-player.is-offline,
.chan297-player.is-password,
.chan297-player.is-whitelist {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Frame state modifiers */
/* Spinner visibility is controlled solely by .chan297-loading-active (toggled
   by showPlaybackLoading / hidePlaybackLoading in JS). The .chan297-ready
   class must NOT hide the spinner — it's added as soon as the WHEP player is
   created, which is long before any video frames actually flow. Hiding the
   spinner via .chan297-ready caused a black screen with no spinner during the
   gap between "WHEP connected" and "frames actually playing". */
.chan297-frame.chan297-loading-active .chan297-loading { opacity: 1; pointer-events: auto; }
.chan297-frame.chan297-gated .chan297-controls { display: none !important; }
.chan297-frame.chan297-has-player { /* informational */ }
/* UI visibility is controlled by JS forceUiVisibility() which sets inline !important.
   Do NOT set opacity/visibility/pointer-events/transform on .chan297-controls here. */

/* Fullscreen native */
.chan297-frame:fullscreen,
.chan297-frame:-webkit-full-screen {
  border-radius: 0;
  box-shadow: none;
}

/* ═══════════════════════════════════════════
   5. LOADING SPINNER
   ═══════════════════════════════════════════ */
.chan297-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t);
  z-index: 4;
}
.chan297-spinner {
  width: 32px;
  height: 32px;
  border-radius: var(--r-pill);
  border: 2px solid rgba(255, 255, 255, 0.12);
  border-top-color: var(--text);
  animation: chan297-spin 0.9s linear infinite;
}
@keyframes chan297-spin { to { transform: rotate(360deg); } }

/* ═══════════════════════════════════════════
   6. FREEZE OVERLAY (last frame when stream stalls)
   ═══════════════════════════════════════════ */
.chan297-freeze {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-color: #000;
  z-index: 3;
  pointer-events: none;
  opacity: 0.85;
}
.chan297-freeze::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 60%, rgba(0,0,0,0.5) 100%);
}
/* Kein Reconnecting-Text-Badge mehr (Jan: flackerte, war unlesbar). Während
   eines Reconnects zeigt der Player das eingefrorene letzte Bild plus den
   durchlaufenden Loading-Spinner (.chan297-loading), bis der Stream wieder
   spielt oder auf offline umschaltet. Die Klasse .chan297-freeze-reconnecting
   wird vom JS nicht mehr gesetzt. */

/* ═══════════════════════════════════════════
   7. CONTEXT SURFACE (pointer capture layer)
   ═══════════════════════════════════════════ */
.chan297-context-surface {
  position: absolute;
  inset: 0;
  z-index: 2;
}

/* ═══════════════════════════════════════════
   8. CONTROL BAR
   hardenControls() sets !important on position, size,
   grid-template-columns, gap, z-index. CSS only styles
   the visual surface.
   ═══════════════════════════════════════════ */

/* Bottom fade — on the frame, full-width, visible when UI is shown */
.chan297-frame::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 90px;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.7) 0%, transparent 100%);
  pointer-events: none;
  z-index: 4;
  opacity: 0;
  transition: opacity var(--t);
}
.chan297-frame.chan297-ui-visible::after,
.chan297-frame.chan297-gated::after { opacity: 0; }
.chan297-frame.chan297-has-player.chan297-ui-visible::after { opacity: 1; }

.chan297-controls {
  background: transparent;
  pointer-events: none;
  transition: opacity var(--t), transform var(--t), visibility var(--t);
  /* opacity/visibility/pointer-events/transform set by JS forceUiVisibility() inline !important */
}
.chan297-ctrl {
  background: transparent;
  color: var(--text);
  border-radius: var(--r-sm);
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
  transition: color var(--t-fast), transform var(--t-fast);
}
.chan297-ctrl:hover { color: var(--accent-2); transform: scale(1.1); }
.chan297-ctrl svg { width: 20px; height: 20px; }

.chan297-volume {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  background: rgba(255, 255, 255, 0.14);
  border-radius: var(--r-pill);
  outline: 0;
  pointer-events: auto;
  cursor: pointer;
  height: 4px;
}
.chan297-volume::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  background: var(--text);
  border-radius: var(--r-pill);
  border: 0;
  cursor: pointer;
}
.chan297-volume::-moz-range-thumb {
  width: 14px;
  height: 14px;
  background: var(--text);
  border-radius: var(--r-pill);
  border: 0;
  cursor: pointer;
}

/* ═══════════════════════════════════════════
   9. VIEWER BAR — grid cell (1, 3), standalone card
   ═══════════════════════════════════════════ */
.chan297-viewers {
  height: 48px;
  min-height: 48px;
  max-height: 48px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 0 14px;
  background: var(--surface);
  border-radius: var(--r-lg);
  flex: 0 0 48px;
  box-sizing: border-box;
  overflow: hidden;
}
.chan297-mv-toggle {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 20px;
  font-weight: 400;
  line-height: 1;
  padding: 0;
  flex: 0 0 auto;
  transition: background var(--t-fast), color var(--t-fast);
}
.chan297-mv-toggle:hover { background: var(--surface-3); color: var(--text); }
.chan297-mv-toggle.is-active {
  background: var(--accent-soft);
  color: var(--text);
}

.chan297-viewer-readout {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: 13px;
}
.chan297-viewer-readout span {
  color: var(--text-3);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 500;
}
.chan297-viewer-readout strong,
#viewer-count {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* ═══════════════════════════════════════════
   10. CHAT SIDEBAR — grid cell (2, 2–3), spans 2 rows
   ═══════════════════════════════════════════ */
.chan297-chat {
  grid-column: 2;
  grid-row: 2 / 4;
  background: var(--surface);
  border-radius: var(--r-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
  min-width: 0;
  position: relative;
}
.chan297-chat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--hairline);
  flex: 0 0 auto;
}
.chan297-chat-head h2 {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.chan297-chat-head span,
.chan297-chat-mode {
  font-size: 11px;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 500;
}
/* All badge states (public, password, whitelist, offline) MUST look identical —
   same size, same font, same color/tone. Only the label text differs. */
.chan297-chat-mode[data-mode="public"],
.chan297-chat-mode[data-mode="password"],
.chan297-chat-mode[data-mode="whitelist"],
.chan297-chat-mode[data-mode="offline"] {
  color: var(--text-3);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
}

.chan297-chat-messages,
#chat-messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-3) var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: 4px;
  scroll-behavior: smooth;
  position: relative;
}

/* Chat message lines (created by chat.js) */
.chat-line {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: 13px;
  font-family: var(--font-ui);
  line-height: 1.5;
  word-break: break-word;
  animation: chatline-in 180ms ease;
}
@keyframes chatline-in {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 1; transform: translateY(0); }
}
.chat-user {
  font-weight: 600;
  font-size: 13px;
  font-family: var(--font-ui);
  flex: 0 0 auto;
  max-width: 45%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-user:hover { opacity: 0.75; }
.chat-text {
  color: var(--text);
  font-size: 13px;
  font-family: var(--font-ui);
  font-weight: 400;
  flex: 1;
  min-width: 0;
}

/* Chat form */
.chan297-chat-form,
#chat-form {
  display: flex;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--hairline);
  flex: 0 0 auto;
}
#chat-input {
  flex: 1;
  background: var(--surface-3);
  border: 0;
  border-radius: var(--r-sm);
  padding: 9px 12px;
  color: var(--text);
  font-size: 13px;
  outline: 0;
  font-family: inherit;
  transition: background var(--t-fast), box-shadow var(--t-fast);
}
#chat-input:focus {
  background: var(--surface-4);
  box-shadow: 0 0 0 1px var(--accent-line);
}
#chat-input::placeholder { color: var(--text-3); }
#chat-form button {
  background: var(--accent);
  color: var(--accent-text);
  padding: 0 var(--sp-4);
  border-radius: var(--r-sm);
  font-weight: 600;
  font-size: 13px;
  transition: background var(--t-fast);
  flex: 0 0 auto;
}
#chat-form button:hover { background: var(--accent-2); }
#chat-form button:disabled { opacity: 0.4; cursor: not-allowed; }

.chan297-chat-login {
  padding: var(--sp-4);
  text-align: center;
  color: var(--text-3);
  font-size: 13px;
  border-top: 1px solid var(--hairline);
  flex: 0 0 auto;
}

/* Chat locked state — the lock overlay covers the ENTIRE chat sidebar */
.chan297-chat.chat-locked {
  /* keep header visible so user always sees "Chat <MODE>"; cover the rest */
}
.chan297-chat.chat-locked .chan297-chat-messages,
.chan297-chat.chat-locked #chat-messages {
  display: none;
}
.chan297-chat.chat-locked .chan297-chat-form,
.chan297-chat.chat-locked #chat-form,
.chan297-chat.chat-locked .chan297-chat-login {
  display: none !important;
}
.chan297-chat.chat-locked .chat-line { display: none; }

/* Chat access lock overlay — covers everything below the chat header.
   Only the lock icon is shown; the header badge already labels the state. */
.chat-access-lock {
  position: absolute;
  top: var(--chat-head-height, 49px);
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  z-index: 20;
  pointer-events: none;
  border-bottom-left-radius: var(--r-lg);
  border-bottom-right-radius: var(--r-lg);
}
.chat-access-icon {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--text-3);
  flex: 0 0 auto;
}
.chat-access-icon svg { width: 20px; height: 20px; }

/* ═══════════════════════════════════════════
   11. ACCESS GATE
   ═══════════════════════════════════════════ */
.chan297-gate {
  background: var(--surface);
  border-radius: var(--r-lg);
  color: var(--text);
  box-shadow: var(--shadow-lg);
}
.chan297-gate-title {
  font-size: 12px !important;
  font-weight: 700 !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase !important;
  color: var(--text-3) !important;
  margin: 0 0 var(--sp-4) 0 !important;
  line-height: 1.2 !important;
  text-align: center !important;
}
.chan297-gate-password .chan297-gate-title { color: var(--text-2) !important; }
.chan297-gate-whitelist .chan297-gate-title { color: var(--text-2) !important; }
.chan297-gate-offline .chan297-gate-title { color: var(--text-3) !important; }

.chan297-gate-message,
.chan297-gate-line {
  font-size: 13px;
  color: var(--text-2);
  line-height: 1.55;
  margin: 0;
  max-width: 280px;
  display: block;
  text-align: center !important;
}
.chan297-gate-line + .chan297-gate-line {
  margin-top: var(--sp-1);
}

.chan297-gate.chan297-gate-offline {
  padding: var(--sp-4) var(--sp-5) !important;
}
/* Offline gate: title is the only content — kill the bottom margin so the
   panel fits the 2 lines of text exactly (no extra empty "third line"). */
.chan297-gate.chan297-gate-offline .chan297-gate-title {
  margin-bottom: 0 !important;
}

.chan297-password-form {
  display: flex !important;
  flex-direction: column !important;
  align-items: stretch !important;
  gap: 0 !important;
  width: 100% !important;
  max-width: 320px !important;
  margin: 0 auto;
}
/* Input row holds the secret input + submit button side-by-side.
   Error lives below in its own row so it can grow/shrink independently
   without ever pushing the submit button sideways. */
.chan297-input-row {
  display: flex !important;
  flex-direction: row !important;
  align-items: stretch !important;
  gap: var(--sp-2) !important;
  width: 100% !important;
}
.chan297-secret {
  display: flex !important;
  align-items: stretch !important;
  flex: 1;
  background: var(--surface-3);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.chan297-secret-input {
  background: transparent !important;
  box-shadow: none !important;
  flex: 1;
  padding: 10px 12px !important;
  font-size: 13px !important;
  border-radius: 0 !important;
  min-width: 0;
}
.chan297-secret-input.is-masked {
  -webkit-text-security: disc;
  text-security: disc;
  letter-spacing: 0.08em;
}
.chan297-secret-toggle {
  width: 38px;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  background: transparent !important;
  color: var(--text-3);
  flex: 0 0 auto;
  border-radius: 0 !important;
  padding: 0 !important;
  transition: background var(--t-fast), color var(--t-fast);
}
.chan297-secret-toggle:hover {
  background: var(--surface-4) !important;
  color: var(--text);
}
.chan297-secret-toggle svg { width: 16px; height: 16px; }

.chan297-submit {
  width: 40px;
  height: 40px;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  background: var(--accent) !important;
  color: var(--accent-text) !important;
  border-radius: var(--r-sm) !important;
  padding: 0 !important;
  flex: 0 0 auto;
  transition: background var(--t-fast);
}
.chan297-submit:hover { background: var(--accent-2) !important; }
.chan297-submit svg { width: 18px; height: 18px; }

/* Error message row — lives below the input row, grows the panel downward
   when shown and shrinks it back when faded out. Centered by default. */
.chan297-error {
  font-size: 12px;
  color: var(--danger);
  text-align: center;
  width: 100% !important;
  margin-top: 0 !important;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  transition: max-height 0.25s ease, opacity 0.2s ease, margin-top 0.25s ease;
}
.chan297-error.is-visible {
  max-height: 40px;
  opacity: 1;
  margin-top: var(--sp-3) !important;
}
.chan297-error.is-fading {
  opacity: 0;
  max-height: 0;
  margin-top: 0 !important;
}

/* ═══════════════════════════════════════════
   12. RESPONSIVE — under 1100px (vertical/narrow)
   Single column, chat fills remaining space, never scrollable.
   ═══════════════════════════════════════════ */
@media (max-width: 1100px) {
  body:has(.chan297-page) { overflow: hidden; }
  .container:has(.chan297-page),
  main.container:has(.chan297-page) {
    height: calc(100svh - var(--topbar));
    min-height: 0;
    padding: var(--sp-2) var(--page-pad) var(--sp-2);
  }
  .chan297-page {
    grid-template-columns: 1fr !important;
    gap: var(--sp-2);
    height: 100%;
    overflow: hidden;
  }
  /* With chat: 4 rows, chat fills remaining space */
  .chan297-page:has(.chan297-chat) {
    grid-template-rows: auto auto auto minmax(0, 1fr) !important;
  }
  /* Without chat: 3 rows only */
  .chan297-page:not(:has(.chan297-chat)) {
    grid-template-rows: auto auto auto !important;
  }
  .chan297-head {
    grid-column: 1;
    grid-row: 1;
  }
  .chan297-frame,
  #channel-player-frame {
    grid-column: 1;
    grid-row: 2;
    aspect-ratio: 16 / 9;
    width: 100% !important;
    height: auto !important;
    border-radius: var(--r-lg);
  }
  .chan297-viewers {
    grid-column: 1;
    grid-row: 3;
  }
  .chan297-chat {
    grid-column: 1;
    grid-row: 4;
    width: 100% !important;
    height: auto !important;
    min-height: 0;
  }
}

@media (max-width: 540px) {
  .chan297-viewer-readout strong,
  #viewer-count { font-size: 16px; }
}
