/* /var/www/meet/assets/styles.css */
:root {
  --bg: #0f1115;
  --panel: #181b22;
  --panel-2: #21252e;
  --text: #e9ecf1;
  --muted: #8a93a4;
  --accent: #4f8cff;
  --danger: #e25555;
  --ok: #34b46c;
  --border: #2c313c;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
  line-height: 1.4;
}
body::-webkit-scrollbar, *::-webkit-scrollbar { width: 8px; height: 8px; }
body::-webkit-scrollbar-thumb, *::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
body::-webkit-scrollbar-track { background: transparent; }

.muted { color: var(--muted); }

/* ====== Panels laterales (chat / participants / tools / config) ======
   Multi-open: cada panel es independiente. Animación pura CSS.
   Estructura: <div.panel> wrapper que colapsa width; <aside> dentro slide
   con transform. workspace + audience se achican naturalmente al abrir más
   panels porque ocupan más width en el flex de la fila central. */
.panel {
  width: 0;
  flex-shrink: 0;
  overflow: hidden;
  transition: width .3s ease-out;
  pointer-events: none;
}
.panel.panel-open {
  width: 320px;
  pointer-events: auto;
}
.panel > aside {
  width: 320px;
  height: 100%;
  transform: translateX(100%);
  opacity: 0;
  transition: transform .3s ease-out, opacity .3s ease-out;
}
.panel.panel-open > aside {
  transform: translateX(0);
  opacity: 1;
}

.btn {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 14px;
  cursor: pointer;
  font-size: 14px;
  transition: background .12s, border-color .12s;
  position: relative;
}
.btn:hover { background: #2a2f3a; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: white; }
.btn.primary:hover { background: #3d75e0; }
.btn.danger { background: var(--danger); border-color: var(--danger); color: white; }
.btn.danger:hover { background: #c84545; }
.btn.ghost { background: transparent; border-color: transparent; padding: 6px 10px; font-size: 18px; }
.btn.ghost:hover { background: var(--panel-2); }

.badge {
  position: absolute;
  top: -4px; right: -4px;
  background: var(--danger);
  color: white;
  border-radius: 999px;
  min-width: 18px;
  padding: 0 5px;
  height: 18px;
  font-size: 11px;
  line-height: 18px;
  text-align: center;
}

/* ====== Lobby ====== */
.lobby { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; }
.lobby__wrap {
  width: 100%;
  max-width: 580px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 28px;
}
.lobby__wrap h1 { margin: 0 0 4px; font-size: 26px; }
.lobby__wrap .footer { margin: 16px 0 0; font-size: 12px; text-align: right; }

.preview {
  position: relative;
  background: #000;
  border-radius: 12px;
  overflow: hidden;
  aspect-ratio: 16/9;
  margin: 16px 0;
}
.preview video { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }
.preview__overlay {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.55); color: var(--muted); font-size: 13px;
}
.preview__overlay.hidden { display: none; }

.form { display: flex; flex-direction: column; gap: 12px; }
.form label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
.form input[type=text], .form select {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
}
.form input[type=text]:focus, .form select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.form .row { display: flex; gap: 12px; }
.form .row .grow { flex: 1; }
.form .check { flex-direction: row; align-items: center; gap: 8px; color: var(--text); font-size: 14px; cursor: pointer; }

/* ====== Room ====== */
/* body, header, footer y gallery los maneja Tailwind via tpl. Acá solo lo que Tailwind no cubre. */

/* Stage: layout puro Tailwind. No reglas adicionales necesarias hoy. */

/* ====== Audience grid sin screen share ======
   El composer (audience/gallery.js) escribe data-count y data-mode.
   Tiles llevan data-host="true|false". El layout se decide acá por CSS.

   - count 1..4: split equitativo (estilo Zoom gallery).
   - count >= 5: spotlight — host ocupa la mayor parte, los demás en columna
     vertical 9:16 (mismo "Stories" style del overlay focus pero aplicado al
     gallery default). */
.audience {
  display: grid;
  gap: 12px;
  width: 100%;
  height: 100%;
}
.audience > .tile { min-width: 0; min-height: 0; }

/* 1 → ocupa todo */
.audience[data-mode="gallery"][data-count="1"] {
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
}
/* 2 → fila */
.audience[data-mode="gallery"][data-count="2"] {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr;
}
/* 3 → 2 arriba, 1 abajo centrado */
.audience[data-mode="gallery"][data-count="3"] {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
.audience[data-mode="gallery"][data-count="3"] > .tile:nth-child(3) {
  grid-column: 1 / span 2;
  max-width: 50%;
  justify-self: center;
  width: 100%;
}
/* 4 → 2x2 */
.audience[data-mode="gallery"][data-count="4"] {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
/* 5+ sin host detectado → todos comparten en auto-fit (rara vez activado,
   solo cuando no hay roles asignados en la sala). */
.audience[data-mode="gallery"][data-count="many"] {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  grid-auto-rows: minmax(160px, 1fr);
  align-content: start;
  overflow-y: auto;
}

/* 5+ → host grande a la izquierda, columna vertical Stories a la derecha.
   Grid auto-placement: host fijo en col 1 spanning todo; los no-host se
   colocan automáticamente en col 2, una fila cada uno (9:16). */
.audience[data-mode="spotlight"] {
  grid-template-columns: 1fr 220px;
  grid-auto-rows: minmax(180px, max-content);
  align-content: start;
  overflow-y: auto;
}
.audience[data-mode="spotlight"] > [data-host="true"] {
  grid-column: 1;
  grid-row: 1 / span 999;
  height: 100%;
  align-self: stretch;
}
.audience[data-mode="spotlight"] > [data-host="false"] {
  grid-column: 2;
  aspect-ratio: 9 / 16;
  width: 100%;
}

/* Pin local: mismo layout que spotlight pero el tile grande es el fijado
   (data-pinned), no el host. Funciona con cualquier count. */
.audience[data-mode="spotlight-pin"] {
  grid-template-columns: 1fr 220px;
  grid-auto-rows: minmax(180px, max-content);
  align-content: start;
  overflow-y: auto;
}
.audience[data-mode="spotlight-pin"] > [data-pinned="true"] {
  grid-column: 1;
  grid-row: 1 / span 999;
  height: 100%;
  align-self: stretch;
}
.audience[data-mode="spotlight-pin"] > [data-pinned="false"] {
  grid-column: 2;
  aspect-ratio: 9 / 16;
  width: 100%;
}
/* Marca visual del tile fijado */
[data-pinned="true"] { outline: 2px solid #4f8cff; outline-offset: -2px; }

/* ====== Móvil: layout tradicional estilo Meet/Zoom ======
   En viewport angosto la columna lateral 9:16 queda apretada y rompe
   el split 2-col. Pasamos a stack vertical full-width con scroll. */
@media (max-width: 640px) {
  .audience,
  .audience[data-mode="gallery"][data-count="1"],
  .audience[data-mode="gallery"][data-count="2"],
  .audience[data-mode="gallery"][data-count="3"],
  .audience[data-mode="gallery"][data-count="4"],
  .audience[data-mode="gallery"][data-count="many"],
  .audience[data-mode="spotlight"],
  .audience[data-mode="spotlight-pin"] {
    grid-template-columns: 1fr;
    grid-auto-rows: minmax(180px, auto);
    grid-template-rows: none;
    grid-template-areas: none;
    overflow-y: auto;
    align-content: start;
  }
  .audience[data-mode="gallery"][data-count="3"] > .tile:nth-child(3) {
    grid-column: auto;
    max-width: none;
    justify-self: stretch;
  }
  .audience[data-mode="spotlight"] > [data-host="true"],
  .audience[data-mode="spotlight-pin"] > [data-pinned="true"] {
    grid-column: auto;
    grid-row: auto;
    aspect-ratio: 16 / 9;
    height: auto;
    align-self: auto;
  }
  .audience[data-mode="spotlight"] > [data-host="false"],
  .audience[data-mode="spotlight-pin"] > [data-pinned="false"] {
    grid-column: auto;
    aspect-ratio: 16 / 9;
  }
}

/* ====== Botones del footer ======
   ctrl-btn: controles de media (mic/cam/hand/reactions/screen), circulares.
   panel-toggle: toggles de panels laterales (tools/participants/chat/config).
   Estados: .off (media apagado, rojo), .active (panel abierto, azul). */
.ctrl-btn, .panel-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 9999px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: #e9ecf1;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.ctrl-btn:hover, .panel-toggle:hover {
  background: #2c313c;
}
.ctrl-btn.off {
  background: rgba(226, 85, 85, .15);
  border-color: rgba(226, 85, 85, .4);
  color: #e25555;
}
.ctrl-btn.active {
  background: rgba(79, 140, 255, .15);
  border-color: rgba(79, 140, 255, .4);
  color: #4f8cff;
}
.panel-toggle.active {
  background: rgba(79, 140, 255, .15);
  border-color: rgba(79, 140, 255, .4);
  color: #4f8cff;
}

/* #btn-more: oculto en desktop, el media query de abajo lo muestra.
   No usamos el atributo [hidden] — .panel-toggle ya fija display:inline-flex
   con mayor especificidad que la UA stylesheet de [hidden], lo anularía. */
#btn-more { display: none; }

/* Footer mobile: a <=440px de viewport el footer completo (nombre + 6
   controles + 5 toggles) mide ~680px de ancho natural, sin wrap ni scroll
   — tools/side-grid/participantes/chat/config quedaban inalcanzables fuera
   de pantalla. Nombre se oculta, tools/side-grid/config se agrupan detrás
   de #btn-more (estilo Zoom/Meet mobile) — participantes y chat quedan
   siempre visibles por ser las acciones más frecuentes.
   "footer #f-name", no "#f-name" pelado: el lobby (index.html) reusa el
   mismo id para el input "Nombre" — un selector sin scope apagaba también
   el campo del formulario, no solo el label del footer de la sala. */
@media (max-width: 640px) {
  footer { padding-left: 12px; padding-right: 12px; }
  footer #f-name { display: none; }
  footer .gap-3 { gap: 6px; }
  footer .w-px.h-8 { display: none; }
  #btn-tools, #btn-side-grid, #btn-config { display: none; }
  #btn-more { display: inline-flex; }
  .ctrl-btn, .panel-toggle { width: 40px; height: 40px; }
  /* font-size:0 colapsa el texto "Salir" (nodo suelto, sin wrapper propio
     para hacer display:none solo del texto) sin afectar el ícono — el SVG
     de Lucide mide por w-/h- explícitos, no por em. */
  #btn-leave { width: 40px; height: 40px; padding: 0; margin-left: 4px; font-size: 0; }
  #btn-leave i { margin-right: 0; }
}

/* Overlays modo focus (host-bubble, vertical-stack, audio-chips) usan Tailwind via tpl. */

/* Audio-only chips, bottom-left. Fixed 2-column grid — flex-wrap let 3+
   narrow pills share a row, breaking the "2 per row" layout. Anchored by
   `bottom`, height:auto up to max-height: the group visually grows upward
   as rows stack, then scrolls once it hits the available area. New chips
   append at the DOM tail (bottom), so scrollTop stays wherever the user
   left it — no JS needed to "keep the scroll at top". Mask instead of a
   visible scrollbar for the fade edges. */
.overlay-chips {
  position: absolute;
  bottom: 24px; left: 24px;
  display: grid;
  /* `1fr` needs a definite container width to resolve; this box is
     position:absolute with no explicit width (shrink-to-fit), so `1fr`
     columns collapsed unpredictably (1 column instead of 2). max-content
     sizes each column to its widest occupant and, with that, the
     container's own auto width — no ambiguity, no leftover space for a
     stray scrollbar track to sit in next to narrow pills. */
  grid-template-columns: repeat(2, max-content);
  gap: 8px;
  width: max-content;
  max-width: 50%;
  max-height: calc(100dvh - 200px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
  mask-image: linear-gradient(to bottom, transparent 0, black 16px, black calc(100% - 16px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 16px, black calc(100% - 16px), transparent 100%);
  z-index: 40;
}
.overlay-chips::-webkit-scrollbar { display: none; }

@media (max-width: 640px) {
  /* Exactamente 2 filas (32px de chip c/u) + 1 gap antes de scrollear. */
  .overlay-chips { max-height: 72px; }
}
/* audio-chip, tile workspace y overlays usan Tailwind via tpl. */

/* Hover no existe en touch: las acciones del tile (que dependen de group-hover
   con opacity-0 → opacity-100) nunca se mostrarían en mobile. Forzar visibles. */
@media (hover: none) {
  [data-slot="actions"] { opacity: 1 !important; }
}

/* Highlight de active speaker: outline verde + leve escala. Usamos transform
   (no cambia el layout) para que el tile "crezca" sin reflow ni saltos del
   grid en cada cambio de hablante. */
[data-sid].speaking {
  outline: 2px solid rgba(16, 185, 129, .7);
  outline-offset: -2px;
  transition: transform .18s ease, outline-color .15s ease-out, box-shadow .18s ease;
}
/* Solo escalamos en modo galería: en las columnas 9:16 del spotlight el
   scale se vería raro y podría desbordar. Moderado (1.04→1.02, shadow más
   suave) — el efecto original saltaba demasiado en cada cambio de hablante. */
.audience[data-mode="gallery"] > [data-sid].speaking {
  transform: scale(1.02);
  z-index: 5;
  box-shadow: 0 4px 16px rgba(16, 185, 129, .18);
}

/* Chips (audio-only, sin cámara): sin outline/scale — un pill chico se ve
   agresivo con ese tratamiento. En vez de eso, "efecto de onda": un anillo
   que se expande y se desvanece, estilo sonar — sutil, no compite con el
   resto de la UI. Especificidad .audio-chip.speaking > [data-sid].speaking
   (misma cantidad de selectores simples, pero declarado después) pisa el
   outline/transform genérico de arriba.
   Ver también rc0.16.6: mismo cuidado de no reventar layout con transform. */
.audio-chip.speaking {
  outline: none;
  transform: none;
  animation: chip-speaking-pulse 1.6s ease-in-out infinite;
}
@keyframes chip-speaking-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, .35); }
  50%      { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
}

/* Stack items (vertical-stack.js): speaking pops out exactly like :hover
   already does (same translate+scale) — user asked for it to read the
   same way as the hover state, not the generic outline treatment above.
   `!important` only on z-index: it's set inline per-item (join order) and
   a speaking item needs to sit above siblings regardless of that order. */
.overlay-stack-item.speaking {
  transform: translateX(-10px) translateY(-1rem) scale(1.1);
  z-index: 45 !important;
}

/* Reacción flotante efímera (emoji subiendo sobre el tile del emisor) */
.reaction-float {
  position: absolute;
  bottom: 30%;
  left: 50%;
  font-size: 48px;
  line-height: 1;
  pointer-events: none;
  z-index: 100;
  animation: reactionFloat 2s ease-out forwards;
  will-change: transform, opacity;
}
@keyframes reactionFloat {
  0%   { transform: translate(-50%, 0)      scale(0.5); opacity: 0; }
  15%  { transform: translate(-50%, -20px)  scale(1.3); opacity: 1; }
  100% { transform: translate(-50%, -200px) scale(1);   opacity: 0; }
}

/* Botones emoji del popup */
.reaction-btn {
  width: 40px; height: 40px;
  font-size: 24px;
  border-radius: 8px;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: transform .12s, background .12s;
}
.reaction-btn:hover { background: #1f2937; transform: scale(1.2); }

/* Overlay reconexión: solo se muestra cuando el SDK agotó retries.
   Durante Reconnecting el badge del header alcanza; no interrumpimos al usuario. */
.overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.72);
  display: flex; align-items: center; justify-content: center;
  z-index: 50;
  padding: 16px;
}
.overlay[hidden] { display: none; }
.overlay__card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px;
  max-width: 360px;
  width: 100%;
  text-align: center;
}
.overlay__card h2 { margin: 0 0 6px; font-size: 18px; }
.overlay__card p { margin: 0 0 16px; }
.overlay__card .btn { width: 100%; margin-top: 6px; }
.overlay__card .btn[disabled] { opacity: .6; cursor: wait; }

/* Botón flotante para destrabar audio en iOS Safari (autoplay policy) */
.audio-unlock {
  position: fixed;
  top: 56px; left: 50%; transform: translateX(-50%);
  background: #d4b14a; color: #1a1a1a; border: none;
  padding: 10px 16px; border-radius: 999px; font-weight: 600;
  font-size: 13px; box-shadow: 0 4px 12px rgba(0,0,0,.4);
  cursor: pointer; z-index: 40;
}
.audio-unlock[hidden] { display: none; }

.perm-banner {
  position: fixed; top: 56px; left: 50%; transform: translateX(-50%);
  background: var(--panel); border: 1px solid var(--danger); border-radius: 12px;
  padding: 14px 18px; max-width: 360px; z-index: 45; box-shadow: 0 6px 18px rgba(0,0,0,.5);
}
.perm-banner[hidden] { display: none; }
.perm-banner strong { color: var(--danger); }
.perm-banner p { margin: 6px 0 10px; font-size: 13px; }
.perm-banner-actions { display: flex; gap: 8px; }
.perm-banner-actions .btn { flex: 1; }

/* Badge de estado en topbar — diferencia visual los 4 estados */
#t-status.status-connecting   { color: #d4b14a; }
#t-status.status-connected    { color: var(--ok); }
#t-status.status-reconnecting { color: #d4b14a; }
#t-status.status-disconnected { color: var(--danger); }
